-
Posted by Jim on Fri, 20 Jun 2008 08:40:52
I can't seem to figure our how to do a timer in Lua, I dont want to use any Ace Addons like candy bar yet because Im not done going thru the book as it is and Ace Addons are a whole differnt animal.
is anyone able to share with me a way to do a countdown timer ?
-
Posted by morlando on Fri, 20 Jun 2008 00:52:48
Chapter 19 has a section on creating a timer :)
-
Posted by jnwhiteh on Fri, 20 Jun 2008 08:40:52
As Matthew said the addon in Chapter 19 uses a simple OnUpdate to simulate a timer, and that's how all of the systems that implement timers actually work. Please feel free to post if you have any questions about it!
-
Posted by jnwhiteh on Wed, 13 Aug 2008 17:11:17
Very nice! It's good to do things like this one your own to figure out exactly how they work. There are a few other time-like implementations out there that use different methods but if it works for you than congratulations! If you're looking for more specific feedback feel free to say something and I'll take a deeper look ;-)
-
Posted by Gararf on Wed, 13 Aug 2008 17:18:04
i'll take this oppertunity to share my timer, the metatable could actually be replaced with an if check in there somewhere, but at the time i was playing with meta tables :P
all my functions are in the GBMFunctions table, so thats about the only thing you have to change, otherwise its a cut and paste job. At the end there i have an example timer which will count to 5 and then stop. to make a new timer you just do: GBMFunctions.NewTimer(name , delay , PayloadFunction , resetvalue), if the reset value is less than the delay then the timer resets and so you have a kind of delayed for loop, in this case the payload function is passed the loop number and the number that the timer appears in the array so that the timer can be stopped . The timer is stopped with GBMFunctions.TimerEnd(i) where i is the second argument passed to the payload function on a repeat. Delay timers stop themselves automatically. the only thing i think could be improved is currently the payload function isnt passed any custom arguments, but i dont really need that so i've not bothered.
Im preety new to programming and im 100% self taught so any criticism / advice etc. is welcomed, here it is:
GBMTimers = {}
local Timermt = {} -- Meta table for data & timers
function Timermt.__index(tbl, key) -- (Prevents timer from breaking most importantly)
if key == "counter" then
tbl[key] = 0
end
return "counter"
end
setmetatable(GBMTimers, Timermt)
GBMTimers[1] = {
Name = "IDLEPROCESS",
delay = 100,
resetvalue = 0.1,
PayloadFunction = "TimerStop",
LoopNo = 0,
counter = 0,
}
function GBMFunctions.NewTimer(name , delay , PayloadFunction , resetvalue)
if not GBMTimerFrame then GBMTimerFrame = CreateFrame("Frame") end
-- Check For a timer with this name already, if it exists then remove it
-- Needed mainly because events sometimes fire multiple times, if they call a timer then they are likely to create an error
for i = 1, #GBMTimers do
if (name == GBMTimers[i]["Name"]) then
table.remove(GBMTimers, i)
end
end
table.insert(GBMTimers , {
["Name"] = name,
["delay"] = delay,
["resetvalue"] = resetvalue,
["PayloadFunction"] = PayloadFunction,
["LoopNo"] = 0,
["counter"] = 0,
})
local function OnUpdate(self, elapsed)
for i = 1, #GBMTimers do
if (type(GBMTimers[i]["counter"]) == 'number') then --ignores the counter if it is a string (because metatable prevents error by returning string instead of nil) counter auto- deletes at delay, but for loops have predetermined start and end values so you cant reduce number of loops.
GBMTimers[i]["counter"] = GBMTimers[i]["counter"]+elapsed
local PayloadFunction = GBMTimers[i]["PayloadFunction"]
local counter = GBMTimers[i]["counter"]
local delay = GBMTimers[i]["delay"]
local resetvalue = GBMTimers[i]["resetvalue"]
local name = GBMTimers[i]["Name"]
-- DEFAULT_CHAT_FRAME:AddMessage(name .. ": " .. counter, 1, 1, 0) -- Super Spam Counter, Use at Own Risk (debugging only)
if (counter >= resetvalue) then
GBMTimers[i]["counter"] = 0
GBMTimers[i]["LoopNo"] = GBMTimers[i]["LoopNo"]+1
if (type(GBMFunctions[PayloadFunction]) == 'function') then
local LoopNo = GBMTimers[i]["LoopNo"]
GBMFunctions[PayloadFunction](LoopNo , i)
else
GBMFunctions.out("Guild Bank Master: No Payload Function For Timer Could Be Found! Please report this error")
end
elseif (counter >= delay) then
if (type(GBMFunctions[PayloadFunction]) == 'function') then
GBMFunctions.TimerEnd(i)
GBMFunctions[PayloadFunction]()
else
GBMFunctions.TimerEnd(i)
end
end
end
end
end
GBMTimerFrame:SetScript("OnUpdate", OnUpdate)
GBMTimerFrame:Show()
end
function GBMFunctions.TimerStop() -- Stops the entire timer process when only the idle timer is running, checks every 5 s
if #GBMTimers == 1 then
GBMTimerFrame:Hide()
end
end
function GBMFunctions.TimerEnd(i) -- ends a timer by position in the timer table, you should never "end" the IDLEPROCESS timer
table.remove(GBMTimers, i)
end
function GBMFunctions.TrialTimer()
GBMFunctions.NewTimer("TrialTimer" , 100 , "TrialTimerStop" , 1)
endfunction GBMFunctions.TrialTimerStop(loopNo, i)
DEFAULT_CHAT_FRAME:AddMessage("Trial Timer has reached loop number: " .. loopNo, 1, 1, 0)
if loopNo >= 5 then
GBMFunctions.TimerEnd(i)
end
end -
Posted by Gararf on Thu, 14 Aug 2008 04:09:44
nahh it was just abit of sharing :) but i have to say its much easier to read with syntax hilighting