- Joined
- Jan 21, 2006
- Messages
- 2,552
I was searching this forum for a timed-effects library (because I use it frequently in my spells, others may too) but there didn't appear to be one. I submitted code for a timed-effects library ages ago, but it was lacking in usefulness. So, centuries later, I am re-submitting this library that I've since updated to gain certain benefits, at the loss of inconsequential accuracy.
Requirements
Pros
Cons
Requirements
- JassNewGen Pack (with most recent version of JassHelper)
Pros
- Only uses a single timer, along with a stack that is updated periodically.
- Very secure (not that this is ever much of an issue), you will not be able to stunt the functionality of this code without changing the code itself. Good use of scope definitions.
- Doesn't require anything but the JassNewGenPack to compile.
- Well it does its job, and there doesn't appear to be anything in the site's data-base.
Cons
- Because it only uses a single timer, you have to sacrifice the dynamic element of using multiple timers and replace it with a static periodic timer. The difference in accuracy between having an exact timer and using only one is unnoticeable.
JASS:
library TimedEffects
globals
//***************
// Config
//
// [refreshAccuracy] defines the maximum time (in seconds) in between a timedeffect's "real" expiration and when
// it is actually destroyed. This is a side-effect of only using one timer to update the stack of effects. It is
// possible to use a linkedlist and use a dynamic expiration, but that ends up costing too much in efficiency.
public constant real refreshAccuracy = 0.05
//
//
endglobals
//*****************
// Timed Effects
//
struct s_timedeffect
private effect p_model = null
// the user has no real need to reference this, because if he/she needs to prematurely destroy the
// effect, he should use the 's_timedeffect.destroy' method.
readonly real timeTotal
readonly real timeRemaining
// the user can reference these (for whatever reason) but he cannot change their values. they are internal components
// but i thought it wasn't any good keeping it from the user for no reason.
private integer p_index
private static thistype array stack
private static integer stackN = 0
private static timer stackRefresh = CreateTimer()
// stackRefresh updates on the interval defined by [refreshAccuracy] in the 'config' declarations
method onDestroy takes nothing returns nothing
set thistype.stackN = thistype.stackN - 1
set thistype.stack[this.p_index] = thistype.stack[thistype.stackN]
set thistype.stack[this.p_index].p_index = this.p_index
// if [thistype.stackN] is 0, then there are no more effects to be updated and we can pause the timer.
if(thistype.stackN==0) then
call PauseTimer(thistype.stackRefresh)
endif
// if the user is destroying the effect else-where, the variable will be null
if(p_model != null) then
call DestroyEffect(this.p_model)
endif
endmethod
static method onRefresh takes nothing returns nothing
local integer i
local thistype fx
set i = thistype.stackN - 1
loop
exitwhen(i < 0)
set fx = thistype.stack[i]
if(fx != 0) then // precaution
set fx.timeRemaining = fx.timeRemaining - refreshAccuracy
if(fx.timeRemaining <= 0.00) then
// when the countdown has reached 0.00, the timed effect must be destroyed
call fx.destroy()
endif
endif
set i = i-1
endloop
endmethod
static method create takes effect e, real duration returns thistype
local thistype fx = thistype.allocate()
set fx.p_model = e
set fx.timeRemaining = duration
set fx.timeTotal = duration
// initially, the timer is not started but we don't want it running unnecessarily. once the first timedeffect
// has been created, we can start the timer. likewise, if there are no more timedeffects left, we pause the timer (onDestroy)
if(thistype.stackN==0) then
call TimerStart(thistype.stackRefresh, refreshAccuracy, true, function thistype.onRefresh)
endif
// add the timed effect to the stack so that they are updated properly.
set fx.p_index = thistype.stackN
set thistype.stack[thistype.stackN] = fx
set thistype.stackN = thistype.stackN+1
return fx
endmethod
endstruct
//
//
endlibrary