- Joined
- Apr 30, 2011
- Messages
- 359
a timer stack system, this system use only one timer, one trigger, and can support up to 8190 timer instances . . .
this system basically stack the timers, one that has the shortest remaining time will be runt first on that only one timer, then search another timer that has shortest expiration time again, this repeats until there's no more timer instances . . .
now it has a documentation . . .
Timer Stack:
[Example] Timed Function:
Feel free to comment, your suggestions are gladly appreciated!
this system basically stack the timers, one that has the shortest remaining time will be runt first on that only one timer, then search another timer that has shortest expiration time again, this repeats until there's no more timer instances . . .
now it has a documentation . . .
Timer Stack:
JASS:
//===================================================================================
//
// Timer Stack System
// -*- overcold_ice -*-
//
// [*] Requirements:
// - JNGP
// - latest version of JassHelper
//
// For your many long expiration time timers
// This system merges all of its timer instances into a dynamic single timer
// That timer will expire on all expiration time its timer instances have
//
// [*] Notes:
// - Not really suitable for short-expiring timer instances
// - Don't use a 0 expiration time timer instance, unless it have a destroy
// method called inside it. Or it will crash the game due to infinite loop
// - A timer instance will always loop if you don't destroy it
//
// [*] API:
//
// public module Implement
//
// static method tsCreate takes real time, code func returns integer
// - create a new timer instance that will expire after 'real time'
// seconds and run 'code func' function
// - returns the timer instance's id
//
// method tsDestroy takes nothing returns nothing
// - destroy a timer instance
//
// integer tsTimerId
// integer tsTimerTypeId
// - both of them are self-explanatory
// - they will get updated when a new timer instance is created (will
// return that new timer's id/typeid) and the timer expires (will
// return running function's timer instance's id/typeid)
// - you can re-assign those variables
//
// [*] Example/Add-on:
/*
library TimedFunc requires TimerStack
//
// API:
//
// set YourTFVariable = TF.start(time, function func)
// run the function after 'time' delay
//
// call YourTFVariable.stop()
// stop the running function
//
// Note:
// - Use TF(tsTimerId).stop() to stop the function when it's called
// - For additional information, read TimerStack's documentation
//
private struct TS extends array
implement TimerStack_Implement // it's a public module, so use that prefix
endstruct
struct TF extends array
static method start takes real time, code func returns integer
return TS.tsCreate(time, func)
endmethod
method stop takes nothing returns nothing
call TS(this).tsDestroy()
endmethod
endstruct
endlibrary
*/
//===================================================================================
library TimerStack
globals
// Timer Section
private integer c = 0 // timer instance count
private integer array r // timer's recycle bin
private integer array t // timer's type
private integer array nt // next timer
private integer array pt // previous timer
private integer array lt // last timer
private conditionfunc array cft // timer's action
// Timer Type Section
private integer tc = 0 // type count
private integer array tr // type's recycle bin
private integer array tn // next type
private integer array tp // previous type
private integer tl // last type
private real array tt // type's time
private real array trt // type's remaining time
private integer array ttc // type's instance count
// Trigger and Timer Section
private trigger trg = CreateTrigger() // the trigger
private timer tmr // the timer
private integer cur // current running timer type
private real let // last elapsed time
// Event Responses
integer tsTimerId = 0 // get instance's timer id
integer tsTimerTypeId = 0 // get instance's timer type id
endglobals
//===============================================================================
// TIMER STACK TYPE
//===============================================================================
// checks if there's another same type, if it's true, then use that type
// else, make a new one
private function GetType takes real time returns integer
local integer this = tl
local boolean exit = false
loop
exitwhen tp [tn [this]] == 0 or exit
if tt [this] == time then
set exit = true
else
set this = tp [this]
endif
endloop
if not exit then
set this = tr [0]
if this == 0 then
set tc = tc + 1
set this = tc
else
set tr [0] = tr [this]
endif
if tl == 0 then
set tp [this] = 0
else
set tp [this] = tl
endif
set tn [tp [this]] = this
set tn [this] = 0
set tl = this
set tr [this] = -1
endif
set tt [this] = time
set trt [this] = time
set ttc [this] = ttc [this] + 1
return this
endfunction
// reduce the amount of an type in a type stack by 1, if it has no more
// instance remaining, then destroy the timer type
private function LoseType takes integer this returns nothing
if tr [this] == -1 then
set ttc [this] = ttc [this] - 1
if ttc [this] == 0 then
if tn [this] == 0 then
if tp [this] == 0 then
set tl = 0
else
set tl = tp [this]
set tn [tp [this]] = 0
endif
else
set tn [tp [this]] = tn [this]
set tp [tn [this]] = tp [this]
endif
set tr [this] = tr [0]
set tr [0] = this
set tt [this] = 0
set trt [this] = 0
set ttc [this] = 0
endif
endif
endfunction
// refresh all timer types' remaining time
private function RefreshType takes nothing returns nothing
local integer this = tl
local real time = TimerGetElapsed(tmr) - let
set let = TimerGetElapsed(tmr)
loop
exitwhen tp [tn [this]] == 0
set trt [this] = trt [this] - time
set this = tp [this]
endloop
endfunction
//===============================================================================
// TIMER STACK
//===============================================================================
// runs when the timer expires, calling each timer type instances' actions
private function Expire takes nothing returns nothing
local integer this = lt [cur]
loop
exitwhen pt [nt [this]] == 0
set tsTimerId = this
set tsTimerTypeId = t [this]
call TriggerClearConditions(trg)
call TriggerAddCondition(trg, cft [this])
call TriggerEvaluate(trg)
set this = pt [this]
endloop
call RefreshType()
set trt [cur] = tt [cur]
set this = tl
loop
exitwhen tp [tn [this]] == 0
if cur == 0 or trt [cur] > trt [this] then
set cur = this
endif
set this = tp [this]
endloop
set let = 0
call DestroyTimer(tmr)
set tmr = CreateTimer()
call TimerStart(tmr, trt [cur], false, function Expire)
endfunction
// create a new timer instance, this timer instance will be automatically
// started
private function Create takes real time, code func returns integer
local integer this = r [0]
local integer that
if this == 0 then
set c = c + 1
set this = c
else
set r [0] = r [this]
endif
call RefreshType()
set t [this] = GetType(time)
set cft [this] = Condition(func)
if lt [t [this]] == 0 then
set nt [lt [t [this]]] = this
set nt [this] = 0
set pt [this] = 0
set lt [t [this]] = this
else
set nt [lt [t [this]]] = this
set nt [this] = 0
set pt [this] = lt [t [this]]
set lt [t [this]] = this
endif
set that = tl
loop
exitwhen tp [tn [that]] == 0
if cur == 0 or trt [cur] > trt [that] then
set cur = that
endif
set that = tp [that]
endloop
set let = 0
call DestroyTimer(tmr)
set tmr = CreateTimer()
call TimerStart(tmr, trt [cur], false, function Expire)
set tsTimerId = this
set tsTimerTypeId = t [this]
return this
endfunction
// destroy a timer instance
private function Destroy takes integer that returns nothing
local integer this = that
call LoseType(t [this])
if ttc [t [this]] == 0 and cur == t [this] then
call RefreshType()
set this = tl
set cur = 0
loop
exitwhen tp [tn [this]] == 0
if cur == 0 or trt [cur] > trt [this] then
set cur = this
endif
set this = tp [this]
endloop
set let = 0
call DestroyTimer(tmr)
set tmr = CreateTimer()
call TimerStart(tmr, trt [cur], false, function Expire)
endif
if nt [that] == 0 then
if pt [that] == 0 then
set lt [t [that]] = 0
else
set lt [t [that]] = pt [that]
set nt [pt [that]] = 0
endif
else
set nt [pt [that]] = nt [that]
set pt [nt [that]] = pt [that]
endif
set r [that] = r [0]
set r [0] = that
set t [that] = 0
set cft [that] = null
endfunction
//===============================================================================
// A P I
//===============================================================================
public module Implement
static method tsCreate takes real time, code func returns integer
return Create(time, func)
endmethod
method tsDestroy takes nothing returns nothing
call Destroy(this)
endmethod
endmodule
endlibrary
[Example] Timed Function:
JASS:
library TimedFunc requires TimerStack
//
// API:
//
// set YourTFVariable = TF.start(time, function func)
// run the function after 'time' delay
//
// call YourTFVariable.stop()
// stop the running function
//
// Note:
// - Use TF(tsTimerId).stop() to stop the function when it's called
// - For additional information, read TimerStack's documentation
//
private struct TS extends array
implement TimerStack_Implement // it's a public module, so use that prefix
endstruct
struct TF extends array
static method start takes real time, code func returns integer
return TS.tsCreate(time, func)
endmethod
method stop takes nothing returns nothing
call TS(this).tsDestroy()
endmethod
endstruct
endlibrary
Feel free to comment, your suggestions are gladly appreciated!
Last edited: