View Single Post
Dragokas
Veteran Member
Join Date: Nov 2017
Location: Ukraine on fire
Old 03-27-2020 , 12:42   Re: [TUT] SourcePawn Scripting - Tips, Basics to Advanced
Reply With Quote #32

Minimal sample "How to stop (delete) global timer"

I see a really lot of questions about:
Quote:
- Native "KillTimer" reported: Invalid timer handle XXX (error 3)
- Handle XXX is invalid (error 1)
- TIMER_FLAG_NO_MAPCHANGE doesn't stop timer when round ends/lost etc...
when somebody wants to start single or repeatable timer and stop it on round_end, manually or using TIMER_FLAG_NO_MAPCHANGE.

To do it without errors, you have to create timer correcly and nullify global variable in correct events.

Here are minimal correct samples with comments:

1. Global single timer (timer_single.sp)
Spoiler


2. Global repeatable timer (timer_repeat.sp)
Spoiler


3. Global single per-client timer (timer_single_per-client.sp)
Spoiler


4. Global repeatable per-client timer (timer_repeat_per-client.sp)
Spoiler


5. (No global var.) Pause repeatable timer
- without the need to manage handle in global variable (timer_repeat_pause.sp)
Spoiler


-------------------

General tips:
  • Do not use TIMER_FLAG_NO_MAPCHANGE flag if you assign timer's handle to a global variable to control the timer via this variable later.
    - TIMER_FLAG_NO_MAPCHANGE flag can be safely used if you create timer without assigning its handle to a variable.

  • When you kill timer outside the timer's callback, use 'delete' keyword.

  • When you kill repeatable timer within its own callback, use "return Plugin_Stop" only!
    - Do not use "delete" or "KillTimer()" there, otherwise you might receive error:
    Quote:
    Plugin "XXX.smx" encountered error 23: Native detected error
    [SM] Invalid timer handle XXX (error 3) during timer end, displayed function is timer callback, not the stack trace
  • You should always assign zero to timer's global variable in the very last line of timer's callback (before return) if timer's handle is about to destruct, that happen:
    - for repeatable timer, when you pass "return Plugin_Stop"
    - for single time, automatically when callback finishes.

    When your global variable is array-based and you don't know how to find it within timer's callback:
    - with per-client timers, use OnClientDisconnect() forward to do it.
    - with incremental based global timers:
    Spoiler

  • Delete timer before creating it to prevent it from firing twice, since some events like "round_start" could be fire multiple times.

  • To stop timer on round end, use both "round_end" event and "OnMapEnd()" forward, because "round_end" doesn't fire when map is forcibly changed.

Good luck!

P.S. If you found some grammar mistakes, please PM me.
Attached Files
File Type: zip Timers.zip (4.1 KB, 196 views)
__________________
Expert of CMD/VBS/VB6. Malware analyst. L4D fun (Bloody Witch & FreeZone)
[My plugins] [My tools] [GitHub] [Articles] [HiJackThis+] [Donate]

Last edited by Dragokas; 01-09-2021 at 09:53.
Dragokas is offline