SA-MP Forums Archive
Timer delay according to gettime() - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Scripting Help (https://sampforum.blast.hk/forumdisplay.php?fid=12)
+--- Thread: Timer delay according to gettime() (/showthread.php?tid=602135)



Timer delay according to gettime() - DOL4N - 02.03.2016

Hey guys!
I am working on a script and something is not working correctly:
I'm trying to do an interest/lvlup system, which gives the +amount of interest and gives +1 score every 1 hour online.

Everything else is working correctly, the problem is the constantly growing delay between saved timer seconds and saved played seconds.

Код:
new FizuIdo;  // timer
new fizump[MAX_PLAYERS]; // seconds

forward FizuTimer(playerid);

public FizuTimer(playerid)
{
	fizump[playerid]++;
	if(fizump[playerid] >= 3600) // 1 hour -- 
	{
	        new time = gettime() - gPlayerJoin[playerid];
		new score = GetPlayerScore(playerid);
	        new string[128], kamat[128], ora, egyenleg;
	        ora = (PlayerInfo[playerid][pJatszottIdo]+time)/3600;
	        egyenleg = PlayerInfo[playerid][pBank];
	        fizump[playerid] = 0;
		...
	}
	return 1;
}

public OnPlayerSpawn(playerid)
{
        gPlayerJoin[playerid] = gettime();
        SetPlayerSkin(playerid, PlayerInfo[playerid][pSkin]);
        fizump[playerid] = PlayerInfo[playerid][pFizetesOra];  // load saved seconds
        FizuIdo = SetTimer("FizuTimer", 1000, 1);   // paycheck timer start again
	return 1;
}

public OnPlayerDisconnect(playerid, reason)
{
	KillTimer(FizuIdo);  // shall this be after saving timer seconds? (line above return 1)
	new time = gettime() - gPlayerJoin[playerid];
	new jOra = (PlayerInfo[playerid][pJatszottIdo]+time)/3600;
	new jPerc = (PlayerInfo[playerid][pJatszottIdo]+time)/60; 
	new jMp = PlayerInfo[playerid][pJatszottIdo]+time-(60*jPerc);
        ...                                                                                                          
        INI_WriteInt(File, "Уra", jOra); 
	INI_WriteInt(File, "Perc", jPerc); 
	INI_WriteInt(File, "Mбsodperc", jMp);
        INI_WriteInt(File, "JбtszottIdő", PlayerInfo[playerid][pJatszottIdo] + time); 
        INI_WriteInt(File, "FizetйsУra", fizump[playerid]); // SAVING TIMER SECONDS
        return 1;
}

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
        if(dialogid == dialog_register)
        {
                ...
                INI_WriteInt(File, "JбtszottIdő", 0);          // saving played seconds
	        INI_WriteInt(File, "FizetйsУra", 0);          // saving timer seconds
        }
        if(dialogid == dialog_login)
        {
                fizump[playerid] = PlayerInfo[playerid][pFizetesOra];  // loading timer seconds
        }
        return 1;
}
After joining and leaving, the timer saved 17 seconds, and with the gettime().. it saved 19 seconds.
I've also tried SetTimerEx, but there was a delay too.
Also, I've checked that after a minute the delay grows into 7 seconds (timer saves 60 seconds, gettime()... saves 67 secs.)
Sorry for unclear explanation and bad english, if something is not clear please tell me.
Please help me with this one.


Re: Timer delay according to gettime() - Vince - 02.03.2016

The point of using gettime() is to not rely on timers. Timers are seriously inaccurate; they're at least 20% off.


Re: Timer delay according to gettime() - DOL4N - 02.03.2016

I see. Can you suggest how to execute this properly? The interest income and +score every hour?


Re: Timer delay according to gettime() - xEF - 02.03.2016

Use gettickcount, it's pretty more easy and it doesn't use so much lines and functions, it can too make actions after a certain time, like give score every 1 hour.


Re: Timer delay according to gettime() - MeCom - 02.03.2016

Quote:
Originally Posted by DOL4N
Посмотреть сообщение
I see. Can you suggest how to execute this properly? The interest income and +score every hour?
i use this way to reward players playing for 1 hour

Код:
enum pInfo
{
    pSecs,
    pMins,
    pHours
}
new PlayerInfo[MAX_PLAYERS][pInfo];

public OnGameModeInit()
{
	SetTimer("PlayedHours", 1000, 1); //sets timer to call every 1 second
	return 1;
}

//saving
public OnPlayerDisconnect(playerid, reason)
{
    new INI:File = INI_Open(UserPath(playerid));
    INI_SetTag(File,"data");
	INI_WriteInt(File,"Mins",PlayerInfo[playerid][pMins]);
	INI_WriteInt(File,"Hours",PlayerInfo[playerid][pHours]);
	INI_WriteInt(File,"Secs",PlayerInfo[playerid][pSecs]);
    INI_Close(File);
	return 1;
}

//loading
public LoadUser_data(playerid,name[],value[])
{
    INI_Int("Mins",PlayerInfo[playerid][pMins]);
    INI_Int("Hours",PlayerInfo[playerid][pHours]);
    INI_Int("Secs",PlayerInfo[playerid][pSecs]);
    return 1;
}

forward PlayedHours(playerid);
public PlayedHours(playerid)
{
	PlayerInfo[playerid][pSecs] ++; // +1 second evertime timer "playedhours" calls
	if(PlayerInfo[playerid][pSecs]>=60)//untill reaches 60
	{
		PlayerInfo[playerid][pSecs]=0; //resets seconds to 0
		PlayerInfo[playerid][pMins]++; // +1 min
	}
	if(PlayerInfo[playerid][pMins]>=60) //untill reaches 60
	{
		PlayerInfo[playerid][pMins]=0; //resets minutes to 0
		PlayerInfo[playerid][pHours]++; // +1 hour

		//reward the player for completeing 1 hour
	}
}
you can try it


Re: Timer delay according to gettime() - DOL4N - 02.03.2016

It's working like that, MeCom. Thank you so much!
Rep++


Re: Timer delay according to gettime() - NaS - 02.03.2016

Quote:
Originally Posted by DOL4N
Посмотреть сообщение
It's working like that, MeCom. Thank you so much!
Rep++
The code he showed you is a) inefficient (no need for a 1s timer, 10min is enough) and b) only working for player 0.

Create a global array and a define:

Код:
#define REWARD_TIME 3600000 // ms, one hour
new tPlayerLogin[MAX_PLAYERS];
In OnPlayerConnect:

Код:
tPlayerLogin[playerid] = GetTickCount();
Set a 600 seconds timer which calls the following function. The timer only defines when the check is done, so it can be anything below one hour but should be around 5-10 minutes to give rewards on time.

Код:
forward PlayedTimer();
public PlayedTimer()
{
	new curTick = GetTickCount();
	
	for(new playerid = 0; playerid < GetMaxPlayers(); playerid ++) // Could be replaced by foreach
	{
		if(!IsPlayerConnected(playerid) || IsPlayerNPC(playerid)) continue;
		
		new timedif = curTick - tPlayerLogin[playerid];
		if(timedif > REWARD_TIME)
		{
			tPlayerLogin[playerid] += REWARD_TIME;

			// Code to do when he played another hour
		}
	}
}
This is an always precise reward timer, to make it exact throughout multiple logins save and load the difference between GetTickCount() and tPlayerLogin, then substract it from the GetTickCount() in OnPlayerConnect.