mirror of
https://github.com/brues-code/pfUI.git
synced 2026-11-03 17:36:56 +00:00
Each feature's settings page now picks its own timers - None, Numbers,
Sweep, or Numbers And Sweep - in place of the "Show Numbers On", "Show
Sweep On" and "Reverse Sweep On" lists on Settings -> Cooldown. Unit
frames get theirs per frame again ("Buff And Debuff Timers" and
"Indicator Timers"), so party and pet can drop their numbers while the
target keeps them. The other dropdowns sit on Action Bars, Bags & Bank,
Buff/Debuff Icons, Totem Icons, Tooltip and Nameplates.
Settings -> Cooldown keeps the shared font, size, threshold, tenths and
colors, plus the timers of Spellbook And Character, Loss Of Control and
Other Addons, which have no page of their own.
CreateCooldown(parent, kind, config, key, name) reads its mode from
config[key]. The kind says only what it times: "spell" hides numbers on
the global cooldown, "aura" drains its sweep, "timer" fills it. The
reverse option is gone; the direction follows the kind.
The migration carries every old setting into its timers: the
C.cooldown kind tables, appearance.cd's foreign and Blizzard toggles,
the buff frame's sweep, the nameplate debuff options, and each unit
frame's timer text, sweep and "Show Time Left" from before the kinds,
so frames that had their own settings keep them. Reverse options are
dropped.
374 lines
13 KiB
Lua
374 lines
13 KiB
Lua
pfUI:RegisterModule("buff", function ()
|
|
-- Hide Blizz
|
|
BuffFrame:Hide()
|
|
BuffFrame:UnregisterAllEvents()
|
|
TemporaryEnchantFrame:Hide()
|
|
TemporaryEnchantFrame:UnregisterAllEvents()
|
|
|
|
local br, bg, bb, ba = GetStringColor(pfUI_config.appearance.border.color)
|
|
|
|
-- Player aura slot ids, enumerated once per refresh pass (ScanPlayerAuraSlots)
|
|
-- and read per button by its aura index: one GetAuraSlots walk per range
|
|
-- instead of a by-index walk per button.
|
|
local helpfulSlots, harmfulSlots = {}, {}
|
|
local function ScanPlayerAuraSlots()
|
|
ScanAuraSlots("player", "HELPFUL", helpfulSlots, 32)
|
|
ScanAuraSlots("player", "HARMFUL", harmfulSlots, 16)
|
|
end
|
|
|
|
-- weapon enchants report only their time left, and no event as their
|
|
-- charges and time run down, so the OnUpdate below refreshes their buttons
|
|
-- too: the charges, and the timer when the enchant was renewed
|
|
local function RefreshWeaponButton(buff, timeleft, charges)
|
|
timeleft = (timeleft or 0) / 1000
|
|
charges = charges or 0
|
|
buff.stacks:SetText(charges > 1 and charges or "")
|
|
|
|
local expires = GetTime() + timeleft
|
|
if timeleft <= 0 then
|
|
buff.cd:Clear()
|
|
buff.cdExpires = nil
|
|
elseif not buff.cdExpires or abs(buff.cdExpires - expires) > 1 then
|
|
SetCooldownTimeLeft(buff.cd, timeleft)
|
|
buff.cdExpires = expires
|
|
end
|
|
buff.cdStart = nil
|
|
end
|
|
|
|
local function RefreshBuffButton(buff)
|
|
if buff.btype == "HELPFUL" then
|
|
if C.buffs.separateweapons == "1" then
|
|
buff.id = buff.gid - (buff.weapon ~= nil and buff.gid or 0)
|
|
else
|
|
buff.id = buff.gid - pfUI.buff.wepbuffs.count
|
|
end
|
|
else
|
|
buff.id = buff.gid
|
|
end
|
|
|
|
if not buff.backdrop then
|
|
CreateBackdrop(buff)
|
|
CreateBackdropShadow(buff)
|
|
end
|
|
|
|
local slots = buff.btype == "HELPFUL" and helpfulSlots or harmfulSlots
|
|
local name, icon, count, dispelType, duration, expirationTime, _, _, _, spellId = C_UnitAuras.UnitAuraBySlot("player", slots[buff.id])
|
|
|
|
--detect weapon buffs
|
|
if buff.btype == "HELPFUL" and ((C.buffs.separateweapons == "0" and buff.gid <= pfUI.buff.wepbuffs.count) or (pfUI.buff.wepbuffs.count > 0 and buff.weapon ~= nil)) then
|
|
local mh, mhtime, mhcharge, oh, ohtime, ohcharge = GetWeaponEnchantInfo()
|
|
if pfUI.buff.wepbuffs.count == 2 then
|
|
if buff.gid == 1 then
|
|
buff.mode = "MAINHAND"
|
|
else
|
|
buff.mode = "OFFHAND"
|
|
end
|
|
else
|
|
if C.buffs.separateweapons == "0" then
|
|
buff.mode = mh and "MAINHAND" or oh and "OFFHAND"
|
|
else
|
|
if buff.gid == 1 then
|
|
buff.mode = mh and "MAINHAND" or oh and "OFFHAND"
|
|
else
|
|
buff:Hide()
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Set Weapon Texture, Border and Timer
|
|
if buff.mode == "MAINHAND" then
|
|
buff.texture:SetTexture(GetInventoryItemTexture("player", 16))
|
|
buff.backdrop:SetBackdropBorderColor(GetItemQualityColor(GetInventoryItemQuality("player", 16) or 1))
|
|
RefreshWeaponButton(buff, mhtime, mhcharge)
|
|
elseif buff.mode == "OFFHAND" then
|
|
buff.texture:SetTexture(GetInventoryItemTexture("player", 17))
|
|
buff.backdrop:SetBackdropBorderColor(GetItemQualityColor(GetInventoryItemQuality("player", 17) or 1))
|
|
RefreshWeaponButton(buff, ohtime, ohcharge)
|
|
end
|
|
elseif name and (( buff.btype == "HARMFUL" and C.buffs.debuffs == "1" ) or ( buff.btype == "HELPFUL" and C.buffs.buffs == "1" )) then
|
|
-- Set Buff Texture and Border
|
|
buff.mode = buff.btype
|
|
buff.spellId = spellId
|
|
buff.texture:SetTexture(icon)
|
|
buff.stacks:SetText((count or 0) > 1 and count or "")
|
|
|
|
if buff.btype == "HARMFUL" then
|
|
local dispelColor = C_UnitAuras.GetAuraDispelTypeColor(dispelType)
|
|
buff.backdrop:SetBackdropBorderColor(dispelColor:GetRGBA())
|
|
else
|
|
buff.backdrop:SetBackdropBorderColor(br,bg,bb,ba)
|
|
end
|
|
|
|
-- start the timer from the aura's duration; permanent auras have none
|
|
local start, dur = GetAuraTimer(duration, expirationTime)
|
|
if dur <= 0 then
|
|
buff.cd:Clear()
|
|
buff.cdStart = nil
|
|
elseif buff.cdStart == nil or abs(buff.cdStart - start) > .5 or buff.cdDuration ~= dur then
|
|
CooldownFrame_SetTimer(buff.cd, start, dur, 1)
|
|
buff.cdStart = start
|
|
buff.cdDuration = dur
|
|
end
|
|
buff.cdExpires = nil
|
|
else
|
|
buff:Hide()
|
|
return
|
|
end
|
|
|
|
buff:Show()
|
|
end
|
|
|
|
local function CreateBuffButton(i, btype, weapon)
|
|
local buttonName, buttonParent
|
|
if btype == "HELPFUL" then
|
|
if weapon == 1 then
|
|
buttonName = "pfWepBuffFrame" .. i
|
|
buttonParent = pfUI.buff.wepbuffs
|
|
else
|
|
buttonName = "pfBuffFrameBuff" .. i
|
|
buttonParent = pfUI.buff.buffs
|
|
end
|
|
else
|
|
buttonName = "pfDebuffFrameBuff" .. i
|
|
buttonParent = pfUI.buff.debuffs
|
|
end
|
|
local buff = CreateFrame("Button", buttonName, buttonParent)
|
|
buff.texture = buff:CreateTexture("BuffIcon" .. i, "BACKGROUND")
|
|
buff.texture:SetTexCoord(.07,.93,.07,.93)
|
|
buff.texture:SetAllPoints(buff)
|
|
|
|
-- overlay lifts the stacks above the sweep: a child frame renders above
|
|
-- all of its parent's own regions, so they would dim under the dark
|
|
-- wedge otherwise
|
|
buff.overlay = CreateFrame("Frame", nil, buff)
|
|
buff.overlay:SetAllPoints(buff)
|
|
|
|
buff.stacks = buff.overlay:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
buff.stacks:SetTextColor(1,1,1,1)
|
|
buff.stacks:SetJustifyH("RIGHT")
|
|
buff.stacks:SetJustifyV("BOTTOM")
|
|
buff.stacks:SetAllPoints(buff)
|
|
|
|
-- the sweep and the duration numbers (the template covers the button and
|
|
-- starts hidden); RefreshBuffButton starts its timer
|
|
buff.cd = CreateCooldown(buff, "aura", C.buffs, "timers", buttonName .. "Cooldown")
|
|
buff.cd:SetFrameLevel(buff:GetFrameLevel() + 1)
|
|
buff.overlay:SetFrameLevel(buff:GetFrameLevel() + 2)
|
|
|
|
buff:RegisterForClicks("RightButtonUp")
|
|
|
|
buff.weapon = weapon
|
|
buff.btype = btype
|
|
buff.gid = i
|
|
|
|
-- PERF: OnUpdate moved to consolidated parent frame handler (see pfUI.buff:SetScript("OnUpdate"))
|
|
-- Individual buff frames no longer have their own OnUpdate
|
|
|
|
buff:SetScript("OnEnter", function()
|
|
GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT")
|
|
if this.mode == this.btype then
|
|
GameTooltip:SetUnitAura("player", this.id, this.btype)
|
|
|
|
if IsShiftKeyDown() then
|
|
local aura = C_UnitAuras.GetAuraDataByIndex("player", this.id, this.btype)
|
|
local playerlist = aura and GetUnbuffedRoster(aura.name) or ""
|
|
if strlen(playerlist) > 0 then
|
|
GameTooltip:AddLine(" ")
|
|
GameTooltip:AddLine(T["Unbuffed"] .. ":", .3, 1, .8)
|
|
GameTooltip:AddLine(playerlist,1,1,1,1)
|
|
GameTooltip:Show()
|
|
end
|
|
end
|
|
elseif this.mode == "MAINHAND" then
|
|
GameTooltip:SetInventoryItem("player", 16)
|
|
elseif this.mode == "OFFHAND" then
|
|
GameTooltip:SetInventoryItem("player", 17)
|
|
end
|
|
end)
|
|
|
|
buff:SetScript("OnLeave", GameTooltip_Hide)
|
|
|
|
buff:SetScript("OnClick", function()
|
|
if this.spellId then
|
|
C_Spell.CancelSpellByID(this.spellId)
|
|
end
|
|
end)
|
|
|
|
RefreshBuffButton(buff)
|
|
|
|
return buff
|
|
end
|
|
|
|
pfUI.buff = CreateFrame("Frame", "pfGlobalBuffFrame", UIParent)
|
|
pfUI.buff:RegisterEvent("PLAYER_AURAS_CHANGED")
|
|
pfUI.buff:RegisterEvent("PLAYER_EQUIPMENT_CHANGED")
|
|
pfUI.buff:RegisterUnitEvent("UNIT_MODEL_CHANGED", "player")
|
|
pfUI.buff:RegisterEvent("BUFF_UPDATE_DURATION_SELF")
|
|
pfUI.buff:RegisterEvent("DEBUFF_UPDATE_DURATION_SELF")
|
|
pfUI.buff:SetScript("OnEvent", function()
|
|
|
|
if C.buffs.weapons == "1" then
|
|
local mh, mhtime, mhcharge, oh, ohtime, ohcharge = GetWeaponEnchantInfo()
|
|
pfUI.buff.wepbuffs.count = (mh and 1 or 0) + (oh and 1 or 0)
|
|
else
|
|
pfUI.buff.wepbuffs.count = 0
|
|
end
|
|
|
|
ScanPlayerAuraSlots()
|
|
|
|
for i=1,32 do
|
|
RefreshBuffButton(pfUI.buff.buffs.buttons[i])
|
|
end
|
|
|
|
for i=1,16 do
|
|
RefreshBuffButton(pfUI.buff.debuffs.buttons[i])
|
|
end
|
|
|
|
if C.buffs.separateweapons == "1" then
|
|
for i=1,2 do
|
|
RefreshBuffButton(pfUI.buff.wepbuffs.buttons[i])
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- the buttons that can show a weapon enchant: the first two buffs, or the
|
|
-- separate weapon buttons
|
|
local weaponButtons
|
|
|
|
-- weapon enchants, see RefreshWeaponButton
|
|
pfUI.buff:SetScript("OnUpdate", function()
|
|
local now = GetTime()
|
|
if not this.nextUpdate then this.nextUpdate = now + 0.1 end
|
|
if this.nextUpdate > now then return end
|
|
this.nextUpdate = now + 0.1
|
|
|
|
local _, mhtime, mhcharge, _, ohtime, ohcharge = GetWeaponEnchantInfo()
|
|
for _, buff in ipairs(weaponButtons) do
|
|
if buff:IsShown() then
|
|
if buff.mode == "MAINHAND" then
|
|
RefreshWeaponButton(buff, mhtime, mhcharge)
|
|
elseif buff.mode == "OFFHAND" then
|
|
RefreshWeaponButton(buff, ohtime, ohcharge)
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- CreateBuffButton refreshes each new button from the slot buffers
|
|
ScanPlayerAuraSlots()
|
|
|
|
-- Weapon Buffs
|
|
pfUI.buff.wepbuffs = CreateFrame("Frame", "pfWepBuffFrame", UIParent)
|
|
pfUI.buff.wepbuffs.count = 0
|
|
pfUI.buff.wepbuffs.buttons = {}
|
|
for i=1,2 do
|
|
pfUI.buff.wepbuffs.buttons[i] = CreateBuffButton(i, "HELPFUL", 1)
|
|
end
|
|
|
|
-- Buff Frame
|
|
pfUI.buff.buffs = CreateFrame("Frame", "pfBuffFrame", UIParent)
|
|
pfUI.buff.buffs.buttons = {}
|
|
for i=1,32 do
|
|
pfUI.buff.buffs.buttons[i] = CreateBuffButton(i, "HELPFUL")
|
|
end
|
|
|
|
-- Debuffs
|
|
pfUI.buff.debuffs = CreateFrame("Frame", "pfDebuffFrame", UIParent)
|
|
pfUI.buff.debuffs.buttons = {}
|
|
for i=1,16 do
|
|
pfUI.buff.debuffs.buttons[i] = CreateBuffButton(i, "HARMFUL")
|
|
end
|
|
|
|
weaponButtons = {
|
|
pfUI.buff.buffs.buttons[1], pfUI.buff.buffs.buttons[2],
|
|
pfUI.buff.wepbuffs.buttons[1], pfUI.buff.wepbuffs.buttons[2],
|
|
}
|
|
|
|
-- config loading
|
|
function pfUI.buff:UpdateConfigBuffButton(buff)
|
|
local fontsize = C.buffs.fontsize == "-1" and C.global.font_size or C.buffs.fontsize
|
|
local buffSize, buffSpacing = tonumber(C.buffs.size), tonumber(C.buffs.spacing)
|
|
local rowextra = C.buffs.textinside == "1" and 0 or GetCooldownFontSize(buffSize) * 1.5
|
|
local rowcount, relFrame, offsetX, offsetY
|
|
if buff.btype == "HELPFUL" then
|
|
if buff.weapon == 1 and C.buffs.separateweapons == "1" then
|
|
rowcount = floor((buff.gid-1) / tonumber(C.buffs.wepbuffrowsize))
|
|
relFrame = pfUI.buff.wepbuffs
|
|
offsetX = -(buff.gid-1-rowcount*tonumber(C.buffs.wepbuffrowsize))*(buffSize+2*buffSpacing)
|
|
offsetY = -(rowcount) * (rowextra+buffSize+2*buffSpacing)
|
|
else
|
|
rowcount = floor((buff.gid-1) / tonumber(C.buffs.buffrowsize))
|
|
relFrame = pfUI.buff.buffs
|
|
offsetX = -(buff.gid-1-rowcount*tonumber(C.buffs.buffrowsize))*(buffSize+2*buffSpacing)
|
|
offsetY = -(rowcount) * (rowextra+buffSize+2*buffSpacing)
|
|
end
|
|
else
|
|
rowcount = floor((buff.gid-1) / tonumber(C.buffs.debuffrowsize))
|
|
relFrame = pfUI.buff.debuffs
|
|
offsetX = -(buff.gid-1-rowcount*tonumber(C.buffs.debuffrowsize))*(buffSize+2*buffSpacing)
|
|
offsetY = -(rowcount) * (rowextra+buffSize+2*buffSpacing)
|
|
end
|
|
buff:SetSize(buffSize, buffSize)
|
|
buff:ClearAllPoints()
|
|
buff:SetPoint("TOPRIGHT", relFrame, "TOPRIGHT",offsetX, offsetY)
|
|
|
|
buff.stacks:SetFont(pfUI.font_default, fontsize+1, "OUTLINE")
|
|
|
|
-- the duration numbers sit inside the icon or below it
|
|
local countdown = buff.cd:GetCountdownFontString()
|
|
countdown:ClearAllPoints()
|
|
if C.buffs.textinside == "1" then
|
|
countdown:SetPoint("CENTER", buff, "CENTER", 0, 0)
|
|
else
|
|
countdown:SetPoint("TOP", buff, "BOTTOM", 0, -3)
|
|
end
|
|
end
|
|
|
|
function pfUI.buff:UpdateConfig()
|
|
local spacing = tonumber(C.buffs.spacing)
|
|
local cell = tonumber(C.buffs.size) + 2 * spacing
|
|
local rowextra = C.buffs.textinside == "1" and 0 or GetCooldownFontSize(tonumber(C.buffs.size)) * 1.5
|
|
|
|
local function SizeBuffFrame(frame, rowsize, count)
|
|
rowsize = tonumber(rowsize)
|
|
frame:SetSize(rowsize * cell, ceil(count / rowsize) * (rowextra + cell))
|
|
end
|
|
|
|
SizeBuffFrame(pfUI.buff.buffs, C.buffs.buffrowsize, 32)
|
|
pfUI.buff.buffs:SetPoint("TOPRIGHT", pfUI.minimap or UIParent, "TOPLEFT", -4 * spacing, 0)
|
|
UpdateMovable(pfUI.buff.buffs)
|
|
|
|
SizeBuffFrame(pfUI.buff.debuffs, C.buffs.debuffrowsize, 16)
|
|
pfUI.buff.debuffs:SetPoint("TOPRIGHT", pfUI.buff.buffs, "BOTTOMRIGHT", 0, 0)
|
|
UpdateMovable(pfUI.buff.debuffs)
|
|
|
|
if C.buffs.separateweapons == "1" then
|
|
pfUI.buff.wepbuffs:ClearAllPoints()
|
|
SizeBuffFrame(pfUI.buff.wepbuffs, C.buffs.wepbuffrowsize, 2)
|
|
pfUI.buff.wepbuffs:SetPoint("TOPRIGHT", pfUI.buff.debuffs, "BOTTOMRIGHT", 0, 0)
|
|
pfUI.buff.wepbuffs:Show()
|
|
UpdateMovable(pfUI.buff.wepbuffs)
|
|
else
|
|
pfUI.buff.wepbuffs:Hide()
|
|
RemoveMovable(pfUI.buff.wepbuffs)
|
|
end
|
|
|
|
for i=1,32 do
|
|
pfUI.buff:UpdateConfigBuffButton(pfUI.buff.buffs.buttons[i])
|
|
end
|
|
|
|
for i=1,16 do
|
|
pfUI.buff:UpdateConfigBuffButton(pfUI.buff.debuffs.buttons[i])
|
|
end
|
|
|
|
for i=1,2 do
|
|
pfUI.buff:UpdateConfigBuffButton(pfUI.buff.wepbuffs.buttons[i])
|
|
end
|
|
|
|
pfUI.buff:GetScript("OnEvent")()
|
|
end
|
|
|
|
pfUI.buff:UpdateConfig()
|
|
end)
|