mirror of
https://github.com/brues-code/pfUI.git
synced 2026-09-22 07:36:56 +00:00
libdebuff/nameplates: drop dead per-aura readers and debuff cache
With every external caller of libdebuff:UnitDebuff / :UnitOwnDebuff now on C_UnitAuras, the two public per-aura readers and the nameplate-side cache they were feeding have no consumers. - libs/libdebuff.lua: removes libdebuff:UnitDebuff (~120 lines), libdebuff:UnitOwnDebuff (~75 lines), the _ownDebuffSortFunc helper, and the local cache table. The slotOwnership / ownDebuffs / allAuraCasts / pendingCasts bookkeeping stays — GetBestAuraCast (libpredict) and GetEnhancedDebuffs (CleveRoids) still read it, and the event handlers maintain it. GetSlotCaster / GetDebuffSlotMap stay too; the DEBUFF_ADDED_OTHER handler and the debug printer use them. File goes 2010 → 1870 lines. - modules/nameplates.lua: deletes PlateCacheDebuffs (was already rewritten on C_UnitAuras and unused once the display loop bypassed the cache), PlateUnitDebuff, the cachedVerify scaffolding, and the nameplate.UnitDebuff / nameplate.CacheDebuffs registrations. - api/config.lua + modules/gui.lua: drops the now-defunct "guessdebuffs" knob — its only effect was gating the dead cache.
This commit is contained in:
@@ -818,7 +818,6 @@ function pfUI:LoadConfig()
|
||||
pfUI:UpdateConfig("nameplates", nil, "showdebuffs_hostile", "1")
|
||||
pfUI:UpdateConfig("nameplates", nil, "showdebuffs_friendly", "0")
|
||||
pfUI:UpdateConfig("nameplates", nil, "owndebuffs", "0")
|
||||
pfUI:UpdateConfig("nameplates", nil, "guessdebuffs", "1")
|
||||
pfUI:UpdateConfig("nameplates", nil, "clickthrough", "0")
|
||||
pfUI:UpdateConfig("nameplates", nil, "rightclick", "1")
|
||||
pfUI:UpdateConfig("nameplates", nil, "clickthreshold", "0.5")
|
||||
|
||||
+5
-216
@@ -11,9 +11,11 @@ setfenv(1, pfUI:GetEnvironment())
|
||||
-- This eliminates ~400 lines of error-prone shift logic while maintaining full
|
||||
-- multi-caster tracking support.
|
||||
--
|
||||
-- libdebuff:UnitDebuff(unit, id)
|
||||
-- Returns debuff informations on the given effect of the specified unit.
|
||||
-- name, rank, texture, stacks, dtype, duration, timeleft, caster
|
||||
-- The public per-aura readers (UnitDebuff, UnitOwnDebuff) were retired in favor
|
||||
-- of ClassicAPI's C_UnitAuras (which now provides sourceUnit/sourceGUID and
|
||||
-- non-player expirationTime). What remains in libdebuff is the cast-event
|
||||
-- bookkeeping consumed by GetBestAuraCast / GetEnhancedDebuffs and the
|
||||
-- libdebuff_casts / libdebuff_*_hooks broadcast surface.
|
||||
|
||||
-- return instantly when another libdebuff is already active
|
||||
if pfUI.api.libdebuff then return end
|
||||
@@ -787,219 +789,6 @@ function libdebuff:AddEffect(unit, unitlevel, effect, duration, caster, rank)
|
||||
lastspell = libdebuff.objects[unit][unitlevel][effect]
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- MAIN API: UnitDebuff (GetUnitField-based)
|
||||
-- ============================================================================
|
||||
|
||||
local cache = {}
|
||||
|
||||
function libdebuff:UnitDebuff(unit, displaySlot)
|
||||
local unitname = UnitName(unit)
|
||||
local unitlevel = UnitLevel(unit)
|
||||
local duration, timeleft = nil, -1
|
||||
local rank = nil
|
||||
local caster = nil
|
||||
local effect = nil
|
||||
local texture = nil
|
||||
local stacks = 0
|
||||
local dtype = nil
|
||||
|
||||
-- Nampower: Use GetUnitField for ALL debuff data (no Blizzard UnitDebuff needed)
|
||||
if hasNampower and UnitGUID then
|
||||
local guid = UnitGUID(unit)
|
||||
if not guid then
|
||||
-- Safety fallback: no GUID available (should not happen with Nampower)
|
||||
local aura = C_UnitAuras.GetDebuffDataByIndex(unit, displaySlot)
|
||||
if aura then
|
||||
return aura.name, rank, aura.icon, aura.applications, aura.dispelName, duration, timeleft, caster
|
||||
end
|
||||
return effect, rank, texture, stacks, dtype, duration, timeleft, caster
|
||||
end
|
||||
|
||||
-- Get current slot map from GetUnitField (cached 50ms)
|
||||
local slotMap = GetDebuffSlotMap(guid)
|
||||
if not slotMap or not slotMap[displaySlot] then
|
||||
return nil
|
||||
end
|
||||
|
||||
local slotData = slotMap[displaySlot]
|
||||
effect = slotData.spellName
|
||||
texture = slotData.texture
|
||||
stacks = slotData.stacks
|
||||
dtype = slotData.dtype
|
||||
local auraSlot = slotData.auraSlot
|
||||
|
||||
-- Get caster info for this slot
|
||||
local slotCasterGuid, isOurs = GetSlotCaster(guid, auraSlot, effect)
|
||||
|
||||
if isOurs then
|
||||
-- OUR debuff - get timer from ownDebuffs
|
||||
if ownDebuffs[guid] and ownDebuffs[guid][effect] then
|
||||
local data = ownDebuffs[guid][effect]
|
||||
local remaining = (data.startTime + data.duration) - GetTime()
|
||||
if remaining > 0 then
|
||||
duration = data.duration
|
||||
timeleft = remaining
|
||||
caster = "player"
|
||||
rank = data.rank
|
||||
elseif remaining > -1 then
|
||||
-- Grace period - show 0 timeleft
|
||||
duration = data.duration
|
||||
timeleft = 0
|
||||
caster = "player"
|
||||
rank = data.rank
|
||||
end
|
||||
end
|
||||
else
|
||||
-- OTHER player's debuff - get timer from allAuraCasts
|
||||
if slotCasterGuid and allAuraCasts[guid] and allAuraCasts[guid][effect] then
|
||||
local data = allAuraCasts[guid][effect][slotCasterGuid]
|
||||
if data then
|
||||
local remaining = (data.startTime + data.duration) - GetTime()
|
||||
if remaining > 0 and data.duration > 0 then
|
||||
duration = data.duration
|
||||
timeleft = remaining
|
||||
caster = "other"
|
||||
rank = data.rank
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback: Search all casters if specific one not found
|
||||
if not duration and allAuraCasts[guid] and allAuraCasts[guid][effect] then
|
||||
for anyCasterGuid, data in pairs(allAuraCasts[guid][effect]) do
|
||||
local remaining = (data.startTime + data.duration) - GetTime()
|
||||
if remaining > 0 and data.duration > 0 then
|
||||
duration = data.duration
|
||||
timeleft = remaining
|
||||
caster = "other"
|
||||
rank = data.rank
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return effect, rank, texture, stacks, dtype, duration, timeleft, caster
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- FALLBACK: Legacy (non-Nampower) system
|
||||
-- ============================================================================
|
||||
|
||||
local aura = C_UnitAuras.GetDebuffDataByIndex(unit, displaySlot)
|
||||
if aura then
|
||||
texture = aura.icon
|
||||
stacks = aura.applications
|
||||
dtype = aura.dispelName
|
||||
effect = aura.name
|
||||
end
|
||||
|
||||
|
||||
if effect and libdebuff.objects[unitname] then
|
||||
for level, effects in pairs(libdebuff.objects[unitname]) do
|
||||
if effects[effect] and effects[effect].duration then
|
||||
local timeleft = effects[effect].start and
|
||||
effects[effect].start + effects[effect].duration - GetTime()
|
||||
|
||||
if timeleft and timeleft > 0 then
|
||||
return effect, effects[effect].rank, texture, stacks, dtype,
|
||||
effects[effect].duration, timeleft, effects[effect].caster
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return effect, rank, texture, stacks, dtype, duration, timeleft, caster
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- API: UnitOwnDebuff (only OUR debuffs)
|
||||
-- ============================================================================
|
||||
|
||||
-- Pre-defined sort function for UnitOwnDebuff (avoids closure creation per call)
|
||||
local _ownDebuffSortFunc = function(a, b)
|
||||
if a.data.startTime == b.data.startTime then
|
||||
return a.spellName < b.spellName
|
||||
end
|
||||
return a.data.startTime < b.data.startTime
|
||||
end
|
||||
|
||||
function libdebuff:UnitOwnDebuff(unit, id)
|
||||
if hasNampower and UnitGUID then
|
||||
local guid = UnitGUID(unit)
|
||||
if guid and ownDebuffs[guid] then
|
||||
-- Build sorted list of our active debuffs
|
||||
local sortedDebuffs = {}
|
||||
local now = GetTime()
|
||||
|
||||
local toRemove = nil
|
||||
for spellName, data in pairs(ownDebuffs[guid]) do
|
||||
local timeleft = (data.startTime + data.duration) - now
|
||||
if timeleft > 0 then
|
||||
local count = table.getn(sortedDebuffs) + 1
|
||||
sortedDebuffs[count] = {
|
||||
spellName = spellName,
|
||||
data = data,
|
||||
timeleft = timeleft
|
||||
}
|
||||
elseif data.pending then
|
||||
if timeleft < -2 then
|
||||
toRemove = toRemove or {}
|
||||
toRemove[spellName] = true
|
||||
end
|
||||
else
|
||||
toRemove = toRemove or {}
|
||||
toRemove[spellName] = true
|
||||
end
|
||||
end
|
||||
if toRemove then
|
||||
for spellName in pairs(toRemove) do
|
||||
ownDebuffs[guid][spellName] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Sort by startTime (oldest first = lowest display slot)
|
||||
-- If startTime is equal (e.g. after Carnage refresh), use spellName for stable sorting
|
||||
table.sort(sortedDebuffs, _ownDebuffSortFunc)
|
||||
|
||||
-- Return debuff at position 'id'
|
||||
if sortedDebuffs[id] then
|
||||
local entry = sortedDebuffs[id]
|
||||
local texture = entry.data.texture or "Interface\\Icons\\INV_Misc_QuestionMark"
|
||||
local displayTimeleft = entry.timeleft > 0 and entry.timeleft or 0
|
||||
|
||||
-- Get dtype from SpellRec DBC via stored spellId
|
||||
local entryDtype = nil
|
||||
if entry.data.spellId and GetSpellRecField then
|
||||
local dispelId = GetSpellRecField(entry.data.spellId, "dispel")
|
||||
if dispelId and dispelId > 0 then
|
||||
entryDtype = dispelTypeMap[dispelId]
|
||||
end
|
||||
end
|
||||
|
||||
return entry.spellName, entry.data.rank, texture, 1, entryDtype, entry.data.duration, displayTimeleft, "player"
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Fallback: Iterate through all debuffs and filter
|
||||
for k in pairs(cache) do cache[k] = nil end
|
||||
local count = 1
|
||||
for i=1,16 do
|
||||
local effect, rank, texture, stacks, dtype, duration, timeleft, caster = libdebuff:UnitDebuff(unit, i)
|
||||
if effect and not cache[effect] and caster and caster == "player" then
|
||||
cache[effect] = true
|
||||
if count == id then
|
||||
return effect, rank, texture, stacks, dtype, duration, timeleft, caster
|
||||
else
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- API: GetBestAuraCast (for libpredict HoT tracking)
|
||||
-- ============================================================================
|
||||
|
||||
@@ -2899,7 +2899,6 @@ pfUI:RegisterModule("gui", function ()
|
||||
CreateConfig(U["nameplates"], T["Debuff Position"], C.nameplates.debuffs, "position", "dropdown", pfUI.gui.dropdowns.debuffposition)
|
||||
CreateConfig(U["nameplates"], T["Debuff Icon Offset"], C.nameplates, "debuffoffset")
|
||||
CreateConfig(U["nameplates"], T["Debuff Icon Size"], C.nameplates, "debuffsize")
|
||||
CreateConfig(U["nameplates"], T["Estimate Debuffs"], C.nameplates, "guessdebuffs", "checkbox")
|
||||
CreateConfig(U["nameplates"], T["Show Debuff Stacks"], C.nameplates.debuffs, "showstacks", "checkbox")
|
||||
CreateConfig(U["nameplates"], T["Enable Debuff Timers"], C.nameplates, "debufftimers", "checkbox")
|
||||
CreateConfig(U["nameplates"], T["Show Timer Text"], C.nameplates, "debufftext", "checkbox")
|
||||
|
||||
@@ -371,62 +371,6 @@ pfUI:RegisterModule("nameplates", function ()
|
||||
end
|
||||
end
|
||||
|
||||
local function PlateCacheDebuffs(self, unitstr, verify)
|
||||
if not self.debuffcache then self.debuffcache = {} end
|
||||
if not libdebuff then return end
|
||||
|
||||
local now = GetTime()
|
||||
|
||||
-- Clear existing cache slots
|
||||
for id = 1, 16 do
|
||||
if self.debuffcache[id] then
|
||||
self.debuffcache[id].empty = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Pull debuffs straight from C_UnitAuras. The HARMFUL filter restricts to
|
||||
-- the debuff range; PLAYER (added when cfg.owndebuffs is on) further
|
||||
-- restricts to auras whose cached caster GUID matches the local player.
|
||||
-- expirationTime comes from ClassicAPI's Aura::Source cache (SMSG_SPELL_GO
|
||||
-- observation) — best-effort, so auras applied before login won't carry
|
||||
-- timing and we treat them as durationless.
|
||||
local filter = cfg.owndebuffs and "HARMFUL|PLAYER" or "HARMFUL"
|
||||
local auras = unitstr and C_UnitAuras.GetUnitAuras(unitstr, filter) or {}
|
||||
for id, aura in ipairs(auras) do
|
||||
if id > 16 then break end
|
||||
local duration = aura.duration or 0
|
||||
local stop = (aura.expirationTime and aura.expirationTime > 0) and aura.expirationTime or nil
|
||||
local start = stop and (stop - duration) or now
|
||||
local cache = self.debuffcache[id] or {}
|
||||
cache.effect = aura.name
|
||||
cache.texture = aura.icon
|
||||
cache.stacks = aura.applications
|
||||
cache.dtype = aura.dispelName
|
||||
cache.duration = duration
|
||||
cache.start = start
|
||||
cache.stop = stop
|
||||
cache.empty = nil
|
||||
self.debuffcache[id] = cache
|
||||
end
|
||||
|
||||
self.verify = verify
|
||||
end
|
||||
|
||||
local function PlateUnitDebuff(self, id)
|
||||
-- break on unknown data
|
||||
if not self.debuffcache then return end
|
||||
if not self.debuffcache[id] then return end
|
||||
if not self.debuffcache[id].stop then return end
|
||||
|
||||
-- break on timeout debuffs
|
||||
if self.debuffcache[id].empty then return end
|
||||
if self.debuffcache[id].stop < GetTime() then return end
|
||||
|
||||
-- return cached debuff
|
||||
local c = self.debuffcache[id]
|
||||
return c.effect, c.rank, c.texture, c.stacks, c.dtype, c.duration, (c.stop - GetTime())
|
||||
end
|
||||
|
||||
local function CreateDebuffIcon(plate, index)
|
||||
plate.debuffs[index] = CreateFrame("Frame", plate.platename.."Debuff"..index, plate)
|
||||
plate.debuffs[index]:Hide()
|
||||
@@ -734,8 +678,6 @@ end
|
||||
nameplate:EnableMouse(0)
|
||||
nameplate.parent = parent
|
||||
nameplate.cache = {}
|
||||
nameplate.UnitDebuff = PlateUnitDebuff
|
||||
nameplate.CacheDebuffs = PlateCacheDebuffs
|
||||
nameplate.original = {}
|
||||
|
||||
-- create shortcuts for all known elements and disable them
|
||||
@@ -1239,19 +1181,6 @@ end
|
||||
local isFriendly = unittype == "FRIENDLY_PLAYER" or unittype == "FRIENDLY_NPC"
|
||||
local showDebuffsForType = cfg.showdebuffs and (isFriendly and cfg.showdebuffs_friendly or (not isFriendly and cfg.showdebuffs_hostile))
|
||||
if showDebuffsForType then
|
||||
-- PERF: Cache verify string - only allocate new string when name/level actually changes
|
||||
if name ~= plate.cachedVerifyName or level ~= plate.cachedVerifyLevel then
|
||||
plate.cachedVerifyName = name
|
||||
plate.cachedVerifyLevel = level
|
||||
plate.cachedVerify = (name or "") .. ":" .. (level or "")
|
||||
end
|
||||
local verify = plate.cachedVerify
|
||||
|
||||
-- update cached debuffs
|
||||
if C.nameplates["guessdebuffs"] == "1" and unitstr then
|
||||
plate:CacheDebuffs(unitstr, verify)
|
||||
end
|
||||
|
||||
-- Pull debuffs from C_UnitAuras (HARMFUL range). owndebuffs adds the
|
||||
-- PLAYER filter token so only auras whose caster GUID matches the local
|
||||
-- player come through. debuffDisplayBuf is a module-level reusable
|
||||
|
||||
Reference in New Issue
Block a user