y_timers - Stopping the timer makes it run
#1

Hello,

I stumbled over some weird issue while using y_timers. I'm making a system that despawns a player's vehicle after 15 minutes if he doesn't come back on the server, and I thought about making a timer with y_timers. Ok, it works and everything, but if the player comes back and I do "stop" or "KillTimer" over the pre-mentioned timer, it actually runs the code inside the timer. Thanks in advance.

Here you have the code:

timer:
pawn Код:
timer DespawnPVeh[900000]( vehid, vehslot, string:playername[ ] ){
    new
        Float: vehhp ;
       
    GetVehicleHealth( vehid, vehhp ) ;     
    p_VehicleData[ vehid ][ HP ] = vehhp ;
       
    SavePVeh( playername, vehid, vehslot ) ;           
           
    enginestatus[ vehid ] = 0 ;
    stlights[ vehid ] = 0 ;
    DestroyVehicle( vehid ) ;
   
    print( "Debug: DespawnPVeh executed succesfully after 900,000ms." ) ;
}
stop:
pawn Код:
stop DespawnPVeh( PlayerData[ playerid ][ SpawnedVeh ], slotspawned[ playerid ], GetName( playerid ) )

or KillTimer( DespawnPVeh( PlayerData[ playerid ][ SpawnedVeh ], slotspawned[ playerid ], GetName( playerid ) ) ) ;
Reply
#2

Cause you call a timer when you want to stop a timer?

Код:
main()
{
    repeat DelayedFunction(42);
    new
        Timer:x = repeat DelayedFunction(42);
    stop x;
}
Reply
#3

pawn Код:
stop DespawnPVeh;
Reply
#4

Quote:
Originally Posted by DRIFT_HUNTER
Посмотреть сообщение
pawn Код:
stop DespawnPVeh;
It doesn't work like that, he have to declare Timer:name variable to stop it.

@topic
It's impossible to stop it after relog with code like that.

There are 2 other ways:

1. Global task with checking player online status and counting variable.
2. Use respawn_delay argument in CreateVehicle, it's much easier.
Reply
#5

Quote:
Originally Posted by raydx
Посмотреть сообщение
It doesn't work like that, he have to declare Timer:name variable to stop it.

@topic
It's impossible to stop it after relog with code like that.

There are 2 other ways:

1. Global task with checking player online status and counting variable.
2. Use respawn_delay argument in CreateVehicle, it's much easier.
Yep my bad
Reply
#6

The issue was solved in some dirty way. Let's see the code (for people that have the same problem like me, or similar problems in the future)

Creating the variables: (penums.inc)
Код:
enum timDat { //More timers to be added in the future
    Timer:crash_timeout	
};
new _gm_timers_data[ MAX_DB_ID ][ timDat ] ;
I really thought better and saw that the playerid method is not gonna work and is a bad idea because another player might connect and get assigned that specific playerid and everything would be f****d up. So, I thought about using the database IDs of the players to make sure nothing gets overwritten and so on. (MAX_DB_ID has been defined as 99999 - a reasonable number let's say)

Moving on... calling the timers (random.pwn)
Код:
public SavePlayerLoc( playerid ){
    new
	    Float: x,
		Float: y,
		Float: z ;
		
	GetPlayerPos( playerid, x, y, z ) ;
	PlayerData[ playerid ][ LastX ] = x ;
	PlayerData[ playerid ][ LastY ] = y ;
	PlayerData[ playerid ][ LastZ ] = z ;	
	
	_gm_timers_data[ PlayerData[ playerid ][ ID ] ][ crash_timeout ] = defer CrashTimeOut( PlayerData[ playerid ][ ID ], PlayerData[ playerid ][ SpawnedVeh ], slotspawned[ playerid ], GetName( playerid ) ) ;
	return 1 ;
}
So, this function just saves a player's last position so he can be spawned back at that specific location, nothing too complicated, but I have chosen to include the timer here because it gets called before the account saves and this gives me better control over the situation. You may ask yourself why I included both GetName and the database ID variable; well, my vehicle saving system works with the player's name so this is why I did this. The rest of it is pretty explainable.

Next -> the timers. (gmtimers.pwn)
Код:
timer CrashTimeOut[900000]( dbid, vehid, vehslot, string:playername[ ] ){
    mysql_format( C_RP_DB_HANDLE, query, sizeof( query ), "UPDATE `players` SET spawnedveh='0', spawnedslot='0', lastx='0', lasty='0', lastz='0', crashed='0', sessiontime='0' WHERE id='%d'",
	dbid ) ;
	mysql_tquery( C_RP_DB_HANDLE, query, "", "" ) ;
	
	print( "CrashTimeOut has been executed." ) ;

        DespawnPVeh( vehid, vehslot, dbid, playername ) ;
}

timer DespawnPVeh[3200]( vehid, vehslot, dbid, string:playername[ ] ){
    new
        Float: vehhp ;
		
    GetVehicleHealth( vehid, vehhp ) ;		
	p_VehicleData[ vehid ][ HP ] = vehhp ;
		
	SavePVeh( playername, vehid, vehslot ) ;		    
			
	enginestatus[ vehid ] = 0 ;
	stlights[ vehid ] = 0 ;
	DestroyVehicle( vehid ) ;
	
	stop _gm_timers_data[ dbid ][ crash_timeout ] ;
	
	print( "DespawnPVeh executed. CrashTimeOut repeat killed." ) ;
}
The first timer just resets the player's variables (related to coming back at the same position and everything) through mysql. The next timer, is set to run at 3.5 seconds after that because I don't want it to be ran at the same time with the first one in case a large number of players just crash at the same time and the database will just get overcrowded with requests. Why would I stop the crash_timeout timer in DespawnPVeh? Because, you can't create a timer through a variable without either 'defer' or 'repeat' before it; so I have chosen to use defer, but that runs the timer one more time and I just don't need that in my life, y'know? So it just kills it and stays dead. So, in conclusion, whenever the player comes online and the timer is still ticking, it just stops it by a function that also resets his "crash" variables. Pretty easy, huh?

I hope this dirty trick actually helped someone and if you guys have other suggestions, let me know. Peace
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)