Need some help with timers...

The situation- I have a command that should only display help for itself if the player does certain things… actually, just read it below.

--I have this script because the following command (not the original) only does what it should under certain conditions defined by the player,
--so if the player doesn't know why the command isn't working how they want (because they are not defining the correct conditions), then the command
--will suggest what to do with HELPFUL TEXT to help them do what they wanted. I decided to try using a timer because I only want the
--HELPFUL TEXT to show if the player has spammed the command in annoyance wondering why it doesn't work as they expect it to, but I don't want
--the command to show the HELPFUL TEXT if the player has already seen the text 2 times, as they should know what to do by now.

local annoycheck 0 -- The var defining how many times this command has been called

concommand.Add( "timer_test_command", function( ply )

	if annoycheck < 2 then --Checks that the function hasn't been called over 2 times

		if ( timer.Exists( "GravityDropAnnoyTimer" ) ) then --Not sure if timers destroy themselves when done, they probably do
		annoycheck = annoycheck + 1 --Add 1 to how many times the function has been called
		local annoyleft = timer.TimeLeft( "GravityDropAnnoyTimer" ) --Checks that the previous timer has not ended
		if annoyleft >= 0.01 then --If the timer has still got time remaining on it, then send over a helpful message.
		ply:SendLua( [[chat.AddText(Color(255,255,100), "HELPFUL TEXT")]] )
		timer.Create( "GravityDropAnnoyTimer", 1, 0, function() end ) --This timer is definitely the issue here, I want it to run in the background instead of running a function or something


		if ( timer.Exists( "GravityDropAnnoyTimer" ) ) then --I'm probably screwing a lot of stuff up with this, but if the function has been called over 100 times, I don't want the helpful text to be sent.
		timer.Destroy( "GravityDropAnnoyTimer" )


So, I’m 99% sure I used the timer completely wrong, as I don’t want it to do anything, just check itself whenever the command is run again. I think the solution is probably really simple or easy, because timers are new for me.

I have made quite a few “systems” that use a console command to display a help-menu of how to use it.

There are several paths you can take to doing this. If the command is client-side then you can use the auto-fill feature to dynamically populate the command to be called ( you can’t use auto-fill if you create the console command on the server but you can create it on the client and network the final arguments to the server )…

Example of autofill :

The other example is how some of my systems are set up so they’d be either: command or command /? to display help menu. If any of the /* commands were incorrect or had incorrect data it’d warn them.

NOTE: Some of these are “dev” tools or examples so they may use BAD practices in the calls ( such as using player:SendLua, etc… ).

TTT Slay Next Round - supports multiple slays, supports punishing on disconnect ( doesn’t save the slay ), etc. This system also uses a dynamic method of outputting data to the server-console or client-console depending who called it ( which is what _func( _funcarg, … ); is )… It has a menu to add slays, remove slays, list-all, force-save the file, force reload the file, etc…

Remove props in map - This comes in various forms… Some have small changes, others slightly more. One has “working object” system and undo system which lets you select props and then confirm them. Others simply add or remove.

This is an automated cleanup system ( was requested as how-to ) which goes through the table step by step ( each time timer is called it increments ). At the end of the table it executes a function ( well, each step it looks for a function to call before incrementing ): - not the most ideal solution for setting up a count-down ( my timed-event system will be released soon ) but it isn’t the worst either ( I’ve seen systems that create 20+ timers at once to do it )…

Timers are meant to delay an action from happening until the time runs out. If you want an action to occur for the specified time, an alternative system is needed ( look at my hook.AddTemp / draw.This / render.This example in my dev-base [ shared code for hook.AddTemp, client for other 2 ] ):

I hope these help in providing different methods of performing certain actions; remove .html to view / copy .lua

Oh, sorry, by ‘certain conditions defined by the player’, I didn’t mean args, I meant clientconvars. I think I should explain a bit more (but hook.AddTemp does sound okay at the moment),

I’m making a gravity remover with quite a few settings. There is a tick box that switches the function of 2 buttons below it, so they either affect the PhysEnv’s gravity or go through every prop on the map setting gravity to ‘false’. If the player presses the button to REMOVE the gravity with BOTH the PhysEnv’s gravity and every individual prop’s gravity set to be FALSE (or the equivalent to false), then it obviously will not work, as if the environment gravity changes, props are still set to float, but if the prop gravity changes, the environment gravity will still be set to float. This is expected to happen, but if the player doesn’t know why the props aren’t falling back down (because they need to tick the box and apply the ‘drop props’ setting, then un-tick it and do the same), they will most likely spam the button in annoyance, so that’s why the HELPFUL TEXT suggests to type a certain command into chat, called ‘gravity_forcedrop’ (created by the tool, obviously), that changes both the PhysEnv and the individual prop settings. I don’t need to fix my script or anything, as this is exactly what it’s meant to do, but I do need to fix the PLAYER and attempt to help them. I could add more buttons, but I don’t like tons of unnecessary clutter.

It is cheaper to simply set sv_gravity to 0 ( don’t forget to read the value prior to setting it so when you set it again, it’ll be what the server originally had it set to ) instead of looping through a possible 8196 entities…

The hook.AddTemp system lets you run something for a specified time. Example: You want text to appear on screen for 3 seconds. You could use draw.This ( helper-function which uses HUDPaint ) and simply add the function to run in HUDPaint for 3 seconds. After the time is up, it’ll be removed.

For what you want, a timer would likely be better in this context:

local _sv_gravity = nil;
function DisableGravityAnnoyance( )
	// Don't run if not set
	if ( !_sv_gravity ) then return; end

	RunConsoleCommand( "sv_gravity", tostring( _sv_gravity || "600" ) );
	_sv_gravity = nil;

function EnableGravityAnnoyance( )
	// Don't run more than once
	if ( _sv_gravity ) then return; end

	_sv_gravity = GetConVarInt( "sv_gravity" );
	RunConsoleCommand( "sv_gravity", "0" );

	// End the annoyance in 3 seconds
	timer.Simple( 3, DisableGravityAnnoyance );

	// If this costs a point or whatever, simply do: if EnableGravityAnnoyance( ) then ... else ... end
	return true;

So, when you enable it, it reads the current value of sv_gravity, then it sets gravity to 0 serverwide, then in 3 seconds it will disable the annoyance. On disable, it sets gravity to what gravity was then unsets it…

In both cases it will only execute if it hasn’t been enabled already or hasn’t already been disabled.

Actually, nevermind. I thought of a solution that won’t confuse players. Thanks for the help, anyway.