9 years
edited 8 years
Useful system especially in making an MUI spell which uses timers. Instead of saving the spell data in a hashtable with the handleid of the timer as the parent key, you can just use normal arrays with the timerid as the index. This also allows you to pass custom data (integer) to timers.
System Features:
System Features:
- Indexed timers (Array safe, 1-8190 but can also be customized to be 8190+) NEW
- Timer custom data (integer) attachment [NEW]
- Timer double free protection
- Automatic timer replacement (Useful safety feature which automatically replaces timers belonging to this system with a timer of the same timerid and handleid when destroyed)
Timer Indexer v1.2library TimerIndexer //v1.2
//! novjass
________________
| |
| Written by AGD |
|________________|
|=====|
| API |
|=====|
function GetTimer takes nothing returns timer/*
- Allocates a new usable timer from the stock
*/function GetTimerEx takes integer i returns timer/*
- Retrieves a new usable timer from the stock and initializes
its custom integer data to <i>
*/function GetTimerById takes integer i returns timer/*
- Retrieves a timer of ID <i> from the stock but returns
null if that timer is not free
*/function FreeTimer takes timer t returns nothing/*
- Releases the timer back to the stock
*/function GetTimerId takes timer t returns integer/*
- Returns the index of the timer
*/function GetTimerData takes timer t returns integer/*
- Returns the custom integer data attached to the timer
*/function SetTimerData takes timer t, integer i returns nothing/*
- Attaches a custom integer data to the timer
*/function IsTimerStocked takes timer t returns boolean/*
- Checks if the timer is free
*/function GetTimerFlag takes timer t returns boolean/*
- Checks if the timer is included in this system's timer stock
*///! endnovjass
globals
/*
Determines the total number of timers on the stock */
private constant integer TIMER_STOCK_SIZE = 8190
/* Determines the delay of timer replacement in case a
timer belonging to the stock is accidentally destroyed
Note that this value should be greater than the time
delay of the handleId recycling which is approximately
0.0050000 ( It's not advised to change this anyway ) */
private constant real REPLACE_DELAY = 0.0050001
endglobals
//================================================================
globals
private timer array T[TIMER_STOCK_SIZE]
private timer tempTimer
private integer START_HANDLE
private integer destroyed
private integer current
private integer pitStop
private integer this
private integer array recycler[TIMER_STOCK_SIZE]
private integer array data[TIMER_STOCK_SIZE]
private boolean dont = false
private boolean array isTimerStocked[TIMER_STOCK_SIZE]
endglobals
static if DEBUG_MODE then
private function Debug takes string msg returns nothing
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "|CFFFFCC00[Timer Indexer]|R : " + msg)
endfunction
endif
function GetTimerId takes timer t returns integer
return GetHandleId(t) - START_HANDLE
endfunction
function GetTimerData takes timer t returns integer
return data[GetTimerId(t)]
endfunction
function SetTimerData takes timer t, integer i returns nothing
set data[GetTimerId(t)] = i
endfunction
function IsTimerStocked takes timer t returns boolean
return isTimerStocked[GetTimerId(t)]
endfunction
function GetTimerFlag takes timer t returns boolean
return GetTimerId(t) > 0 and GetTimerId(t) <= TIMER_STOCK_SIZE
endfunction
function GetTimer takes nothing returns timer
set this = recycler[0]
set recycler[0] = recycler[this]
if isTimerStocked[this] then
set isTimerStocked[this] = false
debug call Debug("Retrieving Timer [" + I2S(this) + "] from stock")
return T[this]
endif
debug call Debug("ERROR: No free timers available, creating a temporary timer.")
return CreateTimer()
endfunction
function GetTimerById takes integer i returns timer
if isTimerStocked[i] then
debug call Debug("Retrieving Timer [" + I2S(i) + "] from stock")
return T[i]
endif
debug if i < 1 or i > TIMER_STOCK_SIZE then
debug call Debug("ERROR: Specified timer ID is out of bounds")
debug else
debug call Debug("ERROR: Timer [" + I2S(i) + "] is not free")
debug endif
return null
endfunction
function GetTimerEx takes integer i returns timer
set tempTimer = GetTimer()
set data[GetTimerId(tempTimer)] = i
return tempTimer
endfunction
function FreeTimer takes timer t returns nothing
local integer i = GetTimerId(t)
if not isTimerStocked[i] and GetTimerFlag(t) then
call TimerStart(t, 0, false, null)
set isTimerStocked[i] = true
set data[i] = 0
set recycler[i] = recycler[0]
set recycler[0] = i
debug call Debug("Releasing Timer [" + I2S(i) + "] back to the stock")
elseif not GetTimerFlag(t) then
call DestroyTimer(t)
debug call Debug("ERROR: Freed timer does not belong to the stack, destroying timer")
debug else
debug call Debug("ERROR: Attempt to double-free Timer [" + I2S(i) + "]")
endif
endfunction
private function Replace takes nothing returns nothing
local integer i = destroyed
set T[i] = CreateTimer()
if GetTimerId(T[i]) == i then
set isTimerStocked[i] = true
debug call Debug("Timer [" + I2S(GetTimerId(T[i])) + "] was replaced")
else
debug call Debug("ERROR: Unable to replace Timer [" + I2S(i) + "]")
set dont = true
call DestroyTimer(T[i])
set dont = false
set T[i] = null
endif
call FreeTimer(GetExpiredTimer())
endfunction
private function OnDestroy takes timer t returns nothing
local integer i = GetTimerId(t)
local trigger trig
if not dont and GetTimerFlag(t) then
set T[i] = null
set isTimerStocked[i] = false
set destroyed = i
call DestroyTimer(null)
call TimerStart(GetTimer(), REPLACE_DELAY, false, function Replace)
debug call Debug("WARNING: Timer [" + I2S(i) + "] got destroyed!")
set trig = null
endif
endfunction
hook DestroyTimer OnDestroy
private function Delegate takes nothing returns nothing
local integer i = current
loop
set i = i + 1
set T[i] = CreateTimer()
set isTimerStocked[i] = true
set recycler[i] = i + 1
if i == TIMER_STOCK_SIZE then
debug call Debug("Total number of timers created: " + I2S(i))
debug call Debug("Timer stock count is complete")
return
endif
exitwhen i == current + pitStop
endloop
set current = i
call Delegate.evaluate()
endfunction
private module M
private static method onInit takes nothing returns nothing
local integer i = 1
if TIMER_STOCK_SIZE <= 8190 then
set pitStop = TIMER_STOCK_SIZE
else
set pitStop = 1000
endif
set recycler[TIMER_STOCK_SIZE] = 0
set recycler[0] = 1
set recycler[1] = 2
set T[i] = CreateTimer()
set START_HANDLE = GetHandleId(T[i]) - 1
set isTimerStocked[i] = true
loop
set i = i + 1
set T[i] = CreateTimer()
set isTimerStocked[i] = true
set recycler[i] = i + 1
exitwhen i == pitStop
endloop
set current = i
if TIMER_STOCK_SIZE > current then
call Delegate.evaluate()
debug else
debug call Debug("Total number of timers created: " + I2S(i))
debug call Debug("Timer stock count is complete")
endif
endmethod
endmodule
private struct S extends array
implement M
endstruct
endlibrary
ChangelogsSpoiler
v1.2
- Added more functionalities such as attaching custom timer data, now the system comprises all but is not limited to the main functionalities of Vexorian's TimerUtils
- Optimized the code especially in the part in updating the timer stack
- Fixed some bugs
v1.1
- Added the possibility for users to configure the timer stock size above 8190
- Some fixes
v1.0
- First Release