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 E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local ElvUF = E.oUF
--Lua functions --Lua functions
local _G = _G local _G = _G
local wipe, date = wipe, date local wipe, date = wipe, date
@@ -210,6 +210,20 @@ function E:ExitVehicleShowFrames(_, unit)
end end
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() function E:RequestBGInfo()
RequestBattlefieldScoreData() RequestBattlefieldScoreData()
end end
+37 -24
View File
@@ -162,11 +162,13 @@ function E:Cooldown_Options(timer, db, parent)
end end
end end
function E:CreateCooldownTimer(parent) function E:CreateCooldownTimer(parent, displayParent)
local timer = CreateFrame("Frame", parent:GetName() and "$parentTimer" or nil, parent) 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:SetFrameLevel(parent:GetFrameLevel() + 1)
timer:Hide() timer:Hide()
timer:SetAllPoints() timer:SetAllPoints(parent)
timer.parent = parent timer.parent = parent
parent.timer = timer parent.timer = timer
@@ -199,9 +201,9 @@ function E:CreateCooldownTimer(parent)
end end
E.RegisteredCooldowns = {} 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 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.start = start
timer.duration = duration timer.duration = duration
timer.endTime = start + duration timer.endTime = start + duration
@@ -213,14 +215,22 @@ function E:OnSetCooldown(start, duration)
end end
end end
function E:RegisterCooldown(cooldown) function E:RegisterCooldown(cooldown, module)
if not cooldown.isHooked then if not cooldown.isHooked then
hooksecurefunc(cooldown, "SetCooldown", E.OnSetCooldown) hooksecurefunc(cooldown, "SetCooldown", E.OnSetCooldown)
if cooldown:GetParent().isNamePlate then
cooldown.Show = cooldown.Hide
cooldown:Hide()
end
cooldown.isHooked = true cooldown.isHooked = true
end end
if not cooldown.isRegisteredCooldown then 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 if not E.RegisteredCooldowns[module] then E.RegisteredCooldowns[module] = {} end
tinsert(E.RegisteredCooldowns[module], cooldown) tinsert(E.RegisteredCooldowns[module], cooldown)
@@ -228,23 +238,26 @@ function E:RegisterCooldown(cooldown)
end end
end end
function E:GetCooldownColors(db) do
if not db then db = E.db.cooldown end -- just incase someone calls this without a first arg use the global local function HEX(db) return E:RGBToHex(db.r, db.g, db.b) end
local c13 = E:RGBToHex(db.hhmmColorIndicator.r, db.hhmmColorIndicator.g, db.hhmmColorIndicator.b) -- color for timers that are soon to expire function E:GetCooldownColors(db)
local c12 = E:RGBToHex(db.mmssColorIndicator.r, db.mmssColorIndicator.g, db.mmssColorIndicator.b) -- color for timers that are soon to expire if not db then db = E.db.cooldown end -- just incase someone calls this without a first arg use the global
local c11 = E:RGBToHex(db.expireIndicator.r, db.expireIndicator.g, db.expireIndicator.b) -- color for timers that are soon to expire return
local c10 = E:RGBToHex(db.secondsIndicator.r, db.secondsIndicator.g, db.secondsIndicator.b) -- color for timers that have seconds remaining db.daysColor,
local c9 = E:RGBToHex(db.minutesIndicator.r, db.minutesIndicator.g, db.minutesIndicator.b) -- color for timers that have minutes remaining db.hoursColor,
local c8 = E:RGBToHex(db.hoursIndicator.r, db.hoursIndicator.g, db.hoursIndicator.b) -- color for timers that have hours remaining db.minutesColor,
local c7 = E:RGBToHex(db.daysIndicator.r, db.daysIndicator.g, db.daysIndicator.b) -- color for timers that have days remaining db.secondsColor,
local c6 = db.hhmmColor -- HH:MM color db.expiringColor,
local c5 = db.mmssColor -- MM:SS color db.mmssColor,
local c4 = db.expiringColor -- color for timers that are soon to expire db.hhmmColor,
local c3 = db.secondsColor -- color for timers that have seconds remaining HEX(db.daysIndicator),
local c2 = db.minutesColor -- color for timers that have minutes remaining HEX(db.hoursIndicator),
local c1 = db.hoursColor -- color for timers that have hours remaining HEX(db.minutesIndicator),
local c0 = db.daysColor -- color for timers that have days remaining HEX(db.secondsIndicator),
return c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13 HEX(db.expireIndicator),
HEX(db.mmssColorIndicator),
HEX(db.hhmmColorIndicator)
end
end end
function E:UpdateCooldownOverride(module) function E:UpdateCooldownOverride(module)
+40
View File
@@ -60,6 +60,7 @@ E.myname = UnitName("player")
E.myrealm = GetRealmName() E.myrealm = GetRealmName()
E.mynameRealm = format('%s - %s', E.myname, E.myrealm) -- contains spaces/dashes in realm (for profile keys) E.mynameRealm = format('%s - %s', E.myname, E.myrealm) -- contains spaces/dashes in realm (for profile keys)
E.version = GetAddOnMetadata("ElvUI", "Version") E.version = GetAddOnMetadata("ElvUI", "Version")
E.versionNum = tonumber(E.version)
E.wowpatch, E.wowbuild = GetBuildInfo() E.wowpatch, E.wowbuild = GetBuildInfo()
E.wowbuild = tonumber(E.wowbuild) E.wowbuild = tonumber(E.wowbuild)
E.resolution = GetCVar("gxResolution") E.resolution = GetCVar("gxResolution")
@@ -1134,6 +1135,14 @@ function E:DBConversions()
if E.private.skins.blizzard.greeting ~= nil then if E.private.skins.blizzard.greeting ~= nil then
E.private.skins.blizzard.greeting = nil E.private.skins.blizzard.greeting = nil
end 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 end
function E:RefreshModulesDB() function E:RefreshModulesDB()
@@ -1143,6 +1152,37 @@ function E:RefreshModulesDB()
UnitFrames.db = self.db.unitframe --new ref UnitFrames.db = self.db.unitframe --new ref
end 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() function E:Initialize()
twipe(self.db) twipe(self.db)
twipe(self.global) 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 len, format, split, strmatch = strlen, format, strsplit, strmatch
local CreateFrame = CreateFrame local CreateFrame = CreateFrame
local IsInRaid, UnitInRaid = IsInRaid, UnitInRaid local IsInRaid, UnitInRaid = GenerateClosure(C_Player, C_Player.IsInRaid, C_Player), UnitInRaid
local IsInGroup, UnitInParty = IsInGroup, UnitInParty 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_HOME = LE_PARTY_CATEGORY_HOME
-- local LE_PARTY_CATEGORY_INSTANCE = LE_PARTY_CATEGORY_INSTANCE -- local LE_PARTY_CATEGORY_INSTANCE = LE_PARTY_CATEGORY_INSTANCE
local ACCEPT, CANCEL, YES, NO = ACCEPT, CANCEL, YES, NO 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 E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local LSM = E.Libs.LSM local LSM = E.Libs.LSM
local NP = E:GetModule('NamePlates')
--Lua functions --Lua functions
local _G = _G local _G = _G
@@ -78,7 +79,7 @@ local function SetInside(obj, anchor, xOffset, yOffset, anchor2)
obj:Point("BOTTOMRIGHT", anchor2 or anchor, "BOTTOMRIGHT", -xOffset, yOffset) obj:Point("BOTTOMRIGHT", anchor2 or anchor, "BOTTOMRIGHT", -xOffset, yOffset)
end end
local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement) local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement, isNamePlateElement)
GetTemplate(template, isUnitFrameElement) GetTemplate(template, isUnitFrameElement)
frame.template = template or "Default" 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 ignoreUpdates then frame.ignoreUpdates = ignoreUpdates end
if forcePixelMode then frame.forcePixelMode = forcePixelMode end if forcePixelMode then frame.forcePixelMode = forcePixelMode end
if isUnitFrameElement then frame.isUnitFrameElement = isUnitFrameElement end if isUnitFrameElement then frame.isUnitFrameElement = isUnitFrameElement end
frame.isNamePlateElement = isNamePlateElement
local bgFile = glossTex and E.media.glossTex or E.media.blankTex 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({ frame:SetBackdrop({
bgFile = bgFile, bgFile = bgFile,
edgeFile = E.media.blankTex, edgeFile = E.media.blankTex,
@@ -99,7 +115,8 @@ local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelM
frame:SetBackdropColor(backdropr, backdropg, backdropb, backdropa) 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 if not frame.iborder then
local border = CreateFrame("Frame", nil, frame) local border = CreateFrame("Frame", nil, frame)
border:SetInside(frame, E.mult, E.mult) border:SetInside(frame, E.mult, E.mult)
@@ -139,7 +156,7 @@ local function SetTemplate(frame, template, glossTex, ignoreUpdates, forcePixelM
end end
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 if not template then template = "Default" end
local parent = (frame.IsObjectType and frame:IsObjectType("Texture") and frame:GetParent()) or frame 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 not frame.backdrop then frame.backdrop = backdrop end
if frame.forcePixelMode or forcePixelMode then 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 else
backdrop:SetOutside(frame) local border = isNamePlateElement and NP.BORDER or nil
backdrop:SetOutside(frame, border, border)
end end
backdrop:SetTemplate(template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement) backdrop:SetTemplate(template, glossTex, ignoreUpdates, forcePixelMode, isUnitFrameElement, isNamePlateElement)
local frameLevel = parent.GetFrameLevel and parent:GetFrameLevel() local frameLevel = parent.GetFrameLevel and parent:GetFrameLevel()
local frameLevelMinusOne = frameLevel and (frameLevel - 1) local frameLevelMinusOne = frameLevel and (frameLevel - 1)
+1 -1
View File
@@ -1,6 +1,6 @@
## Interface: 30300 ## Interface: 30300
## Author: Elv, Bunny ## Author: Elv, Bunny
## Version: 6.18 ## Version: 7.0
## Title: |cff1784d1E|r|cffe5e3e3lvUI|r ## Title: |cff1784d1E|r|cffe5e3e3lvUI|r
## Notes: User Interface replacement AddOn for World of Warcraft. ## Notes: User Interface replacement AddOn for World of Warcraft.
## SavedVariables: ElvDB, ElvPrivateDB ## SavedVariables: ElvDB, ElvPrivateDB
+1 -1
View File
@@ -346,7 +346,7 @@ function AddOn:ToggleOptionsUI(msg)
if not IsAddOnLoaded("ElvUI_OptionsUI") then noConfig = true end if not IsAddOnLoaded("ElvUI_OptionsUI") then noConfig = true end
-- version check elvui options if it's actually enabled -- 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") self:StaticPopup_Show("CLIENT_UPDATE_REQUEST")
end end
else else
+32
View File
@@ -14,6 +14,10 @@ local hiddenParent = CreateFrame('Frame', nil, UIParent)
hiddenParent:SetAllPoints() hiddenParent:SetAllPoints()
hiddenParent:Hide() hiddenParent:Hide()
local offScreenParent = CreateFrame('Frame', nil, UIParent)
offScreenParent:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", 0, -128)
offScreenParent:SetFrameLevel(0)
local function handleFrame(baseName) local function handleFrame(baseName)
local frame local frame
if(type(baseName) == 'string') then if(type(baseName) == 'string') then
@@ -51,6 +55,34 @@ local function handleFrame(baseName)
end end
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) function oUF:DisableBlizzard(unit)
if(not unit) then return end 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 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 end
for debuffType, color in next, DebuffTypeColor do 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 end
for eclass, color in next, FACTION_BAR_COLORS do 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 end
for power, color in next, PowerBarColor do for power, color in next, PowerBarColor do
@@ -48,10 +48,10 @@ for power, color in next, PowerBarColor do
colors.power[power] = {} colors.power[power] = {}
for index, color in next, color do 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 end
else 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 end
end end
+13
View File
@@ -356,6 +356,13 @@ local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontH
end end
local function UpdateAuras(self, event, unit) 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 if(self.unit ~= unit) then return end
local auras = self.Auras local auras = self.Auras
@@ -502,6 +509,12 @@ local function UpdateAuras(self, event, unit)
end end
local function Update(self, event, unit) 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 if(self.unit ~= unit) then return end
UpdateAuras(self, event, unit) UpdateAuras(self, event, unit)
+89 -23
View File
@@ -103,6 +103,7 @@ local function resetAttributes(self)
self.channeling = nil self.channeling = nil
self.notInterruptible = nil self.notInterruptible = nil
self.spellName = nil -- ElvUI self.spellName = nil -- ElvUI
self.spellID = nil
end end
-- ElvUI block -- ElvUI block
@@ -113,13 +114,19 @@ end
-- end block -- end block
local function CastStart(self, event, unit) 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 if(self.unit ~= unit) then return end
local element = self.Castbar 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' event = 'UNIT_SPELLCAST_START'
if(not name) then 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' event = 'UNIT_SPELLCAST_CHANNEL_START'
end end
@@ -141,6 +148,7 @@ local function CastStart(self, event, unit)
element.notInterruptible = notInterruptible element.notInterruptible = notInterruptible
element.holdTime = 0 element.holdTime = 0
element.castID = castID element.castID = castID
element.spellID = spellID
element.spellName = name -- ElvUI element.spellName = name -- ElvUI
if(element.casting) then if(element.casting) then
@@ -205,6 +213,12 @@ local function CastStart(self, event, unit)
end end
local function CastUpdate(self, event, unit, _, _, castID) 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 if(self.unit ~= unit) then return end
local element = self.Castbar local element = self.Castbar
@@ -258,6 +272,12 @@ local function CastUpdate(self, event, unit, _, _, castID)
end end
local function CastStop(self, event, unit, _, _, castID) 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 if(self.unit ~= unit) then return end
local element = self.Castbar local element = self.Castbar
@@ -287,6 +307,12 @@ local function CastStop(self, event, unit, _, _, castID)
end end
local function CastFail(self, event, unit, _, _, castID) 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 if(self.unit ~= unit) then return end
local element = self.Castbar local element = self.Castbar
@@ -324,6 +350,12 @@ local function CastFail(self, event, unit, _, _, castID)
end end
local function CastInterruptible(self, event, unit) 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 if(self.unit ~= unit) then return end
local element = self.Castbar local element = self.Castbar
@@ -408,22 +440,43 @@ local function ForceUpdate(element)
return Update(element.__owner, 'ForceUpdate', element.__owner.unit) return Update(element.__owner, 'ForceUpdate', element.__owner.unit)
end 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 function Enable(self, unit)
local element = self.Castbar local element = self.Castbar
if(element and unit and not unit:match('%wtarget$')) then if(element and unit and not unit:match('%wtarget$')) then
element.__owner = self element.__owner = self
element.ForceUpdate = ForceUpdate element.ForceUpdate = ForceUpdate
self:RegisterEvent('UNIT_SPELLCAST_START', CastStart) if self.isNamePlate then
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_START', CastStart) local castBar = self.nameplateAnchor.CastBar
self:RegisterEvent('UNIT_SPELLCAST_STOP', CastStop) castBar:SetScript("OnShow", GenerateClosure(NamePlateCastBarOnShow, self))
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', CastStop) castBar:SetScript("OnHide", GenerateClosure(NamePlateCastBarOnHide, self))
self:RegisterEvent('UNIT_SPELLCAST_DELAYED', CastUpdate) castBar:SetScript("OnValueChanged", GenerateClosure(NamePlateCastBarOnValueChanged, self))
self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_UPDATE', CastUpdate) else
self:RegisterEvent('UNIT_SPELLCAST_FAILED', CastFail) self:RegisterEvent('UNIT_SPELLCAST_START', CastStart)
self:RegisterEvent('UNIT_SPELLCAST_INTERRUPTED', CastFail) self:RegisterEvent('UNIT_SPELLCAST_CHANNEL_START', CastStart)
self:RegisterEvent('UNIT_SPELLCAST_INTERRUPTIBLE', CastInterruptible) self:RegisterEvent('UNIT_SPELLCAST_STOP', CastStop)
self:RegisterEvent('UNIT_SPELLCAST_NOT_INTERRUPTIBLE', CastInterruptible) 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 -- ElvUI block
self:RegisterEvent('UNIT_SPELLCAST_SENT', UNIT_SPELLCAST_SENT, true) self:RegisterEvent('UNIT_SPELLCAST_SENT', UNIT_SPELLCAST_SENT, true)
@@ -454,7 +507,7 @@ local function Enable(self, unit)
local safeZone = element.SafeZone local safeZone = element.SafeZone
if(safeZone and safeZone:IsObjectType('Texture') and not safeZone:GetTexture()) then if(safeZone and safeZone:IsObjectType('Texture') and not safeZone:GetTexture()) then
safeZone:SetColorTexture(1, 0, 0) safeZone:SetTexture(1, 0, 0)
end end
element:Hide() element:Hide()
@@ -468,16 +521,23 @@ local function Disable(self)
if(element) then if(element) then
element:Hide() element:Hide()
self:UnregisterEvent('UNIT_SPELLCAST_START', CastStart) if self.isNamePlate then
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_START', CastStart) local castBar = self.nameplateAnchor.CastBar
self:UnregisterEvent('UNIT_SPELLCAST_DELAYED', CastUpdate) castBar:SetScript("OnShow", nil)
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_UPDATE', CastUpdate) castBar:SetScript("OnHide", nil)
self:UnregisterEvent('UNIT_SPELLCAST_STOP', CastStop) castBar:SetScript("OnValueChanged", nil)
self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_STOP', CastStop) else
self:UnregisterEvent('UNIT_SPELLCAST_FAILED', CastFail) self:UnregisterEvent('UNIT_SPELLCAST_START', CastStart)
self:UnregisterEvent('UNIT_SPELLCAST_INTERRUPTED', CastFail) self:UnregisterEvent('UNIT_SPELLCAST_CHANNEL_START', CastStart)
self:UnregisterEvent('UNIT_SPELLCAST_INTERRUPTIBLE', CastInterruptible) self:UnregisterEvent('UNIT_SPELLCAST_DELAYED', CastUpdate)
self:UnregisterEvent('UNIT_SPELLCAST_NOT_INTERRUPTIBLE', CastInterruptible) 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) element:SetScript('OnUpdate', nil)
@@ -501,6 +561,12 @@ end)
oUF:AddElement('Castbar', Update, Enable, Disable) oUF:AddElement('Castbar', Update, Enable, Disable)
function CastingBarFrame_SetUnit(self, unit, showTradeSkills, showShield) 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 if(self.unit ~= unit) then
self.unit = unit self.unit = unit
self.showTradeSkills = showTradeSkills self.showTradeSkills = showTradeSkills
@@ -37,6 +37,12 @@ local UnitHasVehicleUI = UnitHasVehicleUI
local MAX_COMBO_POINTS = MAX_COMBO_POINTS local MAX_COMBO_POINTS = MAX_COMBO_POINTS
local function Update(self, event, unit) 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 if(unit == 'pet') then return end
local element = self.ComboPoints local element = self.ComboPoints
@@ -30,6 +30,12 @@ local GetPetHappiness = GetPetHappiness
local HasPetUI = HasPetUI local HasPetUI = HasPetUI
local function Update(self, event, unit) 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 if(not unit or self.unit ~= unit) then return end
local element = self.HappinessIndicator local element = self.HappinessIndicator
+41 -1
View File
@@ -86,6 +86,12 @@ local oUF = ns.oUF
local Private = oUF.Private local Private = oUF.Private
local function UpdateColor(self, event, unit) 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 if(not unit or self.unit ~= unit) then return end
local element = self.Health local element = self.Health
@@ -146,7 +152,14 @@ local function ColorPath(self, ...)
end end
local function Update(self, event, unit) 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 if(not unit or self.unit ~= unit) then return end
local element = self.Health local element = self.Health
--[[ Callback: Health:PreUpdate(unit) --[[ Callback: Health:PreUpdate(unit)
@@ -200,7 +213,6 @@ local function Path(self, ...)
* unit - the unit accompanying the event (string) * unit - the unit accompanying the event (string)
--]] --]]
(self.Health.Override or Update) (self, ...); (self.Health.Override or Update) (self, ...);
ColorPath(self, ...) ColorPath(self, ...)
end end
@@ -242,6 +254,23 @@ local function SetColorHappiness(element, state)
end end
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) --[[ Health:SetColorTapping(state)
Used to toggle coloring if the unit isn't tapped by the player. 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.__owner = self
element.ForceUpdate = ForceUpdate element.ForceUpdate = ForceUpdate
element.SetColorDisconnected = SetColorDisconnected element.SetColorDisconnected = SetColorDisconnected
element.SetColorSelection = SetColorSelection
element.SetColorHappiness = SetColorHappiness element.SetColorHappiness = SetColorHappiness
element.SetColorTapping = SetColorTapping element.SetColorTapping = SetColorTapping
element.SetColorThreat = SetColorThreat element.SetColorThreat = SetColorThreat
@@ -354,6 +384,16 @@ local function Enable(self, unit)
self:RegisterEvent('UNIT_MAXHEALTH', Path) 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 if(element:IsObjectType('StatusBar') and not element:GetStatusBarTexture()) then
element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]]) element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
end end
@@ -43,6 +43,12 @@ local UnitIsUnit = UnitIsUnit
local UnitIsVisible = UnitIsVisible local UnitIsVisible = UnitIsVisible
local function Update(self, event, unit) 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 if(not unit or not UnitIsUnit(self.unit, unit)) then return end
local element = self.Portrait local element = self.Portrait
+12
View File
@@ -100,6 +100,12 @@ local UnitPowerType = UnitPowerType
local UnitReaction = UnitReaction local UnitReaction = UnitReaction
local function UpdateColor(self, event, unit) 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 if(self.unit ~= unit) then return end
local element = self.Power local element = self.Power
@@ -170,6 +176,12 @@ local function ColorPath(self, ...)
end end
local function Update(self, event, unit) 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 if(self.unit ~= unit) then return end
local element = self.Power local element = self.Power
@@ -17,6 +17,12 @@ local UnitPowerType = UnitPowerType
local UnitReaction = UnitReaction local UnitReaction = UnitReaction
local function UpdateColor(self, event, unit) 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 if(self.unit ~= unit) then return end
local element = self.Energy local element = self.Energy
@@ -84,6 +90,12 @@ local function ColorPath(self, ...)
end end
local function Update(self, event, unit) 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 if(self.unit ~= unit) then return end
local element = self.Energy local element = self.Energy
@@ -17,6 +17,12 @@ local UnitPowerType = UnitPowerType
local UnitReaction = UnitReaction local UnitReaction = UnitReaction
local function UpdateColor(self, event, unit) 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 if(self.unit ~= unit) then return end
local element = self.Rage local element = self.Rage
@@ -84,6 +90,12 @@ local function ColorPath(self, ...)
end end
local function Update(self, event, unit) 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 if(self.unit ~= unit) then return end
local element = self.Rage local element = self.Rage
@@ -33,6 +33,12 @@ local FFA_ICON = [[Interface\TargetingFrame\UI-PVP-FFA]]
local FACTION_ICON = [[Interface\TargetingFrame\UI-PVP-]] local FACTION_ICON = [[Interface\TargetingFrame\UI-PVP-]]
local function Update(self, event, unit) 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 if(unit ~= self.unit) then return end
local element = self.PvPIndicator local element = self.PvPIndicator
@@ -36,7 +36,14 @@ local UnitExists = UnitExists
local UnitThreatSituation = UnitThreatSituation local UnitThreatSituation = UnitThreatSituation
local function Update(self, event, unit) 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 local element = self.ThreatIndicator
--[[ Callback: ThreatIndicator:PreUpdate(unit) --[[ Callback: ThreatIndicator:PreUpdate(unit)
+114 -1
View File
@@ -311,6 +311,10 @@ local function togglemenu(self, unit)
end end
local function onShow(self) 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 if(not updateActiveUnit(self, 'OnShow')) then
return self:UpdateAllElements('OnShow') return self:UpdateAllElements('OnShow')
end 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. 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) Private.UpdateUnits(object, objectUnit)
styleFunc(object, objectUnit, not header) styleFunc(object, objectUnit, not header)
object:HookScript('OnAttributeChanged', onAttributeChanged) object:HookScript('OnAttributeChanged', onAttributeChanged)
@@ -761,6 +764,116 @@ function oUF:Spawn(unit, overrideName)
return object return object
end 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) --[[ oUF:AddElement(name, update, enable, disable)
Used to register an element with oUF. Used to register an element with oUF.
@@ -190,6 +190,12 @@ local function sortByTime(a, b)
end end
local function Update(self, event, unit) 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 if self.unit ~= unit then return end
local element = self.AuraBars local element = self.AuraBars
@@ -258,6 +258,12 @@ end
local found = {} local found = {}
local function Update(self, event, unit) 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 if not unit or self.unit ~= unit then return end
local guid = UnitGUID(unit) 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 return (not element.enabled or not self.cur) or element.ready or not maxV
elseif (updateType == POST) then elseif (updateType == POST) then
local curV, maxV, unit = ... 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 return (not element.enabled or not element.cur) or (not element.ready or not curV or not maxV) or element.unit ~= unit
else else
return false return false
@@ -26,6 +26,12 @@ local function GetDebuffType(unit, filterTable)
end end
local function Update(object, event, unit) 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 if unit ~= object.unit then return end
local debuffType, texture, wasFiltered, style, color = GetDebuffType(unit, object.DebuffHighlightFilterTable) local debuffType, texture, wasFiltered, style, color = GetDebuffType(unit, object.DebuffHighlightFilterTable)
@@ -62,6 +62,12 @@ local function Update(self, _, unit)
end end
unit = unit or self.unit 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 if self.unit ~= unit then return end
-- range fader -- range fader
@@ -129,6 +135,7 @@ local function HoverScript(self)
end end
local function TargetScript(self) 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.Fader and self.Fader.TargetHooked == 1 then
if self:IsShown() then if self:IsShown() then
self.Fader:ForceUpdate() self.Fader:ForceUpdate()
@@ -161,6 +161,12 @@ local function UpdateDebuff(self, name, icon, count, debuffType, duration, endTi
end end
local function Update(self, event, unit) 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 if unit ~= self.unit then return end
local element = self.RaidDebuffs local element = self.RaidDebuffs
@@ -37,6 +37,12 @@ local UnitName = UnitName
local enabledUF, enabled = {} local enabledUF, enabled = {}
local function Update(self, event, unit, succeeded) 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 if not unit or self.unit ~= unit then return end
local element = self.ResurrectIndicator local element = self.ResurrectIndicator
+1 -2
View File
@@ -539,7 +539,6 @@ function AB:StyleButton(button, noBackdrop, useMasque)
if macroText then if macroText then
macroText:ClearAllPoints() macroText:ClearAllPoints()
macroText:SetWidth(self.db.fontWidth)
macroText:Point("BOTTOM", 0, 1) macroText:Point("BOTTOM", 0, 1)
macroText:FontTemplate(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline) macroText:FontTemplate(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
macroText:SetTextColor(color.r, color.g, color.b) macroText:SetTextColor(color.r, color.g, color.b)
@@ -995,4 +994,4 @@ local function InitializeCallback()
AB:Initialize() AB:Initialize()
end end
E:RegisterModule(AB:GetName(), InitializeCallback) E:RegisterModule(AB:GetName(), InitializeCallback)
+1
View File
@@ -17,6 +17,7 @@ local MICRO_BUTTONS = {
"SocialsMicroButton", "SocialsMicroButton",
"PVPMicroButton", "PVPMicroButton",
"LFDMicroButton", "LFDMicroButton",
"ChallengesMicroButton",
"MainMenuMicroButton", "MainMenuMicroButton",
"HelpMicroButton" "HelpMicroButton"
} }
+1 -1
View File
@@ -63,7 +63,7 @@ do
end end
do 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() function M:ToggleInterruptAnnounce()
if E.db.general.interruptAnnounce == "NONE" then 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 E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule("NamePlates") local NP = E:GetModule('NamePlates')
local UF = E:GetModule('UnitFrames')
local LSM = E.Libs.LSM local LSM = E.Libs.LSM
local LAI = E.Libs.LAI
--Lua functions local _G = _G
local select, unpack, pairs = select, unpack, pairs local wipe = wipe
local band = bit.band local unpack = unpack
local tinsert = table.insert
local floor = math.floor
local split = string.split
--WoW API / Variables
local CreateFrame = CreateFrame 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 = { local Buffs = CreateFrame('Frame', frameName..'Buffs', nameplate)
BOTTOMLEFT = "TOP", Buffs:Size(1, 1)
BOTTOMRIGHT = "TOP", Buffs.size = 27
LEFT = "RIGHT", Buffs.num = 4
RIGHT = "LEFT", Buffs.spacing = E.Border * 2
TOPLEFT = "BOTTOM", Buffs.onlyShowPlayer = false
TOPRIGHT = "BOTTOM" Buffs.disableMouse = true
} Buffs.isNamePlate = nameplate
local positionValues2 = { Buffs.initialAnchor = 'BOTTOMLEFT'
BOTTOMLEFT = "BOTTOM", Buffs.growthX = 'RIGHT'
BOTTOMRIGHT = "BOTTOM", Buffs.growthY = 'UP'
LEFT = "LEFT", Buffs.type = 'buffs'
RIGHT = "RIGHT", Buffs.forceShow = nameplate == _G.ElvNP_Test
TOPLEFT = "TOP", Buffs.tickers = {} -- StyleFilters
TOPRIGHT = "TOP" 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 = { Buffs.PreUpdate = UF.PreUpdateAura
["STAR"] = 0x00100000, Buffs.PreSetPosition = UF.SortAuras
["CIRCLE"] = 0x00200000, Buffs.SetPosition = UF.SetPosition
["DIAMOND"] = 0x00400000, Buffs.PostCreateIcon = NP.Construct_AuraIcon
["TRIANGLE"] = 0x00800000, Buffs.PostUpdateIcon = UF.PostUpdateAura
["MOON"] = 0x01000000, Buffs.CustomFilter = UF.AuraFilter
["SQUARE"] = 0x02000000,
["CROSS"] = 0x04000000,
["SKULL"] = 0x08000000
}
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) nameplate.Buffs_, nameplate.Debuffs_ = Buffs, Debuffs
self:UpdateElement_AurasByGUID(destGUID, event) nameplate.Buffs, nameplate.Debuffs = Buffs, Debuffs
end end
function NP:LibAuraInfo_AURA_REMOVED(event, destGUID) function NP:Construct_AuraIcon(button)
self:UpdateElement_AurasByGUID(destGUID, event) if not button then return end
end
function NP:LibAuraInfo_AURA_REFRESH(event, destGUID) button:SetTemplate(nil, nil, nil, nil, nil, true, true)
self:LibAuraInfo_AURA_APPLIED(event, destGUID)
end
function NP:LibAuraInfo_AURA_APPLIED_DOSE(event, destGUID) button.cd:SetReverse(true)
self:LibAuraInfo_AURA_APPLIED(event, destGUID) button.cd:SetInside(button)
end
function NP:LibAuraInfo_AURA_CLEAR(event, destGUID) button.icon:SetDrawLayer('ARTWORK')
self:UpdateElement_AurasByGUID(destGUID, event) button.icon:SetInside()
end
function NP:LibAuraInfo_UNIT_AURA(event, destGUID) button.count:ClearAllPoints()
self:UpdateElement_AurasByGUID(destGUID, event) button.count:Point('BOTTOMRIGHT', 1, 1)
end button.count:SetJustifyH('RIGHT')
function NP:UpdateTime(elapsed) button.overlay:SetTexture()
self.timeLeft = self.timeLeft - elapsed button.stealable:SetTexture()
self:SetValue(self.timeLeft)
button.isNamePlate = true
if self.nextUpdate > 0 then E:RegisterCooldown(button.cd, 'nameplates')
self.nextUpdate = self.nextUpdate - elapsed
return local auras = button:GetParent()
if auras and auras.type then
local db = NP:PlateDB(auras.__owner)
button.db = db[auras.type]
end end
if self.timeLeft < 0 then NP:UpdateAuraSettings(button)
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
end end
local unstableAffliction = GetSpellInfo(30108) function NP:Configure_Auras(nameplate, auras, db)
local vampiricTouch = GetSpellInfo(34914) auras.size = db.size
function NP:SetAura(frame, guid, index, filter, isDebuff, visible) auras.height = not db.keepSizeRatio and db.height
local isAura, name, texture, count, debuffType, duration, expiration, caster, spellID, _ = LAI:GUIDAura(guid, index, filter) 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 local index = 1
spellID = 47540 while auras[index] do
name, _, texture = GetSpellInfo(spellID) local button = auras[index]
if frame.forceShow then if button then
isAura, count, debuffType, duration, expiration = true, 5, "Magic", 0, 0 button.db = db
end NP:UpdateAuraSettings(button)
end button:SetBackdropBorderColor(unpack(E.media.bordercolor))
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)
end 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 index = index + 1
end 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: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 end
function NP:ConstructElement_Auras(frame, auraType) function NP:Update_Auras(nameplate)
local auras = CreateFrame("Frame", "$parent"..auraType, frame) local db = NP:PlateDB(nameplate)
auras:Show()
auras:SetSize(150, 27)
auras:SetPoint("TOP", 0, 22)
auras.anchoredIcons = 0
auras.type = string.lower(auraType)
return auras if db.debuffs.enable or db.buffs.enable then
end if not nameplate:IsElementEnabled('Auras') then
nameplate:EnableElement('Auras')
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
end 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
end end
function NP:AuraFilter(guid, button, name, texture, count, debuffType, duration, expiration, caster, spellID) function NP:UpdateAuraSettings(button)
local parent = button:GetParent() local db = button.db
local parentType = parent.type if db then
local db = NP.db.units[parent:GetParent().UnitType][parentType] local point = db.countPosition or 'CENTER'
if not db then return true end button.count:ClearAllPoints()
button.count:SetJustifyH(point:find('RIGHT') and 'RIGHT' or 'LEFT')
local isPlayer = caster == E.myguid button.count:Point(point, db.countXOffset, db.countYOffset)
button.count:FontTemplate(LSM:Fetch('font', db.countFont), db.countFontSize, db.countFontOutline)
-- 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
end end
return filterCheck if button.auraInfo then
end 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 E, L, V, P, G = unpack(ElvUI)
local NP = E:GetModule("NamePlates") local NP = E:GetModule('NamePlates')
local UF = E:GetModule('UnitFrames')
local CH = E:GetModule('Chat')
local LSM = E.Libs.LSM local LSM = E.Libs.LSM
--Lua functions local _G = _G
local abs = abs
local next = next
local unpack = unpack local unpack = unpack
local abs = math.abs local strjoin = strjoin
--WoW API / Variables local strmatch = strmatch
local CreateFrame = CreateFrame local CreateFrame = CreateFrame
local GetTime = GetTime local UnitCanAttack = UnitCanAttack
local UnitCastingInfo = UnitCastingInfo local UnitName = UnitName
local UnitChannelInfo = UnitChannelInfo
local FAILED = FAILED
local INTERRUPTED = INTERRUPTED local INTERRUPTED = INTERRUPTED
local function resetAttributes(self) function NP:Castbar_CheckInterrupt(unit)
self.casting = nil if unit == 'vehicle' then
self.channeling = nil unit = 'player'
self.notInterruptible = nil end
self.spellName = nil
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 end
function NP:Update_CastBarOnUpdate(elapsed) function NP:Castbar_CustomDelayText(duration)
if self.casting or self.channeling then if self.channeling then
local isCasting = self.casting if self.channelTimeFormat == 'CURRENT' then
if isCasting then self.Time:SetFormattedText('%.1f |cffaf5050%.1f|r', abs(duration - self.max), self.delay)
self.value = self.value + elapsed elseif self.channelTimeFormat == 'CURRENTMAX' then
if self.value >= self.max then self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%.1f|r', duration, self.max, self.delay)
resetAttributes(self) elseif self.channelTimeFormat == 'REMAINING' then
self:Hide() self.Time:SetFormattedText('%.1f |cffaf5050%.1f|r', duration, self.delay)
NP:StyleFilterUpdate(self:GetParent(), "FAKE_Casting") elseif self.channelTimeFormat == 'REMAININGMAX' then
return self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%.1f|r', abs(duration - self.max), self.max, self.delay)
end
else
self.value = self.value - elapsed
if self.value <= 0 then
resetAttributes(self)
self:Hide()
NP:StyleFilterUpdate(self:GetParent(), "FAKE_Casting")
return
end
end 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 function NP:Castbar_CustomTimeText(duration)
if self.channeling then if self.channeling then
if self.channelTimeFormat == "CURRENT" then if self.channelTimeFormat == 'CURRENT' then
self.Time:SetFormattedText("%.1f |cffaf5050%.2f|r", abs(self.value - self.max), self.delay) self.Time:SetFormattedText('%.1f', abs(duration - self.max))
elseif self.channelTimeFormat == "CURRENTMAX" then elseif self.channelTimeFormat == 'CURRENTMAX' then
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%.2f|r", abs(self.value - self.max), self.max, self.delay) self.Time:SetFormattedText('%.1f / %.1f', abs(duration - self.max), self.max)
elseif self.channelTimeFormat == "REMAINING" then elseif self.channelTimeFormat == 'REMAINING' then
self.Time:SetFormattedText("%.1f |cffaf5050%.2f|r", self.value, self.delay) self.Time:SetFormattedText('%.1f', duration)
elseif self.channelTimeFormat == "REMAININGMAX" then elseif self.channelTimeFormat == 'REMAININGMAX' then
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%.2f|r", self.value, self.max, self.max, self.delay) 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 end
else elseif frameType == 'ENEMY_NPC' or frameType == 'FRIENDLY_NPC' then
if self.castTimeFormat == "CURRENT" then local target = self.curTarget or UnitName(unit..'target')
self.Time:SetFormattedText("%.1f |cffaf5050%s %.2f|r", self.value, "+", self.delay) if target and target ~= '' and target ~= plate.unitName then
elseif self.castTimeFormat == "CURRENTMAX" then self.Text:SetText(self.spellName..' > '..target)
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)
end end
end end
end end
NP:StyleFilterUpdate(plate, 'FAKE_Cast')
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")
end end
end end
function NP:Update_CastBar(frame, event, unit) function NP:Castbar_PostCastFail()
local castBar = frame.CastBar NP:StyleFilterUpdate(self.__owner, 'FAKE_Cast')
if unit then self:SetStatusBarColor(NP.db.colors.castInterruptedColor.r, NP.db.colors.castInterruptedColor.g, NP.db.colors.castInterruptedColor.b)
if not event then end
if UnitChannelInfo(unit) then
event = "UNIT_SPELLCAST_CHANNEL_START" function NP:Castbar_PostCastInterruptible(unit)
elseif UnitCastingInfo(unit) then self:CheckInterrupt(unit)
event = "UNIT_SPELLCAST_START" end
end
end function NP:Castbar_PostCastStop()
elseif castBar:IsShown() then NP:StyleFilterUpdate(self.__owner, 'FAKE_Cast')
resetAttributes(castBar) end
castBar:Hide()
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 end
if self.db.units[frame.UnitType].castbar.enable ~= true then return end return castbar
if self.db.units[frame.UnitType].health.enable ~= true and not (frame.isTarget and self.db.alwaysShowTargetHealth) then return end --Bug end
if event == "UNIT_SPELLCAST_START" or event == "UNIT_SPELLCAST_CHANNEL_START" then function NP:CASTBAR_COMBAT_LOG_EVENT_UNFILTERED(event, sourceGUID, sourceName, targetGUID)
local name, _, _, texture, startTime, endTime, _, _, notInterruptible = UnitCastingInfo(unit) if (event == 'SPELL_INTERRUPT' or event == 'SPELL_PERIODIC_INTERRUPT') and targetGUID and (sourceName and sourceName ~= '') then
event = "UNIT_SPELLCAST_START" local plate, classColor = NP.PlateGUID[targetGUID]
if not name then if plate and plate.Castbar then
name, _, _, texture, startTime, endTime, _, notInterruptible = UnitChannelInfo(unit) local db = NP:PlateDB(plate)
event = "UNIT_SPELLCAST_CHANNEL_START" 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 end
if not name then castbar.timeToHold = db.timeToHold
resetAttributes(castBar) castbar.castTimeFormat = db.castTimeFormat
castBar:Hide() castbar.channelTimeFormat = db.channelTimeFormat
return
end
endTime = endTime / 1000 castbar:Size(db.width, db.height)
startTime = startTime / 1000 castbar:Point('CENTER', nameplate, 'CENTER', db.xOffset, db.yOffset)
castBar.max = endTime - startTime if db.showIcon then
castBar.startTime = startTime castbar.Button:ClearAllPoints()
castBar.delay = 0 castbar.Button:Point(db.iconPosition == 'RIGHT' and 'BOTTOMLEFT' or 'BOTTOMRIGHT', castbar, db.iconPosition == 'RIGHT' and 'BOTTOMRIGHT' or 'BOTTOMLEFT', db.iconOffsetX, db.iconOffsetY)
castBar.casting = event == "UNIT_SPELLCAST_START" castbar.Button:Size(db.iconSize, db.iconSize)
castBar.channeling = event == "UNIT_SPELLCAST_CHANNEL_START" castbar.Button:Show()
castBar.notInterruptible = notInterruptible
castBar.holdTime = 0
castBar.interrupted = nil
castBar.spellName = name
if castBar.casting then
castBar.value = GetTime() - startTime
else else
castBar.value = endTime - GetTime() castbar.Button:Hide()
end end
castBar:SetMinMaxValues(0, castBar.max) castbar.Time:ClearAllPoints()
castBar:SetValue(castBar.value) castbar.Text:ClearAllPoints()
castBar.Icon.texture:SetTexture(texture) if db.textPosition == 'BELOW' then
castBar.Spark:Show() castbar.Time:Point('TOPRIGHT', castbar, 'BOTTOMRIGHT', db.timeXOffset, db.timeYOffset)
castBar.Name:SetText(name) castbar.Text:Point('TOPLEFT', castbar, 'BOTTOMLEFT', db.textXOffset, db.textYOffset)
castBar.Time:SetText() elseif db.textPosition == 'ABOVE' then
castbar.Time:Point('BOTTOMRIGHT', castbar, 'TOPRIGHT', db.timeXOffset, db.timeYOffset)
castBar:Show() castbar.Text:Point('BOTTOMLEFT', castbar, 'TOPLEFT', db.textXOffset, db.textYOffset)
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)
else else
castBar:SetStatusBarColor(self.db.colors.castColor.r, self.db.colors.castColor.g, self.db.colors.castColor.b) castbar.Time:Point('RIGHT', castbar, 'RIGHT', db.timeXOffset, db.timeYOffset)
end castbar.Text:Point('LEFT', castbar, 'LEFT', db.textXOffset, db.textYOffset)
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()
end end
castBar.scale.width:SetChange(db.width * scale) if db.hideTime then
castBar.scale.height:SetChange(db.height * scale) castbar.Time:Hide()
castBar.scale:Play() 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) if db.hideSpellName then
castBar.Icon.scale.height:SetChange(db.iconSize * scale) castbar.Text:Hide()
castBar.Icon.scale:Play() 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
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/"> <Ui xmlns='http://www.blizzard.com/wow/ui/'>
<Script file="Nameplates.lua"/> <Script file='Nameplates.lua'/>
<Script file="StyleFilter.lua"/> <Script file='StyleFilter.lua'/>
<Script file="Elements\Auras.lua"/> <Script file='Elements\Auras.lua'/>
<Script file="Elements\CastBar.lua"/> <Script file='Elements\BossMods.lua'/>
<Script file="Elements\ComboPoints.lua"/> <Script file='Elements\CastBar.lua'/>
<Script file="Elements\Glow.lua"/> <Script file='Elements\ClassPower.lua'/>
<Script file="Elements\HealthBar.lua"/> <Script file='Elements\Health.lua'/>
<Script file="Elements\CutawayHealth.lua"/> <Script file='Elements\Plugins.lua'/>
<Script file="Elements\Level.lua"/> <Script file='Elements\Power.lua'/>
<Script file="Elements\Name.lua"/> <Script file='Elements\Portraits.lua'/>
<Script file="Elements\RaidIcon.lua"/> <Script file='Elements\PvP.lua'/>
<Script file="Elements\HealerIcon.lua"/> <Script file='Elements\RaidTargetIndicator.lua'/>
<Script file="Elements\Elite.lua"/> <Script file='Elements\Tags.lua'/>
<Script file="Elements\Highlight.lua"/> <Script file='Elements\Threat.lua'/>
<Script file="Elements\IconFrame.lua"/> <Script file='Plugins\ClassificationIndicator.lua'/>
</Ui> <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", "InterfaceOptionsCombatPanelTargetOfTarget",
"InterfaceOptionsCombatPanelEnemyCastBarsOnPortrait", "InterfaceOptionsCombatPanelEnemyCastBarsOnPortrait",
"InterfaceOptionsCombatPanelEnemyCastBarsOnNameplates", "InterfaceOptionsCombatPanelEnemyCastBarsOnNameplates",
"InterfaceOptionsCombatPanelAoEIndicatorsSelf",
"InterfaceOptionsCombatPanelAoEIndicatorsEnemies",
"InterfaceOptionsCombatPanelAoEIndicatorsFriendly",
"InterfaceOptionsDisplayPanelShowCloak", "InterfaceOptionsDisplayPanelShowCloak",
"InterfaceOptionsDisplayPanelShowHelm", "InterfaceOptionsDisplayPanelShowHelm",
"InterfaceOptionsDisplayPanelShowAggroPercentage", "InterfaceOptionsDisplayPanelShowAggroPercentage",
@@ -257,7 +260,11 @@ S:AddCallback("Skin_BlizzardOptions", function()
"InterfaceOptionsAscensionLoseControlPanelEnableSlow", "InterfaceOptionsAscensionLoseControlPanelEnableSlow",
"InterfaceOptionsAscensionLoseControlPanelEnableStun", "InterfaceOptionsAscensionLoseControlPanelEnableStun",
"InterfaceOptionsAscensionLoseControlPanelEnablePacify", "InterfaceOptionsAscensionLoseControlPanelEnablePacify",
"InterfaceOptionsDraftPanelAutoPopupDraft",
"InterfaceOptionsDraftPanelAutoRevealDraft",
"InterfaceOptionsDraftPanelSkipDraftConfirmation",
"InterfaceOptionsDraftPanelSkipDraftSacrificeConfirmation",
"InterfaceOptionsDraftPanelShowBuildDraftSpellCards",
"AudioOptionsSoundPanelEnableSound", "AudioOptionsSoundPanelEnableSound",
"AudioOptionsSoundPanelSoundEffects", "AudioOptionsSoundPanelSoundEffects",
@@ -306,7 +313,9 @@ S:AddCallback("Skin_BlizzardOptions", function()
"InterfaceOptionsCombatPanelSpellActivationOverlayAlpha", "InterfaceOptionsCombatPanelSpellActivationOverlayAlpha",
"InterfaceOptionsMousePanelMouseLookSpeedSlider", "InterfaceOptionsMousePanelMouseLookSpeedSlider",
"InterfaceOptionsMousePanelMouseSensitivitySlider", "InterfaceOptionsMousePanelMouseSensitivitySlider",
"InterfaceOptionsCombatPanelNameplateDistance",
"InterfaceOptionsCombatPanelNameplateZ",
"AudioOptionsSoundPanelSoundQuality", "AudioOptionsSoundPanelSoundQuality",
"AudioOptionsSoundPanelSoundChannels", "AudioOptionsSoundPanelSoundChannels",
"AudioOptionsSoundPanelMasterVolume", "AudioOptionsSoundPanelMasterVolume",
-1
View File
@@ -21,7 +21,6 @@ S:AddCallback("Skin_LFD", function()
AscensionLFGFrameContent:StripTextures(true) AscensionLFGFrameContent:StripTextures(true)
AscensionLFGFrameMenu:StripTextures(true) AscensionLFGFrameMenu:StripTextures(true)
AscensionLFGFrameInset:StripTextures(true) AscensionLFGFrameInset:StripTextures(true)
AscensionLFGFrameInset:CreateBackdrop("Transparent")
AscensionLFGFrameInsetNineSlice:StripTextures(true) AscensionLFGFrameInsetNineSlice:StripTextures(true)
AscensionLFGFrameNineSlice:StripTextures(true) AscensionLFGFrameNineSlice:StripTextures(true)
AscensionLFGFrameMenuNineSlice:StripTextures(true) AscensionLFGFrameMenuNineSlice:StripTextures(true)
+21 -39
View File
@@ -77,47 +77,29 @@ local function createConfigEnv()
__newindex = function(_, key, value) _G[key] = value end, __newindex = function(_, key, value) _G[key] = value end,
}) })
overrideFuncs["namecolor"] = ElvUF.Tags.Methods["namecolor"] overrideFuncs['classcolor'] = ElvUF.Tags.Methods['classcolor']
overrideFuncs["name:veryshort"] = ElvUF.Tags.Methods["name:veryshort"] overrideFuncs['name:veryshort'] = ElvUF.Tags.Methods['name:veryshort']
overrideFuncs["name:short"] = ElvUF.Tags.Methods["name:short"] overrideFuncs['name:short'] = ElvUF.Tags.Methods['name:short']
overrideFuncs["name:medium"] = ElvUF.Tags.Methods["name:medium"] overrideFuncs['name:medium'] = ElvUF.Tags.Methods['name:medium']
overrideFuncs["name:long"] = ElvUF.Tags.Methods["name:long"] overrideFuncs['name:long'] = ElvUF.Tags.Methods['name:long']
overrideFuncs["healthcolor"] = ElvUF.Tags.Methods["healthcolor"] overrideFuncs['healthcolor'] = ElvUF.Tags.Methods['healthcolor']
overrideFuncs["health:current"] = ElvUF.Tags.Methods["health:current"] overrideFuncs['health:current'] = ElvUF.Tags.Methods['health:current']
overrideFuncs["health:deficit"] = ElvUF.Tags.Methods["health:deficit"] overrideFuncs['health:deficit'] = ElvUF.Tags.Methods['health:deficit']
overrideFuncs["health:current-percent"] = ElvUF.Tags.Methods["health:current-percent"] overrideFuncs['health:current-percent'] = ElvUF.Tags.Methods['health:current-percent']
overrideFuncs["health:current-max"] = ElvUF.Tags.Methods["health:current-max"] overrideFuncs['health:current-max'] = ElvUF.Tags.Methods['health:current-max']
overrideFuncs["health:current-max-percent"] = ElvUF.Tags.Methods["health:current-max-percent"] overrideFuncs['health:current-max-percent'] = ElvUF.Tags.Methods['health:current-max-percent']
overrideFuncs["health:max"] = ElvUF.Tags.Methods["health:max"] overrideFuncs['health:max'] = ElvUF.Tags.Methods['health:max']
overrideFuncs["health:percent"] = ElvUF.Tags.Methods["health:percent"] overrideFuncs['health:percent'] = ElvUF.Tags.Methods['health:percent']
overrideFuncs["powercolor"] = ElvUF.Tags.Methods["powercolor"] overrideFuncs['powercolor'] = ElvUF.Tags.Methods['powercolor']
overrideFuncs["power:current"] = ElvUF.Tags.Methods["power:current"] overrideFuncs['power:current'] = ElvUF.Tags.Methods['power:current']
overrideFuncs["power:deficit"] = ElvUF.Tags.Methods["power:deficit"] overrideFuncs['power:deficit'] = ElvUF.Tags.Methods['power:deficit']
overrideFuncs["power:current-percent"] = ElvUF.Tags.Methods["power:current-percent"] overrideFuncs['power:current-percent'] = ElvUF.Tags.Methods['power:current-percent']
overrideFuncs["power:current-max"] = ElvUF.Tags.Methods["power:current-max"] overrideFuncs['power:current-max'] = ElvUF.Tags.Methods['power:current-max']
overrideFuncs["power:current-max-percent"] = ElvUF.Tags.Methods["power:current-max-percent"] overrideFuncs['power:current-max-percent'] = ElvUF.Tags.Methods['power:current-max-percent']
overrideFuncs["power:max"] = ElvUF.Tags.Methods["power:max"] overrideFuncs['power:max'] = ElvUF.Tags.Methods['power:max']
overrideFuncs["power:percent"] = ElvUF.Tags.Methods["power:percent"] 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"]
end end
function UF:ForceShow(frame) function UF:ForceShow(frame)
@@ -173,6 +173,33 @@ function UF.SortAuraBarName(a, b)
return a.name > b.name return a.name > b.name
end 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, ...) function UF:CheckFilter(name, caster, spellID, isFriend, isPlayer, isUnit, allowDuration, noDuration, canDispell, ...)
for i = 1, select("#", ...) do for i = 1, select("#", ...) do
local filterName = select(i, ...) 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 E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local UF = E:GetModule("UnitFrames") local UF = E:GetModule("UnitFrames")
local NP = E:GetModule('NamePlates')
local LSM = E.Libs.LSM local LSM = E.Libs.LSM
--Lua functions --Lua functions
@@ -16,6 +17,58 @@ local UnitCanAttack = UnitCanAttack
local UnitIsFriend = UnitIsFriend local UnitIsFriend = UnitIsFriend
local UnitIsUnit = UnitIsUnit 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) function UF:Construct_Buffs(frame)
local buffs = CreateFrame("Frame", frame:GetName().."Buffs", frame) local buffs = CreateFrame("Frame", frame:GetName().."Buffs", frame)
buffs.spacing = E.Spacing buffs.spacing = E.Spacing
@@ -134,6 +187,48 @@ function UF:UpdateAuraCooldownPosition(button)
button.needsUpdateCooldownPosition = nil button.needsUpdateCooldownPosition = nil
end 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) function UF:Configure_Auras(frame, auraType)
if not frame.VARIABLES_SET then return end if not frame.VARIABLES_SET then return end
@@ -382,6 +477,31 @@ function UF:PostUpdateAura(unit, button)
end end
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) 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 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 if frame.Power then
local powerTexture = frame.Power:GetStatusBarTexture() 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("TOPLEFT", powerTexture, "TOPRIGHT")
cutawayPower:SetPoint("BOTTOMLEFT", powerTexture, "BOTTOMRIGHT") cutawayPower:SetPoint("BOTTOMLEFT", powerTexture, "BOTTOMRIGHT")
cutawayPower:SetTexture(E.media.blankTex) cutawayPower:SetTexture(E.media.blankTex)
@@ -18,7 +18,7 @@ function UF:Construct_Cutaway(frame)
end end
local healthTexture = frame.Health:GetStatusBarTexture() 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("TOPLEFT", healthTexture, "TOPRIGHT")
cutawayHealth:SetPoint("BOTTOMLEFT", healthTexture, "BOTTOMRIGHT") cutawayHealth:SetPoint("BOTTOMLEFT", healthTexture, "BOTTOMRIGHT")
cutawayHealth:SetTexture(E.media.blankTex) cutawayHealth:SetTexture(E.media.blankTex)
@@ -65,6 +65,12 @@ function UF:Configure_Happiness(frame)
end end
function UF:HappinessOverride(event, unit) 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 if not unit or self.unit ~= unit then return end
local db = self.db local db = self.db
@@ -60,7 +60,7 @@ function UF:Configure_Energy(frame)
local energy = frame.Energy local energy = frame.Energy
energy.origParent = frame energy.origParent = frame
if frame.USE_ENERGYBAR then if frame.USE_ENERGYBAR and C_Player:IsHero() then
if not frame:IsElementEnabled("Energy") then if not frame:IsElementEnabled("Energy") then
frame:EnableElement("Energy") frame:EnableElement("Energy")
energy:Show() energy:Show()
@@ -60,7 +60,7 @@ function UF:Configure_Rage(frame)
local rage = frame.Rage local rage = frame.Rage
rage.origParent = frame rage.origParent = frame
if frame.USE_RAGEBAR then if frame.USE_RAGEBAR and C_Player:IsHero() then
if not frame:IsElementEnabled("Rage") then if not frame:IsElementEnabled("Rage") then
frame:EnableElement("Rage") frame:EnableElement("Rage")
rage:Show() rage:Show()
@@ -30,6 +30,12 @@ function UF:Configure_PVPIcon(frame)
end end
function UF:UpdateOverridePvP(event, unit) 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 if not unit or self.unit ~= unit then return end
local element = self.PvPIndicator local element = self.PvPIndicator
+6 -1
View File
@@ -95,7 +95,12 @@ end
function UF:UpdateThreat(unit, status, r, g, b) function UF:UpdateThreat(unit, status, r, g, b)
local parent = self:GetParent() 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 if (parent.unit ~= unit) or not unit then return end
local db = parent.db local db = parent.db
+15
View File
@@ -461,6 +461,21 @@ function UF:Configure_Fader(frame)
end end
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) function UF:Configure_FontString(obj)
UF.fontstrings[obj] = true UF.fontstrings[obj] = true
obj:FontTemplate() --This is temporary. 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 local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
G.nameplates.filters = { G.nameplates.filters = {
ElvUI_Boss = { ["Non-Target Alpha"] = {
actions = {
alpha = 40,
},
triggers = {
requireTarget = true,
notTarget = true,
enable = true,
},
},
["Enlarge Boss Nameplates"] = {
triggers = { triggers = {
level = true, level = true,
curlevel = -1, curlevel = -1,
nameplateType = { nameplateType = {
enable = true, enable = true,
enemyNPC = true enemyNPC = true
} },
enable = true,
}, },
actions = { actions = {
scale = 1.15 scale = 1.15
} }
}, },
ElvUI_Totem = {
triggers = {
totems = {
enable = true
}
},
actions = {
iconOnly = true
}
}
} }
E.StyleFilterDefaults = { E.StyleFilterDefaults = {
triggers = { triggers = {
priority = 1, priority = 1,
targetMe = false,
isTarget = false, isTarget = false,
notTarget = false, notTarget = false,
requireTarget = false,
noTarget = false,
level = 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 = { casting = {
isCasting = false, isCasting = false,
isChanneling = false, isChanneling = false,
@@ -51,6 +64,25 @@ E.StyleFilterDefaults = {
healer = false, healer = false,
damager = 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 = { raidTarget = {
star = false, star = false,
circle = false, circle = false,
@@ -61,6 +93,16 @@ E.StyleFilterDefaults = {
cross = false, cross = false,
skull = false skull = false
}, },
threat = {
enable = false,
good = false,
goodTransition = false,
badTransition = false,
bad = false,
offTank = false,
offTankGoodTransition = false,
offTankBadTransition = false
},
curlevel = 0, curlevel = 0,
maxlevel = 0, maxlevel = 0,
minlevel = 0, minlevel = 0,
@@ -69,103 +111,207 @@ E.StyleFilterDefaults = {
underHealthThreshold = 0, underHealthThreshold = 0,
overHealthThreshold = 0, overHealthThreshold = 0,
powerThreshold = false, powerThreshold = false,
powerUsePlayer = false,
underPowerThreshold = 0, underPowerThreshold = 0,
overPowerThreshold = 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 = { nameplateType = {
enable = false, enable = false,
friendlyPlayer = false, friendlyPlayer = false,
friendlyNPC = false, friendlyNPC = false,
enemyPlayer = false, enemyPlayer = false,
enemyNPC = false enemyNPC = false,
player = false
}, },
reactionType = { reactionType = {
enabled = false, enabled = false,
reputation = false,
hated = false,
hostile = false, hostile = false,
unfriendly = false,
neutral = false, neutral = false,
friendly = false friendly = false,
honored = false,
revered = false,
exalted = false
}, },
instanceType = { instanceType = {
none = false, none = false,
sanctuary = false, scenario = false,
party = false, party = false,
raid = false, raid = false,
arena = false, arena = false,
pvp = 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 = { instanceDifficulty = {
dungeon = { dungeon = {
normal = false, normal = false,
heroic = false heroic = false,
mythic = false,
}, },
raid = { raid = {
normal = false, normal = false,
heroic = false heroic = false,
mythic = false,
ascended = false,
} }
}, },
cooldowns = { cooldowns = {
names = {}, mustHaveAll = false,
mustHaveAll = false names = {}
}, },
buffs = { buffs = {
mustHaveAll = false, mustHaveAll = false,
missing = false, missing = false,
names = {},
minTimeLeft = 0, minTimeLeft = 0,
maxTimeLeft = 0 maxTimeLeft = 0,
hasStealable = false,
hasNoStealable = false,
onMe = false,
onPet = false,
fromMe = false,
fromPet = false,
names = {}
}, },
debuffs = { debuffs = {
mustHaveAll = false, mustHaveAll = false,
missing = false, missing = false,
names = {},
minTimeLeft = 0, minTimeLeft = 0,
maxTimeLeft = 0 maxTimeLeft = 0,
hasDispellable = false,
hasNoDispellable = false,
onMe = false,
onPet = false,
fromMe = false,
fromPet = false,
names = {}
}, },
totems = { bossMods = {
enable = false, hasAura = false,
a1 = true, a2 = true, a3 = true, a4 = true, a5 = true, missingAura = false,
e1 = true, e2 = true, e3 = true, e4 = true, e5 = true, e6 = true, missingAuras = false,
f1 = true, f2 = true, f3 = true, f4 = true, f5 = true, f6 = true, auras = {}
w1 = true, w2 = true, w3 = true, w4 = true, w5 = true,
o1 = true
},
uniqueUnits = {
enable = false,
u1 = true, u2 = true
}, },
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, inCombat = false,
outOfCombat = false outOfCombat = false,
inCombatUnit = false,
outOfCombatUnit = false,
-- vehicle
inVehicle = false,
outOfVehicle = false,
inVehicleUnit = false,
outOfVehicleUnit = false
}, },
actions = { actions = {
color = { color = {
health = false, health = false,
power = false,
border = false, border = false,
name = false, healthClass = false,
healthColor = {r = 1, g = 1, b = 1, a = 1}, healthColor = {r = 1, g = 1, b = 1, a = 1},
borderColor = {r = 1, g = 1, b = 1, a = 1}, powerClass = false,
nameColor = {r = 1, g = 1, b = 1, a = 1} powerColor = {r = 1, g = 1, b = 1, a = 1},
borderClass = false,
borderColor = {r = 1, g = 1, b = 1, a = 1}
}, },
texture = { texture = {
enable = false, enable = false,
texture = "ElvUI Norm" texture = 'ElvUI Norm'
}, },
flash = { flash = {
enable = false, enable = false,
class = false,
color = {r = 1, g = 1, b = 1, a = 1}, color = {r = 1, g = 1, b = 1, a = 1},
speed = 4 speed = 4
}, },
tags = {
name = '',
level = '',
title = '',
health = '',
power = ''
},
hide = false, hide = false,
usePortrait = false,
nameOnly = false, nameOnly = false,
icon = false, scale = 1,
iconOnly = false,
scale = 1.0,
alpha = -1 alpha = -1
} }
} }
G.nameplates.specialFilters = { G.nameplates.specialFilters = {
Personal = true,
nonPersonal = true,
blockNonPersonal = true,
blockNoDuration = true blockNoDuration = true
} }
+497 -635
View File
File diff suppressed because it is too large Load Diff
@@ -33,7 +33,7 @@ S:AddCallbackForAddon("GnomishVendorShrinker", "GnomishVendorShrinker", function
if not GVS then return end if not GVS then return end
GVS:Size(304, 294) GVS:Size(304, 294)
GVS:Point("TOPLEFT", 19, -44) GVS:Point("TOPLEFT", 19, -54)
GVS:SetTemplate("Transparent") GVS:SetTemplate("Transparent")
MerchantBuyBackItem:ClearAllPoints() MerchantBuyBackItem:ClearAllPoints()
@@ -84,7 +84,7 @@ S:AddCallbackForAddon("GnomishVendorShrinker", "GnomishVendorShrinker", function
end end
child:Height(18) child:Height(18)
child:Point("TOPLEFT", GVS, "BOTTOMLEFT", 1, -3) child:Point("TOPLEFT", GVS, "BOTTOMLEFT", 1, -61)
S:HandleEditBox(child) S:HandleEditBox(child)
elseif objType == "Slider" then elseif objType == "Slider" then
for _, child2 in ipairs({child:GetChildren()}) do for _, child2 in ipairs({child:GetChildren()}) do
@@ -112,8 +112,4 @@ S:AddCallbackForAddon("GnomishVendorShrinker", "GnomishVendorShrinker", function
S:HandleScrollBar(child) S:HandleScrollBar(child)
end end
end end
MerchantBuyBackItem:ClearAllPoints() end)
MerchantBuyBackItem:Point("TOPLEFT", MerchantItem10, "BOTTOMLEFT", 0, -24)
MerchantBuyBackItemItemButton:ClearAllPoints()
MerchantBuyBackItemItemButton:Point("TOPLEFT", MerchantBuyBackItem, "TOPLEFT", 4, -4)
end)
@@ -2860,6 +2860,13 @@ do -- CharacterFrame
E.private.enhanced.character.player.orderName2 = E.private.enhanced.character.player.orderName E.private.enhanced.character.player.orderName2 = E.private.enhanced.character.player.orderName
E.private.enhanced.character.player.collapsedName2 = table.copy(E.private.enhanced.character.player.collapsedName) E.private.enhanced.character.player.collapsedName2 = table.copy(E.private.enhanced.character.player.collapsedName)
end end
if C_Player:IsDefaultClass() then
-- default class has no primary stat
PAPERDOLL_STATCATEGORIES["PRIMARY_STAT"] = nil
PAPERDOLL_STATINFO["PRIMARY_STAT"] = nil
table.RemoveItem(PAPERDOLL_STATCATEGORY_DEFAULTORDER, "PRIMARY_STAT")
end
local activeSpec = GetActiveTalentGroup() local activeSpec = GetActiveTalentGroup()
if activeSpec == 1 then if activeSpec == 1 then
+6 -14
View File
@@ -244,15 +244,8 @@ local function BuildABConfig()
desc = L["Set the font outline."], desc = L["Set the font outline."],
values = C.Values.FontFlags values = C.Values.FontFlags
}, },
fontWidth = {
order = 4,
type = "range",
name = "Font Width",
min = 5, max = 150, step = 1,
softMax = 60, softMin = 15
},
fontColor = { fontColor = {
order = 5, order = 4,
type = "color", type = "color",
name = L["COLOR"], name = L["COLOR"],
width = "full", width = "full",
@@ -268,7 +261,7 @@ local function BuildABConfig()
end end
}, },
textPosition = { textPosition = {
order = 6, order = 5,
type = "group", type = "group",
name = L["Text Position"], name = L["Text Position"],
guiInline = true, guiInline = true,
@@ -785,11 +778,11 @@ local function BuildABConfig()
disabled = function() return not E.db.actionbar.microbar.enabled end disabled = function() return not E.db.actionbar.microbar.enabled end
}, },
buttonsPerRow = { buttonsPerRow = {
order = 8, order = 11,
type = "range", type = "range",
name = L["Buttons Per Row"], name = L["Buttons Per Row"],
desc = L["The amount of buttons to display per row."], desc = L["The amount of buttons to display per row."],
min = 1, max = 10, step = 1, min = 1, max = 11, step = 1,
disabled = function() return not E.db.actionbar.microbar.enabled end disabled = function() return not E.db.actionbar.microbar.enabled end
}, },
alpha = { alpha = {
@@ -914,8 +907,7 @@ local function BuildABConfig()
type = "range", type = "range",
name = L["Button Size"], name = L["Button Size"],
desc = L["The size of the action buttons."], desc = L["The size of the action buttons."],
min = 15, softMax = 60, max = 150, step = 1, min = 15, max = 60, step = 1,
disabled = function() return not E.db.actionbar["bar"..i].enabled end disabled = function() return not E.db.actionbar["bar"..i].enabled end
}, },
buttonspacing = { buttonspacing = {
@@ -1138,4 +1130,4 @@ E.Options.args.actionbar = {
} }
} }
group = E.Options.args.actionbar.args group = E.Options.args.actionbar.args
BuildABConfig() BuildABConfig()
+1
View File
@@ -22,6 +22,7 @@ E:AddLib("AceConfig", "AceConfig-3.0-ElvUI")
E:AddLib("AceConfigDialog", "AceConfigDialog-3.0-ElvUI") E:AddLib("AceConfigDialog", "AceConfigDialog-3.0-ElvUI")
E:AddLib("AceConfigRegistry", "AceConfigRegistry-3.0-ElvUI") E:AddLib("AceConfigRegistry", "AceConfigRegistry-3.0-ElvUI")
E:AddLib("AceDBOptions", "AceDBOptions-3.0") E:AddLib("AceDBOptions", "AceDBOptions-3.0")
E:AddLib('ACH', 'LibAceConfigHelper')
local UnitName = UnitName local UnitName = UnitName
local UnitExists = UnitExists local UnitExists = UnitExists
+2 -1
View File
@@ -1,6 +1,6 @@
## Interface: 30300 ## Interface: 30300
## Author: Elv, Bunny ## Author: Elv, Bunny
## Version: 1.06 ## Version: 1.10
## Title: |cff1784d1E|r|cffe5e3e3lvUI|r |cff1784d1O|r|cffe5e3e3ptionsUI|r ## Title: |cff1784d1E|r|cffe5e3e3lvUI|r |cff1784d1O|r|cffe5e3e3ptionsUI|r
## Notes: Options for ElvUI. ## Notes: Options for ElvUI.
## RequiredDeps: ElvUI ## RequiredDeps: ElvUI
@@ -18,6 +18,7 @@ Cooldown.lua
DataTexts.lua DataTexts.lua
Filters.lua Filters.lua
Nameplates.lua Nameplates.lua
StyleFilters.lua
Skins.lua Skins.lua
Tooltip.lua Tooltip.lua
UnitFrames.lua UnitFrames.lua
+1 -2
View File
@@ -196,8 +196,7 @@ E.Options.args.maps = {
type = "range", type = "range",
name = L["Size"], name = L["Size"],
desc = L["Adjust the size of the minimap."], desc = L["Adjust the size of the minimap."],
min = 50, max = 600, step = 1, min = 120, max = 250, step = 1,
softMin = 120, softMax = 250,
get = function(info) return E.db.general.minimap[info[#info]] end, get = function(info) return E.db.general.minimap[info[#info]] end,
set = function(info, value) E.db.general.minimap[info[#info]] = value MM:UpdateSettings() end, set = function(info, value) E.db.general.minimap[info[#info]] = value MM:UpdateSettings() end,
disabled = function() return not E.private.general.minimap.enable end disabled = function() return not E.private.general.minimap.enable end
File diff suppressed because it is too large Load Diff
+797
View File
@@ -0,0 +1,797 @@
local E, _, V, P, G = unpack(ElvUI)
local C, L = unpack(select(2, ...))
local D = E:GetModule('Distributor')
local NP = E:GetModule('NamePlates')
local LibDeflate = E.Libs.Deflate
local ACH = E.Libs.ACH
local LCS = E.Libs.LCS
local _G = _G
local wipe, pairs, strmatch, strsplit, tostring = wipe, pairs, strmatch, strsplit, tostring
local next, sort, tonumber, format = next, sort, tonumber, format
local GetClassInfo = GetClassInfo
local GetDifficultyInfo = GetDifficultyInfo
local GetInstanceInfo = GetInstanceInfo
local GetRealZoneText = GetRealZoneText
local GetSpellInfo = GetSpellInfo
local GetSpellTexture = GetSpellTexture
local tIndexOf = tIndexOf
local GetMapInfo = GetMapInfo
local MAX_PLAYER_LEVEL = GetMaxLevel()
local filters = {}
local exportList = {}
local raidTargetIcon = [[|TInterface\TargetingFrame\UI-RaidTargetingIcon_%s:0|t %s]]
local sortedClasses = E:CopyTable({}, CLASS_SORT_ORDER)
sort(sortedClasses)
C.StyleFilterSelected = nil
E.Options.args.nameplates.args.stylefilters = ACH:Group(L["Style Filter"], nil, 10, 'tab', nil, nil, function() return not E.NamePlates.Initialized end)
local StyleFilters = E.Options.args.nameplates.args.stylefilters.args
local StyleFallback = NP:StyleFilterCopyDefaults()
local function GetFilter(collect, profile)
local setting = (profile and E.db.nameplates.filters[C.StyleFilterSelected]) or E.global.nameplates.filters[C.StyleFilterSelected] or StyleFallback
if collect and setting then
return setting.triggers, setting.actions
else
return setting
end
end
C.StyleFilterGetFilter = GetFilter
local function DisabledFilter()
local profileTriggers = GetFilter(true, true)
return not (profileTriggers and profileTriggers.enable)
end
C.StyleFilterDisabledFilter = DisabledFilter
local function GetFilters(info)
wipe(filters)
local list = E.global.nameplates.filters
if not (list and next(list)) then
return filters
end
local profile, priority, name = E.db.nameplates.filters
for filter, content in pairs(list) do
if info[#info] == 'selectFilter' then
priority = (content.triggers and content.triggers.priority) or '?'
name = (content.triggers and profile[filter] and profile[filter].triggers and profile[filter].triggers.enable and filter) or (content.triggers and format('|cFF666666%s|r', filter)) or filter
filters[filter] = format('|cFFffff00(%s)|r %s', priority, name)
else
filters[filter] = filter
end
end
return filters
end
local function GetSpellFilterInfo(name)
local spell, stacks = strmatch(name, NP.StyleFilterStackPattern)
local spellID = tonumber(spell)
if spellID then
local spellName = GetSpellInfo(spellID)
if spellName then
if DisabledFilter() then
spell = format('%s (%d)', spellName, spellID)
else
spell = format('|cFFffff00%s|r |cFFffffff(%d)|r', spellName, spellID)
if stacks ~= '' then
spell = format('%s|cFF999999%s|r', spell, ' x'..stacks)
end
end
end
end
local spellTexture = GetSpellTexture(spellID or spell)
local spellDescription = spellTexture and E:TextureString(spellTexture, ':32:32:0:0:32:32:4:28:4:28')
return spell, spellDescription
end
local spellTypes = { casting = true, known = true, debuffs = true, buffs = true, cooldowns = true }
local cdOptions = { DISABLED = _G.DISABLE, ONCD = L["On Cooldown"], OFFCD = L["Off Cooldown"] }
local subTypes = { casting = 'spells', known = 'spells', debuffs = 'names', buffs = 'names', cooldowns = 'names', names = 'list', items = 'list' }
local function GetFilterOption(which)
local option
if which == 'cooldowns' then
option = ACH:Select('', nil, nil, cdOptions)
else
option = ACH:Toggle('', nil)
option.textWidth = true
end
return option
end
local function UpdateFilterList(which, initial, opt, add)
local filter = GetFilter()
local spell, desc
local subType, isSpell = subTypes[which], spellTypes[which]
local setting = StyleFilters.triggers.args[which].args[subType]
local triggers = filter.triggers[which][subType] or filter.triggers[which]
setting.hidden = not next(triggers)
if initial and filter.triggers[which] then
setting.args = {}
for name in next, triggers do
if isSpell then
spell, desc = GetSpellFilterInfo(name)
else
spell, desc = nil, nil
end
local option = GetFilterOption(which)
option.name, option.desc = spell or name, spell and desc or nil
setting.args[name] = option
end
elseif not initial then
if isSpell then
spell, desc = GetSpellFilterInfo(opt)
end
local option = GetFilterOption(which)
option.name, option.desc = spell or opt, spell and desc or nil
setting.args[opt] = add and option or nil
end
end
local function UpdateBossModAuras(initial, opt, add)
local filter = GetFilter()
local setting = StyleFilters.triggers.args.bossModAuras.args
setting.auras.hidden = not filter or not next(filter.triggers.bossMods.auras)
if initial then
setting.auras.args = {}
setting.seenList.hidden = true
if filter and filter.triggers and filter.triggers.bossMods and filter.triggers.bossMods.auras then
for aura in next, filter.triggers.bossMods.auras do
setting.auras.args[aura] = ACH:Toggle(aura, E:TextureString(aura, ':32:32:0:0:32:32:4:28:4:28'))
end
end
if filter and filter.triggers and filter.triggers.bossMods and next(NP.BossMods_TextureCache) then
setting.seenList.hidden = false
for texture in next, NP.BossMods_TextureCache do
setting.seenList.args[texture] = ACH:Toggle(texture, E:TextureString(texture, ':32:32:0:0:32:32:4:28:4:28'))
end
end
elseif not initial then
setting.auras.args[opt] = add and ACH:Toggle(opt, E:TextureString(opt, ':32:32:0:0:32:32:4:28:4:28')) or nil
end
end
local function UpdateFilterGroup()
UpdateFilterList('names', true)
UpdateFilterList('items', true)
UpdateFilterList('cooldowns', true)
UpdateFilterList('buffs', true)
UpdateFilterList('debuffs', true)
UpdateFilterList('casting', true)
UpdateFilterList('known', true)
end
function C:StyleFilterSetConfig(filter)
C.StyleFilterSelected = filter
UpdateFilterGroup()
E.Libs.AceConfigDialog:SelectGroup('ElvUI', 'nameplates', 'stylefilters', filter and 'triggers' or 'import')
end
local function validateCreateFilter(_, value) return not (strmatch(value, '^[%s%p]-$') or E.global.nameplates.filters[value]) end
local function validateString(_, value) return not strmatch(value, '^[%s%p]-$') end
StyleFilters.addFilter = ACH:Input(L["Create Filter"], nil, 1, nil, nil, nil, function(_, value) E.global.nameplates.filters[value] = NP:StyleFilterCopyDefaults() C:StyleFilterSetConfig(value) end, nil, nil, validateCreateFilter)
StyleFilters.selectFilter = ACH:Select(L["Select Filter"], nil, 2, GetFilters, nil, nil, function() return C.StyleFilterSelected end, function(_, value) C:StyleFilterSetConfig(value) end)
StyleFilters.selectFilter.sortByValue = true
StyleFilters.removeFilter = ACH:Select(L["Delete Filter"], L["Delete a created filter, you cannot delete pre-existing filters, only custom ones."], 3, function() wipe(filters) for filterName in next, E.global.nameplates.filters do if not G.nameplates.filters[filterName] then filters[filterName] = filterName end end return filters end, true, nil, nil, function(_, value) for profile in pairs(E.data.profiles) do if E.data.profiles[profile].nameplates and E.data.profiles[profile].nameplates.filters then E.data.profiles[profile].nameplates.filters[value] = nil end end E.global.nameplates.filters[value] = nil exportList[value] = nil NP:ConfigureAll() C:StyleFilterSetConfig() end)
StyleFilters.triggers = ACH:Group(L["Triggers"], nil, 5, nil, nil, nil, function() return not C.StyleFilterSelected end)
-- UpdateBossModAuras needed here in get to update the list once every time you load the config with a selected filter.
StyleFilters.triggers.args.enable = ACH:Toggle(L["Enable"], nil, 0, nil, nil, nil, function() UpdateBossModAuras(true) local profileTriggers = GetFilter(true, true) return profileTriggers and profileTriggers.enable end, function(_, value) E.db.nameplates = E.db.nameplates or {} E.db.nameplates.filters = E.db.nameplates.filters or {} E.db.nameplates.filters[C.StyleFilterSelected] = E.db.nameplates.filters[C.StyleFilterSelected] or {} local profileFilter = GetFilter(nil, true) if not profileFilter.triggers then profileFilter.triggers = {} end profileFilter.triggers.enable = value NP:ConfigureAll() end)
StyleFilters.triggers.args.priority = ACH:Range(L["Filter Priority"], L["Lower numbers mean a higher priority. Filters are processed in order from 1 to 100."], 1, { min = 1, max = 100, step = 1 }, nil, function() local triggers = GetFilter(true) return triggers.priority or 1 end, function(_, value) local triggers = GetFilter(true) if triggers then triggers.priority = value NP:ConfigureAll() end end, DisabledFilter)
StyleFilters.triggers.args.resetFilter = ACH:Execute(L["Clear Filter"], L["Return filter to its default state."], 2, function() E.global.nameplates.filters[C.StyleFilterSelected] = E:CopyTable(NP:StyleFilterCopyDefaults(), G.nameplates.filters[C.StyleFilterSelected]) UpdateFilterGroup() NP:ConfigureAll() end)
StyleFilters.triggers.args.names = ACH:Group(L["Name"], nil, 6, nil, nil, nil, DisabledFilter)
StyleFilters.triggers.args.names.args.addName = ACH:Input(L["Add Name or NPC ID"], L["Add a Name or NPC ID to the list."], 1, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.names[value] = true UpdateFilterList('names', nil, value, true) NP:ConfigureAll() end, nil, nil, validateString)
StyleFilters.triggers.args.names.args.removeName = ACH:Select(L["Remove Name or NPC ID"], L["Remove a Name or NPC ID from the list."], 2, function() local triggers, values = GetFilter(true), {} for name in next, triggers.names do values[name] = name end return values end, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.names[value] = nil UpdateFilterList('names', nil, value) NP:ConfigureAll() end)
StyleFilters.triggers.args.names.args.negativeMatch = ACH:Toggle(L["Negative Match"], L["Match if Name or NPC ID is NOT in the list."], 3, nil, nil, nil, function(info) local triggers = GetFilter(true) return triggers[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers[info[#info]] = value NP:ConfigureAll() end)
StyleFilters.triggers.args.names.args.list = ACH:Group('', nil, 50, nil, function(info) local triggers = GetFilter(true) return triggers.names and triggers.names[info[#info]] end, function(info, value) local triggers = GetFilter(true) if not triggers.names then triggers.names = {} end triggers.names[info[#info]] = value NP:ConfigureAll() end, nil, true)
StyleFilters.triggers.args.names.args.list.inline = true
StyleFilters.triggers.args.targeting = ACH:Group(L["Targeting"], nil, 7, nil, function(info) local triggers = GetFilter(true) return triggers[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.targeting.args.types = ACH:Group('', nil, 1)
StyleFilters.triggers.args.targeting.args.types.inline = true
StyleFilters.triggers.args.targeting.args.types.args.isTarget = ACH:Toggle(L["Is Targeted"], L["If enabled then the filter will only activate when you are targeting the unit."], 1)
StyleFilters.triggers.args.targeting.args.types.args.notTarget = ACH:Toggle(L["Not Targeted"], L["If enabled then the filter will only activate when you are not targeting the unit."], 2)
StyleFilters.triggers.args.targeting.args.types.args.requireTarget = ACH:Toggle(L["Require Target"], L["If enabled then the filter will only activate when you have a target."], 3)
StyleFilters.triggers.args.targeting.args.types.args.noTarget = ACH:Toggle(L["No Target"], nil, 4)
StyleFilters.triggers.args.targeting.args.types.args.targetMe = ACH:Toggle(L["Is Targeting Player"], L["If enabled then the filter will only activate when the unit is targeting you."], 5)
StyleFilters.triggers.args.targeting.args.types.args.notTargetMe = ACH:Toggle(L["Not Targeting Player"], L["If enabled then the filter will only activate when the unit is not targeting you."], 6)
StyleFilters.triggers.args.targeting.args.types.args.isFocus = ACH:Toggle(L["Is Focused"], L["If enabled then the filter will only activate when you are focusing the unit."], 7)
StyleFilters.triggers.args.targeting.args.types.args.notFocus = ACH:Toggle(L["Not Focused"], L["If enabled then the filter will only activate when you are not focusing the unit."], 8)
StyleFilters.triggers.args.casting = ACH:Group(L["Casting"], nil, 8, nil, function(info) local triggers = GetFilter(true) return triggers.casting[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.casting[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.casting.args.types = ACH:Group('', nil, 1)
StyleFilters.triggers.args.casting.args.types.inline = true
StyleFilters.triggers.args.casting.args.types.args.interruptible = ACH:Toggle(L["Interruptible"], L["If enabled then the filter will only activate if the unit is casting interruptible spells."], 1)
StyleFilters.triggers.args.casting.args.types.args.notInterruptible = ACH:Toggle(L["Non-Interruptible"], L["If enabled then the filter will only activate if the unit is casting not interruptible spells."], 2)
StyleFilters.triggers.args.casting.args.types.args.spacer1 = ACH:Spacer(3, 'full')
StyleFilters.triggers.args.casting.args.types.args.isCasting = ACH:Toggle(L["Is Casting Anything"], L["If enabled then the filter will activate if the unit is casting anything."], 4)
StyleFilters.triggers.args.casting.args.types.args.notCasting = ACH:Toggle(L["Not Casting Anything"], L["If enabled then the filter will activate if the unit is not casting anything."], 5)
StyleFilters.triggers.args.casting.args.types.args.spacer2 = ACH:Spacer(6, 'full')
StyleFilters.triggers.args.casting.args.types.args.isChanneling = ACH:Toggle(L["Is Channeling Anything"], L["If enabled then the filter will activate if the unit is channeling anything."], 7)
StyleFilters.triggers.args.casting.args.types.args.notChanneling = ACH:Toggle(L["Not Channeling Anything"], L["If enabled then the filter will activate if the unit is not channeling anything."], 8)
StyleFilters.triggers.args.casting.args.addSpell = ACH:Input(L["Add Spell ID or Name"], nil, 2, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.casting.spells[value] = true UpdateFilterList('casting', nil, value, true) NP:ConfigureAll() end, nil, nil, validateString)
StyleFilters.triggers.args.casting.args.removeSpell = ACH:Select(L["Remove Spell ID or Name"], L["If the aura is listed with a number then you need to use that to remove it from the list."], 3, function() local triggers, values = GetFilter(true), {} for spell in next, triggers.casting.spells do values[spell] = spell end return values end, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.casting.spells[value] = nil UpdateFilterList('casting', nil, value) NP:ConfigureAll() end)
StyleFilters.triggers.args.casting.args.notSpell = ACH:Toggle(L["Not Spell"], L["If enabled then the filter will only activate if the unit is not casting or channeling one of the selected spells."], 4)
StyleFilters.triggers.args.casting.args.description1 = ACH:Description(L["You do not need to use Is Casting Anything or Is Channeling Anything for these spells to trigger."], 10)
StyleFilters.triggers.args.casting.args.description2 = ACH:Description(L["If this list is empty, and if Interruptible is checked, then the filter will activate on any type of cast that can be interrupted."], 11)
StyleFilters.triggers.args.casting.args.spells = ACH:Group('', nil, 50, nil, function(info) local triggers = GetFilter(true) return triggers.casting.spells and triggers.casting.spells[info[#info]] end, function(info, value) local triggers = GetFilter(true) if not triggers.casting.spells then triggers.casting.spells = {} end triggers.casting.spells[info[#info]] = value NP:ConfigureAll() end, nil, true)
StyleFilters.triggers.args.casting.args.spells.inline = true
StyleFilters.triggers.args.known = ACH:Group(L["Known Spells"], nil, 9, nil, function(info) local triggers = GetFilter(true) return triggers.known[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.known[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.known.args.types = ACH:Group('', nil, 1)
StyleFilters.triggers.args.known.args.types.inline = true
StyleFilters.triggers.args.known.args.types.args.notKnown = ACH:Toggle(L["Not Known"], L["Match this trigger if the spell is not known."], 1)
StyleFilters.triggers.args.known.args.types.args.playerSpell = ACH:Toggle(L["Player Spell"], L["This uses the IsPlayerSpell API which is only required sometimes."], 2)
StyleFilters.triggers.args.known.args.addSpell = ACH:Input(L["Add Spell ID or Name"], nil, 2, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.known.spells[value] = true UpdateFilterList('known', nil, value, true) NP:ConfigureAll() end, nil, nil, validateString)
StyleFilters.triggers.args.known.args.removeSpell = ACH:Select(L["Remove Spell ID or Name"], L["If the aura is listed with a number then you need to use that to remove it from the list."], 3, function() local triggers, values = GetFilter(true), {} for spell in next, triggers.known.spells do values[spell] = spell end return values end, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.known.spells[value] = nil UpdateFilterList('known', nil, value) NP:ConfigureAll() end)
StyleFilters.triggers.args.known.args.spells = ACH:Group('', nil, 50, nil, function(info) local triggers = GetFilter(true) return triggers.known.spells and triggers.known.spells[info[#info]] end, function(info, value) local triggers = GetFilter(true) if not triggers.known.spells then triggers.known.spells = {} end triggers.known.spells[info[#info]] = value NP:ConfigureAll() end, nil, true)
StyleFilters.triggers.args.known.args.spells.inline = true
StyleFilters.triggers.args.combat = ACH:Group(L["Unit Conditions"], nil, 10, nil, function(info) local triggers = GetFilter(true) return triggers[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.combat.args.playerGroup = ACH:Group(L["Player"], nil, 1)
StyleFilters.triggers.args.combat.args.playerGroup.inline = true
StyleFilters.triggers.args.combat.args.playerGroup.args.inCombat = ACH:Toggle(L["In Combat"], L["If enabled then the filter will only activate when you are in combat."], 1)
StyleFilters.triggers.args.combat.args.playerGroup.args.outOfCombat = ACH:Toggle(L["Out of Combat"], L["If enabled then the filter will only activate when you are out of combat."], 2)
StyleFilters.triggers.args.combat.args.playerGroup.args.inVehicle = ACH:Toggle(L["In Vehicle"], L["If enabled then the filter will only activate when you are in a Vehicle."], 3, nil, nil, nil, nil, nil, nil, not E.Retail)
StyleFilters.triggers.args.combat.args.playerGroup.args.outOfVehicle = ACH:Toggle(L["Out of Vehicle"], L["If enabled then the filter will only activate when you are not in a Vehicle."], 4, nil, nil, nil, nil, nil, nil, not E.Retail)
StyleFilters.triggers.args.combat.args.playerGroup.args.isResting = ACH:Toggle(L["Is Resting"], L["If enabled then the filter will only activate when you are resting at an Inn."], 5)
StyleFilters.triggers.args.combat.args.playerGroup.args.notResting = ACH:Toggle(L["Not Resting"], nil, 6)
StyleFilters.triggers.args.combat.args.playerGroup.args.playerCanAttack = ACH:Toggle(L["Can Attack"], L["If enabled then the filter will only activate when the unit can be attacked by the active player."], 7)
StyleFilters.triggers.args.combat.args.playerGroup.args.playerCanNotAttack = ACH:Toggle(L["Can Not Attack"], L["If enabled then the filter will only activate when the unit can not be attacked by the active player."], 8)
StyleFilters.triggers.args.combat.args.playerGroup.args.inPetBattle = ACH:Toggle(L["In Pet Battle"], nil, 9, nil, nil, nil, nil, nil, nil, not E.Retail)
StyleFilters.triggers.args.combat.args.playerGroup.args.notPetBattle = ACH:Toggle(L["Not Pet Battle"], nil, 10, nil, nil, nil, nil, nil, nil, not E.Retail)
StyleFilters.triggers.args.combat.args.unitGroup = ACH:Group(L["Unit"], nil, 2)
StyleFilters.triggers.args.combat.args.unitGroup.inline = true
StyleFilters.triggers.args.combat.args.unitGroup.args.inCombatUnit = ACH:Toggle(L["In Combat"], L["If enabled then the filter will only activate when the unit is in combat."], 1)
StyleFilters.triggers.args.combat.args.unitGroup.args.outOfCombatUnit = ACH:Toggle(L["Out of Combat"], L["If enabled then the filter will only activate when the unit is out of combat."], 2)
StyleFilters.triggers.args.combat.args.unitGroup.args.inVehicleUnit = ACH:Toggle(L["In Vehicle"], L["If enabled then the filter will only activate when the unit is in a Vehicle."], 3, nil, nil, nil, nil, nil, nil, not E.Retail)
StyleFilters.triggers.args.combat.args.unitGroup.args.outOfVehicleUnit = ACH:Toggle(L["Out of Vehicle"], L["If enabled then the filter will only activate when the unit is not in a Vehicle."], 4, nil, nil, nil, nil, nil, nil, not E.Retail)
StyleFilters.triggers.args.combat.args.unitGroup.args.inParty = ACH:Toggle(L["In Party"], L["If enabled then the filter will only activate when the unit is in your Party."], 5)
StyleFilters.triggers.args.combat.args.unitGroup.args.notInParty = ACH:Toggle(L["Not in Party"], L["If enabled then the filter will only activate when the unit is not in your Party."], 6)
StyleFilters.triggers.args.combat.args.unitGroup.args.inRaid = ACH:Toggle(L["In Raid"], L["If enabled then the filter will only activate when the unit is in your Raid."], 7)
StyleFilters.triggers.args.combat.args.unitGroup.args.notInRaid = ACH:Toggle(L["Not in Raid"], L["If enabled then the filter will only activate when the unit is not in your Raid."], 8)
StyleFilters.triggers.args.combat.args.unitGroup.args.isPet = ACH:Toggle(L["Is Pet"], L["If enabled then the filter will only activate when the unit is the active player's pet."], 9)
StyleFilters.triggers.args.combat.args.unitGroup.args.isNotPet= ACH:Toggle(L["Not Pet"], L["If enabled then the filter will only activate when the unit is not the active player's pet."], 10)
StyleFilters.triggers.args.combat.args.unitGroup.args.isPlayerControlled = ACH:Toggle(L["Player Controlled"], L["If enabled then the filter will only activate when the unit is controlled by the player."], 11)
StyleFilters.triggers.args.combat.args.unitGroup.args.isNotPlayerControlled = ACH:Toggle(L["Not Player Controlled"], L["If enabled then the filter will only activate when the unit is not controlled by the player."], 12)
StyleFilters.triggers.args.combat.args.unitGroup.args.isOwnedByPlayer = ACH:Toggle(L["Owned By Player"], L["If enabled then the filter will only activate when the unit is owned by the player."], 13)
StyleFilters.triggers.args.combat.args.unitGroup.args.isNotOwnedByPlayer = ACH:Toggle(L["Not Owned By Player"], L["If enabled then the filter will only activate when the unit is not owned by the player."], 14)
StyleFilters.triggers.args.combat.args.unitGroup.args.isPvP = ACH:Toggle(L["Is PvP"], L["If enabled then the filter will only activate when the unit is pvp-flagged."], 15)
StyleFilters.triggers.args.combat.args.unitGroup.args.isNotPvP = ACH:Toggle(L["Not PvP"], L["If enabled then the filter will only activate when the unit is not pvp-flagged."], 16)
StyleFilters.triggers.args.combat.args.unitGroup.args.inMyGuild = ACH:Toggle(L["My Guild"], nil, 19)
StyleFilters.triggers.args.combat.args.unitGroup.args.notMyGuild = ACH:Toggle(L["Not My Guild"], nil, 20)
StyleFilters.triggers.args.combat.args.unitGroup.args.isTrivial = ACH:Toggle(L["Is Trivial"], nil, 21)
StyleFilters.triggers.args.combat.args.unitGroup.args.notTrivial = ACH:Toggle(L["Not Trivial"], nil, 22)
StyleFilters.triggers.args.combat.args.unitGroup.args.isPossessed = ACH:Toggle(L["Is Possessed"], nil, 23)
StyleFilters.triggers.args.combat.args.unitGroup.args.notPossessed = ACH:Toggle(L["Not Possessed"], nil, 24)
StyleFilters.triggers.args.combat.args.unitGroup.args.isCharmed = ACH:Toggle(L["Is Charmed"], nil, 25)
StyleFilters.triggers.args.combat.args.unitGroup.args.notCharmed = ACH:Toggle(L["Not Charmed"], nil, 26)
StyleFilters.triggers.args.combat.args.unitGroup.args.isDeadOrGhost = ACH:Toggle(L["Dead or Ghost"], nil, 27)
StyleFilters.triggers.args.combat.args.unitGroup.args.notDeadOrGhost = ACH:Toggle(L["Alive"], nil, 28)
StyleFilters.triggers.args.combat.args.unitGroup.args.isConnected = ACH:Toggle(L["Connected"], nil, 29)
StyleFilters.triggers.args.combat.args.unitGroup.args.notConnected = ACH:Toggle(L["Disconnected"], nil, 30)
StyleFilters.triggers.args.combat.args.npcGroup = ACH:Group('', nil, 3)
StyleFilters.triggers.args.combat.args.npcGroup.inline = true
StyleFilters.triggers.args.combat.args.npcGroup.args.hasTitleNPC = ACH:Toggle(L["Has NPC Title"], nil, 1)
StyleFilters.triggers.args.combat.args.npcGroup.args.noTitleNPC = ACH:Toggle(L["No NPC Title"], nil, 2)
StyleFilters.triggers.args.combat.args.questGroup = ACH:Group('', nil, 4, nil, nil, nil, nil, not E.Retail)
StyleFilters.triggers.args.combat.args.questGroup.inline = true
StyleFilters.triggers.args.combat.args.questGroup.args.isQuest = ACH:Toggle(L["Quest Unit"], nil, 1)
StyleFilters.triggers.args.combat.args.questGroup.args.notQuest = ACH:Toggle(L["Not Quest Unit"], nil, 2)
StyleFilters.triggers.args.faction = ACH:Group(L["Unit Faction"], nil, 11, nil, function(info) local triggers = GetFilter(true) return triggers.faction[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.faction[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.faction.args.types = ACH:Group('', nil, 2)
StyleFilters.triggers.args.faction.args.types.inline = true
StyleFilters.triggers.args.faction.args.types.args.Alliance = ACH:Toggle(L["Alliance"], nil, 1)
StyleFilters.triggers.args.faction.args.types.args.Horde = ACH:Toggle(L["Horde"], nil, 2)
StyleFilters.triggers.args.faction.args.types.args.Neutral = ACH:Toggle(L["Neutral"], nil, 3)
StyleFilters.triggers.args.class = ACH:Group(L["CLASS"], nil, 12, nil, nil, nil, DisabledFilter)
for index = 1, _G.MAX_CLASSES do
local className, classTag = GetClassInfo(index)
if classTag then
local coloredName = RAID_CLASS_COLORS[classTag]
coloredName = (coloredName and coloredName.colorStr) or 'ff666666'
StyleFilters.triggers.args.class.args[classTag] = ACH:Toggle(format('|c%s%s|r', coloredName, className), nil, tIndexOf(sortedClasses, classTag), nil, nil, nil, function() local triggers = GetFilter(true) local tagTrigger = triggers.class[classTag] return tagTrigger and tagTrigger.enabled end, function(_, value) local triggers = GetFilter(true) local tagTrigger = triggers.class[classTag] if not tagTrigger then triggers.class[classTag] = {} end if value then triggers.class[classTag].enabled = value else triggers.class[classTag] = nil end NP:ConfigureAll() end)
local group = ACH:Group(className, nil, tIndexOf(sortedClasses, classTag) + 13, nil, nil, nil, nil, function() local triggers = GetFilter(true) local tagTrigger = triggers.class[classTag] return not tagTrigger or not tagTrigger.enabled end)
group.inline = true
for k = 1, #SPEC_SWAP_SPELLS do
local specID, name = k, "Talent Specialization" .. " " .. k
local tagID = format('%s%s', classTag, specID)
group.args[tagID] = ACH:Toggle(format('|c%s%s|r', coloredName, name), nil, k, nil, nil, nil, function() local triggers = GetFilter(true) local tagTrigger = triggers.class[classTag] return tagTrigger and tagTrigger.specs and tagTrigger.specs[specID] end, function(_, value) local triggers = GetFilter(true) local tagTrigger = triggers.class[classTag] if not tagTrigger.specs then triggers.class[classTag].specs = {} end triggers.class[classTag].specs[specID] = value or nil if not next(triggers.class[classTag].specs) then triggers.class[classTag].specs = nil end NP:ConfigureAll() end)
end
StyleFilters.triggers.args.class.args[format('%s%s', classTag, 'spec')] = group
end
end
StyleFilters.triggers.args.slots = ACH:Group(L["Slots"], nil, 13, nil, nil, nil, DisabledFilter)
StyleFilters.triggers.args.slots.args.types = ACH:MultiSelect(L["Equipped"], nil, 1, nil, nil, nil, function(_, key) local triggers = GetFilter(true) return triggers.slots[key] end, function(_, key, value) local triggers = GetFilter(true) triggers.slots[key] = value or nil NP:ConfigureAll() end)
StyleFilters.triggers.args.slots.args.types.sortByValue = true
StyleFilters.triggers.args.slots.args.types.values = {
[_G.INVSLOT_AMMO] = INVTYPE_AMMO, -- 0
[_G.INVSLOT_HEAD] = INVTYPE_HEAD, -- 1
[_G.INVSLOT_NECK] = INVTYPE_NECK, -- 2
[_G.INVSLOT_SHOULDER] = INVTYPE_SHOULDER, -- 3
[_G.INVSLOT_BODY] = INVTYPE_BODY, -- 4 (shirt)
[_G.INVSLOT_CHEST] = INVTYPE_CHEST, -- 5
[_G.INVSLOT_WAIST] = INVTYPE_WAIST, -- 6
[_G.INVSLOT_LEGS] = INVTYPE_LEGS, -- 7
[_G.INVSLOT_FEET] = INVTYPE_FEET, -- 8
[_G.INVSLOT_WRIST] = INVTYPE_WRIST, -- 9
[_G.INVSLOT_HAND] = INVTYPE_HAND, -- 10
[_G.INVSLOT_FINGER1] = INVTYPE_FINGER1, -- 11 (no real global)
[_G.INVSLOT_FINGER2] = INVTYPE_FINGER2, -- 12 (no real global)
[_G.INVSLOT_TRINKET1] = INVTYPE_TRINKET1, -- 13 (no real global)
[_G.INVSLOT_TRINKET2] = INVTYPE_TRINKET2, -- 14 (no real global)
[_G.INVSLOT_BACK] = INVTYPE_CLOAK, -- 15
[_G.INVSLOT_MAINHAND] = INVTYPE_WEAPONMAINHAND, -- 16
[_G.INVSLOT_OFFHAND] = INVTYPE_WEAPONOFFHAND, -- 17
[_G.INVSLOT_RANGED] = INVTYPE_RANGED, -- 18
[_G.INVSLOT_TABARD] = INVTYPE_TABARD, -- 19
}
StyleFilters.triggers.args.items = ACH:Group(L["Items"], nil, 14, nil, nil, nil, DisabledFilter)
StyleFilters.triggers.args.items.args.addItem = ACH:Input(L["Add Item Name or ID"], L["Add a Item Name or ID to the list."], 1, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.items[value] = true UpdateFilterList('items', nil, value, true) NP:ConfigureAll() end, nil, nil, validateString)
StyleFilters.triggers.args.items.args.removeItem = ACH:Select(L["Remove Item Name or ID"], L["Remove a Item Name or ID from the list."], 2, function() local triggers, values = GetFilter(true), {} for name in next, triggers.items do values[name] = name end return values end, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.items[value] = nil UpdateFilterList('items', nil, value) NP:ConfigureAll() end)
StyleFilters.triggers.args.items.args.negativeMatch = ACH:Toggle(L["Negative Match"], L["Match if Item Name or ID is NOT in the list."], 3, nil, nil, nil, function(info) local triggers = GetFilter(true) return triggers[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers[info[#info]] = value NP:ConfigureAll() end)
StyleFilters.triggers.args.items.args.list = ACH:Group('', nil, 50, nil, function(info) local triggers = GetFilter(true) return triggers.items and triggers.items[info[#info]] end, function(info, value) local triggers = GetFilter(true) if not triggers.items then triggers.items = {} end triggers.items[info[#info]] = value NP:ConfigureAll() end, nil, true)
StyleFilters.triggers.args.items.args.list.inline = true
StyleFilters.triggers.args.role = ACH:Group(L["ROLE"], nil, 15, nil, nil, nil, DisabledFilter)
for option, name in next, { myRole = L["Player"], unitRole = L["Unit"] } do
StyleFilters.triggers.args.role.args[option] = ACH:Group(name, nil, nil, nil, function(info) local triggers = GetFilter(true) return triggers[option] and triggers[option][info[#info]] end, function(info, value) local triggers = GetFilter(true) if not triggers[option] then triggers[option] = {} end triggers[option][info[#info]] = value NP:ConfigureAll() end)
StyleFilters.triggers.args.role.args[option].inline = true
for role, roleLocale in next, { tank = L["Tank"], healer = L["Healer"], damager = L["DAMAGER"] } do
StyleFilters.triggers.args.role.args[option].args[role] = ACH:Toggle(roleLocale)
end
end
StyleFilters.triggers.args.classification = ACH:Group(L["Classification"], nil, 16, nil, function(info) local triggers = GetFilter(true) return triggers.classification[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.classification[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.classification.args.types = ACH:Group('', nil, 2)
StyleFilters.triggers.args.classification.args.types.inline = true
StyleFilters.triggers.args.classification.args.types.args.worldboss = ACH:Toggle(L["Boss"], nil, 1)
StyleFilters.triggers.args.classification.args.types.args.rareelite = ACH:Toggle(L["Rare Elite"], nil, 2)
StyleFilters.triggers.args.classification.args.types.args.normal = ACH:Toggle(PLAYER_DIFFICULTY1, nil, 3)
StyleFilters.triggers.args.classification.args.types.args.rare = ACH:Toggle(ITEM_QUALITY3_DESC, nil, 4)
StyleFilters.triggers.args.classification.args.types.args.trivial = ACH:Toggle(L["Trivial"], nil, 5)
StyleFilters.triggers.args.classification.args.types.args.elite = ACH:Toggle(L["Elite"], nil, 6)
StyleFilters.triggers.args.health = ACH:Group(L["Health Threshold"], nil, 17, nil, function(info) local triggers = GetFilter(true) return triggers[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.health.args.healthThreshold = ACH:Toggle(L["Enable"], nil, 1)
StyleFilters.triggers.args.health.args.healthUsePlayer = ACH:Toggle(L["Player Health"], L["Enabling this will check your health amount."], 2, nil, nil, nil, nil, nil, function() local triggers = GetFilter(true) return not triggers.healthThreshold end)
StyleFilters.triggers.args.health.args.underHealthThreshold = ACH:Range(L["Under Health Threshold"], L["If this threshold is used then the health of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."], 4, { min = 0, max = 1, step = 0.01, isPercent = true }, nil, function() local triggers = GetFilter(true) return triggers.underHealthThreshold or 0 end, nil, function() local triggers = GetFilter(true) return not triggers.healthThreshold end)
StyleFilters.triggers.args.health.args.overHealthThreshold = ACH:Range(L["Over Health Threshold"], L["If this threshold is used then the health of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."], 5, { min = 0, max = 1, step = 0.01, isPercent = true }, nil, function() local triggers = GetFilter(true) return triggers.overHealthThreshold or 0 end, nil, function() local triggers = GetFilter(true) return not triggers.healthThreshold end)
StyleFilters.triggers.args.power = ACH:Group(L["Power Threshold"], nil, 18, nil, function(info) local triggers = GetFilter(true) return triggers[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.power.args.powerThreshold = ACH:Toggle(L["Enable"], nil, 1)
StyleFilters.triggers.args.power.args.powerUsePlayer = ACH:Toggle(L["Player Power"], L["Enabling this will check your power amount."], 2, nil, nil, nil, nil, nil, function() local triggers = GetFilter(true) return not triggers.powerThreshold end)
StyleFilters.triggers.args.power.args.underPowerThreshold = ACH:Range(L["Under Power Threshold"], L["If this threshold is used then the power of the unit needs to be lower than this value in order for the filter to activate. Set to 0 to disable."], 4, { min = 0, max = 1, step = 0.01, isPercent = true }, nil, function() local triggers = GetFilter(true) return triggers.underPowerThreshold or 0 end, nil, function() local triggers = GetFilter(true) return not triggers.powerThreshold end)
StyleFilters.triggers.args.power.args.overPowerThreshold = ACH:Range(L["Over Power Threshold"], L["If this threshold is used then the power of the unit needs to be higher than this value in order for the filter to activate. Set to 0 to disable."], 4, { min = 0, max = 1, step = 0.01, isPercent = true }, nil, function() local triggers = GetFilter(true) return triggers.overPowerThreshold or 0 end, nil, function() local triggers = GetFilter(true) return not triggers.powerThreshold end)
StyleFilters.triggers.args.keyMod = ACH:Group(L["Key Modifiers"], nil, 19, nil, function(info) local triggers = GetFilter(true) return triggers.keyMod and triggers.keyMod[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.keyMod[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.keyMod.args.enable = ACH:Toggle(L["Enable"], nil, 0)
StyleFilters.triggers.args.keyMod.args.types = ACH:Group('', nil, 1, nil, nil, nil, function() local triggers = GetFilter(true) return DisabledFilter() or not triggers.keyMod.enable end)
StyleFilters.triggers.args.keyMod.args.types.inline = true
StyleFilters.triggers.args.keyMod.args.types.args.Shift = ACH:Toggle(SHIFT_KEY_TEXT, nil, 1)
StyleFilters.triggers.args.keyMod.args.types.args.Alt = ACH:Toggle(L["ALT_KEY_TEXT"], nil, 2)
StyleFilters.triggers.args.keyMod.args.types.args.Control = ACH:Toggle(CTRL_KEY_TEXT, nil, 3)
StyleFilters.triggers.args.keyMod.args.types.args.Modifier = ACH:Toggle(L["Any"], nil, 4)
StyleFilters.triggers.args.keyMod.args.types.args.LeftShift = ACH:Toggle(L["Left Shift"], nil, 6)
StyleFilters.triggers.args.keyMod.args.types.args.LeftAlt = ACH:Toggle(L["Left Alt"], nil, 7)
StyleFilters.triggers.args.keyMod.args.types.args.LeftControl = ACH:Toggle(L["Left Control"], nil, 8)
StyleFilters.triggers.args.keyMod.args.types.args.RightShift = ACH:Toggle(L["Right Shift"], nil, 10)
StyleFilters.triggers.args.keyMod.args.types.args.RightAlt = ACH:Toggle(L["Right Alt"], nil, 11)
StyleFilters.triggers.args.keyMod.args.types.args.RightControl = ACH:Toggle(L["Right Control"], nil, 12)
StyleFilters.triggers.args.levels = ACH:Group(L["Level"], nil, 20, nil, function(info) local triggers = GetFilter(true) return triggers[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.levels.args.level = ACH:Toggle(L["Enable"], nil, 1)
StyleFilters.triggers.args.levels.args.mylevel = ACH:Toggle(L["Match Player Level"], L["If enabled then the filter will only activate if the level of the unit matches your own."], 2, nil, nil, nil, nil, nil, function() local triggers = GetFilter(true) return not triggers.level end)
StyleFilters.triggers.args.levels.args.spacer1 = ACH:Description(L["LEVEL_BOSS"], 3)
StyleFilters.triggers.args.levels.args.minlevel = ACH:Range(L["Minimum Level"], L["If enabled then the filter will only activate if the level of the unit is equal to or higher than this value."], 4, { min = -1, max = MAX_PLAYER_LEVEL + 3, step = 1 }, nil, function(info) local triggers = GetFilter(true) return triggers[info[#info]] or 0 end, nil, function() local triggers = GetFilter(true) return not (triggers.level and not triggers.mylevel) end)
StyleFilters.triggers.args.levels.args.maxlevel = ACH:Range(L["Maximum Level"], L["If enabled then the filter will only activate if the level of the unit is equal to or lower than this value."], 5, { min = -1, max = MAX_PLAYER_LEVEL + 3, step = 1 }, nil, function(info) local triggers = GetFilter(true) return triggers[info[#info]] or 0 end, nil, function() local triggers = GetFilter(true) return not (triggers.level and not triggers.mylevel) end)
StyleFilters.triggers.args.levels.args.curlevel = ACH:Range(L["Current Level"], L["If enabled then the filter will only activate if the level of the unit matches this value."], 6, { min = -1, max = MAX_PLAYER_LEVEL + 3, step = 1 }, nil, function(info) local triggers = GetFilter(true) return triggers[info[#info]] or 0 end, nil, function() local triggers = GetFilter(true) return not (triggers.level and not triggers.mylevel) end)
StyleFilters.triggers.args.buffs = ACH:Group(L["Buffs"], nil, 21, nil, function(info) local triggers = GetFilter(true) return triggers.buffs and triggers.buffs[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.buffs[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.debuffs = ACH:Group(L["Debuffs"], nil, 22, nil, function(info) local triggers = GetFilter(true) return triggers.debuffs and triggers.debuffs[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.debuffs[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
do
local stackThreshold
for _, auraType in next, { 'buffs', 'debuffs' } do
local option = StyleFilters.triggers.args[auraType].args
option.minTimeLeft = ACH:Range(L["Minimum Time Left"], nil, 1, { min = 0, max = 10800, step = 1 })
option.maxTimeLeft = ACH:Range(L["Maximum Time Left"], nil, 2, { min = 0, max = 10800, step = 1 })
option.spacer1 = ACH:Spacer(3, 'full')
option.mustHaveAll = ACH:Toggle(L["Require All"], L["If enabled then it will require all auras to activate the filter. Otherwise it will only require any one of the auras to activate it."], 4)
option.missing = ACH:Toggle(L["Missing"], L["If enabled then it checks if auras are missing instead of being present on the unit."], 5, nil, nil, nil, nil, nil, DisabledFilter)
option.hasStealable = ACH:Toggle(L["Has Stealable"], L["If enabled then the filter will only activate when the unit has a stealable buff(s)."], 6)
option.hasNoStealable = ACH:Toggle(L["Has No Stealable"], L["If enabled then the filter will only activate when the unit has no stealable buff(s)."], 7)
option.fromMe = ACH:Toggle(L["From Me"], nil, 8)
option.fromPet = ACH:Toggle(L["From Pet"], nil, 9)
option.onMe = ACH:Toggle(L["On Me"], nil, 10)
option.onPet = ACH:Toggle(L["On Pet"], nil, 11)
option.changeList = ACH:Group(L["Add / Remove"], nil, 10)
option.changeList.inline = true
option.changeList.args.addSpell = ACH:Input(L["Add Spell ID or Name"], nil, 1, nil, nil, nil, function(_, value) if stackThreshold then value = value .. '\n' .. stackThreshold end local triggers = GetFilter(true) triggers[auraType].names[value] = true stackThreshold = nil UpdateFilterList(auraType, nil, value, true) NP:ConfigureAll() end, nil, nil, validateString)
option.changeList.args.removeSpell = ACH:Select(L["Remove Spell ID or Name"], L["If the aura is listed with a number then you need to use that to remove it from the list."], 2, function() local triggers, values = GetFilter(true), {} for name in pairs(triggers[auraType].names) do local n, v = strsplit('\n', name) values[name] = format('%s (%d)', n, v or 0) end return values end, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers[auraType].names[value] = nil UpdateFilterList(auraType, nil, value) end)
option.changeList.args.stackThreshold = ACH:Range(L["Stack Threshold"], L["Allows you to tie a stack count to an aura when you add it to the list, which allows the trigger to act when an aura reaches X number of stacks."], 3, { min = 1, max = 250, softMax = 100, step = 1 }, nil, function() return stackThreshold or 1 end, function(_, value) stackThreshold = (value > 1 and value) or nil end)
option.names = ACH:Group('', nil, 50, nil, function(info) local triggers = GetFilter(true) return triggers[auraType].names and triggers[auraType].names[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers[auraType].names[info[#info]] = value NP:ConfigureAll() end, nil, true)
option.names.inline = true
end
end
StyleFilters.triggers.args.buffs.args.minTimeLeft.desc = L["Apply this filter if a buff has remaining time greater than this. Set to zero to disable."]
StyleFilters.triggers.args.buffs.args.maxTimeLeft.desc = L["Apply this filter if a buff has remaining time less than this. Set to zero to disable."]
StyleFilters.triggers.args.debuffs.args.minTimeLeft.desc = L["Apply this filter if a debuff has remaining time greater than this. Set to zero to disable."]
StyleFilters.triggers.args.debuffs.args.maxTimeLeft.desc = L["Apply this filter if a debuff has remaining time less than this. Set to zero to disable."]
StyleFilters.triggers.args.cooldowns = ACH:Group(L["Cooldowns"], nil, 23, nil, nil, nil, DisabledFilter)
StyleFilters.triggers.args.cooldowns.args.addCooldown = ACH:Input(L["Add Spell ID or Name"], nil, 1, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.cooldowns.names[value] = 'ONCD' UpdateFilterList('cooldowns', nil, value, true) NP:ConfigureAll() end, nil, nil, validateString)
StyleFilters.triggers.args.cooldowns.args.removeCooldown = ACH:Select(L["Remove Spell ID or Name"], L["If the aura is listed with a number then you need to use that to remove it from the list."], 2, function() local values = {} local triggers = GetFilter(true) for item in next, triggers.cooldowns.names do values[item] = item end return values end, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.cooldowns.names[value] = nil UpdateFilterList('cooldowns', nil, value) NP:ConfigureAll() end)
StyleFilters.triggers.args.cooldowns.args.mustHaveAll = ACH:Toggle(L["Require All"], L["If enabled then it will require all cooldowns to activate the filter. Otherwise it will only require any one of the cooldowns to activate it."], 3, nil, nil, nil, function() local triggers = GetFilter(true) return triggers.cooldowns and triggers.cooldowns.mustHaveAll end, function(_, value) local triggers = GetFilter(true) triggers.cooldowns.mustHaveAll = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.cooldowns.args.names = ACH:Group('', nil, 50, nil, function(info) local triggers = GetFilter(true) return triggers.cooldowns.names and triggers.cooldowns.names[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.cooldowns.names[info[#info]] = value NP:ConfigureAll() end)
StyleFilters.triggers.args.cooldowns.args.names.inline = true
StyleFilters.triggers.args.bossModAuras = ACH:Group(L["Boss Mod Auras"], nil, 24, nil, function(info) local triggers = GetFilter(true) return triggers.bossMods and triggers.bossMods[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.bossMods[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.bossModAuras.args.enable = ACH:Toggle(L["Enable"], nil, 0)
StyleFilters.triggers.args.bossModAuras.args.hasAura = ACH:Toggle(L["Has Aura"], nil, 1, nil, nil, nil, nil, nil, function() local triggers = GetFilter(true) return DisabledFilter() or not triggers.bossMods.enable end)
StyleFilters.triggers.args.bossModAuras.args.missingAura = ACH:Toggle(L["Missing Aura"], nil, 2, nil, nil, nil, nil, nil, function() local triggers = GetFilter(true) return DisabledFilter() or not triggers.bossMods.enable end)
StyleFilters.triggers.args.bossModAuras.args.seenList = ACH:Group(L["Seen Textures"], nil, 3, nil, function(info) local triggers = GetFilter(true) return triggers.bossMods and triggers.bossMods.auras and triggers.bossMods.auras[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.bossMods.auras[info[#info]] = value NP:ConfigureAll() end, function() local triggers = GetFilter(true) return DisabledFilter() or triggers.bossMods.missingAura or triggers.bossMods.hasAura or not triggers.bossMods.enable end)
StyleFilters.triggers.args.bossModAuras.args.seenList.inline = true
StyleFilters.triggers.args.bossModAuras.args.seenList.args.desc = ACH:Description(L["This list will display any textures Boss Mods have sent to the Boss Mod Auras element during the current session."], 0, 'medium')
StyleFilters.triggers.args.bossModAuras.args.changeList = ACH:Group(L["Texture Matching"], nil, 5, nil, nil, nil, function() local triggers = GetFilter(true) return DisabledFilter() or triggers.bossMods.missingAura or triggers.bossMods.hasAura or not triggers.bossMods.enable end)
StyleFilters.triggers.args.bossModAuras.args.changeList.inline = true
StyleFilters.triggers.args.bossModAuras.args.changeList.args.addAura = ACH:Input(L["Add Texture"], nil, 1, nil, nil, nil, function(_, value) local triggers = GetFilter(true) local textureID = tonumber(value) or value triggers.bossMods.auras[textureID] = true UpdateBossModAuras(nil, textureID, true) NP:ConfigureAll() end, nil, nil, validateString)
StyleFilters.triggers.args.bossModAuras.args.changeList.args.removeAura = ACH:Select(L["Remove Texture"], nil, 2, function() local triggers, values = GetFilter(true), {} for textureID in next, triggers.bossMods.auras do values[tostring(textureID)] = tostring(textureID) end return values end, nil, nil, nil, function(_, value) local triggers = GetFilter(true) local textureID = tonumber(value) or value triggers.bossMods.auras[textureID] = nil UpdateBossModAuras(nil, textureID) NP:ConfigureAll() end)
StyleFilters.triggers.args.bossModAuras.args.changeList.args.missingAuras = ACH:Toggle(L["Missing Aura"], nil, 2, nil, nil, nil, function(info) local triggers = GetFilter(true) return triggers.bossMods[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.bossMods[info[#info]] = value NP:ConfigureAll() end)
StyleFilters.triggers.args.bossModAuras.args.auras = ACH:Group('', nil, 50, nil, function(info) local triggers = GetFilter(true) return triggers.bossMods and triggers.bossMods.auras and triggers.bossMods.auras[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.bossMods.auras[info[#info]] = value NP:ConfigureAll() end, function() local triggers = GetFilter(true) return DisabledFilter() or triggers.bossMods.missingAura or triggers.bossMods.hasAura or not triggers.bossMods.enable end)
StyleFilters.triggers.args.bossModAuras.args.auras.inline = true
StyleFilters.triggers.args.threat = ACH:Group(L["Threat"], nil, 25, nil, nil, nil, DisabledFilter)
StyleFilters.triggers.args.threat.args.enable = ACH:Toggle(L["Enable"], nil, 0, nil, nil, nil, function() local triggers = GetFilter(true) return triggers.threat and triggers.threat.enable end, function(_, value) local triggers = GetFilter(true) triggers.threat.enable = value NP:ConfigureAll() end)
StyleFilters.triggers.args.threat.args.types = ACH:Group('', nil, 1, nil, function(info) local triggers = GetFilter(true) return triggers.threat[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.threat[info[#info]] = value NP:ConfigureAll() end, function() local triggers = GetFilter(true) return DisabledFilter() or not triggers.threat.enable end)
StyleFilters.triggers.args.threat.args.types.inline = true
StyleFilters.triggers.args.threat.args.types.args.good = ACH:Toggle(L["Good"], nil, 1)
StyleFilters.triggers.args.threat.args.types.args.goodTransition = ACH:Toggle(L["Good Transition"], nil, 2)
StyleFilters.triggers.args.threat.args.types.args.badTransition = ACH:Toggle(L["Bad Transition"], nil, 3)
StyleFilters.triggers.args.threat.args.types.args.bad = ACH:Toggle(L["Bad"], nil, 4)
StyleFilters.triggers.args.threat.args.types.args.spacer1 = ACH:Spacer(5, 'full')
StyleFilters.triggers.args.threat.args.types.args.offTank = ACH:Toggle(L["Off Tank"], nil, 6)
StyleFilters.triggers.args.threat.args.types.args.offTankGoodTransition = ACH:Toggle(L["Off Tank Good Transition"], nil, 7, nil, nil, 200)
StyleFilters.triggers.args.threat.args.types.args.offTankBadTransition = ACH:Toggle(L["Off Tank Bad Transition"], nil, 8, nil, nil, 200)
StyleFilters.triggers.args.nameplateType = ACH:Group(L["Unit Type"], nil, 26, nil, nil, nil, DisabledFilter)
StyleFilters.triggers.args.nameplateType.args.enable = ACH:Toggle(L["Enable"], nil, 0, nil, nil, nil, function() local triggers = GetFilter(true) return triggers.nameplateType and triggers.nameplateType.enable end, function(_, value) local triggers = GetFilter(true) triggers.nameplateType.enable = value NP:ConfigureAll() end)
StyleFilters.triggers.args.nameplateType.args.types = ACH:Group('', nil, 1, nil, function(info) local triggers = GetFilter(true) return triggers.nameplateType[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.nameplateType[info[#info]] = value NP:ConfigureAll() end, function() local triggers = GetFilter(true) return DisabledFilter() or not triggers.nameplateType.enable end)
StyleFilters.triggers.args.nameplateType.args.types.inline = true
for frameType, keyName in next, E.NamePlates.TriggerConditions.frameTypes do
StyleFilters.triggers.args.nameplateType.args.types.args[keyName] = ACH:Toggle(L[frameType == 'PLAYER' and 'Player' or frameType])
end
StyleFilters.triggers.args.reactionType = ACH:Group(L["Reaction Type"], nil, 27, nil, function(info) local triggers = GetFilter(true) return triggers.reactionType and triggers.reactionType[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.reactionType[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.reactionType.args.enable = ACH:Toggle(L["Enable"], nil, 0)
StyleFilters.triggers.args.reactionType.args.reputation = ACH:Toggle(L["Reputation"], L["If this is enabled then the reaction check will use your reputation with the faction the unit belongs to."], 1, nil, nil, nil, nil, nil, function() local triggers = GetFilter(true) return DisabledFilter() or not triggers.reactionType.enable end)
StyleFilters.triggers.args.reactionType.args.types = ACH:Group('', nil, 2, nil, nil, nil, function() local triggers = GetFilter(true) return DisabledFilter() or not triggers.reactionType.enable end)
StyleFilters.triggers.args.reactionType.args.types.inline = true
for i, reactionType in next, E.NamePlates.TriggerConditions.reactions do
StyleFilters.triggers.args.reactionType.args.types.args[reactionType] = ACH:Toggle(L["FACTION_STANDING_LABEL"..i], nil, i)
end
StyleFilters.triggers.args.creatureType = ACH:Group(L["Creature Type"], nil, 28, nil, function(info) local triggers = GetFilter(true) return triggers.creatureType[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.creatureType[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.creatureType.args.enable = ACH:Toggle(L["Enable"], nil, 1, nil, nil, 'full')
StyleFilters.triggers.args.creatureType.args.types = ACH:Group('', nil, 2, nil, nil, nil, function() local triggers = GetFilter(true) return DisabledFilter() or not triggers.creatureType.enable end)
StyleFilters.triggers.args.creatureType.args.types.inline = true
do -- build creatureType options
local creatureTypeOrder = {
Aberration = 2,
Beast = 3,
Critter = 4,
Demon = 5,
Dragonkin = 6,
Elemental = 7,
['Gas Cloud'] = 8,
Giant = 9,
Humanoid = 10,
Mechanical = 11,
['Not specified'] = 12,
Totem = 13,
Undead = 14,
['Wild Pet'] = 15,
['Non-combat Pet'] = 16
}
for k, v in next, E.CreatureTypes do
StyleFilters.triggers.args.creatureType.args.types.args[v] = ACH:Toggle(k, nil, creatureTypeOrder[v], nil, nil, nil, nil, nil, function() local triggers = GetFilter(true) return DisabledFilter() or not triggers.creatureType.enable end)
end
end
StyleFilters.triggers.args.instanceType = ACH:Group(L["Instance Type"], nil, 29, nil, function(info) local triggers = GetFilter(true) return triggers.instanceType[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.instanceType[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.instanceType.args.types = ACH:Group('', nil, 2)
StyleFilters.triggers.args.instanceType.args.types.inline = true
StyleFilters.triggers.args.instanceType.args.types.args.none = ACH:Toggle(L["None"], nil, 1)
StyleFilters.triggers.args.instanceType.args.types.args.scenario = ACH:Toggle(L["SCENARIOS"], nil, 2, nil, nil, nil, nil, nil, nil, not E.Retail)
StyleFilters.triggers.args.instanceType.args.types.args.party = ACH:Toggle(L["Party"], nil, 5)
StyleFilters.triggers.args.instanceType.args.types.args.raid = ACH:Toggle(L["Raid"], nil, 5)
StyleFilters.triggers.args.instanceType.args.types.args.arena = ACH:Toggle(L["Arena"], nil, 7, nil, nil, nil, nil, nil, nil, E.Classic)
StyleFilters.triggers.args.instanceType.args.types.args.pvp = ACH:Toggle(L["BATTLEFIELDS"], nil, 8)
StyleFilters.triggers.args.instanceType.args.dungeonDifficulty = ACH:MultiSelect(L["DUNGEON_DIFFICULTY"], L["Check these to only have the filter active in certain difficulties. If none are checked, it is active in all difficulties."], 10, { normal = GetDifficultyInfo(1), heroic = GetDifficultyInfo(2), mythic = GetDifficultyInfo(3) }, nil, nil, function(_, key) local triggers = GetFilter(true) return triggers.instanceDifficulty.dungeon[key] end, function(_, key, value) local triggers = GetFilter(true) triggers.instanceDifficulty.dungeon[key] = value NP:ConfigureAll() end, nil, function() local filter = GetFilter() return not filter.triggers.instanceType.party end)
StyleFilters.triggers.args.instanceType.args.raidDifficulty = ACH:MultiSelect(L["Raid Difficulty"], L["Check these to only have the filter active in certain difficulties. If none are checked, it is active in all difficulties."], 11, { normal = GetDifficultyInfo(1), heroic = GetDifficultyInfo(2), mythic = GetDifficultyInfo(3), ascended = GetDifficultyInfo(4) }, nil, nil, function(_, key) local triggers = GetFilter(true) return triggers.instanceDifficulty.raid[key] end, function(_, key, value) local triggers = GetFilter(true) triggers.instanceDifficulty.raid[key] = value NP:ConfigureAll() end, nil, function() local filter = GetFilter() return not filter.triggers.instanceType.raid end)
local removeLocationTable = { removeMapID = 'mapIDs', removeInstanceID = 'instanceIDs', removeZoneName = 'zoneNames', removeSubZoneName = 'subZoneNames' }
local function removeLocationList(info)
local vals = {}
local triggers = GetFilter(true)
local idTable = removeLocationTable[info[#info]]
local ids = triggers.location[idTable]
if not (ids and next(ids)) then return vals end
for value in pairs(ids) do
local infoTable
if idTable == 'instanceIDs' or idTable == 'mapIDs' then
infoTable = tonumber(value) and (idTable == 'instanceIDs' and GetRealZoneText(value) or GetMapInfo(value))
if infoTable then
infoTable = '|cFF999999('..value..')|r '..(infoTable.name or infoTable)
end
end
vals[value] = infoTable or value
end
return vals
end
StyleFilters.triggers.args.location = ACH:Group(L["Location"], nil, 30, nil, function(info) local triggers = GetFilter(true) return triggers.location[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.location[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.location.args.map = ACH:Group('', nil, 1)
StyleFilters.triggers.args.location.args.map.inline = true
StyleFilters.triggers.args.location.args.map.args.mapIDEnabled = ACH:Toggle(L["Use Map ID or Name"], L["If enabled, the style filter will only activate when you are in one of the maps specified in Map ID."], 1, nil, nil, 200)
StyleFilters.triggers.args.location.args.map.args.mapIDs = ACH:Input(L["Add Map ID"], nil, 2, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.location.mapIDs[value] = true NP:ConfigureAll() end, function () local triggers = GetFilter(true) return not triggers.location.mapIDEnabled end, nil, function(_, value) local triggers = GetFilter(true) return not (strmatch(value, '^[%s%p]-$') or triggers.location.mapIDs[value]) end)
StyleFilters.triggers.args.location.args.map.args.removeMapID = ACH:Select(L["Remove Map ID"], nil, 3, removeLocationList, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.location.mapIDs[value] = nil NP:ConfigureAll() end, function() local triggers = GetFilter(true) local ids = triggers.location.mapIDs return not (triggers.location.mapIDEnabled and ids and next(ids)) end)
StyleFilters.triggers.args.location.args.instance = ACH:Group('', nil, 2)
StyleFilters.triggers.args.location.args.instance.inline = true
StyleFilters.triggers.args.location.args.instance.args.instanceIDEnabled = ACH:Toggle(L["Use Instance ID or Name"], L["If enabled, the style filter will only activate when you are in one of the instances specified in Instance ID."], 1, nil, nil, 200)
StyleFilters.triggers.args.location.args.instance.args.instanceIDs = ACH:Input(L["Add Instance ID"], nil, 2, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.location.instanceIDs[value] = true NP:ConfigureAll() end, function() local triggers = GetFilter(true) return not triggers.location.instanceIDEnabled end, nil, function(_, value) local triggers = GetFilter(true) return not (strmatch(value, '^[%s%p]-$') or triggers.location.instanceIDs[value]) end)
StyleFilters.triggers.args.location.args.instance.args.removeInstanceID = ACH:Select(L["Remove Instance ID"], nil, 3, removeLocationList, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.location.instanceIDs[value] = nil NP:ConfigureAll() end, function() local triggers = GetFilter(true) local ids = triggers.location.instanceIDs return not (triggers.location.instanceIDEnabled and ids and next(ids)) end)
StyleFilters.triggers.args.location.args.zoneName = ACH:Group('', nil, 3)
StyleFilters.triggers.args.location.args.zoneName.inline = true
StyleFilters.triggers.args.location.args.zoneName.args.zoneNamesEnabled = ACH:Toggle(L["Use Zone Names"], L["If enabled, the style filter will only activate when you are in one of the zones specified in Add Zone Name."], 1, nil, nil, 200)
StyleFilters.triggers.args.location.args.zoneName.args.zoneNames = ACH:Input(L["Add Zone Name"], nil, 2, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.location.zoneNames[value] = true NP:ConfigureAll() end, function () local triggers = GetFilter(true) return not triggers.location.zoneNamesEnabled end, nil, function(_, value) local triggers = GetFilter(true) return not (strmatch(value, '^[%s%p]-$') or triggers.location.zoneNames[value]) end)
StyleFilters.triggers.args.location.args.zoneName.args.removeZoneName = ACH:Select(L["Remove Zone Name"], nil, 3, removeLocationList, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.location.zoneNames[value] = nil NP:ConfigureAll() end, function() local triggers = GetFilter(true) local zone = triggers.location.zoneNames return not (triggers.location.zoneNamesEnabled and zone and next(zone)) end)
StyleFilters.triggers.args.location.args.subZoneName = ACH:Group('', nil, 4)
StyleFilters.triggers.args.location.args.subZoneName.inline = true
StyleFilters.triggers.args.location.args.subZoneName.args.subZoneNamesEnabled = ACH:Toggle(L["Use Subzone Names"], L["If enabled, the style filter will only activate when you are in one of the subzones specified in Add Subzone Name."], 1, nil, nil, 200)
StyleFilters.triggers.args.location.args.subZoneName.args.subZoneNames = ACH:Input(L["Add Subzone Name"], nil, 2, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.location.subZoneNames[value] = true NP:ConfigureAll() end, function () local triggers = GetFilter(true) return not triggers.location.subZoneNamesEnabled end)
StyleFilters.triggers.args.location.args.subZoneName.args.removeSubZoneName = ACH:Select(L["Remove Subzone Name"], nil, 3, removeLocationList, nil, nil, nil, function(_, value) local triggers = GetFilter(true) triggers.location.subZoneNames[value] = nil NP:ConfigureAll() end, function() local triggers = GetFilter(true) local zone = triggers.location.subZoneNames return not (triggers.location.subZoneNamesEnabled and zone and next(zone)) end)
StyleFilters.triggers.args.location.args.btns = ACH:Group(L["Add Current"], nil, 5)
StyleFilters.triggers.args.location.args.btns.inline = true
StyleFilters.triggers.args.location.args.btns.args.mapID = ACH:Execute(L["Map ID"], nil, 1, function() local mapID = E.MapInfo.mapID if not mapID then return end mapID = tostring(mapID) local triggers = GetFilter(true) if triggers.location.mapIDs[mapID] then return end triggers.location.mapIDs[mapID] = true NP:ConfigureAll() E:Print(format(L["Added Map ID: %s"], E.MapInfo.name..' ('..mapID..')')) end, nil, nil, 130)
StyleFilters.triggers.args.location.args.btns.args.instanceID = ACH:Execute(L["Instance ID"], nil, 2, function() local instanceName, _, _, _, _, _, _, instanceID = GetInstanceInfo() if not instanceID then return end instanceID = tostring(instanceID) local triggers = GetFilter(true) if triggers.location.instanceIDs[instanceID] then return end triggers.location.instanceIDs[instanceID] = true NP:ConfigureAll() E:Print(format(L["Added Instance ID: %s"], instanceName..' ('..instanceID..')')) end, nil, nil, 130)
StyleFilters.triggers.args.location.args.btns.args.zoneName = ACH:Execute(L["Zone Name"], nil, 3, function() local zone = E.MapInfo.realZoneText if not zone then return end local triggers = GetFilter(true) if triggers.location.zoneNames[zone] then return end triggers.location.zoneNames[zone] = true NP:ConfigureAll() E:Print(format(L["Added Zone Name: %s"], zone)) end, nil, nil, 130)
StyleFilters.triggers.args.location.args.btns.args.subZoneName = ACH:Execute(L["Subzone Name"], nil, 4, function() local subZone = E.MapInfo.subZoneText if not subZone then return end local triggers = GetFilter(true) if triggers.location.subZoneNames[subZone] then return end triggers.location.subZoneNames[subZone] = true NP:ConfigureAll() E:Print(format(L["Added Subzone Name: %s"], subZone)) end, nil, nil, 130)
StyleFilters.triggers.args.raidTarget = ACH:Group(L["BINDING_HEADER_RAID_TARGET"], nil, 31, nil, function(info) local triggers = GetFilter(true) return triggers.raidTarget[info[#info]] end, function(info, value) local triggers = GetFilter(true) triggers.raidTarget[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.triggers.args.raidTarget.args.types = ACH:Group('')
StyleFilters.triggers.args.raidTarget.args.types.inline = true
for i, iconName in next, E.NamePlates.TriggerConditions.raidTargets do
StyleFilters.triggers.args.raidTarget.args.types.args[iconName] = ACH:Toggle(format(raidTargetIcon, i, L["RAID_TARGET_"..i]), nil, i)
end
local actionDefaults = {
color = {
healthColor = { r = 0.53, g = 1.00, b = 0.40, a = 1 },
powerColor = { r = 0.40, g = 0.53, b = 1.00, a = 1 },
borderColor = { r = 0, g = 0, b = 0, a = 1}
},
flash = {
color = { r = 0.41, g = 0.54, b = 0.85, a = 1 },
speed = 4
},
}
local function actionHidePlate() local _, actions = GetFilter(true) return actions.hide end
local function actionSubGroup(info, ...)
local _, actions = GetFilter(true)
if not actions then return end
if info.type == 'color' then
local t = actions[info[#info-1]][info[#info]]
local r, g, b, a = ...
if r then
t.r, t.g, t.b, t.a = r, g, b, a
else
local d = actionDefaults[info[#info-1]][info[#info]]
return t.r, t.g, t.b, t.a, d.r, d.g, d.b, d.a
end
else
local value = ...
if value ~= nil then
actions[info[#info-1]][info[#info]] = value
else
return actions[info[#info-1]][info[#info]]
end
end
NP:ConfigureAll()
end
StyleFilters.actions = ACH:Group(L["Actions"], nil, 10, nil, function(info) local _, actions = GetFilter(true) return actions[info[#info]] end, function(info, value) local _, actions = GetFilter(true) actions[info[#info]] = value NP:ConfigureAll() end, DisabledFilter)
StyleFilters.actions.args.hide = ACH:Toggle(L["Hide Frame"], nil, 1)
StyleFilters.actions.args.usePortrait = ACH:Toggle(L["Use Portrait"], nil, 2, nil, nil, nil, nil, nil, actionHidePlate)
StyleFilters.actions.args.nameOnly = ACH:Toggle(L["Name Only"], nil, 3, nil, nil, nil, nil, nil, actionHidePlate)
StyleFilters.actions.args.spacer1 = ACH:Spacer(4, 'full')
StyleFilters.actions.args.scale = ACH:Range(L["Scale"], nil, 5, { min = .25, max = 1.5, softMin = .5, softMax = 1.25, step = .01 }, nil, nil, nil, actionHidePlate)
StyleFilters.actions.args.alpha = ACH:Range(L["Alpha"], L["Change the alpha level of the frame."], 6, { min = -1, max = 100, step = 1 }, nil, nil, nil, actionHidePlate)
StyleFilters.actions.args.color = ACH:Group(L["COLOR"], nil, 10, nil, actionSubGroup, actionSubGroup, actionHidePlate)
StyleFilters.actions.args.color.inline = true
StyleFilters.actions.args.color.args.health = ACH:Toggle(L["Health"], nil, 1)
StyleFilters.actions.args.color.args.healthColor = ACH:Color(L["Health Color"], nil, 2, true)
StyleFilters.actions.args.color.args.healthClass = ACH:Toggle(L["Unit Class Color"], nil, 3)
StyleFilters.actions.args.color.args.spacer1 = ACH:Spacer(4, 'full')
StyleFilters.actions.args.color.args.power = ACH:Toggle(L["Power"], nil, 10)
StyleFilters.actions.args.color.args.powerColor = ACH:Color(L["Power Color"], nil, 11, true)
StyleFilters.actions.args.color.args.powerClass = ACH:Toggle(L["Unit Class Color"], nil, 12)
StyleFilters.actions.args.color.args.spacer2 = ACH:Spacer(13, 'full')
StyleFilters.actions.args.color.args.border = ACH:Toggle(L["Border"], nil, 20)
StyleFilters.actions.args.color.args.borderColor = ACH:Color(L["Border Color"], nil, 21, true)
StyleFilters.actions.args.color.args.borderClass = ACH:Toggle(L["Unit Class Color"], nil, 22)
StyleFilters.actions.args.texture = ACH:Group(L["Texture"], nil, 20, nil, actionSubGroup, actionSubGroup, actionHidePlate)
StyleFilters.actions.args.texture.inline = true
StyleFilters.actions.args.texture.args.enable = ACH:Toggle(L["Enable"], nil, 1)
StyleFilters.actions.args.texture.args.texture = ACH:SharedMediaStatusbar(L["Texture"], nil, 2, nil, nil, nil, function() local _, actions = GetFilter(true) return not actions.texture.enable end)
StyleFilters.actions.args.flash = ACH:Group(L["Flash"], nil, 30, nil, actionSubGroup, actionSubGroup, actionHidePlate)
StyleFilters.actions.args.flash.inline = true
StyleFilters.actions.args.flash.args.enable = ACH:Toggle(L["Enable"], nil, 1)
StyleFilters.actions.args.flash.args.color = ACH:Color(L["COLOR"], nil, 2, true)
StyleFilters.actions.args.flash.args.class = ACH:Toggle(L["Unit Class Color"], nil, 3)
StyleFilters.actions.args.flash.args.speed = ACH:Range(L["SPEED"], nil, nil, { min = 1, max = 10, step = 1 })
StyleFilters.actions.args.text_format = ACH:Group(L["Text Format"], nil, 40, nil, function(info) local _, actions = GetFilter(true) return actions.tags[info[#info]] end, function(info, value) local _, actions = GetFilter(true) actions.tags[info[#info]] = value NP:ConfigureAll() end)
StyleFilters.actions.args.text_format.inline = true
StyleFilters.actions.args.text_format.args.info = ACH:Description(L["Controls the text displayed. Tags are available in the Available Tags section of the config."], 1, 'medium')
StyleFilters.actions.args.text_format.args.name = ACH:Input(L["Name"], nil, 1, nil, 'full')
StyleFilters.actions.args.text_format.args.level = ACH:Input(L["Level"], nil, 2, nil, 'full')
StyleFilters.actions.args.text_format.args.title = ACH:Input(L["Title"], nil, 3, nil, 'full')
StyleFilters.actions.args.text_format.args.health = ACH:Input(L["Health"], nil, 4, nil, 'full')
StyleFilters.actions.args.text_format.args.power = ACH:Input(L["Power"], nil, 5, nil, 'full')
-- Import / Export
local function DecodeString(text)
local profileType, profileKey, profileData = D:Decode(text)
if profileType == 'styleFilters' then
local decodedText = (profileData and E:TableToLuaString(profileData)) or nil
return D:CreateProfileExport(decodedText, profileType, profileKey)
else
return ''
end
end
local function DecodeLabel(label, text)
if not validateString(nil, text) then
label.name = ''
return text
end
local decode = DecodeString(text)
if decode then
return decode
else
label.name = L["Error decoding data. Import string may be corrupted!"]
return text
end
end
do
local importText = ''
local label = ACH:Description('', 1)
local function Import_Set(_, val) importText = val end
local function Import_Get() return importText end
local function Import_Decode() importText = DecodeLabel(label, importText) end
local function Import_Button()
if not validateString(nil, importText) then return end
label.name = (D:Decode(importText) == 'styleFilters' and D:ImportProfile(importText) and L["Profile imported successfully!"]) or L["Error decoding data. Import string may be corrupted!"]
end
StyleFilters.import = ACH:Group(L["Import"], nil, 15)
StyleFilters.import.args.label = label
StyleFilters.import.args.text = ACH:Input('', nil, 1, 10, 'full', Import_Get, Import_Set)
StyleFilters.import.args.importButton = ACH:Execute(L["Import"], nil, 2, Import_Button)
StyleFilters.import.args.importDecode = ACH:Execute(L["Decode"], nil, 3, Import_Decode)
end
do
local exportText = ''
local exportPrefix = '!E1!'
local label = ACH:Description('', 5)
local function Filters_Empty() if not next(exportList) then StyleFilters.export.args.text.hidden = true return true end end
local function Filters_Get(_, key) Filters_Empty() return exportList[key] end
local function Filters_Set(_, key, value) exportList[key] = value or nil end
local function Export_Get() label.name = '' return exportText end
local function Export_Set() end
local function Export_Decode() exportText = DecodeLabel(label, exportText) end
local function Export_Button()
local data = {nameplates = {filters = {}}}
if Filters_Empty() then return end
for key in pairs(exportList) do
data.nameplates.filters[key] = E:CopyTable({}, E.global.nameplates.filters[key])
end
NP:StyleFilterClearDefaults(data.nameplates.filters)
data = E:RemoveTableDuplicates(data, G, D.GeneratedKeys.global)
local serialData = D:Serialize(data)
local exportString = D:CreateProfileExport(serialData, 'styleFilters', 'styleFilters')
local compressedData = LibDeflate:CompressDeflate(exportString, LibDeflate.compressLevel)
local printableString = LibDeflate:EncodeForPrint(compressedData)
exportText = printableString and format('%s%s', exportPrefix, printableString) or nil
StyleFilters.export.args.text.hidden = not exportText
end
StyleFilters.export = ACH:Group(L["Export"], nil, 20)
StyleFilters.export.args.filters = ACH:MultiSelect(L["Filters"], nil, 2, GetFilters, nil, nil, Filters_Get, Filters_Set)
StyleFilters.export.args.filters.sortByValue = true
StyleFilters.export.args.exportButton = ACH:Execute(L["Export"], nil, 3, Export_Button)
StyleFilters.export.args.exportDecode = ACH:Execute(L["Decode"], nil, 4, Export_Decode)
StyleFilters.export.args.label = label
StyleFilters.export.args.text = ACH:Input('', nil, -1, 10, 'full', Export_Get, Export_Set, nil, true)
end
+63 -64
View File
@@ -1,72 +1,71 @@
local E, _, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB local E, _, V, P, G = unpack(ElvUI)
local _, L = unpack(select(2, ...)) local C, L = unpack(select(2, ...))
local ACH = E.Libs.ACH
local _G = _G
local format = format local format = format
E.Options.args.tagGroup = { local TagGroup = ACH:Group(L["Available Tags"], nil, 19)
order = 925, TagGroup.args.GuideLink = ACH:Input(L["Guide:"], nil, 1, nil, 310, function() return 'https://github.com/tukui-org/ElvUI/wiki/custom-texts' end)
type = "group", TagGroup.args.WikiLink = ACH:Input(L["Wiki:"], nil, 2, nil, 290, function() return 'https://github.com/tukui-org/ElvUI/wiki' end)
name = L["Available Tags"], TagGroup.args.ColorWheel = ACH:Execute(L["Color Picker"], nil, 3, function() _G.ColorPickerFrame:Show() _G.ColorPickerFrame:SetFrameStrata('FULLSCREEN_DIALOG') _G.ColorPickerFrame:SetClampedToScreen(true) _G.ColorPickerFrame:Raise() end, nil, nil, 120)
childGroups = "tab", TagGroup.args.description = ACH:Description(L["|cffFF3333This is for information. This will not change the tags in the UI.|r"], 4, 'large')
args = { TagGroup.args.spacer = ACH:Spacer(5)
link = {
order = 1,
type = "input",
width = "full",
name = L["Guide:"],
get = function() return "https://www.tukui.org/forum/viewtopic.php?f=9&t=6" end,
},
header = {
order = 2,
type = "header",
name = L["Available Tags"],
},
Colors = {
type = "group",
name = "Colors",
args = {
header = {
order = 0,
type = "header",
name = E.InfoColor.."Colors",
},
customTagColorInfo = {
order = 1,
type = "input",
width = "full",
name = "Custom color your Text: replace the XXXXXX with a Hex color code",
get = function() return "||cffXXXXXX [tags] or text here ||r" end
}
}
},
},
}
for Tag in next, E.oUF.Tags.Methods do TagGroup.args.Colors = ACH:Group(L["Colors"])
if not E.TagInfo[Tag] then TagGroup.args.Colors.args.customTagColorInfo = ACH:Input('Color your tag or text by replacing the XXXXXX with a hex color code. (Name tag as red text. Ex: ||cffFF0000[name]||r)', nil, 1, nil, 'full', function() return '||cffXXXXXX [tag] or text here ||r' end)
E.TagInfo[Tag] = {category = "Miscellaneous", description = ""}
--E:Print("['"..Tag.."'] = { category = 'Miscellaneous', description = '' }") TagGroup.args.Names = ACH:Group(L["Names"])
TagGroup.args.Names.args.nameHealthInfo1 = ACH:Input('|cFF666666[1/5]|r White name text, missing hp red', nil, 1, nil, 'full', function() return '[name:health]' end)
TagGroup.args.Names.args.nameHealthInfo2 = ACH:Input('|cFF666666[2/5]|r Class color name text, missing hp red', nil, 2, nil, 'full', function() return '[name:health{class}]' end)
TagGroup.args.Names.args.nameHealthInfo3 = ACH:Input('|cFF666666[3/5]|r Class color name text, missing hp based on hex code', nil, 3, nil, 'full', function() return '[name:health{class:00ff00}]' end)
TagGroup.args.Names.args.nameHealthInfo4 = ACH:Input('|cFF666666[4/5]|r Name text based on hex code, missing hp red', nil, 4, nil, 'full', function() return '[name:health{00ff00}]' end)
TagGroup.args.Names.args.nameHealthInfo5 = ACH:Input('|cFF666666[5/5]|r Name text based on hex code, missing hp class color', nil, 5, nil, 'full', function() return '[name:health{00ff00:class}]' end)
local getTag = function(info) return format('[%s]', info[#info]) end
local groups = {}
for _, which in pairs({'Events','OnUpdateThrottle'}) do
for Tag in next, E.oUF.Tags[which] do
local info = E.TagInfo[Tag] or E:AddTagInfo(Tag, 'Miscellaneous')
local group = TagGroup.args[info.category]
if not group then
group = { name = info.category, type = 'group', args = {} }
TagGroup.args[info.category] = group
groups[info.category] = group
end
local input = group.args[Tag] or {}
input.name = info.description ~= '' and info.description or getTag
input.order = info.order or nil
input.width = 'full'
input.type = 'input'
input.hidden = info.hidden
input.get = getTag
group.args[Tag] = input
end end
end
if not E.Options.args.tagGroup.args[E.TagInfo[Tag].category] then -- hide groups when all their inputs are hidden
E.Options.args.tagGroup.args[E.TagInfo[Tag].category] = { for _, group in pairs(groups) do
type = "group", local hide = true
name = E.TagInfo[Tag].category, for _, section in pairs(group.args) do
args = { if section.type ~= 'input' or not section.hidden then
header = { hide = false
order = 0, break
type = "header", end
name = E.InfoColor..E.TagInfo[Tag].category,
}
}
}
end end
if hide then
group.hidden = true
end
end
E.Options.args.tagGroup.args[E.TagInfo[Tag].category].args[Tag] = { E.Options.args.tagGroup = TagGroup
type = "input",
name = E.TagInfo[Tag].description, --[[ THIS SHOULD BE EXECUTED IN THE LAST LOADED CONFIG FILE, AT THE BOTTOM
order = E.TagInfo[Tag].order or nil, NOTE: This is used to make sure Plugins use no less than the options order we want. ]]
width = "full", E.OriginalOptions = {'plugins'}
get = function() return format("[%s]", Tag) end, for key in pairs(E.Options.args) do table.insert(E.OriginalOptions, key) end
} setmetatable(E.OriginalOptions, {__newindex = E.noop})
end
+5 -2
View File
@@ -4205,8 +4205,6 @@ E.Options.args.unitframe.args.player = {
health = GetOptionsTable_Health(false, UF.CreateAndUpdateUF, "player"), health = GetOptionsTable_Health(false, UF.CreateAndUpdateUF, "player"),
infoPanel = GetOptionsTable_InformationPanel(UF.CreateAndUpdateUF, "player"), infoPanel = GetOptionsTable_InformationPanel(UF.CreateAndUpdateUF, "player"),
power = GetOptionsTable_Power(true, UF.CreateAndUpdateUF, "player", nil, true), power = GetOptionsTable_Power(true, UF.CreateAndUpdateUF, "player", nil, true),
energy = GetOptionsTable_Energy(true, UF.CreateAndUpdateUF, "player", nil, true),
rage = GetOptionsTable_Rage(true, UF.CreateAndUpdateUF, "player", nil, true),
name = GetOptionsTable_Name(UF.CreateAndUpdateUF, "player"), name = GetOptionsTable_Name(UF.CreateAndUpdateUF, "player"),
portrait = GetOptionsTable_Portrait(UF.CreateAndUpdateUF, "player"), portrait = GetOptionsTable_Portrait(UF.CreateAndUpdateUF, "player"),
fader = GetOptionsTable_Fader(UF.CreateAndUpdateUF, "player"), fader = GetOptionsTable_Fader(UF.CreateAndUpdateUF, "player"),
@@ -4703,6 +4701,11 @@ E.Options.args.unitframe.args.player = {
} }
} }
if C_Player:IsHero() then
E.Options.args.unitframe.args.player.args.energy = GetOptionsTable_Energy(true, UF.CreateAndUpdateUF, "player", nil, true)
E.Options.args.unitframe.args.player.args.rage = GetOptionsTable_Rage(true, UF.CreateAndUpdateUF, "player", nil, true)
end
--Target Frame --Target Frame
E.Options.args.unitframe.args.target = { E.Options.args.unitframe.args.target = {
order = 400, order = 400,