mirror of
https://github.com/brues-code/pfUI.git
synced 2026-10-25 21:40:49 +00:00
Several changes
Fix stale debuff icons/tooltips on target frame after target swap Fix debuffs not showing on nameplates for timer-less spells (e.g. Hurricane) Fix buffwatch timer visually speeding up when another debuff fades Remove 50ms aura cache (slotMapCache/auraFC) - caused stale debuff data Remove "Show Only Own Debuffs" from unitframes and nameplates GUI Force selfdebuff=0 for unitframes/nameplates on login to reset old SavedVariables
This commit is contained in:
@@ -454,6 +454,7 @@ function pfUI:LoadConfig()
|
|||||||
|
|
||||||
local ufs = { "player", "target", "focus", "focustarget", "group", "grouptarget", "grouppet", "raid", "ttarget", "pet", "ptarget", "fallback", "tttarget" }
|
local ufs = { "player", "target", "focus", "focustarget", "group", "grouptarget", "grouppet", "raid", "ttarget", "pet", "ptarget", "fallback", "tttarget" }
|
||||||
for _, unit in pairs(ufs) do
|
for _, unit in pairs(ufs) do
|
||||||
|
pfUI:UpdateConfig("unitframes", unit, "selfdebuff", "0")
|
||||||
pfUI:UpdateConfig("unitframes", unit, "visible", "1")
|
pfUI:UpdateConfig("unitframes", unit, "visible", "1")
|
||||||
pfUI:UpdateConfig("unitframes", unit, "showPVP", "0")
|
pfUI:UpdateConfig("unitframes", unit, "showPVP", "0")
|
||||||
pfUI:UpdateConfig("unitframes", unit, "pvpiconsize", "16" )
|
pfUI:UpdateConfig("unitframes", unit, "pvpiconsize", "16" )
|
||||||
@@ -813,6 +814,7 @@ function pfUI:LoadConfig()
|
|||||||
pfUI:UpdateConfig("nameplates", nil, "targetcastbar", "0")
|
pfUI:UpdateConfig("nameplates", nil, "targetcastbar", "0")
|
||||||
pfUI:UpdateConfig("nameplates", nil, "spellname", "0")
|
pfUI:UpdateConfig("nameplates", nil, "spellname", "0")
|
||||||
pfUI:UpdateConfig("nameplates", nil, "showdebuffs", "1")
|
pfUI:UpdateConfig("nameplates", nil, "showdebuffs", "1")
|
||||||
|
pfUI:UpdateConfig("nameplates", nil, "selfdebuff", "0")
|
||||||
pfUI:UpdateConfig("nameplates", nil, "showdebuffs_hostile", "1")
|
pfUI:UpdateConfig("nameplates", nil, "showdebuffs_hostile", "1")
|
||||||
pfUI:UpdateConfig("nameplates", nil, "showdebuffs_friendly", "0")
|
pfUI:UpdateConfig("nameplates", nil, "showdebuffs_friendly", "0")
|
||||||
pfUI:UpdateConfig("nameplates", nil, "guessdebuffs", "1")
|
pfUI:UpdateConfig("nameplates", nil, "guessdebuffs", "1")
|
||||||
|
|||||||
+6
-34
@@ -409,11 +409,6 @@ end
|
|||||||
-- CORE: GetUnitField-based Slot Mapping (THE KEY INNOVATION!)
|
-- CORE: GetUnitField-based Slot Mapping (THE KEY INNOVATION!)
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
|
|
||||||
-- Cache for GetDebuffSlotMap to reduce GetUnitField calls
|
|
||||||
-- [guid] = {map, timestamp}
|
|
||||||
local slotMapCache = {}
|
|
||||||
local SLOT_MAP_CACHE_DURATION = 0.05 -- 50ms cache (1-2 frames)
|
|
||||||
|
|
||||||
-- Dispel type mapping: SpellRec.dispel index -> Blizzard DebuffTypeColor key
|
-- Dispel type mapping: SpellRec.dispel index -> Blizzard DebuffTypeColor key
|
||||||
local dispelTypeMap = {
|
local dispelTypeMap = {
|
||||||
[1] = "Magic",
|
[1] = "Magic",
|
||||||
@@ -428,27 +423,19 @@ local function GetDebuffSlotMap(guid)
|
|||||||
if not guid or not GetUnitField then
|
if not guid or not GetUnitField then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check cache first
|
|
||||||
local now = GetTime()
|
|
||||||
local cached = slotMapCache[guid]
|
|
||||||
if cached and cached.map and (now - cached.timestamp) < SLOT_MAP_CACHE_DURATION then
|
|
||||||
return cached.map
|
|
||||||
end
|
|
||||||
|
|
||||||
local auras = GetUnitField(guid, "aura")
|
local auras = GetUnitField(guid, "aura")
|
||||||
if not auras then return nil end
|
if not auras then return nil end
|
||||||
|
|
||||||
-- Fetch stacks array (reusable reference - extract values immediately)
|
|
||||||
local auraApps = GetUnitField(guid, "auraApplications")
|
local auraApps = GetUnitField(guid, "auraApplications")
|
||||||
|
|
||||||
if debugStats.enabled then
|
if debugStats.enabled then
|
||||||
debugStats.getunitfield_calls = debugStats.getunitfield_calls + 1
|
debugStats.getunitfield_calls = debugStats.getunitfield_calls + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
local map = {}
|
local map = {}
|
||||||
local displaySlot = 0
|
local displaySlot = 0
|
||||||
|
|
||||||
-- Debuff aura slots are 33-48
|
-- Debuff aura slots are 33-48
|
||||||
for auraSlot = 33, 48 do
|
for auraSlot = 33, 48 do
|
||||||
local spellId = auras[auraSlot]
|
local spellId = auras[auraSlot]
|
||||||
@@ -456,11 +443,7 @@ local function GetDebuffSlotMap(guid)
|
|||||||
displaySlot = displaySlot + 1
|
displaySlot = displaySlot + 1
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
||||||
local texture = libdebuff:GetSpellIcon(spellId)
|
local texture = libdebuff:GetSpellIcon(spellId)
|
||||||
|
|
||||||
-- Get stacks from auraApplications (0-indexed, so +1 for display)
|
|
||||||
local stacks = (auraApps and auraApps[auraSlot] or 0) + 1
|
local stacks = (auraApps and auraApps[auraSlot] or 0) + 1
|
||||||
|
|
||||||
-- Get debuff type from SpellRec DBC
|
|
||||||
local dtype = nil
|
local dtype = nil
|
||||||
if GetSpellRecField then
|
if GetSpellRecField then
|
||||||
local dispelId = GetSpellRecField(spellId, "dispel")
|
local dispelId = GetSpellRecField(spellId, "dispel")
|
||||||
@@ -468,7 +451,6 @@ local function GetDebuffSlotMap(guid)
|
|||||||
dtype = dispelTypeMap[dispelId]
|
dtype = dispelTypeMap[dispelId]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
map[displaySlot] = {
|
map[displaySlot] = {
|
||||||
auraSlot = auraSlot,
|
auraSlot = auraSlot,
|
||||||
spellId = spellId,
|
spellId = spellId,
|
||||||
@@ -479,14 +461,7 @@ local function GetDebuffSlotMap(guid)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Cache the result (separate from buffMap to avoid cross-invalidation)
|
|
||||||
if not slotMapCache[guid] then
|
|
||||||
slotMapCache[guid] = { timestamp = now }
|
|
||||||
end
|
|
||||||
slotMapCache[guid].map = map
|
|
||||||
slotMapCache[guid].timestamp = now
|
|
||||||
|
|
||||||
return map
|
return map
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1779,7 +1754,6 @@ if hasNampower then
|
|||||||
local auraSlot = auraSlot_0based and (auraSlot_0based + 1) or nil
|
local auraSlot = auraSlot_0based and (auraSlot_0based + 1) or nil
|
||||||
|
|
||||||
-- Invalidate slot map cache for this GUID
|
-- Invalidate slot map cache for this GUID
|
||||||
slotMapCache[guid] = nil
|
|
||||||
|
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
@@ -1915,7 +1889,6 @@ if hasNampower then
|
|||||||
local auraSlot = auraSlot_0based and (auraSlot_0based + 1) or nil
|
local auraSlot = auraSlot_0based and (auraSlot_0based + 1) or nil
|
||||||
|
|
||||||
-- Invalidate slot map cache for this GUID
|
-- Invalidate slot map cache for this GUID
|
||||||
slotMapCache[guid] = nil
|
|
||||||
|
|
||||||
local spellName = (GetSpellRecField and GetSpellRecField(spellId, "name")) or "?"
|
local spellName = (GetSpellRecField and GetSpellRecField(spellId, "name")) or "?"
|
||||||
|
|
||||||
@@ -2006,7 +1979,6 @@ if hasNampower then
|
|||||||
if targetGuid and targetGuid ~= "" then
|
if targetGuid and targetGuid ~= "" then
|
||||||
-- Invalidate slot map cache on retarget
|
-- Invalidate slot map cache on retarget
|
||||||
-- Prevents stale slot mappings after untarget/retarget cycles
|
-- Prevents stale slot mappings after untarget/retarget cycles
|
||||||
slotMapCache[targetGuid] = nil
|
|
||||||
-- Cleanup expired timers for new target
|
-- Cleanup expired timers for new target
|
||||||
CleanupExpiredTimers(targetGuid)
|
CleanupExpiredTimers(targetGuid)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -277,14 +277,8 @@ pfUI:RegisterModule("buffwatch", "vanilla:tbc", function ()
|
|||||||
and data[3] and data[3] ~= "" -- buff has a name
|
and data[3] and data[3] ~= "" -- buff has a name
|
||||||
and data[4] and data[4] ~= "" -- buff has a texture
|
and data[4] and data[4] ~= "" -- buff has a texture
|
||||||
then
|
then
|
||||||
-- For player: no slot in uuid (slots shift when other buffs expire)
|
-- No slot in uuid: slots shift when debuffs expire causing timer resets
|
||||||
-- For target: include slot (multiple players can have same debuff, slot identifies who)
|
local uuid = data[4] .. data[3] -- texture + name only
|
||||||
local uuid
|
|
||||||
if frame.unit == "player" or (frame.config and frame.config.selfdebuff == "1") then
|
|
||||||
uuid = data[4] .. data[3] -- texture + name only (stable in selfdebuff mode)
|
|
||||||
else
|
|
||||||
uuid = data[4] .. data[3] .. data[2] -- texture + name + slot
|
|
||||||
end
|
|
||||||
|
|
||||||
-- update bar data
|
-- update bar data
|
||||||
frame.bars[bar] = frame.bars[bar] or CreateStatusBar(bar, frame)
|
frame.bars[bar] = frame.bars[bar] or CreateStatusBar(bar, frame)
|
||||||
@@ -518,4 +512,4 @@ pfUI:RegisterModule("buffwatch", "vanilla:tbc", function ()
|
|||||||
pfUI.uf.target.debuffbar:SetPoint("BOTTOM", pfUI.uf.target, "TOP", 0, border*2+1)
|
pfUI.uf.target.debuffbar:SetPoint("BOTTOM", pfUI.uf.target, "TOP", 0, border*2+1)
|
||||||
UpdateMovable(pfUI.uf.target.debuffbar)
|
UpdateMovable(pfUI.uf.target.debuffbar)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
+36
-27
@@ -327,28 +327,39 @@ pfUI:RegisterModule("nameplates", "vanilla", function ()
|
|||||||
|
|
||||||
local function PlateCacheDebuffs(self, unitstr, verify)
|
local function PlateCacheDebuffs(self, unitstr, verify)
|
||||||
if not self.debuffcache then self.debuffcache = {} end
|
if not self.debuffcache then self.debuffcache = {} end
|
||||||
if not libdebuff then return end -- Safety check
|
if not libdebuff then return end
|
||||||
|
|
||||||
|
local now = GetTime()
|
||||||
|
|
||||||
|
-- Clear existing cache slots
|
||||||
for id = 1, 16 do
|
for id = 1, 16 do
|
||||||
local effect, _, texture, stacks, _, duration, timeleft
|
if self.debuffcache[id] then
|
||||||
|
self.debuffcache[id].empty = true
|
||||||
if unitstr and C.nameplates.selfdebuff == "1" then
|
|
||||||
effect, _, texture, stacks, _, duration, timeleft = libdebuff:UnitOwnDebuff(unitstr, id)
|
|
||||||
else
|
|
||||||
effect, _, texture, stacks, _, duration, timeleft = libdebuff:UnitDebuff(unitstr, id)
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if effect and timeleft and timeleft > 0 then
|
-- Get GUID - unitstr may already be a GUID from plate.parent:GetName(1)
|
||||||
local start = GetTime() - ( (duration or 0) - ( timeleft or 0) )
|
local guid = unitstr
|
||||||
local stop = GetTime() + ( timeleft or 0 )
|
if unitstr and not string.find(unitstr, "^0x") and GetUnitGUID then
|
||||||
self.debuffcache[id] = self.debuffcache[id] or {}
|
guid = GetUnitGUID(unitstr) or unitstr
|
||||||
self.debuffcache[id].effect = effect
|
end
|
||||||
self.debuffcache[id].texture = texture
|
|
||||||
self.debuffcache[id].stacks = stacks
|
if guid then
|
||||||
self.debuffcache[id].duration = duration or 0
|
for id = 1, 16 do
|
||||||
self.debuffcache[id].start = start
|
local effect, _, texture, stacks, dtype, duration, timeleft
|
||||||
self.debuffcache[id].stop = stop
|
effect, _, texture, stacks, dtype, duration, timeleft = libdebuff:UnitDebuff(guid, id)
|
||||||
self.debuffcache[id].empty = nil
|
if effect and texture then
|
||||||
|
local stop = (timeleft and timeleft > 0) and (now + timeleft) or nil
|
||||||
|
local start = stop and (stop - (duration or 0)) or now
|
||||||
|
self.debuffcache[id] = self.debuffcache[id] or {}
|
||||||
|
self.debuffcache[id].effect = effect
|
||||||
|
self.debuffcache[id].texture = texture
|
||||||
|
self.debuffcache[id].stacks = stacks
|
||||||
|
self.debuffcache[id].duration = duration or 0
|
||||||
|
self.debuffcache[id].start = start
|
||||||
|
self.debuffcache[id].stop = stop
|
||||||
|
self.debuffcache[id].empty = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -359,15 +370,15 @@ pfUI:RegisterModule("nameplates", "vanilla", function ()
|
|||||||
-- break on unknown data
|
-- break on unknown data
|
||||||
if not self.debuffcache then return end
|
if not self.debuffcache then return end
|
||||||
if not self.debuffcache[id] then return end
|
if not self.debuffcache[id] then return end
|
||||||
if not self.debuffcache[id].stop then return end
|
|
||||||
|
|
||||||
-- break on timeout debuffs
|
-- break on timeout debuffs
|
||||||
if self.debuffcache[id].empty then return end
|
if self.debuffcache[id].empty then return end
|
||||||
if self.debuffcache[id].stop < GetTime() then return end
|
if self.debuffcache[id].stop and self.debuffcache[id].stop < GetTime() then return end
|
||||||
|
|
||||||
-- return cached debuff
|
-- return cached debuff
|
||||||
local c = self.debuffcache[id]
|
local c = self.debuffcache[id]
|
||||||
return c.effect, c.rank, c.texture, c.stacks, c.dtype, c.duration, (c.stop - GetTime())
|
local timeleft = c.stop and (c.stop - GetTime()) or -1
|
||||||
|
return c.effect, c.rank, c.texture, c.stacks, c.dtype, c.duration, timeleft
|
||||||
end
|
end
|
||||||
|
|
||||||
local function CreateDebuffIcon(plate, index)
|
local function CreateDebuffIcon(plate, index)
|
||||||
@@ -994,8 +1005,8 @@ nameplates:RegisterEvent("ZONE_CHANGED_NEW_AREA")
|
|||||||
-- yet updated. So while being inside this event, we cannot trust the unitstr.
|
-- yet updated. So while being inside this event, we cannot trust the unitstr.
|
||||||
if event == "PLAYER_TARGET_CHANGED" then unitstr = nil end
|
if event == "PLAYER_TARGET_CHANGED" then unitstr = nil end
|
||||||
|
|
||||||
-- remove unitstr on unit name mismatch
|
-- remove unitstr on unit name mismatch (skip for GUIDs - they're always valid)
|
||||||
if unitstr and UnitName(unitstr) ~= name then unitstr = nil end
|
if unitstr and not string.find(unitstr, "^0x") and UnitName(unitstr) ~= name then unitstr = nil end
|
||||||
|
|
||||||
-- use mobhealth values if addon is running
|
-- use mobhealth values if addon is running
|
||||||
if (MobHealth3 or MobHealthFrame) and target and name == UnitName('target') and MobHealth_GetTargetCurHP() then
|
if (MobHealth3 or MobHealthFrame) and target and name == UnitName('target') and MobHealth_GetTargetCurHP() then
|
||||||
@@ -1193,13 +1204,11 @@ nameplates:RegisterEvent("ZONE_CHANGED_NEW_AREA")
|
|||||||
plate:CacheDebuffs(unitstr, verify)
|
plate:CacheDebuffs(unitstr, verify)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update all debuff icons
|
-- update all debuff icons - use direct UnitDebuff when unitstr available
|
||||||
for i = 1, 16 do
|
for i = 1, 16 do
|
||||||
local effect, rank, texture, stacks, dtype, duration, timeleft
|
local effect, rank, texture, stacks, dtype, duration, timeleft
|
||||||
|
|
||||||
if unitstr and C.nameplates.selfdebuff == "1" and libdebuff then
|
if unitstr and libdebuff then
|
||||||
effect, rank, texture, stacks, dtype, duration, timeleft = libdebuff:UnitOwnDebuff(unitstr, i)
|
|
||||||
elseif unitstr and libdebuff then
|
|
||||||
effect, rank, texture, stacks, dtype, duration, timeleft = libdebuff:UnitDebuff(unitstr, i)
|
effect, rank, texture, stacks, dtype, duration, timeleft = libdebuff:UnitDebuff(unitstr, i)
|
||||||
elseif plate.verify == verify then
|
elseif plate.verify == verify then
|
||||||
effect, rank, texture, stacks, dtype, duration, timeleft = plate:UnitDebuff(i)
|
effect, rank, texture, stacks, dtype, duration, timeleft = plate:UnitDebuff(i)
|
||||||
|
|||||||
Reference in New Issue
Block a user