From d4df0a3b26102c69fefc5a5ceb0f3e42cf9f0ace Mon Sep 17 00:00:00 2001 From: Brues <5278969+brues-code@users.noreply.github.com> Date: Sun, 21 Jun 2026 02:10:46 -0500 Subject: [PATCH] CancelAura via C_Spell.CancelSpellByID; stop [focus] no-focus warning - CancelAura: cancel matched buffs through ClassicAPI's C_Spell.CancelSpellByID instead of nampower CancelPlayerAuraSpellId and the legacy slot-based CancelPlayerBuff + tooltip-scan path. The buff scan (SuperWoW GetPlayerBuffID / nampower raw GetPlayerAuraDuration + overflow tracking) and the boolean return are preserved, so the ~spell cancel-vs-cast toggle still works. CancelSpellByName isn't usable here because it reports no match. - Focus: GetFocusUnitId no longer warns when no focus is set. In a fallback macro ([@focus] as one alternative) that's a normal state; the clause now silently falls through like any unresolved @unit. Dropped the unused warn parameter and updated both callers. --- Conditionals.lua | 130 ++++++++++++++++------------------------------- Core.lua | 13 ++--- 2 files changed, 50 insertions(+), 93 deletions(-) diff --git a/Conditionals.lua b/Conditionals.lua index a1ef7eb..072c180 100644 --- a/Conditionals.lua +++ b/Conditionals.lua @@ -2013,98 +2013,58 @@ function CleveRoids.GetCurrentShapeshiftIndex() end function CleveRoids.CancelAura(auraName) - local ix = 0 - auraName = string.lower(string.gsub(auraName, "_"," ")) + auraName = string.lower(string.gsub(auraName, "_", " ")) - -- v2.34+ path: cancel by spell ID (works for buff-capped overflow auras too) - local API = CleveRoids.NampowerAPI - if API and API.features.hasCancelPlayerAuraSpellId then - -- First scan visible buffs via GetPlayerBuff - if CleveRoids.hasSuperwow then - -- SuperWoW path: GetPlayerBuffID provides spell ID directly - while true do - local aura_ix = GetPlayerBuff(ix, "HELPFUL") - ix = ix + 1 - if aura_ix == -1 then break end - local bid = GetPlayerBuffID(aura_ix) - bid = (bid < -1) and (bid + 65536) or bid - if string.lower(GetSpellRecField(bid, "name")) == auraName then - _G.CancelPlayerAuraSpellId(bid, 1) - return true - end - end - elseif API.features.hasGetPlayerAuraDuration and _G.GetPlayerAuraDuration then - -- Nampower path: scan buff aura slots 0-31 for spell IDs - for slot = 0, 31 do - local spellId = _G.GetPlayerAuraDuration(slot) - if spellId and spellId > 0 then - local name = GetSpellRecField(spellId, "name") - if name and string.lower(name) == auraName then - _G.CancelPlayerAuraSpellId(spellId, 1) - return true - end - end + -- Find the matching player buff's spell ID, then cancel it via ClassicAPI's + -- C_Spell.CancelSpellByID. SuperWoW exposes buff spell IDs directly; + -- otherwise use Nampower's raw aura-slot read (sees slots the UI filters out). + if CleveRoids.hasSuperwow then + local ix = 0 + while true do + local aura_ix = GetPlayerBuff(ix, "HELPFUL") + ix = ix + 1 + if aura_ix == -1 then break end + local bid = GetPlayerBuffID(aura_ix) + bid = (bid < -1) and (bid + 65536) or bid + if string.lower(GetSpellRecField(bid, "name") or "") == auraName then + C_Spell.CancelSpellByID(bid) + return true end end - - -- Not found in visible buffs - scan all 32 raw aura slots - -- GetPlayerAuraDuration reads unit data fields directly (same 32 slots but bypasses UI filtering) - if API.features.hasGetPlayerAuraDuration and _G.GetPlayerAuraDuration then - for slot = 0, 31 do - local spellId = _G.GetPlayerAuraDuration(slot) - if spellId and spellId > 0 then - local name = GetSpellRecField(spellId, "name") - if name and string.lower(name) == auraName then - _G.CancelPlayerAuraSpellId(spellId, 1) - return true - end - end - end - end - - -- Final fallback: check overflow buff tracking (buffs applied while buff-capped - -- that have NO client aura slot - tracked via AURA_CAST_ON_SELF events) - for spellId, entry in pairs(CleveRoids.OverflowBuffs) do - -- Skip expired overflow entries - local elapsed = GetTime() - (entry.timestamp or 0) - if entry.durationSec and entry.durationSec > 0 and elapsed > entry.durationSec then - CleveRoids.OverflowBuffs[spellId] = nil - else - local name = GetSpellRecField(spellId, "name") - if name and string.lower(name) == auraName then - _G.CancelPlayerAuraSpellId(spellId, 1) - CleveRoids.OverflowBuffs[spellId] = nil - return true - end - end - end - return false end - -- Legacy path for older Nampower versions - while true do - local aura_ix = GetPlayerBuff(ix,"HELPFUL") - ix = ix + 1 - if aura_ix == -1 then break end + -- Nampower raw aura-slot read (sees slots the UI filters out; also the + -- non-SuperWoW path). Runs after the SuperWoW visible scan above. + if _G.GetPlayerAuraDuration then + for slot = 0, 31 do + local spellId = _G.GetPlayerAuraDuration(slot) + if spellId and spellId > 0 then + local name = GetSpellRecField(spellId, "name") + if name and string.lower(name) == auraName then + C_Spell.CancelSpellByID(spellId) + return true + end + end + end + end - if CleveRoids.hasSuperwow then - local bid = GetPlayerBuffID(aura_ix) - bid = (bid < -1) and (bid + 65536) or bid - if string.lower(GetSpellRecField(bid, "name")) == auraName then - CancelPlayerBuff(aura_ix) - return true - end - else - AuraScanTooltip:SetPlayerBuff(aura_ix) - local name = string.lower(getglobal("AuraScanTooltipTextLeft1"):GetText()) - if name == auraName then - CancelPlayerBuff(aura_ix) - break - end - end + -- Overflow buffs: applied while buff-capped, no client aura slot - tracked + -- via AURA_CAST_ON_SELF events. Cancel by spell ID. + for spellId, entry in pairs(CleveRoids.OverflowBuffs) do + local elapsed = GetTime() - (entry.timestamp or 0) + if entry.durationSec and entry.durationSec > 0 and elapsed > entry.durationSec then + CleveRoids.OverflowBuffs[spellId] = nil + else + local name = GetSpellRecField(spellId, "name") + if name and string.lower(name) == auraName then + C_Spell.CancelSpellByID(spellId) + CleveRoids.OverflowBuffs[spellId] = nil + return true + end + end + end - end - return false + return false end function CleveRoids.HasGearEquipped(gearId) diff --git a/Core.lua b/Core.lua index 6a6a7fc..8cd3170 100644 --- a/Core.lua +++ b/Core.lua @@ -1707,9 +1707,9 @@ end -- Prefers pfUI's emulated focus (resolves to a real token like "party2"/"raid5") -- for pfUI users, then falls back to ClassicAPI's native "focus" token (which -- every UnitX function accepts) for everyone else. --- Returns the resolved token or nil if no focus is set. --- warn: if true, prints a chat message when no focus is set. -function CleveRoids.GetFocusUnitId(warn) +-- Returns the resolved token, or nil when no focus is set so @focus clauses +-- silently fall through to the next macro alternative (no warning spam). +function CleveRoids.GetFocusUnitId() if pfUI and pfUI.uf and pfUI.uf.focus and pfUI.uf.focus.label and pfUI.uf.focus.id and UnitExists(pfUI.uf.focus.label .. pfUI.uf.focus.id) then return pfUI.uf.focus.label .. pfUI.uf.focus.id @@ -1718,9 +1718,6 @@ function CleveRoids.GetFocusUnitId(warn) if UnitExists("focus") then return "focus" end - if warn then - DEFAULT_CHAT_FRAME:AddMessage("|cffff6600SuperCleveRoidMacros:|r [focus] used but no focus is set. Use /focus or the FOCUSTARGET keybind.", 1, 0.4, 0) - end return nil end @@ -2518,7 +2515,7 @@ function CleveRoids.DoWithConditionals(msg, hook, fixEmptyTargetFunc, targetBefo if conditionals.target == "focus" or conditionals.target == "focustarget" then local isFocusTarget = conditionals.target == "focustarget" - local focusUnitId = CleveRoids.GetFocusUnitId(true) + local focusUnitId = CleveRoids.GetFocusUnitId() if focusUnitId then -- Use the resolved pfUI unit token directly (avoids changing the player's target) @@ -2897,7 +2894,7 @@ function CleveRoids.DoTarget(msg) if unitTok == "focus" or unitTok == "focustarget" then local isFocusTarget = unitTok == "focustarget" - local fTok = CleveRoids.GetFocusUnitId(true) + local fTok = CleveRoids.GetFocusUnitId() if fTok then unitTok = fTok .. (isFocusTarget and "target" or "") if not UnitExists(unitTok) then unitTok = nil end