mirror of
https://github.com/brues-code/pfUI.git
synced 2026-10-01 19:30:00 +00:00
With selfdebuff on, the displayed debuff list is PLAYER-filtered while GameTooltip:SetUnitAura indexes the unfiltered HARMFUL list, so both handlers map one to the other by matching name + sourceGUID. That mapping scanned slots 1..16 only. The unfiltered harmful list is not capped at 16. Once a unit's 16 debuff slots are full the server parks further debuffs in buff slots, and C_UnitAuras classifies by the aura's polarity flag rather than its slot range, so it reports those as harmful too -- verified live at 18 harmful on a 20-aura target. Past the sixteenth the lookup found nothing and fell through to the raw filtered index, opening the wrong tooltip or none. Both now enumerate however many harmful auras the unit actually has, via ScanAuraSlots, which also drops the per-index rescan the by-index accessor was doing. Each handler gets its own slot buffer: OnEnter can fire while a refresh is showing/hiding frames under the cursor, so sharing the refresh buffer could clobber a scan mid-walk. The nameplate module still collects at most 16 debuffs per plate. That one is a display cap matching its 16 configured icon frames, not an aura-count assumption, so it is left alone.
510 lines
19 KiB
Lua
510 lines
19 KiB
Lua
pfUI:RegisterModule("buffwatch", function ()
|
|
local rawborder, border = GetBorderSize("panels")
|
|
|
|
local fcache = {}
|
|
local function BuffIsVisible(config, name)
|
|
-- return if all buffs should be shown
|
|
if config.filter == "none" then return true end
|
|
|
|
local index = tostring(config)
|
|
local mode = config.filter
|
|
|
|
if not fcache[index] then
|
|
fcache[index] = {}
|
|
for _, val in pairs({strsplit("#", config[mode])}) do
|
|
fcache[index][val] = true
|
|
end
|
|
end
|
|
|
|
if mode == "whitelist" then
|
|
return fcache[index][name]
|
|
elseif mode == "blacklist" then
|
|
return not fcache[index][name]
|
|
end
|
|
end
|
|
|
|
local rgbcache = setmetatable({},{__mode="kv"})
|
|
local function str2rgb(text)
|
|
if not text then return 1, 1, 1 end
|
|
if rgbcache[text] then return unpack(rgbcache[text]) end
|
|
local counter = 1
|
|
local l = string.len(text)
|
|
for i = 1, l, 3 do
|
|
counter = mod(counter*8161, 4294967279) + (string.byte(text,i)*16776193) + ((string.byte(text,i+1) or (l-i+256))*8372226) + ((string.byte(text,i+2) or (l-i+256))*3932164)
|
|
end
|
|
counter = mod(8161, 4294967279) + (string.byte(text,l)*16776193) + ((string.byte(text,l+1) or (l-l+256))*8372226) + ((string.byte(text,l+2) or (l+256))*3932164)
|
|
|
|
local hash = mod(mod(counter, 4294967291),16777216)
|
|
local r = (hash - (mod(hash,65536))) / 65536
|
|
local g = ((hash - r*65536) - ( mod((hash - r*65536),256)) ) / 256
|
|
local b = hash - r*65536 - g*256
|
|
rgbcache[text] = { r / 255, g / 255, b / 255 }
|
|
return unpack(rgbcache[text])
|
|
end
|
|
|
|
|
|
local function GetSafeTop(frame)
|
|
if frame and frame.IsShown and frame:IsShown() and frame:IsVisible() then
|
|
return frame:GetTop(), frame
|
|
end
|
|
|
|
return 0
|
|
end
|
|
|
|
-- iterate over given tables and return the first frame that is shown
|
|
local function GetTopAnchor(anchors)
|
|
local top, anchor = 0, anchors[1]
|
|
|
|
for _, tbl in pairs(anchors) do
|
|
|
|
-- in case of multiple anchor elements, iterate over each one
|
|
for i=32, 1, -1 do
|
|
if GetSafeTop(tbl[i]) > top then
|
|
top, anchor = GetSafeTop(tbl[i])
|
|
end
|
|
end
|
|
|
|
-- check top of regular anchor elements
|
|
if GetSafeTop(tbl) > top then
|
|
top, anchor = GetSafeTop(tbl)
|
|
end
|
|
end
|
|
|
|
return anchor
|
|
end
|
|
|
|
-- reusable GetAuraSlots buffer, filled once per RefreshBuffBarFrame
|
|
local auraSlots = {}
|
|
|
|
-- Separate buffer for the tooltip handler: OnEnter can fire while a refresh
|
|
-- is showing/hiding bars under the cursor, so it must not share the above.
|
|
local tooltipSlots = {}
|
|
|
|
-- Reads one aura by the slot id GetAuraSlots returned (nil slot -> nil).
|
|
local function GetBuffData(unit, slot)
|
|
local name, icon, count, dispelType, _, expirationTime = C_UnitAuras.UnitAuraBySlot(unit, slot)
|
|
if not name then return end
|
|
local remaining = expirationTime > 0 and (expirationTime - GetTime()) or 0
|
|
return remaining, icon, name, count, dispelType
|
|
end
|
|
|
|
local function StatusBarOnClick()
|
|
if arg1 == "LeftButton" then
|
|
local config = this.parent.config
|
|
local skill = this.text:GetText()
|
|
if IsControlKeyDown() then
|
|
for _, val in pairs({strsplit("#", config.whitelist)}) do
|
|
if val == skill then return end
|
|
end
|
|
config.whitelist = config.whitelist .. "#" .. skill
|
|
fcache[tostring(config)] = nil -- invalidate so the new entry takes effect immediately
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cff33ffcc" .. skill .. "|r" .. T["is now whitelisted."])
|
|
elseif IsShiftKeyDown() then
|
|
for _, val in pairs({strsplit("#", config.blacklist)}) do
|
|
if val == skill then return end
|
|
end
|
|
config.blacklist = config.blacklist .. "#" .. skill
|
|
fcache[tostring(config)] = nil -- invalidate so the new entry takes effect immediately
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cff33ffcc" .. skill .. "|r" .. T["is now blacklisted."])
|
|
end
|
|
elseif this.parent.unit == "player" then
|
|
local aura = C_UnitAuras.GetAuraDataByIndex("player", this.id, this.type)
|
|
if aura and aura.spellId then C_Spell.CancelSpellByID(aura.spellId) end
|
|
end
|
|
end
|
|
|
|
local function StatusBarOnEnter()
|
|
GameTooltip:SetOwner(this, "NONE")
|
|
|
|
if this.unit == "player" then
|
|
GameTooltip:SetUnitAura("player", this.id, this.type)
|
|
elseif this.type == "HARMFUL" then
|
|
-- selfdebuff filters the displayed list to player-cast harmful auras, but
|
|
-- SetUnitAura's index has to be into the unfiltered HARMFUL list. Look up
|
|
-- the displayed aura via the PLAYER filter, then find its position in the
|
|
-- unfiltered list by name + sourceGUID.
|
|
--
|
|
-- The unfiltered list is NOT capped at 16: once a unit's 16 debuff slots
|
|
-- are full the server parks further debuffs in buff slots, and
|
|
-- C_UnitAuras reports those as harmful too. So enumerate what it has.
|
|
local config = this.parent and this.parent.config
|
|
if config and config.selfdebuff == "1" then
|
|
local ownAura = C_UnitAuras.GetAuraDataByIndex(this.unit, this.id, "HARMFUL|PLAYER")
|
|
if ownAura then
|
|
local n = ScanAuraSlots(this.unit, "HARMFUL", tooltipSlots)
|
|
for i = 1, n do
|
|
local check = C_UnitAuras.GetAuraDataBySlot(this.unit, tooltipSlots[i])
|
|
if check and check.name == ownAura.name and check.sourceGUID == ownAura.sourceGUID then
|
|
GameTooltip:SetUnitAura(this.unit, i, "HARMFUL")
|
|
break
|
|
end
|
|
end
|
|
end
|
|
else
|
|
GameTooltip:SetUnitAura(this.unit, this.id, "HARMFUL")
|
|
end
|
|
elseif this.type == "HELPFUL" then
|
|
GameTooltip:SetUnitAura(this.unit, this.id, "HELPFUL")
|
|
end
|
|
|
|
if IsShiftKeyDown() then
|
|
GameTooltip:AddLine(" ")
|
|
GameTooltip:AddDoubleLine(T["Ctrl-Click"], T["Add to Whitelist"], 1,1,1, .2,1,.8)
|
|
GameTooltip:AddDoubleLine(T["Shift-Click"], T["Add to Blacklist"], 1,1,1, .2,1,.8)
|
|
end
|
|
|
|
GameTooltip:Show()
|
|
end
|
|
|
|
local function StatusBarOnLeave()
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
local function StatusBarOnUpdate()
|
|
local remaining = this.endtime - GetTime()
|
|
this.bar:SetValue(remaining > 0 and remaining or 0)
|
|
|
|
if ( this.tick or 1) > GetTime() then return else this.tick = GetTime() + .1 end
|
|
this.time:SetText(remaining > 0 and GetColoredTimeString(remaining) or "")
|
|
end
|
|
|
|
local function StatusBarRefreshParent()
|
|
this.parent:RefreshPosition()
|
|
end
|
|
|
|
local function CreateStatusBar(bar, parent)
|
|
local color = parent.color
|
|
local bordercolor = parent.bordercolor
|
|
local textcolor = parent.textcolor
|
|
local width, height = parent:GetSize()
|
|
local framename = "pf" .. parent.unit .. ( parent.type == "HARMFUL" and "Debuff" or "Buff" ) .. "Bar" .. bar
|
|
|
|
local font = parent.config.use_unitfonts == "1" and pfUI.font_unit or pfUI.font_default
|
|
|
|
local frame = _G[framename] or CreateFrame("Button", framename, parent)
|
|
frame:EnableMouse(1)
|
|
frame:Hide()
|
|
frame:SetPoint("BOTTOM", 0, (bar-1)*(height+2*border+1))
|
|
frame:SetSize(width, height)
|
|
|
|
frame.bar = CreateFrame("StatusBar", "pfBuffBar" .. bar, frame)
|
|
frame.bar:SetPoint("TOPLEFT", frame, "TOPLEFT", height+1, 0)
|
|
frame.bar:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0)
|
|
frame.bar:SetStatusBarTexture(pfUI.media["img:bar"])
|
|
frame.bar:SetStatusBarColor(color.r, color.g, color.b, color.a)
|
|
|
|
frame.text = frame.bar:CreateFontString("Status", "DIALOG", "GameFontNormal")
|
|
frame.text:ClearAllPoints()
|
|
frame.text:SetPoint("TOPLEFT", frame.bar, "TOPLEFT", 3, 0)
|
|
frame.text:SetPoint("BOTTOMRIGHT", frame.bar, "BOTTOMRIGHT", -3, 0)
|
|
frame.text:SetNonSpaceWrap(false)
|
|
frame.text:SetFontObject(GameFontWhite)
|
|
frame.text:SetFont(font, C.global.font_size)
|
|
frame.text:SetTextColor(textcolor.r,textcolor.g,textcolor.b,1)
|
|
frame.text:SetJustifyH("LEFT")
|
|
|
|
frame.time = frame.bar:CreateFontString("Status", "DIALOG", "GameFontNormal")
|
|
frame.time:ClearAllPoints()
|
|
frame.time:SetPoint("TOPLEFT", frame.bar, "TOPLEFT", 3, 0)
|
|
frame.time:SetPoint("BOTTOMRIGHT", frame.bar, "BOTTOMRIGHT", -3, 0)
|
|
frame.time:SetNonSpaceWrap(false)
|
|
frame.time:SetFontObject(GameFontWhite)
|
|
frame.time:SetFont(font, C.global.font_size)
|
|
frame.time:SetTextColor(1,1,1,1)
|
|
frame.time:SetJustifyH("RIGHT")
|
|
|
|
frame.icon = frame:CreateTexture(nil, "OVERLAY")
|
|
frame.icon:SetSize(height, height)
|
|
frame.icon:SetPoint("LEFT", frame, "LEFT", 0, 0)
|
|
frame.icon:SetTexCoord(.07,.93,.07,.93)
|
|
|
|
frame.stacks = frame.bar:CreateFontString("Status", "DIALOG", "GameFontWhite")
|
|
frame.stacks:SetFont(font, C.global.font_size, "OUTLINE")
|
|
frame.stacks:SetAllPoints(frame.icon)
|
|
frame.stacks:SetJustifyH("CENTER")
|
|
frame.stacks:SetJustifyV("CENTER")
|
|
|
|
frame.parent = parent
|
|
frame:SetScript("OnUpdate", StatusBarOnUpdate)
|
|
frame:SetScript("OnShow", StatusBarRefreshParent)
|
|
frame:SetScript("OnHide", StatusBarRefreshParent)
|
|
|
|
frame:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
|
frame:SetScript("OnClick", StatusBarOnClick)
|
|
frame:SetScript("OnEnter", StatusBarOnEnter)
|
|
frame:SetScript("OnLeave", StatusBarOnLeave)
|
|
|
|
CreateBackdrop(frame)
|
|
CreateBackdropShadow(frame)
|
|
if bordercolor.r ~= 0 and bordercolor.g ~= 0 and bordercolor.b ~= 0 and bordercolor.a ~= 0 then
|
|
frame.backdrop:SetBackdropBorderColor(bordercolor.r,bordercolor.g,bordercolor.b,1)
|
|
end
|
|
|
|
return frame
|
|
end
|
|
|
|
local function RefreshBuffBarFrame(frame)
|
|
-- reinitialize all active buffs
|
|
local selfdebuff = frame.config.selfdebuff == "1"
|
|
local filter = (selfdebuff and frame.type == "HARMFUL") and "HARMFUL|PLAYER" or frame.type
|
|
|
|
-- one GetAuraSlots enumeration per refresh instead of a by-index walk per
|
|
-- bar; the i-th slot is the i-th aura of the filtered list, so `i` stays
|
|
-- the index the tooltip / cancel handlers pass to the by-index API
|
|
ScanAuraSlots(frame.unit, filter, auraSlots, 32)
|
|
|
|
for i=1,32 do
|
|
local timeleft, texture, name, stacks, dtype = GetBuffData(frame.unit, auraSlots[i])
|
|
timeleft = timeleft or 0
|
|
|
|
if texture and name and name ~= "" and BuffIsVisible(frame.config, name) then
|
|
frame.buffs[i][1] = timeleft
|
|
frame.buffs[i][2] = i
|
|
frame.buffs[i][3] = name
|
|
frame.buffs[i][4] = texture
|
|
frame.buffs[i][5] = stacks
|
|
frame.buffs[i][6] = dtype
|
|
else
|
|
frame.buffs[i][1] = 0
|
|
frame.buffs[i][2] = nil
|
|
frame.buffs[i][3] = nil
|
|
frame.buffs[i][4] = nil
|
|
frame.buffs[i][5] = 0
|
|
frame.buffs[i][6] = nil
|
|
end
|
|
end
|
|
|
|
table.sort(frame.buffs, frame.buffcmp)
|
|
|
|
-- create a buff bar for each below threshold
|
|
local bar = 1
|
|
for id, data in pairs(frame.buffs) do
|
|
if data[1] and ((data[1] ~= 0 and data[1] < frame.threshold) or frame.threshold == -1) -- timeleft checks
|
|
and data[3] and data[3] ~= "" -- buff has a name
|
|
and data[4] and data[4] ~= "" -- buff has a texture
|
|
then
|
|
-- No slot in uuid: slots shift when debuffs expire causing timer resets
|
|
local uuid = data[4] .. data[3] -- texture + name only
|
|
|
|
-- update bar data
|
|
frame.bars[bar] = frame.bars[bar] or CreateStatusBar(bar, frame)
|
|
frame.bars[bar].id = data[2]
|
|
frame.bars[bar].unit = frame.unit
|
|
frame.bars[bar].type = frame.type
|
|
frame.bars[bar].endtime = GetTime() + ( data[1] > 0 and data[1] or -1 )
|
|
|
|
-- update max duration the cached remaining values is less than
|
|
-- the real one, indicates a buff renewal
|
|
frame.durations[uuid] = frame.durations[uuid] or {}
|
|
if not frame.durations[uuid][1] or frame.durations[uuid][1] < data[1] then
|
|
frame.durations[uuid][2] = data[1] -- max
|
|
end
|
|
frame.durations[uuid][1] = data[1] -- current
|
|
|
|
-- cache max stacks for the buff
|
|
if not frame.charges[uuid] or frame.charges[uuid] < data[5] then
|
|
frame.charges[uuid] = data[5]
|
|
end
|
|
|
|
-- set name
|
|
if frame.bars[bar].cacheName ~= data[3] then
|
|
frame.bars[bar].cacheName = data[3]
|
|
frame.bars[bar].text:SetText(data[3])
|
|
|
|
-- calculate dynamic auto color
|
|
local r, g, b
|
|
if frame.type == "HARMFUL" then
|
|
-- official Blizzard dispel-type colors (matches unitframes/buff);
|
|
-- nil/unknown type falls back to the DEBUFF_TYPE_NONE colour
|
|
r, g, b = C_UnitAuras.GetAuraDispelTypeColor(data[6] or ""):GetRGBA()
|
|
else
|
|
r,g,b = str2rgb(data[3])
|
|
end
|
|
|
|
-- set auto background color
|
|
if frame.config.dtypebg == "1" then
|
|
frame.bars[bar].bar:SetStatusBarColor(r,g,b,1)
|
|
end
|
|
|
|
-- set auto border color
|
|
if frame.config.dtypeborder == "1" then
|
|
frame.bars[bar].backdrop:SetBackdropBorderColor(r,g,b,1)
|
|
end
|
|
|
|
-- set auto text color
|
|
if frame.config.dtypetext == "1" then
|
|
frame.bars[bar].text:SetTextColor(r,g,b,1)
|
|
end
|
|
end
|
|
|
|
-- set texture
|
|
if frame.bars[bar].cacheTexture ~= data[4] then
|
|
frame.bars[bar].cacheTexture = data[4]
|
|
frame.bars[bar].icon:SetTexture(data[4])
|
|
end
|
|
|
|
-- cache maxduration
|
|
if frame.bars[bar].cacheMaxDuration ~= frame.durations[uuid][2] then
|
|
frame.bars[bar].cacheMaxDuration = frame.durations[uuid][2]
|
|
frame.bars[bar].bar:SetMinMaxValues(0, frame.durations[uuid][2])
|
|
end
|
|
|
|
-- set stacks
|
|
if data[5] > 1 then
|
|
local stacks_percentage = data[5] / (frame.charges[uuid] * .01)
|
|
local sr, sg, sb, sa
|
|
if stacks_percentage >= 90 then
|
|
sr, sg, sb, sa = .3, 1, .3, 1
|
|
elseif stacks_percentage >= 60 then
|
|
sr, sg, sb, sa = 1, 1, .3, 1
|
|
elseif stacks_percentage >= 0 then
|
|
sr, sg, sb, sa = 1, .3, .3, 1
|
|
end
|
|
if frame.config.colorstacks == "1" then
|
|
frame.bars[bar].stacks:SetText(rgbhex(sr,sg,sb) .. data[5])
|
|
else
|
|
frame.bars[bar].stacks:SetText(data[5])
|
|
end
|
|
else
|
|
frame.bars[bar].stacks:SetText("")
|
|
end
|
|
|
|
frame.bars[bar]:Show()
|
|
bar = bar + 1
|
|
end
|
|
end
|
|
|
|
-- hide remaining bars
|
|
for i = bar, table.getn(frame.bars) do
|
|
frame.bars[i]:Hide()
|
|
end
|
|
end
|
|
|
|
-- Create a new Buff Bar
|
|
local function BuffBarFrameOnUpdate()
|
|
if ( this.tick or 1) > GetTime() then return else this.tick = GetTime() + .4 end
|
|
RefreshBuffBarFrame(this)
|
|
this:RefreshPosition()
|
|
end
|
|
|
|
local function RefreshPosition(self)
|
|
-- avoid position changes during unlock
|
|
if pfUI.unlock and pfUI.unlock:IsShown() then return end
|
|
|
|
if not pfUI_config["position"][self:GetName()] then
|
|
local anchor = GetTopAnchor(self.anchors)
|
|
|
|
if not self.lastanchor or self.lastanchor ~= anchor then
|
|
self:ClearAllPoints()
|
|
self:SetPoint("LEFT", self.anchors[1], "LEFT", 0, 0)
|
|
self:SetPoint("BOTTOM", anchor, "TOP", 0, border*2+1)
|
|
UpdateMovable(self, true)
|
|
self.lastanchor = anchor
|
|
end
|
|
end
|
|
end
|
|
|
|
local function CreateBuffBarFrame(unit, type)
|
|
local framename = "pf" .. unit .. ( type == "HARMFUL" and "Debuff" or "Buff" ) .. "Bar"
|
|
local frame = _G[framename] or CreateFrame("Frame", framename, UIParent)
|
|
|
|
frame.unit = strlower(unit)
|
|
frame.type = type
|
|
frame.bars = { }
|
|
frame.durations = { }
|
|
frame.charges = { }
|
|
frame.buffs = { }
|
|
for i=1,32 do
|
|
frame.buffs[i] = { }
|
|
end
|
|
|
|
frame.RefreshPosition = RefreshPosition
|
|
|
|
-- OnEvent (UNIT_AURA) doesn't trigger properly on buff refresh
|
|
frame:SetScript("OnUpdate", BuffBarFrameOnUpdate)
|
|
|
|
return frame
|
|
end
|
|
|
|
local function asc(a,b)
|
|
return a[1] > b[1]
|
|
end
|
|
|
|
local function desc(a,b)
|
|
return a[1] < b[1]
|
|
end
|
|
|
|
-- create player buffbars
|
|
if pfUI.uf.player and C.buffbar.pbuff.enable == "1" then
|
|
pfUI.uf.player.buffbar = CreateBuffBarFrame("Player", "HELPFUL")
|
|
local config = C.buffbar.pbuff
|
|
|
|
pfUI.uf.player.buffbar:SetWidth(config.width == "-1" and pfUI.uf.player:GetWidth() or config.width)
|
|
pfUI.uf.player.buffbar:SetHeight(config.height)
|
|
pfUI.uf.player.buffbar.threshold = tonumber(config.threshold)
|
|
pfUI.uf.player.buffbar.config = config
|
|
pfUI.uf.player.buffbar.buffcmp = config.sort == "asc" and asc or desc
|
|
pfUI.uf.player.buffbar.color = GetStringColorObject(config.color)
|
|
pfUI.uf.player.buffbar.bordercolor = GetStringColorObject(config.bordercolor)
|
|
pfUI.uf.player.buffbar.textcolor = GetStringColorObject(config.textcolor)
|
|
pfUI.uf.player.buffbar.anchors = {
|
|
pfUI.uf.player,
|
|
pfUI.uf.player and pfUI.uf.player.debuffs,
|
|
pfUI.uf.player and pfUI.uf.player.buffs
|
|
}
|
|
|
|
pfUI.uf.player.buffbar:SetPoint("LEFT", pfUI.uf.player, "LEFT", 0, 0)
|
|
pfUI.uf.player.buffbar:SetPoint("BOTTOM", pfUI.uf.player, "TOP", 0, border*2+1)
|
|
UpdateMovable(pfUI.uf.player.buffbar)
|
|
end
|
|
|
|
-- create player debuffbars
|
|
if pfUI.uf.player and C.buffbar.pdebuff.enable == "1" then
|
|
local config = C.buffbar.pdebuff
|
|
|
|
pfUI.uf.player.debuffbar = CreateBuffBarFrame("Player", "HARMFUL")
|
|
pfUI.uf.player.debuffbar:SetWidth(config.width == "-1" and pfUI.uf.player:GetWidth() or config.width)
|
|
pfUI.uf.player.debuffbar:SetHeight(config.height)
|
|
pfUI.uf.player.debuffbar.threshold = tonumber(config.threshold)
|
|
pfUI.uf.player.debuffbar.config = config
|
|
pfUI.uf.player.debuffbar.buffcmp = config.sort == "asc" and asc or desc
|
|
pfUI.uf.player.debuffbar.color = GetStringColorObject(config.color)
|
|
pfUI.uf.player.debuffbar.bordercolor = GetStringColorObject(config.bordercolor)
|
|
pfUI.uf.player.debuffbar.textcolor = GetStringColorObject(config.textcolor)
|
|
pfUI.uf.player.debuffbar.anchors = {
|
|
pfUI.uf.player,
|
|
pfUI.uf.player and pfUI.uf.player.buffbar and pfUI.uf.player.buffbar.bars,
|
|
pfUI.uf.player and pfUI.uf.player.debuffs,
|
|
pfUI.uf.player and pfUI.uf.player.buffs
|
|
}
|
|
|
|
pfUI.uf.player.debuffbar:SetPoint("LEFT", pfUI.uf.player, "LEFT", 0, 0)
|
|
pfUI.uf.player.debuffbar:SetPoint("BOTTOM", pfUI.uf.player, "TOP", 0, border*2+1)
|
|
UpdateMovable(pfUI.uf.player.debuffbar)
|
|
end
|
|
|
|
-- create target debuffbars
|
|
if pfUI.uf.target and C.buffbar.tdebuff.enable == "1" then
|
|
local config = C.buffbar.tdebuff
|
|
|
|
pfUI.uf.target.debuffbar = CreateBuffBarFrame("Target", "HARMFUL")
|
|
pfUI.uf.target.debuffbar:SetWidth(config.width == "-1" and pfUI.uf.target:GetWidth() or config.width)
|
|
pfUI.uf.target.debuffbar:SetHeight(config.height)
|
|
pfUI.uf.target.debuffbar.config = config
|
|
pfUI.uf.target.debuffbar.buffcmp = config.sort == "asc" and asc or desc
|
|
pfUI.uf.target.debuffbar.color = GetStringColorObject(config.color)
|
|
pfUI.uf.target.debuffbar.bordercolor = GetStringColorObject(config.bordercolor)
|
|
pfUI.uf.target.debuffbar.textcolor = GetStringColorObject(config.textcolor)
|
|
pfUI.uf.target.debuffbar.threshold = tonumber(config.threshold)
|
|
pfUI.uf.target.debuffbar.anchors = {
|
|
pfUI.uf.target,
|
|
pfUI.uf.target and pfUI.uf.target.buffbar and pfUI.uf.target.buffbar.bars,
|
|
pfUI.uf.target and pfUI.uf.target.debuffs,
|
|
pfUI.uf.target and pfUI.uf.target.buffs
|
|
}
|
|
|
|
pfUI.uf.target.debuffbar:SetPoint("LEFT", pfUI.uf.target, "LEFT", 0, 0)
|
|
pfUI.uf.target.debuffbar:SetPoint("BOTTOM", pfUI.uf.target, "TOP", 0, border*2+1)
|
|
UpdateMovable(pfUI.uf.target.debuffbar)
|
|
end
|
|
end) |