From b235345b2c2a0321441578f3624f2f06467519a4 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 20 Mar 2026 12:11:24 -0700 Subject: [PATCH] feat: add C_Timer.After and C_Timer.NewTicker for Lua addons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement WoW's C_Timer API used by most modern addons: - C_Timer.After(seconds, callback) — fire callback after delay - C_Timer.NewTicker(seconds, callback, iterations) — repeating timer with optional iteration limit and :Cancel() method Implemented in pure Lua using a hidden OnUpdate frame that auto-hides when no timers are pending (zero overhead when idle). Example: C_Timer.After(3, function() print("3 sec later!") end) local ticker = C_Timer.NewTicker(1, function() print("tick") end, 5) --- src/addons/lua_engine.cpp | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/addons/lua_engine.cpp b/src/addons/lua_engine.cpp index 34329462..6ae0a41b 100644 --- a/src/addons/lua_engine.cpp +++ b/src/addons/lua_engine.cpp @@ -691,6 +691,47 @@ void LuaEngine::registerCoreAPI() { // OnUpdate frame tracking table lua_newtable(L_); lua_setglobal(L_, "__WoweeOnUpdateFrames"); + + // C_Timer implementation via Lua (uses OnUpdate internally) + luaL_dostring(L_, + "C_Timer = {}\n" + "local timers = {}\n" + "local timerFrame = CreateFrame('Frame', '__WoweeTimerFrame')\n" + "timerFrame:SetScript('OnUpdate', function(self, elapsed)\n" + " local i = 1\n" + " while i <= #timers do\n" + " timers[i].remaining = timers[i].remaining - elapsed\n" + " if timers[i].remaining <= 0 then\n" + " local cb = timers[i].callback\n" + " table.remove(timers, i)\n" + " cb()\n" + " else\n" + " i = i + 1\n" + " end\n" + " end\n" + " if #timers == 0 then self:Hide() end\n" + "end)\n" + "timerFrame:Hide()\n" + "function C_Timer.After(seconds, callback)\n" + " tinsert(timers, {remaining = seconds, callback = callback})\n" + " timerFrame:Show()\n" + "end\n" + "function C_Timer.NewTicker(seconds, callback, iterations)\n" + " local count = 0\n" + " local maxIter = iterations or -1\n" + " local ticker = {cancelled = false}\n" + " local function tick()\n" + " if ticker.cancelled then return end\n" + " count = count + 1\n" + " callback(ticker)\n" + " if maxIter > 0 and count >= maxIter then return end\n" + " C_Timer.After(seconds, tick)\n" + " end\n" + " C_Timer.After(seconds, tick)\n" + " function ticker:Cancel() self.cancelled = true end\n" + " return ticker\n" + "end\n" + ); } // ---- Event System ----