A Kobold Labourer
Join Date: Aug 2020
Posts: 1
|
Trying to add Pitbull support to BigDebuffs, refuses to work
Hi, as title suggests, I'm trying to add Pitbull support to BigDebuffs, however it refuses to work even though I've seemingly done it correctly.
I've added the Pitbull things on lines 285 through 293 and 372 through 383, however even though I precisely copied Shadowed Unit Frames' code and simply inserted the names of Pitbull frames instead. I'm honestly at a loss here, if there is a soul kind enough to offer some help you'd make me the happiest I can be today. Here's the code of the addon with the Pitbull bits I added. Thanks in advance!
Code:
-- BigDebuffs by Jordon
local addonName, addon = ...
BigDebuffs = LibStub("AceAddon-3.0"):NewAddon(addonName, "AceEvent-3.0", "AceHook-3.0")
local LibSharedMedia = LibStub("LibSharedMedia-3.0")
local LibClassicDurations = WOW_PROJECT_ID == WOW_PROJECT_CLASSIC and LibStub("LibClassicDurations")
if LibClassicDurations then LibClassicDurations:Register(addonName) end
-- Defaults
local defaults = {
profile = {
raidFrames = {
maxDebuffs = 1,
anchor = "INNER",
enabled = true,
cooldownCount = true,
cooldownFontSize = 10,
cooldownFontEffect = "OUTLINE",
cooldownFont = "Friz Quadrata TT",
showAllClassBuffs = true,
hideBliz = true,
redirectBliz = false,
increaseBuffs = false,
cc = 50,
dispellable = {
cc = 60,
roots = 50,
},
interrupts = 55,
roots = 40,
warning = 40,
default = 30,
special = 30,
pve = 50,
warningList = {
[212183] = true, -- Smoke Bomb
[81261] = true, -- Solar Beam
[233490] = true, -- Unstable Affliction
[34914] = true, -- Vampiric Touch
},
inRaid = {
hide = false,
size = 5
}
},
unitFrames = {
enabled = true,
cooldownCount = true,
cooldownFontSize = 16,
cooldownFontEffect = "OUTLINE",
cooldownFont = "Friz Quadrata TT",
tooltips = true,
player = {
enabled = true,
anchor = "auto",
size = 50,
},
target = {
enabled = true,
anchor = "auto",
size = 50,
},
pet = {
enabled = true,
anchor = "auto",
size = 50,
},
party = {
enabled = true,
anchor = "auto",
size = 50,
},
cc = true,
interrupts = true,
immunities = true,
immunities_spells = true,
buffs_defensive = true,
buffs_offensive = true,
buffs_other = true,
roots = true,
},
nameplates = {
enabled = true,
cooldownCount = true,
cooldownFontSize = 16,
cooldownFontEffect = "OUTLINE",
cooldownFont = "Friz Quadrata TT",
tooltips = true,
enemy = true,
friendly = true,
npc = true,
anchor = WOW_PROJECT_ID == WOW_PROJECT_CLASSIC and "TOP" or "RIGHT",
size = 40,
x = 0,
y = 0,
cc = true,
interrupts = true,
immunities = true,
immunities_spells = true,
buffs_defensive = true,
buffs_offensive = true,
buffs_other = true,
roots = true,
},
priority = {
immunities = 80,
immunities_spells = 70,
cc = 60,
interrupts = 55,
buffs_defensive = 50,
buffs_offensive = 40,
buffs_other = 30,
roots = 20,
special = 19,
},
spells = {},
}
}
BigDebuffs.WarningDebuffs = addon.WarningDebuffs or {}
BigDebuffs.Spells = addon.Spells
-- create a lookup table since CombatLogGetCurrentEventInfo() returns 0 for spellId
local spellIdByName
if WOW_PROJECT_ID == WOW_PROJECT_CLASSIC then
spellIdByName = {}
for id, value in pairs(BigDebuffs.Spells) do
if not value.parent then spellIdByName[GetSpellInfo(id)] = id end
end
local classDispel = {
PRIEST = {
Magic = true,
Disease = true,
},
MAGE = {
Curse = true,
},
PALADIN = {
Magic = true,
Poison = true,
Disease = true,
},
DRUID = {
Curse = true,
Poison = true,
},
SHAMAN = {
Disease = true,
Poison = true,
},
WARLOCK = {
-- Felhunter's Devour Magic or Doomguard's Dispel Magic
Magic = function() return IsUsableSpell(GetSpellInfo(19736)) or IsUsableSpell(GetSpellInfo(19476)) end,
},
}
BigDebuffs.dispelTypes = classDispel[select(2, UnitClass("player"))] or {}
else
defaults.profile.unitFrames.focus = {
enabled = true,
anchor = "auto",
size = 50,
}
defaults.profile.unitFrames.arena = {
enabled = true,
anchor = "auto",
size = 50,
}
BigDebuffs.specDispelTypes = {
[62] = { -- Arcane Mage
Curse = true,
},
[63] = { -- Fire Mage
Curse = true,
},
[64] = { -- Frost Mage
Curse = true,
},
[65] = { -- Holy Paladin
Magic = true,
Poison = true,
Disease = true,
},
[66] = { -- Protection Paladin
Poison = true,
Disease = true,
},
[70] = { -- Retribution Paladin
Poison = true,
Disease = true,
},
[102] = { -- Balance Druid
Curse = true,
Poison = true,
},
[103] = { -- Feral Druid
Curse = true,
Poison = true,
},
[104] = { -- Guardian Druid
Curse = true,
Poison = true,
},
[105] = { -- Restoration Druid
Magic = true,
Curse = true,
Poison = true,
},
[256] = { -- Discipline Priest
Magic = true,
Disease = true,
},
[257] = { -- Holy Priest
Magic = true,
Disease = true,
},
[258] = { -- Shadow Priest
Magic = true,
Disease = true,
},
[262] = { -- Elemental Shaman
Curse = true,
},
[263] = { -- Enhancement Shaman
Curse = true,
},
[264] = { -- Restoration Shaman
Magic = true,
Curse = true,
},
[268] = { -- Brewmaster Monk
Poison = true,
Disease = true,
},
[269] = { -- Windwalker Monk
Poison = true,
Disease = true,
},
[270] = { -- Mistweaver Monk
Magic = true,
Poison = true,
Disease = true,
},
[577] = {
Magic = function() return GetSpellInfo(205604) end, -- Reverse Magic
},
[581] = {
Magic = function() return GetSpellInfo(205604) end, -- Reverse Magic
},
}
end
BigDebuffs.PriorityDebuffs = addon.PriorityDebuffs
-- Store interrupt spellId and start time
BigDebuffs.units = {}
local units = addon.Units
local unitsWithRaid = {}
for i = 1, #units do
table.insert(unitsWithRaid, units[i])
end
for i = 1, 40 do
table.insert(unitsWithRaid, "raid" .. i)
end
local UnitDebuff, UnitBuff = UnitDebuff, UnitBuff
local GetAnchor = {
ShadowedUnitFrames = function(anchor)
local frame = _G[anchor]
if not frame then return end
if frame.portrait and frame.portrait:IsShown() then
return frame.portrait, frame
else
return frame, frame, true
end
end,
Pitbull = function(anchor)
local frame = _G[anchor]
if not frame then return end
if frame.portrait and frame.portrait:IsShown() then
return frame.portrait, frame
else
return frame, frame, true
end
end,
ZPerl = function(anchor)
local frame = _G[anchor]
if not frame then return end
if frame:IsShown() then
return frame, frame
else
frame = frame:GetParent()
return frame, frame, true
end
end,
}
local GetNameplateAnchor = {
ElvUINameplates = function(frame)
if frame.unitFrame and frame.unitFrame.Health and frame.unitFrame.Health:IsShown() then
return frame.unitFrame.Health, frame.unitFrame
elseif frame.unitFrame then
return frame.unitFrame, frame.unitFrame
end
end,
KuiNameplate = function(frame)
if frame.kui and frame.kui.HealthBar and frame.kui.HealthBar:IsShown() then
return frame.kui.HealthBar, frame.kui
elseif frame.kui and frame.kui.NameText and frame.kui.NameText:IsShown() then
return frame.kui.NameText, frame.kui
elseif frame.kui then
return frame.kui, frame.kui
end
end,
Plater = function(frame)
if frame.unitFrame and frame.unitFrame.healthBar and frame.unitFrame.healthBar:IsShown() then
return frame.unitFrame.healthBar, frame.unitFrame
elseif frame.unitFrame and frame.unitFrame.ActorNameSpecial and frame.unitFrame.ActorNameSpecial:IsShown() then
return frame.unitFrame.ActorNameSpecial, frame.unitFrame
elseif frame.unitFrame then
return frame.unitFrame, frame.unitFrame
end
end,
Blizzard = function(frame)
if WOW_PROJECT_ID == WOW_PROJECT_CLASSIC then
return frame.UnitFrame, frame.UnitFrame
end
if frame.UnitFrame and frame.UnitFrame.healthBar and frame.UnitFrame.healthBar:IsShown() then
return frame.UnitFrame.healthBar, frame.UnitFrame
elseif frame.UnitFrame and frame.UnitFrame.name and frame.UnitFrame.name:IsShown() then
return frame.UnitFrame.name, frame.UnitFrame
elseif frame.UnitFrame then
return frame.UnitFrame, frame.UnitFrame
end
end,
}
local nameplatesAnchors = {
[1] = {
used = function()
return ElvUI and ElvUI[1].NamePlates and ElvUI[1].NamePlates.Initialized
end,
func = GetNameplateAnchor.ElvUINameplates,
},
[2] = {
used = function()
return KuiNameplates ~= nil
end,
func = GetNameplateAnchor.KuiNameplate,
},
[3] = {
used = function()
return Plater ~= nil
end,
func = GetNameplateAnchor.Plater,
},
[4] = {
used = function(frame) return frame.UnitFrame ~= nil end,
func = GetNameplateAnchor.Blizzard,
},
}
local anchors = {
["Pitbull"] = {
units = {
player = "Pitbull4_Frames_Player",
pet = "Pitbull4_Frames_Player's pet",
target = "Pitbull4_Frames_Target",
focus = "Pitbull4_Frames_Focus",
party1 = "Pitbull4_Groups_PartyUnitButton1",
party2 = "Pitbull4_Groups_PartyUnitButton2",
party3 = "Pitbull4_Groups_PartyUnitButton3",
party4 = "Pitbull4_Groups_PartyUnitButton4",
},
},
["ElvUI"] = {
noPortait = true,
units = {
player = "ElvUF_Player",
pet = "ElvUF_Pet",
target = "ElvUF_Target",
focus = "ElvUF_Focus",
party1 = "ElvUF_PartyGroup1UnitButton1",
party2 = "ElvUF_PartyGroup1UnitButton2",
party3 = "ElvUF_PartyGroup1UnitButton3",
party4 = "ElvUF_PartyGroup1UnitButton4",
},
},
["bUnitFrames"] = {
noPortait = true,
alignLeft = true,
units = {
player = "bplayerUnitFrame",
pet = "bpetUnitFrame",
target = "btargetUnitFrame",
focus = "bfocusUnitFrame",
arena1 = "barena1UnitFrame",
arena2 = "barena2UnitFrame",
arena3 = "barena3UnitFrame",
arena4 = "barena4UnitFrame",
},
},
["Shadowed Unit Frames"] = {
func = GetAnchor.ShadowedUnitFrames,
units = {
player = "SUFUnitplayer",
pet = "SUFUnitpet",
target = "SUFUnittarget",
focus = "SUFUnitfocus",
party1 = "SUFHeaderpartyUnitButton1",
party2 = "SUFHeaderpartyUnitButton2",
party3 = "SUFHeaderpartyUnitButton3",
party4 = "SUFHeaderpartyUnitButton4",
},
},
["ZPerl"] = {
func = GetAnchor.ZPerl,
units = {
player = "XPerl_PlayerportraitFrame",
pet = "XPerl_Player_PetportraitFrame",
target = "XPerl_TargetportraitFrame",
focus = "XPerl_FocusportraitFrame",
party1 = "XPerl_party1portraitFrame",
party2 = "XPerl_party2portraitFrame",
party3 = "XPerl_party3portraitFrame",
party4 = "XPerl_party4portraitFrame",
},
},
["Blizzard"] = {
units = {
player = "PlayerPortrait",
pet = "PetPortrait",
target = "TargetFramePortrait",
focus = "FocusFramePortrait",
party1 = "PartyMemberFrame1Portrait",
party2 = "PartyMemberFrame2Portrait",
party3 = "PartyMemberFrame3Portrait",
party4 = "PartyMemberFrame4Portrait",
arena1 = "ArenaEnemyFrame1ClassPortrait",
arena2 = "ArenaEnemyFrame2ClassPortrait",
arena3 = "ArenaEnemyFrame3ClassPortrait",
arena4 = "ArenaEnemyFrame4ClassPortrait",
arena5 = "ArenaEnemyFrame5ClassPortrait",
},
},
}
function BigDebuffs:OnInitialize()
self.db = LibStub("AceDB-3.0"):New("BigDebuffsDB", defaults, true)
-- Upgrade old database
if type(self.db.profile.raidFrames.dispellable) == "number" then
self.db.profile.raidFrames.dispellable = {
cc = self.db.profile.raidFrames.dispellable,
roots = self.db.profile.raidFrames.roots
}
end
for i = 1, #units do
local key = units[i]:gsub("%d", "")
if type(self.db.profile.unitFrames[key]) == "boolean" then
self.db.profile.unitFrames[key] = {
enabled = self.db.profile.unitFrames[key],
anchor = "auto",
}
end
end
if self.db.profile.raidFrames.showAllClassBuffs == nil then
self.db.profile.raidFrames.showAllClassBuffs = true
end
self.db.RegisterCallback(self, "OnProfileChanged", "Refresh")
self.db.RegisterCallback(self, "OnProfileCopied", "Refresh")
self.db.RegisterCallback(self, "OnProfileReset", "Refresh")
self.frames = {}
self.UnitFrames = {}
self.Nameplates = {}
self:SetupOptions()
end
local function HideBigDebuffs(frame)
if not frame.BigDebuffs then return end
for i = 1, #frame.BigDebuffs do
frame.BigDebuffs[i]:Hide()
end
end
function BigDebuffs:Refresh()
for frame, _ in pairs(self.frames) do
if frame:IsVisible() then CompactUnitFrame_UpdateAuras(frame) end
if frame and frame.BigDebuffs then self:AddBigDebuffs(frame) end
end
for unit, frame in pairs(self.UnitFrames) do
frame:Hide()
frame.current = nil
if self.db.profile.unitFrames.cooldownCount then
local text = frame.cooldown:GetRegions()
if text then
text:SetFont(LibSharedMedia:Fetch("font", BigDebuffs.db.profile.unitFrames.cooldownFont),
self.db.profile.unitFrames.cooldownFontSize, self.db.profile.unitFrames.cooldownFontEffect)
end
end
frame.cooldown:SetHideCountdownNumbers(not self.db.profile.unitFrames.cooldownCount)
frame.cooldown.noCooldownCount = not self.db.profile.unitFrames.cooldownCount
self:UNIT_AURA(unit)
end
for unit, frame in pairs(self.Nameplates) do
frame:Hide()
frame.current = nil
if self.db.profile.unitFrames.cooldownCount then
local text = frame.cooldown:GetRegions()
if text then
text:SetFont(LibSharedMedia:Fetch("font", BigDebuffs.db.profile.unitFrames.cooldownFont),
self.db.profile.unitFrames.cooldownFontSize, self.db.profile.unitFrames.cooldownFontEffect)
end
end
frame.cooldown:SetHideCountdownNumbers(not self.db.profile.unitFrames.cooldownCount)
frame.cooldown.noCooldownCount = not self.db.profile.unitFrames.cooldownCount
self:UNIT_AURA_NAMEPLATE(unit)
end
end
function BigDebuffs:AttachUnitFrame(unit)
if InCombatLockdown() then return end
local frame = self.UnitFrames[unit]
local frameName = addonName .. unit .. "UnitFrame"
if not frame then
frame = CreateFrame("Button", frameName, UIParent, "BigDebuffsUnitFrameTemplate")
self.UnitFrames[unit] = frame
frame:SetScript("OnEvent", function() self:UNIT_AURA(unit) end)
if self.db.profile.unitFrames.cooldownCount then
local text = frame.cooldown:GetRegions()
if text then
text:SetFont(LibSharedMedia:Fetch("font", BigDebuffs.db.profile.unitFrames.cooldownFont),
self.db.profile.unitFrames.cooldownFontSize, self.db.profile.unitFrames.cooldownFontEffect)
end
end
frame.cooldown:SetHideCountdownNumbers(not self.db.profile.unitFrames.cooldownCount)
frame.cooldown.noCooldownCount = not self.db.profile.unitFrames.cooldownCount
frame.icon:SetDrawLayer("BORDER")
frame:RegisterUnitEvent("UNIT_AURA", unit)
frame:RegisterForDrag("LeftButton")
frame:SetMovable(true)
frame.unit = unit
end
frame:EnableMouse(self.test)
_G[frameName.."Name"]:SetText(self.test and not frame.anchor and unit)
frame.anchor = nil
frame.blizzard = nil
local config = self.db.profile.unitFrames[unit:gsub("%d", "")]
if config.anchor == "auto" then
-- Find a frame to attach to
for k,v in pairs(anchors) do
local anchor, parent, noPortait
if v.units[unit] then
if v.func then
anchor, parent, noPortait = v.func(v.units[unit])
else
anchor = _G[v.units[unit]]
end
if anchor then
frame.anchor, frame.parent, frame.noPortait = anchor, parent, noPortait
if v.noPortait then frame.noPortait = true end
frame.alignLeft = v.alignLeft
frame.blizzard = k == "Blizzard"
if not frame.blizzard then break end
end
end
end
end
if frame.anchor then
if frame.blizzard then
-- Blizzard Frame
frame:SetParent(frame.anchor:GetParent())
frame:SetFrameLevel(frame.anchor:GetParent():GetFrameLevel())
frame.cooldown:SetFrameLevel(frame.anchor:GetParent():GetFrameLevel())
frame.anchor:SetDrawLayer("BACKGROUND")
frame.cooldown:SetSwipeTexture("Interface\\CHARACTERFRAME\\TempPortraitAlphaMaskSmall")
else
frame:SetParent(frame.parent and frame.parent or frame.anchor)
frame:SetFrameLevel(99)
end
frame:ClearAllPoints()
if frame.noPortait then
-- No portrait, so attach to the side
if frame.alignLeft then
frame:SetPoint("TOPRIGHT", frame.anchor, "TOPLEFT")
else
frame:SetPoint("TOPLEFT", frame.anchor, "TOPRIGHT")
end
local height = frame.anchor:GetHeight()
frame:SetSize(height, height)
else
frame:SetAllPoints(frame.anchor)
end
else
-- Manual
frame:SetParent(UIParent)
frame:ClearAllPoints()
if not self.db.profile.unitFrames[unit] then self.db.profile.unitFrames[unit] = {} end
if self.db.profile.unitFrames[unit].position then
frame:SetPoint(unpack(self.db.profile.unitFrames[unit].position))
else
-- No saved position, anchor to the blizzard position
if WOW_PROJECT_ID ~= WOW_PROJECT_CLASSIC then LoadAddOn("Blizzard_ArenaUI") end
local relativeFrame = _G[anchors.Blizzard.units[unit]] or UIParent
frame:SetPoint("CENTER", relativeFrame, "CENTER")
end
frame:SetSize(config.size, config.size)
end
end
function BigDebuffs:AttachNameplate(unit)
if InCombatLockdown() then return end
local frame = self.Nameplates[unit]
local config = self.db.profile.nameplates
if config.cooldownCount then
local text = frame.cooldown:GetRegions()
if text then
text:SetFont(LibSharedMedia:Fetch("font", config.cooldownFont),
config.cooldownFontSize, config.cooldownFontEffect)
end
end
frame.cooldown:SetHideCountdownNumbers(not config.cooldownCount)
frame.cooldown.noCooldownCount = not config.cooldownCount
frame:EnableMouse(config.tooltips)
frame:ClearAllPoints()
if config.anchor == "RIGHT" then
frame:SetPoint("LEFT", frame.anchor, "RIGHT", config.x, config.y)
elseif config.anchor == "TOP" then
frame:SetPoint("BOTTOM", frame.anchor, "TOP", config.x, config.y)
elseif config.anchor == "LEFT" then
frame:SetPoint("RIGHT", frame.anchor, "LEFT", config.x, config.y)
elseif config.anchor == "BOTTOM" then
frame:SetPoint("TOP", frame.anchor, "BOTTOM", config.x, config.y)
end
frame:SetSize(config.size, config.size)
end
function BigDebuffs:SaveUnitFramePosition(frame)
self.db.profile.unitFrames[frame.unit].position = { frame:GetPoint() }
end
function BigDebuffs:Test()
self.test = not self.test
self:Refresh()
end
local TestDebuffs = {}
local function InsertTestDebuff(spellID, dispelType)
local texture = GetSpellTexture(spellID)
table.insert(TestDebuffs, { spellID, texture, 0, dispelType })
end
local function UnitDebuffTest(unit, index)
local debuff = TestDebuffs[index]
if not debuff then return end
-- name, icon, count, debuffType, duration, expirationTime, unitCaster, canStealOrPurge, _, spellId
return "Test", debuff[2], 0, debuff[4], 60, GetTime() + 60, nil, nil, nil, debuff[1]
end
function BigDebuffs:OnEnable()
self:RegisterEvent("PLAYER_REGEN_ENABLED")
self:RegisterEvent("PLAYER_TARGET_CHANGED")
self:RegisterEvent("UNIT_PET")
self:RegisterEvent("PLAYER_ENTERING_WORLD")
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
self:RegisterEvent("NAME_PLATE_UNIT_ADDED")
self:RegisterEvent("NAME_PLATE_UNIT_REMOVED")
if WOW_PROJECT_ID ~= WOW_PROJECT_CLASSIC then
self:RegisterEvent("PLAYER_TALENT_UPDATE")
self:RegisterEvent("PLAYER_FOCUS_CHANGED")
self:PLAYER_TALENT_UPDATE()
end
InsertTestDebuff(8122, "Magic") -- Psychic Scream
InsertTestDebuff(408, nil) -- Kidney Shot
if WOW_PROJECT_ID ~= WOW_PROJECT_CLASSIC then
InsertTestDebuff(233490, "Magic") -- Unstable Affliction
InsertTestDebuff(114404, nil) -- Void Tendrils
end
InsertTestDebuff(339, "Magic") -- Entangling Roots
InsertTestDebuff(589, "Magic") -- Shadow Word: Pain
InsertTestDebuff(589, "Magic") -- Shadow Word: Pain
InsertTestDebuff(589, "Magic") -- Shadow Word: Pain
InsertTestDebuff(589, "Magic") -- Shadow Word: Pain
InsertTestDebuff(772, nil) -- Rend
end
function BigDebuffs:PLAYER_ENTERING_WORLD()
for i = 1, #units do
self:AttachUnitFrame(units[i])
end
end
local function UnitBuffByName(unit, name)
for i = 1, 40 do
local n = UnitBuff(unit, i)
if n == name then return true end
end
end
function BigDebuffs:COMBAT_LOG_EVENT_UNFILTERED()
local _, event, _,_,_,_,_, destGUID, _,_,_, spellId, spellName = CombatLogGetCurrentEventInfo()
-- SPELL_INTERRUPT doesn't fire for some channeled spells
if event ~= "SPELL_INTERRUPT" and event ~= "SPELL_CAST_SUCCESS" then return end
if spellId == 0 then spellId = spellIdByName[spellName] end
local spell = self.Spells[spellId]
if not spell then return end
local spellType = spell.parent and self.Spells[spell.parent].type or spell.type
if spellType ~= "interrupts" then return end
-- Find unit
for i = 1, #unitsWithRaid do
local unit = unitsWithRaid[i]
if destGUID == UnitGUID(unit) and (event ~= "SPELL_CAST_SUCCESS" or
(UnitChannelInfo and select(7, UnitChannelInfo(unit)) == false))
then
local duration = spell.parent and self.Spells[spell.parent].duration or spell.duration
local _, class = UnitClass(unit)
if UnitBuffByName(unit, "Calming Waters") then
duration = duration * 0.5
end
self.units[destGUID] = self.units[destGUID] or {}
self.units[destGUID].expires = GetTime() + duration
self.units[destGUID].spellId = spellId
self.units[destGUID].duration = duration
self.units[destGUID].spellId = spell.parent and spell.parent or spellId
-- Make sure we clear it after the duration
C_Timer.After(duration, function()
self:UNIT_AURA_ALL_UNITS()
end)
self:UNIT_AURA_ALL_UNITS()
return
end
end
end
function BigDebuffs:UNIT_AURA_ALL_UNITS()
for i = 1, #unitsWithRaid do
local unit = unitsWithRaid[i]
if self.AttachedFrames[unit] then
self:ShowBigDebuffs(self.AttachedFrames[unit])
end
if not unit:match("^raid") and not unit:find("nameplate") then
self:UNIT_AURA(unit)
end
if unit:find("nameplate") then
self:UNIT_AURA_NAMEPLATE(unit)
end
end
end
BigDebuffs.AttachedFrames = {}
local MAX_BUFFS = 6
function BigDebuffs:AddBigDebuffs(frame)
if not frame or not frame.displayedUnit or not UnitIsPlayer(frame.displayedUnit) then return end
local frameName = frame:GetName()
if self.db.profile.raidFrames.increaseBuffs then
for i = 4, MAX_BUFFS do
local buffPrefix = frameName .. "Buff"
local buffFrame = _G[buffPrefix .. i] or
CreateFrame("Button", buffPrefix .. i, frame, "CompactBuffTemplate")
buffFrame:ClearAllPoints()
buffFrame:SetSize(frame.buffFrames[1]:GetSize())
if math.fmod(i - 1, 3) == 0 then
buffFrame:SetPoint("BOTTOMRIGHT", _G[buffPrefix .. i - 3], "TOPRIGHT")
else
buffFrame:SetPoint("BOTTOMRIGHT", _G[buffPrefix .. i - 1], "BOTTOMLEFT")
end
end
end
self.AttachedFrames[frame.displayedUnit] = frame
frame.BigDebuffs = frame.BigDebuffs or {}
local max = self.db.profile.raidFrames.maxDebuffs + 1 -- add a frame for warning debuffs
for i = 1, max do
local big = frame.BigDebuffs[i] or
CreateFrame("Button", frameName .. "BigDebuffsRaid" .. i, frame, "CompactDebuffTemplate")
big:ClearAllPoints()
if i > 1 then
if self.db.profile.raidFrames.anchor == "INNER" then
big:SetPoint("BOTTOMLEFT", frame.BigDebuffs[i-1], "BOTTOMRIGHT", 0, 0)
elseif self.db.profile.raidFrames.anchor == "LEFT" then
big:SetPoint("BOTTOMRIGHT", frame.BigDebuffs[i-1], "BOTTOMLEFT", 0, 0)
elseif self.db.profile.raidFrames.anchor == "RIGHT" then
big:SetPoint("BOTTOMLEFT", frame.BigDebuffs[i-1], "BOTTOMRIGHT", 0, 0)
end
else
if self.db.profile.raidFrames.anchor == "INNER" then
big:SetPoint("BOTTOMLEFT", frame.debuffFrames[1], "BOTTOMLEFT", 0, 0)
elseif self.db.profile.raidFrames.anchor == "LEFT" then
big:SetPoint("BOTTOMRIGHT", frame, "BOTTOMLEFT", 0, 1)
elseif self.db.profile.raidFrames.anchor == "RIGHT" then
big:SetPoint("BOTTOMLEFT", frame, "BOTTOMRIGHT", 0, 1)
end
end
big.cooldown:SetHideCountdownNumbers(not self.db.profile.raidFrames.cooldownCount)
big.cooldown.noCooldownCount = not self.db.profile.raidFrames.cooldownCount
big.cooldown:SetDrawEdge(false)
frame.BigDebuffs[i] = big
big:Hide()
self.frames[frame] = true
self:ShowBigDebuffs(frame)
end
return true
end
local pending = {}
hooksecurefunc("CompactUnitFrame_UpdateAll", function(frame)
if not BigDebuffs.db.profile.raidFrames.enabled then return end
if frame:IsForbidden() then return end
local name = frame:GetName()
if not name or not name:match("^Compact") then return end
if InCombatLockdown() and not frame.BigDebuffs then
if not pending[frame] then pending[frame] = true end
else
BigDebuffs:AddBigDebuffs(frame)
end
end)
if WOW_PROJECT_ID ~= WOW_PROJECT_CLASSIC then
function BigDebuffs:PLAYER_TALENT_UPDATE()
local specID = GetSpecializationInfo(GetSpecialization() or 1)
self.specDispel = specID and self.specDispelTypes[specID] and self.specDispelTypes[specID]
end
end
function BigDebuffs:PLAYER_REGEN_ENABLED()
for frame,_ in pairs(pending) do
BigDebuffs:AddBigDebuffs(frame)
pending[frame] = nil
end
end
function BigDebuffs:IsPriorityDebuff(id)
for i = 1, #BigDebuffs.PriorityDebuffs do
if id == BigDebuffs.PriorityDebuffs[i] then
return true
end
end
end
hooksecurefunc("CompactUnitFrame_HideAllDebuffs", HideBigDebuffs)
function BigDebuffs:IsDispellable(unit, dispelType)
if WOW_PROJECT_ID == WOW_PROJECT_CLASSIC then
-- if stoneform is usable and it's on player
if not dispelType then return end
if type(self.dispelTypes[dispelType]) == "function" then return self.dispelTypes[dispelType]() end
-- dwarves can use Stoneform to remove diseases and poisons
if (not self.dispelTypes[dispelType]) and
unit == "player" and
(dispelType == "Poison" or dispelType == "Disease")
then
return IsUsableSpell("Stoneform")
end
return self.dispelTypes[dispelType]
else
if not dispelType or not self.specDispel then return end
if type(self.specDispel[dispelType]) == "function" then return self.specDispel[dispelType]() end
return self.specDispel[dispelType]
end
end
function BigDebuffs:GetDebuffSize(id, dispellable)
if self.db.profile.raidFrames.pve > 0 then
local _, instanceType = IsInInstance()
if dispellable and instanceType and (instanceType == "raid" or instanceType == "party") then
return self.db.profile.raidFrames.pve
end
end
if not self.Spells[id] then return end
id = self.Spells[id].parent or id -- Check for parent spellID
local category = self.Spells[id].type
if not category or not self.db.profile.raidFrames[category] then return end
-- Check for user set
if self.db.profile.spells[id] then
if self.db.profile.spells[id].raidFrames and self.db.profile.spells[id].raidFrames == 0 then return end
if self.db.profile.spells[id].size then return self.db.profile.spells[id].size end
end
if self.Spells[id].noraidFrames and
(not self.db.profile.spells[id] or not self.db.profile.spells[id].raidFrames)
then
return
end
local dispellableSize = self.db.profile.raidFrames.dispellable[category]
if dispellable and dispellableSize and dispellableSize > 0 then return dispellableSize end
if self.db.profile.raidFrames[category] > 0 then
return self.db.profile.raidFrames[category]
end
end
-- For raid frames
function BigDebuffs:GetDebuffPriority(id)
if not self.Spells[id] then return 0 end
id = self.Spells[id].parent or id -- Check for parent spellID
return self.db.profile.spells[id] and self.db.profile.spells[id].priority or
self.db.profile.priority[self.Spells[id].type] or 0
end
-- For unit frames
function BigDebuffs:GetAuraPriority(id)
if not self.Spells[id] then return end
id = self.Spells[id].parent or id -- Check for parent spellID
-- Make sure category is enabled
if not self.db.profile.unitFrames[self.Spells[id].type] then return end
-- Check for user set
if self.db.profile.spells[id] then
if self.db.profile.spells[id].unitFrames and self.db.profile.spells[id].unitFrames == 0 then return end
if self.db.profile.spells[id].priority then return self.db.profile.spells[id].priority end
end
if self.Spells[id].nounitFrames and
(not self.db.profile.spells[id] or not self.db.profile.spells[id].unitFrames)
then
return
end
return self.db.profile.priority[self.Spells[id].type] or 0
end
-- For nameplates
function BigDebuffs:GetNameplatesPriority(id)
if not self.Spells[id] then return end
id = self.Spells[id].parent or id -- Check for parent spellID
-- Make sure category is enabled
if not self.db.profile.nameplates[self.Spells[id].type] then return end
-- Check for user set
if self.db.profile.spells[id] then
if self.db.profile.spells[id].nameplates and self.db.profile.spells[id].nameplates == 0 then return end
if self.db.profile.spells[id].priority then return self.db.profile.spells[id].priority end
end
if self.Spells[id].nounitFrames and
(not self.db.profile.spells[id] or not self.db.profile.spells[id].nameplates)
then
return
end
return self.db.profile.priority[self.Spells[id].type] or 0
end
if LibClassicDurations then
hooksecurefunc("CompactUnitFrame_UtilSetBuff", function(buffFrame, unit, index, filter)
if not LibClassicDurations then return end
local name, icon, count, debuffType, duration, expirationTime, unitCaster,
canStealOrPurge, _, spellId, canApplyAura = UnitBuff(unit, index, filter);
local durationNew, expirationTimeNew = LibClassicDurations:GetAuraDurationByUnit(unit, spellId, unitCaster)
if duration == 0 and durationNew then
duration = durationNew
expirationTime = expirationTimeNew
end
local enabled = expirationTime and expirationTime ~= 0;
if enabled then
local startTime = expirationTime - duration;
CooldownFrame_Set(buffFrame.cooldown, startTime, duration, true);
else
CooldownFrame_Clear(buffFrame.cooldown);
end
end)
end
local function CompactUnitFrame_UtilSetDebuff(debuffFrame, unit, index, filter, isBossAura, isBossBuff, ...)
local UnitDebuff = BigDebuffs.test and UnitDebuffTest or UnitDebuff
-- make sure you are using the correct index here!
--isBossAura says make this look large.
--isBossBuff looks in HELPFULL auras otherwise it looks in HARMFULL ones
local name, icon, count, debuffType, duration, expirationTime, unitCaster, _, _, spellId = ...;
if index == -1 then
-- it's an interrupt
local spell = BigDebuffs.units[UnitGUID(unit)]
spellId = spell.spellId
icon = GetSpellTexture(spellId)
count = 1
duration = spell.duration
expirationTime = spell.expires
else
if name == nil then
-- for backwards compatibility - this functionality will be removed in a future update
if unit then
if (isBossBuff) then
name, icon, count, debuffType, duration, expirationTime, unitCaster, _, _, spellId = UnitBuff(unit, index, filter);
else
name, icon, count, debuffType, duration, expirationTime, unitCaster, _, _, spellId = UnitDebuff(unit, index, filter);
end
else
return;
end
end
end
debuffFrame.filter = filter;
debuffFrame.icon:SetTexture(icon);
if ( count > 1 ) then
local countText = count;
if ( count >= 100 ) then
countText = BUFF_STACKS_OVERFLOW;
end
debuffFrame.count:Show();
debuffFrame.count:SetText(countText);
else
debuffFrame.count:Hide();
end
debuffFrame:SetID(index);
if LibClassicDurations then
local durationNew, expirationTimeNew = LibClassicDurations:GetAuraDurationByUnit(unit, spellId, unitCaster)
if duration == 0 and durationNew then
duration = durationNew
expirationTime = expirationTimeNew
end
end
local enabled = expirationTime and expirationTime ~= 0;
if enabled then
local startTime = expirationTime - duration;
local text = debuffFrame.cooldown:GetRegions();
text:SetFont(LibSharedMedia:Fetch("font", BigDebuffs.db.profile.raidFrames.cooldownFont),
BigDebuffs.db.profile.raidFrames.cooldownFontSize, BigDebuffs.db.profile.raidFrames.cooldownFontEffect);
CooldownFrame_Set(debuffFrame.cooldown, startTime, duration, true);
else
CooldownFrame_Clear(debuffFrame.cooldown);
end
local color = DebuffTypeColor[debuffType] or DebuffTypeColor["none"];
debuffFrame.border:SetVertexColor(color.r, color.g, color.b);
debuffFrame.isBossBuff = isBossBuff;
if ( isBossAura ) then
local size = min(debuffFrame.baseSize + BOSS_DEBUFF_SIZE_INCREASE, debuffFrame.maxHeight);
debuffFrame:SetSize(size, size);
else
debuffFrame:SetSize(debuffFrame.baseSize, debuffFrame.baseSize);
end
debuffFrame:Show();
end
if WOW_PROJECT_ID == WOW_PROJECT_CLASSIC then
local Default_CompactUnitFrame_UtilIsPriorityDebuff = CompactUnitFrame_UtilIsPriorityDebuff
local function CompactUnitFrame_UtilIsPriorityDebuff(...)
local _,_,_,_,_,_,_,_,_, spellId = UnitDebuff(...)
return BigDebuffs:IsPriorityDebuff(spellId) or Default_CompactUnitFrame_UtilIsPriorityDebuff(...)
end
local Default_SpellGetVisibilityInfo = SpellGetVisibilityInfo
local function CompactUnitFrame_UtilShouldDisplayBuff(unit, index, filter)
local name, icon, count, debuffType, duration, expirationTime, unitCaster, canStealOrPurge, _, spellId, canApplyAura = UnitBuff(unit, index, filter);
local hasCustom, alwaysShowMine, showForMySpec = SpellGetVisibilityInfo(spellId, UnitAffectingCombat("player") and "RAID_INCOMBAT" or "RAID_OUTOFCOMBAT");
local showAllClassBuffs = BigDebuffs.db.profile.raidFrames.showAllClassBuffs and canApplyAura
if ( hasCustom ) then
return showForMySpec or (alwaysShowMine and (showAllClassBuffs or unitCaster == "player" or unitCaster == "pet" or unitCaster == "vehicle"));
else
return (showAllClassBuffs or unitCaster == "player" or unitCaster == "pet" or unitCaster == "vehicle") and canApplyAura and not SpellIsSelfBuff(spellId);
end
end
local function CompactUnitFrame_UtilShouldDisplayDebuff(unit, index, filter)
local name, icon, count, debuffType, duration, expirationTime, unitCaster, canStealOrPurge, _, spellId, canApplyAura, isBossAura = UnitDebuff(unit, index, filter);
local hasCustom, alwaysShowMine, showForMySpec = SpellGetVisibilityInfo(spellId, UnitAffectingCombat("player") and "RAID_INCOMBAT" or "RAID_OUTOFCOMBAT");
local showAllClassBuffs = BigDebuffs.db.profile.raidFrames.showAllClassBuffs and canApplyAura
if ( hasCustom ) then
return showForMySpec or (alwaysShowMine and (showAllClassBuffs or unitCaster == "player" or unitCaster == "pet" or unitCaster == "vehicle") ); --Would only be "mine" in the case of something like forbearance.
else
return true;
end
end
hooksecurefunc("CompactUnitFrame_UpdateDebuffs", function(frame)
if ( not frame.debuffFrames or not frame.optionTable.displayDebuffs ) then
CompactUnitFrame_HideAllDebuffs(frame);
return;
end
local index = 1;
local frameNum = 1;
local filter = nil;
local maxDebuffs = frame.maxDebuffs;
--Show both Boss buffs & debuffs in the debuff location
--First, we go through all the debuffs looking for any boss flagged ones.
while ( frameNum <= maxDebuffs ) do
local debuffName = UnitDebuff(frame.displayedUnit, index, filter);
if ( debuffName ) then
if ( CompactUnitFrame_UtilIsBossAura(frame.displayedUnit, index, filter, false) ) then
local debuffFrame = frame.debuffFrames[frameNum];
CompactUnitFrame_UtilSetDebuff(debuffFrame, frame.displayedUnit, index, filter, true, false);
frameNum = frameNum + 1;
--Boss debuffs are about twice as big as normal debuffs, so display one less.
local bossDebuffScale = (debuffFrame.baseSize + BOSS_DEBUFF_SIZE_INCREASE)/debuffFrame.baseSize
maxDebuffs = maxDebuffs - (bossDebuffScale - 1);
end
else
break;
end
index = index + 1;
end
--Then we go through all the buffs looking for any boss flagged ones.
index = 1;
while ( frameNum <= maxDebuffs ) do
local debuffName = UnitBuff(frame.displayedUnit, index, filter);
if ( debuffName ) then
if ( CompactUnitFrame_UtilIsBossAura(frame.displayedUnit, index, filter, true) ) then
local debuffFrame = frame.debuffFrames[frameNum];
CompactUnitFrame_UtilSetDebuff(debuffFrame, frame.displayedUnit, index, filter, true, true);
frameNum = frameNum + 1;
--Boss debuffs are about twice as big as normal debuffs, so display one less.
local bossDebuffScale = (debuffFrame.baseSize + BOSS_DEBUFF_SIZE_INCREASE)/debuffFrame.baseSize
maxDebuffs = maxDebuffs - (bossDebuffScale - 1);
end
else
break;
end
index = index + 1;
end
--Now we go through the debuffs with a priority (e.g. Weakened Soul and Forbearance)
index = 1;
while ( frameNum <= maxDebuffs ) do
local debuffName = UnitDebuff(frame.displayedUnit, index, filter);
if ( debuffName ) then
if ( CompactUnitFrame_UtilIsPriorityDebuff(frame.displayedUnit, index, filter) ) then
local debuffFrame = frame.debuffFrames[frameNum];
CompactUnitFrame_UtilSetDebuff(debuffFrame, frame.displayedUnit, index, filter, false, false);
frameNum = frameNum + 1;
end
else
break;
end
index = index + 1;
end
if ( frame.optionTable.displayOnlyDispellableDebuffs ) then
filter = "RAID";
end
index = 1;
--Now, we display all normal debuffs.
if ( frame.optionTable.displayNonBossDebuffs ) then
while ( frameNum <= maxDebuffs ) do
local debuffName = UnitDebuff(frame.displayedUnit, index, filter);
if ( debuffName ) then
if ( CompactUnitFrame_UtilShouldDisplayDebuff(frame.displayedUnit, index, filter) and not CompactUnitFrame_UtilIsBossAura(frame.displayedUnit, index, filter, false) and
not CompactUnitFrame_UtilIsPriorityDebuff(frame.displayedUnit, index, filter)) then
local debuffFrame = frame.debuffFrames[frameNum];
CompactUnitFrame_UtilSetDebuff(debuffFrame, frame.displayedUnit, index, filter, false, false);
frameNum = frameNum + 1;
end
else
break;
end
index = index + 1;
end
end
for i=frameNum, frame.maxDebuffs do
local debuffFrame = frame.debuffFrames[i];
debuffFrame:Hide();
end
BigDebuffs:ShowBigDebuffs(frame)
end)
-- Show extra buffs
local MAX_BUFFS = 6
hooksecurefunc("CompactUnitFrame_UpdateBuffs", function(frame)
if ( not frame.buffFrames or not frame.optionTable.displayBuffs ) then
CompactUnitFrame_HideAllBuffs(frame);
return;
end
if not UnitIsPlayer(frame.displayedUnit) then
return
end
if (not BigDebuffs.db.profile.raidFrames.increaseBuffs) and
(not BigDebuffs.db.profile.raidFrames.showAllClassBuffs)
then
return
end
local maxBuffs = BigDebuffs.db.profile.raidFrames.increaseBuffs and MAX_BUFFS or frame.maxBuffs
local index = 1;
local frameNum = 1;
local filter = nil;
while ( frameNum <= maxBuffs ) do
local buffName = UnitBuff(frame.displayedUnit, index, filter);
if ( buffName ) then
if ( CompactUnitFrame_UtilShouldDisplayBuff(frame.displayedUnit, index, filter) and
not CompactUnitFrame_UtilIsBossAura(frame.displayedUnit, index, filter, true) )
then
local buffFrame = frame.buffFrames[frameNum];
if buffFrame then
CompactUnitFrame_UtilSetBuff(buffFrame, frame.displayedUnit, index, filter);
frameNum = frameNum + 1;
end
end
else
break;
end
index = index + 1;
end
for i=frameNum, maxBuffs do
local buffFrame = frame.buffFrames[i];
if buffFrame then buffFrame:Hide() end
end
end)
else
local Default_CompactUnitFrame_Util_IsPriorityDebuff = CompactUnitFrame_Util_IsPriorityDebuff
local function CompactUnitFrame_Util_IsPriorityDebuff(...)
local default = Default_CompactUnitFrame_Util_IsPriorityDebuff(...)
local spellId = select(10, ...)
return BigDebuffs:IsPriorityBigDebuff(spellId) or default
end
local function SetDebuffsHelper(debuffFrames, frameNum, maxDebuffs, filter, isBossAura, isBossBuff, auras)
if auras then
for i = 1,#auras do
local aura = auras[i];
if frameNum > maxDebuffs then
break;
end
local debuffFrame = debuffFrames[frameNum];
local index, name, icon, count, debuffType, duration, expirationTime, unitCaster, canStealOrPurge, nameplateShowPersonal, spellId = aura[1], aura[2], aura[3], aura[4], aura[5], aura[6], aura[7], aura[8], aura[9], aura[10], aura[11];
local unit = nil;
CompactUnitFrame_UtilSetDebuff(debuffFrame, unit, index, "HARMFUL", isBossAura, isBossBuff, name, icon, count, debuffType, duration, expirationTime, unitCaster, canStealOrPurge, nameplateShowPersonal, spellId);
frameNum = frameNum + 1;
if isBossAura then
--Boss auras are about twice as big as normal debuffs, so we may need to display fewer buffs
local bossDebuffScale = (debuffFrame.baseSize + BOSS_DEBUFF_SIZE_INCREASE)/debuffFrame.baseSize;
maxDebuffs = maxDebuffs - (bossDebuffScale - 1);
end
end
end
return frameNum, maxDebuffs;
end
local function NumElements(arr)
return arr and #arr or 0;
end
local dispellableDebuffTypes = { Magic = true, Curse = true, Disease = true, Poison = true};
hooksecurefunc("CompactUnitFrame_UpdateAuras", function(frame)
if not UnitIsPlayer(frame.displayedUnit) then
return
end
local doneWithBuffs = not frame.buffFrames or not frame.optionTable.displayBuffs or frame.maxBuffs == 0;
local doneWithDebuffs = not frame.debuffFrames or not frame.optionTable.displayDebuffs or frame.maxDebuffs == 0;
local doneWithDispelDebuffs = not frame.dispelDebuffFrames or not frame.optionTable.displayDispelDebuffs or frame.maxDispelDebuffs == 0;
local numUsedBuffs = 0;
local numUsedDebuffs = 0;
local numUsedDispelDebuffs = 0;
local displayOnlyDispellableDebuffs = frame.optionTable.displayOnlyDispellableDebuffs;
-- The following is the priority order for debuffs
local bossDebuffs, bossBuffs, priorityDebuffs, nonBossDebuffs;
local index = 1;
local batchCount = frame.maxDebuffs;
if not doneWithDebuffs then
AuraUtil.ForEachAura(frame.displayedUnit, "HARMFUL", batchCount, function(...)
if CompactUnitFrame_Util_IsBossAura(...) then
if not bossDebuffs then
bossDebuffs = {};
end
tinsert(bossDebuffs, {index, ...});
numUsedDebuffs = numUsedDebuffs + 1;
if numUsedDebuffs == frame.maxDebuffs then
doneWithDebuffs = true;
return true;
end
elseif CompactUnitFrame_Util_IsPriorityDebuff(...) then
if not priorityDebuffs then
priorityDebuffs = {};
end
tinsert(priorityDebuffs, {index, ...});
elseif not displayOnlyDispellableDebuffs and CompactUnitFrame_Util_ShouldDisplayDebuff(...) then
if not nonBossDebuffs then
nonBossDebuffs = {};
end
tinsert(nonBossDebuffs, {index, ...});
end
index = index + 1;
return false;
end);
end
if not doneWithBuffs or not doneWithDebuffs then
local maxBuffs = BigDebuffs.db.profile.raidFrames.increaseBuffs and MAX_BUFFS or frame.maxBuffs
index = 1;
batchCount = math.max(frame.maxDebuffs, maxBuffs);
AuraUtil.ForEachAura(frame.displayedUnit, "HELPFUL", batchCount, function(...)
if CompactUnitFrame_Util_IsBossAura(...) then
-- Boss Auras are considered Debuffs for our purposes.
if not doneWithDebuffs then
if not bossBuffs then
bossBuffs = {};
end
tinsert(bossBuffs, {index, ...});
numUsedDebuffs = numUsedDebuffs + 1;
if numUsedDebuffs == frame.maxDebuffs then
doneWithDebuffs = true;
end
end
elseif CompactUnitFrame_UtilShouldDisplayBuff(...) then
if not doneWithBuffs then
numUsedBuffs = numUsedBuffs + 1;
local buffFrame = frame.buffFrames[numUsedBuffs];
CompactUnitFrame_UtilSetBuff(buffFrame, index, ...);
if numUsedBuffs == maxBuffs then
doneWithBuffs = true;
end
end
end
index = index + 1;
return doneWithBuffs and doneWithDebuffs;
end);
end
numUsedDebuffs = math.min(frame.maxDebuffs, numUsedDebuffs + NumElements(priorityDebuffs));
if numUsedDebuffs == frame.maxDebuffs then
doneWithDebuffs = true;
end
if not doneWithDispelDebuffs then
--Clear what we currently have for dispellable debuffs
for debuffType, display in pairs(dispellableDebuffTypes) do
if ( display ) then
frame["hasDispel"..debuffType] = false;
end
end
end
if not doneWithDispelDebuffs or not doneWithDebuffs then
batchCount = math.max(frame.maxDebuffs, frame.maxDispelDebuffs);
index = 1;
AuraUtil.ForEachAura(frame.displayedUnit, "HARMFUL|RAID", batchCount, function(...)
if not doneWithDebuffs and displayOnlyDispellableDebuffs then
if CompactUnitFrame_Util_ShouldDisplayDebuff(...) and not CompactUnitFrame_Util_IsBossAura(...) and not CompactUnitFrame_Util_IsPriorityDebuff(...) then
if not nonBossDebuffs then
nonBossDebuffs = {};
end
tinsert(nonBossDebuffs, {index, ...});
numUsedDebuffs = numUsedDebuffs + 1;
if numUsedDebuffs == frame.maxDebuffs then
doneWithDebuffs = true;
end
end
end
if not doneWithDispelDebuffs then
local debuffType = select(4, ...);
if ( dispellableDebuffTypes[debuffType] and not frame["hasDispel"..debuffType] ) then
frame["hasDispel"..debuffType] = true;
numUsedDispelDebuffs = numUsedDispelDebuffs + 1;
local dispellDebuffFrame = frame.dispelDebuffFrames[numUsedDispelDebuffs];
CompactUnitFrame_UtilSetDispelDebuff(dispellDebuffFrame, debuffType, index)
if numUsedDispelDebuffs == frame.maxDispelDebuffs then
doneWithDispelDebuffs = true;
end
end
end
index = index + 1;
return (doneWithDebuffs or not displayOnlyDispellableDebuffs) and doneWithDispelDebuffs;
end);
end
local frameNum = 1;
local maxDebuffs = frame.maxDebuffs;
do
local isBossAura = true;
local isBossBuff = false;
frameNum, maxDebuffs = SetDebuffsHelper(frame.debuffFrames, frameNum, maxDebuffs, "HARMFUL", isBossAura, isBossBuff, bossDebuffs);
end
do
local isBossAura = true;
local isBossBuff = true;
frameNum, maxDebuffs = SetDebuffsHelper(frame.debuffFrames, frameNum, maxDebuffs, "HELPFUL", isBossAura, isBossBuff, bossBuffs);
end
do
local isBossAura = false;
local isBossBuff = false;
frameNum, maxDebuffs = SetDebuffsHelper(frame.debuffFrames, frameNum, maxDebuffs, "HARMFUL", isBossAura, isBossBuff, priorityDebuffs);
end
do
local isBossAura = false;
local isBossBuff = false;
frameNum, maxDebuffs = SetDebuffsHelper(frame.debuffFrames, frameNum, maxDebuffs, "HARMFUL|RAID", isBossAura, isBossBuff, nonBossDebuffs);
end
numUsedDebuffs = frameNum - 1;
CompactUnitFrame_HideAllBuffs(frame, numUsedBuffs + 1);
CompactUnitFrame_HideAllDebuffs(frame, numUsedDebuffs + 1);
CompactUnitFrame_HideAllDispelDebuffs(frame, numUsedDispelDebuffs + 1);
BigDebuffs:ShowBigDebuffs(frame)
end)
end
function BigDebuffs:ShowBigDebuffs(frame)
if (not self.db.profile.raidFrames.enabled) or
(not frame.debuffFrames) or
(not frame.BigDebuffs) or
(not self:ShowInRaids()) or
(not UnitIsPlayer(frame.displayedUnit))
then
return
end
local UnitDebuff = self.test and UnitDebuffTest or UnitDebuff
HideBigDebuffs(frame)
local debuffs = {}
local big
local now = GetTime()
local warning, warningId
for i = 1, 40 do
local _,_,_, dispelType, _, time, caster, _,_, id = UnitDebuff(frame.displayedUnit, i)
if id then
local reaction = caster and UnitReaction("player", caster) or 0
local friendlySmokeBomb = id == 212183 and reaction > 4
local size = self:GetDebuffSize(id, self:IsDispellable(frame.displayedUnit, dispelType))
if size and not friendlySmokeBomb then
big = true
local duration = time and time - now or 0
tinsert(debuffs, { i, size, duration, self:GetDebuffPriority(id) })
elseif self.db.profile.raidFrames.redirectBliz or
(self.db.profile.raidFrames.anchor == "INNER" and not self.db.profile.raidFrames.hideBliz) then
if not frame.optionTable.displayOnlyDispellableDebuffs or
self:IsDispellable(frame.displayedUnit, dispelType)
then
-- duration 0 to preserve Blizzard order
tinsert(debuffs, { i, self.db.profile.raidFrames.default, 0, 0 })
end
end
-- Set warning debuff
if WOW_PROJECT_ID ~= WOW_PROJECT_CLASSIC then
local k
for j = 1, #self.WarningDebuffs do
if id == self.WarningDebuffs[j] and
self.db.profile.raidFrames.warningList[id] and
not friendlySmokeBomb and
(not k or j < k) then
k = j
warning = i
warningId = id
end
end
end
end
end
-- check for interrupts
local guid = UnitGUID(frame.displayedUnit)
if guid and self.units[guid] and self.units[guid].expires and self.units[guid].expires > GetTime() then
local spellId = self.units[guid].spellId
local size = self:GetDebuffSize(spellId, false)
if size then
big = true
tinsert(debuffs, { -1, size, 0, self:GetDebuffPriority(spellId) })
end
end
if #debuffs > 0 then
-- insert the warning debuff if it exists and we have a big debuff
if big and warning then
local size = self.db.profile.raidFrames.warning
-- remove duplicate
for k,v in pairs(debuffs) do
if v[1] == warning then
if self.Spells[warningId] then size = v[2] end -- preserve the size
table.remove(debuffs, k)
break
end
end
tinsert(debuffs, { warning, size, 0, 0, true })
else
warning = nil
end
-- sort by priority > size > duration > index
table.sort(debuffs, function(a, b)
if a[4] == b[4] then
if a[2] == b[2] then
if a[3] < b[3] then return true end
if a[3] == b[3] then return a[1] < b[1] end
end
return a[2] > b[2]
end
return a[4] > b[4]
end)
local index = 1
if self.db.profile.raidFrames.hideBliz or
self.db.profile.raidFrames.anchor == "INNER" or
self.db.profile.raidFrames.redirectBliz then
CompactUnitFrame_HideAllDebuffs(frame)
end
for i = 1, #debuffs do
if index <= self.db.profile.raidFrames.maxDebuffs or debuffs[i][1] == warning then
if not frame.BigDebuffs[index] then break end
frame.BigDebuffs[index].baseSize = frame:GetHeight() * debuffs[i][2] * 0.01
CompactUnitFrame_UtilSetDebuff(frame.BigDebuffs[index],
frame.displayedUnit, debuffs[i][1], nil, false, false)
frame.BigDebuffs[index].cooldown:SetSwipeColor(0, 0, 0, 0.7)
index = index + 1
end
end
end
end
function BigDebuffs:IsPriorityBigDebuff(id)
if not self.Spells[id] then return end
id = self.Spells[id].parent or id -- Check for parent spellID
return self.Spells[id].priority
end
function BigDebuffs:UNIT_AURA(unit)
if not self.db.profile.unitFrames.enabled or
not self.db.profile.unitFrames[unit:gsub("%d", "")].enabled
then
return
end
self:AttachUnitFrame(unit)
local frame = self.UnitFrames[unit]
if not frame then return end
local UnitDebuff = BigDebuffs.test and UnitDebuffTest or UnitDebuff
local now = GetTime()
local left, priority, duration, expires, icon, debuff, buff, interrupt = 0, 0
for i = 1, 40 do
-- Check debuffs
local _, n, _,_, d, e, caster, _,_, id = UnitDebuff(unit, i)
if id then
if self.Spells[id] then
if LibClassicDurations then
local durationNew, expirationTimeNew = LibClassicDurations:GetAuraDurationByUnit(unit, id, caster)
if d == 0 and durationNew then
d = durationNew
e = expirationTimeNew
end
end
local reaction = caster and UnitReaction("player", caster) or 0
local friendlySmokeBomb = id == 212183 and reaction > 4
local p = self:GetAuraPriority(id)
if p and p >= priority and not friendlySmokeBomb then
if p > priority or self:IsPriorityBigDebuff(id) or e == 0 or e - now > left then
left = e - now
duration = d
debuff = i
priority = p
expires = e
icon = n
end
end
end
end
-- Check buffs
if LibClassicDurations then
_, n, _,_, d, e, caster, _,_, id = LibClassicDurations:UnitAura(unit, i, "HELPFUL")
else
_, n, _,_, d, e, caster, _,_, id = UnitBuff(unit, i)
end
if id then
if self.Spells[id] then
if LibClassicDurations then
local durationNew, expirationTimeNew = LibClassicDurations:GetAuraDurationByUnit(unit, id, caster)
if d == 0 and durationNew then
d = durationNew
e = expirationTimeNew
end
end
local p = self:GetAuraPriority(id)
if p and p >= priority then
if p > priority or self:IsPriorityBigDebuff(id) or e == 0 or e - now > left then
left = e - now
duration = d
debuff = i
priority = p
expires = e
icon = n
buff = true
end
end
end
end
end
-- Check for interrupt
local guid = UnitGUID(unit)
if guid and self.units[guid] and self.units[guid].expires and self.units[guid].expires > GetTime() then
local spell = self.units[guid]
local spellId = spell.spellId
local p = self:GetAuraPriority(spellId)
if p and p >= priority then
left = spell.expires - now
duration = self.Spells[spellId].duration
debuff = spellId
expires = spell.expires
icon = GetSpellTexture(spellId)
interrupt = spellId
end
end
if debuff then
if duration < 1 then duration = 1 end -- auras like Solar Beam don't have a duration
if frame.current ~= icon then
if frame.blizzard then
-- Blizzard Frame
-- fix Obsidian Claw icon
icon = icon == 611425 and 1508487 or icon
SetPortraitToTexture(frame.icon, icon)
else
frame.icon:SetTexture(icon)
end
end
frame.cooldown:SetCooldown(expires - duration, duration)
frame:Show()
frame.cooldown:SetSwipeColor(0, 0, 0, 0.6)
-- set for tooltips
frame:SetID(debuff)
frame.buff = buff
frame.interrupt = interrupt
frame.current = icon
else
frame:Hide()
frame.current = nil
end
end
function BigDebuffs:UNIT_AURA_NAMEPLATE(unit)
if not self.db.profile.nameplates.enabled
or not unit:find("nameplate")
or (not UnitCanAttack("player", unit) and not self.db.profile.nameplates.friendly)
or (UnitCanAttack("player", unit) and not self.db.profile.nameplates.enemy)
or (not UnitIsPlayer(unit) and not self.db.profile.nameplates.npc)
or (UnitIsUnit("player", unit))
then
return
end
self:AttachNameplate(unit)
local frame = self.Nameplates[unit]
if not frame then return end
local UnitDebuff = BigDebuffs.test and UnitDebuffTest or UnitDebuff
local now = GetTime()
local left, priority, duration, expires, icon, debuff, buff, interrupt = 0, 0
for i = 1, 40 do
-- Check debuffs
local _, n, _,_, d, e, caster, _,_, id = UnitDebuff(unit, i)
if id then
if self.Spells[id] then
if LibClassicDurations then
local durationNew, expirationTimeNew = LibClassicDurations:GetAuraDurationByUnit(unit, id, caster)
if d == 0 and durationNew then
d = durationNew
e = expirationTimeNew
end
end
local reaction = caster and UnitReaction("player", caster) or 0
local friendlySmokeBomb = id == 212183 and reaction > 4
local p = self:GetNameplatesPriority(id)
if p and p >= priority and not friendlySmokeBomb then
if p > priority or self:IsPriorityBigDebuff(id) or e == 0 or e - now > left then
left = e - now
duration = d
debuff = i
priority = p
expires = e
icon = n
end
end
end
end
-- Check buffs
if LibClassicDurations then
_, n, _,_, d, e, caster, _,_, id = LibClassicDurations:UnitAura(unit, i, "HELPFUL")
else
_, n, _,_, d, e, caster, _,_, id = UnitBuff(unit, i)
end
if id then
if self.Spells[id] then
if LibClassicDurations then
local durationNew, expirationTimeNew = LibClassicDurations:GetAuraDurationByUnit(unit, id, caster)
if d == 0 and durationNew then
d = durationNew
e = expirationTimeNew
end
end
local p = self:GetNameplatesPriority(id)
if p and p >= priority then
if p > priority or self:IsPriorityBigDebuff(id) or e == 0 or e - now > left then
left = e - now
duration = d
debuff = i
priority = p
expires = e
icon = n
buff = true
end
end
end
end
end
-- Check for interrupt
local guid = UnitGUID(unit)
if guid and self.units[guid] and self.units[guid].expires and self.units[guid].expires > GetTime() then
local spell = self.units[guid]
local spellId = spell.spellId
local p = self:GetNameplatesPriority(spellId)
if p and p >= priority then
left = spell.expires - now
duration = self.Spells[spellId].duration
debuff = spellId
expires = spell.expires
icon = GetSpellTexture(spellId)
interrupt = spellId
end
end
if debuff then
if duration < 1 then duration = 1 end -- auras like Solar Beam don't have a duration
if frame.current ~= icon then
frame.icon:SetTexture(icon)
end
frame.cooldown:SetCooldown(expires - duration, duration)
frame:Show()
frame.cooldown:SetSwipeColor(0, 0, 0, 0.6)
-- set for tooltips
frame:SetID(debuff)
frame.buff = buff
frame.interrupt = interrupt
frame.current = icon
else
frame:Hide()
frame.current = nil
end
end
function BigDebuffs:PLAYER_FOCUS_CHANGED()
self:UNIT_AURA("focus")
end
function BigDebuffs:PLAYER_TARGET_CHANGED()
self:UNIT_AURA("target")
end
function BigDebuffs:UNIT_PET()
self:UNIT_AURA("pet")
end
function BigDebuffs:NAME_PLATE_UNIT_ADDED(_, unit)
local namePlate = C_NamePlate.GetNamePlateForUnit(unit)
if namePlate:IsForbidden() then return end
local anchor, frame
for k, v in ipairs(nameplatesAnchors) do
if v.used(namePlate) then
anchor, frame = v.func(namePlate)
break
end
end
if not frame or not anchor or frame:IsForbidden() then return end
if not frame.BigDebuffs then
frame.BigDebuffs = CreateFrame("Frame", "$parent.BigDebuffs", frame)
frame.BigDebuffs:SetFrameLevel(frame:GetFrameLevel())
frame.BigDebuffs.icon = frame.BigDebuffs:CreateTexture("$parent.Icon", "OVERLAY", nil, 3)
frame.BigDebuffs.icon:SetAllPoints(frame.BigDebuffs)
frame.BigDebuffs.cooldown = CreateFrame("Cooldown", "$parent.Cooldown", frame.BigDebuffs, "CooldownFrameTemplate")
frame.BigDebuffs.cooldown:SetAllPoints(frame.BigDebuffs)
frame.BigDebuffs.cooldown:SetDrawEdge(false)
frame.BigDebuffs.cooldown:SetAlpha(1)
frame.BigDebuffs.cooldown:SetDrawBling(false)
frame.BigDebuffs.cooldown:SetDrawSwipe(true)
frame.BigDebuffs.cooldown:SetReverse(true)
frame.BigDebuffs:SetScript("OnEnter", function(self)
if ( BigDebuffs.db.profile.nameplates.tooltips ) then
NamePlateTooltip:SetOwner(self, "ANCHOR_RIGHT", 0, 0);
if self.interrupt then
NamePlateTooltip:SetSpellByID(self.interrupt)
elseif self.buff then
NamePlateTooltip:SetUnitBuff(self.unit, self:GetID());
else
NamePlateTooltip:SetUnitDebuff(self.unit, self:GetID());
end
elseif NamePlateTooltip:IsOwned(self) then
NamePlateTooltip:Hide();
end
end)
frame.BigDebuffs:SetScript("OnLeave", function()
NamePlateTooltip:Hide()
end)
end
frame.BigDebuffs.anchor = anchor
self.Nameplates[unit] = frame.BigDebuffs
frame.BigDebuffs.unit = unit
frame.BigDebuffs:RegisterUnitEvent("UNIT_AURA", unit)
frame.BigDebuffs:SetScript("OnEvent", function()
self:UNIT_AURA_NAMEPLATE(unit)
end)
self:UNIT_AURA_NAMEPLATE(unit)
table.insert(unitsWithRaid, unit)
end
function BigDebuffs:NAME_PLATE_UNIT_REMOVED(_, unit)
local frame = self.Nameplates[unit]
frame:UnregisterEvent("UNIT_AURA")
for i = 1, #unitsWithRaid do
if (unitsWithRaid[i] == unit) then
table.remove(unitsWithRaid, i)
end
end
end
function BigDebuffs:ShowInRaids()
local grpSize = GetNumGroupMembers();
local inRaid = self.db.profile.raidFrames.inRaid;
if ( inRaid.hide and grpSize > inRaid.size ) then
return false;
end
return true;
end
SLASH_BigDebuffs1 = "/bd"
SLASH_BigDebuffs2 = "/bigdebuffs"
SlashCmdList.BigDebuffs = function(msg)
InterfaceOptionsFrame_OpenToCategory(addonName)
InterfaceOptionsFrame_OpenToCategory(addonName)
end
|