mirror of
https://github.com/brues-code/SuperCleveRoidMacros.git
synced 2026-09-16 03:38:00 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64e3f93042 | ||
|
|
0c86ed67e9 | ||
|
|
60c1b7f235 | ||
|
|
8c10353567 | ||
|
|
fcd206756d | ||
|
|
8d86389a03 | ||
|
|
8c85ce572a |
+5
-115
@@ -197,102 +197,6 @@ local function IsSharedDebuffByIdOrName(lib, spellID, debuffName)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- PERFORMANCE: Equipment cache for HasGearEquipped (avoids 19-slot scan per call)
|
|
||||||
-- Invalidated on UNIT_INVENTORY_CHANGED via CleveRoids.InvalidateEquipmentCache()
|
|
||||||
-- Enhanced with Nampower v2.18+ GetEquippedItems when available
|
|
||||||
local _equippedItemIDs = {} -- [slot] = itemID (number)
|
|
||||||
local _equippedItemNames = {} -- [slot] = itemName (lowercase string)
|
|
||||||
local _equipmentCacheValid = false
|
|
||||||
|
|
||||||
-- Track if we've warned about GetEquippedItems errors (warn once per session)
|
|
||||||
local _getEquippedItemsErrorWarned = false
|
|
||||||
|
|
||||||
local function BuildEquipmentCache()
|
|
||||||
if _equipmentCacheValid then return end
|
|
||||||
_equipmentCacheValid = true
|
|
||||||
|
|
||||||
-- Clear old data
|
|
||||||
for i = 1, 19 do
|
|
||||||
_equippedItemIDs[i] = nil
|
|
||||||
_equippedItemNames[i] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local string_find = string.find
|
|
||||||
local string_lower = string.lower
|
|
||||||
|
|
||||||
-- Try Nampower GetEquippedItems for faster enumeration
|
|
||||||
-- Requires v2.22+ because earlier versions (e.g., v2.19.1) have internal bug
|
|
||||||
local API = CleveRoids.NampowerAPI
|
|
||||||
local hasValidNampower = API and API.HasMinimumVersion and API.HasMinimumVersion(2, 22, 0)
|
|
||||||
|
|
||||||
if hasValidNampower and GetEquippedItems then
|
|
||||||
-- Use pcall to catch any internal Nampower errors and fall back gracefully
|
|
||||||
local success, result = pcall(GetEquippedItems, "player")
|
|
||||||
|
|
||||||
if not success then
|
|
||||||
-- Log the error once per session for debugging
|
|
||||||
if not _getEquippedItemsErrorWarned then
|
|
||||||
_getEquippedItemsErrorWarned = true
|
|
||||||
local errMsg = tostring(result)
|
|
||||||
if CleveRoids.Print then
|
|
||||||
CleveRoids.Print("|cffff6600Warning:|r GetEquippedItems failed: " .. errMsg)
|
|
||||||
CleveRoids.Print("Using fallback equipment detection. Consider updating Nampower.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Fall through to manual enumeration
|
|
||||||
elseif result and type(result) == "table" then
|
|
||||||
local usedNampower = false
|
|
||||||
for nampowerSlot, itemInfo in pairs(result) do
|
|
||||||
-- Nampower uses 0-indexed slots, WoW API uses 1-indexed
|
|
||||||
-- tonumber() handles both string and numeric keys from different Nampower versions
|
|
||||||
-- Skip non-numeric keys (metadata fields, etc.)
|
|
||||||
local slotNum = tonumber(nampowerSlot)
|
|
||||||
if slotNum and type(itemInfo) == "table" and itemInfo.itemId then
|
|
||||||
local slot = slotNum + 1
|
|
||||||
-- itemInfo must be a table to access .itemId (userdata from some Nampower versions is not indexable)
|
|
||||||
if slot >= 1 and slot <= 19 then
|
|
||||||
_equippedItemIDs[slot] = itemInfo.itemId
|
|
||||||
usedNampower = true
|
|
||||||
|
|
||||||
-- Get item name via Nampower API or GetItemInfo
|
|
||||||
local itemName = API and API.GetItemName and API.GetItemName(itemInfo.itemId)
|
|
||||||
if not itemName then
|
|
||||||
itemName = GetItemInfo(itemInfo.itemId)
|
|
||||||
end
|
|
||||||
if itemName then
|
|
||||||
_equippedItemNames[slot] = string_lower(itemName)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if usedNampower then
|
|
||||||
return -- Done with Nampower path
|
|
||||||
end
|
|
||||||
-- Fall through to manual enumeration if Nampower returned userdata items
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Fallback: manual slot enumeration via ClassicAPI (id + decorated name),
|
|
||||||
-- no link string built. C_Item.GetItemName carries random-suffix decoration
|
|
||||||
-- and falls back to the base name internally, so it replaces the old
|
|
||||||
-- bracket-name / GetItemInfo two-step in a single call.
|
|
||||||
for slot = 1, 19 do
|
|
||||||
local id = GetInventoryItemID("player", slot)
|
|
||||||
if id then
|
|
||||||
_equippedItemIDs[slot] = id
|
|
||||||
local name = C_Item.GetItemName({ equipmentSlotIndex = slot })
|
|
||||||
if name then
|
|
||||||
_equippedItemNames[slot] = string_lower(name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Invalidate equipment cache (call on UNIT_INVENTORY_CHANGED)
|
|
||||||
function CleveRoids.InvalidateEquipmentCache()
|
|
||||||
_equipmentCacheValid = false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
-- PERFORMANCE: Unified item location lookup using CleveRoids.Items cache
|
-- PERFORMANCE: Unified item location lookup using CleveRoids.Items cache
|
||||||
-- Returns: { type="inventory"|"bag", inventoryID=N } or { type="bag", bag=N, slot=N }
|
-- Returns: { type="inventory"|"bag", inventoryID=N } or { type="bag", bag=N, slot=N }
|
||||||
@@ -2060,26 +1964,12 @@ function CleveRoids.CancelAura(auraName)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ClassicAPI's C_Item.IsEquippedItem walks the 19 equipment slots natively and
|
||||||
|
-- short-circuits on the first match, so it replaces the old Lua-side equipment
|
||||||
|
-- cache entirely -- no per-call scan, no invalidation. Accepts itemID, item
|
||||||
|
-- link, or (case-insensitive, decorated) name.
|
||||||
function CleveRoids.HasGearEquipped(gearId)
|
function CleveRoids.HasGearEquipped(gearId)
|
||||||
if not gearId then return false end
|
return (gearId and C_Item.IsEquippedItem(gearId)) or false
|
||||||
|
|
||||||
-- PERFORMANCE: Build/refresh equipment cache if needed
|
|
||||||
BuildEquipmentCache()
|
|
||||||
|
|
||||||
-- Handle both numeric IDs and string IDs like "5196"
|
|
||||||
local wantId = tonumber(gearId)
|
|
||||||
local wantName = (type(gearId) == "string" and not wantId) and string.lower(gearId) or nil
|
|
||||||
|
|
||||||
-- PERFORMANCE: Use cached data instead of scanning all slots
|
|
||||||
for slot = 1, 19 do
|
|
||||||
if wantId and _equippedItemIDs[slot] == wantId then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
if wantName and _equippedItemNames[slot] == wantName then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3974,25 +3974,6 @@ function CleveRoids.OnUpdate(self)
|
|||||||
CR.EnsureSendChatMessageHook()
|
CR.EnsureSendChatMessageHook()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Process deferred equipment index updates (for throttled UNIT_INVENTORY_CHANGED)
|
|
||||||
-- PERFORMANCE: Skip check entirely if no pending update
|
|
||||||
local pendingTime = CR.equipIndexPendingTime
|
|
||||||
if pendingTime and not UnitAffectingCombat("player") then
|
|
||||||
if (time - (CR.lastEquipIndexTime or 0)) >= 0.2 then
|
|
||||||
CR.lastEquipIndexTime = time
|
|
||||||
CR.equipIndexPendingTime = nil
|
|
||||||
CR.lastItemIndexTime = time
|
|
||||||
CR.IndexItems()
|
|
||||||
CR.Actions = {}
|
|
||||||
CR.Macros = {}
|
|
||||||
CR.IndexActionBars()
|
|
||||||
|
|
||||||
if CRM.realtime == 0 then
|
|
||||||
CR.QueueActionUpdate()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- PERFORMANCE: Check for expired reactive procs only if we have any
|
-- PERFORMANCE: Check for expired reactive procs only if we have any
|
||||||
-- Use statically allocated removal buffer to avoid per-frame allocation
|
-- Use statically allocated removal buffer to avoid per-frame allocation
|
||||||
local reactiveProcs = CR.reactiveProcs
|
local reactiveProcs = CR.reactiveProcs
|
||||||
@@ -5740,31 +5721,21 @@ function CleveRoids.Frame:BAG_UPDATE_DELAYED()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function CleveRoids.Frame:PLAYER_EQUIPMENT_CHANGED()
|
function CleveRoids.Frame:PLAYER_EQUIPMENT_CHANGED()
|
||||||
-- PERFORMANCE: Invalidate equipment cache for HasGearEquipped
|
-- arg1 = inventory slot that changed, arg2 = hasCurrent (slot now holds an item)
|
||||||
if CleveRoids.InvalidateEquipmentCache then
|
local slot, hasCurrent = arg1, arg2
|
||||||
CleveRoids.InvalidateEquipmentCache()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- In combat: Skip ALL processing - EquipBagItem already handles cache invalidation
|
-- In combat: skip the slot reindex to avoid lag during rapid gear swapping.
|
||||||
-- This eliminates lag from IndexEquippedItems during rapid gear swapping
|
-- [equipped] reads live engine state (C_Item.IsEquippedItem) so it stays
|
||||||
|
-- correct regardless; the Items table self-heals on the next BAG_UPDATE.
|
||||||
if UnitAffectingCombat("player") then
|
if UnitAffectingCombat("player") then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Out of combat: Full indexing with throttle
|
-- Out of combat: reindex only the one slot that changed (the bag side of any
|
||||||
local now = GetTime()
|
-- swap is covered by BAG_UPDATE_DELAYED). No action-bar rebuild is needed -
|
||||||
if (now - (CleveRoids.lastEquipIndexTime or 0)) < 0.2 then
|
-- gear swaps don't change what's on the bars; QueueActionUpdate re-evaluates
|
||||||
CleveRoids.equipIndexPendingTime = now
|
-- [equipped:...] icons/conditionals.
|
||||||
return
|
CleveRoids.IndexEquipSlot(slot, hasCurrent)
|
||||||
end
|
|
||||||
|
|
||||||
CleveRoids.lastEquipIndexTime = now
|
|
||||||
CleveRoids.equipIndexPendingTime = nil
|
|
||||||
CleveRoids.lastItemIndexTime = now
|
|
||||||
CleveRoids.IndexItems()
|
|
||||||
CleveRoids.Actions = {}
|
|
||||||
CleveRoids.Macros = {}
|
|
||||||
CleveRoids.IndexActionBars()
|
|
||||||
|
|
||||||
if CleveRoidMacros.realtime == 0 then
|
if CleveRoidMacros.realtime == 0 then
|
||||||
CleveRoids.QueueActionUpdate()
|
CleveRoids.QueueActionUpdate()
|
||||||
@@ -5930,11 +5901,9 @@ function CleveRoids.Frame:SPELL_QUEUE_EVENT()
|
|||||||
queueType = eventCode,
|
queueType = eventCode,
|
||||||
queueTime = GetTime()
|
queueTime = GetTime()
|
||||||
}
|
}
|
||||||
if GetSpellRecField then
|
local name = C_Spell.GetSpellName(spellId)
|
||||||
local name = C_Spell.GetSpellName(spellId)
|
if name then
|
||||||
if name then
|
CleveRoids.queuedSpell.spellName = name
|
||||||
CleveRoids.queuedSpell.spellName = name
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
-- BUGFIX: Update casting state when spell is queued (for [casting] conditional)
|
-- BUGFIX: Update casting state when spell is queued (for [casting] conditional)
|
||||||
if CleveRoids.UpdateCastingState then
|
if CleveRoids.UpdateCastingState then
|
||||||
@@ -5971,11 +5940,9 @@ function CleveRoids.Frame:SPELL_CAST_EVENT()
|
|||||||
targetGuid = targetGuid,
|
targetGuid = targetGuid,
|
||||||
timestamp = GetTime()
|
timestamp = GetTime()
|
||||||
}
|
}
|
||||||
if GetSpellRecField then
|
local name = C_Spell.GetSpellName(spellId)
|
||||||
local name = C_Spell.GetSpellName(spellId)
|
if name then
|
||||||
if name then
|
CleveRoids.lastCastSpell.spellName = name
|
||||||
CleveRoids.lastCastSpell.spellName = name
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Track pending cast for SPELL_GO correlation (reactive ability detection)
|
-- Track pending cast for SPELL_GO correlation (reactive ability detection)
|
||||||
|
|||||||
+251
-14
@@ -2,18 +2,15 @@
|
|||||||
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
|
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
|
||||||
License: MIT License
|
License: MIT License
|
||||||
|
|
||||||
pfUI integration. pfUI's own unitframes now set the native mouseover unit
|
Fixes pfUI mouseover issues by:
|
||||||
(Nampower SetMouseoverUnit, via pfUI.uf.OnEnter bound in pfUI.uf:EnableScripts
|
- Using a unique source key per pfUI frame (e.g., "pfui:party3", "pfui:raid7")
|
||||||
on every unitframe), so [@mouseover]/[mouseover] resolve against pfUI frames
|
- Pairing Set/Clear with the same per-frame key
|
||||||
through the native "mouseover" token -- every consumer checks UnitExists(
|
- Resolving a real UnitID when .unit isn't set
|
||||||
"mouseover") before the CleveRoids.mouseoverUnit fallback, so no per-frame
|
- Properly hooking party group[0] (your own party slot) with a safe closure and defaulting to "player"
|
||||||
hooking is needed here anymore. What remains is the two things pfUI doesn't
|
|
||||||
cover:
|
|
||||||
- Raid-marker rows: NOT unitframes (never go through EnableScripts), so pfUI
|
|
||||||
sets no mouseover for them. Hooked so hovering registers "mark1".."mark8"
|
|
||||||
via CleveRoids.mouseoverUnit.
|
|
||||||
- /pfcast: wrapped so its argument runs through CleveRoids conditionals.
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
if pfPlayer and pfPlayer.GetAttribute and pfPlayer:GetAttribute('unit') == 'player' then return end
|
||||||
|
|
||||||
local _G = _G or getfenv(0)
|
local _G = _G or getfenv(0)
|
||||||
local CleveRoids = _G.CleveRoids or {}
|
local CleveRoids = _G.CleveRoids or {}
|
||||||
|
|
||||||
@@ -101,11 +98,241 @@ local function PfClear(frame)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- PLAYER
|
||||||
|
function Extension.RegisterPlayerScripts()
|
||||||
|
if not pfUI or not pfUI.uf or not pfUI.uf.player then return end
|
||||||
|
local frame = pfUI.uf.player
|
||||||
|
local onEnterFunc = frame:GetScript("OnEnter")
|
||||||
|
local onLeaveFunc = frame:GetScript("OnLeave")
|
||||||
|
|
||||||
|
frame:SetScript("OnEnter", function()
|
||||||
|
PfSet(this, "player")
|
||||||
|
if onEnterFunc then onEnterFunc(this) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
frame:SetScript("OnLeave", function()
|
||||||
|
PfClear(this)
|
||||||
|
if onLeaveFunc then onLeaveFunc(this) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TARGET
|
||||||
|
function Extension.RegisterTargetScripts()
|
||||||
|
if not pfUI or not pfUI.uf or not pfUI.uf.target then return end
|
||||||
|
local frame = pfUI.uf.target
|
||||||
|
local onEnterFunc = frame:GetScript("OnEnter")
|
||||||
|
local onLeaveFunc = frame:GetScript("OnLeave")
|
||||||
|
|
||||||
|
frame:SetScript("OnEnter", function()
|
||||||
|
PfSet(this, "target")
|
||||||
|
if onEnterFunc then onEnterFunc(this) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
frame:SetScript("OnLeave", function()
|
||||||
|
PfClear(this)
|
||||||
|
if onLeaveFunc then onLeaveFunc(this) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TARGETTARGET
|
||||||
|
function Extension.RegisterTargetTargetScripts()
|
||||||
|
if not pfUI or not pfUI.uf or not pfUI.uf.targettarget then return end
|
||||||
|
local frame = pfUI.uf.targettarget
|
||||||
|
local onEnterFunc = frame:GetScript("OnEnter")
|
||||||
|
local onLeaveFunc = frame:GetScript("OnLeave")
|
||||||
|
|
||||||
|
frame:SetScript("OnEnter", function()
|
||||||
|
PfSet(this, "targettarget")
|
||||||
|
if onEnterFunc then onEnterFunc(this) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
frame:SetScript("OnLeave", function()
|
||||||
|
PfClear(this)
|
||||||
|
if onLeaveFunc then onLeaveFunc(this) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- PARTY (pfUI.uf.group[0..4]) -- include 0 to cover your own party slot
|
||||||
|
function Extension.RegisterPartyScripts()
|
||||||
|
if not pfUI or not pfUI.uf or not pfUI.uf.group then return end
|
||||||
|
|
||||||
|
local i
|
||||||
|
for i = 0, 4 do
|
||||||
|
local frame = pfUI.uf.group[i]
|
||||||
|
if frame then
|
||||||
|
-- bind loop index for closures (Vanilla-safe)
|
||||||
|
local idx = i
|
||||||
|
local onEnterFunc = frame:GetScript("OnEnter")
|
||||||
|
local onLeaveFunc = frame:GetScript("OnLeave")
|
||||||
|
|
||||||
|
frame:SetScript("OnEnter", function()
|
||||||
|
-- For group[0] (your own party frame), default to "player"
|
||||||
|
local defaultUnit = (idx == 0) and "player" or nil
|
||||||
|
PfSet(this, defaultUnit)
|
||||||
|
if onEnterFunc then onEnterFunc(this) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
frame:SetScript("OnLeave", function()
|
||||||
|
PfClear(this)
|
||||||
|
if onLeaveFunc then onLeaveFunc(this) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- RAID (pfUI.uf.raid[1..40])
|
||||||
|
function Extension.RegisterRaidScripts()
|
||||||
|
if not pfUI or not pfUI.uf or not pfUI.uf.raid then return end
|
||||||
|
|
||||||
|
local i
|
||||||
|
for i = 1, 40 do
|
||||||
|
local frame = pfUI.uf.raid[i]
|
||||||
|
if frame then
|
||||||
|
local onEnterFunc = frame:GetScript("OnEnter")
|
||||||
|
local onLeaveFunc = frame:GetScript("OnLeave")
|
||||||
|
|
||||||
|
frame:SetScript("OnEnter", function()
|
||||||
|
PfSet(this)
|
||||||
|
if onEnterFunc then onEnterFunc(this) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
frame:SetScript("OnLeave", function()
|
||||||
|
PfClear(this)
|
||||||
|
if onLeaveFunc then onLeaveFunc(this) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- FOCUS
|
||||||
|
function Extension.RegisterFocusScripts()
|
||||||
|
if not pfUI or not pfUI.uf or not pfUI.uf.focus then return end
|
||||||
|
local frame = pfUI.uf.focus
|
||||||
|
local onEnterFunc = frame:GetScript("OnEnter")
|
||||||
|
local onLeaveFunc = frame:GetScript("OnLeave")
|
||||||
|
|
||||||
|
frame:SetScript("OnEnter", function()
|
||||||
|
PfSet(this) -- ResolvePfUnit handles focus emulation
|
||||||
|
if onEnterFunc then onEnterFunc(this) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
frame:SetScript("OnLeave", function()
|
||||||
|
PfClear(this)
|
||||||
|
if onLeaveFunc then onLeaveFunc(this) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- FOCUSTARGET (if your pfUI build provides it)
|
||||||
|
function Extension.RegisterFocusTargetScripts()
|
||||||
|
if not pfUI or not pfUI.uf or not pfUI.uf.focustarget then return end
|
||||||
|
local frame = pfUI.uf.focustarget
|
||||||
|
local onEnterFunc = frame:GetScript("OnEnter")
|
||||||
|
local onLeaveFunc = frame:GetScript("OnLeave")
|
||||||
|
|
||||||
|
frame:SetScript("OnEnter", function()
|
||||||
|
PfSet(this)
|
||||||
|
if onEnterFunc then onEnterFunc(this) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
frame:SetScript("OnLeave", function()
|
||||||
|
PfClear(this)
|
||||||
|
if onLeaveFunc then onLeaveFunc(this) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- PETTARGET (if your pfUI build provides it)
|
||||||
|
function Extension.RegisterPetTargetScripts()
|
||||||
|
if not pfUI or not pfUI.uf or not pfUI.uf.pettarget then return end
|
||||||
|
local frame = pfUI.uf.pettarget
|
||||||
|
local onEnterFunc = frame:GetScript("OnEnter")
|
||||||
|
local onLeaveFunc = frame:GetScript("OnLeave")
|
||||||
|
|
||||||
|
frame:SetScript("OnEnter", function()
|
||||||
|
PfSet(this)
|
||||||
|
if onEnterFunc then onEnterFunc(this) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
frame:SetScript("OnLeave", function()
|
||||||
|
PfClear(this)
|
||||||
|
if onLeaveFunc then onLeaveFunc(this) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TARGETTARGETTARGET (if your pfUI build provides it)
|
||||||
|
function Extension.RegisterTargetTargetTargetScripts()
|
||||||
|
if not pfUI or not pfUI.uf or not pfUI.uf.targettargettarget then return end
|
||||||
|
local frame = pfUI.uf.targettargettarget
|
||||||
|
local onEnterFunc = frame:GetScript("OnEnter")
|
||||||
|
local onLeaveFunc = frame:GetScript("OnLeave")
|
||||||
|
|
||||||
|
frame:SetScript("OnEnter", function()
|
||||||
|
PfSet(this)
|
||||||
|
if onEnterFunc then onEnterFunc(this) end
|
||||||
|
end)
|
||||||
|
|
||||||
|
frame:SetScript("OnLeave", function()
|
||||||
|
PfClear(this)
|
||||||
|
if onLeaveFunc then onLeaveFunc(this) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- PARTYTARGET (party1target..party4target, plus player's target)
|
||||||
|
function Extension.RegisterPartyTargetScripts()
|
||||||
|
if not pfUI or not pfUI.uf then return end
|
||||||
|
|
||||||
|
-- This helper function is used to hook any given frame.
|
||||||
|
local function hookFrame(frame, defaultUnit)
|
||||||
|
if not frame then return end
|
||||||
|
local onEnterFunc = frame:GetScript("OnEnter")
|
||||||
|
local onLeaveFunc = frame:GetScript("OnLeave")
|
||||||
|
|
||||||
|
frame:SetScript("OnEnter", function()
|
||||||
|
PfSet(this, defaultUnit)
|
||||||
|
-- We remove the call to the original onEnterFunc to prevent overwritten tooltips.
|
||||||
|
end)
|
||||||
|
|
||||||
|
frame:SetScript("OnLeave", function()
|
||||||
|
PfClear(this)
|
||||||
|
if onLeaveFunc then onLeaveFunc(this) end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This helper function is specifically for party member targets (1-4)
|
||||||
|
local function hookPartyMemberTarget(i, frame)
|
||||||
|
if not frame then return end
|
||||||
|
local defaultUnit = "party" .. i .. "target"
|
||||||
|
hookFrame(frame, defaultUnit)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Case A: Hook dedicated arrays for party members 1-4
|
||||||
|
if pfUI.uf.grouptarget then
|
||||||
|
for i = 1, 4 do hookPartyMemberTarget(i, pfUI.uf.grouptarget[i]) end
|
||||||
|
end
|
||||||
|
if pfUI.uf.partytarget then
|
||||||
|
for i = 1, 4 do hookPartyMemberTarget(i, pfUI.uf.partytarget[i]) end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Case B: Hook child target frames for party members 1-4
|
||||||
|
if pfUI.uf.group then
|
||||||
|
for i = 1, 4 do
|
||||||
|
local g = pfUI.uf.group[i]
|
||||||
|
if g and g.target then hookPartyMemberTarget(i, g.target) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- START OF FIX to include party0target ---
|
||||||
|
-- Case C: Specifically find and hook the player's own target frame (group[0].target)
|
||||||
|
if pfUI.uf.group and pfUI.uf.group[0] and pfUI.uf.group[0].target then
|
||||||
|
-- The player's target UnitID is always "target", not "party0target".
|
||||||
|
hookFrame(pfUI.uf.group[0].target, "target")
|
||||||
|
end
|
||||||
|
--- END OF FIX ---
|
||||||
|
end
|
||||||
|
|
||||||
-- RAID MARKERS (pfUI raidmarkers module)
|
-- RAID MARKERS (pfUI raidmarkers module)
|
||||||
-- Rows are plain Buttons with label="mark" and id=1-8. They have no OnEnter/OnLeave
|
-- Rows are plain Buttons with label="mark" and id=1-8. They have no OnEnter/OnLeave
|
||||||
-- by default, so [mouseover] macros are blind to them. We hook each row so hovering
|
-- by default, so [mouseover] macros are blind to them. We hook each row so hovering
|
||||||
-- registers "mark1".."mark8" through the normal priority system. pfUI's own
|
-- registers "mark1".."mark8" through the normal priority system.
|
||||||
-- SetMouseoverUnit path only covers unitframes, so this stays.
|
|
||||||
function Extension.RegisterRaidMarkScripts()
|
function Extension.RegisterRaidMarkScripts()
|
||||||
if not pfUI or not pfUI.raidmarkers or not pfUI.raidmarkers.rows then return end
|
if not pfUI or not pfUI.raidmarkers or not pfUI.raidmarkers.rows then return end
|
||||||
|
|
||||||
@@ -147,7 +374,17 @@ function Extension.HookPfCast()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Extension.PLAYER_ENTERING_WORLD()
|
function Extension.PLAYER_ENTERING_WORLD()
|
||||||
if not pfUI then return end
|
if not pfUI or not pfUI.uf then return end
|
||||||
|
Extension.RegisterPlayerScripts()
|
||||||
|
Extension.RegisterTargetScripts()
|
||||||
|
Extension.RegisterTargetTargetScripts()
|
||||||
|
Extension.RegisterPartyScripts()
|
||||||
|
Extension.RegisterPartyTargetScripts()
|
||||||
|
Extension.RegisterRaidScripts()
|
||||||
|
Extension.RegisterFocusScripts()
|
||||||
|
Extension.RegisterFocusTargetScripts()
|
||||||
|
Extension.RegisterPetTargetScripts()
|
||||||
|
Extension.RegisterTargetTargetTargetScripts()
|
||||||
Extension.RegisterRaidMarkScripts()
|
Extension.RegisterRaidMarkScripts()
|
||||||
Extension.HookPfCast()
|
Extension.HookPfCast()
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -156,53 +156,27 @@ end
|
|||||||
|
|
||||||
-- Lightweight equipment-only indexing for combat situations
|
-- Lightweight equipment-only indexing for combat situations
|
||||||
-- Updates existing cache rather than rebuilding it
|
-- Updates existing cache rather than rebuilding it
|
||||||
function CleveRoids.IndexEquippedItems()
|
|
||||||
local items = CleveRoids.Items or {}
|
|
||||||
|
|
||||||
for inventoryID = 1, 19 do
|
|
||||||
local itemID = GetInventoryItemID("player", inventoryID)
|
|
||||||
if itemID then
|
|
||||||
local name, link, _, _, itemType, itemSubType, _, _, texture = GetItemInfo(itemID)
|
|
||||||
if name then
|
|
||||||
local count = GetInventoryItemCount("player", inventoryID)
|
|
||||||
if not items[name] then
|
|
||||||
items[name] = {
|
|
||||||
inventoryID = inventoryID,
|
|
||||||
id = itemID,
|
|
||||||
name = name,
|
|
||||||
count = count,
|
|
||||||
texture = texture,
|
|
||||||
link = link,
|
|
||||||
}
|
|
||||||
items[itemID] = name
|
|
||||||
local lowerName = string.lower(name)
|
|
||||||
if lowerName ~= name then
|
|
||||||
items[lowerName] = name
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Update existing entry with current equipment state
|
|
||||||
items[name].inventoryID = inventoryID
|
|
||||||
items[name].count = count
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- Slot is now empty - clear inventoryID from any item that was there
|
|
||||||
-- This is handled lazily by GetItem() fallback, so we skip expensive iteration
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
CleveRoids.lastGetItem = nil
|
|
||||||
CleveRoids.Items = items
|
|
||||||
end
|
|
||||||
|
|
||||||
-- PERFORMANCE: Index a single equipment slot instead of all 20
|
-- PERFORMANCE: Index a single equipment slot instead of all 20
|
||||||
-- Use when we know exactly which slot changed (e.g., from EquipBagItem)
|
-- Use when we know exactly which slot changed (e.g., from EquipBagItem or
|
||||||
function CleveRoids.IndexEquipSlot(inventoryID)
|
-- PLAYER_EQUIPMENT_CHANGED). hasCurrent is the event's arg2 (does the slot now
|
||||||
|
-- hold an item); pass false to skip the API probe on a slot we know is empty.
|
||||||
|
function CleveRoids.IndexEquipSlot(inventoryID, hasCurrent)
|
||||||
if not inventoryID then return end
|
if not inventoryID then return end
|
||||||
|
|
||||||
local items = CleveRoids.Items or {}
|
local items = CleveRoids.Items or {}
|
||||||
local itemID = GetInventoryItemID("player", inventoryID)
|
|
||||||
|
|
||||||
|
-- Clear any stale inventoryID still pointing at this slot: the item that was
|
||||||
|
-- here is now unequipped or swapped out (its real location comes from the
|
||||||
|
-- paired BAG_UPDATE rebuild). Equip changes are user-paced, so this table
|
||||||
|
-- scan is off the hot path.
|
||||||
|
for _, entry in pairs(items) do
|
||||||
|
if type(entry) == "table" and entry.inventoryID == inventoryID then
|
||||||
|
entry.inventoryID = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- hasCurrent == false (arg2) => slot is now empty, nothing to add.
|
||||||
|
local itemID = hasCurrent ~= false and GetInventoryItemID("player", inventoryID)
|
||||||
if itemID then
|
if itemID then
|
||||||
local name, itemLink, _, _, itemType, itemSubType, _, _, texture = GetItemInfo(itemID)
|
local name, itemLink, _, _, itemType, itemSubType, _, _, texture = GetItemInfo(itemID)
|
||||||
if name then
|
if name then
|
||||||
|
|||||||
+2
-6
@@ -247,7 +247,6 @@ function CleveRoids.GetChannelDurationFromTooltipByID(spellID)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Fallback: resolve name and scan tooltip
|
-- Fallback: resolve name and scan tooltip
|
||||||
if not GetSpellRecField then return nil end
|
|
||||||
local spellName = C_Spell.GetSpellName(spellID)
|
local spellName = C_Spell.GetSpellName(spellID)
|
||||||
if not spellName then return nil end
|
if not spellName then return nil end
|
||||||
return CleveRoids.GetSpellDurationFromTooltip(spellName)
|
return CleveRoids.GetSpellDurationFromTooltip(spellName)
|
||||||
@@ -7105,10 +7104,7 @@ function CleveRoids.ApplySetBonusModifier(spellID, baseDuration)
|
|||||||
local modifiedDuration = modifier.modifier(baseDuration)
|
local modifiedDuration = modifier.modifier(baseDuration)
|
||||||
|
|
||||||
if modifiedDuration ~= baseDuration and CleveRoids.debug then
|
if modifiedDuration ~= baseDuration and CleveRoids.debug then
|
||||||
local spellName = "Unknown"
|
local spellName = C_Spell.GetSpellName(spellID) or "Unknown"
|
||||||
if GetSpellRecField then
|
|
||||||
spellName = C_Spell.GetSpellName(spellID) or spellName
|
|
||||||
end
|
|
||||||
DEFAULT_CHAT_FRAME:AddMessage(
|
DEFAULT_CHAT_FRAME:AddMessage(
|
||||||
string.format("|cff00ffff[Set Bonus Modifier]|r %s (ID:%d): %.1fs -> %.1fs (%d/%d pieces)",
|
string.format("|cff00ffff[Set Bonus Modifier]|r %s (ID:%d): %.1fs -> %.1fs (%d/%d pieces)",
|
||||||
spellName, spellID, baseDuration, modifiedDuration,
|
spellName, spellID, baseDuration, modifiedDuration,
|
||||||
@@ -7585,7 +7581,7 @@ local function GetSpellSchool(spellName, spellID)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- If we only have spellID but no name, try to get name from GetSpellRecField
|
-- If we only have spellID but no name, try to get name from GetSpellRecField
|
||||||
if spellID and not spellName and GetSpellRecField then
|
if spellID and not spellName then
|
||||||
spellName = C_Spell.GetSpellName(spellID)
|
spellName = C_Spell.GetSpellName(spellID)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user