New feature for "Buff" > "Target Debuff Bar"

"Target Debuff Bar" should now correctly show only own debuffs (there will be still debuffs that are not shown up properly like AOE spells or procs)
This commit is contained in:
Meow
2026-03-31 07:11:48 +02:00
parent df532862b6
commit 1f72b93ea5
4 changed files with 92 additions and 19 deletions
-2
View File
@@ -490,7 +490,6 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("unitframes", unit, "debuffsize", "20")
pfUI:UpdateConfig("unitframes", unit, "debufflimit", "32")
pfUI:UpdateConfig("unitframes", unit, "debuffperrow", "8")
pfUI:UpdateConfig("unitframes", unit, "selfdebuff", "0")
pfUI:UpdateConfig("unitframes", unit, "invert_healthbar", "0")
pfUI:UpdateConfig("unitframes", unit, "verticalbar", "0")
pfUI:UpdateConfig("unitframes", unit, "buff_indicator", "0")
@@ -816,7 +815,6 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("nameplates", nil, "showdebuffs", "1")
pfUI:UpdateConfig("nameplates", nil, "showdebuffs_hostile", "1")
pfUI:UpdateConfig("nameplates", nil, "showdebuffs_friendly", "0")
pfUI:UpdateConfig("nameplates", nil, "selfdebuff", "0")
pfUI:UpdateConfig("nameplates", nil, "guessdebuffs", "1")
pfUI:UpdateConfig("nameplates", nil, "clickthrough", "0")
pfUI:UpdateConfig("nameplates", nil, "rightclick", "1")
+89 -12
View File
@@ -616,6 +616,22 @@ end
local function CleanupOutOfRangeUnits()
local now = GetTime()
-- Cleanup expired pending entries (every 1s)
if not pfUI.libdebuff_last_pending_cleanup then pfUI.libdebuff_last_pending_cleanup = 0 end
if now - pfUI.libdebuff_last_pending_cleanup >= 1 then
pfUI.libdebuff_last_pending_cleanup = now
for guid, spells in pairs(ownDebuffs) do
for spellName, data in pairs(spells) do
if data.pending then
local timeleft = (data.startTime + data.duration) - now
if timeleft < -2 then
spells[spellName] = nil
end
end
end
end
end
if now - lastRangeCheck < 10 then return end
lastRangeCheck = now
@@ -959,15 +975,29 @@ function libdebuff:UnitOwnDebuff(unit, id)
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 > -1 then -- Grace period
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
@@ -1111,29 +1141,41 @@ if hasNampower then
local refreshTime = GetTime()
local myGuid = GetPlayerGUID()
-- Refresh in ownDebuffs
-- Refresh in ownDebuffs - only if timer still active
if ownDebuffs[guid] then
if ownDebuffs[guid]["Rip"] then
ownDebuffs[guid]["Rip"].startTime = refreshTime
if debugStats.enabled then
DEFAULT_CHAT_FRAME:AddMessage("|cff00ffff[CARNAGE]|r Rip refreshed (CP detected)")
local timeleft = (ownDebuffs[guid]["Rip"].startTime + ownDebuffs[guid]["Rip"].duration) - refreshTime
if timeleft > 0 then
ownDebuffs[guid]["Rip"].startTime = refreshTime
if debugStats.enabled then
DEFAULT_CHAT_FRAME:AddMessage("|cff00ffff[CARNAGE]|r Rip refreshed (CP detected)")
end
end
end
if ownDebuffs[guid]["Rake"] then
ownDebuffs[guid]["Rake"].startTime = refreshTime
if debugStats.enabled then
DEFAULT_CHAT_FRAME:AddMessage("|cff00ffff[CARNAGE]|r Rake refreshed (CP detected)")
local timeleft = (ownDebuffs[guid]["Rake"].startTime + ownDebuffs[guid]["Rake"].duration) - refreshTime
if timeleft > 0 then
ownDebuffs[guid]["Rake"].startTime = refreshTime
if debugStats.enabled then
DEFAULT_CHAT_FRAME:AddMessage("|cff00ffff[CARNAGE]|r Rake refreshed (CP detected)")
end
end
end
end
-- Refresh in allAuraCasts
-- Refresh in allAuraCasts - only if timer still active
if allAuraCasts[guid] then
if allAuraCasts[guid]["Rip"] and allAuraCasts[guid]["Rip"][myGuid] then
allAuraCasts[guid]["Rip"][myGuid].startTime = refreshTime
local d = allAuraCasts[guid]["Rip"][myGuid]
if (d.startTime + d.duration) > refreshTime then
d.startTime = refreshTime
end
end
if allAuraCasts[guid]["Rake"] and allAuraCasts[guid]["Rake"][myGuid] then
allAuraCasts[guid]["Rake"][myGuid].startTime = refreshTime
local d = allAuraCasts[guid]["Rake"][myGuid]
if (d.startTime + d.duration) > refreshTime then
d.startTime = refreshTime
end
end
end
@@ -1316,7 +1358,7 @@ if hasNampower then
if numMissed > 0 or numHit == 0 then return end
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
local spellRankString
local spellRankString = GetSpellRecField and GetSpellRecField(spellId, "rank")
if not spellName then return end
local castRank = 0
@@ -1333,6 +1375,41 @@ if hasNampower then
time = GetTime()
}
end
-- selfdebuff mode: write ownDebuffs immediately on confirmed hit
-- so buffwatch shows our debuffs even when over the 16 debuff cap
if event == "SPELL_GO_SELF" and targetGuid and not isNullTarget then
local selfdebuffMode = pfUI_config and pfUI_config.buffbar and
pfUI_config.buffbar.tdebuff and pfUI_config.buffbar.tdebuff.selfdebuff == "1"
if selfdebuffMode then
local myGuid2 = GetPlayerGUID()
if casterGuid == myGuid2 then
local duration = libdebuff:GetDuration(spellName, castRank) or 0
if duration > 0 then
local texture = libdebuff:GetSpellIcon(spellId)
ownDebuffs[targetGuid] = ownDebuffs[targetGuid] or {}
-- Downrank protection
local existing = ownDebuffs[targetGuid][spellName]
local blocked = false
if existing and existing.rank and castRank > 0 and existing.rank > castRank then
local existingTimeleft = (existing.startTime + existing.duration) - GetTime()
if existingTimeleft > 0 then blocked = true end
end
if not blocked then
ownDebuffs[targetGuid][spellName] = {
startTime = GetTime(),
duration = duration,
texture = texture,
rank = castRank,
spellId = spellId,
stacks = 1,
pending = true,
}
end
end
end
end
end
-- Store rank for our casts
local myGuid = GetPlayerGUID()
+2 -2
View File
@@ -280,8 +280,8 @@ pfUI:RegisterModule("buffwatch", "vanilla:tbc", function ()
-- For player: no slot in uuid (slots shift when other buffs expire)
-- For target: include slot (multiple players can have same debuff, slot identifies who)
local uuid
if frame.unit == "player" then
uuid = data[4] .. data[3] -- texture + name only
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
+1 -3
View File
@@ -2341,7 +2341,6 @@ pfUI:RegisterModule("gui", "vanilla:tbc", function ()
CreateConfig(U[c], T["Debuffs Per Row"], C.unitframes[c], "debuffperrow")
if c ~= "player" then
CreateConfig(U[c], T["Only Show Own Debuffs (|cffffaaaaExperimental|r)"], C.unitframes[c], "selfdebuff", "checkbox")
end
CreateConfig(U[c], T["Combat/Aggro Indicators"], nil, nil, "header")
@@ -2526,7 +2525,7 @@ pfUI:RegisterModule("gui", "vanilla:tbc", function ()
CreateConfig(nil, T["Color Debuff Stacks"], C.buffbar.tdebuff, "colorstacks", "checkbox")
CreateConfig(nil, T["Buffbar Width"], C.buffbar.tdebuff, "width")
CreateConfig(nil, T["Buffbar Height"], C.buffbar.tdebuff, "height")
CreateConfig(nil, T["Only Show Own Debuffs (|cffffaaaaExperimental|r)"], C.buffbar.tdebuff, "selfdebuff", "checkbox")
CreateConfig(nil, T["Show Only Own Debuffs"], C.buffbar.tdebuff, "selfdebuff", "checkbox")
CreateConfig(nil, T["Filter Mode"], C.buffbar.tdebuff, "filter", "dropdown", pfUI.gui.dropdowns.buffbarfilter)
CreateConfig(nil, T["Time Threshold"], C.buffbar.tdebuff, "threshold")
CreateConfig(nil, T["Whitelist"], C.buffbar.tdebuff, "whitelist", "list")
@@ -2906,7 +2905,6 @@ pfUI:RegisterModule("gui", "vanilla:tbc", function ()
CreateConfig(U["nameplates"], T["Show Timer Text"], C.nameplates, "debufftext", "checkbox")
CreateConfig(Reload, T["Show Timer Animation"], C.nameplates, "debuffanim", "checkbox")
CreateConfig(U["nameplates"], T["Only Show Own Debuffs (|cffffaaaaExperimental|r)"], C.nameplates, "selfdebuff", "checkbox")
CreateConfig(U["nameplates"], T["Filter Mode"], C.nameplates.debuffs, "filter", "dropdown", pfUI.gui.dropdowns.buffbarfilter)
CreateConfig(U["nameplates"], T["Blacklist"], C.nameplates.debuffs, "blacklist", "list")
CreateConfig(U["nameplates"], T["Whitelist"], C.nameplates.debuffs, "whitelist", "list")