Nameplate Overhaul (#38)

* ElvUI/NamePlates: initial nameplate conversions

* More nameplate work

* Modules/Cooldowns: various CD fixes, nameplates cant show 'swipe' texture

* ElvUI/NamePlates: final nameplate polish

* Modules/Misc: add space before interrupted announcement
This commit is contained in:
Andrew
2023-05-22 19:18:59 -07:00
committed by GitHub
parent 5d51f92ed3
commit 8edf2d7f8a
75 changed files with 8870 additions and 8088 deletions
+15 -1
View File
@@ -1,5 +1,5 @@
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local ElvUF = E.oUF
--Lua functions
local _G = _G
local wipe, date = wipe, date
@@ -210,6 +210,20 @@ function E:ExitVehicleShowFrames(_, unit)
end
end
function E:GetThreatStatusColor(status, nothreat)
local color = ElvUF.colors.threat[status]
if color then
return color.r, color.g, color.b, color.a or 1
elseif nothreat then
if status == -1 then -- how or why?
return 1, 1, 1, 1
else
return .7, .7, .7, 1
end
end
end
function E:RequestBGInfo()
RequestBattlefieldScoreData()
end
+37 -24
View File
@@ -162,11 +162,13 @@ function E:Cooldown_Options(timer, db, parent)
end
end
function E:CreateCooldownTimer(parent)
local timer = CreateFrame("Frame", parent:GetName() and "$parentTimer" or nil, parent)
function E:CreateCooldownTimer(parent, displayParent)
local timer = CreateFrame("Frame", parent:GetName() and parent:GetName().."Timer" or nil, displayParent)
hooksecurefunc(parent, "Hide", function() timer:Hide() end)
hooksecurefunc(parent, "Show", function() timer:Show() end)
timer:SetFrameLevel(parent:GetFrameLevel() + 1)
timer:Hide()
timer:SetAllPoints()
timer:SetAllPoints(parent)
timer.parent = parent
parent.timer = timer
@@ -199,9 +201,9 @@ function E:CreateCooldownTimer(parent)
end
E.RegisteredCooldowns = {}
function E:OnSetCooldown(start, duration)
function E:OnSetCooldown(start, duration, recursive)
if (not self.forceDisabled) and (start and duration) and (duration > MIN_DURATION) then
local timer = self.timer or E:CreateCooldownTimer(self)
local timer = self.timer or E:CreateCooldownTimer(self, self:GetParent())
timer.start = start
timer.duration = duration
timer.endTime = start + duration
@@ -213,14 +215,22 @@ function E:OnSetCooldown(start, duration)
end
end
function E:RegisterCooldown(cooldown)
function E:RegisterCooldown(cooldown, module)
if not cooldown.isHooked then
hooksecurefunc(cooldown, "SetCooldown", E.OnSetCooldown)
if cooldown:GetParent().isNamePlate then
cooldown.Show = cooldown.Hide
cooldown:Hide()
end
cooldown.isHooked = true
end
if not cooldown.isRegisteredCooldown then
local module = (cooldown.CooldownOverride or "global")
if module then
cooldown.CooldownOverride = module
else
module = (cooldown.CooldownOverride or "global")
end
if not E.RegisteredCooldowns[module] then E.RegisteredCooldowns[module] = {} end
tinsert(E.RegisteredCooldowns[module], cooldown)
@@ -228,23 +238,26 @@ function E:RegisterCooldown(cooldown)
end
end
function E:GetCooldownColors(db)
if not db then db = E.db.cooldown end -- just incase someone calls this without a first arg use the global
local c13 = E:RGBToHex(db.hhmmColorIndicator.r, db.hhmmColorIndicator.g, db.hhmmColorIndicator.b) -- color for timers that are soon to expire
local c12 = E:RGBToHex(db.mmssColorIndicator.r, db.mmssColorIndicator.g, db.mmssColorIndicator.b) -- color for timers that are soon to expire
local c11 = E:RGBToHex(db.expireIndicator.r, db.expireIndicator.g, db.expireIndicator.b) -- color for timers that are soon to expire
local c10 = E:RGBToHex(db.secondsIndicator.r, db.secondsIndicator.g, db.secondsIndicator.b) -- color for timers that have seconds remaining
local c9 = E:RGBToHex(db.minutesIndicator.r, db.minutesIndicator.g, db.minutesIndicator.b) -- color for timers that have minutes remaining
local c8 = E:RGBToHex(db.hoursIndicator.r, db.hoursIndicator.g, db.hoursIndicator.b) -- color for timers that have hours remaining
local c7 = E:RGBToHex(db.daysIndicator.r, db.daysIndicator.g, db.daysIndicator.b) -- color for timers that have days remaining
local c6 = db.hhmmColor -- HH:MM color
local c5 = db.mmssColor -- MM:SS color
local c4 = db.expiringColor -- color for timers that are soon to expire
local c3 = db.secondsColor -- color for timers that have seconds remaining
local c2 = db.minutesColor -- color for timers that have minutes remaining
local c1 = db.hoursColor -- color for timers that have hours remaining
local c0 = db.daysColor -- color for timers that have days remaining
return c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13
do
local function HEX(db) return E:RGBToHex(db.r, db.g, db.b) end
function E:GetCooldownColors(db)
if not db then db = E.db.cooldown end -- just incase someone calls this without a first arg use the global
return
db.daysColor,
db.hoursColor,
db.minutesColor,
db.secondsColor,
db.expiringColor,
db.mmssColor,
db.hhmmColor,
HEX(db.daysIndicator),
HEX(db.hoursIndicator),
HEX(db.minutesIndicator),
HEX(db.secondsIndicator),
HEX(db.expireIndicator),
HEX(db.mmssColorIndicator),
HEX(db.hhmmColorIndicator)
end
end
function E:UpdateCooldownOverride(module)
+40
View File
@@ -60,6 +60,7 @@ E.myname = UnitName("player")
E.myrealm = GetRealmName()
E.mynameRealm = format('%s - %s', E.myname, E.myrealm) -- contains spaces/dashes in realm (for profile keys)
E.version = GetAddOnMetadata("ElvUI", "Version")
E.versionNum = tonumber(E.version)
E.wowpatch, E.wowbuild = GetBuildInfo()
E.wowbuild = tonumber(E.wowbuild)
E.resolution = GetCVar("gxResolution")
@@ -1134,6 +1135,14 @@ function E:DBConversions()
if E.private.skins.blizzard.greeting ~= nil then
E.private.skins.blizzard.greeting = nil
end
-- VERSION 7.0 -- nameplate overhaul
if not E.db.version or E.db.version < 7 then
-- wipe nameplates
E:CopyTable(self.db.nameplates, P.nameplates)
end
E.db.version = E.versionNum
end
function E:RefreshModulesDB()
@@ -1143,6 +1152,37 @@ function E:RefreshModulesDB()
UnitFrames.db = self.db.unitframe --new ref
end
do
-- Shamelessly taken from AceDB-3.0 and stripped down by Simpy
function E:CopyDefaults(dest, src)
for k, v in pairs(src) do
if type(v) == 'table' then
if not rawget(dest, k) then rawset(dest, k, {}) end
if type(dest[k]) == 'table' then E:CopyDefaults(dest[k], v) end
elseif rawget(dest, k) == nil then
rawset(dest, k, v)
end
end
return dest
end
function E:RemoveDefaults(db, defaults)
setmetatable(db, nil)
for k, v in pairs(defaults) do
if type(v) == 'table' and type(db[k]) == 'table' then
E:RemoveDefaults(db[k], v)
if next(db[k]) == nil then db[k] = nil end
elseif db[k] == defaults[k] then
db[k] = nil
end
end
return db
end
end
function E:Initialize()
twipe(self.db)
twipe(self.global)
+2 -2
View File
@@ -8,8 +8,8 @@ local tonumber, type, gsub, pairs, pcall, loadstring = tonumber, type, gsub, pai
local len, format, split, strmatch = strlen, format, strsplit, strmatch
local CreateFrame = CreateFrame
local IsInRaid, UnitInRaid = IsInRaid, UnitInRaid
local IsInGroup, UnitInParty = IsInGroup, UnitInParty
local IsInRaid, UnitInRaid = GenerateClosure(C_Player, C_Player.IsInRaid, C_Player), UnitInRaid
local IsInGroup, UnitInParty = GenerateClosure(C_Player, C_Player.IsInGroup, C_Player), UnitInParty
-- local LE_PARTY_CATEGORY_HOME = LE_PARTY_CATEGORY_HOME
-- local LE_PARTY_CATEGORY_INSTANCE = LE_PARTY_CATEGORY_INSTANCE
local ACCEPT, CANCEL, YES, NO = ACCEPT, CANCEL, YES, NO
+1268 -608
View File
File diff suppressed because it is too large Load Diff
+26 -8
View File
@@ -1,5 +1,6 @@
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local LSM = E.Libs.LSM
local NP = E:GetModule('NamePlates')
--Lua functions
local _G = _G
@@ -78,7 +79,7 @@ local function SetInside(obj, anchor, xOffset, yOffset, anchor2)
obj:Point("BOTTOMRIGHT", anchor2 or anchor, "BOTTOMRIGHT", -xOffset, yOffset)
end
local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement, isNamePlateElement)
GetTemplate(template, isUnitFrameElement)
frame.template = template or "Default"
@@ -86,10 +87,25 @@ local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelM
if ignoreUpdates then frame.ignoreUpdates = ignoreUpdates end
if forcePixelMode then frame.forcePixelMode = forcePixelMode end
if isUnitFrameElement then frame.isUnitFrameElement = isUnitFrameElement end
frame.isNamePlateElement = isNamePlateElement
local bgFile = glossTex and E.media.glossTex or E.media.blankTex
if template ~= "NoBackdrop" then
if isNamePlateElement then
local bg = frame:CreateTexture(nil, "BACKGROUND")
bg:SetAllPoints()
GetTemplate(template, isUnitFrameElement)
--bg:SetTexture(bgFile)
bg:SetTexture(backdropr, backdropg, backdropb, backdropa)
if not frame.ignoreUpdates then
if frame.isUnitFrameElement then
E.unitFrameElements[frame] = true
else
E.frames[frame] = true
end
end
return
elseif template ~= "NoBackdrop" then
frame:SetBackdrop({
bgFile = bgFile,
edgeFile = E.media.blankTex,
@@ -99,7 +115,8 @@ local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelM
frame:SetBackdropColor(backdropr, backdropg, backdropb, backdropa)
if not E.PixelMode and not frame.forcePixelMode then
local notPixelMode = not isUnitFrameElement and not isNamePlateElement and not E.PixelMode
if notPixelMode and not frame.forcePixelMode then
if not frame.iborder then
local border = CreateFrame("Frame", nil, frame)
border:SetInside(frame, E.mult, E.mult)
@@ -139,7 +156,7 @@ local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelM
end
end
local function CreateBackdrop(frame, template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
local function CreateBackdrop(frame, template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement, isNamePlateElement)
if not template then template = "Default" end
local parent = (frame.IsObjectType and frame:IsObjectType("Texture") and frame:GetParent()) or frame
@@ -147,12 +164,13 @@ local function CreateBackdrop(frame, template, glossTex, ignoreUpdates, forcePix
if not frame.backdrop then frame.backdrop = backdrop end
if frame.forcePixelMode or forcePixelMode then
backdrop:SetOutside(frame, E.mult, E.mult)
backdrop:SetOutside(frame, E.twoPixelsPlease and 2 or 1, E.twoPixelsPlease and 2 or 1)
else
backdrop:SetOutside(frame)
local border = isNamePlateElement and NP.BORDER or nil
backdrop:SetOutside(frame, border, border)
end
backdrop:SetTemplate(template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement)
backdrop:SetTemplate(template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement, isNamePlateElement)
local frameLevel = parent.GetFrameLevel and parent:GetFrameLevel()
local frameLevelMinusOne = frameLevel and (frameLevel - 1)
+1 -1
View File
@@ -1,6 +1,6 @@
## Interface: 30300
## Author: Elv, Bunny
## Version: 6.18
## Version: 7.0
## Title: |cff1784d1E|r|cffe5e3e3lvUI|r
## Notes: User Interface replacement AddOn for World of Warcraft.
## SavedVariables: ElvDB, ElvPrivateDB
+1 -1
View File
@@ -346,7 +346,7 @@ function AddOn:ToggleOptionsUI(msg)
if not IsAddOnLoaded("ElvUI_OptionsUI") then noConfig = true end
-- version check elvui options if it's actually enabled
if (not noConfig) and GetAddOnMetadata("ElvUI_OptionsUI", "Version") ~= "1.06" then
if (not noConfig) and GetAddOnMetadata("ElvUI_OptionsUI", "Version") ~= "1.10" then
self:StaticPopup_Show("CLIENT_UPDATE_REQUEST")
end
else
+32
View File
@@ -14,6 +14,10 @@ local hiddenParent = CreateFrame('Frame', nil, UIParent)
hiddenParent:SetAllPoints()
hiddenParent:Hide()
local offScreenParent = CreateFrame('Frame', nil, UIParent)
offScreenParent:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", 0, -128)
offScreenParent:SetFrameLevel(0)
local function handleFrame(baseName)
local frame
if(type(baseName) == 'string') then
@@ -51,6 +55,34 @@ local function handleFrame(baseName)
end
end
function oUF:DisableBlizzardNamePlate(nameplate)
-- we have to preserve the base frame since the unit frame will attach to it
local blizzElements = {nameplate:GetRegions()}
local healthBar, castBar = nameplate:GetChildren()
tinsert(blizzElements, healthBar)
nameplate.blizzHighlight = blizzElements[6]
nameplate.HealthBar = healthBar
nameplate.CastBar = castBar
for _, child in ipairs(blizzElements) do
child:SetParent(hiddenParent)
child:SetAlpha(0)
child:Hide()
if child.SetTexture then
child:SetTexture()
elseif child.SetStatusBarTexture then
child:SetStatusBarTexture(nil) -- this needs nil
end
end
-- cast bar has to be special because we need onhide / onshow to fire still
castBar:SetParent(offScreenParent)
castBar:SetStatusBarTexture(nil)
castBar:SetAlpha(0)
castBar:Hide()
end
function oUF:DisableBlizzard(unit)
if(not unit) then return end
+5 -5
View File
@@ -31,15 +31,15 @@ local colors = {
}
for classToken, color in next, RAID_CLASS_COLORS do
colors.class[classToken] = {color.r, color.g, color.b}
colors.class[classToken] = {color.r, color.g, color.b, r = color.r, g = color.g, b = color.b}
end
for debuffType, color in next, DebuffTypeColor do
colors.debuff[debuffType] = {color.r, color.g, color.b}
colors.debuff[debuffType] = {color.r, color.g, color.b, r = color.r, g = color.g, b = color.b}
end
for eclass, color in next, FACTION_BAR_COLORS do
colors.reaction[eclass] = {color.r, color.g, color.b}
colors.reaction[eclass] = {color.r, color.g, color.b, r = color.r, g = color.g, b = color.b}
end
for power, color in next, PowerBarColor do
@@ -48,10 +48,10 @@ for power, color in next, PowerBarColor do
colors.power[power] = {}
for index, color in next, color do
colors.power[power][index] = {color.r, color.g, color.b}
colors.power[power][index] = {color.r, color.g, color.b, r = color.r, g = color.g, b = color.b}
end
else
colors.power[power] = {color.r, color.g, color.b, atlas = color.atlas}
colors.power[power] = {color.r, color.g, color.b, atlas = color.atlas, r = color.r, g = color.g, b = color.b}
end
end
end
+13
View File
@@ -356,6 +356,13 @@ local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontH
end
local function UpdateAuras(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local auras = self.Auras
@@ -502,6 +509,12 @@ local function UpdateAuras(self, event, unit)
end
local function Update(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
UpdateAuras(self, event, unit)
+89 -23
View File
@@ -103,6 +103,7 @@ local function resetAttributes(self)
self.channeling = nil
self.notInterruptible = nil
self.spellName = nil -- ElvUI
self.spellID = nil
end
-- ElvUI block
@@ -113,13 +114,19 @@ end
-- end block
local function CastStart(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Castbar
local name, _, _, texture, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitCastingInfo(unit)
local name, _, _, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(unit)
event = 'UNIT_SPELLCAST_START'
if(not name) then
name, _, _, texture, startTime, endTime, isTradeSkill, notInterruptible = UnitChannelInfo(unit)
name, _, _, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo(unit)
event = 'UNIT_SPELLCAST_CHANNEL_START'
end
@@ -141,6 +148,7 @@ local function CastStart(self, event, unit)
element.notInterruptible = notInterruptible
element.holdTime = 0
element.castID = castID
element.spellID = spellID
element.spellName = name -- ElvUI
if(element.casting) then
@@ -205,6 +213,12 @@ local function CastStart(self, event, unit)
end
local function CastUpdate(self, event, unit, _, _, castID)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Castbar
@@ -258,6 +272,12 @@ local function CastUpdate(self, event, unit, _, _, castID)
end
local function CastStop(self, event, unit, _, _, castID)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Castbar
@@ -287,6 +307,12 @@ local function CastStop(self, event, unit, _, _, castID)
end
local function CastFail(self, event, unit, _, _, castID)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Castbar
@@ -324,6 +350,12 @@ local function CastFail(self, event, unit, _, _, castID)
end
local function CastInterruptible(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Castbar
@@ -408,22 +440,43 @@ local function ForceUpdate(element)
return Update(element.__owner, 'ForceUpdate', element.__owner.unit)
end
local function NamePlateCastBarOnShow(self)
if C_NamePlateManager.IsNamePlateMoving(self) then return end
CastStart(self, "UNIT_SPELLCAST_START", self.unit)
end
local function NamePlateCastBarOnHide(self)
if C_NamePlateManager.IsNamePlateMoving(self) then return end
CastFail(self, "UNIT_SPELLCAST_FAILED", self.unit, nil, nil, self.Castbar.castID)
end
local function NamePlateCastBarOnValueChanged(self)
CastUpdate(self, nil, self.unit, nil, nil, self.Castbar.castID)
end
local function Enable(self, unit)
local element = self.Castbar
if(element and unit and not unit:match('%wtarget$')) then
element.__owner = self
element.ForceUpdate = ForceUpdate
self:RegisterEvent('UNIT_SPELLCAST_START', CastStart)
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_START', CastStart)
self:RegisterEvent('UNIT_SPELLCAST_STOP', CastStop)
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', CastStop)
self:RegisterEvent('UNIT_SPELLCAST_DELAYED', CastUpdate)
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_UPDATE', CastUpdate)
self:RegisterEvent('UNIT_SPELLCAST_FAILED', CastFail)
self:RegisterEvent('UNIT_SPELLCAST_INTERRUPTED', CastFail)
self:RegisterEvent('UNIT_SPELLCAST_INTERRUPTIBLE', CastInterruptible)
self:RegisterEvent('UNIT_SPELLCAST_NOT_INTERRUPTIBLE', CastInterruptible)
if self.isNamePlate then
local castBar = self.nameplateAnchor.CastBar
castBar:SetScript("OnShow", GenerateClosure(NamePlateCastBarOnShow, self))
castBar:SetScript("OnHide", GenerateClosure(NamePlateCastBarOnHide, self))
castBar:SetScript("OnValueChanged", GenerateClosure(NamePlateCastBarOnValueChanged, self))
else
self:RegisterEvent('UNIT_SPELLCAST_START', CastStart)
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_START', CastStart)
self:RegisterEvent('UNIT_SPELLCAST_STOP', CastStop)
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', CastStop)
self:RegisterEvent('UNIT_SPELLCAST_DELAYED', CastUpdate)
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_UPDATE', CastUpdate)
self:RegisterEvent('UNIT_SPELLCAST_FAILED', CastFail)
self:RegisterEvent('UNIT_SPELLCAST_INTERRUPTED', CastFail)
self:RegisterEvent('UNIT_SPELLCAST_INTERRUPTIBLE', CastInterruptible)
self:RegisterEvent('UNIT_SPELLCAST_NOT_INTERRUPTIBLE', CastInterruptible)
end
-- ElvUI block
self:RegisterEvent('UNIT_SPELLCAST_SENT', UNIT_SPELLCAST_SENT, true)
@@ -454,7 +507,7 @@ local function Enable(self, unit)
local safeZone = element.SafeZone
if(safeZone and safeZone:IsObjectType('Texture') and not safeZone:GetTexture()) then
safeZone:SetColorTexture(1, 0, 0)
safeZone:SetTexture(1, 0, 0)
end
element:Hide()
@@ -468,16 +521,23 @@ local function Disable(self)
if(element) then
element:Hide()
self:UnregisterEvent('UNIT_SPELLCAST_START', CastStart)
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_START', CastStart)
self:UnregisterEvent('UNIT_SPELLCAST_DELAYED', CastUpdate)
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_UPDATE', CastUpdate)
self:UnregisterEvent('UNIT_SPELLCAST_STOP', CastStop)
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', CastStop)
self:UnregisterEvent('UNIT_SPELLCAST_FAILED', CastFail)
self:UnregisterEvent('UNIT_SPELLCAST_INTERRUPTED', CastFail)
self:UnregisterEvent('UNIT_SPELLCAST_INTERRUPTIBLE', CastInterruptible)
self:UnregisterEvent('UNIT_SPELLCAST_NOT_INTERRUPTIBLE', CastInterruptible)
if self.isNamePlate then
local castBar = self.nameplateAnchor.CastBar
castBar:SetScript("OnShow", nil)
castBar:SetScript("OnHide", nil)
castBar:SetScript("OnValueChanged", nil)
else
self:UnregisterEvent('UNIT_SPELLCAST_START', CastStart)
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_START', CastStart)
self:UnregisterEvent('UNIT_SPELLCAST_DELAYED', CastUpdate)
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_UPDATE', CastUpdate)
self:UnregisterEvent('UNIT_SPELLCAST_STOP', CastStop)
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', CastStop)
self:UnregisterEvent('UNIT_SPELLCAST_FAILED', CastFail)
self:UnregisterEvent('UNIT_SPELLCAST_INTERRUPTED', CastFail)
self:UnregisterEvent('UNIT_SPELLCAST_INTERRUPTIBLE', CastInterruptible)
self:UnregisterEvent('UNIT_SPELLCAST_NOT_INTERRUPTIBLE', CastInterruptible)
end
element:SetScript('OnUpdate', nil)
@@ -501,6 +561,12 @@ end)
oUF:AddElement('Castbar', Update, Enable, Disable)
function CastingBarFrame_SetUnit(self, unit, showTradeSkills, showShield)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then
self.unit = unit
self.showTradeSkills = showTradeSkills
@@ -37,6 +37,12 @@ local UnitHasVehicleUI = UnitHasVehicleUI
local MAX_COMBO_POINTS = MAX_COMBO_POINTS
local function Update(self, event, unit)
if self.isNamePlate then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(unit == 'pet') then return end
local element = self.ComboPoints
@@ -30,6 +30,12 @@ local GetPetHappiness = GetPetHappiness
local HasPetUI = HasPetUI
local function Update(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(not unit or self.unit ~= unit) then return end
local element = self.HappinessIndicator
+41 -1
View File
@@ -86,6 +86,12 @@ local oUF = ns.oUF
local Private = oUF.Private
local function UpdateColor(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(not unit or self.unit ~= unit) then return end
local element = self.Health
@@ -146,7 +152,14 @@ local function ColorPath(self, ...)
end
local function Update(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(not unit or self.unit ~= unit) then return end
local element = self.Health
--[[ Callback: Health:PreUpdate(unit)
@@ -200,7 +213,6 @@ local function Path(self, ...)
* unit - the unit accompanying the event (string)
--]]
(self.Health.Override or Update) (self, ...);
ColorPath(self, ...)
end
@@ -242,6 +254,23 @@ local function SetColorHappiness(element, state)
end
end
--[[ Health:SetColorSelection(state, isForced)
Used to toggle coloring by the unit's selection.
* self - the Health element
* state - the desired state (boolean)
* isForced - forces the event update even if the state wasn't changed (boolean)
--]]
local function SetColorSelection(element, state, isForced)
if(element.colorSelection ~= state or isForced) then
element.colorSelection = state
if(state) then
element.__owner:RegisterEvent('UNIT_FLAGS', ColorPath)
else
element.__owner:UnregisterEvent('UNIT_FLAGS', ColorPath)
end
end
end
--[[ Health:SetColorTapping(state)
Used to toggle coloring if the unit isn't tapped by the player.
@@ -320,6 +349,7 @@ local function Enable(self, unit)
element.__owner = self
element.ForceUpdate = ForceUpdate
element.SetColorDisconnected = SetColorDisconnected
element.SetColorSelection = SetColorSelection
element.SetColorHappiness = SetColorHappiness
element.SetColorTapping = SetColorTapping
element.SetColorThreat = SetColorThreat
@@ -354,6 +384,16 @@ local function Enable(self, unit)
self:RegisterEvent('UNIT_MAXHEALTH', Path)
if self.isNamePlate then
local healthBar = self.nameplateAnchor.HealthBar
healthBar:SetScript("OnValueChanged", function()
Path(self, "UNIT_HEALTH", self.unit)
end)
healthBar:SetScript("OnMinMaxChanged", function()
Path(self, "UNIT_MAXHEALTH", self.unit)
end)
end
if(element:IsObjectType('StatusBar') and not element:GetStatusBarTexture()) then
element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
end
@@ -43,6 +43,12 @@ local UnitIsUnit = UnitIsUnit
local UnitIsVisible = UnitIsVisible
local function Update(self, event, unit)
if self.isNamePlate then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(not unit or not UnitIsUnit(self.unit, unit)) then return end
local element = self.Portrait
+12
View File
@@ -100,6 +100,12 @@ local UnitPowerType = UnitPowerType
local UnitReaction = UnitReaction
local function UpdateColor(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Power
@@ -170,6 +176,12 @@ local function ColorPath(self, ...)
end
local function Update(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Power
@@ -17,6 +17,12 @@ local UnitPowerType = UnitPowerType
local UnitReaction = UnitReaction
local function UpdateColor(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Energy
@@ -84,6 +90,12 @@ local function ColorPath(self, ...)
end
local function Update(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Energy
@@ -17,6 +17,12 @@ local UnitPowerType = UnitPowerType
local UnitReaction = UnitReaction
local function UpdateColor(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Rage
@@ -84,6 +90,12 @@ local function ColorPath(self, ...)
end
local function Update(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.Rage
@@ -33,6 +33,12 @@ local FFA_ICON = [[Interface\TargetingFrame\UI-PVP-FFA]]
local FACTION_ICON = [[Interface\TargetingFrame\UI-PVP-]]
local function Update(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(unit ~= self.unit) then return end
local element = self.PvPIndicator
@@ -36,7 +36,14 @@ local UnitExists = UnitExists
local UnitThreatSituation = UnitThreatSituation
local function Update(self, event, unit)
if(not unit or self.unit ~= unit) then return end
if not unit then return end
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if(self.unit ~= unit) then return end
local element = self.ThreatIndicator
--[[ Callback: ThreatIndicator:PreUpdate(unit)
+114 -1
View File
@@ -311,6 +311,10 @@ local function togglemenu(self, unit)
end
local function onShow(self)
if self.isNamePlate then
local nameplate = C_NamePlate.GetNamePlateForUnit(self.unit)
if nameplate and C_NamePlateManager.IsNamePlateMoving(nameplate.unitFrame) then return end
end
if(not updateActiveUnit(self, 'OnShow')) then
return self:UpdateAllElements('OnShow')
end
@@ -417,7 +421,6 @@ local function initObject(unit, style, styleFunc, header, ...)
activeElements[object] = {} -- ElvUI: styleFunc on headers break before this is set when they try to enable elements before it's set.
Private.UpdateUnits(object, objectUnit)
styleFunc(object, objectUnit, not header)
object:HookScript('OnAttributeChanged', onAttributeChanged)
@@ -761,6 +764,116 @@ function oUF:Spawn(unit, overrideName)
return object
end
--[[ oUF:SpawnNamePlates(prefix, callback, variables)
Used to create nameplates and apply the currently active style to them.
* self - the global oUF object
* prefix - prefix for the global name of the nameplate. Defaults to an auto-generated prefix (string?)
* callback - function to be called after a nameplate unit or the player's target has changed. The arguments passed to
the callback are the updated nameplate, if any, the event that triggered the update, and the new unit
(function?)
* variables - list of console variable-value pairs to be set when the player logs in (table?)
--]]
local nameplateUnitToFrame = {}
function oUF:SpawnNamePlates(namePrefix, nameplateCallback, nameplateCVars)
argcheck(nameplateCallback, 3, 'function', 'nil')
argcheck(nameplateCVars, 4, 'table', 'nil')
if(not style) then return error('Unable to create frame. No styles have been registered.') end
if(_G.oUF_NamePlateDriver) then return error('oUF nameplate driver has already been initialized.') end
local style = style
local prefix = namePrefix or generateName()
local eventHandler = CreateFrame('Frame', 'oUF_NamePlateDriver')
eventHandler:RegisterEvent('NAME_PLATE_UNIT_ADDED')
eventHandler:RegisterEvent('NAME_PLATE_UNIT_REMOVED')
eventHandler:RegisterEvent('PLAYER_TARGET_CHANGED')
eventHandler:RegisterEvent('UNIT_FACTION')
eventHandler:RegisterEvent('UNIT_FLAGS')
if(IsLoggedIn()) then
if(nameplateCVars) then
for cvar, value in next, nameplateCVars do
SetCVar(cvar, value)
end
end
else
eventHandler:RegisterEvent('PLAYER_LOGIN')
end
C_NamePlateManager.SetEnableResizeNamePlates(true)
eventHandler:SetScript('OnEvent', function(_, event, unit)
if(event == 'PLAYER_LOGIN') then
if(nameplateCVars) then
for cvar, value in next, nameplateCVars do
SetCVar(cvar, value)
end
end
elseif(event == 'PLAYER_TARGET_CHANGED') then
local nameplate = C_NamePlate.GetNamePlateForUnit('target')
if(nameplateCallback) then
nameplateCallback(nameplate and nameplate.unitFrame, event, 'target')
end
-- UAE is called after the callback to reduce the number of
-- ForceUpdate calls layout devs have to do themselves
if(nameplate) then
nameplate.unitFrame:UpdateAllElements(event)
end
elseif(event == 'UNIT_FACTION' and unit) then
local nameplate = C_NamePlate.GetNamePlateForUnit(unit)
if(not nameplate) then return end
if(nameplateCallback) then
nameplateCallback(nameplate.unitFrame, event, unit)
end
elseif(event == 'NAME_PLATE_UNIT_ADDED' and unit) then
local nameplate = C_NamePlate.GetNamePlateForUnit(unit)
if(not nameplate) then return end
nameplateUnitToFrame[unit] = nameplate
if(not nameplate.unitFrame) then
self:DisableBlizzardNamePlate(nameplate)
nameplate.style = style
nameplate.isNamePlate = true
nameplate.unitFrame = CreateFrame('Button', prefix..tostring(nameplate), nameplate)
nameplate.unitFrame:EnableMouse(false)
nameplate.unitFrame.isNamePlate = true
nameplate.unitFrame.nameplateAnchor = nameplate
Private.UpdateUnits(nameplate.unitFrame, unit)
walkObject(nameplate.unitFrame, unit)
C_NamePlateManager.ApplyFPSIncrease(nameplate.unitFrame)
else
-- for _, child in ipairs(nameplate.blizzElements) do
-- ClearNamePlateElement(child)
-- end
Private.UpdateUnits(nameplate.unitFrame, unit)
end
nameplate.unitFrame:SetAttribute('unit', unit)
if(nameplateCallback) then
nameplateCallback(nameplate.unitFrame, event, unit)
end
-- UAE is called after the callback to reduce the number of
-- ForceUpdate calls layout devs have to do themselves
nameplate.unitFrame:UpdateAllElements(event)
elseif(event == 'NAME_PLATE_UNIT_REMOVED' and unit) then
local nameplate = nameplateUnitToFrame[unit]
if(not nameplate) then return end
nameplateUnitToFrame[unit] = nil
nameplate.unitFrame:SetAttribute('unit', nil)
if(nameplateCallback) then
nameplateCallback(nameplate.unitFrame, event, unit)
end
end
end)
end
--[[ oUF:AddElement(name, update, enable, disable)
Used to register an element with oUF.
@@ -190,6 +190,12 @@ local function sortByTime(a, b)
end
local function Update(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if self.unit ~= unit then return end
local element = self.AuraBars
@@ -258,6 +258,12 @@ end
local found = {}
local function Update(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if not unit or self.unit ~= unit then return end
local guid = UnitGUID(unit)
@@ -83,6 +83,12 @@ local function Shared_UpdateCheckReturn(self, element, updateType, ...)
return (not element.enabled or not self.cur) or element.ready or not maxV
elseif (updateType == POST) then
local curV, maxV, unit = ...
if unit and element.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = element.unit and UnitIsUnit(element.unit, unit)
if isUnit then
unit = element.unit
end
end
return (not element.enabled or not element.cur) or (not element.ready or not curV or not maxV) or element.unit ~= unit
else
return false
@@ -26,6 +26,12 @@ local function GetDebuffType(unit, filterTable)
end
local function Update(object, event, unit)
if unit and object.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = object.unit and UnitIsUnit(object.unit, unit)
if isUnit then
unit = object.unit
end
end
if unit ~= object.unit then return end
local debuffType, texture, wasFiltered, style, color = GetDebuffType(unit, object.DebuffHighlightFilterTable)
@@ -62,6 +62,12 @@ local function Update(self, _, unit)
end
unit = unit or self.unit
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if self.unit ~= unit then return end
-- range fader
@@ -129,6 +135,7 @@ local function HoverScript(self)
end
local function TargetScript(self)
if self.isNamePlate and C_NamePlateManager.IsNamePlateMoving(self) then return end
if self.Fader and self.Fader.TargetHooked == 1 then
if self:IsShown() then
self.Fader:ForceUpdate()
@@ -161,6 +161,12 @@ local function UpdateDebuff(self, name, icon, count, debuffType, duration, endTi
end
local function Update(self, event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if unit ~= self.unit then return end
local element = self.RaidDebuffs
@@ -37,6 +37,12 @@ local UnitName = UnitName
local enabledUF, enabled = {}
local function Update(self, event, unit, succeeded)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if not unit or self.unit ~= unit then return end
local element = self.ResurrectIndicator
+1 -2
View File
@@ -539,7 +539,6 @@ function AB:StyleButton(button, noBackdrop, useMasque)
if macroText then
macroText:ClearAllPoints()
macroText:SetWidth(self.db.fontWidth)
macroText:Point("BOTTOM", 0, 1)
macroText:FontTemplate(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
macroText:SetTextColor(color.r, color.g, color.b)
@@ -995,4 +994,4 @@ local function InitializeCallback()
AB:Initialize()
end
E:RegisterModule(AB:GetName(), InitializeCallback)
E:RegisterModule(AB:GetName(), InitializeCallback)
+1
View File
@@ -17,6 +17,7 @@ local MICRO_BUTTONS = {
"SocialsMicroButton",
"PVPMicroButton",
"LFDMicroButton",
"ChallengesMicroButton",
"MainMenuMicroButton",
"HelpMicroButton"
}
+1 -1
View File
@@ -63,7 +63,7 @@ do
end
do
local interruptMsg = INTERRUPTED.." %s's \124cff71d5ff\124Hspell:%d\124h[%s]\124h\124r!"
local interruptMsg = " "..INTERRUPTED.." %s's \124cff71d5ff\124Hspell:%d\124h[%s]\124h\124r!"
function M:ToggleInterruptAnnounce()
if E.db.general.interruptAnnounce == "NONE" then
+150 -425
View File
@@ -1,463 +1,188 @@
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local NP = E:GetModule("NamePlates")
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local UF = E:GetModule('UnitFrames')
local LSM = E.Libs.LSM
local LAI = E.Libs.LAI
--Lua functions
local select, unpack, pairs = select, unpack, pairs
local band = bit.band
local tinsert = table.insert
local floor = math.floor
local split = string.split
--WoW API / Variables
local _G = _G
local wipe = wipe
local unpack = unpack
local CreateFrame = CreateFrame
local GetSpellInfo = GetSpellInfo
local GetTime = GetTime
local CREATED, VISIBLE, HIDDEN = 2, 1, 0
function NP:Construct_Auras(nameplate)
local frameName = nameplate:GetName()
local positionValues = {
BOTTOMLEFT = "TOP",
BOTTOMRIGHT = "TOP",
LEFT = "RIGHT",
RIGHT = "LEFT",
TOPLEFT = "BOTTOM",
TOPRIGHT = "BOTTOM"
}
local Buffs = CreateFrame('Frame', frameName..'Buffs', nameplate)
Buffs:Size(1, 1)
Buffs.size = 27
Buffs.num = 4
Buffs.spacing = E.Border * 2
Buffs.onlyShowPlayer = false
Buffs.disableMouse = true
Buffs.isNamePlate = nameplate
local positionValues2 = {
BOTTOMLEFT = "BOTTOM",
BOTTOMRIGHT = "BOTTOM",
LEFT = "LEFT",
RIGHT = "RIGHT",
TOPLEFT = "TOP",
TOPRIGHT = "TOP"
}
Buffs.initialAnchor = 'BOTTOMLEFT'
Buffs.growthX = 'RIGHT'
Buffs.growthY = 'UP'
Buffs.type = 'buffs'
Buffs.forceShow = nameplate == _G.ElvNP_Test
Buffs.tickers = {} -- StyleFilters
Buffs.stacks = {}
Buffs.rows = {}
local Debuffs = CreateFrame('Frame', frameName..'Debuffs', nameplate)
Debuffs:Size(1, 1)
Debuffs.size = 27
Debuffs.num = 4
Debuffs.spacing = E.Border * 2
Debuffs.onlyShowPlayer = false
Debuffs.disableMouse = true
Debuffs.isNamePlate = nameplate
Debuffs.initialAnchor = 'BOTTOMLEFT'
Debuffs.growthX = 'RIGHT'
Debuffs.growthY = 'UP'
Debuffs.type = 'debuffs'
Debuffs.forceShow = nameplate == _G.ElvNP_Test
Debuffs.tickers = {} -- StyleFilters
Debuffs.stacks = {}
Debuffs.rows = {}
local RaidIconBit = {
["STAR"] = 0x00100000,
["CIRCLE"] = 0x00200000,
["DIAMOND"] = 0x00400000,
["TRIANGLE"] = 0x00800000,
["MOON"] = 0x01000000,
["SQUARE"] = 0x02000000,
["CROSS"] = 0x04000000,
["SKULL"] = 0x08000000
}
Buffs.PreUpdate = UF.PreUpdateAura
Buffs.PreSetPosition = UF.SortAuras
Buffs.SetPosition = UF.SetPosition
Buffs.PostCreateIcon = NP.Construct_AuraIcon
Buffs.PostUpdateIcon = UF.PostUpdateAura
Buffs.CustomFilter = UF.AuraFilter
local ByRaidIcon = {}
Debuffs.PreUpdate = UF.PreUpdateAura
Debuffs.PreSetPosition = UF.SortAuras
Debuffs.SetPosition = UF.SetPosition
Debuffs.PostCreateIcon = NP.Construct_AuraIcon
Debuffs.PostUpdateIcon = UF.PostUpdateAura
Debuffs.CustomFilter = UF.AuraFilter
function NP:LibAuraInfo_AURA_APPLIED(event, destGUID)
self:UpdateElement_AurasByGUID(destGUID, event)
nameplate.Buffs_, nameplate.Debuffs_ = Buffs, Debuffs
nameplate.Buffs, nameplate.Debuffs = Buffs, Debuffs
end
function NP:LibAuraInfo_AURA_REMOVED(event, destGUID)
self:UpdateElement_AurasByGUID(destGUID, event)
end
function NP:Construct_AuraIcon(button)
if not button then return end
function NP:LibAuraInfo_AURA_REFRESH(event, destGUID)
self:LibAuraInfo_AURA_APPLIED(event, destGUID)
end
button:SetTemplate(nil, nil, nil, nil, nil, true, true)
function NP:LibAuraInfo_AURA_APPLIED_DOSE(event, destGUID)
self:LibAuraInfo_AURA_APPLIED(event, destGUID)
end
button.cd:SetReverse(true)
button.cd:SetInside(button)
function NP:LibAuraInfo_AURA_CLEAR(event, destGUID)
self:UpdateElement_AurasByGUID(destGUID, event)
end
button.icon:SetDrawLayer('ARTWORK')
button.icon:SetInside()
function NP:LibAuraInfo_UNIT_AURA(event, destGUID)
self:UpdateElement_AurasByGUID(destGUID, event)
end
button.count:ClearAllPoints()
button.count:Point('BOTTOMRIGHT', 1, 1)
button.count:SetJustifyH('RIGHT')
function NP:UpdateTime(elapsed)
self.timeLeft = self.timeLeft - elapsed
self:SetValue(self.timeLeft)
button.overlay:SetTexture()
button.stealable:SetTexture()
button.isNamePlate = true
if self.nextUpdate > 0 then
self.nextUpdate = self.nextUpdate - elapsed
return
E:RegisterCooldown(button.cd, 'nameplates')
local auras = button:GetParent()
if auras and auras.type then
local db = NP:PlateDB(auras.__owner)
button.db = db[auras.type]
end
if self.timeLeft < 0 then
self:SetScript("OnUpdate", nil)
self:Hide()
return
end
local value, id, nextUpdate, remainder = E:GetTimeInfo(self.timeLeft, self.threshold, self.hhmmThreshold, self.mmssThreshold)
self.nextUpdate = nextUpdate
local style = E.TimeFormats[id]
if style then
local which = (self.textColors and 2 or 1) + (self.showSeconds and 0 or 2)
if self.textColors then
self.text:SetFormattedText(style[which], value, self.textColors[id], remainder)
else
self.text:SetFormattedText(style[which], value, remainder)
end
end
local color = self.timeColors[id]
if color then
self.text:SetTextColor(color.r, color.g, color.b)
end
NP:UpdateAuraSettings(button)
end
local unstableAffliction = GetSpellInfo(30108)
local vampiricTouch = GetSpellInfo(34914)
function NP:SetAura(frame, guid, index, filter, isDebuff, visible)
local isAura, name, texture, count, debuffType, duration, expiration, caster, spellID, _ = LAI:GUIDAura(guid, index, filter)
function NP:Configure_Auras(nameplate, auras, db)
auras.size = db.size
auras.height = not db.keepSizeRatio and db.height
auras.numAuras = db.numAuras
auras.numRows = db.numRows
auras.onlyShowPlayer = false
auras.spacing = db.spacing
auras.growthY = UF.MatchGrowthY[db.anchorPoint] or db.growthY
auras.growthX = UF.MatchGrowthX[db.anchorPoint] or db.growthX
auras.xOffset = db.xOffset
auras.yOffset = db.yOffset
auras.anchorPoint = db.anchorPoint
auras.auraSort = UF.SortAuraFuncs[db.sortMethod]
auras.initialAnchor = E.InversePoints[db.anchorPoint]
auras.filterList = UF:ConvertFilters(auras, db.priority)
auras.smartPosition, auras.smartFluid = UF:SetSmartPosition(nameplate)
auras.attachTo = UF:GetAuraAnchorFrame(nameplate, db.attachTo) -- keep below SetSmartPosition
auras.num = db.numAuras * db.numRows
auras.db = db -- for auraSort
if frame.forceShow or frame.forceCreate then
spellID = 47540
name, _, texture = GetSpellInfo(spellID)
if frame.forceShow then
isAura, count, debuffType, duration, expiration = true, 5, "Magic", 0, 0
end
end
if isAura then
local position = visible + 1
local button = frame[position] or NP:Construct_AuraIcon(frame, position)
button.caster = caster
button.filter = filter
button.isDebuff = isDebuff
local filterCheck = not frame.forceCreate
if not (frame.forceShow or frame.forceCreate) then
filterCheck = NP:AuraFilter(guid, button, name, texture, count, debuffType, duration, expiration, caster, spellID)
local index = 1
while auras[index] do
local button = auras[index]
if button then
button.db = db
NP:UpdateAuraSettings(button)
button:SetBackdropBorderColor(unpack(E.media.bordercolor))
end
if filterCheck then
if button.icon then button.icon:SetTexture(texture) end
if button.count then button.count:SetText(count > 1 and count) end
if duration > 0 and expiration ~= 0 then
local timeLeft = expiration - GetTime()
if timeLeft > 0 then
button.timeLeft = timeLeft
button.nextUpdate = 0
button:SetMinMaxValues(0, duration)
button:SetValue(timeLeft)
button:SetScript("OnUpdate", NP.UpdateTime)
-- else
-- return HIDDEN
end
else
button.timeLeft = nil
button.text:SetText("")
button:SetScript("OnUpdate", nil)
button:SetMinMaxValues(0, 1)
button:SetValue(0)
end
button:SetID(index)
button:Show()
if isDebuff then
local color = (debuffType and DebuffTypeColor[debuffType]) or DebuffTypeColor.none
if button.name and (button.name == unstableAffliction or button.name == vampiricTouch) then
self:StyleFrameColor(button, 0.05, 0.85, 0.94)
else
self:StyleFrameColor(button, color.r * 0.6, color.g * 0.6, color.b * 0.6)
end
end
return VISIBLE
elseif frame.forceCreate then
button:Hide()
return CREATED
else
return HIDDEN
end
end
end
function NP:Update_AurasPosition(frame, db)
local size = db.size + db.spacing
local anchor = E.InversePoints[db.anchorPoint]
local growthx = (db.growthX == "LEFT" and -1) or 1
local growthy = (db.growthY == "DOWN" and -1) or 1
local cols = db.perrow
for i = frame.anchoredIcons + 1, #frame do
local button = frame[i]
if not button then break end
local col = (i - 1) % cols
local row = floor((i - 1) / cols)
button:SetSize(db.size, db.size)
button:ClearAllPoints()
button:SetPoint(anchor, frame, anchor, col * size * growthx, row * size * growthy)
button.count:FontTemplate(LSM:Fetch("font", db.countFont), db.countFontSize, db.countFontOutline)
button.count:ClearAllPoints()
button.count:SetPoint(db.countPosition, db.countXOffset, db.countYOffset)
button.text:FontTemplate(LSM:Fetch("font", db.durationFont), db.durationFontSize, db.durationFontOutline)
button.text:ClearAllPoints()
button.text:SetPoint(db.durationPosition, db.durationXOffset, db.durationYOffset)
button:SetOrientation(db.cooldownOrientation)
button.bg:ClearAllPoints()
if db.cooldownOrientation == "VERTICAL" then
button.bg:SetPoint("TOPLEFT", button)
button.bg:SetPoint("BOTTOMRIGHT", button:GetStatusBarTexture(), "TOPRIGHT")
else
button.bg:SetPoint("TOPRIGHT", button)
button.bg:SetPoint("BOTTOMLEFT", button:GetStatusBarTexture(), "BOTTOMRIGHT")
end
if db.reverseCooldown then
button:SetStatusBarColor(0, 0, 0, 0.5)
button.bg:SetTexture(0, 0, 0, 0)
else
button:SetStatusBarColor(0, 0, 0, 0)
button.bg:SetTexture(0, 0, 0, 0.5)
end
end
end
function NP:UpdateElement_AuraIcons(frame, guid, filter, limit, isDebuff)
local index, visible, hidden, created = 1, 0, 0, 0
while visible < limit do
local result = NP:SetAura(frame, guid, index, filter, isDebuff, visible)
if not result then
break
elseif result == HIDDEN then
hidden = hidden + 1
elseif result == VISIBLE then
visible = visible + 1
elseif result == CREATED then
visible = visible + 1
created = created + 1
end
index = index + 1
end
visible = visible - created
for i = visible + 1, #frame do
frame[i].timeLeft = nil
frame[i]:SetScript("OnUpdate", nil)
frame[i]:Hide()
end
return visible
end
function NP:UpdateElement_Auras(frame)
if not frame.Health:IsShown() then return end
local guid = frame.guid
if not guid then
if frame.UnitClass == "HERO" then
local name = frame.UnitName
guid = self.GUIDByName[name]
elseif frame.RaidIcon:IsShown() then
guid = ByRaidIcon[frame.RaidIconType]
end
if guid then
frame.guid = guid
elseif not frame.Buffs.forceShow and not frame.Debuffs.forceShow then
return
end
end
local db = NP.db.units[frame.UnitType].buffs
if db.enable then
local buffs = frame.Buffs
buffs.visibleBuffs = NP:UpdateElement_AuraIcons(buffs, guid, buffs.filter or "HELPFUL", db.perrow * db.numrows)
if #buffs > buffs.anchoredIcons then
self:Update_AurasPosition(buffs, db)
buffs.anchoredIcons = #buffs
end
end
db = NP.db.units[frame.UnitType].debuffs
if db.enable then
local debuffs = frame.Debuffs
debuffs.visibleDebuffs = NP:UpdateElement_AuraIcons(debuffs, guid, debuffs.filter or "HARMFUL", db.perrow * db.numrows, true)
if #debuffs > debuffs.anchoredIcons then
self:Update_AurasPosition(debuffs, db)
debuffs.anchoredIcons = #debuffs
end
end
self:StyleFilterUpdate(frame, "UNIT_AURA")
end
function NP:UpdateElement_AurasByGUID(guid, event)
local destName, destFlags = LAI:GetGUIDInfo(guid)
if destName then
destName = split("-", destName)
end
local raidIcon
if destFlags then
for iconName, bitmask in pairs(RaidIconBit) do
if band(destFlags, bitmask) > 0 then
ByRaidIcon[iconName] = guid
raidIcon = iconName
break
end
end
end
local frame = self:SearchForFrame(guid, raidIcon, destName)
if frame then
frame.guid = guid
self.GUIDByName[destName] = guid
self:UpdateElement_Auras(frame)
end
end
function NP:Construct_AuraIcon(parent, index)
local db = NP.db.units[parent:GetParent().UnitType][parent.type]
local button = CreateFrame("StatusBar", "$parentButton"..index, parent)
NP:StyleFrame(button, true)
button:SetStatusBarTexture(E.media.blankTex)
button:SetStatusBarColor(0, 0, 0, 0)
button:SetOrientation("VERTICAL")
button.bg = button:CreateTexture()
button.bg:SetTexture(0, 0, 0, 0.5)
button.bg:SetPoint("TOPLEFT", button)
button.bg:SetPoint("BOTTOMRIGHT", button:GetStatusBarTexture(), "TOPRIGHT")
button.icon = button:CreateTexture(nil, "BORDER")
button.icon:SetTexCoord(unpack(E.TexCoords))
button.icon:SetAllPoints()
button.count = button:CreateFontString(nil, "OVERLAY")
button.count:SetJustifyH("RIGHT")
button.count:FontTemplate(LSM:Fetch("font", db.countFont), db.countFontSize, db.countFontOutline)
button.text = button:CreateFontString(nil, "OVERLAY")
-- support cooldown override
if not button.isRegisteredCooldown then
button.CooldownOverride = "nameplates"
button.isRegisteredCooldown = true
button.forceEnabled = true
if not E.RegisteredCooldowns.nameplates then E.RegisteredCooldowns.nameplates = {} end
tinsert(E.RegisteredCooldowns.nameplates, button)
end
button.text:FontTemplate(LSM:Fetch("font", db.durationFont), db.durationFontSize, db.durationFontOutline)
NP:Update_CooldownOptions(button)
tinsert(parent, button)
return button
end
function NP:Update_CooldownOptions(button)
E:Cooldown_Options(button, self.db.cooldown, button)
end
function NP:Configure_Auras(frame, auraType)
local auras = frame[auraType]
local db = self.db.units[frame.UnitType][auras.type]
auras:SetWidth(db.perrow * db.size + ((db.perrow - 1) * db.spacing))
auras:SetHeight(db.numrows * db.size + ((db.numrows - 1) * db.spacing))
auras:ClearAllPoints()
auras:SetPoint(positionValues[db.anchorPoint], db.attachTo == "BUFFS" and frame.Buffs or frame.Health, positionValues2[db.anchorPoint], db.xOffset, db.yOffset)
auras:Point(auras.initialAnchor, auras.attachTo, auras.anchorPoint, auras.xOffset, auras.yOffset)
auras:Size(db.numAuras * db.size + ((db.numAuras - 1) * db.spacing), 1)
end
function NP:ConstructElement_Auras(frame, auraType)
local auras = CreateFrame("Frame", "$parent"..auraType, frame)
auras:Show()
auras:SetSize(150, 27)
auras:SetPoint("TOP", 0, 22)
auras.anchoredIcons = 0
auras.type = string.lower(auraType)
function NP:Update_Auras(nameplate)
local db = NP:PlateDB(nameplate)
return auras
end
function NP:CheckFilter(name, spellID, isPlayer, allowDuration, noDuration, ...)
for i = 1, select("#", ...) do
local filterName = select(i, ...)
if not filterName then return true end
if G.nameplates.specialFilters[filterName] or E.global.unitframe.aurafilters[filterName] then
local filter = E.global.unitframe.aurafilters[filterName]
if filter then
local filterType = filter.type
local spellList = filter.spells
local spell = spellList and (spellList[spellID] or spellList[name])
if filterType and (filterType == "Whitelist") and (spell and spell.enable) and allowDuration then
return true
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 == "blockNoDuration" and noDuration then
return false
elseif filterName == "blockNonPersonal" and (not isPlayer) then
return false
end
if db.debuffs.enable or db.buffs.enable then
if not nameplate:IsElementEnabled('Auras') then
nameplate:EnableElement('Auras')
end
nameplate.Buffs_:ClearAllPoints()
nameplate.Debuffs_:ClearAllPoints()
if db.debuffs.enable then
nameplate.Debuffs = nameplate.Debuffs_
NP:Configure_Auras(nameplate, nameplate.Debuffs, db.debuffs)
nameplate.Debuffs:Show()
nameplate.Debuffs:ForceUpdate()
elseif nameplate.Debuffs then
nameplate.Debuffs:Hide()
nameplate.Debuffs = nil
end
if db.buffs.enable then
nameplate.Buffs = nameplate.Buffs_
NP:Configure_Auras(nameplate, nameplate.Buffs, db.buffs)
nameplate.Buffs:Show()
nameplate.Buffs:ForceUpdate()
elseif nameplate.Buffs then
nameplate.Buffs:Hide()
nameplate.Buffs = nil
end
elseif nameplate:IsElementEnabled('Auras') then
nameplate:DisableElement('Auras')
end
end
function NP:AuraFilter(guid, button, name, texture, count, debuffType, duration, expiration, caster, spellID)
local parent = button:GetParent()
local parentType = parent.type
local db = NP.db.units[parent:GetParent().UnitType][parentType]
if not db then return true end
local isPlayer = caster == E.myguid
-- keep these same as in `UF:AuraFilter`
button.isPlayer = isPlayer
button.dtype = debuffType
button.duration = duration
button.expiration = expiration
button.stackCount = count
button.name = name
button.spellID = spellID
button.spell = name
button.priority = 0
if not db.filters then return true end
local priority = db.filters.priority
local noDuration = (not duration or duration == 0)
local allowDuration = noDuration or (duration and (duration > 0) and db.filters.maxDuration == 0 or duration <= db.filters.maxDuration) and (db.filters.minDuration == 0 or duration >= db.filters.minDuration)
local filterCheck
if priority ~= "" then
filterCheck = NP:CheckFilter(name, spellID, isPlayer, allowDuration, noDuration, split(",", priority))
else
filterCheck = allowDuration and true -- Allow all auras to be shown when the filter list is empty, while obeying duration sliders
function NP:UpdateAuraSettings(button)
local db = button.db
if db then
local point = db.countPosition or 'CENTER'
button.count:ClearAllPoints()
button.count:SetJustifyH(point:find('RIGHT') and 'RIGHT' or 'LEFT')
button.count:Point(point, db.countXOffset, db.countYOffset)
button.count:FontTemplate(LSM:Fetch('font', db.countFont), db.countFontSize, db.countFontOutline)
end
return filterCheck
end
if button.auraInfo then
wipe(button.auraInfo)
else
button.auraInfo = {}
end
button.needsButtonTrim = true
button.needsUpdateCooldownPosition = true
end
@@ -0,0 +1,299 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local UF = E:GetModule('UnitFrames')
local AB = E:GetModule('ActionBars')
local _G = _G
local wipe = wipe
local next = next
local pairs = pairs
local unpack = unpack
local GetTime = GetTime
local UnitGUID = UnitGUID
local CreateFrame = CreateFrame
NP.BossMods_ActiveUnitGUID = {}
NP.BossMods_TextureCache = {}
local allowHostile = false
function NP:BossMods_CreateIcon(element)
element.index = not element.index and 1 or (element.index + 1)
local button = CreateFrame('Button', element:GetName()..'Button'..element.index, element)
button:EnableMouse(false)
button:SetTemplate(nil, nil, nil, nil, nil, true, true)
local cooldown = CreateFrame('Cooldown', '$parentCooldown', button, 'CooldownFrameTemplate')
cooldown:SetReverse(true)
cooldown:SetInside(button)
E:RegisterCooldown(cooldown, 'nameplates')
local icon = button:CreateTexture(nil, 'ARTWORK')
icon:SetTexCoord(unpack(E.TexCoords))
icon:SetInside()
button.icon = icon
button.cd = cooldown
button.db = element.db
return button
end
function NP:BossMods_GetIcon(plate, texture)
local element, unused, avaiableIcon = plate.BossMods
local activeButton = element.activeIcons[texture]
if not activeButton then
unused, avaiableIcon = next(element.unusedIcons)
if unused then element.unusedIcons[unused] = nil end
end
local button = activeButton or avaiableIcon or NP:BossMods_CreateIcon(element)
if not activeButton then
element.activeIcons[texture] = button
end
return button
end
function NP:BossMods_PositionIcons(element)
if not next(element.activeIcons) then return end
local index = 1
local anchor, inversed, growthX, growthY, width, height, cols, point, middle = UF:GetAuraPosition(element)
element.currentRow = nil -- clear this for a new update
for _, button in pairs(element.activeIcons) do
UF:SetAuraPosition(element, button, index, anchor, inversed, growthX, growthY, width, height, cols, point, middle)
button:Size(width, height)
button:Show()
AB:TrimIcon(button)
index = index + 1
end
end
function NP:BossMods_TrackIcons(track, unitGUID, texture, duration, desaturate, startTime)
if track then
NP.BossMods_TextureCache[texture] = true -- use this to easily populate boss mod style filters
if not NP.BossMods_ActiveUnitGUID[unitGUID] then
NP.BossMods_ActiveUnitGUID[unitGUID] = {}
end
local active = NP.BossMods_ActiveUnitGUID[unitGUID]
if not active[texture] then
active[texture] = {}
end
local activeTexture = active[texture]
activeTexture.duration = duration
activeTexture.desaturate = desaturate
activeTexture.startTime = startTime
else
local active = NP.BossMods_ActiveUnitGUID[unitGUID]
if active then
if active[texture] then
active[texture] = nil
end
if not next(active) then
NP.BossMods_ActiveUnitGUID[unitGUID] = nil
end
end
end
end
function NP:BossMods_ClearIcons()
if not next(NP.BossMods_ActiveUnitGUID) then return end
for unitGUID, textures in pairs(NP.BossMods_ActiveUnitGUID) do
for texture in pairs(textures) do
local plate = NP.PlateGUID[unitGUID]
if plate then
NP:BossMods_ClearIcon(plate, texture)
NP:StyleFilterUpdate(plate, 'FAKE_BossModAuras')
end
end
end
wipe(NP.BossMods_ActiveUnitGUID)
end
function NP:BossMods_AddIcon(unitGUID, texture, duration, desaturate, skip)
local active = NP.BossMods_ActiveUnitGUID[unitGUID]
local activeTexture = active and active[texture]
local pastTime = activeTexture and activeTexture.startTime
local pastDuration = activeTexture and activeTexture.duration
if pastTime and pastDuration and pastDuration ~= duration then
pastTime = nil -- reset the cooldown timer if a new duration is given
end
local startTime = duration and (pastTime or GetTime()) or nil
NP:BossMods_TrackIcons(true, unitGUID, texture, duration, desaturate, startTime)
local plate = NP.PlateGUID[unitGUID]
if not plate then return end
local button = NP:BossMods_GetIcon(plate, texture)
button.icon:SetDesaturated(desaturate)
button.icon:SetTexture(texture)
if duration then
button.cd:SetCooldown(startTime, duration)
button.cd:Show()
else
button.cd:Hide()
end
if desaturate then
button:SetBackdropBorderColor(unpack(E.media.bordercolor))
else
local color = _G.DebuffTypeColor.none
button:SetBackdropBorderColor(color.r * 0.6, color.g * 0.6, color.b * 0.6)
end
NP:BossMods_PositionIcons(plate.BossMods)
if not skip then -- this will happen already during PostUpdateAllElements
NP:StyleFilterUpdate(plate, 'FAKE_BossModAuras')
end
end
function NP:BossMods_RemoveIcon(unitGUID, texture)
NP:BossMods_TrackIcons(false, unitGUID, texture)
local plate = NP.PlateGUID[unitGUID]
if plate then
NP:BossMods_ClearIcon(plate, texture)
NP:BossMods_PositionIcons(plate.BossMods)
NP:StyleFilterUpdate(plate, 'FAKE_BossModAuras')
end
end
function NP:BossMods_ClearIcon(plate, texture)
local element = plate.BossMods
local button = element.activeIcons[texture]
if not button then return end
button:Hide()
element.activeIcons[texture] = nil
element.unusedIcons[texture] = button
end
function NP:BossMods_UpdateIcon(plate, removed)
local unitGUID = plate.unitGUID
local active = NP.BossMods_ActiveUnitGUID[unitGUID]
if not active then
local element = plate.BossMods
if element and next(element.activeIcons) then
for texture in pairs(element.activeIcons) do
NP:BossMods_ClearIcon(plate, texture)
end
end
return
end
local enabled = allowHostile and NP.db.bossMods.enable
for texture, info in pairs(active) do
if removed or not enabled then
NP:BossMods_ClearIcon(plate, texture)
elseif enabled then
NP:BossMods_AddIcon(unitGUID, texture, info.duration, info.desaturate, true)
end
end
end
function NP:BossMods_AddIcon_DBM(isGUID, unit, texture, duration, desaturate)
if not (allowHostile and NP.db.bossMods.enable) then return end
local unitGUID = (isGUID and unit) or UnitGUID(unit)
NP:BossMods_AddIcon(unitGUID, texture, duration, desaturate)
end
function NP:BossMods_RemoveIcon_DBM(isGUID, unit, texture)
local unitGUID = (isGUID and unit) or UnitGUID(unit)
NP:BossMods_RemoveIcon(unitGUID, texture)
end
function NP:BossMods_AddIcon_BW(_, unitGUID, texture, duration, desaturate)
if not (allowHostile and NP.db.bossMods.enable) then return end
NP:BossMods_AddIcon(unitGUID, texture, duration, desaturate)
end
function NP:BossMods_RemoveIcon_BW(_, unitGUID, texture)
NP:BossMods_RemoveIcon(unitGUID, texture)
end
function NP:BossMods_DisableHostile()
NP:BossMods_ClearIcons()
allowHostile = false
end
function NP:BossMods_EnableHostile()
allowHostile = true
end
function NP:DBM_SupportedNPMod()
return _G.DBM.Options.UseNameplateHandoff
end
function NP:BossMods_RegisterCallbacks()
local DBM = _G.DBM
if DBM and DBM.RegisterCallback and DBM.Nameplate then
DBM.Nameplate.SupportedNPMod = NP.DBM_SupportedNPMod
DBM:RegisterCallback('BossMod_ShowNameplateAura',NP.BossMods_AddIcon_DBM)
DBM:RegisterCallback('BossMod_HideNameplateAura',NP.BossMods_RemoveIcon_DBM)
DBM:RegisterCallback('BossMod_EnableHostileNameplates',NP.BossMods_EnableHostile)
DBM:RegisterCallback('BossMod_DisableHostileNameplates',NP.BossMods_DisableHostile)
end
local BWL = _G.BigWigsLoader
if BWL and BWL.RegisterMessage then
BWL.RegisterMessage(NP,'BigWigs_AddNameplateIcon',NP.BossMods_AddIcon_BW)
BWL.RegisterMessage(NP,'BigWigs_RemoveNameplateIcon',NP.BossMods_RemoveIcon_BW)
BWL.RegisterMessage(NP,'BigWigs_EnableHostileNameplates',NP.BossMods_EnableHostile)
BWL.RegisterMessage(NP,'BigWigs_DisableHostileNameplates',NP.BossMods_DisableHostile)
end
end
function NP:Update_BossMods(plate)
local db = NP.db.bossMods
if not db.enable then return end
local anchor = db.anchorPoint
local inverse = E.InversePoints[anchor]
local element = plate.BossMods
element:ClearAllPoints()
element:SetPoint(inverse or 'TOPRIGHT', plate, anchor or 'TOPRIGHT', db.xOffset, db.yOffset)
element:SetSize(plate.width or 150, db.size)
element.db = db
element.spacing = db.spacing
element.initialAnchor = inverse
element.growthY = UF.MatchGrowthY[anchor] or db.growthY
element.growthX = UF.MatchGrowthX[anchor] or db.growthX
element.size = db.size + (db.spacing or 0)
element.height = not db.keepSizeRatio and db.height
element.rows = {}
end
function NP:Construct_BossMods(nameplate)
local element = CreateFrame('Frame', '$parentBossMods', nameplate)
element.activeIcons = {}
element.unusedIcons = {}
return element
end
+220 -324
View File
@@ -1,358 +1,254 @@
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local NP = E:GetModule("NamePlates")
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local UF = E:GetModule('UnitFrames')
local CH = E:GetModule('Chat')
local LSM = E.Libs.LSM
--Lua functions
local _G = _G
local abs = abs
local next = next
local unpack = unpack
local abs = math.abs
--WoW API / Variables
local strjoin = strjoin
local strmatch = strmatch
local CreateFrame = CreateFrame
local GetTime = GetTime
local UnitCastingInfo = UnitCastingInfo
local UnitChannelInfo = UnitChannelInfo
local FAILED = FAILED
local UnitCanAttack = UnitCanAttack
local UnitName = UnitName
local INTERRUPTED = INTERRUPTED
local function resetAttributes(self)
self.casting = nil
self.channeling = nil
self.notInterruptible = nil
self.spellName = nil
function NP:Castbar_CheckInterrupt(unit)
if unit == 'vehicle' then
unit = 'player'
end
if self.notInterruptible and UnitCanAttack('player', unit) then
self:SetStatusBarColor(NP.db.colors.castNoInterruptColor.r, NP.db.colors.castNoInterruptColor.g, NP.db.colors.castNoInterruptColor.b)
if self.Icon and NP.db.colors.castbarDesaturate then
self.Icon:SetDesaturated(true)
end
else
self:SetStatusBarColor(NP.db.colors.castColor.r, NP.db.colors.castColor.g, NP.db.colors.castColor.b)
if self.Icon then
self.Icon:SetDesaturated(false)
end
end
end
function NP:Update_CastBarOnUpdate(elapsed)
if self.casting or self.channeling then
local isCasting = self.casting
if isCasting then
self.value = self.value + elapsed
if self.value >= self.max then
resetAttributes(self)
self:Hide()
NP:StyleFilterUpdate(self:GetParent(), "FAKE_Casting")
return
end
else
self.value = self.value - elapsed
if self.value <= 0 then
resetAttributes(self)
self:Hide()
NP:StyleFilterUpdate(self:GetParent(), "FAKE_Casting")
return
end
function NP:Castbar_CustomDelayText(duration)
if self.channeling then
if self.channelTimeFormat == 'CURRENT' then
self.Time:SetFormattedText('%.1f |cffaf5050%.1f|r', abs(duration - self.max), self.delay)
elseif self.channelTimeFormat == 'CURRENTMAX' then
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%.1f|r', duration, self.max, self.delay)
elseif self.channelTimeFormat == 'REMAINING' then
self.Time:SetFormattedText('%.1f |cffaf5050%.1f|r', duration, self.delay)
elseif self.channelTimeFormat == 'REMAININGMAX' then
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%.1f|r', abs(duration - self.max), self.max, self.delay)
end
else
if self.castTimeFormat == 'CURRENT' then
self.Time:SetFormattedText('%.1f |cffaf5050%s %.1f|r', duration, '+', self.delay)
elseif self.castTimeFormat == 'CURRENTMAX' then
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%s %.1f|r', duration, self.max, '+', self.delay)
elseif self.castTimeFormat == 'REMAINING' then
self.Time:SetFormattedText('%.1f |cffaf5050%s %.1f|r', abs(duration - self.max), '+', self.delay)
elseif self.castTimeFormat == 'REMAININGMAX' then
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%s %.1f|r', abs(duration - self.max), self.max, '+', self.delay)
end
end
end
if self.delay ~= 0 then
if self.channeling then
if self.channelTimeFormat == "CURRENT" then
self.Time:SetFormattedText("%.1f |cffaf5050%.2f|r", abs(self.value - self.max), self.delay)
elseif self.channelTimeFormat == "CURRENTMAX" then
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%.2f|r", abs(self.value - self.max), self.max, self.delay)
elseif self.channelTimeFormat == "REMAINING" then
self.Time:SetFormattedText("%.1f |cffaf5050%.2f|r", self.value, self.delay)
elseif self.channelTimeFormat == "REMAININGMAX" then
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%.2f|r", self.value, self.max, self.max, self.delay)
function NP:Castbar_CustomTimeText(duration)
if self.channeling then
if self.channelTimeFormat == 'CURRENT' then
self.Time:SetFormattedText('%.1f', abs(duration - self.max))
elseif self.channelTimeFormat == 'CURRENTMAX' then
self.Time:SetFormattedText('%.1f / %.1f', abs(duration - self.max), self.max)
elseif self.channelTimeFormat == 'REMAINING' then
self.Time:SetFormattedText('%.1f', duration)
elseif self.channelTimeFormat == 'REMAININGMAX' then
self.Time:SetFormattedText('%.1f / %.1f', duration, self.max)
end
else
if self.castTimeFormat == 'CURRENT' then
self.Time:SetFormattedText('%.1f', duration)
elseif self.castTimeFormat == 'CURRENTMAX' then
self.Time:SetFormattedText('%.1f / %.1f', duration, self.max)
elseif self.castTimeFormat == 'REMAINING' then
self.Time:SetFormattedText('%.1f', abs(duration - self.max))
elseif self.castTimeFormat == 'REMAININGMAX' then
self.Time:SetFormattedText('%.1f / %.1f', abs(duration - self.max), self.max)
end
end
end
function NP:Castbar_PostCastStart(unit)
self:CheckInterrupt(unit)
-- player or NPCs; if used on other players: the cast target doesn't match their target, can be misleading if they mouseover cast
local plate = self.__owner
local db = NP:PlateDB(plate)
if db.castbar and db.castbar.enable then
if db.castbar.displayTarget then
local frameType = plate.frameType
if frameType == 'PLAYER' then
if self.curTarget then
self.Text:SetText(self.spellName..' > '..self.curTarget)
end
else
if self.castTimeFormat == "CURRENT" then
self.Time:SetFormattedText("%.1f |cffaf5050%s %.2f|r", self.value, "+", self.delay)
elseif self.castTimeFormat == "CURRENTMAX" then
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%s %.2f|r", self.value, self.max, "+", self.delay)
elseif self.castTimeFormat == "REMAINING" then
self.Time:SetFormattedText("%.1f |cffaf5050%s %.2f|r", abs(self.value - self.max), "+", self.delay)
elseif self.castTimeFormat == "REMAININGMAX" then
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%s %.2f|r", abs(self.value - self.max), self.max, "+", self.delay)
end
end
else
if self.channeling then
if self.channelTimeFormat == "CURRENT" then
self.Time:SetFormattedText("%.1f", abs(self.value - self.max))
elseif self.channelTimeFormat == "CURRENTMAX" then
self.Time:SetFormattedText("%.1f / %.2f", abs(self.value - self.max), self.max)
elseif self.channelTimeFormat == "REMAINING" then
self.Time:SetFormattedText("%.1f", self.value)
elseif self.channelTimeFormat == "REMAININGMAX" then
self.Time:SetFormattedText("%.1f / %.2f", self.value, self.max)
end
else
if self.castTimeFormat == "CURRENT" then
self.Time:SetFormattedText("%.1f", self.value)
elseif self.castTimeFormat == "CURRENTMAX" then
self.Time:SetFormattedText("%.1f / %.2f", self.value, self.max)
elseif self.castTimeFormat == "REMAINING" then
self.Time:SetFormattedText("%.1f", abs(self.value - self.max))
elseif self.castTimeFormat == "REMAININGMAX" then
self.Time:SetFormattedText("%.1f / %.2f", abs(self.value - self.max), self.max)
elseif frameType == 'ENEMY_NPC' or frameType == 'FRIENDLY_NPC' then
local target = self.curTarget or UnitName(unit..'target')
if target and target ~= '' and target ~= plate.unitName then
self.Text:SetText(self.spellName..' > '..target)
end
end
end
self:SetValue(self.value)
elseif self.holdTime > 0 then
self.holdTime = self.holdTime - elapsed
else
resetAttributes(self)
self:Hide()
NP:StyleFilterUpdate(self:GetParent(), "FAKE_Casting")
NP:StyleFilterUpdate(plate, 'FAKE_Cast')
end
end
function NP:Update_CastBar(frame, event, unit)
local castBar = frame.CastBar
if unit then
if not event then
if UnitChannelInfo(unit) then
event = "UNIT_SPELLCAST_CHANNEL_START"
elseif UnitCastingInfo(unit) then
event = "UNIT_SPELLCAST_START"
end
end
elseif castBar:IsShown() then
resetAttributes(castBar)
castBar:Hide()
function NP:Castbar_PostCastFail()
NP:StyleFilterUpdate(self.__owner, 'FAKE_Cast')
self:SetStatusBarColor(NP.db.colors.castInterruptedColor.r, NP.db.colors.castInterruptedColor.g, NP.db.colors.castInterruptedColor.b)
end
function NP:Castbar_PostCastInterruptible(unit)
self:CheckInterrupt(unit)
end
function NP:Castbar_PostCastStop()
NP:StyleFilterUpdate(self.__owner, 'FAKE_Cast')
end
function NP:Construct_Castbar(nameplate)
local castbar = CreateFrame('StatusBar', nameplate:GetName()..'Castbar', nameplate)
castbar:SetParent(nameplate)
castbar:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
castbar:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
NP.StatusBars[castbar] = true
castbar.ModuleStatusBars = NP.StatusBars -- not oUF
castbar.Button = CreateFrame('Frame', nil, castbar)
castbar.Button:SetTemplate(nil, nil, nil, nil, nil, true, true)
castbar.Icon = castbar.Button:CreateTexture(nil, 'ARTWORK')
castbar.Icon:SetParent(castbar.Button)
castbar.Icon:SetTexCoord(unpack(E.TexCoords))
castbar.Icon:SetInside()
castbar.Time = castbar:CreateFontString(nil, 'OVERLAY')
castbar.Time:FontTemplate(LSM:Fetch('font', NP.db.font), NP.db.fontSize, NP.db.fontOutline)
castbar.Time:Point('RIGHT', castbar, 'RIGHT', -4, 0)
castbar.Time:SetJustifyH('RIGHT')
castbar.Text = castbar:CreateFontString(nil, 'OVERLAY')
castbar.Text:FontTemplate(LSM:Fetch('font', NP.db.font), NP.db.fontSize, NP.db.fontOutline)
castbar.Text:Point('LEFT', castbar, 'LEFT', 4, 0)
castbar.Text:SetJustifyH('LEFT')
castbar.Text:SetWordWrap(false)
castbar.CheckInterrupt = NP.Castbar_CheckInterrupt
castbar.CustomDelayText = NP.Castbar_CustomDelayText
castbar.CustomTimeText = NP.Castbar_CustomTimeText
castbar.PostCastStart = NP.Castbar_PostCastStart
castbar.PostCastFail = NP.Castbar_PostCastFail
castbar.PostCastInterruptible = NP.Castbar_PostCastInterruptible
castbar.PostCastStop = NP.Castbar_PostCastStop
if nameplate == _G.ElvNP_Test then
castbar.Hide = castbar.Show
castbar:Show()
castbar.Text:SetText('Casting')
castbar.Time:SetText('3.1')
castbar.Icon:SetTexture([[Interface\Icons\Achievement_Character_Pandaren_Female]])
castbar:SetStatusBarColor(NP.db.colors.castColor.r, NP.db.colors.castColor.g, NP.db.colors.castColor.b)
end
if self.db.units[frame.UnitType].castbar.enable ~= true then return end
if self.db.units[frame.UnitType].health.enable ~= true and not (frame.isTarget and self.db.alwaysShowTargetHealth) then return end --Bug
return castbar
end
if event == "UNIT_SPELLCAST_START" or event == "UNIT_SPELLCAST_CHANNEL_START" then
local name, _, _, texture, startTime, endTime, _, _, notInterruptible = UnitCastingInfo(unit)
event = "UNIT_SPELLCAST_START"
if not name then
name, _, _, texture, startTime, endTime, _, notInterruptible = UnitChannelInfo(unit)
event = "UNIT_SPELLCAST_CHANNEL_START"
function NP:CASTBAR_COMBAT_LOG_EVENT_UNFILTERED(event, sourceGUID, sourceName, targetGUID)
if (event == 'SPELL_INTERRUPT' or event == 'SPELL_PERIODIC_INTERRUPT') and targetGUID and (sourceName and sourceName ~= '') then
local plate, classColor = NP.PlateGUID[targetGUID]
if plate and plate.Castbar then
local db = NP:PlateDB(plate)
if db.castbar and db.castbar.enable and db.castbar.sourceInterrupt and (db.castbar.timeToHold > 0) then
local name = strmatch(sourceName, '([^%-]+).*')
if db.castbar.sourceInterruptClassColor then
local data = CH:GetPlayerInfoByGUID(sourceGUID)
if data and data.classColor then
classColor = data.classColor.colorStr
end
plate.Castbar.Text:SetFormattedText('%s > %s', INTERRUPTED, classColor and strjoin('', '|c', classColor, name) or name)
else
plate.Castbar.Text:SetFormattedText('%s > %s', INTERRUPTED, name)
end
end
end
end
end
function NP:Update_Castbar(nameplate)
local frameDB = NP:PlateDB(nameplate)
local db = frameDB.castbar
local castbar = nameplate.Castbar
if nameplate == _G.ElvNP_Test then
castbar:SetAlpha((not frameDB.nameOnly and db.enable) and 1 or 0)
end
if db.enable then
if not nameplate:IsElementEnabled('Castbar') then
nameplate:EnableElement('Castbar')
end
if not name then
resetAttributes(castBar)
castBar:Hide()
return
end
castbar.timeToHold = db.timeToHold
castbar.castTimeFormat = db.castTimeFormat
castbar.channelTimeFormat = db.channelTimeFormat
endTime = endTime / 1000
startTime = startTime / 1000
castbar:Size(db.width, db.height)
castbar:Point('CENTER', nameplate, 'CENTER', db.xOffset, db.yOffset)
castBar.max = endTime - startTime
castBar.startTime = startTime
castBar.delay = 0
castBar.casting = event == "UNIT_SPELLCAST_START"
castBar.channeling = event == "UNIT_SPELLCAST_CHANNEL_START"
castBar.notInterruptible = notInterruptible
castBar.holdTime = 0
castBar.interrupted = nil
castBar.spellName = name
if castBar.casting then
castBar.value = GetTime() - startTime
if db.showIcon then
castbar.Button:ClearAllPoints()
castbar.Button:Point(db.iconPosition == 'RIGHT' and 'BOTTOMLEFT' or 'BOTTOMRIGHT', castbar, db.iconPosition == 'RIGHT' and 'BOTTOMRIGHT' or 'BOTTOMLEFT', db.iconOffsetX, db.iconOffsetY)
castbar.Button:Size(db.iconSize, db.iconSize)
castbar.Button:Show()
else
castBar.value = endTime - GetTime()
castbar.Button:Hide()
end
castBar:SetMinMaxValues(0, castBar.max)
castBar:SetValue(castBar.value)
castbar.Time:ClearAllPoints()
castbar.Text:ClearAllPoints()
castBar.Icon.texture:SetTexture(texture)
castBar.Spark:Show()
castBar.Name:SetText(name)
castBar.Time:SetText()
castBar:Show()
elseif event == "UNIT_SPELLCAST_STOP" or event == "UNIT_SPELLCAST_CHANNEL_STOP" then
if castBar:IsShown() then
resetAttributes(castBar)
end
elseif event == "UNIT_SPELLCAST_FAILED" or event == "UNIT_SPELLCAST_INTERRUPTED" then
if castBar:IsShown() then
castBar.Spark:Hide()
castBar.Name:SetText(event == "UNIT_SPELLCAST_FAILED" and FAILED or INTERRUPTED)
castBar.holdTime = self.db.units[frame.UnitType].castbar.timeToHold --How long the castbar should stay visible after being interrupted, in seconds
castBar.interrupted = true
resetAttributes(castBar)
castBar:SetValue(castBar.max)
end
elseif event == "UNIT_SPELLCAST_DELAYED" or event == "UNIT_SPELLCAST_CHANNEL_UPDATE" then
if frame:IsShown() then
local name, startTime, endTime, _
if event == "UNIT_SPELLCAST_DELAYED" then
name, _, _, _, startTime, endTime = UnitCastingInfo(unit)
else
name, _, _, _, startTime, endTime = UnitChannelInfo(unit)
end
if not name then
resetAttributes(castBar)
castBar:Hide()
return
end
endTime = endTime / 1000
startTime = startTime / 1000
local delta
if castBar.casting then
delta = startTime - castBar.startTime
castBar.value = GetTime() - startTime
else
delta = castBar.startTime - startTime
castBar.value = endTime - GetTime()
end
if delta < 0 then
delta = 0
end
castBar.Name:SetText(name)
castBar.max = endTime - startTime
castBar.startTime = startTime
castBar.delay = castBar.delay + delta
castBar:SetMinMaxValues(0, castBar.max)
castBar:SetValue(castBar.value)
end
elseif event == "UNIT_SPELLCAST_INTERRUPTIBLE" or event == "UNIT_SPELLCAST_NOT_INTERRUPTIBLE" then
castBar.notInterruptible = event == "UNIT_SPELLCAST_NOT_INTERRUPTIBLE"
end
if not castBar.notInterruptible then
if castBar.interrupted then
castBar:SetStatusBarColor(self.db.colors.castInterruptedColor.r, self.db.colors.castInterruptedColor.g, self.db.colors.castInterruptedColor.b)
if db.textPosition == 'BELOW' then
castbar.Time:Point('TOPRIGHT', castbar, 'BOTTOMRIGHT', db.timeXOffset, db.timeYOffset)
castbar.Text:Point('TOPLEFT', castbar, 'BOTTOMLEFT', db.textXOffset, db.textYOffset)
elseif db.textPosition == 'ABOVE' then
castbar.Time:Point('BOTTOMRIGHT', castbar, 'TOPRIGHT', db.timeXOffset, db.timeYOffset)
castbar.Text:Point('BOTTOMLEFT', castbar, 'TOPLEFT', db.textXOffset, db.textYOffset)
else
castBar:SetStatusBarColor(self.db.colors.castColor.r, self.db.colors.castColor.g, self.db.colors.castColor.b)
end
castBar.Icon.texture:SetDesaturated(false)
else
castBar:SetStatusBarColor(self.db.colors.castNoInterruptColor.r, self.db.colors.castNoInterruptColor.g, self.db.colors.castNoInterruptColor.b)
if self.db.colors.castbarDesaturate then
castBar.Icon.texture:SetDesaturated(true)
end
end
self:StyleFilterUpdate(frame, "FAKE_Casting")
end
function NP:Configure_CastBarScale(frame, scale, noPlayAnimation)
if frame.currentScale == scale then return end
local db = self.db.units[frame.UnitType].castbar
if not db.enable then return end
local castBar = frame.CastBar
if noPlayAnimation then
castBar:SetSize(db.width * scale, db.height * scale)
castBar.Icon:SetSize(db.iconSize * scale, db.iconSize * scale)
else
if castBar.scale:IsPlaying() or castBar.Icon.scale:IsPlaying() then
castBar.scale:Stop()
castBar.Icon.scale:Stop()
castbar.Time:Point('RIGHT', castbar, 'RIGHT', db.timeXOffset, db.timeYOffset)
castbar.Text:Point('LEFT', castbar, 'LEFT', db.textXOffset, db.textYOffset)
end
castBar.scale.width:SetChange(db.width * scale)
castBar.scale.height:SetChange(db.height * scale)
castBar.scale:Play()
if db.hideTime then
castbar.Time:Hide()
else
castbar.Time:FontTemplate(LSM:Fetch('font', db.font), db.fontSize, db.fontOutline)
castbar.Time:Show()
end
castBar.Icon.scale.width:SetChange(db.iconSize * scale)
castBar.Icon.scale.height:SetChange(db.iconSize * scale)
castBar.Icon.scale:Play()
if db.hideSpellName then
castbar.Text:Hide()
else
castbar.Text:FontTemplate(LSM:Fetch('font', db.font), db.fontSize, db.fontOutline)
castbar.Text:Show()
end
elseif nameplate:IsElementEnabled('Castbar') then
nameplate:DisableElement('Castbar')
end
end
function NP:Configure_CastBar(frame, configuring)
local db = self.db.units[frame.UnitType].castbar
local castBar = frame.CastBar
castBar:SetPoint("TOP", frame.Health, "BOTTOM", db.xOffset, db.yOffset)
if db.showIcon then
castBar.Icon:ClearAllPoints()
castBar.Icon:SetPoint(db.iconPosition == "RIGHT" and "BOTTOMLEFT" or "BOTTOMRIGHT", castBar, db.iconPosition == "RIGHT" and "BOTTOMRIGHT" or "BOTTOMLEFT", db.iconOffsetX, db.iconOffsetY)
castBar.Icon:Show()
else
castBar.Icon:Hide()
end
castBar.Time:ClearAllPoints()
castBar.Name:ClearAllPoints()
castBar.Spark:SetPoint("CENTER", castBar:GetStatusBarTexture(), "RIGHT", 0, 0)
castBar.Spark:SetHeight(db.height * 2)
if db.textPosition == "BELOW" then
castBar.Time:SetPoint("TOPRIGHT", castBar, "BOTTOMRIGHT")
castBar.Name:SetPoint("TOPLEFT", castBar, "BOTTOMLEFT")
elseif db.textPosition == "ABOVE" then
castBar.Time:SetPoint("BOTTOMRIGHT", castBar, "TOPRIGHT")
castBar.Name:SetPoint("BOTTOMLEFT", castBar, "TOPLEFT")
else
castBar.Time:SetPoint("RIGHT", castBar, "RIGHT", -4, 0)
castBar.Name:SetPoint("LEFT", castBar, "LEFT", 4, 0)
end
if configuring then
self:Configure_CastBarScale(frame, frame.currentScale or 1, configuring)
end
castBar.Name:FontTemplate(LSM:Fetch("font", db.font), db.fontSize, db.fontOutline)
castBar.Time:FontTemplate(LSM:Fetch("font", db.font), db.fontSize, db.fontOutline)
if db.hideSpellName then
castBar.Name:Hide()
else
castBar.Name:Show()
end
if db.hideTime then
castBar.Time:Hide()
else
castBar.Time:Show()
end
castBar:SetStatusBarTexture(LSM:Fetch("statusbar", self.db.statusbar))
castBar.castTimeFormat = db.castTimeFormat
castBar.channelTimeFormat = db.channelTimeFormat
end
function NP:Construct_CastBar(parent)
local frame = CreateFrame("StatusBar", "$parentCastBar", parent)
NP:StyleFrame(frame)
frame:SetScript("OnUpdate", NP.Update_CastBarOnUpdate)
frame.Icon = CreateFrame("Frame", nil, frame)
frame.Icon.texture = frame.Icon:CreateTexture(nil, "BORDER")
frame.Icon.texture:SetAllPoints()
frame.Icon.texture:SetTexCoord(unpack(E.TexCoords))
NP:StyleFrame(frame.Icon)
frame.Time = frame:CreateFontString(nil, "OVERLAY")
frame.Time:SetJustifyH("RIGHT")
frame.Time:SetWordWrap(false)
frame.Name = frame:CreateFontString(nil, "OVERLAY")
frame.Name:SetJustifyH("LEFT")
frame.Name:SetWordWrap(false)
frame.Spark = frame:CreateTexture(nil, "OVERLAY")
frame.Spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
frame.Spark:SetBlendMode("ADD")
frame.Spark:SetSize(15, 15)
frame.holdTime = 0
frame.interrupted = nil
frame.scale = CreateAnimationGroup(frame)
frame.scale.width = frame.scale:CreateAnimation("Width")
frame.scale.width:SetDuration(0.2)
frame.scale.height = frame.scale:CreateAnimation("Height")
frame.scale.height:SetDuration(0.2)
frame.Icon.scale = CreateAnimationGroup(frame.Icon)
frame.Icon.scale.width = frame.Icon.scale:CreateAnimation("Width")
frame.Icon.scale.width:SetDuration(0.2)
frame.Icon.scale.height = frame.Icon.scale:CreateAnimation("Height")
frame.Icon.scale.height:SetDuration(0.2)
frame:Hide()
return frame
end
@@ -0,0 +1,310 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local UF = E:GetModule('UnitFrames')
local LSM = E.Libs.LSM
local _G = _G
local max, next, ipairs = max, next, ipairs
local CreateFrame = CreateFrame
local UnitHasVehicleUI = UnitHasVehicleUI
local MAX_COMBO_POINTS = MAX_COMBO_POINTS
local MAX_POINTS = { -- match to UF.classMaxResourceBar
DEATHKNIGHT = max(6, MAX_COMBO_POINTS),
ROGUE = max(7, MAX_COMBO_POINTS),
HERO = max(5, MAX_COMBO_POINTS),
DRUID = max(5, MAX_COMBO_POINTS)
}
function NP:ClassPower_SetBarColor(bar, r, g, b)
bar:SetStatusBarColor(r, g, b)
if bar.bg then
bar.bg:SetVertexColor(r * NP.multiplier, g * NP.multiplier, b * NP.multiplier)
end
end
function NP:ClassPower_UpdateColor(powerType, rune)
local isRunes = powerType == 'RUNES'
local classPower = self.classColor
local colors = NP.db.colors.classResources
local fallback = NP.db.colors.power[powerType]
if isRunes and NP.db.colors.chargingRunes then
NP:Runes_UpdateCharged(self, rune)
elseif isRunes and rune and not classPower then
local color = colors.DEATHKNIGHT[rune.runeType or 0]
NP:ClassPower_SetBarColor(rune, color.r, color.g, color.b)
else
local classColor = not classPower and ((isRunes and colors.DEATHKNIGHT) or (powerType == 'COMBO_POINTS' and colors.comboPoints) or (powerType == 'ESSENCE' and colors.EVOKER) or (powerType == 'CHI' and colors.MONK))
for i, bar in ipairs(self) do
local color = classPower or (isRunes and classColor[bar.runeType or 0]) or (classColor and classColor[i]) or colors[E.myclass] or fallback
NP:ClassPower_SetBarColor(bar, color.r, color.g, color.b)
end
end
end
function NP:ClassPower_PostUpdate(Cur, _, needUpdate, powerType, chargedPoints)
if Cur and Cur > 0 then
self:Show()
else
self:Hide()
end
if needUpdate then
NP:Update_ClassPower(self.__owner)
end
if powerType == 'COMBO_POINTS' and E.myclass == 'ROGUE' then
NP.ClassPower_UpdateColor(self, powerType)
if chargedPoints then
local color = NP.db.colors.classResources.chargedComboPoint
for _, chargedIndex in next, chargedPoints do
self[chargedIndex]:SetStatusBarColor(color.r, color.g, color.b)
self[chargedIndex].bg:SetVertexColor(color.r * NP.multiplier, color.g * NP.multiplier, color.b * NP.multiplier)
end
end
end
end
function NP:Construct_ClassPower(nameplate)
local frameName = nameplate:GetName()
local ClassPower = CreateFrame('Frame', frameName..'ClassPower', nameplate)
ClassPower:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
ClassPower:Hide()
local texture = LSM:Fetch('statusbar', NP.db.statusbar)
local total = MAX_POINTS[E.myclass] or 0
for i = 1, total do
local bar = CreateFrame('StatusBar', frameName..'ClassPower'..i, ClassPower)
bar:SetStatusBarTexture(texture)
NP.StatusBars[bar] = true
bar.bg = ClassPower:CreateTexture(frameName..'ClassPower'..i..'bg', 'BORDER')
bar.bg:SetTexture(texture)
bar.bg:SetAllPoints()
if nameplate == _G.ElvNP_Test then
local combo = NP.db.colors.classResources.comboPoints[i]
bar.bg:SetVertexColor(combo.r, combo.g, combo.b)
end
ClassPower[i] = bar
end
if nameplate == _G.ElvNP_Test then
ClassPower.Hide = ClassPower.Show
ClassPower:Show()
end
ClassPower.UpdateColor = NP.ClassPower_UpdateColor
ClassPower.PostUpdate = NP.ClassPower_PostUpdate
return ClassPower
end
function NP:Update_ClassPower(nameplate)
local db = NP:PlateDB(nameplate)
if nameplate == _G.ElvNP_Test then
if not db.nameOnly and db.classpower and db.classpower.enable then
NP.ClassPower_UpdateColor(nameplate.ClassPower, 'COMBO_POINTS')
nameplate.ClassPower:SetAlpha(1)
else
nameplate.ClassPower:SetAlpha(0)
end
end
local target = nameplate.frameType == 'TARGET'
if (target or nameplate.frameType == 'PLAYER') and db.classpower and db.classpower.enable then
if not nameplate:IsElementEnabled('ClassPower') then
nameplate:EnableElement('ClassPower')
end
local anchor = target and NP:GetClassAnchor()
nameplate.ClassPower:ClearAllPoints()
nameplate.ClassPower:Point('CENTER', anchor or nameplate, 'CENTER', db.classpower.xOffset, db.classpower.yOffset)
nameplate.ClassPower:Size(db.classpower.width, db.classpower.height)
nameplate.ClassPower.classColor = db.classpower.classColor and RAID_CLASS_COLORS[E.myclass]
for i = 1, #nameplate.ClassPower do
nameplate.ClassPower[i]:Hide()
nameplate.ClassPower[i].bg:Hide()
end
local maxButtons = nameplate.ClassPower.__max
if maxButtons > 0 then
local Width = db.classpower.width / maxButtons
for i = 1, maxButtons do
local button = nameplate.ClassPower[i]
button:Show()
button.bg:Show()
button:ClearAllPoints()
if i == 1 then
local width = Width - (maxButtons == 6 and 2 or 0)
button:Point('LEFT', nameplate.ClassPower, 'LEFT', 0, 0)
button:Size(width, db.classpower.height)
else
button:Point('LEFT', nameplate.ClassPower[i - 1], 'RIGHT', 1, 0)
button:Size(Width - 1, db.classpower.height)
if i == maxButtons then
button:Point('RIGHT', nameplate.ClassPower)
end
end
end
end
else
if nameplate:IsElementEnabled('ClassPower') then
nameplate:DisableElement('ClassPower')
end
nameplate.ClassPower:Hide()
end
end
function NP:Runes_UpdateCharged(runes, rune)
local colors = NP.db.colors.classResources.DEATHKNIGHT
local classColor = (runes and runes.classColor) or (rune and rune.__owner and rune.__owner.classColor)
if rune then
NP:ClassPower_SetBarColor(rune, UF:Runes_GetColor(rune, colors, classColor))
elseif runes then
for _, bar in ipairs(runes) do
NP:ClassPower_SetBarColor(bar, UF:Runes_GetColor(bar, colors, classColor))
end
end
end
function NP:Runes_PostUpdate()
self:SetShown(not UnitHasVehicleUI('player'))
if NP.db.colors.chargingRunes then
NP:Runes_UpdateCharged(self)
end
end
function NP:Runes_UpdateChargedColor()
if NP.db.colors.chargingRunes then
NP:Runes_UpdateCharged(nil, self)
end
end
function NP:Runes_PostUpdateColor(r, g, b, color, rune)
NP.ClassPower_UpdateColor(self, 'RUNES', rune)
end
function NP:Construct_Runes(nameplate)
local frameName = nameplate:GetName()
local Runes = CreateFrame('Frame', frameName..'Runes', nameplate)
Runes:SetFrameStrata("BACKGROUND")
Runes:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
Runes:Hide()
Runes.PostUpdate = NP.Runes_PostUpdate
Runes.PostUpdateColor = NP.Runes_PostUpdateColor
local texture = LSM:Fetch('statusbar', NP.db.statusbar)
local color = NP.db.colors.classResources.DEATHKNIGHT[0]
for i = 1, 6 do
local rune = CreateFrame('StatusBar', frameName..'Runes'..i, Runes)
rune:SetStatusBarTexture(texture)
rune:SetStatusBarColor(color.r, color.g, color.b)
rune.PostUpdateColor = NP.Runes_UpdateChargedColor
rune.__owner = Runes
NP.StatusBars[rune] = true
rune.bg = rune:CreateTexture(frameName..'Runes'..i..'bg', 'BORDER')
rune.bg:SetVertexColor(color.r * NP.multiplier, color.g * NP.multiplier, color.b * NP.multiplier)
rune.bg:SetTexture(texture)
rune.bg:SetAllPoints()
rune.bg.multiplier = 0.35
Runes[i] = rune
end
return Runes
end
function NP:Update_Runes(nameplate)
local db = NP:PlateDB(nameplate)
local target = nameplate.frameType == 'TARGET'
if (target or nameplate.frameType == 'PLAYER') and db.classpower and db.classpower.enable then
if not nameplate:IsElementEnabled('Runes') then
nameplate:EnableElement('Runes')
end
local anchor = target and NP:GetClassAnchor()
nameplate.Runes:ClearAllPoints()
nameplate.Runes:Point('CENTER', anchor or nameplate, 'CENTER', db.classpower.xOffset, db.classpower.yOffset)
nameplate.Runes:Show()
nameplate.Runes.classColor = db.classpower.classColor and RAID_CLASS_COLORS[E.myclass]
nameplate.Runes.sortOrder = (db.classpower.sortDirection ~= 'NONE') and db.classpower.sortDirection
nameplate.Runes.colorSpec = NP.db.colors.runeBySpec
local width = db.classpower.width / 6
nameplate.Runes:Size(db.classpower.width, db.classpower.height)
for i = 1, 6 do
local rune = nameplate.Runes[i]
if i == 1 then
rune:Size(width, db.classpower.height)
rune:ClearAllPoints()
rune:Point('LEFT', nameplate.Runes, 'LEFT', 0, 0)
else
rune:Size(width - 1, db.classpower.height)
rune:ClearAllPoints()
rune:Point('LEFT', nameplate.Runes[i-1], 'RIGHT', 1, 0)
if i == 6 then
rune:Point('RIGHT', nameplate.Runes)
end
end
end
else
if nameplate:IsElementEnabled('Runes') then
nameplate:DisableElement('Runes')
end
nameplate.Runes:Hide()
end
end
function NP:Construct_Stagger(nameplate)
local Stagger = CreateFrame('StatusBar', nameplate:GetName()..'Stagger', nameplate)
Stagger:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
Stagger:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
Stagger:Hide()
NP.StatusBars[Stagger] = true
return Stagger
end
function NP:Update_Stagger(nameplate)
local db = NP:PlateDB(nameplate)
local target = nameplate.frameType == 'TARGET'
if (target or nameplate.frameType == 'PLAYER') and db.classpower and db.classpower.enable then
if not nameplate:IsElementEnabled('Stagger') then
nameplate:EnableElement('Stagger')
end
local anchor = target and NP:GetClassAnchor()
nameplate.Stagger:ClearAllPoints()
nameplate.Stagger:Point('CENTER', anchor or nameplate, 'CENTER', db.classpower.xOffset, db.classpower.yOffset)
nameplate.Stagger:Size(db.classpower.width, db.classpower.height)
elseif nameplate:IsElementEnabled('Stagger') then
nameplate:DisableElement('Stagger')
end
end
@@ -0,0 +1,302 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local UF = E:GetModule('UnitFrames')
local LSM = E.Libs.LSM
local ipairs = ipairs
local unpack = unpack
local UnitPlayerControlled = UnitPlayerControlled
local UnitClass = UnitClass
local UnitReaction = UnitReaction
local UnitIsConnected = UnitIsConnected
local CreateFrame = CreateFrame
function NP:Health_UpdateColor(_, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if not unit or self.unit ~= unit then return end
local element = self.Health
local r, g, b, t
if element.colorDisconnected and not UnitIsConnected(unit) then
t = self.colors.disconnected
elseif (element.colorClass and self.isPlayer) or (element.colorClassNPC and not self.isPlayer) or (element.colorClassPet and UnitPlayerControlled(unit) and not self.isPlayer) then
local _, class = UnitClass(unit)
t = self.colors.class[class]
elseif element.colorReaction and UnitReaction(unit, 'player') then
local reaction = UnitReaction(unit, 'player')
t = NP.db.colors.reactions[reaction == 4 and 'neutral' or reaction <= 3 and 'bad' or 'good']
elseif element.colorSmooth then
r, g, b = self:ColorGradient(element.cur or 1, element.max or 1, unpack(element.smoothGradient or self.colors.smooth))
elseif element.colorHealth then
t = NP.db.colors.health
end
if t then
r, g, b = t.r, t.g, t.b
element.r, element.g, element.b = r, g, b -- save these for the style filter to switch back
end
local sf = NP:StyleFilterChanges(self)
if sf.HealthColor then
r, g, b = sf.HealthColor.r, sf.HealthColor.g, sf.HealthColor.b
end
if b then
element:SetStatusBarColor(r, g, b)
if element.bg then
element.bg:SetVertexColor(r * NP.multiplier, g * NP.multiplier, b * NP.multiplier)
end
end
if element.PostUpdateColor then
element:PostUpdateColor(unit, r, g, b)
end
end
function NP:Construct_Health(nameplate)
local Health = CreateFrame('StatusBar', nameplate:GetName()..'Health', nameplate)
Health:SetParent(nameplate)
Health:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
Health:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
Health.considerSelectionInCombatHostile = true
Health.UpdateColor = NP.Health_UpdateColor
NP.StatusBars[Health] = true
local statusBarTexture = Health:GetStatusBarTexture()
local healthFlashTexture = Health:CreateTexture(nameplate:GetName()..'FlashTexture', 'OVERLAY')
healthFlashTexture:SetTexture(LSM:Fetch('background', 'ElvUI Blank'))
healthFlashTexture:Point('BOTTOMLEFT', statusBarTexture, 'BOTTOMLEFT')
healthFlashTexture:Point('TOPRIGHT', statusBarTexture, 'TOPRIGHT')
healthFlashTexture:Hide()
nameplate.HealthFlashTexture = healthFlashTexture
local clipFrame = CreateFrame("Frame", nil, Health)
clipFrame:SetScript("OnUpdate", UF.HealthClipFrame_OnUpdate)
clipFrame:SetAllPoints()
clipFrame:EnableMouse(false)
clipFrame.__frame = Health
Health.ClipFrame = clipFrame
return Health
end
function NP:Health_SetColors(nameplate, threatColors)
if threatColors then -- managed by ThreatIndicator_PostUpdate
nameplate.Health:SetColorTapping(nil)
nameplate.Health:SetColorSelection(nil)
nameplate.Health.colorReaction = nil
nameplate.Health.colorClass = nil
else
local db = NP:PlateDB(nameplate)
nameplate.Health:SetColorTapping(true)
nameplate.Health:SetColorSelection(true)
nameplate.Health.colorReaction = true
nameplate.Health.colorClass = db.health and db.health.useClassColor
end
end
function NP:Update_Health(nameplate, skipUpdate)
local db = NP:PlateDB(nameplate)
NP:Health_SetColors(nameplate)
if skipUpdate then return end
if db.health.enable then
if not nameplate:IsElementEnabled('Health') then
nameplate:EnableElement('Health')
end
nameplate.Health:Point('CENTER')
nameplate.Health:Point('LEFT')
nameplate.Health:Point('RIGHT')
E:SetSmoothing(nameplate.Health, NP.db.smoothbars)
elseif nameplate:IsElementEnabled('Health') then
nameplate:DisableElement('Health')
end
nameplate.Health.width = db.health.width
nameplate.Health.height = db.health.height
nameplate.Health:Height(db.health.height)
end
function NP:Update_HealComm(nameplate)
local db = NP:PlateDB(nameplate)
if db.health.enable and db.health.healPrediction then
if not nameplate:IsElementEnabled('HealCommBar') then
nameplate:EnableElement('HealCommBar')
end
nameplate.HealCommBar.myBar:SetStatusBarColor(NP.db.colors.healPrediction.personal.r, NP.db.colors.healPrediction.personal.g, NP.db.colors.healPrediction.personal.b)
nameplate.HealCommBar.otherBar:SetStatusBarColor(NP.db.colors.healPrediction.others.r, NP.db.colors.healPrediction.others.g, NP.db.colors.healPrediction.others.b)
elseif nameplate:IsElementEnabled('HealCommBar') then
nameplate:DisableElement('HealCommBar')
end
end
function NP.HealthClipFrame_HealComm(frame)
local pred = frame.HealCommBar
if pred then
NP:SetAlpha_HealComm(pred, true)
NP:SetVisibility_HealComm(pred)
end
end
function NP:SetAlpha_HealComm(obj, show)
obj.myBar:SetAlpha(show and 1 or 0)
obj.otherBar:SetAlpha(show and 1 or 0)
end
function NP:SetVisibility_HealComm(obj)
-- the first update is from `HealthClipFrame_HealComm`
-- we set this variable to allow `Configure_HealComm` to
-- update the elements overflow lock later on by option
if not obj.allowClippingUpdate then
obj.allowClippingUpdate = true
end
if obj.maxOverflow > 1 then
obj.myBar:SetParent(obj.health)
obj.otherBar:SetParent(obj.health)
else
obj.myBar:SetParent(obj.parent)
obj.otherBar:SetParent(obj.parent)
end
end
function NP:Construct_HealComm(frame)
local health = frame.Health
local parent = health.ClipFrame
local myBar = CreateFrame("StatusBar", nil, parent)
local otherBar = CreateFrame("StatusBar", nil, parent)
myBar:SetFrameLevel(health:GetFrameLevel()+1)
otherBar:SetFrameLevel(health:GetFrameLevel()+1)
NP.StatusBars[myBar] = true
NP.StatusBars[otherBar] = true
local healPrediction = {
myBar = myBar,
otherBar = otherBar,
PostUpdate = NP.UpdateHealComm,
maxOverflow = 1,
health = health,
parent = parent,
frame = frame
}
NP:SetAlpha_HealComm(healPrediction)
return healPrediction
end
function NP:Configure_HealComm(frame)
local db = NP:PlateDB(frame)
if db.health.enable and db.health.healPrediction then
if not frame:IsElementEnabled('HealComm4') then
frame:EnableElement('HealComm4')
end
local healPrediction = frame.HealCommBar
local c = db.colors.healPrediction
healPrediction.maxOverflow = 1 + (c.maxOverflow or 0)
if healPrediction.allowClippingUpdate then
NP:SetVisibility_HealComm(healPrediction)
end
local health = frame.Health
local orientation = health:GetOrientation()
local myBar = healPrediction.myBar
local otherBar = healPrediction.otherBar
myBar:SetOrientation(orientation)
otherBar:SetOrientation(orientation)
if orientation == "HORIZONTAL" then
local width = health:GetWidth()
width = (width > 0 and width) or health.WIDTH
local healthTexture = health:GetStatusBarTexture()
myBar:Size(width, 0)
myBar:ClearAllPoints()
myBar:Point("TOP", health, "TOP")
myBar:Point("BOTTOM", health, "BOTTOM")
myBar:Point("LEFT", healthTexture, "RIGHT")
otherBar:Size(width, 0)
otherBar:ClearAllPoints()
otherBar:Point("TOP", health, "TOP")
otherBar:Point("BOTTOM", health, "BOTTOM")
otherBar:Point("LEFT", myBar:GetStatusBarTexture(), "RIGHT")
else
local height = health:GetHeight()
height = (height > 0 and height) or health.HEIGHT
local healthTexture = health:GetStatusBarTexture()
myBar:Size(0, height)
myBar:ClearAllPoints()
myBar:Point("LEFT", health, "LEFT")
myBar:Point("RIGHT", health, "RIGHT")
myBar:Point("BOTTOM", healthTexture, "TOP")
otherBar:Size(0, height)
otherBar:ClearAllPoints()
otherBar:Point("LEFT", health, "LEFT")
otherBar:Point("RIGHT", health, "RIGHT")
otherBar:Point("BOTTOM", myBar:GetStatusBarTexture(), "TOP")
end
frame.HealCommBar.myBar:SetStatusBarColor(NP.db.colors.healPrediction.personal.r, NP.db.colors.healPrediction.personal.g, NP.db.colors.healPrediction.personal.b)
frame.HealCommBar.otherBar:SetStatusBarColor(NP.db.colors.healPrediction.others.r, NP.db.colors.healPrediction.others.g, NP.db.colors.healPrediction.others.b)
elseif frame:IsElementEnabled('HealComm4') then
frame:DisableElement('HealComm4')
end
end
local function UpdateFillBar(frame, previousTexture, bar, amount)
if amount == 0 then
bar:Hide()
return previousTexture
end
local orientation = frame:GetOrientation()
bar:ClearAllPoints()
if orientation == "HORIZONTAL" then
bar:SetPoint("TOPLEFT", previousTexture, "TOPRIGHT")
bar:SetPoint("BOTTOMLEFT", previousTexture, "BOTTOMRIGHT")
else
bar:SetPoint("BOTTOMRIGHT", previousTexture, "TOPRIGHT")
bar:SetPoint("BOTTOMLEFT", previousTexture, "TOPLEFT")
end
local totalWidth, totalHeight = frame:GetSize()
if orientation == "HORIZONTAL" then
bar:Width(totalWidth)
else
bar:Height(totalHeight)
end
return bar:GetStatusBarTexture()
end
function NP:UpdateHealComm(_, myIncomingHeal, allIncomingHeal)
local health = self.health
local previousTexture = health:GetStatusBarTexture()
previousTexture = UpdateFillBar(health, previousTexture, self.myBar, myIncomingHeal)
UpdateFillBar(health, previousTexture, self.otherBar, allIncomingHeal)
end
@@ -0,0 +1,313 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local LSM = E.Libs.LSM
local strfind = strfind
local ipairs, unpack = ipairs, unpack
local CreateFrame = CreateFrame
local targetIndicators = {'Spark', 'TopIndicator', 'LeftIndicator', 'RightIndicator'}
function NP:Construct_QuestIcons(nameplate)
local QuestIcons = CreateFrame('Frame', nameplate:GetName() .. 'QuestIcons', nameplate)
QuestIcons:Size(20)
QuestIcons:Hide()
for _, object in ipairs(NP.QuestIcons.iconTypes) do
local icon = QuestIcons:CreateTexture(nil, 'BORDER', nil, 1)
icon.Text = QuestIcons:CreateFontString(nil, 'OVERLAY')
icon.Text:FontTemplate()
icon:Hide()
QuestIcons[object] = icon
end
QuestIcons.Item:SetTexCoord(unpack(E.TexCoords))
QuestIcons.Chat:SetTexture([[Interface\WorldMap\ChatBubble_64.PNG]])
QuestIcons.Chat:SetTexCoord(0, 0.5, 0.5, 1)
return QuestIcons
end
function NP:Update_QuestIcons(nameplate)
local plateDB = NP:PlateDB(nameplate)
local db = plateDB.questIcon
if db and db.enable and (nameplate.frameType == 'FRIENDLY_NPC' or nameplate.frameType == 'ENEMY_NPC') then
if not nameplate:IsElementEnabled('QuestIcons') then
nameplate:EnableElement('QuestIcons')
end
nameplate.QuestIcons:ClearAllPoints()
nameplate.QuestIcons:Point(E.InversePoints[db.position], nameplate, db.position, db.xOffset, db.yOffset)
for _, object in ipairs(NP.QuestIcons.iconTypes) do
local icon = nameplate.QuestIcons[object]
icon:Size(db.size, db.size)
icon:SetAlpha(db.hideIcon and 0 or 1)
local xoffset = strfind(db.textPosition, 'LEFT') and -2 or 2
local yoffset = strfind(db.textPosition, 'BOTTOM') and 2 or -2
icon.Text:ClearAllPoints()
icon.Text:Point('CENTER', icon, db.textPosition, xoffset, yoffset)
icon.Text:FontTemplate(LSM:Fetch('font', db.font), db.fontSize, db.fontOutline)
icon.Text:SetJustifyH('CENTER')
icon.size, icon.position = db.size, db.position
end
elseif nameplate:IsElementEnabled('QuestIcons') then
nameplate:DisableElement('QuestIcons')
end
end
function NP:Construct_ClassificationIndicator(nameplate)
return nameplate:CreateTexture(nameplate:GetName() .. 'ClassificationIndicator', 'OVERLAY')
end
function NP:Update_ClassificationIndicator(nameplate)
local plateDB = NP:PlateDB(nameplate)
local db = plateDB.eliteIcon
if db and db.enable and (nameplate.frameType == 'FRIENDLY_NPC' or nameplate.frameType == 'ENEMY_NPC') then
if not nameplate:IsElementEnabled('ClassificationIndicator') then
nameplate:EnableElement('ClassificationIndicator')
end
nameplate.ClassificationIndicator:ClearAllPoints()
nameplate.ClassificationIndicator:Size(db.size, db.size)
nameplate.ClassificationIndicator:Point(E.InversePoints[db.position], nameplate, db.position, db.xOffset, db.yOffset)
elseif nameplate:IsElementEnabled('ClassificationIndicator') then
nameplate:DisableElement('ClassificationIndicator')
end
end
function NP:Construct_TargetIndicator(nameplate)
local TargetIndicator = CreateFrame('Frame', nameplate:GetName() .. 'TargetIndicator', nameplate)
TargetIndicator:SetFrameLevel(nameplate:GetFrameLevel()-1)
TargetIndicator.Shadow = CreateFrame('Frame', nil, TargetIndicator)
TargetIndicator.Shadow:Hide()
for _, object in ipairs(targetIndicators) do
local indicator = TargetIndicator:CreateTexture(nil, 'BACKGROUND')
indicator:Hide()
TargetIndicator[object] = indicator
end
return TargetIndicator
end
function NP:Update_TargetIndicator(nameplate)
local enabled = nameplate:IsElementEnabled('TargetIndicator')
if nameplate.frameType == 'PLAYER' then
if enabled then
nameplate:DisableElement('TargetIndicator')
end
return
elseif not enabled then
nameplate:EnableElement('TargetIndicator')
end
local tdb = NP.db.units.TARGET
local indicator = nameplate.TargetIndicator
indicator.arrow = E.Media.Textures[NP.db.units.TARGET.arrow] or E.Media.Textures.TopIndicator
indicator.lowHealthThreshold = NP.db.lowHealthThreshold
indicator.preferGlowColor = NP.db.colors.preferGlowColor
indicator.style = tdb.glowStyle
if indicator.style ~= 'none' then
local style, color, size, spacing = tdb.glowStyle, NP.db.colors.glowColor, tdb.arrowSize, tdb.arrowSpacing
local r, g, b, a = color.r, color.g, color.b, color.a
local db = NP:PlateDB(nameplate)
-- background glow is 2, 6, and 8; 2 is background glow only
if not db.health.enable and (style ~= 'style2' and style ~= 'style6' and style ~= 'style8') then
style = 'style2'
indicator.style = style
end
-- top arrow is 3, 5, 6
if indicator.TopIndicator and (style == 'style3' or style == 'style5' or style == 'style6') then
indicator.TopIndicator:Point('BOTTOM', nameplate.Health, 'TOP', 0, spacing)
indicator.TopIndicator:SetVertexColor(r, g, b, a)
indicator.TopIndicator:SetSize(size, size)
end
-- side arrows are 4, 7, 8
if indicator.LeftIndicator and indicator.RightIndicator and (style == 'style4' or style == 'style7' or style == 'style8') then
indicator.LeftIndicator:Point('LEFT', nameplate.Health, 'RIGHT', spacing, 0)
indicator.RightIndicator:Point('RIGHT', nameplate.Health, 'LEFT', -spacing, 0)
indicator.LeftIndicator:SetVertexColor(r, g, b, a)
indicator.RightIndicator:SetVertexColor(r, g, b, a)
indicator.LeftIndicator:SetSize(size, size)
indicator.RightIndicator:SetSize(size, size)
end
-- border glow is 1, 5, 7
if indicator.Shadow and (style == 'style1' or style == 'style5' or style == 'style7') then
indicator.Shadow:SetOutside(nameplate.Health, E.PixelMode and 6 or 8, E.PixelMode and 6 or 8, nil, true)
indicator.Shadow:SetBackdropBorderColor(r, g, b)
indicator.Shadow:SetAlpha(a)
end
-- background glow is 2, 6, and 8
if indicator.Spark and (style == 'style2' or style == 'style6' or style == 'style8') then
local size
if db.health.enable and not (db.nameOnly or nameOnlySF) then
parent = nameplate.Health
size = E.Border + 14
else
parent = nameplate
size = -(E.Border + 4)
end
indicator.Spark:Point('TOPLEFT', parent, 'TOPLEFT', -(size * 2), size)
indicator.Spark:Point('BOTTOMRIGHT', parent, 'BOTTOMRIGHT', (size * 2), -size)
indicator.Spark:SetVertexColor(r, g, b, a)
end
end
end
function NP:Construct_Highlight(nameplate)
Highlight = nameplate.nameplateAnchor.blizzHighlight
return Highlight
end
function NP:Update_Highlight(nameplate, nameOnlySF)
local db = NP:PlateDB(nameplate)
if NP.db.highlight and db.enable then
if not nameplate:IsElementEnabled('Highlight') then
nameplate:EnableElement('Highlight')
end
local highlight = nameplate.Highlight
if highlight:GetParent() ~= nameplate then
highlight:SetParent(nameplate)
end
if highlight:GetDrawLayer() ~= "OVERLAY" then
Highlight:SetDrawLayer("OVERLAY")
end
highlight:SetTexture(E.Media.Textures.Spark)
highlight:SetAllPoints(nameplate)
if db.health.enable and not (db.nameOnly or nameOnlySF) then
highlight:SetAlpha(0.75)
else
highlight:SetAlpha(0.50)
end
elseif nameplate:IsElementEnabled('Highlight') then
nameplate:DisableElement('Highlight')
end
end
function NP:Construct_PVPRole(nameplate)
local texture = nameplate:CreateTexture(nameplate:GetName() .. 'PVPRole', 'OVERLAY', nil, 1)
texture:Size(40)
texture.HealerTexture = E.Media.Textures.Healer
texture.TankTexture = E.Media.Textures.Tank
texture:SetTexture(texture.HealerTexture)
texture:Hide()
return texture
end
function NP:Update_PVPRole(nameplate)
local db = NP:PlateDB(nameplate)
if (nameplate.frameType == 'FRIENDLY_PLAYER' or nameplate.frameType == 'ENEMY_PLAYER') and (db.markHealers or db.markTanks) then
if not nameplate:IsElementEnabled('PVPRole') then
nameplate:EnableElement('PVPRole')
end
nameplate.PVPRole.ShowHealers = db.markHealers
nameplate.PVPRole.ShowTanks = db.markTanks
nameplate.PVPRole:Point('RIGHT', nameplate.Health, 'LEFT', -6, 0)
elseif nameplate:IsElementEnabled('PVPRole') then
nameplate:DisableElement('PVPRole')
end
end
function NP:Update_Fader(nameplate)
local db = NP:PlateDB(nameplate)
local vis = db.visibility
if not vis or vis.showAlways then
if nameplate:IsElementEnabled('Fader') then
nameplate:DisableElement('Fader')
NP:PlateFade(nameplate, 0.5, nameplate:GetAlpha(), 1)
end
elseif db.enable then
if not nameplate.Fader then
nameplate.Fader = {}
end
if not nameplate:IsElementEnabled('Fader') then
nameplate:EnableElement('Fader')
nameplate.Fader:SetOption('MinAlpha', 0)
nameplate.Fader:SetOption('Smooth', 0.3)
nameplate.Fader:SetOption('Hover', true)
--nameplate.Fader:SetOption('Power', true)
nameplate.Fader:SetOption('Health', true)
nameplate.Fader:SetOption('Casting', true)
end
nameplate.Fader:SetOption('Combat', vis.showInCombat)
nameplate.Fader:SetOption('PlayerTarget', vis.showWithTarget)
nameplate.Fader:SetOption('DelayAlpha', (vis.alphaDelay > 0 and vis.alphaDelay) or nil)
nameplate.Fader:SetOption('Delay', (vis.hideDelay > 0 and vis.hideDelay) or nil)
nameplate.Fader:ForceUpdate()
end
end
function NP:Construct_Cutaway(nameplate)
local frameName = nameplate:GetName()
local Cutaway = {}
Cutaway.Health = nameplate.Health.ClipFrame:CreateTexture(frameName .. 'CutawayHealth')
local healthTexture = nameplate.Health:GetStatusBarTexture()
Cutaway.Health:Point('TOPLEFT', healthTexture, 'TOPRIGHT')
Cutaway.Health:Point('BOTTOMLEFT', healthTexture, 'BOTTOMRIGHT')
-- Cutaway.Power = nameplate.Power.ClipFrame:CreateTexture(frameName .. 'CutawayPower')
-- local powerTexture = nameplate.Power:GetStatusBarTexture()
-- Cutaway.Power:Point('TOPLEFT', powerTexture, 'TOPRIGHT')
-- Cutaway.Power:Point('BOTTOMLEFT', powerTexture, 'BOTTOMRIGHT')
return Cutaway
end
function NP:Update_Cutaway(nameplate)
local eitherEnabled = NP.db.cutaway.health.enabled or NP.db.cutaway.power.enabled
if not eitherEnabled then
if nameplate:IsElementEnabled('Cutaway') then
nameplate:DisableElement('Cutaway')
end
else
if not nameplate:IsElementEnabled('Cutaway') then
nameplate:EnableElement('Cutaway')
end
nameplate.Cutaway:UpdateConfigurationValues(NP.db.cutaway)
if NP.db.cutaway.health.forceBlankTexture then
nameplate.Cutaway.Health:SetTexture(E.media.blankTex)
else
nameplate.Cutaway.Health:SetTexture(LSM:Fetch('statusbar', NP.db.statusbar))
end
-- if NP.db.cutaway.power.forceBlankTexture then
-- nameplate.Cutaway.Power:SetTexture(E.media.blankTex)
-- else
-- nameplate.Cutaway.Power:SetTexture(LSM:Fetch('statusbar', NP.db.statusbar))
-- end
end
end
@@ -0,0 +1,66 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local _G = _G
local unpack = unpack
local hooksecurefunc = hooksecurefunc
function NP:Portrait_PostUpdate()
local nameplate = self.__owner
local db = NP:PlateDB(nameplate)
local sf = NP:StyleFilterChanges(nameplate)
if sf.Portrait or (db.portrait and db.portrait.enable) then
if db.portrait.classicon and nameplate.isPlayer then
self:SetTexture([[Interface\WorldStateFrame\Icons-Classes]])
self:SetTexCoord(unpack(_G.CLASS_ICON_TCOORDS[nameplate.classFile]))
self.backdrop:Hide()
else
self:SetTexCoord(.18, .82, .18, .82)
self.backdrop:Show()
end
else
self.backdrop:Hide()
end
end
function NP:Update_PortraitBackdrop()
if self.backdrop then
self.backdrop:SetShown(self:IsShown())
end
end
function NP:Construct_Portrait(nameplate)
local Portrait = nameplate:CreateTexture(nameplate:GetName() .. 'Portrait', 'OVERLAY', nil, 2)
Portrait:SetTexCoord(.18, .82, .18, .82)
Portrait:CreateBackdrop(nil, nil, nil, nil, nil, true, true)
Portrait:Hide()
Portrait.PostUpdate = NP.Portrait_PostUpdate
hooksecurefunc(Portrait, 'Hide', NP.Update_PortraitBackdrop)
hooksecurefunc(Portrait, 'Show', NP.Update_PortraitBackdrop)
return Portrait
end
function NP:Update_Portrait(nameplate)
local db = NP:PlateDB(nameplate)
local sf = NP:StyleFilterChanges(nameplate)
if sf.Portrait or (db.portrait and db.portrait.enable) then
if not nameplate:IsElementEnabled('Portrait') then
nameplate:EnableElement('Portrait')
nameplate.Portrait:ForceUpdate()
end
nameplate.Portrait:Size(db.portrait.width, db.portrait.height)
-- These values are forced in name only mode inside of DisablePlate
if not (db.nameOnly or sf.NameOnly) then
nameplate.Portrait:ClearAllPoints()
nameplate.Portrait:Point(E.InversePoints[db.portrait.position], nameplate, db.portrait.position, db.portrait.xOffset, db.portrait.yOffset)
end
elseif nameplate:IsElementEnabled('Portrait') then
nameplate:DisableElement('Portrait')
end
end
+148
View File
@@ -0,0 +1,148 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local UF = E:GetModule('UnitFrames')
local LSM = E.Libs.LSM
local unpack = unpack
local UnitPlayerControlled = UnitPlayerControlled
local UnitClass = UnitClass
local UnitReaction = UnitReaction
local UnitIsConnected = UnitIsConnected
local CreateFrame = CreateFrame
local UnitPowerType = UnitPowerType
local POWERTYPE_ALTERNATE = 10
function NP:Power_UpdateColor(_, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if self.unit ~= unit then return end
local element = self.Power
local ptype, ptoken, altR, altG, altB = UnitPowerType(unit)
element.token = ptoken
local sf = NP:StyleFilterChanges(self)
if sf.PowerColor then return end
local Selection = element.colorSelection and NP:UnitSelectionType(unit, element.considerSelectionInCombatHostile)
local r, g, b, t, atlas
if element.colorDisconnected and not UnitIsConnected(unit) then
t = self.colors.disconnected
elseif element.colorPower then
if element.displayType ~= POWERTYPE_ALTERNATE then
t = NP.db.colors.power[ptoken or ptype]
if not t then
if element.GetAlternativeColor then
r, g, b = element:GetAlternativeColor(unit, ptype, ptoken, altR, altG, altB)
elseif altR then
r, g, b = altR, altG, altB
if r > 1 or g > 1 or b > 1 then -- BUG: As of 7.0.3, altR, altG, altB may be in 0-1 or 0-255 range.
r, g, b = r / 255, g / 255, b / 255
end
end
end
else
t = NP.db.colors.power.ALT_POWER
end
if element.useAtlas and t and t.atlas then
atlas = t.atlas
end
elseif (element.colorClass and self.isPlayer) or (element.colorClassNPC and not self.isPlayer) or (element.colorClassPet and UnitPlayerControlled(unit) and not self.isPlayer) then
local _, class = UnitClass(unit)
t = self.colors.class[class]
elseif Selection then
t = NP.db.colors.selection[Selection]
elseif element.colorReaction and UnitReaction(unit, 'player') then
local reaction = UnitReaction(unit, 'player')
t = NP.db.colors.reactions[reaction == 4 and 'neutral' or reaction <= 3 and 'bad' or 'good']
elseif element.colorSmooth then
local adjust = 0 - (element.min or 0)
r, g, b = self:ColorGradient((element.cur or 1) + adjust, (element.max or 1) + adjust, unpack(element.smoothGradient or self.colors.smooth))
end
if t then
r, g, b = t[1] or t.r, t[2] or t.g, t[3] or t.b
end
if atlas then
element:SetStatusBarTexture(atlas)
element:SetStatusBarColor(1, 1, 1)
elseif b then
element:SetStatusBarColor(r, g, b)
end
if element.bg and b then element.bg:SetVertexColor(r * NP.multiplier, g * NP.multiplier, b * NP.multiplier) end
if element.PostUpdateColor then
element:PostUpdateColor(unit, r, g, b)
end
end
function NP:Power_PostUpdate(_, cur) --unit, cur, min, max
local db = NP:PlateDB(self.__owner)
if not db.enable then return end
if self.__owner.frameType ~= 'PLAYER' and db.power.displayAltPower and not self.displayType then
self:Hide()
return
end
if db.power and db.power.enable and db.power.hideWhenEmpty and (cur == 0) then
self:Hide()
else
self:Show()
end
end
function NP:Construct_Power(nameplate)
local Power = CreateFrame('StatusBar', nameplate:GetName()..'Power', nameplate)
Power:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
NP.StatusBars[Power] = true
--Power.frequentUpdates = true
Power.colorTapping = false
Power.colorClass = false
Power.PostUpdate = NP.Power_PostUpdate
Power.UpdateColor = NP.Power_UpdateColor
local clipFrame = CreateFrame('Frame', nil, Power)
clipFrame:SetAllPoints()
clipFrame:EnableMouse(false)
clipFrame.__frame = Power
Power.ClipFrame = clipFrame
return Power
end
function NP:Update_Power(nameplate)
local db = NP:PlateDB(nameplate)
if db.power.enable then
if not nameplate:IsElementEnabled('Power') then
nameplate:EnableElement('Power')
end
nameplate.Power:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
nameplate.Power:Point('CENTER', nameplate, 'CENTER', db.power.xOffset, db.power.yOffset)
E:SetSmoothing(nameplate.Power, NP.db.smoothbars)
elseif nameplate:IsElementEnabled('Power') then
nameplate:DisableElement('Power')
end
nameplate.Power.displayAltPower = db.power.displayAltPower
nameplate.Power.useAtlas = db.power.useAtlas
nameplate.Power.colorClass = db.power.useClassColor
nameplate.Power.colorPower = not db.power.useClassColor
nameplate.Power.width = db.power.width
nameplate.Power.height = db.power.height
nameplate.Power:Size(db.power.width, db.power.height)
end
+64
View File
@@ -0,0 +1,64 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local strlower = strlower
function NP:PvPIndicator_PostUpdate(_, status)
if status and status ~= 'FFA' and (not self.Badge or not self.Badge:IsShown()) then
self:SetAtlas('bfa-landingbutton-'..strlower(status)..'-up')
self:SetTexCoord(0, 1, 0, 1)
end
end
function NP:Construct_PvPIndicator(nameplate)
local PvPIndicator = nameplate:CreateTexture(nil, 'OVERLAY')
PvPIndicator.Badge_ = nameplate:CreateTexture(nil, 'ARTWORK')
PvPIndicator.PostUpdate = NP.PvPIndicator_PostUpdate
return PvPIndicator
end
function NP:Update_PvPIndicator(nameplate)
local db = NP:PlateDB(nameplate)
if db.pvpindicator and db.pvpindicator.enable then
if not nameplate:IsElementEnabled('PvPIndicator') then
nameplate:EnableElement('PvPIndicator')
end
nameplate.PvPIndicator:Size(db.pvpindicator.size, db.pvpindicator.size)
nameplate.PvPIndicator.Badge_:Size(db.pvpindicator.size + 14, db.pvpindicator.size + 16)
nameplate.PvPIndicator.Badge = nil
if db.pvpindicator.showBadge then
nameplate.PvPIndicator.Badge = nameplate.PvPIndicator.Badge_
end
nameplate.PvPIndicator:ClearAllPoints()
nameplate.PvPIndicator:Point(E.InversePoints[db.pvpindicator.position], nameplate, db.pvpindicator.position, db.pvpindicator.xOffset, db.pvpindicator.yOffset)
elseif nameplate:IsElementEnabled('PvPIndicator') then
nameplate:DisableElement('PvPIndicator')
end
end
function NP:Construct_PvPClassificationIndicator(nameplate)
local PvPClassificationIndicator = nameplate:CreateTexture(nil, 'OVERLAY')
return PvPClassificationIndicator
end
function NP:Update_PvPClassificationIndicator(nameplate)
local db = NP:PlateDB(nameplate)
if (nameplate.frameType == 'ENEMY_PLAYER' or nameplate.frameType == 'FRIENDLY_PLAYER' or nameplate.frameType == 'PLAYER') and db.pvpclassificationindicator and db.pvpclassificationindicator.enable then
if not nameplate:IsElementEnabled('PvPClassificationIndicator') then
nameplate:EnableElement('PvPClassificationIndicator')
end
nameplate.PvPClassificationIndicator:ClearAllPoints()
nameplate.PvPClassificationIndicator:Point(E.InversePoints[db.pvpclassificationindicator.position], nameplate, db.pvpclassificationindicator.position, db.pvpclassificationindicator.xOffset, db.pvpclassificationindicator.yOffset)
nameplate.PvPClassificationIndicator:Size(db.pvpclassificationindicator.size)
elseif nameplate:IsElementEnabled('PvPClassificationIndicator') then
nameplate:DisableElement('PvPClassificationIndicator')
end
end
@@ -0,0 +1,41 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local GetRaidTargetIndex = GetRaidTargetIndex
local SetRaidTargetIconTexture = SetRaidTargetIconTexture
function NP:RaidTargetIndicator_Override()
local element = self.RaidTargetIndicator
local index = self.unit and GetRaidTargetIndex(self.unit)
if index then
SetRaidTargetIconTexture(element, index)
element:Show()
else
element:Hide()
end
end
function NP:Construct_RaidTargetIndicator(nameplate)
local RaidTargetIndicator = nameplate:CreateTexture(nil, 'OVERLAY', nil, 7)
RaidTargetIndicator.Override = NP.RaidTargetIndicator_Override
RaidTargetIndicator:Hide()
return RaidTargetIndicator
end
function NP:Update_RaidTargetIndicator(nameplate)
local db = NP:PlateDB(nameplate)
if db.raidTargetIndicator and db.raidTargetIndicator.enable then
if not nameplate:IsElementEnabled('RaidTargetIndicator') then
nameplate:EnableElement('RaidTargetIndicator')
end
nameplate.RaidTargetIndicator:ClearAllPoints()
nameplate.RaidTargetIndicator:Point(E.InversePoints[db.raidTargetIndicator.position], nameplate, db.raidTargetIndicator.position, db.raidTargetIndicator.xOffset, db.raidTargetIndicator.yOffset)
nameplate.RaidTargetIndicator:Size(db.raidTargetIndicator.size)
elseif nameplate:IsElementEnabled('RaidTargetIndicator') then
nameplate:DisableElement('RaidTargetIndicator')
end
end
@@ -0,0 +1,38 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local LSM = E.Libs.LSM
function NP:Construct_TagText(nameplate)
local Text = nameplate:CreateFontString(nil, 'OVERLAY')
Text:FontTemplate(E.LSM:Fetch('font', NP.db.font), NP.db.fontSize, NP.db.fontOutline)
return Text
end
function NP:Update_TagText(nameplate, element, db, hide)
if not db then return end
if db.enable and not hide then
nameplate:Tag(element, db.format or '')
element:FontTemplate(LSM:Fetch('font', db.font), db.fontSize, db.fontOutline)
element:UpdateTag()
element:ClearAllPoints()
element:Point(E.InversePoints[db.position], db.parent == 'Nameplate' and nameplate or nameplate[db.parent], db.position, db.xOffset, db.yOffset)
element:Show()
else
nameplate:Untag(element)
element:Hide()
end
end
function NP:Update_Tags(nameplate, nameOnlySF)
local db = NP:PlateDB(nameplate)
local hide = db.nameOnly or nameOnlySF
NP:Update_TagText(nameplate, nameplate.Name, db.name)
NP:Update_TagText(nameplate, nameplate.Title, db.title)
NP:Update_TagText(nameplate, nameplate.Level, db.level, hide)
NP:Update_TagText(nameplate, nameplate.Health.Text, db.health and db.health.text, hide)
--NP:Update_TagText(nameplate, nameplate.Power.Text, db.power and db.power.text, hide)
end
@@ -0,0 +1,96 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local UnitName = UnitName
local UnitExists = UnitExists
local UnitIsUnit = UnitIsUnit
NP.ThreatPets = {
}
function NP:ThreatIndicator_PreUpdate(unit, pass)
local nameplate, db, unitTarget, imTank = self.__owner, NP.db.threat, unit..'target', E.myrole == 'TANK' or NP.GroupRoles[E.myname] == 'TANK'
local unitRole = NP.IsInGroup and (UnitExists(unitTarget) and not UnitIsUnit(unitTarget, 'player')) and NP.GroupRoles[UnitName(unitTarget)] or 'NONE'
local unitTank = unitRole == 'TANK' or (db.beingTankedByPet and NP.ThreatPets[NP:UnitNPCID(unitTarget)])
local isTank, offTank, feedbackUnit = unitTank or imTank, db.beingTankedByTank and (unitTank and imTank) or false, (unitTank and unitTarget) or 'player'
nameplate.ThreatScale = nil
if pass then
return isTank, offTank, feedbackUnit
else
self.feedbackUnit = feedbackUnit
self.offTank = offTank
self.isTank = isTank
end
end
function NP:ThreatIndicator_PostUpdate(unit, status)
local nameplate, colors, db = self.__owner, NP.db.colors.threat, NP.db.threat
local sf = NP:StyleFilterChanges(nameplate)
if not status and not sf.Scale then
nameplate.ThreatScale = 1
NP:ScalePlate(nameplate, 1)
elseif status and db.enable and db.useThreatColor then
NP:Health_SetColors(nameplate, true)
nameplate.ThreatStatus = status
local Color, Scale
if status == 3 then -- securely tanking
Color = self.offTank and colors.offTankColor or self.isTank and colors.goodColor or colors.badColor
Scale = self.isTank and db.goodScale or db.badScale
elseif status == 2 then -- insecurely tanking
Color = self.offTank and colors.offTankColorBadTransition or self.isTank and colors.badTransition or colors.goodTransition
Scale = 1
elseif status == 1 then -- not tanking but threat higher than tank
Color = self.offTank and colors.offTankColorGoodTransition or self.isTank and colors.goodTransition or colors.badTransition
Scale = 1
else -- not tanking at all
Color = self.isTank and colors.badColor or colors.goodColor
Scale = self.isTank and db.badScale or db.goodScale
end
if sf.HealthColor then
self.r, self.g, self.b = Color.r, Color.g, Color.b
else
nameplate.Health:SetStatusBarColor(Color.r, Color.g, Color.b)
end
if Scale then
nameplate.ThreatScale = Scale
if not sf.Scale then
NP:ScalePlate(nameplate, Scale)
end
end
end
end
function NP:Construct_ThreatIndicator(nameplate)
local ThreatIndicator = nameplate:CreateTexture(nil, 'OVERLAY')
ThreatIndicator:Size(16, 16)
ThreatIndicator:Hide()
ThreatIndicator:Point('CENTER', nameplate, 'TOPRIGHT')
ThreatIndicator.PreUpdate = NP.ThreatIndicator_PreUpdate
ThreatIndicator.PostUpdate = NP.ThreatIndicator_PostUpdate
return ThreatIndicator
end
function NP:Update_ThreatIndicator(nameplate)
local db = NP.db.threat
if nameplate.frameType == 'ENEMY_NPC' and db.enable then
if not nameplate:IsElementEnabled('ThreatIndicator') then
nameplate:EnableElement('ThreatIndicator')
end
if db.indicator then
nameplate.ThreatIndicator:SetAlpha(1)
else
nameplate.ThreatIndicator:SetAlpha(0)
end
elseif nameplate:IsElementEnabled('ThreatIndicator') then
nameplate:DisableElement('ThreatIndicator')
end
end
+19 -17
View File
@@ -1,17 +1,19 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="Nameplates.lua"/>
<Script file="StyleFilter.lua"/>
<Script file="Elements\Auras.lua"/>
<Script file="Elements\CastBar.lua"/>
<Script file="Elements\ComboPoints.lua"/>
<Script file="Elements\Glow.lua"/>
<Script file="Elements\HealthBar.lua"/>
<Script file="Elements\CutawayHealth.lua"/>
<Script file="Elements\Level.lua"/>
<Script file="Elements\Name.lua"/>
<Script file="Elements\RaidIcon.lua"/>
<Script file="Elements\HealerIcon.lua"/>
<Script file="Elements\Elite.lua"/>
<Script file="Elements\Highlight.lua"/>
<Script file="Elements\IconFrame.lua"/>
</Ui>
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
<Script file='Nameplates.lua'/>
<Script file='StyleFilter.lua'/>
<Script file='Elements\Auras.lua'/>
<Script file='Elements\BossMods.lua'/>
<Script file='Elements\CastBar.lua'/>
<Script file='Elements\ClassPower.lua'/>
<Script file='Elements\Health.lua'/>
<Script file='Elements\Plugins.lua'/>
<Script file='Elements\Power.lua'/>
<Script file='Elements\Portraits.lua'/>
<Script file='Elements\PvP.lua'/>
<Script file='Elements\RaidTargetIndicator.lua'/>
<Script file='Elements\Tags.lua'/>
<Script file='Elements\Threat.lua'/>
<Script file='Plugins\ClassificationIndicator.lua'/>
<Script file='Plugins\QuestIcons.lua'/>
<Script file='Plugins\TargetIndicator.lua'/>
</Ui>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,60 @@
local E, L, V, P, G = unpack(ElvUI)
local oUF = E.oUF
local function Update(self)
local element = self.ClassificationIndicator
if element.PreUpdate then
element:PreUpdate()
end
local classification = self.classification
if classification == 'elite' or classification == 'worldboss' then
element:SetAtlas('nameplates-icon-elite-gold')
element:Show()
elseif classification == 'rareelite' or classification == 'rare' then
element:SetAtlas('nameplates-icon-elite-silver')
element:Show()
else
element:Hide()
end
if element.PostUpdate then
return element:PostUpdate(classification)
end
end
local function Path(self, ...)
return (self.ClassificationIndicator.Override or Update) (self, ...)
end
local function ForceUpdate(element)
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
end
local function Enable(self)
local element = self.ClassificationIndicator
if element then
element.__owner = self
element.ForceUpdate = ForceUpdate
if element:IsObjectType('Texture') and not element:GetTexture() then
element:SetTexture([[Interface\TARGETINGFRAME\Nameplates]])
end
self:RegisterEvent('UNIT_CLASSIFICATION_CHANGED', Path)
return true
end
end
local function Disable(self)
local element = self.ClassificationIndicator
if element then
element:Hide()
self:UnregisterEvent('UNIT_CLASSIFICATION_CHANGED', Path)
end
end
oUF:AddElement('ClassificationIndicator', Path, Enable, Disable)
@@ -0,0 +1,77 @@
local E, L, V, P, G = unpack(ElvUI)
local oUF = E.oUF
local UnitExists = UnitExists
local UnitIsUnit = UnitIsUnit
local function MouseOnUnit(frame)
if frame and frame:IsVisible() and UnitExists('mouseover') then
return frame.unit and UnitIsUnit('mouseover', frame.unit)
end
return false
end
local function OnUpdate(self, elapsed)
if self.elapsed and self.elapsed > 0.1 then
if not MouseOnUnit(self) then
self:Hide()
self:ForceUpdate()
end
self.elapsed = 0
else
self.elapsed = (self.elapsed or 0) + elapsed
end
end
local function Update(self)
local element = self.Highlight
if element.PreUpdate then
element:PreUpdate()
end
if MouseOnUnit(self) then
element:Show()
else
element:Hide()
end
if element.PostUpdate then
return element:PostUpdate(element:IsShown())
end
end
local function Path(self, ...)
return (self.Highlight.Override or Update)(self, ...)
end
local function ForceUpdate(element)
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
end
local function Enable(self)
local element = self.Highlight
if element then
element.__owner = self
element.ForceUpdate = ForceUpdate
element:SetScript('OnUpdate', OnUpdate)
self:RegisterEvent('UPDATE_MOUSEOVER_UNIT', Path, true)
return true
end
end
local function Disable(self)
local element = self.Highlight
if element then
element:Hide()
element:SetScript('OnUpdate', nil)
self:UnregisterEvent('UPDATE_MOUSEOVER_UNIT', Path)
end
end
oUF:AddElement('Highlight', Path, Enable, Disable)
@@ -0,0 +1,315 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local oUF = E.oUF
local _G = _G
local pairs, ipairs, ceil, floor, tonumber = pairs, ipairs, ceil, floor, tonumber
local wipe, strmatch, strlower, strfind = wipe, strmatch, strlower, strfind
local IsInInstance = IsInInstance
local UnitIsPlayer = UnitIsPlayer
local GetQuestLogSpecialItemInfo = GetQuestLogSpecialItemInfo
local GetQuestLogTitle = GetQuestLogTitle
local GetNumQuestLogEntries = GetNumQuestLogEntries
local C_Quest_GetQuestID = GenerateClosure(C_Quest.GetQuestID, C_Quest)
local ThreatTooltip = THREAT_TOOLTIP:gsub('%%d', '%%d-')
local questIcons = {
iconTypes = { 'Default', 'Item', 'Skull', 'Chat' },
indexByID = {}, --[questID] = questIndex
activeQuests = {} --[questTitle] = questID
}
NP.QuestIcons = questIcons
local typesLocalized = {
enUS = {
--- short matching applies here so,
-- kill: killed, destory: destoryed, etc ...
KILL = {'slain', 'destroy', 'eliminate', 'repel', 'kill', 'defeat'},
CHAT = {'speak', 'talk'}
},
deDE = {
KILL = {'besiegen', 'besiegt', 'getötet', 'töten', 'tötet', 'vernichtet', 'zerstört', 'genährt'},
CHAT = {'befragt', 'sprecht'}
},
ruRU = {
KILL = {'убит', 'уничтож', 'разбомблен', 'разбит', 'сразит'},
CHAT = {'поговорит', 'спрашивать'}
},
esMX = {
-- asesinad: asesinado, asesinados, asesinada, asesinadas
-- derrota: derrotar, derrotado, derrotados, derrotada, derrotadas
-- destrui: destruir, destruido, destruidos, destruida, destruidas
-- elimin: eliminar, elimine, eliminadas, eliminada, eliminados, eliminado
-- repel: repele, repelido, repelidos, repelida, repelidas
KILL = {'asesinad', 'destrui', 'elimin', 'repel', 'derrota'},
CHAT = {'habla', 'pídele'}
},
ptBR = {
-- destrui: above but also destruição
-- repel: repelir, repelido, repelidos, repelida, repelidas
KILL = {'morto', 'morta', 'matar', 'destrui', 'elimin', 'repel', 'derrota'},
CHAT = {'falar', 'pedir'}
},
frFR = {
-- tué: tués, tuée, tuées
-- abattu: abattus, abattue
-- détrui: détruite, détruire, détruit, détruits, détruites
-- repouss: repousser, repoussés, repoussée, repoussées
-- élimin: éliminer, éliminé, éliminés, éliminée, éliminées
KILL = {'tué', 'tuer', 'attaqué', 'attaque', 'abattre', 'abattu', 'détrui', 'élimin', 'repouss', 'vaincu', 'vaincre'},
-- demande: demander, demandez
-- parle: parler, parlez
CHAT = {'parle', 'demande'}
},
koKR = {
KILL = {'쓰러뜨리기', '물리치기', '공격', '파괴'},
CHAT = {'대화'}
},
zhCN = {
KILL = {'消灭', '摧毁', '击败', '毁灭', '击退'},
CHAT = {'交谈', '谈一谈'}
},
zhTW = {
KILL = {'毀滅', '擊退', '殺死'},
CHAT = {'交談', '說話'}
},
}
local questTypes = typesLocalized[E.locale] or typesLocalized.enUS
local function CheckTextForQuest(text)
local x, y = strmatch(text, '(%d+)/(%d+)')
if x and y then
local diff = floor(y - x)
if diff > 0 then
return diff
end
elseif not strmatch(text, ThreatTooltip) then
local progress = tonumber(strmatch(text, '([%d%.]+)%%'))
if progress and progress <= 100 then
return ceil(100 - progress), true
end
end
end
NP.QuestIcons.CheckTextForQuest = CheckTextForQuest
local function GetQuests(unitID)
if IsInInstance() then return end
E.ScanTooltip:SetOwner(_G.UIParent, 'ANCHOR_NONE')
E.ScanTooltip:SetUnit(unitID)
E.ScanTooltip:Show()
local QuestList, notMyQuest, activeID
for i = 3, E.ScanTooltip:NumLines() do
local str = _G['ElvUI_ScanTooltipTextLeft' .. i]
local text = str and str:GetText()
if not text or text == '' then return end
if UnitIsPlayer(text) then
notMyQuest = text ~= E.myname
elseif text and not notMyQuest then
local count, percent = CheckTextForQuest(text)
-- this line comes from one line up in the tooltip
local activeQuest = questIcons.activeQuests[text]
if activeQuest then activeID = activeQuest end
if count then
local type, index, texture, _
if activeID then
index = questIcons.indexByID[activeID]
_, texture = GetQuestLogSpecialItemInfo(index)
end
if texture then
type = 'QUEST_ITEM'
else
local lowerText = strlower(text)
-- check kill type first
for _, listText in ipairs(questTypes.KILL) do
if strfind(lowerText, listText, nil, true) then
type = 'KILL'
break
end
end
-- check chat type if kill type doesn't exist
if not type then
for _, listText in ipairs(questTypes.CHAT) do
if strfind(lowerText, listText, nil, true) then
type = 'CHAT'
break
end
end
end
end
if not QuestList then QuestList = {} end
QuestList[#QuestList + 1] = {
isPercent = percent,
itemTexture = texture,
objectiveCount = count,
questType = type or 'DEFAULT',
-- below keys are currently unused
questLogIndex = index,
questID = activeID
}
end
end
end
E.ScanTooltip:Hide()
return QuestList
end
local function hideIcons(element)
for _, object in pairs(questIcons.iconTypes) do
local icon = element[object]
icon:Hide()
if icon.Text then
icon.Text:SetText('')
end
end
end
local function Update(self, event, arg1)
local element = self.QuestIcons
if not element then return end
local unit = (event == 'UNIT_NAME_UPDATE' and arg1) or self.unit
if unit ~= self.unit then return end
if element.PreUpdate then
element:PreUpdate()
end
hideIcons(element)
local QuestList = GetQuests(unit)
if QuestList then
element:Show()
else
element:Hide()
return
end
local shownCount
for i = 1, #QuestList do
local quest = QuestList[i]
local objectiveCount = quest.objectiveCount
local questType = quest.questType
local isPercent = quest.isPercent
if isPercent or objectiveCount > 0 then
local icon
if questType == 'DEFAULT' then
icon = element.Default
elseif questType == 'KILL' then
icon = element.Skull
elseif questType == 'CHAT' then
icon = element.Chat
elseif questType == 'QUEST_ITEM' then
icon = element.Item
end
if icon and not icon:IsShown() then
shownCount = (shownCount and shownCount + 1) or 0
local size = icon.size or 25
local setPosition = icon.position or 'TOPLEFT'
local newPosition = E.InversePoints[setPosition]
local offset = shownCount * (5 + size)
icon:Show()
icon:ClearAllPoints()
icon:Point(newPosition, element, newPosition, (strmatch(setPosition, 'LEFT') and -offset) or offset, 0)
if questType ~= 'CHAT' and icon.Text and (isPercent or objectiveCount > 1) then
icon.Text:SetText((isPercent and objectiveCount..'%') or objectiveCount)
end
if questType == 'QUEST_ITEM' then
element.Item:SetTexture(quest.itemTexture)
end
end
end
end
if element.PostUpdate then
return element:PostUpdate()
end
end
local function Path(self, ...)
return (self.QuestIcons.Override or Update) (self, ...)
end
local function ForceUpdate(element)
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
end
local function Enable(self)
local element = self.QuestIcons
if element then
element.__owner = self
element.ForceUpdate = ForceUpdate
if element.Default:IsObjectType('Texture') and not element.Default:GetAtlas() then
element.Default:SetAtlas('SmallQuestBang')
end
if element.Skull:IsObjectType('Texture') and not element.Skull:GetTexture() then
element.Skull:SetTexture(E.Media.Textures.SkullIcon)
end
if element.Chat:IsObjectType('StatusBar') and not element.Chat:GetTexture() then
element.Chat:SetTexture([[Interface\WorldMap\ChatBubble_64.PNG]])
end
self:RegisterEvent('QUEST_LOG_UPDATE', Path, true)
self:RegisterEvent('UNIT_NAME_UPDATE', Path, true)
self:RegisterEvent('PLAYER_ENTERING_WORLD', Path, true)
return true
end
end
local function Disable(self)
local element = self.QuestIcons
if element then
element:Hide()
hideIcons(element)
self:UnregisterEvent('QUEST_LOG_UPDATE', Path)
self:UnregisterEvent('UNIT_NAME_UPDATE', Path)
self:UnregisterEvent('PLAYER_ENTERING_WORLD', Path)
end
end
local frame = CreateFrame('Frame')
frame:RegisterEvent('QUEST_ACCEPTED')
frame:RegisterEvent('QUEST_REMOVED')
frame:RegisterEvent('PLAYER_ENTERING_WORLD')
frame:SetScript('OnEvent', function(self, event)
wipe(questIcons.indexByID)
wipe(questIcons.activeQuests)
for i = 1, GetNumQuestLogEntries() do
local id = C_Quest_GetQuestID(i)
if id and id > 0 then
questIcons.indexByID[id] = i
local title = GetQuestLogTitle(i)
if title then questIcons.activeQuests[title] = id end
end
end
if event == 'PLAYER_ENTERING_WORLD' then
self:UnregisterEvent(event)
end
end)
oUF:AddElement('QuestIcons', Path, Enable, Disable)
@@ -0,0 +1,152 @@
local E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule('NamePlates')
local ElvUF = E.oUF
local UnitHealth = UnitHealth
local UnitIsUnit = UnitIsUnit
local UnitHealthMax = UnitHealthMax
--[[ Target Glow Style Option Variables
style1:'Border',
style2:'Background',
style3:'Top Arrow Only',
style4:'Side Arrows Only',
style5:'Border + Top Arrow',
style6:'Background + Top Arrow',
style7:'Border + Side Arrows',
style8:'Background + Side Arrows'
]]
local function HideIndicators(element)
if element.TopIndicator then element.TopIndicator:Hide() end
if element.LeftIndicator then element.LeftIndicator:Hide() end
if element.RightIndicator then element.RightIndicator:Hide() end
if element.Shadow then element.Shadow:Hide() end
if element.Spark then element.Spark:Hide() end
end
local function ShowIndicators(element, isTarget, color)
if isTarget then
if element.TopIndicator and (element.style == 'style3' or element.style == 'style5' or element.style == 'style6') then
element.TopIndicator:SetVertexColor(color.r, color.g, color.b)
element.TopIndicator:SetTexture(element.arrow)
element.TopIndicator:Show()
end
if element.LeftIndicator and element.RightIndicator and (element.style == 'style4' or element.style == 'style7' or element.style == 'style8') then
element.LeftIndicator:SetVertexColor(color.r, color.g, color.b)
element.RightIndicator:SetVertexColor(color.r, color.g, color.b)
element.LeftIndicator:SetTexture(element.arrow)
element.RightIndicator:SetTexture(element.arrow)
element.RightIndicator:Show()
element.LeftIndicator:Show()
end
end
if element.Shadow and (element.style == 'style1' or element.style == 'style5' or element.style == 'style7') then
element.Shadow:SetBackdropBorderColor(color.r, color.g, color.b)
element.Shadow:Show()
end
if element.Spark and (element.style == 'style2' or element.style == 'style6' or element.style == 'style8') then
element.Spark:SetVertexColor(color.r, color.g, color.b)
element.Spark:Show()
end
end
local function Update(self)
local element = self.TargetIndicator
if element.PreUpdate then
element:PreUpdate()
end
HideIndicators(element)
if element.style ~= 'none' then
local isTarget = UnitIsUnit(self.unit, 'target')
local lowHealth = element.lowHealthThreshold > 0
if isTarget and (element.preferGlowColor or not lowHealth) then
ShowIndicators(element, isTarget, NP.db.colors.glowColor)
elseif lowHealth then
local health, maxHealth = UnitHealth(self.unit), UnitHealthMax(self.unit)
local perc = (maxHealth > 0 and health/maxHealth) or 0
-- color tables are class updated in UpdateMedia
if perc <= element.lowHealthThreshold * 0.5 then
ShowIndicators(element, isTarget, NP.db.colors.lowHealthHalf)
elseif perc <= element.lowHealthThreshold then
ShowIndicators(element, isTarget, NP.db.colors.lowHealthColor)
elseif isTarget then
ShowIndicators(element, isTarget, NP.db.colors.glowColor)
end
end
end
if element.PostUpdate then
return element:PostUpdate(self.unit)
end
end
local function Path(self, ...)
return (self.TargetIndicator.Override or Update) (self, ...)
end
local function ForceUpdate(element)
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
end
local function Enable(self)
local element = self.TargetIndicator
if element then
element.__owner = self
element.ForceUpdate = ForceUpdate
if not element.style then element.style = 'style1' end
if not element.preferGlowColor then element.preferGlowColor = true end
if not element.lowHealthThreshold then element.lowHealthThreshold = .4 end
if element.Shadow and element.Shadow:IsObjectType('Frame') and not element.Shadow:GetBackdrop() then
element.Shadow:SetBackdrop({edgeFile = E.Media.Textures.GlowTex, edgeSize = 5})
end
if element.Spark and element.Spark:IsObjectType('Texture') and not element.Spark:GetTexture() then
element.Spark:SetTexture(E.Media.Textures.Spark)
end
if element.TopIndicator and element.TopIndicator:IsObjectType('Texture') and not element.TopIndicator:GetTexture() then
element.TopIndicator:SetTexture(E.Media.Textures.ArrowUp)
element.TopIndicator:SetTexCoord(1, 1, 1, 0, 0, 1, 0, 0) --Rotates texture 180 degress (Up arrow to face down)
end
if element.LeftIndicator and element.LeftIndicator:IsObjectType('Texture') and not element.LeftIndicator:GetTexture() then
element.LeftIndicator:SetTexture(E.Media.Textures.ArrowUp)
element.LeftIndicator:SetTexCoord(1, 0, 0, 0, 1, 1, 0, 1) --Rotates texture 90 degrees clockwise (Up arrow to face right)
end
if element.RightIndicator and element.RightIndicator:IsObjectType('Texture') and not element.RightIndicator:GetTexture() then
element.RightIndicator:SetTexture(E.Media.Textures.ArrowUp)
element.RightIndicator:SetTexCoord(1, 1, 0, 1, 1, 0, 0, 0) --Flips texture horizontally (Right facing arrow to face left)
end
self:RegisterEvent('UNIT_HEALTH', Path)
self:RegisterEvent('UNIT_MAXHEALTH', Path)
self:RegisterEvent('PLAYER_TARGET_CHANGED', Path, true)
return true
end
end
local function Disable(self)
local element = self.TargetIndicator
if element then
HideIndicators(element)
self:UnregisterEvent('UNIT_HEALTH', Path)
self:UnregisterEvent('UNIT_MAXHEALTH', Path)
self:UnregisterEvent('PLAYER_TARGET_CHANGED', Path)
end
end
ElvUF:AddElement('TargetIndicator', Path, Enable, Disable)
File diff suppressed because it is too large Load Diff
@@ -137,6 +137,9 @@ S:AddCallback("Skin_BlizzardOptions", function()
"InterfaceOptionsCombatPanelTargetOfTarget",
"InterfaceOptionsCombatPanelEnemyCastBarsOnPortrait",
"InterfaceOptionsCombatPanelEnemyCastBarsOnNameplates",
"InterfaceOptionsCombatPanelAoEIndicatorsSelf",
"InterfaceOptionsCombatPanelAoEIndicatorsEnemies",
"InterfaceOptionsCombatPanelAoEIndicatorsFriendly",
"InterfaceOptionsDisplayPanelShowCloak",
"InterfaceOptionsDisplayPanelShowHelm",
"InterfaceOptionsDisplayPanelShowAggroPercentage",
@@ -257,7 +260,11 @@ S:AddCallback("Skin_BlizzardOptions", function()
"InterfaceOptionsAscensionLoseControlPanelEnableSlow",
"InterfaceOptionsAscensionLoseControlPanelEnableStun",
"InterfaceOptionsAscensionLoseControlPanelEnablePacify",
"InterfaceOptionsDraftPanelAutoPopupDraft",
"InterfaceOptionsDraftPanelAutoRevealDraft",
"InterfaceOptionsDraftPanelSkipDraftConfirmation",
"InterfaceOptionsDraftPanelSkipDraftSacrificeConfirmation",
"InterfaceOptionsDraftPanelShowBuildDraftSpellCards",
"AudioOptionsSoundPanelEnableSound",
"AudioOptionsSoundPanelSoundEffects",
@@ -306,7 +313,9 @@ S:AddCallback("Skin_BlizzardOptions", function()
"InterfaceOptionsCombatPanelSpellActivationOverlayAlpha",
"InterfaceOptionsMousePanelMouseLookSpeedSlider",
"InterfaceOptionsMousePanelMouseSensitivitySlider",
"InterfaceOptionsCombatPanelNameplateDistance",
"InterfaceOptionsCombatPanelNameplateZ",
"AudioOptionsSoundPanelSoundQuality",
"AudioOptionsSoundPanelSoundChannels",
"AudioOptionsSoundPanelMasterVolume",
-1
View File
@@ -21,7 +21,6 @@ S:AddCallback("Skin_LFD", function()
AscensionLFGFrameContent:StripTextures(true)
AscensionLFGFrameMenu:StripTextures(true)
AscensionLFGFrameInset:StripTextures(true)
AscensionLFGFrameInset:CreateBackdrop("Transparent")
AscensionLFGFrameInsetNineSlice:StripTextures(true)
AscensionLFGFrameNineSlice:StripTextures(true)
AscensionLFGFrameMenuNineSlice:StripTextures(true)
+21 -39
View File
@@ -77,47 +77,29 @@ local function createConfigEnv()
__newindex = function(_, key, value) _G[key] = value end,
})
overrideFuncs["namecolor"] = ElvUF.Tags.Methods["namecolor"]
overrideFuncs["name:veryshort"] = ElvUF.Tags.Methods["name:veryshort"]
overrideFuncs["name:short"] = ElvUF.Tags.Methods["name:short"]
overrideFuncs["name:medium"] = ElvUF.Tags.Methods["name:medium"]
overrideFuncs["name:long"] = ElvUF.Tags.Methods["name:long"]
overrideFuncs['classcolor'] = ElvUF.Tags.Methods['classcolor']
overrideFuncs['name:veryshort'] = ElvUF.Tags.Methods['name:veryshort']
overrideFuncs['name:short'] = ElvUF.Tags.Methods['name:short']
overrideFuncs['name:medium'] = ElvUF.Tags.Methods['name:medium']
overrideFuncs['name:long'] = ElvUF.Tags.Methods['name:long']
overrideFuncs["healthcolor"] = ElvUF.Tags.Methods["healthcolor"]
overrideFuncs["health:current"] = ElvUF.Tags.Methods["health:current"]
overrideFuncs["health:deficit"] = ElvUF.Tags.Methods["health:deficit"]
overrideFuncs["health:current-percent"] = ElvUF.Tags.Methods["health:current-percent"]
overrideFuncs["health:current-max"] = ElvUF.Tags.Methods["health:current-max"]
overrideFuncs["health:current-max-percent"] = ElvUF.Tags.Methods["health:current-max-percent"]
overrideFuncs["health:max"] = ElvUF.Tags.Methods["health:max"]
overrideFuncs["health:percent"] = ElvUF.Tags.Methods["health:percent"]
overrideFuncs['healthcolor'] = ElvUF.Tags.Methods['healthcolor']
overrideFuncs['health:current'] = ElvUF.Tags.Methods['health:current']
overrideFuncs['health:deficit'] = ElvUF.Tags.Methods['health:deficit']
overrideFuncs['health:current-percent'] = ElvUF.Tags.Methods['health:current-percent']
overrideFuncs['health:current-max'] = ElvUF.Tags.Methods['health:current-max']
overrideFuncs['health:current-max-percent'] = ElvUF.Tags.Methods['health:current-max-percent']
overrideFuncs['health:max'] = ElvUF.Tags.Methods['health:max']
overrideFuncs['health:percent'] = ElvUF.Tags.Methods['health:percent']
overrideFuncs["powercolor"] = ElvUF.Tags.Methods["powercolor"]
overrideFuncs["power:current"] = ElvUF.Tags.Methods["power:current"]
overrideFuncs["power:deficit"] = ElvUF.Tags.Methods["power:deficit"]
overrideFuncs["power:current-percent"] = ElvUF.Tags.Methods["power:current-percent"]
overrideFuncs["power:current-max"] = ElvUF.Tags.Methods["power:current-max"]
overrideFuncs["power:current-max-percent"] = ElvUF.Tags.Methods["power:current-max-percent"]
overrideFuncs["power:max"] = ElvUF.Tags.Methods["power:max"]
overrideFuncs["power:percent"] = ElvUF.Tags.Methods["power:percent"]
overrideFuncs["energycolor"] = ElvUF.Tags.Methods["energycolor"]
overrideFuncs["energy:current"] = ElvUF.Tags.Methods["energy:current"]
overrideFuncs["energy:deficit"] = ElvUF.Tags.Methods["energy:deficit"]
overrideFuncs["energy:current-percent"] = ElvUF.Tags.Methods["energy:current-percent"]
overrideFuncs["energy:current-max"] = ElvUF.Tags.Methods["energy:current-max"]
overrideFuncs["energy:current-max-percent"] = ElvUF.Tags.Methods["energy:current-max-percent"]
overrideFuncs["energy:max"] = ElvUF.Tags.Methods["energy:max"]
overrideFuncs["energy:percent"] = ElvUF.Tags.Methods["energy:percent"]
overrideFuncs["ragecolor"] = ElvUF.Tags.Methods["ragecolor"]
overrideFuncs["rage:current"] = ElvUF.Tags.Methods["rage:current"]
overrideFuncs["rage:deficit"] = ElvUF.Tags.Methods["rage:deficit"]
overrideFuncs["rage:current-percent"] = ElvUF.Tags.Methods["rage:current-percent"]
overrideFuncs["rage:current-max"] = ElvUF.Tags.Methods["rage:current-max"]
overrideFuncs["rage:current-max-percent"] = ElvUF.Tags.Methods["rage:current-max-percent"]
overrideFuncs["rage:max"] = ElvUF.Tags.Methods["rage:max"]
overrideFuncs["rage:percent"] = ElvUF.Tags.Methods["rage:percent"]
overrideFuncs['powercolor'] = ElvUF.Tags.Methods['powercolor']
overrideFuncs['power:current'] = ElvUF.Tags.Methods['power:current']
overrideFuncs['power:deficit'] = ElvUF.Tags.Methods['power:deficit']
overrideFuncs['power:current-percent'] = ElvUF.Tags.Methods['power:current-percent']
overrideFuncs['power:current-max'] = ElvUF.Tags.Methods['power:current-max']
overrideFuncs['power:current-max-percent'] = ElvUF.Tags.Methods['power:current-max-percent']
overrideFuncs['power:max'] = ElvUF.Tags.Methods['power:max']
overrideFuncs['power:percent'] = ElvUF.Tags.Methods['power:percent']
end
function UF:ForceShow(frame)
@@ -173,6 +173,33 @@ function UF.SortAuraBarName(a, b)
return a.name > b.name
end
function UF:ConvertFilters(auras, priority)
if not priority or priority == '' then return end
local list = auras.filterList or {}
if next(list) then wipe(list) end
local special, filters = G.unitframe.specialFilters, E.global.unitframe.aurafilters
for _, name in next, { strsplit(',', priority) } do
local friend, enemy = strmatch(name, '^Friendly:([^,]*)'), strmatch(name, '^Enemy:([^,]*)')
local real = friend or enemy or name
local custom = filters[real]
if special[real] or custom then
tinsert(list, {
name = real,
custom = custom,
status = (friend and 1) or (enemy and 2)
})
end
end
if next(list) then
return list
end
end
function UF:CheckFilter(name, caster, spellID, isFriend, isPlayer, isUnit, allowDuration, noDuration, canDispell, ...)
for i = 1, select("#", ...) do
local filterName = select(i, ...)
+120
View File
@@ -1,5 +1,6 @@
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local UF = E:GetModule("UnitFrames")
local NP = E:GetModule('NamePlates')
local LSM = E.Libs.LSM
--Lua functions
@@ -16,6 +17,58 @@ local UnitCanAttack = UnitCanAttack
local UnitIsFriend = UnitIsFriend
local UnitIsUnit = UnitIsUnit
UF.MatchGrowthY = { TOP = 'TOP', BOTTOM = 'BOTTOM' }
UF.MatchGrowthX = { LEFT = 'LEFT', RIGHT = 'RIGHT' }
UF.SortAuraFuncs = {
TIME_REMAINING = function(a, b, dir)
local A = a.noTime and huge or a.expiration or -huge
local B = b.noTime and huge or b.expiration or -huge
if dir == 'DESCENDING' then return A < B else return A > B end
end,
DURATION = function(a, b, dir)
local A = a.noTime and huge or a.duration or -huge
local B = b.noTime and huge or b.duration or -huge
if dir == 'DESCENDING' then return A < B else return A > B end
end,
NAME = function(a, b, dir)
local A, B = a.name or '', b.name or ''
if dir == 'DESCENDING' then return A < B else return A > B end
end,
PLAYER = function(a, b, dir)
local A, B = a.isPlayer or false, b.isPlayer or false
if dir == 'DESCENDING' then return A and not B else return not A and B end
end,
}
UF.SmartPosition = {
BUFFS_ON_DEBUFFS = {
from = 'BUFFS', to = 'Debuffs',
warning = 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"]),
func = function(db, buffs, debuffs)
db.buffs.attachTo = 'DEBUFFS'
buffs.attachTo = debuffs
buffs.PostUpdate = nil
debuffs.PostUpdate = UF.UpdateAuraSmartPoisition
end
},
DEBUFFS_ON_BUFFS = {
from = 'DEBUFFS', to = 'Buffs',
warning = 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"]),
func = function(db, buffs, debuffs)
db.debuffs.attachTo = 'BUFFS'
debuffs.attachTo = buffs
debuffs.PostUpdate = nil
buffs.PostUpdate = UF.UpdateAuraSmartPoisition
end
}
}
UF.SmartPosition.FLUID_BUFFS_ON_DEBUFFS = E:CopyTable({fluid = true}, UF.SmartPosition.BUFFS_ON_DEBUFFS)
UF.SmartPosition.FLUID_DEBUFFS_ON_BUFFS = E:CopyTable({fluid = true}, UF.SmartPosition.DEBUFFS_ON_BUFFS)
function UF:Construct_Buffs(frame)
local buffs = CreateFrame("Frame", frame:GetName().."Buffs", frame)
buffs.spacing = E.Spacing
@@ -134,6 +187,48 @@ function UF:UpdateAuraCooldownPosition(button)
button.needsUpdateCooldownPosition = nil
end
function UF:GetAuraElements(frame)
if frame.isNamePlate then
return frame.Buffs_, frame.Debuffs_
else
return frame.Buffs, frame.Debuffs
end
end
function UF:SetSmartPosition(frame, db)
if frame.isNamePlate then db = NP:PlateDB(frame) end
local position, fluid = db.smartAuraPosition
local buffs, debuffs = UF:GetAuraElements(frame)
local info = UF.SmartPosition[position]
if info then
local TO = db[strlower(info.to)]
if TO.attachTo == info.from then
TO.attachTo = 'FRAME'
E:Print(info.warning)
local element = (info.to == 'Debuffs' and debuffs) or buffs
element.attachTo = frame
element:ClearAllPoints()
element:Point(element.initialAnchor, element.attachTo, element.anchorPoint, element.xOffset, element.yOffset)
end
fluid = info.fluid
info.func(db, buffs, debuffs, info.isFuild)
else
buffs.PostUpdate = nil
debuffs.PostUpdate = nil
end
if db.debuffs.attachTo == 'BUFFS' and db.buffs.attachTo == 'DEBUFFS' then
E:Print(format(L["%s frame has a conflicting anchor point. Forcing the Buffs to be attached to the main unitframe."], E:StringTitle(frame:GetName())))
db.buffs.attachTo = 'FRAME'
end
return position, fluid
end
function UF:Configure_Auras(frame, auraType)
if not frame.VARIABLES_SET then return end
@@ -382,6 +477,31 @@ function UF:PostUpdateAura(unit, button)
end
end
function UF:GetSmartAuraElements(auras)
local Buffs, Debuffs = UF:GetAuraElements(auras:GetParent())
if auras == Buffs then
return Debuffs, Buffs, auras.visibleBuffs
else
return Buffs, Debuffs, auras.visibleDebuffs
end
end
function UF:UpdateAuraSmartPoisition()
local element, other, visible = UF:GetSmartAuraElements(self)
if visible == 0 then
if self.smartFluid then
element:ClearAllPoints()
element:Point(other.initialAnchor, other.attachTo, other.anchorPoint, other.xOffset, other.yOffset)
else
other:Height(UF:GetAuraPosition(other, true))
end
else
element:ClearAllPoints()
element:Point(element.initialAnchor, element.attachTo, element.anchorPoint, element.xOffset, element.yOffset)
end
end
function UF:AuraFilter(unit, button, name, _, _, _, debuffType, duration, expiration, caster, isStealable, _, spellID)
if not name then return end -- checking for an aura that is not there, pass nil to break while loop
@@ -10,7 +10,7 @@ function UF:Construct_Cutaway(frame)
if frame.Power then
local powerTexture = frame.Power:GetStatusBarTexture()
local cutawayPower = frame.Power.ClipFrame:CreateTexture(frameName.."CutawayPower")
local cutawayPower = frame.Power:CreateTexture(frameName.."CutawayPower")
cutawayPower:SetPoint("TOPLEFT", powerTexture, "TOPRIGHT")
cutawayPower:SetPoint("BOTTOMLEFT", powerTexture, "BOTTOMRIGHT")
cutawayPower:SetTexture(E.media.blankTex)
@@ -18,7 +18,7 @@ function UF:Construct_Cutaway(frame)
end
local healthTexture = frame.Health:GetStatusBarTexture()
local cutawayHealth = frame.Health.ClipFrame:CreateTexture(frameName.."CutawayHealth")
local cutawayHealth = frame.Health:CreateTexture(frameName.."CutawayHealth")
cutawayHealth:SetPoint("TOPLEFT", healthTexture, "TOPRIGHT")
cutawayHealth:SetPoint("BOTTOMLEFT", healthTexture, "BOTTOMRIGHT")
cutawayHealth:SetTexture(E.media.blankTex)
@@ -65,6 +65,12 @@ function UF:Configure_Happiness(frame)
end
function UF:HappinessOverride(event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if not unit or self.unit ~= unit then return end
local db = self.db
@@ -60,7 +60,7 @@ function UF:Configure_Energy(frame)
local energy = frame.Energy
energy.origParent = frame
if frame.USE_ENERGYBAR then
if frame.USE_ENERGYBAR and C_Player:IsHero() then
if not frame:IsElementEnabled("Energy") then
frame:EnableElement("Energy")
energy:Show()
@@ -60,7 +60,7 @@ function UF:Configure_Rage(frame)
local rage = frame.Rage
rage.origParent = frame
if frame.USE_RAGEBAR then
if frame.USE_RAGEBAR and C_Player:IsHero() then
if not frame:IsElementEnabled("Rage") then
frame:EnableElement("Rage")
rage:Show()
@@ -30,6 +30,12 @@ function UF:Configure_PVPIcon(frame)
end
function UF:UpdateOverridePvP(event, unit)
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
if isUnit then
unit = self.unit
end
end
if not unit or self.unit ~= unit then return end
local element = self.PvPIndicator
+6 -1
View File
@@ -95,7 +95,12 @@ end
function UF:UpdateThreat(unit, status, r, g, b)
local parent = self:GetParent()
if unit and parent.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
local isUnit = parent.unit and UnitIsUnit(parent.unit, unit)
if isUnit then
unit = parent.unit
end
end
if (parent.unit ~= unit) or not unit then return end
local db = parent.db
+15
View File
@@ -461,6 +461,21 @@ function UF:Configure_Fader(frame)
end
end
function UF:Construct_ClipFrame(frame, bar)
local clipFrame = CreateFrame('ScrollFrame', nil, bar)
clipFrame:SetAllPoints()
clipFrame:EnableMouse(false)
local child = CreateFrame("Frame", nil, clipFrame)
child:SetPoint("CENTER")
child:SetSize(clipFrame:GetSize())
child.__frame = frame
bar.ClipFrame = child
return child
end
function UF:Configure_FontString(obj)
UF.fontstrings[obj] = true
obj:FontTemplate() --This is temporary.
+192 -46
View File
@@ -6,37 +6,50 @@
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
G.nameplates.filters = {
ElvUI_Boss = {
["Non-Target Alpha"] = {
actions = {
alpha = 40,
},
triggers = {
requireTarget = true,
notTarget = true,
enable = true,
},
},
["Enlarge Boss Nameplates"] = {
triggers = {
level = true,
curlevel = -1,
nameplateType = {
enable = true,
enemyNPC = true
}
},
enable = true,
},
actions = {
scale = 1.15
}
},
ElvUI_Totem = {
triggers = {
totems = {
enable = true
}
},
actions = {
iconOnly = true
}
}
}
E.StyleFilterDefaults = {
triggers = {
priority = 1,
targetMe = false,
isTarget = false,
notTarget = false,
requireTarget = false,
noTarget = false,
level = false,
names = {},
items = {},
slots = {},
known = {
notKnown = false,
playerSpell = false,
spells = {} -- new talents
},
class = {}, -- this can stay empty we only will accept values that exist
casting = {
isCasting = false,
isChanneling = false,
@@ -51,6 +64,25 @@ E.StyleFilterDefaults = {
healer = false,
damager = false
},
faction = {
Alliance = false,
Horde = false,
Neutral = false,
},
unitRole = {
tank = false,
healer = false,
damager = false
},
classification = {
worldboss = false,
rareelite = false,
elite = false,
rare = false,
normal = false,
trivial = false,
minus = false
},
raidTarget = {
star = false,
circle = false,
@@ -61,6 +93,16 @@ E.StyleFilterDefaults = {
cross = false,
skull = false
},
threat = {
enable = false,
good = false,
goodTransition = false,
badTransition = false,
bad = false,
offTank = false,
offTankGoodTransition = false,
offTankBadTransition = false
},
curlevel = 0,
maxlevel = 0,
minlevel = 0,
@@ -69,103 +111,207 @@ E.StyleFilterDefaults = {
underHealthThreshold = 0,
overHealthThreshold = 0,
powerThreshold = false,
powerUsePlayer = false,
underPowerThreshold = 0,
overPowerThreshold = 0,
names = {},
creatureType = {
enable = false,
Aberration = false,
Beast = false,
Critter = false,
Demon = false,
Dragonkin = false,
Elemental = false,
['Gas Cloud'] = false,
Giant = false,
Humanoid = false,
Mechanical = false,
['Not specified'] = false,
Totem = false,
Undead = false,
['Wild Pet'] = false,
['Non-combat Pet'] = false
},
nameplateType = {
enable = false,
friendlyPlayer = false,
friendlyNPC = false,
enemyPlayer = false,
enemyNPC = false
enemyNPC = false,
player = false
},
reactionType = {
enabled = false,
reputation = false,
hated = false,
hostile = false,
unfriendly = false,
neutral = false,
friendly = false
friendly = false,
honored = false,
revered = false,
exalted = false
},
instanceType = {
none = false,
sanctuary = false,
scenario = false,
party = false,
raid = false,
arena = false,
pvp = false
},
location = {
mapIDEnabled = false,
mapIDs = {},
instanceIDEnabled = false,
instanceIDs = {},
zoneNamesEnabled = false,
zoneNames = {},
subZoneNamesEnabled = false,
subZoneNames = {}
},
keyMod = {
enable = false,
Modifier = false,
Shift = false,
Alt = false,
Control = false,
LeftShift = false,
LeftAlt = false,
LeftControl = false,
RightShift = false,
RightAlt = false,
RightControl = false
},
instanceDifficulty = {
dungeon = {
normal = false,
heroic = false
heroic = false,
mythic = false,
},
raid = {
normal = false,
heroic = false
heroic = false,
mythic = false,
ascended = false,
}
},
cooldowns = {
names = {},
mustHaveAll = false
mustHaveAll = false,
names = {}
},
buffs = {
mustHaveAll = false,
missing = false,
names = {},
minTimeLeft = 0,
maxTimeLeft = 0
maxTimeLeft = 0,
hasStealable = false,
hasNoStealable = false,
onMe = false,
onPet = false,
fromMe = false,
fromPet = false,
names = {}
},
debuffs = {
mustHaveAll = false,
missing = false,
names = {},
minTimeLeft = 0,
maxTimeLeft = 0
maxTimeLeft = 0,
hasDispellable = false,
hasNoDispellable = false,
onMe = false,
onPet = false,
fromMe = false,
fromPet = false,
names = {}
},
totems = {
enable = false,
a1 = true, a2 = true, a3 = true, a4 = true, a5 = true,
e1 = true, e2 = true, e3 = true, e4 = true, e5 = true, e6 = true,
f1 = true, f2 = true, f3 = true, f4 = true, f5 = true, f6 = true,
w1 = true, w2 = true, w3 = true, w4 = true, w5 = true,
o1 = true
},
uniqueUnits = {
enable = false,
u1 = true, u2 = true
bossMods = {
hasAura = false,
missingAura = false,
missingAuras = false,
auras = {}
},
inRaid = false,
notInRaid = false,
inParty = false,
notInParty = false,
inMyGuild = false,
notMyGuild = false,
isTrivial = false,
notTrivial = false,
isPossessed = false,
notPossessed = false,
isCharmed = false,
notCharmed = false,
isDeadOrGhost = false,
notDeadOrGhost = false,
isConnected = false,
notConnected = false,
isResting = false,
notResting = false,
isPet = false,
isNotPet = false,
isPlayerControlled = false,
isNotPlayerControlled = false,
isOwnedByPlayer = false,
isNotOwnedByPlayer = false,
isPvP = false,
isNotPvP = false,
playerCanAttack = false,
playerCanNotAttack = false,
hasTitleNPC = false,
noTitleNPC = false,
isQuest = false,
notQuest = false,
-- combat
inCombat = false,
outOfCombat = false
outOfCombat = false,
inCombatUnit = false,
outOfCombatUnit = false,
-- vehicle
inVehicle = false,
outOfVehicle = false,
inVehicleUnit = false,
outOfVehicleUnit = false
},
actions = {
color = {
health = false,
power = false,
border = false,
name = false,
healthClass = false,
healthColor = {r = 1, g = 1, b = 1, a = 1},
borderColor = {r = 1, g = 1, b = 1, a = 1},
nameColor = {r = 1, g = 1, b = 1, a = 1}
powerClass = false,
powerColor = {r = 1, g = 1, b = 1, a = 1},
borderClass = false,
borderColor = {r = 1, g = 1, b = 1, a = 1}
},
texture = {
enable = false,
texture = "ElvUI Norm"
texture = 'ElvUI Norm'
},
flash = {
enable = false,
class = false,
color = {r = 1, g = 1, b = 1, a = 1},
speed = 4
},
tags = {
name = '',
level = '',
title = '',
health = '',
power = ''
},
hide = false,
usePortrait = false,
nameOnly = false,
icon = false,
iconOnly = false,
scale = 1.0,
scale = 1,
alpha = -1
}
}
G.nameplates.specialFilters = {
Personal = true,
nonPersonal = true,
blockNonPersonal = true,
blockNoDuration = true
}
+497 -635
View File
File diff suppressed because it is too large Load Diff