Merge pull request #20 from EnsignPayton/auras-work

Auras to main repo branch
This commit is contained in:
Logan Payton
2018-05-17 22:27:16 -05:00
committed by GitHub
13 changed files with 1441 additions and 157 deletions
+2 -14
View File
@@ -558,7 +558,7 @@ function E:SetupLayout(layout, noDataReset)
E.db.unitframe.units.arena.castbar.width = 200
end
if(layout == "dpsCaster" or layout == "healer" or (layout == "dpsMelee" and E.myclass == "HUNTER")) then
if layout == "dpsCaster" or layout == "healer" or (layout == "dpsMelee" and E.myclass == "HUNTER") then
if not E.db.movers then E.db.movers = {} end
E.db.unitframe.units.player.castbar.width = E.PixelMode and 406 or 436
E.db.unitframe.units.player.castbar.height = 28
@@ -664,18 +664,6 @@ local function SetupAuras(style)
UF:Configure_AuraBars(frame)
end
frame = UF["focus"]
E:CopyTable(E.db.unitframe.units.focus.buffs, P.unitframe.units.focus.buffs)
E:CopyTable(E.db.unitframe.units.focus.debuffs, P.unitframe.units.focus.debuffs)
E:CopyTable(E.db.unitframe.units.focus.aurabar, P.unitframe.units.focus.aurabar)
E.db.unitframe.units.focus.smartAuraDisplay = P.unitframe.units.focus.smartAuraDisplay
if frame then
UF:Configure_Auras(frame, "Buffs")
UF:Configure_Auras(frame, "Debuffs")
UF:Configure_AuraBars(frame)
end
if not style then
E.db.unitframe.units.player.buffs.enable = true
E.db.unitframe.units.player.buffs.attachTo = "FRAME"
@@ -690,7 +678,7 @@ local function SetupAuras(style)
E:GetModule("UnitFrames"):CreateAndUpdateUF("target")
end
if(InstallStepComplete) then
if InstallStepComplete then
InstallStepComplete.message = L["Auras Set"]
InstallStepComplete:Show()
end
+1
View File
@@ -17,6 +17,7 @@
<Include file="LibDataBroker\LibDataBroker-1.1.xml"/>
<Include file="LibElvUIPlugin-1.0\LibElvUIPlugin-1.0.xml"/>
<Include file="oUF\oUF.xml"/>
<Include file="oUF_Plugins\oUF_Plugins.xml"/>
<Include file="UTF8\UTF8.xml"/>
<Include file="LibCompress\LibCompress.xml"/>
<Include file="LibBase64-1.0\LibBase64-1.0.xml"/>
+147 -133
View File
@@ -64,18 +64,25 @@ button.isDebuff - indicates if the button holds a debuff (boolean)
local ns = oUF
local oUF = ns.oUF
local tinsert = table.insert
local floor = math.floor
local tinsert, getn = table.insert, table.getn
local floor, min, mod = math.floor, math.min, math.mod
local CreateFrame = CreateFrame
local GetTime = GetTime
local UnitAura = UnitAura
local GetPlayerBuff = GetPlayerBuff
local GetPlayerBuffTexture = GetPlayerBuffTexture
local GetPlayerBuffApplications = GetPlayerBuffApplications
local GetPlayerBuffDispelType = GetPlayerBuffDispelType
local GetPlayerBuffTimeLeft = GetPlayerBuffTimeLeft
local VISIBLE = 1
local HIDDEN = 0
local function UpdateTooltip(self)
if self.filter == 'HELPFUL' then
if self:GetParent().__owner.unit == "player" then
GameTooltip:SetPlayerBuff(self:GetID())
elseif self.filter == 'HELPFUL' then
GameTooltip:SetUnitBuff(self:GetParent().__owner.unit, self:GetID(), self.filter)
else
GameTooltip:SetUnitDebuff(self:GetParent().__owner.unit, self:GetID(), self.filter)
@@ -83,7 +90,7 @@ local function UpdateTooltip(self)
end
local function onEnter(self)
if(not self:IsVisible()) then return end
if not self:IsVisible() then return end
GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
self:UpdateTooltip()
@@ -97,7 +104,7 @@ local function createAuraIcon(element, index)
local button = CreateFrame('Button', '$parentButton' .. index, element)
button:RegisterForClicks('RightButtonUp')
local cd = CreateFrame('Cooldown', '$parentCooldown', button, 'oUF_CooldownFrameTemplate')
local cd = CreateFrame('Frame', '$parentCooldown', button, 'oUF_CooldownFrameTemplate')
cd:SetAllPoints()
local icon = button:CreateTexture(nil, 'BORDER')
@@ -126,117 +133,124 @@ local function createAuraIcon(element, index)
* self - the widget holding the aura buttons
* button - the newly created aura button (Button)
--]]
if(element.PostCreateIcon) then element:PostCreateIcon(button) end
if element.PostCreateIcon then element:PostCreateIcon(button) end
return button
end
local function customFilter(element, unit, button, name)
if(name) then
return true
end
if name then return true end
end
local function updateIcon(element, unit, index, offset, filter, isDebuff, visible)
local name, rank, texture, count, dispelType, duration, expiration = UnitAura(unit, index, filter)
if unit == "player" then
local idx = GetPlayerBuff(index - 1, filter)
if idx < 0 then return end
index = idx
texture = GetPlayerBuffTexture(idx)
count = GetPlayerBuffApplications(idx)
dispelType = GetPlayerBuffDispelType(idx)
duration = GetPlayerBuffTimeLeft(idx)
end
if element.forceShow then
name, rank, texture = GetSpellInfo(26993)
count, dispelType, duration, expiration = 5, 'Magic', 0, 60
end
if(name) then
local position = visible + offset + 1
local button = element[position]
if(not button) then
--[[ Override: Auras:CreateIcon(position)
Used to create the aura button at a given position.
if not name then return end
* self - the widget holding the aura buttons
* position - the position at which the aura button is to be created (number)
local position = visible + offset + 1
local button = element[position]
if not button then
--[[ Override: Auras:CreateIcon(position)
Used to create the aura button at a given position.
## Returns
* button - the button used to represent the aura (Button)
--]]
button = (element.CreateIcon or createAuraIcon) (element, position)
tinsert(element, button)
element.createdIcons = element.createdIcons + 1
end
button.filter = filter
button.isDebuff = isDebuff
--[[ Override: Auras:CustomFilter(unit, button, ...)
Defines a custom filter that controls if the aura button should be shown.
* self - the widget holding the aura buttons
* unit - the unit on which the aura is cast (string)
* button - the button displaying the aura (Button)
* ... - the return values from [UnitAura](http://wowprogramming.com/docs/api/UnitAura)
* self - the widget holding the aura buttons
* position - the position at which the aura button is to be created (number)
## Returns
* show - indicates whether the aura button should be shown (boolean)
* button - the button used to represent the aura (Button)
--]]
local show = true
if not element.forceShow then
show = (element.CustomFilter or customFilter) (element, unit, button, name, rank, texture, count, dispelType, duration, expiration)
end
button = (element.CreateIcon or createAuraIcon) (element, position)
if(show) then
-- We might want to consider delaying the creation of an actual cooldown
-- object to this point, but I think that will just make things needlessly
-- complicated.
if(button.cd and not element.disableCooldown) then
if(duration and duration > 0) then
button.cd:SetCooldown(GetTime() - (duration - expiration), duration)
button.cd:Show()
else
button.cd:Hide()
end
end
tinsert(element, button)
element.createdIcons = element.createdIcons + 1
end
if(button.overlay) then
if((isDebuff and element.showDebuffType) or (not isDebuff and element.showBuffType) or element.showType) then
local color = DebuffTypeColor[dispelType] or DebuffTypeColor.none
button.filter = filter
button.isDebuff = isDebuff
button.overlay:SetVertexColor(color.r, color.g, color.b)
button.overlay:Show()
else
button.overlay:Hide()
end
end
--[[ Override: Auras:CustomFilter(unit, button, ...)
Defines a custom filter that controls if the aura button should be shown.
if(button.icon) then button.icon:SetTexture(texture) end
if(button.count) then button.count:SetText(count > 1 and count) end
* self - the widget holding the aura buttons
* unit - the unit on which the aura is cast (string)
* button - the button displaying the aura (Button)
* ... - the return values from [UnitAura](http://wowprogramming.com/docs/api/UnitAura)
local size = element.size or 16
button:SetSize(size, size)
## Returns
button:EnableMouse(not element.disableMouse)
button:SetID(index)
button:Show()
* show - indicates whether the aura button should be shown (boolean)
--]]
local show = true
if not element.forceShow then
show = (element.CustomFilter or customFilter) (element, unit, button, name, rank, texture, count, dispelType, duration, expiration)
end
--[[ Callback: Auras:PostUpdateIcon(unit, button, index, position)
Called after the aura button has been updated.
if not show then return HIDDEN end
* self - the widget holding the aura buttons
* unit - the unit on which the aura is cast (string)
* button - the updated aura button (Button)
* index - the index of the aura (number)
* position - the actual position of the aura button (number)
--]]
if(element.PostUpdateIcon) then
element:PostUpdateIcon(unit, button, index, position)
end
return VISIBLE
-- We might want to consider delaying the creation of an actual cooldown
-- object to this point, but I think that will just make things needlessly
-- complicated.
if button.cd and not element.disableCooldown then
if duration and duration > 0 then
-- button.cd:SetCooldown(GetTime() - (duration - expiration), duration)
button.cd:Show()
else
return HIDDEN
button.cd:Hide()
end
end
if button.overlay then
if (isDebuff and element.showDebuffType) or (not isDebuff and element.showBuffType) or element.showType then
local color = DebuffTypeColor[dispelType] or DebuffTypeColor.none
button.overlay:SetVertexColor(color.r, color.g, color.b)
button.overlay:Show()
else
button.overlay:Hide()
end
end
if button.icon then button.icon:SetTexture(texture) end
if button.count then button.count:SetText(count > 1 and count) end
local size = element.size or 16
button:SetWidth(size)
button:SetHeight(size)
button:EnableMouse(not element.disableMouse)
button:SetID(index)
button:Show()
--[[ Callback: Auras:PostUpdateIcon(unit, button, index, position)
Called after the aura button has been updated.
* self - the widget holding the aura buttons
* unit - the unit on which the aura is cast (string)
* button - the updated aura button (Button)
* index - the index of the aura (number)
* position - the actual position of the aura button (number)
--]]
if element.PostUpdateIcon then
element:PostUpdateIcon(unit, button, index, position)
end
return VISIBLE
end
local function SetPosition(element, from, to)
@@ -252,7 +266,7 @@ local function SetPosition(element, from, to)
-- Bail out if the to range is out of scope.
if(not button) then break end
local col = (i - 1) % cols
local col = mod((i - 1), cols)
local row = floor((i - 1) / cols)
button:ClearAllPoints()
@@ -261,25 +275,25 @@ local function SetPosition(element, from, to)
end
local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontHide)
if(not offset) then offset = 0 end
if not offset then offset = 0 end
local index = 1
local visible = 0
local hidden = 0
while(visible < limit) do
while visible < limit do
local result = updateIcon(element, unit, index, offset, filter, isDebuff, visible)
if(not result) then
if not result then
break
elseif(result == VISIBLE) then
elseif result == VISIBLE then
visible = visible + 1
elseif(result == HIDDEN) then
elseif result == HIDDEN then
hidden = hidden + 1
end
index = index + 1
end
if(not dontHide) then
for i = visible + offset + 1, #element do
if not dontHide then
for i = visible + offset + 1, getn(element) do
element[i]:Hide()
end
end
@@ -288,42 +302,42 @@ local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontH
end
local function UpdateAuras(self, event, unit)
if(self.unit ~= unit) then return end
if self.unit ~= unit then return end
local auras = self.Auras
if(auras) then
if auras then
--[[ Callback: Auras:PreUpdate(unit)
Called before the element has been updated.
* self - the widget holding the aura buttons
* unit - the unit for which the update has been triggered (string)
--]]
if(auras.PreUpdate) then auras:PreUpdate(unit) end
if auras.PreUpdate then auras:PreUpdate(unit) end
local numBuffs = auras.numBuffs or 32
local numDebuffs = auras.numDebuffs or 40
local max = auras.numTotal or numBuffs + numDebuffs
local visibleBuffs, hiddenBuffs = filterIcons(auras, unit, auras.buffFilter or auras.filter or 'HELPFUL', math.min(numBuffs, max), nil, 0, true)
local visibleBuffs, hiddenBuffs = filterIcons(auras, unit, auras.buffFilter or auras.filter or 'HELPFUL', min(numBuffs, max), nil, 0, true)
local hasGap
if(visibleBuffs ~= 0 and auras.gap) then
if visibleBuffs ~= 0 and auras.gap then
hasGap = true
visibleBuffs = visibleBuffs + 1
local button = auras[visibleBuffs]
if(not button) then
if not button then
button = (auras.CreateIcon or createAuraIcon) (auras, visibleBuffs)
tinsert(auras, button)
auras.createdIcons = auras.createdIcons + 1
end
-- Prevent the button from displaying anything.
if(button.cd) then button.cd:Hide() end
if(button.icon) then button.icon:SetTexture() end
if(button.overlay) then button.overlay:Hide() end
if(button.stealable) then button.stealable:Hide() end
if(button.count) then button.count:SetText() end
if button.cd then button.cd:Hide() end
if button.icon then button.icon:SetTexture() end
if button.overlay then button.overlay:Hide() end
if button.stealable then button.stealable:Hide() end
if button.count then button.count:SetText() end
button:EnableMouse(false)
button:Show()
@@ -341,10 +355,10 @@ local function UpdateAuras(self, event, unit)
end
end
local visibleDebuffs, hiddenDebuffs = filterIcons(auras, unit, auras.debuffFilter or auras.filter or 'HARMFUL', math.min(numDebuffs, max - visibleBuffs), true, visibleBuffs)
local visibleDebuffs, hiddenDebuffs = filterIcons(auras, unit, auras.debuffFilter or auras.filter or 'HARMFUL', min(numDebuffs, max - visibleBuffs), true, visibleBuffs)
auras.visibleDebuffs = visibleDebuffs
if(hasGap and visibleDebuffs == 0) then
if hasGap and visibleDebuffs == 0 then
auras[visibleBuffs]:Hide()
visibleBuffs = visibleBuffs - 1
end
@@ -364,11 +378,11 @@ local function UpdateAuras(self, event, unit)
* from - the offset of the first aura button to be (re-)anchored (number)
* to - the offset of the last aura button to be (re-)anchored (number)
--]]
if(auras.PreSetPosition) then
if auras.PreSetPosition then
fromRange, toRange = auras:PreSetPosition(max)
end
if(fromRange or auras.createdIcons > auras.anchoredIcons) then
if fromRange or auras.createdIcons > auras.anchoredIcons then
--[[ Override: Auras:SetPosition(from, to)
Used to (re-)anchor the aura buttons.
Called when new aura buttons have been created or if :PreSetPosition is defined.
@@ -387,72 +401,72 @@ local function UpdateAuras(self, event, unit)
* self - the widget holding the aura buttons
* unit - the unit for which the update has been triggered (string)
--]]
if(auras.PostUpdate) then auras:PostUpdate(unit) end
if auras.PostUpdate then auras:PostUpdate(unit) end
end
local buffs = self.Buffs
if(buffs) then
if(buffs.PreUpdate) then buffs:PreUpdate(unit) end
if buffs then
if buffs.PreUpdate then buffs:PreUpdate(unit) end
local numBuffs = buffs.num or 32
local visibleBuffs, hiddenBuffs = filterIcons(buffs, unit, buffs.filter or 'HELPFUL', numBuffs)
buffs.visibleBuffs = visibleBuffs
local fromRange, toRange
if(buffs.PreSetPosition) then
if buffs.PreSetPosition then
fromRange, toRange = buffs:PreSetPosition(numBuffs)
end
if(fromRange or buffs.createdIcons > buffs.anchoredIcons) then
if fromRange or buffs.createdIcons > buffs.anchoredIcons then
(buffs.SetPosition or SetPosition) (buffs, fromRange or buffs.anchoredIcons + 1, toRange or buffs.createdIcons)
buffs.anchoredIcons = buffs.createdIcons
end
if(buffs.PostUpdate) then buffs:PostUpdate(unit) end
if buffs.PostUpdate then buffs:PostUpdate(unit) end
end
local debuffs = self.Debuffs
if(debuffs) then
if(debuffs.PreUpdate) then debuffs:PreUpdate(unit) end
if debuffs then
if debuffs.PreUpdate then debuffs:PreUpdate(unit) end
local numDebuffs = debuffs.num or 40
local visibleDebuffs, hiddenDebuffs = filterIcons(debuffs, unit, debuffs.filter or 'HARMFUL', numDebuffs, true)
debuffs.visibleDebuffs = visibleDebuffs
local fromRange, toRange
if(debuffs.PreSetPosition) then
if debuffs.PreSetPosition then
fromRange, toRange = debuffs:PreSetPosition(numDebuffs)
end
if(fromRange or debuffs.createdIcons > debuffs.anchoredIcons) then
if fromRange or debuffs.createdIcons > debuffs.anchoredIcons then
(debuffs.SetPosition or SetPosition) (debuffs, fromRange or debuffs.anchoredIcons + 1, toRange or debuffs.createdIcons)
debuffs.anchoredIcons = debuffs.createdIcons
end
if(debuffs.PostUpdate) then debuffs:PostUpdate(unit) end
if debuffs.PostUpdate then debuffs:PostUpdate(unit) end
end
end
local function Update(self, event, unit)
if(self.unit ~= unit) then return end
if self.unit ~= unit then return end
UpdateAuras(self, event, unit)
-- Assume no event means someone wants to re-anchor things. This is usually
-- done by UpdateAllElements and :ForceUpdate.
if(event == 'ForceUpdate' or not event) then
if event == 'ForceUpdate' or not event then
local buffs = self.Buffs
if(buffs) then
if buffs then
(buffs.SetPosition or SetPosition) (buffs, 1, buffs.createdIcons)
end
local debuffs = self.Debuffs
if(debuffs) then
if debuffs then
(debuffs.SetPosition or SetPosition) (debuffs, 1, debuffs.createdIcons)
end
local auras = self.Auras
if(auras) then
if auras then
(auras.SetPosition or SetPosition) (auras, 1, auras.createdIcons)
end
end
@@ -463,11 +477,11 @@ local function ForceUpdate(element)
end
local function Enable(self)
if(self.Buffs or self.Debuffs or self.Auras) then
self:RegisterEvent('UNIT_AURA', UpdateAuras)
if self.Buffs or self.Debuffs or self.Auras then
self:RegisterEvent('PLAYER_AURAS_CHANGED', UpdateAuras)
local buffs = self.Buffs
if(buffs) then
if buffs then
buffs.__owner = self
buffs.ForceUpdate = ForceUpdate
@@ -478,7 +492,7 @@ local function Enable(self)
end
local debuffs = self.Debuffs
if(debuffs) then
if debuffs then
debuffs.__owner = self
debuffs.ForceUpdate = ForceUpdate
@@ -489,7 +503,7 @@ local function Enable(self)
end
local auras = self.Auras
if(auras) then
if auras then
auras.__owner = self
auras.ForceUpdate = ForceUpdate
@@ -504,12 +518,12 @@ local function Enable(self)
end
local function Disable(self)
if(self.Buffs or self.Debuffs or self.Auras) then
self:UnregisterEvent('UNIT_AURA', UpdateAuras)
if self.Buffs or self.Debuffs or self.Auras then
self:UnregisterEvent('PLAYER_AURAS_CHANGED', UpdateAuras)
if(self.Buffs) then self.Buffs:Hide() end
if(self.Debuffs) then self.Debuffs:Hide() end
if(self.Auras) then self.Auras:Hide() end
if self.Buffs then self.Buffs:Hide() end
if self.Debuffs then self.Debuffs:Hide() end
if self.Auras then self.Auras:Hide() end
end
end
+1 -1
View File
@@ -1,6 +1,6 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="power.lua"/>
<!--<Script file="auras.lua"/>-->
<Script file="auras.lua"/>
<Script file="health.lua"/>
<Script file="raidtargetindicator.lua"/>
<Script file="leaderindicator.lua"/>
@@ -0,0 +1,392 @@
local ns = oUF
local oUF = ns.oUF
assert(oUF, "oUF_AuraBars was unable to locate oUF install.")
local format = string.format
local floor, huge, min, mod = math.floor, math.huge, math.min, math.mod
local tsort, getn = table.sort, table.getn
local tremove = table.remove
local random = math.random
local CreateFrame = CreateFrame
local UnitAura = UnitAura
local UnitIsFriend = UnitIsFriend
local DAY, HOUR, MINUTE = 86400, 3600, 60
local function FormatTime(s)
if s < MINUTE then
return format("%.1fs", s)
elseif s < HOUR then
return format("%dm %ds", mod(s/60,60), mod(s,60))
elseif s < DAY then
return format("%dh %dm", s/(60*60), mod(s/60,60))
else
return format("%dd %dh", s/DAY, (s / HOUR) - (floor(s/DAY) * 24))
end
end
local function UpdateTooltip(self)
GameTooltip:SetUnitAura(self.__unit, self:GetParent().aura.name, self:GetParent().aura.rank, self:GetParent().aura.filter)
end
local function OnEnter(self)
if(not self:IsVisible()) then return end
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")
self:UpdateTooltip()
end
local function OnLeave(self)
GameTooltip:Hide()
end
local function SetAnchors(self)
local bars = self.bars
for index = 1, getn(bars) do
local frame = bars[index]
local anchor = frame.anchor
frame:Height(self.auraBarHeight or 20)
frame.statusBar.iconHolder:Size(frame:GetHeight())
frame:Width((self.auraBarWidth or self:GetWidth()) - (frame:GetHeight() + (self.gap or 0)))
frame:ClearAllPoints()
if self.down == true then
if self == anchor then -- Root frame so indent for icon
frame:SetPoint("TOPLEFT", anchor, "TOPLEFT", (frame:GetHeight() + (self.gap or 0) ), -1)
else
frame:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, (-self.spacing or 0))
end
else
if self == anchor then -- Root frame so indent for icon
frame:SetPoint("BOTTOMLEFT", anchor, "BOTTOMLEFT", (frame:GetHeight() + (self.gap or 0)), 1)
else
frame:SetPoint("BOTTOMLEFT", anchor, "TOPLEFT", 0, (self.spacing or 0))
end
end
end
end
local function CreateAuraBar(oUF, anchor)
local auraBarParent = oUF.AuraBars
local frame = CreateFrame("Frame", nil, auraBarParent)
frame:SetHeight(auraBarParent.auraBarHeight or 20)
frame:SetWidth((auraBarParent.auraBarWidth or auraBarParent:GetWidth()) - (frame:GetHeight() + (auraBarParent.gap or 0)))
frame.anchor = anchor
-- the main bar
local statusBar = CreateFrame("StatusBar", nil, frame)
statusBar:SetStatusBarTexture(auraBarParent.auraBarTexture or [[Interface\TargetingFrame\UI-StatusBar]])
statusBar:SetAlpha(auraBarParent.fgalpha or 1)
statusBar:SetAllPoints(frame)
frame.statusBar = statusBar
if auraBarParent.down == true then
if auraBarParent == anchor then -- Root frame so indent for icon
frame:SetPoint("TOPLEFT", anchor, "TOPLEFT", (frame:GetHeight() + (auraBarParent.gap or 0) ), -1)
else
frame:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, (-auraBarParent.spacing or 0))
end
else
if auraBarParent == anchor then -- Root frame so indent for icon
frame:SetPoint("BOTTOMLEFT", anchor, "BOTTOMLEFT", (frame:GetHeight() + (auraBarParent.gap or 0)), 1)
else
frame:SetPoint("BOTTOMLEFT", anchor, "TOPLEFT", 0, (auraBarParent.spacing or 0))
end
end
local spark = statusBar:CreateTexture(nil, "OVERLAY", nil)
spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
spark:SetWidth(12)
spark:SetBlendMode("ADD")
spark:SetPoint("CENTER", statusBar:GetStatusBarTexture(), "RIGHT")
statusBar.spark = spark
statusBar.iconHolder = CreateFrame("Button", nil, statusBar)
statusBar.iconHolder:SetHeight(frame:GetHeight())
statusBar.iconHolder:SetWidth(frame:GetHeight())
statusBar.iconHolder:SetPoint("BOTTOMRIGHT", frame, "BOTTOMLEFT", -auraBarParent.gap, 0)
statusBar.iconHolder.__unit = oUF.unit
statusBar.iconHolder:SetScript("OnEnter", OnEnter)
statusBar.iconHolder:SetScript("OnLeave", OnLeave)
statusBar.iconHolder.UpdateTooltip = UpdateTooltip
statusBar.icon = statusBar.iconHolder:CreateTexture(nil, "BACKGROUND")
statusBar.icon:SetTexCoord(.07, .93, .07, .93)
statusBar.icon:SetAllPoints()
statusBar.spelltime = statusBar:CreateFontString(nil, "ARTWORK")
if auraBarParent.spellTimeObject then
statusBar.spelltime:SetFontObject(auraBarParent.spellTimeObject)
else
statusBar.spelltime:SetFont(auraBarParent.spellTimeFont or [[Fonts\FRIZQT__.TTF]], auraBarParent.spellTimeSize or 10)
end
statusBar.spelltime:SetTextColor(1, 1, 1)
statusBar.spelltime:SetJustifyH("RIGHT")
statusBar.spelltime:SetJustifyV("CENTER")
statusBar.spelltime:SetPoint("RIGHT", 0, 0)
statusBar.spellname = statusBar:CreateFontString(nil, "ARTWORK")
if auraBarParent.spellNameObject then
statusBar.spellname:SetFontObject(auraBarParent.spellNameObject)
else
statusBar.spellname:SetFont(auraBarParent.spellNameFont or [[Fonts\FRIZQT__.TTF]], auraBarParent.spellNameSize or 10)
end
statusBar.spellname:SetTextColor(1, 1, 1)
statusBar.spellname:SetJustifyH("LEFT")
statusBar.spellname:SetJustifyV("CENTER")
statusBar.spellname:SetPoint("LEFT", 0, 0)
statusBar.spellname:SetPoint("RIGHT", statusBar.spelltime, "LEFT")
if auraBarParent.PostCreateBar then
auraBarParent.PostCreateBar(frame)
end
return frame
end
local function UpdateBars(auraBars)
local bars = auraBars.bars
local timenow = GetTime()
for index = 1, getn(bars) do
local frame = bars[index]
local bar = frame.statusBar
if not frame:IsVisible() then
break
end
if bar.aura.noTime then
bar.spelltime:SetText()
bar.spark:Hide()
else
local timeleft = bar.aura.expirationTime - timenow
bar:SetValue(timeleft)
bar.spelltime:SetText(FormatTime(timeleft))
if auraBars.spark == true then
if (auraBars.scaleTime and ((auraBars.scaleTime <= 0) or (auraBars.scaleTime > 0 and timeleft < auraBars.scaleTime))) then
bar.spark:Show()
else
bar.spark:Hide()
end
end
end
end
end
local function DefaultFilter(self, unit, name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate)
if unitCaster == "player" and not shouldConsolidate then
return true
end
end
local sort = function(a, b)
local compa, compb = a.noTime and huge or a.expirationTime, b.noTime and huge or b.expirationTime
return compa > compb
end
local function Update(self, event, unit)
if self.unit ~= unit then return end
local auraBars = self.AuraBars
local helpOrHarm
local isFriend = UnitIsFriend("player", unit) == 1 and true or false
local both = false
if auraBars.friendlyAuraType and auraBars.enemyAuraType then
if isFriend then
helpOrHarm = auraBars.friendlyAuraType
else
helpOrHarm = auraBars.enemyAuraType
end
else
helpOrHarm = isFriend and "HELPFUL" or "HARMFUL"
end
if helpOrHarm == "BOTH" then
both = true
helpOrHarm = "HELPFUL"
end
-- Create a table of auras to display
local auras = {}
local lastAuraIndex = 0
local counter = 0
if auraBars.forceShow then
for index = 1, auraBars.maxBars do
local spellID = 47540
local name, rank, icon = GetSpellInfo(spellID)
local count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate = 5, "Magic", 0, 0, "player", nil, nil
lastAuraIndex = lastAuraIndex + 1
auras[lastAuraIndex] = {}
auras[lastAuraIndex].spellID = spellID
auras[lastAuraIndex].name = name
auras[lastAuraIndex].rank = rank
auras[lastAuraIndex].icon = icon
auras[lastAuraIndex].count = count
auras[lastAuraIndex].debuffType = debuffType
auras[lastAuraIndex].duration = duration
auras[lastAuraIndex].expirationTime = expirationTime
auras[lastAuraIndex].unitCaster = unitCaster
auras[lastAuraIndex].isStealable = isStealable
auras[lastAuraIndex].noTime = (duration == 0 and expirationTime == 0)
auras[lastAuraIndex].filter = helpOrHarm
auras[lastAuraIndex].shouldConsolidate = shouldConsolidate
end
else
for index = 1, 40 do
local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellID
if not both then
name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellID = UnitAura(unit, index, helpOrHarm)
if not name then break end
else
name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellID = UnitAura(unit, index, "HELPFUL")
if not name then
name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellID = UnitAura(unit, index, "HARMFUL")
if not name then break end
end
end
if (auraBars.filter or DefaultFilter)(self, unit, name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellID) then
lastAuraIndex = lastAuraIndex + 1
auras[lastAuraIndex] = {}
auras[lastAuraIndex].spellID = spellID
auras[lastAuraIndex].name = name
auras[lastAuraIndex].rank = rank
auras[lastAuraIndex].icon = icon
auras[lastAuraIndex].count = count
auras[lastAuraIndex].debuffType = debuffType
auras[lastAuraIndex].duration = duration
auras[lastAuraIndex].expirationTime = expirationTime
auras[lastAuraIndex].unitCaster = unitCaster
auras[lastAuraIndex].isStealable = isStealable
auras[lastAuraIndex].noTime = (duration == 0 and expirationTime == 0)
auras[lastAuraIndex].filter = helpOrHarm
auras[lastAuraIndex].shouldConsolidate = shouldConsolidate
end
end
end
if auraBars.sort and not auraBars.forceShow then
tsort(auras, type(auraBars.sort) == "function" and auraBars.sort or sort)
end
for i=1, getn(auras) do
if i > auraBars.maxBars then
tremove(auras, i)
else
lastAuraIndex = i
end
end
-- Show and configure bars for buffs/debuffs.
local bars = auraBars.bars
if lastAuraIndex == 0 then
self.AuraBars:SetHeight(1)
end
for index = 1 , lastAuraIndex do
-- if auraBars:GetWidth() == 0 then break end
local aura = auras[index]
local frame = bars[index]
if not frame then
frame = CreateAuraBar(self, index == 1 and auraBars or bars[index - 1])
bars[index] = frame
end
if index == lastAuraIndex then
if self.AuraBars.down then
self.AuraBars:SetHeight(self.AuraBars:GetTop() - frame:GetBottom())
elseif frame:GetTop() and self.AuraBars:GetBottom() then
self.AuraBars:SetHeight(frame:GetTop() - self.AuraBars:GetBottom())
else
self.AuraBars:SetHeight(20)
end
end
local bar = frame.statusBar
frame.index = index
-- Backup the details of the aura onto the bar, so the OnUpdate function can use it
bar.aura = aura
-- Configure
if bar.aura.noTime then
bar:SetMinMaxValues(0, 1)
bar:SetValue(1)
else
if auraBars.scaleTime and auraBars.scaleTime > 0 then
local maxvalue = min(auraBars.scaleTime, bar.aura.duration)
bar:SetMinMaxValues(0, auraBars.scaleTime)
bar:SetWidth(
( maxvalue / auraBars.scaleTime ) *
( ( auraBars.auraBarWidth or auraBars:GetWidth() ) -
( bar:GetHeight() + (auraBars.gap or 0) ) ) ) -- icon size + gap
else
bar:SetMinMaxValues(0, bar.aura.duration)
end
bar:SetValue(bar.aura.expirationTime - GetTime())
end
bar.icon:SetTexture(bar.aura.icon)
-- bar.spellname:SetText(bar.aura.count > 1 and format("%s [%d]", bar.aura.name, bar.aura.count) or bar.aura.name)
bar.spelltime:SetText(not bar.noTime and FormatTime(bar.aura.expirationTime-GetTime()))
-- Colour bars
local r, g, b = .2, .6, 1 -- Colour for buffs
if auraBars.buffColor then
r, g, b = unpack(auraBars.buffColor)
end
if helpOrHarm == "HARMFUL" then
local debuffType = bar.aura.debuffType and bar.aura.debuffType or "none"
r, g, b = DebuffTypeColor[debuffType].r, DebuffTypeColor[debuffType].g, DebuffTypeColor[debuffType].b
if auraBars.debuffColor then
r, g, b = unpack(auraBars.debuffColor)
else
if debuffType == "none" and auraBars.defaultDebuffColor then
r, g, b = unpack(auraBars.defaultDebuffColor)
end
end
end
bar:SetStatusBarColor(r, g, b)
frame:Show()
end
-- Hide unused bars.
for index = lastAuraIndex + 1, getn(bars) do
bars[index]:Hide()
end
if auraBars.PostUpdate then
auraBars:PostUpdate(event, unit)
end
end
local function Enable(self)
if self.AuraBars then
self:RegisterEvent("PLAYER_AURAS_CHANGED")
self:SetScript("OnEvent", function() Update(self, event, "player") end)
self.AuraBars:SetHeight(1)
self.AuraBars.bars = self.AuraBars.bars or {}
self.AuraBars.SetAnchors = SetAnchors
self.AuraBars:SetScript("OnUpdate", function() UpdateBars(self.AuraBars) end)
self.AuraBars.maxBars = self.AuraBars.maxBars or 40
return true
end
end
local function Disable(self)
local auraFrame = self.AuraBars
if auraFrame then
self:UnregisterEvent("PLAYER_AURAS_CHANGED", Update)
auraFrame:SetScript("OnUpdate", nil)
end
end
oUF:AddElement("AuraBars", Update, Enable, Disable)
@@ -0,0 +1,3 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="oUF_AuraBars.lua"/>
</Ui>
+5 -3
View File
@@ -12,13 +12,15 @@ local format = string.format
local wipe, tinsert, tsort, tremove = table.wipe, table.insert, table.sort, table.remove
--WoW API / Variables
local CreateFrame = CreateFrame
local UnitAura = UnitAura
local CancelItemTempEnchantment = CancelItemTempEnchantment
local CancelUnitBuff = CancelUnitBuff
local GetInventoryItemQuality = GetInventoryItemQuality
local GetItemQualityColor = GetItemQualityColor
local GetWeaponEnchantInfo = GetWeaponEnchantInfo
local GetInventoryItemTexture = GetInventoryItemTexture
local GetPlayerBuff = GetPlayerBuff
local GetPlayerBuffTexture = GetPlayerBuffTexture
local GetPlayerBuffApplications = GetPlayerBuffApplications
local GetPlayerBuffDispelType = GetPlayerBuffDispelType
local GetPlayerBuffTimeLeft = GetPlayerBuffTimeLeft
local DIRECTION_TO_POINT = {
DOWN_RIGHT = "TOPLEFT",
@@ -0,0 +1,288 @@
local E, L, V, P, G = unpack(ElvUI) --Inport: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local UF = E:GetModule("UnitFrames")
--Cache global variables
--Lua functions
local match = string.match
local strsplit = strsplit
local tostring = tostring
local format = format
local select = select
local getn = table.getn
--WoW API / Variables
local CreateFrame = CreateFrame
local IsShiftKeyDown = IsShiftKeyDown
local IsAltKeyDown = IsAltKeyDown
local IsControlKeyDown = IsControlKeyDown
local UnitIsFriend = UnitIsFriend
local UnitIsUnit = UnitIsUnit
local UnitCanAttack = UnitCanAttack
local RAID_CLASS_COLORS = RAID_CLASS_COLORS
function UF:Construct_AuraBars()
local bar = self.statusBar
E:SetTemplate(self, "Default", nil, nil, UF.thinBorders, true)
local inset = UF.thinBorders and E.mult or nil
E:SetInside(bar, self, inset, inset)
UF["statusbars"][bar] = true
UF:Update_StatusBar(bar)
UF:Configure_FontString(bar.spelltime)
UF:Configure_FontString(bar.spellname)
UF:Update_FontString(bar.spelltime)
UF:Update_FontString(bar.spellname)
bar.spellname:ClearAllPoints()
E:Point(bar.spellname, "LEFT", bar, "LEFT", 2, 0)
E:Point(bar.spellname, "RIGHT", bar.spelltime, "LEFT", -4, 0)
-- bar.spellname:SetWordWrap(false)
E:SetTemplate(bar.iconHolder, "Default", nil, nil, UF.thinBorders, true)
E:SetInside(bar.icon, bar.iconHolder, inset, inset)
bar.icon:SetDrawLayer("OVERLAY")
bar.bg = bar:CreateTexture(nil, "BORDER")
bar.bg:Hide()
bar.iconHolder:RegisterForClicks("RightButtonUp")
bar.iconHolder:SetScript("OnClick", function(self)
if E.db.unitframe.auraBlacklistModifier == "NONE" or not ((E.db.unitframe.auraBlacklistModifier == "SHIFT" and IsShiftKeyDown()) or (E.db.unitframe.auraBlacklistModifier == "ALT" and IsAltKeyDown()) or (E.db.unitframe.auraBlacklistModifier == "CTRL" and IsControlKeyDown())) then return; end
local auraName = self:GetParent().aura.name
if auraName then
E:Print(format(L["The spell '%s' has been added to the Blacklist unitframe aura filter."], auraName))
E.global["unitframe"]["aurafilters"]["Blacklist"]["spells"][auraName] = {
["enable"] = true,
["priority"] = 0,
}
UF:Update_AllFrames()
end
end)
end
function UF:Construct_AuraBarHeader(frame)
local auraBar = CreateFrame("Frame", nil, frame)
auraBar:SetFrameLevel(frame.RaisedElementParent:GetFrameLevel() + 10) --Make them appear above any text element
auraBar.PostCreateBar = UF.Construct_AuraBars
auraBar.gap = (-frame.BORDER + frame.SPACING*3)
auraBar.spacing = (-frame.BORDER + frame.SPACING*3)
auraBar.spark = true
auraBar.filter = UF.AuraBarFilter
auraBar.PostUpdate = UF.ColorizeAuraBars
return auraBar
end
function UF:Configure_AuraBars(frame)
if not frame.VARIABLES_SET then return end
local auraBars = frame.AuraBars
local db = frame.db
if db.aurabar.enable then
if not frame:IsElementEnabled("AuraBars") then
frame:EnableElement("AuraBars")
end
auraBars:Show()
auraBars.friendlyAuraType = db.aurabar.friendlyAuraType
auraBars.enemyAuraType = db.aurabar.enemyAuraType
auraBars.scaleTime = db.aurabar.uniformThreshold
local buffColor = self.db.colors.auraBarBuff
local debuffColor = self.db.colors.auraBarDebuff
local attachTo = frame
if E:CheckClassColor(buffColor.r, buffColor.g, buffColor.b) then
buffColor = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass])
end
if E:CheckClassColor(debuffColor.r, debuffColor.g, debuffColor.b) then
debuffColor = E.myclass == "PRIEST" and E.PriestColors or (CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS[E.myclass] or RAID_CLASS_COLORS[E.myclass])
end
if db.aurabar.attachTo == "BUFFS" then
attachTo = frame.Buffs
elseif db.aurabar.attachTo == "DEBUFFS" then
attachTo = frame.Debuffs
elseif db.aurabar.attachTo == "PLAYER_AURABARS" and ElvUF_Player then
attachTo = ElvUF_Player.AuraBars
end
local anchorPoint, anchorTo = "BOTTOM", "TOP"
if db.aurabar.anchorPoint == "BELOW" then
anchorPoint, anchorTo = "TOP", "BOTTOM"
end
local yOffset
local spacing = (((db.aurabar.attachTo == "FRAME" and 3) or (db.aurabar.attachTo == "PLAYER_AURABARS" and 4) or 2) * frame.SPACING)
local border = (((db.aurabar.attachTo == "FRAME" or db.aurabar.attachTo == "PLAYER_AURABARS") and 2 or 1) * frame.BORDER)
if db.aurabar.anchorPoint == "BELOW" then
yOffset = -spacing + border - (not db.aurabar.yOffset and 0 or db.aurabar.yOffset)
else
yOffset = spacing - border + (not db.aurabar.yOffset and 0 or db.aurabar.yOffset)
end
local xOffset = (db.aurabar.attachTo == "FRAME" and frame.SPACING or 0)
local offsetLeft = xOffset + ((db.aurabar.attachTo == "FRAME" and ((anchorTo == "TOP" and frame.ORIENTATION ~= "LEFT") or (anchorTo == "BOTTOM" and frame.ORIENTATION == "LEFT"))) and frame.POWERBAR_OFFSET or 0)
local offsetRight = -xOffset - ((db.aurabar.attachTo == "FRAME" and ((anchorTo == "TOP" and frame.ORIENTATION ~= "RIGHT") or (anchorTo == "BOTTOM" and frame.ORIENTATION == "RIGHT"))) and frame.POWERBAR_OFFSET or 0)
auraBars.auraBarHeight = db.aurabar.height
auraBars:ClearAllPoints()
E:Point(auraBars, anchorPoint.."LEFT", attachTo, anchorTo.."LEFT", offsetLeft, yOffset)
E:Point(auraBars, anchorPoint.."RIGHT", attachTo, anchorTo.."RIGHT", offsetRight, yOffset)
auraBars.buffColor = {buffColor.r, buffColor.g, buffColor.b}
if UF.db.colors.auraBarByType then
auraBars.debuffColor = nil;
auraBars.defaultDebuffColor = {debuffColor.r, debuffColor.g, debuffColor.b}
else
auraBars.debuffColor = {debuffColor.r, debuffColor.g, debuffColor.b}
auraBars.defaultDebuffColor = nil;
end
auraBars.down = db.aurabar.anchorPoint == "BELOW"
if db.aurabar.sort == "TIME_REMAINING" then
auraBars.sort = true --default function
elseif db.aurabar.sort == "TIME_REMAINING_REVERSE" then
auraBars.sort = self.SortAuraBarReverse
elseif db.aurabar.sort == "TIME_DURATION" then
auraBars.sort = self.SortAuraBarDuration
elseif db.aurabar.sort == "TIME_DURATION_REVERSE" then
auraBars.sort = self.SortAuraBarDurationReverse
elseif db.aurabar.sort == "NAME" then
auraBars.sort = self.SortAuraBarName
else
auraBars.sort = nil
end
auraBars.maxBars = db.aurabar.maxBars
auraBars.forceShow = frame.forceShowAuras
-- auraBars:SetAnchors()
else
if frame:IsElementEnabled("AuraBars") then
frame:DisableElement("AuraBars")
auraBars:Hide()
end
end
end
local huge = math.huge
function UF.SortAuraBarReverse(a, b)
local compa, compb = a.noTime and huge or a.expirationTime, b.noTime and huge or b.expirationTime
return compa < compb
end
function UF.SortAuraBarDuration(a, b)
local compa, compb = a.noTime and huge or a.duration, b.noTime and huge or b.duration
return compa > compb
end
function UF.SortAuraBarDurationReverse(a, b)
local compa, compb = a.noTime and huge or a.duration, b.noTime and huge or b.duration
return compa < compb
end
function UF.SortAuraBarName(a, b)
return a.name > b.name
end
function UF:CheckFilter(name, caster, spellID, isFriend, isPlayer, isUnit, allowDuration, noDuration, canDispell, ...)
-- local friendCheck, filterName, filter, filterType, spellList, spell
-- for i=1, select("#", ...) do
-- filterName = select(i, ...)
-- friendCheck = (isFriend and match(filterName, "^Friendly:([^,]*)")) or (not isFriend and match(filterName, "^Enemy:([^,]*)")) or nil
-- if friendCheck ~= false then
-- if friendCheck ~= nil and (G.unitframe.specialFilters[friendCheck] or E.global.unitframe.aurafilters[friendCheck]) then
-- filterName = friendCheck -- this is for our filters to handle Friendly and Enemy
-- end
-- filter = E.global.unitframe.aurafilters[filterName]
-- if filter then
-- filterType = filter.type
-- spellList = filter.spells
-- spell = spellList and (spellList[spellID] or spellList[name])
-- if filterType and (filterType == "Whitelist") and (spell and spell.enable) and allowDuration then
-- return true, spell.priority -- this is the only difference from auarbars code
-- elseif filterType and (filterType == "Blacklist") and (spell and spell.enable) then
-- return false
-- end
-- elseif filterName == "Personal" and isPlayer and allowDuration then
-- return true
-- elseif filterName == "nonPersonal" and (not isPlayer) and allowDuration then
-- return true
-- elseif filterName == "CastByUnit" and (caster and isUnit) and allowDuration then
-- return true
-- elseif filterName == "notCastByUnit" and (caster and not isUnit) and allowDuration then
-- return true
-- elseif filterName == "Dispellable" and canDispell and allowDuration then
-- return true
-- elseif filterName == "blockNoDuration" and noDuration then
-- return false
-- elseif filterName == "blockNonPersonal" and (not isPlayer) then
-- return false
-- end
-- end
-- end
return true
end
function UF:AuraBarFilter(unit, name, _, _, _, debuffType, duration, _, unitCaster, isStealable, _, spellID)
if not self.db then return; end
local db = self.db.aurabar
if not name then return nil end
local filterCheck, isUnit, isFriend, isPlayer, canDispell, allowDuration, noDuration
if db.priority ~= "" then
noDuration = (not duration or duration == 0)
isFriend = unit and UnitIsFriend("player", unit) and not UnitCanAttack("player", unit)
isPlayer = (unitCaster == "player" or unitCaster == "vehicle")
isUnit = unit and unitCaster and UnitIsUnit(unit, unitCaster)
canDispell = (self.type == "Buffs" and isStealable) or (self.type == "Debuffs" and debuffType and E:IsDispellableByMe(debuffType))
allowDuration = noDuration or (duration and (duration > 0) and (db.maxDuration == 0 or duration <= db.maxDuration) and (db.minDuration == 0 or duration >= db.minDuration))
filterCheck = UF:CheckFilter(name, unitCaster, spellID, isFriend, isPlayer, isUnit, allowDuration, noDuration, canDispell, strsplit(",", db.priority))
else
filterCheck = true -- Allow all auras to be shown when the filter list is empty
end
return filterCheck
end
function UF:ColorizeAuraBars()
local bars = self.bars
for index = 1, getn(bars) do
local frame = bars[index]
if not frame:IsVisible() then break end
local spellName = frame.statusBar.aura.name
local spellID = frame.statusBar.aura.spellID
-- local colors = E.global.unitframe.AuraBarColors[spellID] or E.global.unitframe.AuraBarColors[tostring(spellID)] or E.global.unitframe.AuraBarColors[spellName]
-- if E.db.unitframe.colors.auraBarTurtle and (E.global.unitframe.aurafilters.TurtleBuffs.spells[spellID] or E.global.unitframe.aurafilters.TurtleBuffs.spells[spellName]) and not colors then
-- colors = E.db.unitframe.colors.auraBarTurtleColor
-- end
if colors then
frame.statusBar:SetStatusBarColor(colors.r, colors.g, colors.b)
frame.statusBar.bg:SetTexture(colors.r * 0.25, colors.g * 0.25, colors.b * 0.25)
else
local r, g, b = frame.statusBar:GetStatusBarColor()
frame.statusBar.bg:SetTexture(r * 0.25, g * 0.25, b * 0.25)
end
if UF.db.colors.transparentAurabars and not frame.statusBar.isTransparent then
UF:ToggleTransparentStatusBar(true, frame.statusBar, frame.statusBar.bg, nil, true)
elseif(frame.statusBar.isTransparent and not UF.db.colors.transparentAurabars) then
UF:ToggleTransparentStatusBar(false, frame.statusBar, frame.statusBar.bg, nil, true)
end
if UF.db.colors.transparentAurabars then
local _, _, _, alpha = frame:GetBackdropColor()
if colors then
frame:SetBackdropColor(colors.r * 0.58, colors.g * 0.58, colors.b * 0.58, alpha)
else
local r, g, b = frame.statusBar:GetStatusBarColor()
frame:SetBackdropColor(r * 0.58, g * 0.58, b * 0.58, alpha)
end
end
end
end
+592
View File
@@ -0,0 +1,592 @@
local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local UF = E:GetModule("UnitFrames");
local LSM = LibStub("LibSharedMedia-3.0");
--Cache global variables
--Lua functions
local unpack = unpack
local find, format, lower = string.find, string.format, string.lower
local strsplit = strsplit
local tsort, getn = table.sort, table.getn
local ceil = math.ceil
--WoW API / Variables
local GetTime = GetTime
local CreateFrame = CreateFrame
local IsShiftKeyDown = IsShiftKeyDown
local IsAltKeyDown = IsAltKeyDown
local IsControlKeyDown = IsControlKeyDown
local UnitCanAttack = UnitCanAttack
local UnitIsFriend = UnitIsFriend
local UnitIsUnit = UnitIsUnit
function UF:Construct_Buffs(frame)
local buffs = CreateFrame("Frame", frame:GetName().."Buffs", frame)
buffs.spacing = E.Spacing
buffs.PreSetPosition = (not frame:GetScript("OnUpdate")) and self.SortAuras or nil
buffs.PostCreateIcon = self.Construct_AuraIcon
buffs.PostUpdateIcon = self.PostUpdateAura
buffs.CustomFilter = self.AuraFilter
buffs:SetFrameLevel(frame.RaisedElementParent:GetFrameLevel() + 10) --Make them appear above any text element
buffs.type = "buffs"
--Set initial width to prevent division by zero. This value doesn't matter, as it will be updated later
E:Width(buffs, 100)
return buffs
end
function UF:Construct_Debuffs(frame)
local debuffs = CreateFrame("Frame", frame:GetName().."Debuffs", frame)
debuffs.spacing = E.Spacing
debuffs.PreSetPosition = (not frame:GetScript("OnUpdate")) and self.SortAuras or nil
debuffs.PostCreateIcon = self.Construct_AuraIcon
debuffs.PostUpdateIcon = self.PostUpdateAura
debuffs.CustomFilter = self.AuraFilter
debuffs.type = "debuffs"
debuffs:SetFrameLevel(frame.RaisedElementParent:GetFrameLevel() + 10) --Make them appear above any text element
--Set initial width to prevent division by zero. This value doesn't matter, as it will be updated later
E:Width(debuffs, 100)
return debuffs
end
function UF:Construct_AuraIcon(button)
local offset = UF.thinBorders and E.mult or E.Border
button.text = button.cd:CreateFontString(nil, "OVERLAY")
E:Point(button.text, "CENTER", 1, 1)
button.text:SetJustifyH("CENTER")
E:SetTemplate(button, "Default", nil, nil, UF.thinBorders, true)
button.cd.noOCC = true
button.cd.noCooldownCount = true
-- button.cd:SetReverse(true)
-- button.cd:SetDrawEdge(true)
E:SetInside(button.cd, button, offset, offset)
E:SetInside(button.icon, button, offset, offset)
button.icon:SetTexCoord(unpack(E.TexCoords))
button.icon:SetDrawLayer("ARTWORK")
button.count:ClearAllPoints()
E:Point(button.count, "BOTTOMRIGHT", 1, 1)
button.count:SetJustifyH("RIGHT")
button.overlay:SetTexture(nil)
-- button.stealable:SetTexture(nil)
button:RegisterForClicks("RightButtonUp")
button:SetScript("OnClick", function(self)
if E.db.unitframe.auraBlacklistModifier == "NONE"
or not ((E.db.unitframe.auraBlacklistModifier == "SHIFT" and IsShiftKeyDown())
or (E.db.unitframe.auraBlacklistModifier == "ALT" and IsAltKeyDown())
or (E.db.unitframe.auraBlacklistModifier == "CTRL" and IsControlKeyDown())) then return end
local auraName = self.name
if auraName then
E:Print(format(L["The spell '%s' has been added to the Blacklist unitframe aura filter."], auraName))
E.global["unitframe"]["aurafilters"]["Blacklist"]["spells"][auraName] = {
["enable"] = true,
["priority"] = 0,
}
UF:Update_AllFrames()
end
end)
UF:UpdateAuraIconSettings(button, true)
end
function UF:EnableDisable_Auras(frame)
if frame.db.debuffs.enable or frame.db.buffs.enable then
if not frame:IsElementEnabled("Aura") then
frame:EnableElement("Aura")
end
else
if frame:IsElementEnabled("Aura") then
frame:DisableElement("Aura")
end
end
end
local function ReverseUpdate(frame)
UF:Configure_Auras(frame, "Debuffs")
UF:Configure_Auras(frame, "Buffs")
end
function UF:Configure_Auras(frame, auraType)
if not frame.VARIABLES_SET then return end
local db = frame.db
local auras = frame[auraType]
auraType = lower(auraType)
local rows = db[auraType].numrows
local totalWidth = frame.UNIT_WIDTH - frame.SPACING*2
if frame.USE_POWERBAR_OFFSET then
local powerOffset = ((frame.ORIENTATION == "MIDDLE" and 2 or 1) * frame.POWERBAR_OFFSET)
if not (db[auraType].attachTo == "POWER" and frame.ORIENTATION == "MIDDLE") then
totalWidth = totalWidth - powerOffset
end
end
E:Width(auras, totalWidth)
auras.forceShow = frame.forceShowAuras
auras.num = db[auraType].perrow * rows
auras.size = db[auraType].sizeOverride ~= 0 and db[auraType].sizeOverride or ((((auras:GetWidth() - (auras.spacing*(auras.num/rows - 1))) / auras.num)) * rows)
if db[auraType].sizeOverride and db[auraType].sizeOverride > 0 then
auras:Width(db[auraType].perrow * db[auraType].sizeOverride)
end
local attachTo = self:GetAuraAnchorFrame(frame, db[auraType].attachTo, db.debuffs.attachTo == "BUFFS" and db.buffs.attachTo == "DEBUFFS")
--Use frame.SPACING override since it may be different from E.Spacing due to forced thin borders
local x, y = E:GetXYOffset(db[auraType].anchorPoint, frame.SPACING)
if db[auraType].attachTo == "FRAME" then
y = 0
elseif db[auraType].attachTo == "HEALTH" or db[auraType].attachTo == "POWER" then
local newX = E:GetXYOffset(db[auraType].anchorPoint, -frame.BORDER)
local _, newY = E:GetXYOffset(db[auraType].anchorPoint, (frame.BORDER + frame.SPACING))
x = newX
y = newY
else
x = 0
end
if auraType == "buffs" and frame.Debuffs.attachTo and frame.Debuffs.attachTo == frame.Buffs and db[auraType].attachTo == "DEBUFFS" then
--Update Debuffs first, as we would otherwise get conflicting anchor points
--This is usually only an issue on profile change
ReverseUpdate(frame)
return
end
auras:ClearAllPoints()
E:Point(auras, E.InversePoints[db[auraType].anchorPoint], attachTo, db[auraType].anchorPoint, x + db[auraType].xOffset, y + db[auraType].yOffset)
E:Height(auras, auras.size * rows)
auras["growth-y"] = find(db[auraType].anchorPoint, "TOP") and "UP" or "DOWN"
auras["growth-x"] = db[auraType].anchorPoint == "LEFT" and "LEFT" or db[auraType].anchorPoint == "RIGHT" and "RIGHT" or (find(db[auraType].anchorPoint, "LEFT") and "RIGHT" or "LEFT")
auras.initialAnchor = E.InversePoints[db[auraType].anchorPoint]
--These are needed for SmartAuraPosition
auras.attachTo = attachTo
auras.point = E.InversePoints[db[auraType].anchorPoint]
auras.anchorPoint = db[auraType].anchorPoint
auras.xOffset = x + db[auraType].xOffset
auras.yOffset = y + db[auraType].yOffset
if db[auraType].enable then
auras:Show()
UF:UpdateAuraIconSettings(auras)
else
auras:Hide()
end
local position = db.smartAuraPosition
if position == "BUFFS_ON_DEBUFFS" then
if db.debuffs.attachTo == "BUFFS" then
E:Print(format(L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."], L["Buffs"], L["Debuffs"], L["Frame"]))
db.debuffs.attachTo = "FRAME"
frame.Debuffs.attachTo = frame
end
frame.Buffs.PostUpdate = nil
frame.Debuffs.PostUpdate = UF.UpdateBuffsHeaderPosition
elseif position == "DEBUFFS_ON_BUFFS" then
if db.buffs.attachTo == "DEBUFFS" then
E:Print(format(L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."], L["Debuffs"], L["Buffs"], L["Frame"]))
db.buffs.attachTo = "FRAME"
frame.Buffs.attachTo = frame
end
frame.Buffs.PostUpdate = UF.UpdateDebuffsHeaderPosition
frame.Debuffs.PostUpdate = nil
elseif position == "FLUID_BUFFS_ON_DEBUFFS" then
if db.debuffs.attachTo == "BUFFS" then
E:Print(format(L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."], L["Buffs"], L["Debuffs"], L["Frame"]))
db.debuffs.attachTo = "FRAME"
frame.Debuffs.attachTo = frame
end
frame.Buffs.PostUpdate = UF.UpdateBuffsHeight
frame.Debuffs.PostUpdate = UF.UpdateBuffsPositionAndDebuffHeight
elseif position == "FLUID_DEBUFFS_ON_BUFFS" then
if db.buffs.attachTo == "DEBUFFS" then
E:Print(format(L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."], L["Debuffs"], L["Buffs"], L["Frame"]))
db.buffs.attachTo = "FRAME"
frame.Buffs.attachTo = frame
end
frame.Buffs.PostUpdate = UF.UpdateDebuffsPositionAndBuffHeight
frame.Debuffs.PostUpdate = UF.UpdateDebuffsHeight
else
frame.Buffs.PostUpdate = nil
frame.Debuffs.PostUpdate = nil
end
end
local function SortAurasByTime(a, b)
if a and b and a:GetParent().db then
if a:IsShown() and b:IsShown() then
local sortDirection = a:GetParent().db.sortDirection
local aTime = a.expiration or -1
local bTime = b.expiration or -1
if aTime and bTime then
if sortDirection == "DESCENDING" then
return aTime < bTime
else
return aTime > bTime
end
end
elseif a:IsShown() then
return true
end
end
end
local function SortAurasByName(a, b)
if a and b and a:GetParent().db then
if a:IsShown() and b:IsShown() then
local sortDirection = a:GetParent().db.sortDirection
local aName = a.spell or ""
local bName = b.spell or ""
if aName and bName then
if sortDirection == "DESCENDING" then
return aName < bName
else
return aName > bName
end
end
elseif a:IsShown() then
return true
end
end
end
local function SortAurasByDuration(a, b)
if a and b and a:GetParent().db then
if a:IsShown() and b:IsShown() then
local sortDirection = a:GetParent().db.sortDirection
local aTime = a.duration or -1
local bTime = b.duration or -1
if aTime and bTime then
if sortDirection == "DESCENDING" then
return aTime < bTime
else
return aTime > bTime
end
end
elseif a:IsShown() then
return true
end
end
end
local function SortAurasByCaster(a, b)
if a and b and a:GetParent().db then
if a:IsShown() and b:IsShown() then
local sortDirection = a:GetParent().db.sortDirection
local aPlayer = a.isPlayer or false
local bPlayer = b.isPlayer or false
if sortDirection == "DESCENDING" then
return (aPlayer and not bPlayer)
else
return (not aPlayer and bPlayer)
end
elseif a:IsShown() then
return true
end
end
end
function UF:SortAuras()
if not self.db then return end
--Sorting by Index is Default
if self.db.sortMethod == "TIME_REMAINING" then
tsort(self, SortAurasByTime)
elseif self.db.sortMethod == "NAME" then
tsort(self, SortAurasByName)
elseif self.db.sortMethod == "DURATION" then
tsort(self, SortAurasByDuration)
elseif self.db.sortMethod == "PLAYER" then
tsort(self, SortAurasByCaster)
end
--Look into possibly applying filter priorities for auras here.
return 1, getn(self) --from/to range needed for the :SetPosition call in oUF aura element. Without this aura icon position gets all whacky when not sorted by index
end
function UF:UpdateAuraIconSettings(auras, noCycle)
local frame = auras:GetParent()
local type = auras.type
if noCycle then
frame = auras:GetParent():GetParent()
type = auras:GetParent().type
end
if not frame.db then return end
local db = frame.db[type]
local unitframeFont = LSM:Fetch("font", E.db["unitframe"].font)
local unitframeFontOutline = E.db["unitframe"].fontOutline
local index = 1
auras.db = db
if db then
if not noCycle then
while auras[index] do
local button = auras[index]
E:FontTemplate(button.text, unitframeFont, db.fontSize, unitframeFontOutline)
E:FontTemplate(button.count, unitframeFont, db.countFontSize or db.fontSize, unitframeFontOutline)
if db.clickThrough and button:IsMouseEnabled() then
button:EnableMouse(false)
elseif not db.clickThrough and not button:IsMouseEnabled() then
button:EnableMouse(true)
end
index = index + 1
end
else
E:FontTemplate(auras.text, unitframeFont, db.fontSize, unitframeFontOutline)
E:FontTemplate(auras.count, unitframeFont, db.countFontSize or db.fontSize, unitframeFontOutline)
if db.clickThrough and auras:IsMouseEnabled() then
auras:EnableMouse(false)
elseif not db.clickThrough and not auras:IsMouseEnabled() then
auras:EnableMouse(true)
end
end
end
end
function UF:PostUpdateAura(unit, button)
local auras = button:GetParent()
local frame = auras:GetParent()
local type = auras.type
local db = frame.db and frame.db[type]
if db then
if db.clickThrough and button:IsMouseEnabled() then
button:EnableMouse(false)
elseif not db.clickThrough and not button:IsMouseEnabled() then
button:EnableMouse(true)
end
end
if button.isDebuff then
if not button.isFriend and not button.isPlayer then --[[and (not E.isDebuffWhiteList[name])]]
button:SetBackdropBorderColor(0.9, 0.1, 0.1)
button.icon:SetDesaturated((unit and not find(unit, "arena%d")) and true or false)
else
local color = (button.dtype and DebuffTypeColor[button.dtype]) or DebuffTypeColor.none
button:SetBackdropBorderColor(color.r * 0.6, color.g * 0.6, color.b * 0.6)
button.icon:SetDesaturated(false)
end
else
if button.isStealable and not button.isFriend then
button:SetBackdropBorderColor(237/255, 234/255, 142/255)
else
button:SetBackdropBorderColor(unpack(E["media"].unitframeBorderColor))
end
end
local size = button:GetParent().size
if size then
button:SetSize(size, size)
end
if button.expiration and button.duration and (button.duration ~= 0) then
local getTime = GetTime()
if not button:GetScript("OnUpdate") then
button.expirationTime = button.expiration
button.expirationSaved = button.expiration - getTime
button.nextupdate = -1
button:SetScript("OnUpdate", UF.UpdateAuraTimer)
end
if (button.expirationTime ~= button.expiration) or (button.expirationSaved ~= (button.expiration - getTime)) then
button.expirationTime = button.expiration
button.expirationSaved = button.expiration - getTime
button.nextupdate = -1
end
end
if button.expiration and button.duration and (button.duration == 0 or button.expiration <= 0) then
button.expirationTime = nil
button.expirationSaved = nil
button:SetScript("OnUpdate", nil)
if button.text:GetFont() then
button.text:SetText("")
end
end
end
function UF:UpdateAuraTimer(elapsed)
self.expirationSaved = self.expirationSaved - elapsed
if self.nextupdate > 0 then
self.nextupdate = self.nextupdate - elapsed
return
end
if self.expirationSaved <= 0 then
self:SetScript("OnUpdate", nil)
if self.text:GetFont() then
self.text:SetText("")
end
return
end
local timervalue, formatid
timervalue, formatid, self.nextupdate = E:GetTimeInfo(self.expirationSaved, 4)
if self.text:GetFont() then
self.text:SetFormattedText(format("%s%s|r", E.TimeColors[formatid], E.TimeFormats[formatid][2]), timervalue)
elseif self:GetParent():GetParent().db then
self.text:FontTemplate(LSM:Fetch("font", E.db["unitframe"].font), self:GetParent():GetParent().db[self:GetParent().type].fontSize, E.db["unitframe"].fontOutline)
self.text:SetFormattedText(format("%s%s|r", E.TimeColors[formatid], E.TimeFormats[formatid][2]), timervalue)
end
end
function UF:AuraFilter(unit, button, name, _, _, _, dispelType, duration, expiration, caster, isStealable, _, spellID)
local db = self:GetParent().db
if not db or not db[self.type] then return true end
db = db[self.type]
if not name then return nil end
local filterCheck, isUnit, isFriend, isPlayer, canDispell, allowDuration, noDuration, spellPriority
isPlayer = (caster == "player" or caster == "vehicle")
isFriend = unit and UnitIsFriend("player", unit) and not UnitCanAttack("player", unit)
button.isPlayer = isPlayer
button.isFriend = isFriend
button.isStealable = isStealable
button.dtype = dispelType
button.duration = duration
button.expiration = expiration
button.name = name
button.owner = caster --what uses this?
button.spell = name --what uses this? (SortAurasByName?)
button.priority = 0
noDuration = (not duration or duration == 0)
allowDuration = noDuration or (duration and (duration > 0) and (db.maxDuration == 0 or duration <= db.maxDuration) and (db.minDuration == 0 or duration >= db.minDuration))
if db.priority ~= "" then
isUnit = unit and caster and UnitIsUnit(unit, caster)
canDispell = (self.type == "buffs" and isStealable) or (self.type == "debuffs" and dispelType and E:IsDispellableByMe(dispelType))
filterCheck, spellPriority = UF:CheckFilter(name, caster, spellID, isFriend, isPlayer, isUnit, allowDuration, noDuration, canDispell, strsplit(",", db.priority))
if spellPriority then button.priority = spellPriority end -- this is the only difference from auarbars code
else
filterCheck = allowDuration and true -- Allow all auras to be shown when the filter list is empty, while obeying duration sliders
end
return filterCheck
end
function UF:UpdateBuffsHeaderPosition()
local parent = self:GetParent()
local buffs = parent.Buffs
local debuffs = parent.Debuffs
local numDebuffs = self.visibleDebuffs
if numDebuffs == 0 then
buffs:ClearAllPoints()
buffs:Point(debuffs.point, debuffs.attachTo, debuffs.anchorPoint, debuffs.xOffset, debuffs.yOffset)
else
buffs:ClearAllPoints()
buffs:Point(buffs.point, buffs.attachTo, buffs.anchorPoint, buffs.xOffset, buffs.yOffset)
end
end
function UF:UpdateDebuffsHeaderPosition()
local parent = self:GetParent()
local debuffs = parent.Debuffs
local buffs = parent.Buffs
local numBuffs = self.visibleBuffs
if numBuffs == 0 then
debuffs:ClearAllPoints()
debuffs:Point(buffs.point, buffs.attachTo, buffs.anchorPoint, buffs.xOffset, buffs.yOffset)
else
debuffs:ClearAllPoints()
debuffs:Point(debuffs.point, debuffs.attachTo, debuffs.anchorPoint, debuffs.xOffset, debuffs.yOffset)
end
end
function UF:UpdateBuffsPositionAndDebuffHeight()
local parent = self:GetParent()
local db = parent.db
local buffs = parent.Buffs
local debuffs = parent.Debuffs
local numDebuffs = self.visibleDebuffs
if numDebuffs == 0 then
buffs:ClearAllPoints()
buffs:Point(debuffs.point, debuffs.attachTo, debuffs.anchorPoint, debuffs.xOffset, debuffs.yOffset)
else
buffs:ClearAllPoints()
buffs:Point(buffs.point, buffs.attachTo, buffs.anchorPoint, buffs.xOffset, buffs.yOffset)
end
if numDebuffs > 0 then
local numRows = ceil(numDebuffs/db.debuffs.perrow)
debuffs:Height(debuffs.size * (numRows > db.debuffs.numrows and db.debuffs.numrows or numRows))
else
debuffs:Height(debuffs.size)
end
end
function UF:UpdateDebuffsPositionAndBuffHeight()
local parent = self:GetParent()
local db = parent.db
local debuffs = parent.Debuffs
local buffs = parent.Buffs
local numBuffs = self.visibleBuffs
if numBuffs == 0 then
debuffs:ClearAllPoints()
debuffs:Point(buffs.point, buffs.attachTo, buffs.anchorPoint, buffs.xOffset, buffs.yOffset)
else
debuffs:ClearAllPoints()
debuffs:Point(debuffs.point, debuffs.attachTo, debuffs.anchorPoint, debuffs.xOffset, debuffs.yOffset)
end
if numBuffs > 0 then
local numRows = ceil(numBuffs/db.buffs.perrow)
buffs:Height(buffs.size * (numRows > db.buffs.numrows and db.buffs.numrows or numRows))
else
buffs:Height(buffs.size)
end
end
function UF:UpdateBuffsHeight()
local parent = self:GetParent()
local db = parent.db
local buffs = parent.Buffs
local numBuffs = self.visibleBuffs
if numBuffs > 0 then
local numRows = ceil(numBuffs/db.buffs.perrow)
buffs:Height(buffs.size * (numRows > db.buffs.numrows and db.buffs.numrows or numRows))
else
buffs:Height(buffs.size)
-- Any way to get rid of the last row as well?
-- Using buffs:SetHeight(0) makes frames anchored to this one disappear
end
end
function UF:UpdateDebuffsHeight()
local parent = self:GetParent()
local db = parent.db
local debuffs = parent.Debuffs
local numDebuffs = self.visibleDebuffs
if numDebuffs > 0 then
local numRows = ceil(numDebuffs/db.debuffs.perrow)
debuffs:Height(debuffs.size * (numRows > db.debuffs.numrows and db.debuffs.numrows or numRows))
else
debuffs:Height(debuffs.size)
-- Any way to get rid of the last row as well?
-- Using debuffs:SetHeight(0) makes frames anchored to this one disappear
end
end
@@ -1,4 +1,6 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AuraBars.lua"/>
<Script file="Auras.lua"/>
<Script file="CombatIndicator.lua"/>
<Script file="Health.lua"/>
<Script file="Name.lua"/>
@@ -2,9 +2,4 @@
<Script file="Player.lua"/>
<Script file="Target.lua"/>
<Script file="TargetTarget.lua"/>
<Script file="focus.lua"/>
<Script file="focustarget.lua"/>
<Script file="pet.lua"/>
<Script file="pettarget.lua"/>
<Script file="targettargettarget.lua"/>
</Ui>
@@ -22,9 +22,13 @@ function UF:Construct_PlayerFrame(frame)
frame.Portrait3D = self:Construct_Portrait(frame, "model")
frame.Portrait2D = self:Construct_Portrait(frame, "texture")
frame.Buffs = self:Construct_Buffs(frame)
frame.Debuffs = self:Construct_Debuffs(frame)
-- frame.Castbar = self:Construct_Castbar(frame, L["Player Castbar"])
frame.RaidTargetIndicator = UF:Construct_RaidIcon(frame)
frame.RestingIndicator = self:Construct_RestingIndicator(frame)
frame.CombatIndicator = self:Construct_CombatIndicator(frame)
frame.AuraBars = self:Construct_AuraBarHeader(frame)
frame.InfoPanel = self:Construct_InfoPanel(frame)
frame:SetPoint("BOTTOMLEFT", E.UIParent, "BOTTOM", -413, 68)
@@ -20,8 +20,11 @@ function UF:Construct_TargetFrame(frame)
frame.Portrait3D = self:Construct_Portrait(frame, "model")
frame.Portrait2D = self:Construct_Portrait(frame, "texture")
frame.Buffs = self:Construct_Buffs(frame)
frame.Debuffs = self:Construct_Debuffs(frame)
frame.RaidTargetIndicator = UF:Construct_RaidIcon(frame)
frame.InfoPanel = self:Construct_InfoPanel(frame)
frame.AuraBars = self:Construct_AuraBarHeader(frame)
E:Point(frame, "BOTTOMRIGHT", E.UIParent, "BOTTOM", 413, 68)
E:CreateMover(frame, frame:GetName().."Mover", L["Target Frame"], nil, nil, nil, "ALL,SOLO")