SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Scripting Help > Tutorials

Reply
 
Thread Tools Display Modes
Old 12/10/2010, 10:36 AM   #1
Lenny the Cup
Huge Clucker
 
Join Date: Jan 2008
Posts: 212
Reputation: 17
Default Player-timers

I have seen a lot of people using the SA-MP timers for their players, which is rather redundant if you want an efficient script. There is no point in starting a new timer just to check if they're close to something every 5 seconds, or if they're using hacks every two seconds, or anything else every x seconds.

Instead, use variables to store unix time and put them in OnPlayerUpdate. Let me demonstrate:

Issue: I want a timer to check every three seconds if a player is near XYZ.
Solution:
First I need a variable to store the timer in:
pawn Code:
new XYZCheckTimer[MAX_PLAYERS];
Now I put the variable inside OnPlayerUpdate, which is called lots of times each second.
pawn Code:
public OnPlayerUpdate(playerid)
{
    new iTime = gettime();
    if(XYZCheckTimer[playerid] < iTime)
    {
        if(IsPlayerInRangeOfPoint(playerid, range, x, y, z))
        {
            do the stuff!
            XYZCheckTimer[playerid] = iTime+3;
        }
    }
    return 1;
}
Note that this causes less CPU reduction than a timer does since it only checks for a variable in a function that is already called automatically instead of creating a new process for the server to take care of.

I can even create my own "One-second timer" here:
pawn Code:
new OneSecondTimer;

public OnPlayerUpdate(playerid)
{
    new iTime = gettime();
    if(OneSecondTimer < iTime)
    {
        OneSecond();
        OneSecondTimer = iTime;
    }
    return 1;
}

stock OneSecond()
{
    One second passed!
}

(Update)
This technique can also be applied to command restrictions (And other similar player-based restrictions). Let's say we need to make sure players can't repair their cars more often than every X seconds:
pawn Code:
new aRepairTime[MAX_PLAYERS];

public OnPlayerCommandText
{
    // ... they try to repair:
    if(aRepairTime[playerid] < gettime()) // Checks if they've waited long enough since last time (Or haven't done it at all)
    {
        // Do the repair
        aRepairTime[playerid] = gettime()+X // X = Amount of seconds you want to block them
    }
}

Please note that these timers only work if there are players online and active (Not tabbed out). OnPlayerUpdate is only called when a player sends their information to the server (Position, facing angle etc), but if they're playing this happens many times each second, as I mentioned above.

Good luck!
__________________
Lenny / Lenny Carlson @ LS-RP.com
My pastebin - All my released scripts
pawn Code:
-,-----,
/----/ |                                           ,---,   ,----,
|    | |      ,------, ,----,  ,----, ,----,  ,---/---/ \ /---/ |
|    | |     /-----/ |/----/ \/---/ |/----/ \/--- \   \  /   / /
|    | |     |  ,__|/ |     \|    | ||     \|    | \   \/   / /
|    | |____ |  ---,/||      \    | ||      \    | |\      / /
|    |____/ ||  ,__|/ |   ^\      | ||   ^\      | | |    | |
|         | ||  ---,/||   | \     | /|   | \     | | |    | |
|_________|/ |_____|/ |___,/ \____,/ |___,/ \____,/  |____,/

Last edited by Lenny the Cup; 12/10/2010 at 11:53 AM.
Lenny the Cup is offline   Reply With Quote
Old 12/10/2010, 11:03 AM   #2
Rachael
Huge Clucker
 
Rachael's Avatar
 
Join Date: Feb 2010
Posts: 380
Reputation: 28
Default Re: Player-timers

While I do not disagree with the logic here, especially for very frequent ( or short ) timers, I am sceptical as to the efficiency of putting an entire scripts worth of timers under OnPlayerUpdate. Particularly for things which might be checked every 10 minutes or more.

I would be interested to know if it would still be more efficient to check unix time vs a variable 12,000 times, rather than doing one larger computation under a repeating 10 minute timer.

To put this in perspective, in my script I often use a repeating 1 minute timer to manipulate variables that have been set according to how many minutes I want the 'cooldown' period to be. Eg If I want to block a player from repairing a vehicle for 5 minutes, I will set 'repairtime[playerid]' to 5, and decrement it under the aforementioned 1 minute timer.

I consider this to be neater, and assume it is more efficient than a new SetTimerEx("function","d",playerid); for each player.

Tell me what you think.
Rachael is offline   Reply With Quote
Old 12/10/2010, 11:22 AM   #3
Lenny the Cup
Huge Clucker
 
Join Date: Jan 2008
Posts: 212
Reputation: 17
Default Re: Player-timers

That's quite a bad way of putting restrictions on players, timers should never be used for such things. Just put the time of their last action you want to block in a variable, then when they try to do it again check if X seconds passed since that timestamp.
pawn Code:
new repairtime[MAX_PLAYERS];

OnPlayerCommandText // or whatever function you're using it in
{
    // ... they try to do it:
    if(repairtime[playerid] < gettime()) // If they've waited long enough
    {
        // Do the repair
        repairtime[playerid] = gettime()+X // X = Amount of seconds you want to block them
    }
}

I would love to have some form of comparison between the CPU usage of the two different methods, but I can't think of any way to benchmark them properly.
__________________
Lenny / Lenny Carlson @ LS-RP.com
My pastebin - All my released scripts
pawn Code:
-,-----,
/----/ |                                           ,---,   ,----,
|    | |      ,------, ,----,  ,----, ,----,  ,---/---/ \ /---/ |
|    | |     /-----/ |/----/ \/---/ |/----/ \/--- \   \  /   / /
|    | |     |  ,__|/ |     \|    | ||     \|    | \   \/   / /
|    | |____ |  ---,/||      \    | ||      \    | |\      / /
|    |____/ ||  ,__|/ |   ^\      | ||   ^\      | | |    | |
|         | ||  ---,/||   | \     | /|   | \     | | |    | |
|_________|/ |_____|/ |___,/ \____,/ |___,/ \____,/  |____,/
Lenny the Cup is offline   Reply With Quote
Old 12/10/2010, 11:43 AM   #4
Rachael
Huge Clucker
 
Rachael's Avatar
 
Join Date: Feb 2010
Posts: 380
Reputation: 28
Default Re: Player-timers

This is good, I can see the benefits of using gettime for this. I already use unix timestamps for quite a lot of similar applications in the script, some of which are over a much greater time period.

Assuming the result of gettime() is an integer, how large is it? can it be stored in a variable without wrapping to negative?

Does a unix timestamp ever roll around to zero? effectively causing an error in the longer time comparisons that I have. and if so how often?
[edit] ****** answered my second question
Rachael is offline   Reply With Quote
Old 12/10/2010, 11:50 AM   #5
Lenny the Cup
Huge Clucker
 
Join Date: Jan 2008
Posts: 212
Reputation: 17
Default Re: Player-timers

As you can see on the SA-MP wiki, the function returns the amount of seconds passed since 00:00 Jan 1 1970, which is the "official" start of the Unix era. So it can never return a lower value at a later point than the first. It can very much be stored in a regular integer or array cell.
__________________
Lenny / Lenny Carlson @ LS-RP.com
My pastebin - All my released scripts
pawn Code:
-,-----,
/----/ |                                           ,---,   ,----,
|    | |      ,------, ,----,  ,----, ,----,  ,---/---/ \ /---/ |
|    | |     /-----/ |/----/ \/---/ |/----/ \/--- \   \  /   / /
|    | |     |  ,__|/ |     \|    | ||     \|    | \   \/   / /
|    | |____ |  ---,/||      \    | ||      \    | |\      / /
|    |____/ ||  ,__|/ |   ^\      | ||   ^\      | | |    | |
|         | ||  ---,/||   | \     | /|   | \     | | |    | |
|_________|/ |_____|/ |___,/ \____,/ |___,/ \____,/  |____,/
Lenny the Cup is offline   Reply With Quote
Old 12/10/2010, 04:18 PM   #6
playbox12
High-roller
 
playbox12's Avatar
 
Join Date: Feb 2010
Location: Netherlands
Posts: 1,319
Reputation: 216
Default Re: Player-timers

Quote:
Originally Posted by ****** View Post
I'm sorry, if this is more efficient that normal timers I will be VERY much surprised!

1) Normal timers are C++, these timers are PAWN - instant win for natives!

2) You are just replicating the source of normal timers in PAWN - how do you think they work? It is NOT using processes as you seem to think, it is just a function in the server called in EXACTLY the same way as you are doing, to check the elapsed time and fire off PAWN functions as appropriate.

3) This doesn't support timers with sub-second fractions.

When used properly there is nothing at all wrong with using SA:MP timers - they were designed to have many spawned, plus they keep code neat and separated, this method doesn't.

I also don't see the big 'hype' about 'timers are bad, don't use them' I've used timers quite alot, and I never had any lagg at all, that includes a timer that is called every second.

But, anyways, nice tutorial Lenny, I did learn something from it, and I am sure some more people will.
playbox12 is offline   Reply With Quote
Old 13/10/2010, 11:13 AM   #7
Lenny the Cup
Huge Clucker
 
Join Date: Jan 2008
Posts: 212
Reputation: 17
Default Re: Player-timers

How often are the timers checked?
__________________
Lenny / Lenny Carlson @ LS-RP.com
My pastebin - All my released scripts
pawn Code:
-,-----,
/----/ |                                           ,---,   ,----,
|    | |      ,------, ,----,  ,----, ,----,  ,---/---/ \ /---/ |
|    | |     /-----/ |/----/ \/---/ |/----/ \/--- \   \  /   / /
|    | |     |  ,__|/ |     \|    | ||     \|    | \   \/   / /
|    | |____ |  ---,/||      \    | ||      \    | |\      / /
|    |____/ ||  ,__|/ |   ^\      | ||   ^\      | | |    | |
|         | ||  ---,/||   | \     | /|   | \     | | |    | |
|_________|/ |_____|/ |___,/ \____,/ |___,/ \____,/  |____,/
Lenny the Cup is offline   Reply With Quote
Old 13/10/2010, 08:23 PM   #8
Lenny the Cup
Huge Clucker
 
Join Date: Jan 2008
Posts: 212
Reputation: 17
Default Re: Player-timers

afaik OnPlayerUpdate is only run twice a second per player when on foot, which is equal to 5 milliseconds if you have 100 players active on your server (2x100 = 200 times a second = once every 5 ms right?)

But like you said, C++ wins :/
__________________
Lenny / Lenny Carlson @ LS-RP.com
My pastebin - All my released scripts
pawn Code:
-,-----,
/----/ |                                           ,---,   ,----,
|    | |      ,------, ,----,  ,----, ,----,  ,---/---/ \ /---/ |
|    | |     /-----/ |/----/ \/---/ |/----/ \/--- \   \  /   / /
|    | |     |  ,__|/ |     \|    | ||     \|    | \   \/   / /
|    | |____ |  ---,/||      \    | ||      \    | |\      / /
|    |____/ ||  ,__|/ |   ^\      | ||   ^\      | | |    | |
|         | ||  ---,/||   | \     | /|   | \     | | |    | |
|_________|/ |_____|/ |___,/ \____,/ |___,/ \____,/  |____,/
Lenny the Cup is offline   Reply With Quote
Old 13/10/2010, 08:29 PM   #9
Slice
High-roller
 
Join Date: Mar 2008
Location: Sweden
Posts: 1,835
Reputation: 1607
Default Re: Player-timers

Quote:
Originally Posted by Lenny the Cup View Post
afaik OnPlayerUpdate is only run twice a second per player when on foot, which is equal to 5 milliseconds if you have 100 players active on your server (2x100 = 200 times a second = once every 5 ms right?)

But like you said, C++ wins :/
Usually ~30 times a second when moving, aiming, or driving.
Slice is offline   Reply With Quote
Old 14/10/2010, 05:37 PM   #10
RoBo
Huge Clucker
 
RoBo's Avatar
 
Join Date: Jan 2008
Posts: 378
Reputation: 12
Default Re: Player-timers

Most of the time you don't need timers anyway, OnPlayerUpdate is much better as it spreads out the load rather than running the code for up to 500 players in 1 go. As it stands, I'm sure you could rewrite 90% of SA:MP gamemodes with no timers at all.
RoBo is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Multiple per-player timers or just one timer with a loop? Hiddos Help Archive 4 28/08/2010 10:15 AM
Individual player timers? VictorMartinez Help Archive 5 21/07/2010 03:43 AM
GetPlayerSpeed, No timers-Player Speed instantly misco Help Archive 51 04/06/2010 10:45 AM
TIMERS?!!? coole210 Help Archive 5 06/07/2009 04:18 AM
Timers streetzuk Help Archive 13 11/04/2009 06:17 PM


All times are GMT. The time now is 02:59 PM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.