Using timers?

I just started coding lua a few days ago, and I’m trying to get a timer.Simple to call a function every 12 seconds.

I have a function called ShowLvl(ply). How would I go about use this function every 12 seconds?

you need to either use **[Timer.Create

http://wiki.garrysmod.com/favicon.ico](http://wiki.garrysmod.com/?title=Timer.Create)** or you can put a new timer call at the end of the function like
[lua]
– This

function ShowLvl(ply)
– Blah, Blah, Code, Blah
end
timer.Create(“ShowLVLTimer”, 12, 0, ShowLvl, ply)

– or this
function ShowLvl(ply)

-- Blah, Blah, Code, Blah

timer.Simple(12, ShowLvl, ply)

end
[/lua]

Depending on what you’re doing this might not be the best way, but that’s how you can use timers. In the first example don’t forget to define ply before calling timer.Create and every time you call the second function it starts a loop so only run it once it will keep it’s self running

That worked, but now I seem to have an entity problem. I spawn it, it grows, but then the seed entity still exists. A friend told me just to make two entities, and remove 1 then spawn the other. But I have no idea how to do that either… Can someone please tell me how to remove it? Or tell what what I am doing wrong??

Most of the code works, except when when the tree grows and I eat it, it says ‘ENT (a nil value)’ in console… And I’ve got no idea how to set it.



include( 'shared.lua' )
include( 'core.lua' )

local GrowTime = 10
local SpawnPos = Vector.Zero

function ENT:Initialize()

if(GrowTime > 0) then
	self.Entity:SetModel( "models/weapons/w_bugbait.mdl" )


end
	
end

function ENT:SpawnFunction( ply, tr )

GrowTime = 10
SpawnPos = tr.HitPos + tr.HitNormal * 0

	local ent = ents.Create( "hm_tree" )
	ent:SetPos( SpawnPos )
	ent:SetSolid(SOLID_VPHYSICS)
	ent:Spawn()
	ent:Activate()
	ShowLvl( ply, ent )
	return ent
	
	
	
end


function ShowLvl( ply, ent )


GrowTime = GrowTime - 1

if(GrowTime == 0) then

local ent2 = ents.Create( "hm_tree" )
ent:Remove()
	ent2:SetModel( "models/props/CS_militia/tree_large_militia.mdl" )
	ent2:PhysicsInit(SOLID_VPHYSICS)
	ent2:SetSolid(SOLID_VPHYSICS)
	ent2:SetPos( SpawnPos )
	ent2:Spawn()

timer.Stop("ShowLVLTimer")

end


timer.Create("ShowLVLTimer", 1, 0, ShowLvl, ply)
 
end


function ENT:Use( activator, caller )

if(GrowTime <= 0) then

GrowTime = 10
SpawnPos = nil 
timer.Stop("ShowLVLTimer")
SetFoodLvl( ply, 25 )
	self.Entity:Remove()
	
if( activator:IsPlayer() ) then
	activator:SetHealth(activator:Health() + 25)

end

	
else 
	Msg("You must first wait for it to grow!")

	
	
	end

end


Ok, here’s a cleaned up commented version of the code, I believe this should work, but I wasn’t sure exactly how you wanted it to work.
I commented the code a lot and hope it makes sense.
I guessed that after the tree is used it will disappear and the player must spawn a new seed for another tree.
Hope this helps, and as for the error it was hard to tell looking at the code.
You should use [noparse] [lua] [/lua] [/noparse] around your code instead of the code tags.
If you still get the error let me know and i’ll see if I can help anymore.
[lua]
include( ‘shared.lua’ )
include( ‘core.lua’ )

local GrowTime = 10 – Only need this once
local TimerName = “” – save the timer name

function ENT:Initialize()
– The only time this function will be called is the first time you spawn each copy of this entity
self.Entity:SetModel( “models/weapons/w_bugbait.mdl” )
– I added the tostring(self) otherwise more than one of this entity will overwrite the other’s timers
– and we save it so we can get that from any function in here
TimerName = “ShowLVLTimer” … tostring(self)
end

function ENT:SpawnFunction( ply, tr )

local SpawnPos = tr.HitPos + tr.HitNormal * 0
local ent = ents.Create( "hm_tree" )
ent:SetPos( SpawnPos )
ent:SetSolid(SOLID_VPHYSICS)
ent:Spawn()
ent:Activate()
timer.Create(TimerName, 1, 0, ShowLvl, ply, ent )
return ent

end

function ShowLvl( ply, ent )

-- Take one away from the GrowTime 
GrowTime = GrowTime - 1

if (GrowTime &lt;= 0) then
	--Since this is the same entity and we just need to change the look 
	--We can just set the model and stop the timer.
	self:SetModel( "models/props/CS_militia/tree_large_militia.mdl" )
	timer.Stop(TimerName)
end
--Only need to create the timer here if we are using timer.Simple
--timer.Create("ShowLVLTimer", 1, 0, ShowLvl, ply)

end

–Not sure if you want to reuse the tree or not but it looks like you don’t
function ENT:Use( activator, caller )

if(GrowTime &lt;= 0) then
	-- ply isn't defined in this function so i'm guesing you wanted this to go to the person that used the tree
	SetFoodLvl( activator, 25 )
	if( activator:IsPlayer() ) then
		activator:SetHealth(activator:Health() + 25)
	end
	-- This will remove the current tree on the next tick ( almost instantly but less prone to errors
	SafeRemoveEntityDelayed(self, 0)
	-- if you want it replace it will a new seed then save self:GetPos() to a variable before the
	-- remove and spawn a new tree in it's place
	
	-- Check to see if the timer is still running and kill it if it is.
	if timer.IsTimer(TimerName) then timer.Destroy(TimerName) end
else 
	-- Msg will only show in the console if you want to let the person using it know
	if activator:IsPlayer() then activator:ChatPrint("You must first wait for it to grow!") end
end

end
[/lua]

I ran into a problem with your script… keeps saying: Timer Error: [addons\hunger\lua\entities\hm_tree\init.lua:37] attempt to index global ‘self’ (a nil value)
Also right now I have one more question… I’ve put some derma progress bar in the core.lua file, but when ever I open the menu I get a ‘vgui(a nil value)’ in console. But I used the code correctly…

[lua]

function GetFoodStatus( )

local DFrame = vgui.Create(‘DFrame’)
DFrame:SetSize(200, 80)
DFrame:SetPos(0,0)
DFrame:Center()
DFrame:SetTitle(‘Your food status’)
DFrame:SetSizable(false)
DFrame:SetDeleteOnClose(false)
DFrame:SetBackgroundBlur(false)
DFrame:ShowCloseButton(false)
DFrame:MakePopup()

local myProgressBar = vgui.Create( “DProgressBar”,DFrame)
myProgressBar:SetSize( 150, 40 )
myProgressBar:SetPos( 25, 25 )
myProgressBar:SetMin( 0 )
myProgressBar:SetMax(MaxFood)
myProgressBar:SetValue(plyFood)

end

concommand.Add(“ShowFoodStatus”, GetFoodStatus)

[/lua]

The vgui stuff is clientside only. You should put the display function in cl_init.lua. Then use usermessages to call it and don’t name your frame DFrame it can could cause problems.

try it like this
[lua]
– Client Side
– Goes in cl_init.lua
function ShowFoodStatus( msgData )

--Values must be read in the order sent
local MaxFood = msgData:ReadLong()
local plyFood = msgData:ReadLong()

local foodFrame = vgui.Create('DFrame')
foodFrame:SetSize(200, 80)
foodFrame:SetPos(0,0)
foodFrame:Center()
foodFrame:SetTitle('Your food status')
foodFrame:SetSizable(false)
foodFrame:SetDeleteOnClose(false)
foodFrame:SetBackgroundBlur(false)
foodFrame:ShowCloseButton(false)
foodFrame:MakePopup()

local myProgressBar = vgui.Create( "DProgressBar", foodFrame)
myProgressBar:SetSize( 150, 40 )
myProgressBar:SetPos( 25, 25 )
myProgressBar:SetMin( 0 )
myProgressBar:SetMax(MaxFood)
myProgressBar:SetValue(plyFood)

end
usermessage.Hook(“ShowFoodStatus”, ShowFoodStatus)

–Server Side

– This part goes in the serverside function when you want it to show the frame to the player
– this will send MaxFood and plyFood to the whatever ply to send the msg to. So in the use of your tree
– it would be activator instead of ply
umsg.Start(“ShowFoodStatus”, ply)
umsg.Long(MaxFood)
umsg.Long(plyFood)
umsg.End()
[/lua]

Oh-right thanks, also I ran into an issue with the tree script…

Timer Error: [addons\hunger\lua\entities\hm_tree\init.lua:37] attempt to index global ‘self’ (a nil value)

try changing self:SetModel in the ShowLvl Function to ent:SetModel

–SNIP–

Seems to be working fine, the only thing I gotta do now is making a progress bar with no cursor. O_o

After changing it back does it load again? and here are some changes that should work
the problem was ShowLvl didn’t know what self was, I was thinking ent was the same entity as the one running… i’m tired… anyway:
I changed 2 things because we need to pass self to the timer function

  1. on the timer line i added the self argument, this comes from any function starting with ENT: that means the first argument passed to the function is the entity

  2. changed the definition of ShowLvl to use ENT: so function ENT:ShowLvl
    [lua]
    function ENT:SpawnFunction( ply, tr )

    local SpawnPos = tr.HitPos + tr.HitNormal * 0
    local ent = ents.Create( “hm_tree” )
    ent:SetPos( SpawnPos )
    ent:SetSolid(SOLID_VPHYSICS)
    ent:Spawn()
    ent:Activate()
    – I added the tostring(self) otherwise more than one of this entity will overwrite the other’s timers
    timer.Create(TimerName, 1, 0, ShowLvl, self, ply, ent )
    return ent

end

function ENT:ShowLvl( ply, ent )

-- Take one away from the GrowTime 
GrowTime = GrowTime - 1

if (GrowTime &lt;= 0) then
	--Since this is the same entity and we just need to change the look 
	--We can just set the model and stop the timer.
	self:SetModel( "models/props/CS_militia/tree_large_militia.mdl" )
	timer.Stop(TimerName)
end
--Only need to create the timer here if we are using timer.Simple
--timer.Create("ShowLVLTimer", 1, 0, ShowLvl, ply)

end
[/lua]

It’s working fine now, I just made a scripting error…

Now I gotta figure out how to make a progress bar with-out a cursor, or some kind of way to tell the player their level without spamming them with messages.

You could just draw it instead of using the vgui stuff.

You just need a client side render hook, like **[Gamemode.HUDPaint

http://wiki.garrysmod.com/favicon.ico](wiki.garrysmod.com/?title=Gamemode.HUDPaint)** the example in there is half of what you need. The other half is the usermessages again, but this time it doesn’t show anything it just gets the values from the server, then in the HUDPaint hook check to see if you have a max value, and if you do draw the progress, just remeber to send a max of 0 when you want to stop drawing. I’d try to do some more code, but i’m getting to tired to think, so good luck.

Edit:
as far as when or how to show it you could make it an on demand thing and use **[Input.IsKeyDown

http://wiki.garrysmod.com/favicon.ico](http://wiki.garrysmod.com/?title=Input.IsKeyDown)** you need to put it in a client side think hook, but then you can have them press a key to see it like P for progress. I did this in my meteor game for the menu, however I still need to fix the problem of it reading the key when i’m typing in chat or console. Just an idea.

Ok, that’s all I need. Thanks for the help.