From 25b35d52242bbdc22bc0677661536769ca8c47f9 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sun, 22 Mar 2026 17:23:52 -0700 Subject: [PATCH] fix: include GCD in GetSpellCooldown and GetActionCooldown returns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GetSpellCooldown only returned per-spell cooldowns from the spellCooldowns map, ignoring the Global Cooldown. Addons like OmniCC and action bar addons rely on GetSpellCooldown returning GCD timing when no individual spell cooldown is active — this is what drives the cooldown sweep animation on action bar buttons after casting. Now falls back to GCD timing (from getGCDRemaining/getGCDTotal) when the spell has no individual cooldown but the GCD is active. Returns proper (start, duration) values so addons can compute elapsed/remaining. Same fix applied to GetActionCooldown for spell-type action bar slots. --- src/addons/lua_engine.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/addons/lua_engine.cpp b/src/addons/lua_engine.cpp index ab5c92fe..7dc2a9d5 100644 --- a/src/addons/lua_engine.cpp +++ b/src/addons/lua_engine.cpp @@ -1538,19 +1538,32 @@ static int lua_GetSpellCooldown(lua_State* L) { } } float cd = gh->getSpellCooldown(spellId); + // Also check GCD — if spell has no individual cooldown but GCD is active, + // return the GCD timing (this is how WoW handles it) + float gcdRem = gh->getGCDRemaining(); + float gcdTotal = gh->getGCDTotal(); + // WoW returns (start, duration, enabled) where remaining = start + duration - GetTime() - // Compute start = GetTime() - elapsed, duration = total cooldown static auto sStart = std::chrono::steady_clock::now(); double nowSec = std::chrono::duration( std::chrono::steady_clock::now() - sStart).count(); + if (cd > 0.01f) { - lua_pushnumber(L, nowSec); // start (approximate — we don't track exact start) - lua_pushnumber(L, cd); // duration (remaining, used as total for simplicity) + // Spell-specific cooldown (longer than GCD) + double start = nowSec - 0.01; // approximate start as "just now" minus epsilon + lua_pushnumber(L, start); + lua_pushnumber(L, cd); + } else if (gcdRem > 0.01f) { + // GCD is active — return GCD timing + double elapsed = gcdTotal - gcdRem; + double start = nowSec - elapsed; + lua_pushnumber(L, start); + lua_pushnumber(L, gcdTotal); } else { lua_pushnumber(L, 0); // not on cooldown lua_pushnumber(L, 0); } - lua_pushnumber(L, 1); // enabled (always 1 — spell is usable) + lua_pushnumber(L, 1); // enabled return 3; } @@ -3751,6 +3764,18 @@ static int lua_GetActionCooldown(lua_State* L) { lua_pushnumber(L, start); lua_pushnumber(L, action.cooldownTotal); lua_pushnumber(L, 1); + } else if (action.type == game::ActionBarSlot::SPELL && gh->isGCDActive()) { + // No individual cooldown but GCD is active — show GCD sweep + float gcdRem = gh->getGCDRemaining(); + float gcdTotal = gh->getGCDTotal(); + double now = 0; + lua_getglobal(L, "GetTime"); + if (lua_isfunction(L, -1)) { lua_call(L, 0, 1); now = lua_tonumber(L, -1); lua_pop(L, 1); } + else lua_pop(L, 1); + double elapsed = gcdTotal - gcdRem; + lua_pushnumber(L, now - elapsed); + lua_pushnumber(L, gcdTotal); + lua_pushnumber(L, 1); } else { lua_pushnumber(L, 0); lua_pushnumber(L, 0);