diff --git a/ClassicAPI.lua b/ClassicAPI.lua index 6d37ef4..a09cf76 100644 --- a/ClassicAPI.lua +++ b/ClassicAPI.lua @@ -106,3 +106,15 @@ end function API.IsPlayerFalling() return IsFalling() end + +-------------------------------------------------------------------------------- +-- Action +-------------------------------------------------------------------------------- + +-- Action descriptor for a 1-based action-bar slot: actionType, id, subType. +-- actionType: "spell" (id = spellID) | "macro" (id = macroSlot) | +-- "item" (id = itemID, or nil for a bag-instance item) +-- nil for an empty slot. +function API.GetActionInfo(slot) + return GetActionInfo(slot) +end diff --git a/Compatibility/pfUI.lua b/Compatibility/pfUI.lua index f71dacd..a79bb82 100644 --- a/Compatibility/pfUI.lua +++ b/Compatibility/pfUI.lua @@ -440,10 +440,15 @@ function Extension.RegisterPfUIActionEventHandler() )) end - -- For slot change events, do a full button update + -- For slot change events, do a full button update so the icon, + -- cooldown, and tooltip refresh through CleveRoids' hooked + -- GetActionTexture / GetActionCooldown / GameTooltip:SetAction. + -- pfUI's ButtonMacroScan defers to us for managed macros (leaves + -- spellslot nil), so its ButtonFullUpdate routes through those hooks + -- and follows the active conditional — no manual cooldown override + -- needed. if event == "ACTIONBAR_SLOT_CHANGED" then - -- Trigger pfUI's button update for this slot - -- Mark the slot for update in pfUI's cache, which will be processed on next OnUpdate + -- Mark the slot for update in pfUI's cache (processed next OnUpdate) if pfUI.bars and pfUI.bars.update then pfUI.bars.update[slot] = true end @@ -453,50 +458,6 @@ function Extension.RegisterPfUIActionEventHandler() pfUI.bars.ButtonFullUpdate(button) end end - - -- COOLDOWN FIX: Always update cooldowns explicitly - -- pfUI's macro scanner caches spell info and doesn't know about - -- CleveRoids' conditional spell changes. Manually update the cooldown - -- using the active spell from CleveRoids. - -- Note: pfUI uses button.cd for cooldown frame (not button.cooldown) - if button and button.cd then - local start, duration, enable - local spellSlot, bookType = CleveRoids.GetActionSpellSlot(slot) - - if spellSlot and bookType then - -- Active spell found - get its cooldown - start, duration, enable = GetSpellCooldown(spellSlot, bookType) - else - -- No active spell - check for item cooldown - local actions = CleveRoids.GetAction(slot) - local actionToCheck = actions and (actions.active or actions.tooltip) - if actionToCheck and actionToCheck.item then - local item = actionToCheck.item - if item.bagID and item.slot then - start, duration, enable = GetContainerItemCooldown(item.bagID, item.slot) - elseif item.inventoryID then - start, duration, enable = GetInventoryItemCooldown("player", item.inventoryID) - end - elseif actionToCheck then - -- Check for equipment slot (e.g., trinket) - local slotId = tonumber(actionToCheck.action) - if slotId and slotId >= 1 and slotId <= 19 then - start, duration, enable = GetInventoryItemCooldown("player", slotId) - end - end - - -- Fallback: use the hooked GetActionCooldown for non-CleveRoids actions - if not start then - start, duration, enable = GetActionCooldown(slot) - end - end - - -- Apply cooldown if we have valid data - -- Ensure enable is at least 1 (0 can hide the cooldown) - if start and duration then - CooldownFrame_SetTimer(button.cd, start, duration, (enable and enable > 0) and enable or 1) - end - end end) Extension.actionHandlerRegistered = true diff --git a/Conditionals.lua b/Conditionals.lua index 7db476d..c3532e1 100644 --- a/Conditionals.lua +++ b/Conditionals.lua @@ -5108,19 +5108,8 @@ function CleveRoids.IsReactive(name) return CleveRoids.reactiveSpells[spellName] ~= nil end -function CleveRoids.GetActionButtonInfo(slot) - local macroName, actionType, id = GetActionText(slot) - if actionType == "MACRO" then - return actionType, id, macroName - elseif actionType == "SPELL" and id then - local spellName = GetSpellRecField(id, "name") - local rank = GetSpellRecField(id, "rank") - return actionType, id, spellName, rank - elseif actionType == "ITEM" and id then - local item = CleveRoids.GetItem(id) - return actionType, id, (item and item.name), (item and item.id) - end -end +-- NOTE: CleveRoids.GetActionButtonInfo is defined in Extensions/Tooltip/Generic.lua +-- (ClassicAPI GetActionInfo-based) and loads after this file. function CleveRoids.IsReactiveUsable(spellName) -- For Overpower, Revenge, and Riposte: ONLY use combat log tracking diff --git a/Core.lua b/Core.lua index 155d7a0..26186f6 100644 --- a/Core.lua +++ b/Core.lua @@ -4366,15 +4366,10 @@ function GameTooltip.SetAction(self, slot) -- End new logic local current_spell_data = CleveRoids.GetSpell(action_name) - if current_spell_data then - GameTooltip:SetSpell(current_spell_data.spellSlot, current_spell_data.bookType) - local rank_info = current_spell_data.rank or (current_spell_data.highest and current_spell_data.highest.rank) - if rank_info and rank_info ~= "" then - GameTooltipTextRight1:SetText("|cff808080" .. rank_info .. "|r") - else - GameTooltipTextRight1:SetText("") - end - GameTooltipTextRight1:Show() + if current_spell_data and current_spell_data.id then + -- ClassicAPI: render by spellID (rank included) instead of routing + -- through the spellbook slot via SetSpell(spellSlot, bookType). + GameTooltip:SetSpellByID(current_spell_data.id) GameTooltip:Show() return end @@ -4399,15 +4394,8 @@ function GameTooltip.SetAction(self, slot) local nested_action_name = nested_action_info.action current_spell_data = CleveRoids.GetSpell(nested_action_name) - if current_spell_data then - GameTooltip:SetSpell(current_spell_data.spellSlot, current_spell_data.bookType) - local rank_info = current_spell_data.rank or (current_spell_data.highest and current_spell_data.highest.rank) - if rank_info and rank_info ~= "" then - GameTooltipTextRight1:SetText("|cff808080" .. rank_info .. "|r") - else - GameTooltipTextRight1:SetText("") - end - GameTooltipTextRight1:Show() + if current_spell_data and current_spell_data.id then + GameTooltip:SetSpellByID(current_spell_data.id) GameTooltip:Show() return end diff --git a/Extensions/Tooltip/Generic.lua b/Extensions/Tooltip/Generic.lua index cb1d486..e090a96 100644 --- a/Extensions/Tooltip/Generic.lua +++ b/Extensions/Tooltip/Generic.lua @@ -14,8 +14,7 @@ local GetInventoryItemLink = GetInventoryItemLink local GetInventoryItemTexture = GetInventoryItemTexture local GetInventoryItemCount = GetInventoryItemCount local GetItemInfo = GetItemInfo -local GetSpellName = GetSpellName -local GetSpellTexture = GetSpellTexture +local GetSpellInfo = GetSpellInfo local tonumber = tonumber local type = type local pairs = pairs @@ -45,7 +44,10 @@ function CleveRoids.IndexSpells() while true do i = i + 1 - local spellName, spellRank = GetSpellName(i, bookType) + -- ClassicAPI GetSpellInfo(slot, bookType) returns the spellID as the + -- 10th value, giving us slot -> spellID natively (plus name/rank/icon + -- in one call, replacing GetSpellName + GetSpellTexture). + local spellName, spellRank, texture, _, _, _, _, _, _, spellId = GetSpellInfo(i, bookType) if not spellName then i = 0 book = book + 1 @@ -61,10 +63,10 @@ function CleveRoids.IndexSpells() if (not reagent or reagent == "") and CleveRoids.ReagentBySpell then reagent = CleveRoids.ReagentBySpell[spellName] end - local texture = GetSpellTexture(i, bookType) if not spells[bookType][spellName] then spells[bookType][spellName] = { spellSlot = i, + id = spellId, name = spellName, bookType = bookType, texture = texture, @@ -75,6 +77,7 @@ function CleveRoids.IndexSpells() if spellRank and not spells[bookType][spellName][spellRank] then spells[bookType][spellName][spellRank] = { spellSlot = i, + id = spellId, name = spellName, rank = spellRank, bookType = bookType, @@ -371,34 +374,24 @@ function CleveRoids.ClearSlot(slots, slot) slots[slot] = nil end --- Local helper for 1.12.1: safely get action button info via tooltip +-- Map a 1-based action slot to (actionType, id, name, rank) via ClassicAPI's +-- GetActionInfo, resolving spell/item/macro names from the id. actionType is +-- "SPELL" | "ITEM" | "MACRO" to match existing callers; returns nil for an +-- empty slot. Bag-instance items (no itemID from GetActionInfo) yield no name. function CleveRoids.GetActionButtonInfo(slot) - if not CleveRoidsActionTooltip then - CreateFrame("GameTooltip", "CleveRoidsActionTooltip", UIParent, "GameTooltipTemplate") + local actionType, id = CleveRoids.ClassicAPI.GetActionInfo(slot) + if not actionType then return end + + if actionType == "spell" and id then + local rank = GetSpellRecField(id, "rank") + if rank == "" then rank = nil end + return "SPELL", id, GetSpellRecField(id, "name"), rank + elseif actionType == "item" and id then + local item = CleveRoids.GetItem(id) + return "ITEM", id, (item and item.name) + elseif actionType == "macro" and id then + return "MACRO", id, GetMacroInfo(id) end - - local tooltip = CleveRoidsActionTooltip - tooltip:SetOwner(UIParent, "ANCHOR_NONE") - tooltip:ClearLines() - tooltip:SetAction(slot) - - local name, rank - local text = _G["CleveRoidsActionTooltipTextLeft1"] - if text then name = text:GetText() end - local text2 = _G["CleveRoidsActionTooltipTextLeft2"] - if text2 then - local maybeRank = text2:GetText() - -- Rank lines usually start with "Rank" - if maybeRank and string.find(maybeRank, "Rank") then - rank = maybeRank - end - end - - -- Determine if it's an item or spell based on texture (heuristic) - local tex = GetActionTexture(slot) - local actionType = tex and "SPELL" or "ITEM" - - return actionType, tex, name, rank end function CleveRoids.IndexActionSlot(slot) diff --git a/docs/CLASSICAPI-TODO.md b/docs/CLASSICAPI-TODO.md index 974afbe..901e5ca 100644 --- a/docs/CLASSICAPI-TODO.md +++ b/docs/CLASSICAPI-TODO.md @@ -82,6 +82,22 @@ API references are line numbers into `C:\Git\ClassicAPI\docs\API.md`. ## Tier 2 — replace custom scanning / extra deps +### `GetActionInfo(slot)` — action-slot → spell/macro/item mapping +- **API:** `API.md:489` — returns `actionType, id, subType`. +- **DONE:** `ClassicAPI.GetActionInfo` wrapper added; `GetActionButtonInfo` + (`Extensions/Tooltip/Generic.lua`) rewritten to use it and resolve names via + `GetSpellRecField` / `GetItem` / `GetMacroInfo`, replacing the per-slot + GameTooltip scan + texture heuristic (which couldn't tell spell from item and + never recognized macros). Powers reactive-ability slot detection + (`IndexActionSlot`). Deleted the dead SuperWoW-`GetActionText` copy of + `GetActionButtonInfo` in `Conditionals.lua`. +- **Known limitation:** GetActionInfo returns `id = nil` for bag-instance items + (items dragged from bags rather than placed by itemID), so those slots get no + name. The consumers (`actionSlots` for `/startattack`·`/shoot`·auto-shot + proxies, reactive spells) only need spells, so this is acceptable. +- **Follow-up (optional):** migrate the remaining `GetActionText` macro-slot + detection in `Core.lua` / `ComboPointTracker.lua` to `GetActionInfo` too. + ### 4. `C_Spell.*` / `GetSpellInfo(spellID)` - **API:** `API.md:6649+` — `GetSpellCooldown`, `IsUsableSpell`, `IsSpellKnown`, `SpellHasRange`, `GetSpellSchool`, `FindSpellBookSlotByID`.