• HUD Countdown Timer
    22 replies, posted
Hello everyone. I haven't done any lua coding in a while and I recently came back to one of my old projects. Can someone give me an example of how i could create a 30 minute countdown timer? I need it to show up on the players HUD, and to reset and call a function when the timer runs out. Thank you!
[img]http://wiki.garrysmod.com/favicon.ico[/img] [url=http://wiki.garrysmod.com/page/timer/Create]timer.Create[/url]
[QUOTE]give me an example[/QUOTE]
Read the page, it's not hard to figure out. [CODE] timer.Create( "GIVE_ME_AN_EXAMPLE", 60 * 30, 0, function() print( 'Function called' ) end ) -- later in some HUD hook shove the thing below in a text drawing function: timer.TimeLeft( "GIVE_ME_AN_EXAMPLE" ) -- just divide this by 60 if you want it in minutes or whatever [/CODE]
[QUOTE=A-c-e;50852906][quote]give me an example[/quote][/QUOTE] You mean like the one on the page he linked?
Another question, I have this code in my shared file: [CODE]local function DropTimer() timer.Create( "Drop Timer", 45 * 60, 0, function() for k, ply in pairs( player.GetAll() ) do ply:ChatPrint( "Timer Done" ) end end) end hook.Add( "Initialize", "Drop Timer", DropTimer )[/CODE] And this in my cl_inv file (I put the value in a derma panel instead of the HUD) [CODE]local droptimer = vgui.Create( "DLabel", mp ) droptimer:SetText( math.Round( timer.TimeLeft( "Drop Timer" )/60 ).." minutes to next drop." ) droptimer:SetPos( 12, 450 - 24 )[/CODE] The times are inconsistent between players, what's wrong?
If the code is shared then what's probably happening is that whenever a client joins the timer gets created on their side depending on their initial join time, which will obviously have differences. Try using a serverside only timer or set a serverside variable indicating when the timer started and subtract that from the current time
In the time waiting for a response, I've realized the shared issue, but now I can't seem to figure out how to get the variable from the server into the derma text. I'm using umsg.Start() to send the time as a float value, but how do i get the variable in the derma text?
[QUOTE=A-c-e;50864157]In the time waiting for a response, I've realized the shared issue, but now I can't seem to figure out how to get the variable from the server into the derma text. I'm using umsg.Start() to send the time as a float value, but how do i get the variable in the derma text?[/QUOTE] I think it'd be easiest if you did what I was trying to suggest before, first, create a variable for the timer serverside, E.G. [CODE] local timevariable = CurTime() [/CODE] Then when a client joins, just do some simple stuff to send the variable to them for them to use, e.g. [CODE] hook.Add( 'PlayerInitialSpawn', 'SendVariable', function( ply ) net.Start( 'sendvar' ) net.WriteFloat( timevariable ) -- the time variable set before net.Send( ply ) end ) [/CODE] Then in the clientside code: [CODE] net.Receive( 'sendvar', function() local var = net.ReadFloat() LocalPlayer().timevar = var end ) [/CODE] Then for the HUD you just need to do [CODE] CurTime() - LocalPlayer().timevar [/CODE] And that'll give you the time since the timer was called. If you want it to count down from 30 minutes then try this: [CODE] 60*30 - ( CurTime() - LocalPlayer().timevar ) [/CODE] Also, before for the 30 minute timer thing you seemed to be doing this: [CODE]timer.Create( "Drop Timer", 45 * 60, 0, function()[/CODE] 45 * 60 in seconds is not equal to 30 minutes. There are 60 seconds in a minute, just times 60 by 30 (30 minutes) to get the proper number (1800) Just to sum up what I said: [CODE] -- SERVERSIDE local timevariable = CurTime() -- Change this to whatever start time you want util.AddNetworkString( 'sendtimevariable' ) hook.Add( 'PlayerInitialSpawn', 'SendVariable', function( ply ) net.Start( 'sendtimevariable' ) net.WriteFloat( timevariable ) -- the time variable set before net.Send( ply ) end ) -- CLIENTSIDE local timevariable = 0 net.Receive( 'sendtimevariable', function() timevariable = net.ReadFloat() end ) hook.Add( 'HUDPaint', 'some_hud_idk', function() -- This is an example of how you could use it local countdowntime = (60*30)-(CurTime()-timevariable) draw.DrawText( countdowntime/60, "DermaDefault", ScrW()/2, ScrH()/2, Color( 255, 255, 255, 255 ), TEXT_ALIGN_LEFT ) -- divided by 60 to get it in minutes end ) [/CODE] I just tested that and it works for me :) [editline]11th August 2016[/editline] Also, if you want to use a DLabel for this, make sure to update it's number every frame... which can be done far more efficiently by not using a DLabel at all and just using a HUDPaint hook like everyone else :P
Exactly what I needed, thank you [editline]11th August 2016[/editline] Shoot one more thing, how do I reset the timer and when it's at 0? I know that I can use an if statement to see if the timer's at 0, but what variable do I need to manipulate?
Really don't understand why this is giving me zero [CODE] --SERVERSIDE timer.Create( "DropTimer", 30 * 60, 0, function() print( "done" ) end ) local timeleft = timer.TimeLeft( "DropTimer" ) util.AddNetworkString( 'sendtime' ) hook.Add( 'Initialize', 'SendDropTime', function() net.Start( 'sendtime' ) net.WriteFloat( timeleft ) -- the time variable set before end ) --CLIENTSIDE local timeleft = 0 net.Receive( 'sendtime', function() timeleft = net.ReadFloat() end ) hook.Add("HUDPaint", "HUD", function() local countdowntime = timeleft/60 draw.DrawText( countdowntime, "Default", ScrW()/2, ScrH()/2, Color( 255, 255, 255, 255 ), TEXT_ALIGN_LEFT ) end ) [/CODE]
Because you never sent it to a player. That's how the net library works, you have to send a message to a player, as I did in the thing I posted before. [CODE] net.Start( 'sendtimevariable' ) net.WriteFloat( timevariable ) net.Send( ply ) -- you need to send it to a player for it to work [/CODE] Why are you using the Initialize function anyway? It's far easier to use PlayerInitialSpawn since that accounts for players that will join when the server's already up. :snip: I get what you were trying to do, sorry
I understood the code, but I was trying to use a timer so i could call a function and reset it when it got to zero, if you see what i mean.
[QUOTE=A-c-e;50871557]I understood the code, but I was trying to use a timer so i could call a function and reset it when it got to zero, if you see what i mean.[/QUOTE] Yeah, I was thinking that... the way you were doing it was better than the stupid idea i had before [editline]12th August 2016[/editline] I *think* this might work, but I'm not sure... [CODE] --SERVERSIDE timer.Create( "DropTimer", 30 * 60, 0, function() print( "done" ) end ) local timeleft = CurTime() + timer.TimeLeft( "DropTimer" ) util.AddNetworkString( 'sendtime' ) hook.Add( 'PlayerInitialSpawn', 'SendDropTime', function( ply ) net.Start( 'sendtime' ) net.WriteFloat( timeleft ) -- the time variable set before net.Send( ply ) end ) --CLIENTSIDE local timeleft = 0 net.Receive( 'sendtime', function() timeleft = net.ReadFloat() end ) hook.Add( "HUDPaint", "HUD", function() local countdowntime =( timeleft - CurTime() ) / 60 draw.DrawText( countdowntime, "Default", ScrW()/2, ScrH()/2, Color( 255, 255, 255, 255 ), TEXT_ALIGN_LEFT ) end ) [/CODE] All I did was change the hook and add the net.Send bit and change a thing in the HUDPaint bit (since the timeleft variable doesn't get constantly updated) [editline]12th August 2016[/editline] Just remember that the timeleft thing doesn't get updated clientside every frame since that'd be quite slow (because of the constant networking), so you usually need to do something with CurTime() in the HUDPaint hook to get the right up-to-date time
I put in the code and once I joined the timer was at 10 seconds and it went into the negatives...?
Oh, I think I know why... I changed the post from before, I'll test it this time
I think that did it, just a second
By the way, all I changed was: [CODE] timeleft/60 - CurTime() [/CODE] To be: [CODE] ( timeleft - CurTime() ) / 60 [/CODE] Since if you divide the timeleft (which is now technically the time that the timer will stop at) by 60 then it'll get a bit weird when you take away the CurTime() [editline]12th August 2016[/editline] automerge :/
Working :) except one thing, the timer doesn't reset on the hud, I'm guessing that's what you were talking about earlier. [editline]12th August 2016[/editline] that's it because it's still printing in the console when it's done, what exactly can i do to update it?
Oh no, I didn't notice it was a resetting timer... I think if the timer is always out of 30 minutes then this would make it wrap back around: [CODE] local countdowntime = (( timeleft - CurTime() ) / 60 ) % 30 [/CODE] But there's probably a less stupid way, hold on, I'll try to find it
honestly that works great
Honestly this is the least stupid way I can think of: [CODE] --SERVERSIDE timer.Create( "DropTimer", 30 * 60, 0, function() print( "done" ) end ) util.AddNetworkString( 'sendtime' ) hook.Add( 'PlayerInitialSpawn', 'SendDropTime', function( ply ) net.Start( 'sendtime' ) net.WriteFloat( CurTime() + timer.TimeLeft( 'DropTimer' ) ) net.Send( ply ) end ) --CLIENTSIDE local TimeUp_Time = 0 net.Receive( 'sendtime', function() TimeUp_Time = net.ReadFloat() end ) hook.Add( "HUDPaint", "HUD", function() local countdowntime = ( ( TimeUp_Time - CurTime() ) / 60 ) % 30 draw.DrawText( countdowntime, "Default", ScrW() / 2, ScrH() / 2, Color( 255, 255, 255, 255 ), TEXT_ALIGN_LEFT ) end ) [/CODE] And it pretty much is the same thing as before... Hopefully someone else thinks of a better way
Thanks for your help I really appreciate it :)
Sorry, you need to Log In to post a reply to this thread.