9 years
edited 8 years
LoopCode v1.3
This system allows you to register a code that will run every specified timeout. Note that this system only uses one timer for all registered codes. Therefore, codes with periods indivisible by 0.03125 doesn't run with a constant time interval. Although the difference will not exceed 0.03125, you probably don't want it to be that way. But this will not be much of a problem for codes with low frequency period such as those with timeouts greater than 2 seconds since the difference wouldn't be so noticeable.
In short, this works best for codes with timeout divisible by 0.03125 seconds.
Main Script
Sample Script
Changelogs
v1.3
- Fixed a minor error concerning the index of a registered code in the RunLoop not being decremented by 1 when a code is removed from the loop.
v1.2
- Replaced TriggerEvaluate() with .evaluate() through the use of function interface
- Added an option to the configuration whether or not the system will automatically adjust the code timeout in case the entered timeout is lesser than the minimum supported timeout
- Removed the requirement Table. Instead, uses arrays which were made possible through using interface functions as the index.
v1.1
- Fixed the bug regarding the incorrect unregistering and re-registering codes to the loop
- Uses a TableArray instead of two separate tables
v1.0
- Initial release
Feedback will be appreciated.
This system allows you to register a code that will run every specified timeout. Note that this system only uses one timer for all registered codes. Therefore, codes with periods indivisible by 0.03125 doesn't run with a constant time interval. Although the difference will not exceed 0.03125, you probably don't want it to be that way. But this will not be much of a problem for codes with low frequency period such as those with timeouts greater than 2 seconds since the difference wouldn't be so noticeable.
In short, this works best for codes with timeout divisible by 0.03125 seconds.
Main Script
library LoopCode
//! novjass
________________
| |
| Written by AGD |
|________________|
|=====|
| API |
|=====|
function interface LoopCode takes nothing returns nothing/*
- Interface of functions to be registered in the loop
*/function RegisterLoopCode takes LoopCode c, real timeout returns boolean/*
- Registers a code to run every <timeout> seconds and returns a boolean value depending
on the success of the operation
*/function RemoveLoopCode takes LoopCode c returns boolean/*
- Unregisters a code from the loop and returns a boolean value depending
on the success of the operation
*/function SetCodeTimeout takes LoopCode c, real timeout returns boolean/*
- Sets a new loop timeout for a code
*///! endnovjass
//======================================================================================
globals
private constant real TIMEOUT = 0.03125
private constant boolean AUTO_ADJUST = true
endglobals
//======================================================================================
globals
private LoopCode array codes
private timer Timer = CreateTimer()
private integer id = 0
private integer count = 0
private real array codeTimeout
private real array elapsed
private integer array index
private boolean array check
endglobals
//======================================================================================
function interface LoopCode takes nothing returns nothing
static if DEBUG_MODE then
private function Debug takes string msg returns nothing
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "|CFFFFCC00[LoopEvent] :|R" + msg)
endfunction
endif
private function RunLoop takes nothing returns nothing
set id = 0
loop
set id = id + 1
set elapsed[id] = elapsed[id] + TIMEOUT
if elapsed[id] >= codeTimeout[id] then
call codes[id].evaluate()
set elapsed[id] = elapsed[id] - codeTimeout[id]
endif
exitwhen id == count
endloop
endfunction
function RegisterLoopCode takes LoopCode c, real timeout returns boolean
static if AUTO_ADJUST then
if timeout < TIMEOUT then
set timeout = TIMEOUT
debug call Debug("Entered code execution timeout is less than the minimum value (" + R2S(TIMEOUT) + "), auto-adjusting timeout to (" + R2S(TIMEOUT) + ")")
endif
else
if timeout < TIMEOUT then
debug call Debug("ERROR: Entered code execution timeout is less than the minimum value (" + R2S(TIMEOUT) + ")")
return false
endif
endif
if not check[c] then
debug if timeout - (timeout/TIMEOUT)*TIMEOUT > 0.00 then
debug call Debug("WARNING: Entered code timeout is not divisible by " + R2S(TIMEOUT) + ", this code's execution interval will not be even")
debug endif
set count = count + 1
set elapsed[count] = 0.00
set codeTimeout[count] = timeout
set codes[count] = c
set index[c] = count
set check[c] = true
if count == 1 then
call TimerStart(Timer, TIMEOUT, true, function RunLoop)
debug call Debug("There is one code instance registered, starting to run timer")
endif
return true
endif
debug call Debug("ERROR: Attempt to double register a code")
return false
endfunction
function RemoveLoopCode takes LoopCode c returns boolean
local integer i = index[c]
if check[c] then
debug call Debug("Removing a code from the loop")
set check[c] = false
set index[codes[count]] = i
set codes[i] = codes[count]
set codeTimeout[i] = codeTimeout[count]
if id >= i then
set id = id - 1
endif
set count = count - 1
if count == 0 then
call TimerStart(Timer, 0, false, null)
debug call Debug("There are no code instances running, stopping timer")
endif
return true
endif
debug call Debug("ERROR: Attempt to remove a null or an already removed code")
return false
endfunction
function SetCodeTimeout takes LoopCode c, real timeout returns boolean
local integer i = index[c]
if check[c] then
static if AUTO_ADJUST then
if codeTimeout[i] >= TIMEOUT then
set codeTimeout[i] = timeout
else
set codeTimeout[i] = TIMEOUT
debug call Debug("Entered code execution timeout is less than the minimum value (" + R2S(TIMEOUT) + "), auto-adjusting timeout to (" + R2S(TIMEOUT) + ")")
endif
return true
else
if codeTimeout[i] >= TIMEOUT then
set codeTimeout[i] = timeout
return true
endif
debug call Debug("ERROR: Entered code execution timeout is less than the minimum value (" + R2S(TIMEOUT) + ")")
return false
endif
endif
debug call Debug("ERROR: Specified code is not registered")
return false
endfunction
endlibrarySample Script
Spoiler
scope MySpell initializer Init
globals
private constant real TIMEOUT = 0.03125
private integer maxIndex = 0
private real array elapsed
endglobals
private function Loop takes nothing returns nothing
local integer index = 0
loop
set index = index + 1
if elapsed < 10 then
set elapsed[index] = elapsed[index] + TIMEOUT
else
set elapsed[index] = elapsed[maxIndex]
set maxIndex = maxIndex - 1
set index = index - 1
if maxIndex == 0 then
call RemoveLoopCode(LoopCode.Loop)
endif
endif
exitwhen index == maxIndex
endloop
endfunction
private function OnCast takes nothing returns boolean
// Setup spell data and oncast effects
set maxIndex = maxIndex + 1
set elapsed[maxIndex] = 0.00
call RegisterLoopCode(LoopCode.Loop, TIMEOUT)
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, FIlter(function OnCast))
endfunction
endscopeChangelogs
Spoiler
v1.3
- Fixed a minor error concerning the index of a registered code in the RunLoop not being decremented by 1 when a code is removed from the loop.
v1.2
- Replaced TriggerEvaluate() with .evaluate() through the use of function interface
- Added an option to the configuration whether or not the system will automatically adjust the code timeout in case the entered timeout is lesser than the minimum supported timeout
- Removed the requirement Table. Instead, uses arrays which were made possible through using interface functions as the index.
v1.1
- Fixed the bug regarding the incorrect unregistering and re-registering codes to the loop
- Uses a TableArray instead of two separate tables
v1.0
- Initial release
Feedback will be appreciated.