Use ClassicAPI for action-bar mapping, spell IDs, and dynamic pfUI icons

GetActionInfo:
- Add ClassicAPI.GetActionInfo wrapper; rewrite GetActionButtonInfo
  (Generic.lua) to use it and resolve names via GetSpellRecField /
  GetItem / GetMacroInfo, replacing the per-slot GameTooltip scan +
  texture heuristic. Powers reactive-ability slot detection.
- Delete the dead SuperWoW-GetActionText copy of GetActionButtonInfo.

Spell IDs in the index:
- IndexSpells now uses ClassicAPI GetSpellInfo(slot, bookType), whose
  10th return is the spellID, so every Spells entry carries .id (one
  call also replaces GetSpellName + GetSpellTexture).

Dynamic pfUI action-button icons (pairs with the pfUI fork change):
- GameTooltip.SetAction hook renders spells via ClassicAPI
  SetSpellByID(spell.id) instead of SetSpell(spellSlot, bookType) +
  manual rank text. Items stay location-based (instance data).
- Drop the redundant GetActionSpellSlot -> GetSpellCooldown cooldown
  shim in the pfUI handler; pfUI now routes through the hooked
  GetActionCooldown when it defers macro scanning to us.
This commit is contained in:
Brues
2026-06-21 00:11:46 -05:00
parent b28f4452b9
commit 73e8938d76
6 changed files with 67 additions and 108 deletions
+12
View File
@@ -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
+8 -47
View File
@@ -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
+2 -13
View File
@@ -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
+6 -18
View File
@@ -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
+23 -30
View File
@@ -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)
+16
View File
@@ -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`.