mirror of
https://github.com/brues-code/pfUI.git
synced 2026-10-10 23:50:01 +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_hostile", "1")
|
||||||
pfUI:UpdateConfig("nameplates", nil, "showdebuffs_friendly", "0")
|
pfUI:UpdateConfig("nameplates", nil, "showdebuffs_friendly", "0")
|
||||||
pfUI:UpdateConfig("nameplates", nil, "owndebuffs", "0")
|
pfUI:UpdateConfig("nameplates", nil, "owndebuffs", "0")
|
||||||
pfUI:UpdateConfig("nameplates", nil, "guessdebuffs", "1")
|
|
||||||
pfUI:UpdateConfig("nameplates", nil, "clickthrough", "0")
|
pfUI:UpdateConfig("nameplates", nil, "clickthrough", "0")
|
||||||
pfUI:UpdateConfig("nameplates", nil, "rightclick", "1")
|
pfUI:UpdateConfig("nameplates", nil, "rightclick", "1")
|
||||||
pfUI:UpdateConfig("nameplates", nil, "clickthreshold", "0.5")
|
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
|
-- This eliminates ~400 lines of error-prone shift logic while maintaining full
|
||||||
-- multi-caster tracking support.
|
-- multi-caster tracking support.
|
||||||
--
|
--
|
||||||
-- libdebuff:UnitDebuff(unit, id)
|
-- The public per-aura readers (UnitDebuff, UnitOwnDebuff) were retired in favor
|
||||||
-- Returns debuff informations on the given effect of the specified unit.
|
-- of ClassicAPI's C_UnitAuras (which now provides sourceUnit/sourceGUID and
|
||||||
-- name, rank, texture, stacks, dtype, duration, timeleft, caster
|
-- 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
|
-- return instantly when another libdebuff is already active
|
||||||
if pfUI.api.libdebuff then return end
|
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]
|
lastspell = libdebuff.objects[unit][unitlevel][effect]
|
||||||
end
|
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)
|
-- 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 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 Offset"], C.nameplates, "debuffoffset")
|
||||||
CreateConfig(U["nameplates"], T["Debuff Icon Size"], C.nameplates, "debuffsize")
|
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["Show Debuff Stacks"], C.nameplates.debuffs, "showstacks", "checkbox")
|
||||||
CreateConfig(U["nameplates"], T["Enable Debuff Timers"], C.nameplates, "debufftimers", "checkbox")
|
CreateConfig(U["nameplates"], T["Enable Debuff Timers"], C.nameplates, "debufftimers", "checkbox")
|
||||||
CreateConfig(U["nameplates"], T["Show Timer Text"], C.nameplates, "debufftext", "checkbox")
|
CreateConfig(U["nameplates"], T["Show Timer Text"], C.nameplates, "debufftext", "checkbox")
|
||||||
|
|||||||
@@ -371,62 +371,6 @@ pfUI:RegisterModule("nameplates", function ()
|
|||||||
end
|
end
|
||||||
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)
|
local function CreateDebuffIcon(plate, index)
|
||||||
plate.debuffs[index] = CreateFrame("Frame", plate.platename.."Debuff"..index, plate)
|
plate.debuffs[index] = CreateFrame("Frame", plate.platename.."Debuff"..index, plate)
|
||||||
plate.debuffs[index]:Hide()
|
plate.debuffs[index]:Hide()
|
||||||
@@ -734,8 +678,6 @@ end
|
|||||||
nameplate:EnableMouse(0)
|
nameplate:EnableMouse(0)
|
||||||
nameplate.parent = parent
|
nameplate.parent = parent
|
||||||
nameplate.cache = {}
|
nameplate.cache = {}
|
||||||
nameplate.UnitDebuff = PlateUnitDebuff
|
|
||||||
nameplate.CacheDebuffs = PlateCacheDebuffs
|
|
||||||
nameplate.original = {}
|
nameplate.original = {}
|
||||||
|
|
||||||
-- create shortcuts for all known elements and disable them
|
-- create shortcuts for all known elements and disable them
|
||||||
@@ -1239,19 +1181,6 @@ end
|
|||||||
local isFriendly = unittype == "FRIENDLY_PLAYER" or unittype == "FRIENDLY_NPC"
|
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))
|
local showDebuffsForType = cfg.showdebuffs and (isFriendly and cfg.showdebuffs_friendly or (not isFriendly and cfg.showdebuffs_hostile))
|
||||||
if showDebuffsForType then
|
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
|
-- Pull debuffs from C_UnitAuras (HARMFUL range). owndebuffs adds the
|
||||||
-- PLAYER filter token so only auras whose caster GUID matches the local
|
-- PLAYER filter token so only auras whose caster GUID matches the local
|
||||||
-- player come through. debuffDisplayBuf is a module-level reusable
|
-- player come through. debuffDisplayBuf is a module-level reusable
|
||||||
|
|||||||
Reference in New Issue
Block a user