-
Notifications
You must be signed in to change notification settings - Fork 4
Async Logic
There are a couple known approaches that are used to implement time based logic, each with specific advantages
A control that is used to trigger a task on a set interval.
function SETUP_TIMER(frame)
local timer = frame:CreateOrGetControl("timer", "addontimer", 10, 10);
AUTO_CAST(timer);
timer:Stop();
timer:SetUpdateScript("AUTOAWAKENING_ON_AUTO_ATTEMPT_TIMER_TICK");
timer:Start(1);
end
function MY_FUNCTION(frame)
print("HI");
end- Very straightforward to setup and use. Call the
Stop()method of the timer to stop it.
- It is a control object, meaning that we have to go through the regular boilerplate of setting up a ui control.
- Timer is paused from ticking when parent frame visibility becomes
false(although there is a workaround)
- The first invocation always happen immediately after
Start()
A system message that is broadcasted almost on every frame. Thus if you need a process that needs to constantly check for a certain condition, and if you need a very fine grain frequency, you can register to the FPS_UPDATE message. Within the game client, this message is used to update FPS text. But many addons use it as a good-for-almost-everything hook.
function MYADDON_ON_INIT(addon, frame)
addon:RegisterMsg('FPS_UPDATE', 'ON_FPS_UPDATE')
end
function ON_FPS_UPDATE(frame, msg, argStr, argNum)
... do stuff
end- Useful if you need to constantly update some permanent UI element
- Hook always runs even if frame is not visible. Thus it can be a resource hog if not used properly. I would recommend using
timerif possible.
Used to invoke a function on a delay in seconds, can be as low as 0.01 second. The function is invoked only once.
function MY_FUNC()
ReserveScript("MY_OTHER_FUNCTION()", 2);
end
function MY_OTHER_FUNCTION()
print("I'm invoked after a 2 second delay");
end- Since we do not have mechanisms to sleep or wait without completely freezing the game, if we have some script that we want to run after an
namount of seconds,ReserveScriptis the best mechanisms. - Unlike
timerwhich always initially have an invocation immediately on callingtimer:Start(),ReserveScript()always invokes the script after the provided delay. - Useful when trying to prevent race conditions by delaying an operation
0.01seconds later
- When you want to chain multiple
ReserveScriptthrough recursion, improper recursion may cause stack overflows. - Each
ReserveScriptcreates a new background thread (or at least that's what it feels like). Thus, an uncontrolled usage ofReserveScriptcan spawn unwanted amount of threads, and crash the game. - Let's say you want to call
ReserveScriptwhen a user clicks on a button, or presses a certain key. You might want to use a higher scopeboolean"isWaiting" variable accompanied with a conditional statement so that you don't invoke reserve a million scripts if the user decides to mash on the button.
Similar to a timer, but without the timer control.
func START_UPDATE(frame)
frame:RunUpdateScript("ON_TICK", 1);
end
function ON_TICK(frame)
if (condition) then
return 1;
end
return 0;
endRunUpdateScript works almost exactly like how a timer works. However, the tick only continues as long as the UpdateScript continues to return 1. If anything other than 1 is returned (or if nothing is returned), the UpdateScript stops running.
You can also manually stop the script through StopUpdateScript(funcName)
- No need to create a control
- Because the timer keeps ticking as long as
1is returned, if you know the condition of when you want to continue running or stopping the timer,RunUpdateScript()can be much easier to use than thetimercontrol. - Same other advantages as
timer
- Same disadvantages as
timer - The UpdateScript is paused from ticking when parent frame visibility becomes
false(you can use same workaround as that oftimercontrol)