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:
@@ -539,7 +539,6 @@ function AB:StyleButton(button, noBackdrop, useMasque)
|
||||
|
||||
if macroText then
|
||||
macroText:ClearAllPoints()
|
||||
macroText:SetWidth(self.db.fontWidth)
|
||||
macroText:Point("BOTTOM", 0, 1)
|
||||
macroText:FontTemplate(LSM:Fetch("font", self.db.font), self.db.fontSize, self.db.fontOutline)
|
||||
macroText:SetTextColor(color.r, color.g, color.b)
|
||||
@@ -995,4 +994,4 @@ local function InitializeCallback()
|
||||
AB:Initialize()
|
||||
end
|
||||
|
||||
E:RegisterModule(AB:GetName(), InitializeCallback)
|
||||
E:RegisterModule(AB:GetName(), InitializeCallback)
|
||||
@@ -17,6 +17,7 @@ local MICRO_BUTTONS = {
|
||||
"SocialsMicroButton",
|
||||
"PVPMicroButton",
|
||||
"LFDMicroButton",
|
||||
"ChallengesMicroButton",
|
||||
"MainMenuMicroButton",
|
||||
"HelpMicroButton"
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ do
|
||||
end
|
||||
|
||||
do
|
||||
local interruptMsg = INTERRUPTED.." %s's \124cff71d5ff\124Hspell:%d\124h[%s]\124h\124r!"
|
||||
local interruptMsg = " "..INTERRUPTED.." %s's \124cff71d5ff\124Hspell:%d\124h[%s]\124h\124r!"
|
||||
|
||||
function M:ToggleInterruptAnnounce()
|
||||
if E.db.general.interruptAnnounce == "NONE" then
|
||||
|
||||
@@ -1,463 +1,188 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local NP = E:GetModule("NamePlates")
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local UF = E:GetModule('UnitFrames')
|
||||
local LSM = E.Libs.LSM
|
||||
local LAI = E.Libs.LAI
|
||||
|
||||
--Lua functions
|
||||
local select, unpack, pairs = select, unpack, pairs
|
||||
local band = bit.band
|
||||
local tinsert = table.insert
|
||||
local floor = math.floor
|
||||
local split = string.split
|
||||
--WoW API / Variables
|
||||
local _G = _G
|
||||
local wipe = wipe
|
||||
local unpack = unpack
|
||||
local CreateFrame = CreateFrame
|
||||
local GetSpellInfo = GetSpellInfo
|
||||
local GetTime = GetTime
|
||||
|
||||
local CREATED, VISIBLE, HIDDEN = 2, 1, 0
|
||||
function NP:Construct_Auras(nameplate)
|
||||
local frameName = nameplate:GetName()
|
||||
|
||||
local positionValues = {
|
||||
BOTTOMLEFT = "TOP",
|
||||
BOTTOMRIGHT = "TOP",
|
||||
LEFT = "RIGHT",
|
||||
RIGHT = "LEFT",
|
||||
TOPLEFT = "BOTTOM",
|
||||
TOPRIGHT = "BOTTOM"
|
||||
}
|
||||
local Buffs = CreateFrame('Frame', frameName..'Buffs', nameplate)
|
||||
Buffs:Size(1, 1)
|
||||
Buffs.size = 27
|
||||
Buffs.num = 4
|
||||
Buffs.spacing = E.Border * 2
|
||||
Buffs.onlyShowPlayer = false
|
||||
Buffs.disableMouse = true
|
||||
Buffs.isNamePlate = nameplate
|
||||
|
||||
local positionValues2 = {
|
||||
BOTTOMLEFT = "BOTTOM",
|
||||
BOTTOMRIGHT = "BOTTOM",
|
||||
LEFT = "LEFT",
|
||||
RIGHT = "RIGHT",
|
||||
TOPLEFT = "TOP",
|
||||
TOPRIGHT = "TOP"
|
||||
}
|
||||
Buffs.initialAnchor = 'BOTTOMLEFT'
|
||||
Buffs.growthX = 'RIGHT'
|
||||
Buffs.growthY = 'UP'
|
||||
Buffs.type = 'buffs'
|
||||
Buffs.forceShow = nameplate == _G.ElvNP_Test
|
||||
Buffs.tickers = {} -- StyleFilters
|
||||
Buffs.stacks = {}
|
||||
Buffs.rows = {}
|
||||
|
||||
local Debuffs = CreateFrame('Frame', frameName..'Debuffs', nameplate)
|
||||
Debuffs:Size(1, 1)
|
||||
Debuffs.size = 27
|
||||
Debuffs.num = 4
|
||||
Debuffs.spacing = E.Border * 2
|
||||
Debuffs.onlyShowPlayer = false
|
||||
Debuffs.disableMouse = true
|
||||
Debuffs.isNamePlate = nameplate
|
||||
Debuffs.initialAnchor = 'BOTTOMLEFT'
|
||||
Debuffs.growthX = 'RIGHT'
|
||||
Debuffs.growthY = 'UP'
|
||||
Debuffs.type = 'debuffs'
|
||||
Debuffs.forceShow = nameplate == _G.ElvNP_Test
|
||||
Debuffs.tickers = {} -- StyleFilters
|
||||
Debuffs.stacks = {}
|
||||
Debuffs.rows = {}
|
||||
|
||||
local RaidIconBit = {
|
||||
["STAR"] = 0x00100000,
|
||||
["CIRCLE"] = 0x00200000,
|
||||
["DIAMOND"] = 0x00400000,
|
||||
["TRIANGLE"] = 0x00800000,
|
||||
["MOON"] = 0x01000000,
|
||||
["SQUARE"] = 0x02000000,
|
||||
["CROSS"] = 0x04000000,
|
||||
["SKULL"] = 0x08000000
|
||||
}
|
||||
Buffs.PreUpdate = UF.PreUpdateAura
|
||||
Buffs.PreSetPosition = UF.SortAuras
|
||||
Buffs.SetPosition = UF.SetPosition
|
||||
Buffs.PostCreateIcon = NP.Construct_AuraIcon
|
||||
Buffs.PostUpdateIcon = UF.PostUpdateAura
|
||||
Buffs.CustomFilter = UF.AuraFilter
|
||||
|
||||
local ByRaidIcon = {}
|
||||
Debuffs.PreUpdate = UF.PreUpdateAura
|
||||
Debuffs.PreSetPosition = UF.SortAuras
|
||||
Debuffs.SetPosition = UF.SetPosition
|
||||
Debuffs.PostCreateIcon = NP.Construct_AuraIcon
|
||||
Debuffs.PostUpdateIcon = UF.PostUpdateAura
|
||||
Debuffs.CustomFilter = UF.AuraFilter
|
||||
|
||||
function NP:LibAuraInfo_AURA_APPLIED(event, destGUID)
|
||||
self:UpdateElement_AurasByGUID(destGUID, event)
|
||||
nameplate.Buffs_, nameplate.Debuffs_ = Buffs, Debuffs
|
||||
nameplate.Buffs, nameplate.Debuffs = Buffs, Debuffs
|
||||
end
|
||||
|
||||
function NP:LibAuraInfo_AURA_REMOVED(event, destGUID)
|
||||
self:UpdateElement_AurasByGUID(destGUID, event)
|
||||
end
|
||||
function NP:Construct_AuraIcon(button)
|
||||
if not button then return end
|
||||
|
||||
function NP:LibAuraInfo_AURA_REFRESH(event, destGUID)
|
||||
self:LibAuraInfo_AURA_APPLIED(event, destGUID)
|
||||
end
|
||||
button:SetTemplate(nil, nil, nil, nil, nil, true, true)
|
||||
|
||||
function NP:LibAuraInfo_AURA_APPLIED_DOSE(event, destGUID)
|
||||
self:LibAuraInfo_AURA_APPLIED(event, destGUID)
|
||||
end
|
||||
button.cd:SetReverse(true)
|
||||
button.cd:SetInside(button)
|
||||
|
||||
function NP:LibAuraInfo_AURA_CLEAR(event, destGUID)
|
||||
self:UpdateElement_AurasByGUID(destGUID, event)
|
||||
end
|
||||
button.icon:SetDrawLayer('ARTWORK')
|
||||
button.icon:SetInside()
|
||||
|
||||
function NP:LibAuraInfo_UNIT_AURA(event, destGUID)
|
||||
self:UpdateElement_AurasByGUID(destGUID, event)
|
||||
end
|
||||
button.count:ClearAllPoints()
|
||||
button.count:Point('BOTTOMRIGHT', 1, 1)
|
||||
button.count:SetJustifyH('RIGHT')
|
||||
|
||||
function NP:UpdateTime(elapsed)
|
||||
self.timeLeft = self.timeLeft - elapsed
|
||||
self:SetValue(self.timeLeft)
|
||||
button.overlay:SetTexture()
|
||||
button.stealable:SetTexture()
|
||||
|
||||
button.isNamePlate = true
|
||||
|
||||
if self.nextUpdate > 0 then
|
||||
self.nextUpdate = self.nextUpdate - elapsed
|
||||
return
|
||||
E:RegisterCooldown(button.cd, 'nameplates')
|
||||
|
||||
local auras = button:GetParent()
|
||||
if auras and auras.type then
|
||||
local db = NP:PlateDB(auras.__owner)
|
||||
button.db = db[auras.type]
|
||||
end
|
||||
|
||||
if self.timeLeft < 0 then
|
||||
self:SetScript("OnUpdate", nil)
|
||||
self:Hide()
|
||||
return
|
||||
end
|
||||
|
||||
local value, id, nextUpdate, remainder = E:GetTimeInfo(self.timeLeft, self.threshold, self.hhmmThreshold, self.mmssThreshold)
|
||||
self.nextUpdate = nextUpdate
|
||||
|
||||
local style = E.TimeFormats[id]
|
||||
if style then
|
||||
local which = (self.textColors and 2 or 1) + (self.showSeconds and 0 or 2)
|
||||
if self.textColors then
|
||||
self.text:SetFormattedText(style[which], value, self.textColors[id], remainder)
|
||||
else
|
||||
self.text:SetFormattedText(style[which], value, remainder)
|
||||
end
|
||||
end
|
||||
|
||||
local color = self.timeColors[id]
|
||||
if color then
|
||||
self.text:SetTextColor(color.r, color.g, color.b)
|
||||
end
|
||||
NP:UpdateAuraSettings(button)
|
||||
end
|
||||
|
||||
local unstableAffliction = GetSpellInfo(30108)
|
||||
local vampiricTouch = GetSpellInfo(34914)
|
||||
function NP:SetAura(frame, guid, index, filter, isDebuff, visible)
|
||||
local isAura, name, texture, count, debuffType, duration, expiration, caster, spellID, _ = LAI:GUIDAura(guid, index, filter)
|
||||
function NP:Configure_Auras(nameplate, auras, db)
|
||||
auras.size = db.size
|
||||
auras.height = not db.keepSizeRatio and db.height
|
||||
auras.numAuras = db.numAuras
|
||||
auras.numRows = db.numRows
|
||||
auras.onlyShowPlayer = false
|
||||
auras.spacing = db.spacing
|
||||
auras.growthY = UF.MatchGrowthY[db.anchorPoint] or db.growthY
|
||||
auras.growthX = UF.MatchGrowthX[db.anchorPoint] or db.growthX
|
||||
auras.xOffset = db.xOffset
|
||||
auras.yOffset = db.yOffset
|
||||
auras.anchorPoint = db.anchorPoint
|
||||
auras.auraSort = UF.SortAuraFuncs[db.sortMethod]
|
||||
auras.initialAnchor = E.InversePoints[db.anchorPoint]
|
||||
auras.filterList = UF:ConvertFilters(auras, db.priority)
|
||||
auras.smartPosition, auras.smartFluid = UF:SetSmartPosition(nameplate)
|
||||
auras.attachTo = UF:GetAuraAnchorFrame(nameplate, db.attachTo) -- keep below SetSmartPosition
|
||||
auras.num = db.numAuras * db.numRows
|
||||
auras.db = db -- for auraSort
|
||||
|
||||
if frame.forceShow or frame.forceCreate then
|
||||
spellID = 47540
|
||||
name, _, texture = GetSpellInfo(spellID)
|
||||
if frame.forceShow then
|
||||
isAura, count, debuffType, duration, expiration = true, 5, "Magic", 0, 0
|
||||
end
|
||||
end
|
||||
|
||||
if isAura then
|
||||
local position = visible + 1
|
||||
local button = frame[position] or NP:Construct_AuraIcon(frame, position)
|
||||
|
||||
button.caster = caster
|
||||
button.filter = filter
|
||||
button.isDebuff = isDebuff
|
||||
|
||||
local filterCheck = not frame.forceCreate
|
||||
if not (frame.forceShow or frame.forceCreate) then
|
||||
filterCheck = NP:AuraFilter(guid, button, name, texture, count, debuffType, duration, expiration, caster, spellID)
|
||||
local index = 1
|
||||
while auras[index] do
|
||||
local button = auras[index]
|
||||
if button then
|
||||
button.db = db
|
||||
NP:UpdateAuraSettings(button)
|
||||
button:SetBackdropBorderColor(unpack(E.media.bordercolor))
|
||||
end
|
||||
|
||||
if filterCheck then
|
||||
if button.icon then button.icon:SetTexture(texture) end
|
||||
if button.count then button.count:SetText(count > 1 and count) end
|
||||
|
||||
if duration > 0 and expiration ~= 0 then
|
||||
local timeLeft = expiration - GetTime()
|
||||
if timeLeft > 0 then
|
||||
button.timeLeft = timeLeft
|
||||
button.nextUpdate = 0
|
||||
|
||||
button:SetMinMaxValues(0, duration)
|
||||
button:SetValue(timeLeft)
|
||||
|
||||
button:SetScript("OnUpdate", NP.UpdateTime)
|
||||
-- else
|
||||
-- return HIDDEN
|
||||
end
|
||||
else
|
||||
button.timeLeft = nil
|
||||
button.text:SetText("")
|
||||
button:SetScript("OnUpdate", nil)
|
||||
button:SetMinMaxValues(0, 1)
|
||||
button:SetValue(0)
|
||||
end
|
||||
|
||||
button:SetID(index)
|
||||
button:Show()
|
||||
|
||||
if isDebuff then
|
||||
local color = (debuffType and DebuffTypeColor[debuffType]) or DebuffTypeColor.none
|
||||
if button.name and (button.name == unstableAffliction or button.name == vampiricTouch) then
|
||||
self:StyleFrameColor(button, 0.05, 0.85, 0.94)
|
||||
else
|
||||
self:StyleFrameColor(button, color.r * 0.6, color.g * 0.6, color.b * 0.6)
|
||||
end
|
||||
end
|
||||
|
||||
return VISIBLE
|
||||
elseif frame.forceCreate then
|
||||
button:Hide()
|
||||
|
||||
return CREATED
|
||||
else
|
||||
return HIDDEN
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Update_AurasPosition(frame, db)
|
||||
local size = db.size + db.spacing
|
||||
local anchor = E.InversePoints[db.anchorPoint]
|
||||
local growthx = (db.growthX == "LEFT" and -1) or 1
|
||||
local growthy = (db.growthY == "DOWN" and -1) or 1
|
||||
local cols = db.perrow
|
||||
|
||||
for i = frame.anchoredIcons + 1, #frame do
|
||||
local button = frame[i]
|
||||
if not button then break end
|
||||
|
||||
local col = (i - 1) % cols
|
||||
local row = floor((i - 1) / cols)
|
||||
|
||||
button:SetSize(db.size, db.size)
|
||||
button:ClearAllPoints()
|
||||
button:SetPoint(anchor, frame, anchor, col * size * growthx, row * size * growthy)
|
||||
|
||||
button.count:FontTemplate(LSM:Fetch("font", db.countFont), db.countFontSize, db.countFontOutline)
|
||||
button.count:ClearAllPoints()
|
||||
button.count:SetPoint(db.countPosition, db.countXOffset, db.countYOffset)
|
||||
|
||||
button.text:FontTemplate(LSM:Fetch("font", db.durationFont), db.durationFontSize, db.durationFontOutline)
|
||||
button.text:ClearAllPoints()
|
||||
button.text:SetPoint(db.durationPosition, db.durationXOffset, db.durationYOffset)
|
||||
|
||||
button:SetOrientation(db.cooldownOrientation)
|
||||
|
||||
button.bg:ClearAllPoints()
|
||||
if db.cooldownOrientation == "VERTICAL" then
|
||||
button.bg:SetPoint("TOPLEFT", button)
|
||||
button.bg:SetPoint("BOTTOMRIGHT", button:GetStatusBarTexture(), "TOPRIGHT")
|
||||
else
|
||||
button.bg:SetPoint("TOPRIGHT", button)
|
||||
button.bg:SetPoint("BOTTOMLEFT", button:GetStatusBarTexture(), "BOTTOMRIGHT")
|
||||
end
|
||||
|
||||
if db.reverseCooldown then
|
||||
button:SetStatusBarColor(0, 0, 0, 0.5)
|
||||
button.bg:SetTexture(0, 0, 0, 0)
|
||||
else
|
||||
button:SetStatusBarColor(0, 0, 0, 0)
|
||||
button.bg:SetTexture(0, 0, 0, 0.5)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:UpdateElement_AuraIcons(frame, guid, filter, limit, isDebuff)
|
||||
local index, visible, hidden, created = 1, 0, 0, 0
|
||||
|
||||
while visible < limit do
|
||||
local result = NP:SetAura(frame, guid, index, filter, isDebuff, visible)
|
||||
if not result then
|
||||
break
|
||||
elseif result == HIDDEN then
|
||||
hidden = hidden + 1
|
||||
elseif result == VISIBLE then
|
||||
visible = visible + 1
|
||||
elseif result == CREATED then
|
||||
visible = visible + 1
|
||||
created = created + 1
|
||||
end
|
||||
index = index + 1
|
||||
end
|
||||
|
||||
visible = visible - created
|
||||
|
||||
for i = visible + 1, #frame do
|
||||
frame[i].timeLeft = nil
|
||||
frame[i]:SetScript("OnUpdate", nil)
|
||||
frame[i]:Hide()
|
||||
end
|
||||
return visible
|
||||
end
|
||||
|
||||
function NP:UpdateElement_Auras(frame)
|
||||
if not frame.Health:IsShown() then return end
|
||||
|
||||
local guid = frame.guid
|
||||
|
||||
if not guid then
|
||||
if frame.UnitClass == "HERO" then
|
||||
local name = frame.UnitName
|
||||
guid = self.GUIDByName[name]
|
||||
elseif frame.RaidIcon:IsShown() then
|
||||
guid = ByRaidIcon[frame.RaidIconType]
|
||||
end
|
||||
|
||||
if guid then
|
||||
frame.guid = guid
|
||||
elseif not frame.Buffs.forceShow and not frame.Debuffs.forceShow then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local db = NP.db.units[frame.UnitType].buffs
|
||||
if db.enable then
|
||||
local buffs = frame.Buffs
|
||||
buffs.visibleBuffs = NP:UpdateElement_AuraIcons(buffs, guid, buffs.filter or "HELPFUL", db.perrow * db.numrows)
|
||||
|
||||
if #buffs > buffs.anchoredIcons then
|
||||
self:Update_AurasPosition(buffs, db)
|
||||
|
||||
buffs.anchoredIcons = #buffs
|
||||
end
|
||||
end
|
||||
|
||||
db = NP.db.units[frame.UnitType].debuffs
|
||||
if db.enable then
|
||||
local debuffs = frame.Debuffs
|
||||
debuffs.visibleDebuffs = NP:UpdateElement_AuraIcons(debuffs, guid, debuffs.filter or "HARMFUL", db.perrow * db.numrows, true)
|
||||
|
||||
if #debuffs > debuffs.anchoredIcons then
|
||||
self:Update_AurasPosition(debuffs, db)
|
||||
|
||||
debuffs.anchoredIcons = #debuffs
|
||||
end
|
||||
end
|
||||
|
||||
self:StyleFilterUpdate(frame, "UNIT_AURA")
|
||||
end
|
||||
|
||||
function NP:UpdateElement_AurasByGUID(guid, event)
|
||||
local destName, destFlags = LAI:GetGUIDInfo(guid)
|
||||
|
||||
if destName then
|
||||
destName = split("-", destName)
|
||||
end
|
||||
|
||||
local raidIcon
|
||||
if destFlags then
|
||||
for iconName, bitmask in pairs(RaidIconBit) do
|
||||
if band(destFlags, bitmask) > 0 then
|
||||
ByRaidIcon[iconName] = guid
|
||||
raidIcon = iconName
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local frame = self:SearchForFrame(guid, raidIcon, destName)
|
||||
if frame then
|
||||
frame.guid = guid
|
||||
self.GUIDByName[destName] = guid
|
||||
self:UpdateElement_Auras(frame)
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_AuraIcon(parent, index)
|
||||
local db = NP.db.units[parent:GetParent().UnitType][parent.type]
|
||||
|
||||
local button = CreateFrame("StatusBar", "$parentButton"..index, parent)
|
||||
NP:StyleFrame(button, true)
|
||||
|
||||
button:SetStatusBarTexture(E.media.blankTex)
|
||||
button:SetStatusBarColor(0, 0, 0, 0)
|
||||
button:SetOrientation("VERTICAL")
|
||||
|
||||
button.bg = button:CreateTexture()
|
||||
button.bg:SetTexture(0, 0, 0, 0.5)
|
||||
|
||||
button.bg:SetPoint("TOPLEFT", button)
|
||||
button.bg:SetPoint("BOTTOMRIGHT", button:GetStatusBarTexture(), "TOPRIGHT")
|
||||
|
||||
button.icon = button:CreateTexture(nil, "BORDER")
|
||||
button.icon:SetTexCoord(unpack(E.TexCoords))
|
||||
button.icon:SetAllPoints()
|
||||
|
||||
button.count = button:CreateFontString(nil, "OVERLAY")
|
||||
button.count:SetJustifyH("RIGHT")
|
||||
button.count:FontTemplate(LSM:Fetch("font", db.countFont), db.countFontSize, db.countFontOutline)
|
||||
|
||||
button.text = button:CreateFontString(nil, "OVERLAY")
|
||||
|
||||
-- support cooldown override
|
||||
if not button.isRegisteredCooldown then
|
||||
button.CooldownOverride = "nameplates"
|
||||
button.isRegisteredCooldown = true
|
||||
button.forceEnabled = true
|
||||
|
||||
if not E.RegisteredCooldowns.nameplates then E.RegisteredCooldowns.nameplates = {} end
|
||||
tinsert(E.RegisteredCooldowns.nameplates, button)
|
||||
end
|
||||
|
||||
button.text:FontTemplate(LSM:Fetch("font", db.durationFont), db.durationFontSize, db.durationFontOutline)
|
||||
|
||||
NP:Update_CooldownOptions(button)
|
||||
|
||||
tinsert(parent, button)
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
function NP:Update_CooldownOptions(button)
|
||||
E:Cooldown_Options(button, self.db.cooldown, button)
|
||||
end
|
||||
|
||||
function NP:Configure_Auras(frame, auraType)
|
||||
local auras = frame[auraType]
|
||||
local db = self.db.units[frame.UnitType][auras.type]
|
||||
|
||||
auras:SetWidth(db.perrow * db.size + ((db.perrow - 1) * db.spacing))
|
||||
auras:SetHeight(db.numrows * db.size + ((db.numrows - 1) * db.spacing))
|
||||
auras:ClearAllPoints()
|
||||
auras:SetPoint(positionValues[db.anchorPoint], db.attachTo == "BUFFS" and frame.Buffs or frame.Health, positionValues2[db.anchorPoint], db.xOffset, db.yOffset)
|
||||
auras:Point(auras.initialAnchor, auras.attachTo, auras.anchorPoint, auras.xOffset, auras.yOffset)
|
||||
auras:Size(db.numAuras * db.size + ((db.numAuras - 1) * db.spacing), 1)
|
||||
end
|
||||
|
||||
function NP:ConstructElement_Auras(frame, auraType)
|
||||
local auras = CreateFrame("Frame", "$parent"..auraType, frame)
|
||||
auras:Show()
|
||||
auras:SetSize(150, 27)
|
||||
auras:SetPoint("TOP", 0, 22)
|
||||
auras.anchoredIcons = 0
|
||||
auras.type = string.lower(auraType)
|
||||
function NP:Update_Auras(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
return auras
|
||||
end
|
||||
|
||||
function NP:CheckFilter(name, spellID, isPlayer, allowDuration, noDuration, ...)
|
||||
for i = 1, select("#", ...) do
|
||||
local filterName = select(i, ...)
|
||||
if not filterName then return true end
|
||||
if G.nameplates.specialFilters[filterName] or E.global.unitframe.aurafilters[filterName] then
|
||||
local filter = E.global.unitframe.aurafilters[filterName]
|
||||
if filter then
|
||||
local filterType = filter.type
|
||||
local spellList = filter.spells
|
||||
local spell = spellList and (spellList[spellID] or spellList[name])
|
||||
|
||||
if filterType and (filterType == "Whitelist") and (spell and spell.enable) and allowDuration then
|
||||
return true
|
||||
elseif filterType and (filterType == "Blacklist") and (spell and spell.enable) then
|
||||
return false
|
||||
end
|
||||
elseif filterName == "Personal" and isPlayer and allowDuration then
|
||||
return true
|
||||
elseif filterName == "nonPersonal" and (not isPlayer) and allowDuration then
|
||||
return true
|
||||
elseif filterName == "blockNoDuration" and noDuration then
|
||||
return false
|
||||
elseif filterName == "blockNonPersonal" and (not isPlayer) then
|
||||
return false
|
||||
end
|
||||
if db.debuffs.enable or db.buffs.enable then
|
||||
if not nameplate:IsElementEnabled('Auras') then
|
||||
nameplate:EnableElement('Auras')
|
||||
end
|
||||
|
||||
nameplate.Buffs_:ClearAllPoints()
|
||||
nameplate.Debuffs_:ClearAllPoints()
|
||||
|
||||
if db.debuffs.enable then
|
||||
nameplate.Debuffs = nameplate.Debuffs_
|
||||
NP:Configure_Auras(nameplate, nameplate.Debuffs, db.debuffs)
|
||||
nameplate.Debuffs:Show()
|
||||
nameplate.Debuffs:ForceUpdate()
|
||||
elseif nameplate.Debuffs then
|
||||
nameplate.Debuffs:Hide()
|
||||
nameplate.Debuffs = nil
|
||||
end
|
||||
|
||||
if db.buffs.enable then
|
||||
nameplate.Buffs = nameplate.Buffs_
|
||||
NP:Configure_Auras(nameplate, nameplate.Buffs, db.buffs)
|
||||
nameplate.Buffs:Show()
|
||||
nameplate.Buffs:ForceUpdate()
|
||||
elseif nameplate.Buffs then
|
||||
nameplate.Buffs:Hide()
|
||||
nameplate.Buffs = nil
|
||||
end
|
||||
elseif nameplate:IsElementEnabled('Auras') then
|
||||
nameplate:DisableElement('Auras')
|
||||
end
|
||||
end
|
||||
|
||||
function NP:AuraFilter(guid, button, name, texture, count, debuffType, duration, expiration, caster, spellID)
|
||||
local parent = button:GetParent()
|
||||
local parentType = parent.type
|
||||
local db = NP.db.units[parent:GetParent().UnitType][parentType]
|
||||
if not db then return true end
|
||||
|
||||
local isPlayer = caster == E.myguid
|
||||
|
||||
-- keep these same as in `UF:AuraFilter`
|
||||
button.isPlayer = isPlayer
|
||||
button.dtype = debuffType
|
||||
button.duration = duration
|
||||
button.expiration = expiration
|
||||
button.stackCount = count
|
||||
button.name = name
|
||||
button.spellID = spellID
|
||||
button.spell = name
|
||||
button.priority = 0
|
||||
|
||||
if not db.filters then return true end
|
||||
|
||||
local priority = db.filters.priority
|
||||
local noDuration = (not duration or duration == 0)
|
||||
local allowDuration = noDuration or (duration and (duration > 0) and db.filters.maxDuration == 0 or duration <= db.filters.maxDuration) and (db.filters.minDuration == 0 or duration >= db.filters.minDuration)
|
||||
local filterCheck
|
||||
|
||||
if priority ~= "" then
|
||||
filterCheck = NP:CheckFilter(name, spellID, isPlayer, allowDuration, noDuration, split(",", priority))
|
||||
else
|
||||
filterCheck = allowDuration and true -- Allow all auras to be shown when the filter list is empty, while obeying duration sliders
|
||||
function NP:UpdateAuraSettings(button)
|
||||
local db = button.db
|
||||
if db then
|
||||
local point = db.countPosition or 'CENTER'
|
||||
button.count:ClearAllPoints()
|
||||
button.count:SetJustifyH(point:find('RIGHT') and 'RIGHT' or 'LEFT')
|
||||
button.count:Point(point, db.countXOffset, db.countYOffset)
|
||||
button.count:FontTemplate(LSM:Fetch('font', db.countFont), db.countFontSize, db.countFontOutline)
|
||||
end
|
||||
|
||||
return filterCheck
|
||||
end
|
||||
if button.auraInfo then
|
||||
wipe(button.auraInfo)
|
||||
else
|
||||
button.auraInfo = {}
|
||||
end
|
||||
|
||||
button.needsButtonTrim = true
|
||||
button.needsUpdateCooldownPosition = true
|
||||
end
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local UF = E:GetModule('UnitFrames')
|
||||
local AB = E:GetModule('ActionBars')
|
||||
|
||||
local _G = _G
|
||||
local wipe = wipe
|
||||
local next = next
|
||||
local pairs = pairs
|
||||
local unpack = unpack
|
||||
local GetTime = GetTime
|
||||
local UnitGUID = UnitGUID
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
NP.BossMods_ActiveUnitGUID = {}
|
||||
NP.BossMods_TextureCache = {}
|
||||
|
||||
local allowHostile = false
|
||||
function NP:BossMods_CreateIcon(element)
|
||||
element.index = not element.index and 1 or (element.index + 1)
|
||||
|
||||
local button = CreateFrame('Button', element:GetName()..'Button'..element.index, element)
|
||||
button:EnableMouse(false)
|
||||
button:SetTemplate(nil, nil, nil, nil, nil, true, true)
|
||||
|
||||
local cooldown = CreateFrame('Cooldown', '$parentCooldown', button, 'CooldownFrameTemplate')
|
||||
cooldown:SetReverse(true)
|
||||
cooldown:SetInside(button)
|
||||
E:RegisterCooldown(cooldown, 'nameplates')
|
||||
|
||||
local icon = button:CreateTexture(nil, 'ARTWORK')
|
||||
icon:SetTexCoord(unpack(E.TexCoords))
|
||||
icon:SetInside()
|
||||
|
||||
button.icon = icon
|
||||
button.cd = cooldown
|
||||
button.db = element.db
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
function NP:BossMods_GetIcon(plate, texture)
|
||||
local element, unused, avaiableIcon = plate.BossMods
|
||||
|
||||
local activeButton = element.activeIcons[texture]
|
||||
if not activeButton then
|
||||
unused, avaiableIcon = next(element.unusedIcons)
|
||||
if unused then element.unusedIcons[unused] = nil end
|
||||
end
|
||||
|
||||
local button = activeButton or avaiableIcon or NP:BossMods_CreateIcon(element)
|
||||
if not activeButton then
|
||||
element.activeIcons[texture] = button
|
||||
end
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
function NP:BossMods_PositionIcons(element)
|
||||
if not next(element.activeIcons) then return end
|
||||
|
||||
local index = 1
|
||||
local anchor, inversed, growthX, growthY, width, height, cols, point, middle = UF:GetAuraPosition(element)
|
||||
|
||||
element.currentRow = nil -- clear this for a new update
|
||||
|
||||
for _, button in pairs(element.activeIcons) do
|
||||
UF:SetAuraPosition(element, button, index, anchor, inversed, growthX, growthY, width, height, cols, point, middle)
|
||||
|
||||
button:Size(width, height)
|
||||
button:Show()
|
||||
|
||||
AB:TrimIcon(button)
|
||||
|
||||
index = index + 1
|
||||
end
|
||||
end
|
||||
|
||||
function NP:BossMods_TrackIcons(track, unitGUID, texture, duration, desaturate, startTime)
|
||||
if track then
|
||||
NP.BossMods_TextureCache[texture] = true -- use this to easily populate boss mod style filters
|
||||
|
||||
if not NP.BossMods_ActiveUnitGUID[unitGUID] then
|
||||
NP.BossMods_ActiveUnitGUID[unitGUID] = {}
|
||||
end
|
||||
|
||||
local active = NP.BossMods_ActiveUnitGUID[unitGUID]
|
||||
if not active[texture] then
|
||||
active[texture] = {}
|
||||
end
|
||||
|
||||
local activeTexture = active[texture]
|
||||
activeTexture.duration = duration
|
||||
activeTexture.desaturate = desaturate
|
||||
activeTexture.startTime = startTime
|
||||
else
|
||||
local active = NP.BossMods_ActiveUnitGUID[unitGUID]
|
||||
if active then
|
||||
if active[texture] then
|
||||
active[texture] = nil
|
||||
end
|
||||
|
||||
if not next(active) then
|
||||
NP.BossMods_ActiveUnitGUID[unitGUID] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:BossMods_ClearIcons()
|
||||
if not next(NP.BossMods_ActiveUnitGUID) then return end
|
||||
|
||||
for unitGUID, textures in pairs(NP.BossMods_ActiveUnitGUID) do
|
||||
for texture in pairs(textures) do
|
||||
local plate = NP.PlateGUID[unitGUID]
|
||||
if plate then
|
||||
NP:BossMods_ClearIcon(plate, texture)
|
||||
NP:StyleFilterUpdate(plate, 'FAKE_BossModAuras')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wipe(NP.BossMods_ActiveUnitGUID)
|
||||
end
|
||||
|
||||
function NP:BossMods_AddIcon(unitGUID, texture, duration, desaturate, skip)
|
||||
local active = NP.BossMods_ActiveUnitGUID[unitGUID]
|
||||
local activeTexture = active and active[texture]
|
||||
|
||||
local pastTime = activeTexture and activeTexture.startTime
|
||||
local pastDuration = activeTexture and activeTexture.duration
|
||||
if pastTime and pastDuration and pastDuration ~= duration then
|
||||
pastTime = nil -- reset the cooldown timer if a new duration is given
|
||||
end
|
||||
|
||||
local startTime = duration and (pastTime or GetTime()) or nil
|
||||
NP:BossMods_TrackIcons(true, unitGUID, texture, duration, desaturate, startTime)
|
||||
|
||||
local plate = NP.PlateGUID[unitGUID]
|
||||
if not plate then return end
|
||||
|
||||
local button = NP:BossMods_GetIcon(plate, texture)
|
||||
button.icon:SetDesaturated(desaturate)
|
||||
button.icon:SetTexture(texture)
|
||||
|
||||
if duration then
|
||||
button.cd:SetCooldown(startTime, duration)
|
||||
button.cd:Show()
|
||||
else
|
||||
button.cd:Hide()
|
||||
end
|
||||
|
||||
if desaturate then
|
||||
button:SetBackdropBorderColor(unpack(E.media.bordercolor))
|
||||
else
|
||||
local color = _G.DebuffTypeColor.none
|
||||
button:SetBackdropBorderColor(color.r * 0.6, color.g * 0.6, color.b * 0.6)
|
||||
end
|
||||
|
||||
NP:BossMods_PositionIcons(plate.BossMods)
|
||||
|
||||
if not skip then -- this will happen already during PostUpdateAllElements
|
||||
NP:StyleFilterUpdate(plate, 'FAKE_BossModAuras')
|
||||
end
|
||||
end
|
||||
|
||||
function NP:BossMods_RemoveIcon(unitGUID, texture)
|
||||
NP:BossMods_TrackIcons(false, unitGUID, texture)
|
||||
|
||||
local plate = NP.PlateGUID[unitGUID]
|
||||
if plate then
|
||||
NP:BossMods_ClearIcon(plate, texture)
|
||||
NP:BossMods_PositionIcons(plate.BossMods)
|
||||
NP:StyleFilterUpdate(plate, 'FAKE_BossModAuras')
|
||||
end
|
||||
end
|
||||
|
||||
function NP:BossMods_ClearIcon(plate, texture)
|
||||
local element = plate.BossMods
|
||||
local button = element.activeIcons[texture]
|
||||
if not button then return end
|
||||
|
||||
button:Hide()
|
||||
|
||||
element.activeIcons[texture] = nil
|
||||
element.unusedIcons[texture] = button
|
||||
end
|
||||
|
||||
function NP:BossMods_UpdateIcon(plate, removed)
|
||||
local unitGUID = plate.unitGUID
|
||||
local active = NP.BossMods_ActiveUnitGUID[unitGUID]
|
||||
|
||||
if not active then
|
||||
local element = plate.BossMods
|
||||
if element and next(element.activeIcons) then
|
||||
for texture in pairs(element.activeIcons) do
|
||||
NP:BossMods_ClearIcon(plate, texture)
|
||||
end
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local enabled = allowHostile and NP.db.bossMods.enable
|
||||
for texture, info in pairs(active) do
|
||||
if removed or not enabled then
|
||||
NP:BossMods_ClearIcon(plate, texture)
|
||||
elseif enabled then
|
||||
NP:BossMods_AddIcon(unitGUID, texture, info.duration, info.desaturate, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:BossMods_AddIcon_DBM(isGUID, unit, texture, duration, desaturate)
|
||||
if not (allowHostile and NP.db.bossMods.enable) then return end
|
||||
|
||||
local unitGUID = (isGUID and unit) or UnitGUID(unit)
|
||||
NP:BossMods_AddIcon(unitGUID, texture, duration, desaturate)
|
||||
end
|
||||
|
||||
function NP:BossMods_RemoveIcon_DBM(isGUID, unit, texture)
|
||||
local unitGUID = (isGUID and unit) or UnitGUID(unit)
|
||||
NP:BossMods_RemoveIcon(unitGUID, texture)
|
||||
end
|
||||
|
||||
function NP:BossMods_AddIcon_BW(_, unitGUID, texture, duration, desaturate)
|
||||
if not (allowHostile and NP.db.bossMods.enable) then return end
|
||||
|
||||
NP:BossMods_AddIcon(unitGUID, texture, duration, desaturate)
|
||||
end
|
||||
|
||||
function NP:BossMods_RemoveIcon_BW(_, unitGUID, texture)
|
||||
NP:BossMods_RemoveIcon(unitGUID, texture)
|
||||
end
|
||||
|
||||
function NP:BossMods_DisableHostile()
|
||||
NP:BossMods_ClearIcons()
|
||||
|
||||
allowHostile = false
|
||||
end
|
||||
|
||||
function NP:BossMods_EnableHostile()
|
||||
allowHostile = true
|
||||
end
|
||||
|
||||
function NP:DBM_SupportedNPMod()
|
||||
return _G.DBM.Options.UseNameplateHandoff
|
||||
end
|
||||
|
||||
function NP:BossMods_RegisterCallbacks()
|
||||
local DBM = _G.DBM
|
||||
if DBM and DBM.RegisterCallback and DBM.Nameplate then
|
||||
DBM.Nameplate.SupportedNPMod = NP.DBM_SupportedNPMod
|
||||
|
||||
DBM:RegisterCallback('BossMod_ShowNameplateAura',NP.BossMods_AddIcon_DBM)
|
||||
DBM:RegisterCallback('BossMod_HideNameplateAura',NP.BossMods_RemoveIcon_DBM)
|
||||
DBM:RegisterCallback('BossMod_EnableHostileNameplates',NP.BossMods_EnableHostile)
|
||||
DBM:RegisterCallback('BossMod_DisableHostileNameplates',NP.BossMods_DisableHostile)
|
||||
end
|
||||
|
||||
local BWL = _G.BigWigsLoader
|
||||
if BWL and BWL.RegisterMessage then
|
||||
BWL.RegisterMessage(NP,'BigWigs_AddNameplateIcon',NP.BossMods_AddIcon_BW)
|
||||
BWL.RegisterMessage(NP,'BigWigs_RemoveNameplateIcon',NP.BossMods_RemoveIcon_BW)
|
||||
BWL.RegisterMessage(NP,'BigWigs_EnableHostileNameplates',NP.BossMods_EnableHostile)
|
||||
BWL.RegisterMessage(NP,'BigWigs_DisableHostileNameplates',NP.BossMods_DisableHostile)
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Update_BossMods(plate)
|
||||
local db = NP.db.bossMods
|
||||
if not db.enable then return end
|
||||
|
||||
local anchor = db.anchorPoint
|
||||
local inverse = E.InversePoints[anchor]
|
||||
|
||||
local element = plate.BossMods
|
||||
element:ClearAllPoints()
|
||||
element:SetPoint(inverse or 'TOPRIGHT', plate, anchor or 'TOPRIGHT', db.xOffset, db.yOffset)
|
||||
element:SetSize(plate.width or 150, db.size)
|
||||
|
||||
element.db = db
|
||||
element.spacing = db.spacing
|
||||
element.initialAnchor = inverse
|
||||
element.growthY = UF.MatchGrowthY[anchor] or db.growthY
|
||||
element.growthX = UF.MatchGrowthX[anchor] or db.growthX
|
||||
element.size = db.size + (db.spacing or 0)
|
||||
element.height = not db.keepSizeRatio and db.height
|
||||
element.rows = {}
|
||||
end
|
||||
|
||||
function NP:Construct_BossMods(nameplate)
|
||||
local element = CreateFrame('Frame', '$parentBossMods', nameplate)
|
||||
|
||||
element.activeIcons = {}
|
||||
element.unusedIcons = {}
|
||||
|
||||
return element
|
||||
end
|
||||
@@ -1,358 +1,254 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local NP = E:GetModule("NamePlates")
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local UF = E:GetModule('UnitFrames')
|
||||
local CH = E:GetModule('Chat')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
--Lua functions
|
||||
local _G = _G
|
||||
local abs = abs
|
||||
local next = next
|
||||
local unpack = unpack
|
||||
local abs = math.abs
|
||||
--WoW API / Variables
|
||||
local strjoin = strjoin
|
||||
local strmatch = strmatch
|
||||
local CreateFrame = CreateFrame
|
||||
local GetTime = GetTime
|
||||
local UnitCastingInfo = UnitCastingInfo
|
||||
local UnitChannelInfo = UnitChannelInfo
|
||||
local FAILED = FAILED
|
||||
local UnitCanAttack = UnitCanAttack
|
||||
local UnitName = UnitName
|
||||
|
||||
local INTERRUPTED = INTERRUPTED
|
||||
|
||||
local function resetAttributes(self)
|
||||
self.casting = nil
|
||||
self.channeling = nil
|
||||
self.notInterruptible = nil
|
||||
self.spellName = nil
|
||||
function NP:Castbar_CheckInterrupt(unit)
|
||||
if unit == 'vehicle' then
|
||||
unit = 'player'
|
||||
end
|
||||
|
||||
if self.notInterruptible and UnitCanAttack('player', unit) then
|
||||
self:SetStatusBarColor(NP.db.colors.castNoInterruptColor.r, NP.db.colors.castNoInterruptColor.g, NP.db.colors.castNoInterruptColor.b)
|
||||
|
||||
if self.Icon and NP.db.colors.castbarDesaturate then
|
||||
self.Icon:SetDesaturated(true)
|
||||
end
|
||||
else
|
||||
self:SetStatusBarColor(NP.db.colors.castColor.r, NP.db.colors.castColor.g, NP.db.colors.castColor.b)
|
||||
|
||||
if self.Icon then
|
||||
self.Icon:SetDesaturated(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Update_CastBarOnUpdate(elapsed)
|
||||
if self.casting or self.channeling then
|
||||
local isCasting = self.casting
|
||||
if isCasting then
|
||||
self.value = self.value + elapsed
|
||||
if self.value >= self.max then
|
||||
resetAttributes(self)
|
||||
self:Hide()
|
||||
NP:StyleFilterUpdate(self:GetParent(), "FAKE_Casting")
|
||||
return
|
||||
end
|
||||
else
|
||||
self.value = self.value - elapsed
|
||||
if self.value <= 0 then
|
||||
resetAttributes(self)
|
||||
self:Hide()
|
||||
NP:StyleFilterUpdate(self:GetParent(), "FAKE_Casting")
|
||||
return
|
||||
end
|
||||
function NP:Castbar_CustomDelayText(duration)
|
||||
if self.channeling then
|
||||
if self.channelTimeFormat == 'CURRENT' then
|
||||
self.Time:SetFormattedText('%.1f |cffaf5050%.1f|r', abs(duration - self.max), self.delay)
|
||||
elseif self.channelTimeFormat == 'CURRENTMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%.1f|r', duration, self.max, self.delay)
|
||||
elseif self.channelTimeFormat == 'REMAINING' then
|
||||
self.Time:SetFormattedText('%.1f |cffaf5050%.1f|r', duration, self.delay)
|
||||
elseif self.channelTimeFormat == 'REMAININGMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%.1f|r', abs(duration - self.max), self.max, self.delay)
|
||||
end
|
||||
else
|
||||
if self.castTimeFormat == 'CURRENT' then
|
||||
self.Time:SetFormattedText('%.1f |cffaf5050%s %.1f|r', duration, '+', self.delay)
|
||||
elseif self.castTimeFormat == 'CURRENTMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%s %.1f|r', duration, self.max, '+', self.delay)
|
||||
elseif self.castTimeFormat == 'REMAINING' then
|
||||
self.Time:SetFormattedText('%.1f |cffaf5050%s %.1f|r', abs(duration - self.max), '+', self.delay)
|
||||
elseif self.castTimeFormat == 'REMAININGMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f |cffaf5050%s %.1f|r', abs(duration - self.max), self.max, '+', self.delay)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.delay ~= 0 then
|
||||
if self.channeling then
|
||||
if self.channelTimeFormat == "CURRENT" then
|
||||
self.Time:SetFormattedText("%.1f |cffaf5050%.2f|r", abs(self.value - self.max), self.delay)
|
||||
elseif self.channelTimeFormat == "CURRENTMAX" then
|
||||
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%.2f|r", abs(self.value - self.max), self.max, self.delay)
|
||||
elseif self.channelTimeFormat == "REMAINING" then
|
||||
self.Time:SetFormattedText("%.1f |cffaf5050%.2f|r", self.value, self.delay)
|
||||
elseif self.channelTimeFormat == "REMAININGMAX" then
|
||||
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%.2f|r", self.value, self.max, self.max, self.delay)
|
||||
function NP:Castbar_CustomTimeText(duration)
|
||||
if self.channeling then
|
||||
if self.channelTimeFormat == 'CURRENT' then
|
||||
self.Time:SetFormattedText('%.1f', abs(duration - self.max))
|
||||
elseif self.channelTimeFormat == 'CURRENTMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f', abs(duration - self.max), self.max)
|
||||
elseif self.channelTimeFormat == 'REMAINING' then
|
||||
self.Time:SetFormattedText('%.1f', duration)
|
||||
elseif self.channelTimeFormat == 'REMAININGMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f', duration, self.max)
|
||||
end
|
||||
else
|
||||
if self.castTimeFormat == 'CURRENT' then
|
||||
self.Time:SetFormattedText('%.1f', duration)
|
||||
elseif self.castTimeFormat == 'CURRENTMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f', duration, self.max)
|
||||
elseif self.castTimeFormat == 'REMAINING' then
|
||||
self.Time:SetFormattedText('%.1f', abs(duration - self.max))
|
||||
elseif self.castTimeFormat == 'REMAININGMAX' then
|
||||
self.Time:SetFormattedText('%.1f / %.1f', abs(duration - self.max), self.max)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Castbar_PostCastStart(unit)
|
||||
self:CheckInterrupt(unit)
|
||||
|
||||
-- player or NPCs; if used on other players: the cast target doesn't match their target, can be misleading if they mouseover cast
|
||||
local plate = self.__owner
|
||||
local db = NP:PlateDB(plate)
|
||||
if db.castbar and db.castbar.enable then
|
||||
if db.castbar.displayTarget then
|
||||
local frameType = plate.frameType
|
||||
if frameType == 'PLAYER' then
|
||||
if self.curTarget then
|
||||
self.Text:SetText(self.spellName..' > '..self.curTarget)
|
||||
end
|
||||
else
|
||||
if self.castTimeFormat == "CURRENT" then
|
||||
self.Time:SetFormattedText("%.1f |cffaf5050%s %.2f|r", self.value, "+", self.delay)
|
||||
elseif self.castTimeFormat == "CURRENTMAX" then
|
||||
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%s %.2f|r", self.value, self.max, "+", self.delay)
|
||||
elseif self.castTimeFormat == "REMAINING" then
|
||||
self.Time:SetFormattedText("%.1f |cffaf5050%s %.2f|r", abs(self.value - self.max), "+", self.delay)
|
||||
elseif self.castTimeFormat == "REMAININGMAX" then
|
||||
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%s %.2f|r", abs(self.value - self.max), self.max, "+", self.delay)
|
||||
end
|
||||
end
|
||||
else
|
||||
if self.channeling then
|
||||
if self.channelTimeFormat == "CURRENT" then
|
||||
self.Time:SetFormattedText("%.1f", abs(self.value - self.max))
|
||||
elseif self.channelTimeFormat == "CURRENTMAX" then
|
||||
self.Time:SetFormattedText("%.1f / %.2f", abs(self.value - self.max), self.max)
|
||||
elseif self.channelTimeFormat == "REMAINING" then
|
||||
self.Time:SetFormattedText("%.1f", self.value)
|
||||
elseif self.channelTimeFormat == "REMAININGMAX" then
|
||||
self.Time:SetFormattedText("%.1f / %.2f", self.value, self.max)
|
||||
end
|
||||
else
|
||||
if self.castTimeFormat == "CURRENT" then
|
||||
self.Time:SetFormattedText("%.1f", self.value)
|
||||
elseif self.castTimeFormat == "CURRENTMAX" then
|
||||
self.Time:SetFormattedText("%.1f / %.2f", self.value, self.max)
|
||||
elseif self.castTimeFormat == "REMAINING" then
|
||||
self.Time:SetFormattedText("%.1f", abs(self.value - self.max))
|
||||
elseif self.castTimeFormat == "REMAININGMAX" then
|
||||
self.Time:SetFormattedText("%.1f / %.2f", abs(self.value - self.max), self.max)
|
||||
elseif frameType == 'ENEMY_NPC' or frameType == 'FRIENDLY_NPC' then
|
||||
local target = self.curTarget or UnitName(unit..'target')
|
||||
if target and target ~= '' and target ~= plate.unitName then
|
||||
self.Text:SetText(self.spellName..' > '..target)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:SetValue(self.value)
|
||||
elseif self.holdTime > 0 then
|
||||
self.holdTime = self.holdTime - elapsed
|
||||
else
|
||||
resetAttributes(self)
|
||||
self:Hide()
|
||||
NP:StyleFilterUpdate(self:GetParent(), "FAKE_Casting")
|
||||
NP:StyleFilterUpdate(plate, 'FAKE_Cast')
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Update_CastBar(frame, event, unit)
|
||||
local castBar = frame.CastBar
|
||||
if unit then
|
||||
if not event then
|
||||
if UnitChannelInfo(unit) then
|
||||
event = "UNIT_SPELLCAST_CHANNEL_START"
|
||||
elseif UnitCastingInfo(unit) then
|
||||
event = "UNIT_SPELLCAST_START"
|
||||
end
|
||||
end
|
||||
elseif castBar:IsShown() then
|
||||
resetAttributes(castBar)
|
||||
castBar:Hide()
|
||||
function NP:Castbar_PostCastFail()
|
||||
NP:StyleFilterUpdate(self.__owner, 'FAKE_Cast')
|
||||
self:SetStatusBarColor(NP.db.colors.castInterruptedColor.r, NP.db.colors.castInterruptedColor.g, NP.db.colors.castInterruptedColor.b)
|
||||
end
|
||||
|
||||
function NP:Castbar_PostCastInterruptible(unit)
|
||||
self:CheckInterrupt(unit)
|
||||
end
|
||||
|
||||
function NP:Castbar_PostCastStop()
|
||||
NP:StyleFilterUpdate(self.__owner, 'FAKE_Cast')
|
||||
end
|
||||
|
||||
function NP:Construct_Castbar(nameplate)
|
||||
local castbar = CreateFrame('StatusBar', nameplate:GetName()..'Castbar', nameplate)
|
||||
castbar:SetParent(nameplate)
|
||||
castbar:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
|
||||
castbar:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
|
||||
|
||||
NP.StatusBars[castbar] = true
|
||||
castbar.ModuleStatusBars = NP.StatusBars -- not oUF
|
||||
|
||||
castbar.Button = CreateFrame('Frame', nil, castbar)
|
||||
castbar.Button:SetTemplate(nil, nil, nil, nil, nil, true, true)
|
||||
|
||||
castbar.Icon = castbar.Button:CreateTexture(nil, 'ARTWORK')
|
||||
castbar.Icon:SetParent(castbar.Button)
|
||||
castbar.Icon:SetTexCoord(unpack(E.TexCoords))
|
||||
castbar.Icon:SetInside()
|
||||
|
||||
castbar.Time = castbar:CreateFontString(nil, 'OVERLAY')
|
||||
castbar.Time:FontTemplate(LSM:Fetch('font', NP.db.font), NP.db.fontSize, NP.db.fontOutline)
|
||||
castbar.Time:Point('RIGHT', castbar, 'RIGHT', -4, 0)
|
||||
castbar.Time:SetJustifyH('RIGHT')
|
||||
|
||||
castbar.Text = castbar:CreateFontString(nil, 'OVERLAY')
|
||||
castbar.Text:FontTemplate(LSM:Fetch('font', NP.db.font), NP.db.fontSize, NP.db.fontOutline)
|
||||
castbar.Text:Point('LEFT', castbar, 'LEFT', 4, 0)
|
||||
castbar.Text:SetJustifyH('LEFT')
|
||||
castbar.Text:SetWordWrap(false)
|
||||
|
||||
castbar.CheckInterrupt = NP.Castbar_CheckInterrupt
|
||||
castbar.CustomDelayText = NP.Castbar_CustomDelayText
|
||||
castbar.CustomTimeText = NP.Castbar_CustomTimeText
|
||||
castbar.PostCastStart = NP.Castbar_PostCastStart
|
||||
castbar.PostCastFail = NP.Castbar_PostCastFail
|
||||
castbar.PostCastInterruptible = NP.Castbar_PostCastInterruptible
|
||||
castbar.PostCastStop = NP.Castbar_PostCastStop
|
||||
|
||||
if nameplate == _G.ElvNP_Test then
|
||||
castbar.Hide = castbar.Show
|
||||
castbar:Show()
|
||||
castbar.Text:SetText('Casting')
|
||||
castbar.Time:SetText('3.1')
|
||||
castbar.Icon:SetTexture([[Interface\Icons\Achievement_Character_Pandaren_Female]])
|
||||
castbar:SetStatusBarColor(NP.db.colors.castColor.r, NP.db.colors.castColor.g, NP.db.colors.castColor.b)
|
||||
end
|
||||
|
||||
if self.db.units[frame.UnitType].castbar.enable ~= true then return end
|
||||
if self.db.units[frame.UnitType].health.enable ~= true and not (frame.isTarget and self.db.alwaysShowTargetHealth) then return end --Bug
|
||||
return castbar
|
||||
end
|
||||
|
||||
if event == "UNIT_SPELLCAST_START" or event == "UNIT_SPELLCAST_CHANNEL_START" then
|
||||
local name, _, _, texture, startTime, endTime, _, _, notInterruptible = UnitCastingInfo(unit)
|
||||
event = "UNIT_SPELLCAST_START"
|
||||
if not name then
|
||||
name, _, _, texture, startTime, endTime, _, notInterruptible = UnitChannelInfo(unit)
|
||||
event = "UNIT_SPELLCAST_CHANNEL_START"
|
||||
function NP:CASTBAR_COMBAT_LOG_EVENT_UNFILTERED(event, sourceGUID, sourceName, targetGUID)
|
||||
if (event == 'SPELL_INTERRUPT' or event == 'SPELL_PERIODIC_INTERRUPT') and targetGUID and (sourceName and sourceName ~= '') then
|
||||
local plate, classColor = NP.PlateGUID[targetGUID]
|
||||
if plate and plate.Castbar then
|
||||
local db = NP:PlateDB(plate)
|
||||
if db.castbar and db.castbar.enable and db.castbar.sourceInterrupt and (db.castbar.timeToHold > 0) then
|
||||
local name = strmatch(sourceName, '([^%-]+).*')
|
||||
if db.castbar.sourceInterruptClassColor then
|
||||
local data = CH:GetPlayerInfoByGUID(sourceGUID)
|
||||
if data and data.classColor then
|
||||
classColor = data.classColor.colorStr
|
||||
end
|
||||
|
||||
plate.Castbar.Text:SetFormattedText('%s > %s', INTERRUPTED, classColor and strjoin('', '|c', classColor, name) or name)
|
||||
else
|
||||
plate.Castbar.Text:SetFormattedText('%s > %s', INTERRUPTED, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Update_Castbar(nameplate)
|
||||
local frameDB = NP:PlateDB(nameplate)
|
||||
local db = frameDB.castbar
|
||||
|
||||
local castbar = nameplate.Castbar
|
||||
if nameplate == _G.ElvNP_Test then
|
||||
castbar:SetAlpha((not frameDB.nameOnly and db.enable) and 1 or 0)
|
||||
end
|
||||
|
||||
if db.enable then
|
||||
if not nameplate:IsElementEnabled('Castbar') then
|
||||
nameplate:EnableElement('Castbar')
|
||||
end
|
||||
|
||||
if not name then
|
||||
resetAttributes(castBar)
|
||||
castBar:Hide()
|
||||
return
|
||||
end
|
||||
castbar.timeToHold = db.timeToHold
|
||||
castbar.castTimeFormat = db.castTimeFormat
|
||||
castbar.channelTimeFormat = db.channelTimeFormat
|
||||
|
||||
endTime = endTime / 1000
|
||||
startTime = startTime / 1000
|
||||
castbar:Size(db.width, db.height)
|
||||
castbar:Point('CENTER', nameplate, 'CENTER', db.xOffset, db.yOffset)
|
||||
|
||||
castBar.max = endTime - startTime
|
||||
castBar.startTime = startTime
|
||||
castBar.delay = 0
|
||||
castBar.casting = event == "UNIT_SPELLCAST_START"
|
||||
castBar.channeling = event == "UNIT_SPELLCAST_CHANNEL_START"
|
||||
castBar.notInterruptible = notInterruptible
|
||||
castBar.holdTime = 0
|
||||
castBar.interrupted = nil
|
||||
castBar.spellName = name
|
||||
|
||||
if castBar.casting then
|
||||
castBar.value = GetTime() - startTime
|
||||
if db.showIcon then
|
||||
castbar.Button:ClearAllPoints()
|
||||
castbar.Button:Point(db.iconPosition == 'RIGHT' and 'BOTTOMLEFT' or 'BOTTOMRIGHT', castbar, db.iconPosition == 'RIGHT' and 'BOTTOMRIGHT' or 'BOTTOMLEFT', db.iconOffsetX, db.iconOffsetY)
|
||||
castbar.Button:Size(db.iconSize, db.iconSize)
|
||||
castbar.Button:Show()
|
||||
else
|
||||
castBar.value = endTime - GetTime()
|
||||
castbar.Button:Hide()
|
||||
end
|
||||
|
||||
castBar:SetMinMaxValues(0, castBar.max)
|
||||
castBar:SetValue(castBar.value)
|
||||
castbar.Time:ClearAllPoints()
|
||||
castbar.Text:ClearAllPoints()
|
||||
|
||||
castBar.Icon.texture:SetTexture(texture)
|
||||
castBar.Spark:Show()
|
||||
castBar.Name:SetText(name)
|
||||
castBar.Time:SetText()
|
||||
|
||||
castBar:Show()
|
||||
elseif event == "UNIT_SPELLCAST_STOP" or event == "UNIT_SPELLCAST_CHANNEL_STOP" then
|
||||
if castBar:IsShown() then
|
||||
resetAttributes(castBar)
|
||||
end
|
||||
elseif event == "UNIT_SPELLCAST_FAILED" or event == "UNIT_SPELLCAST_INTERRUPTED" then
|
||||
if castBar:IsShown() then
|
||||
castBar.Spark:Hide()
|
||||
castBar.Name:SetText(event == "UNIT_SPELLCAST_FAILED" and FAILED or INTERRUPTED)
|
||||
|
||||
castBar.holdTime = self.db.units[frame.UnitType].castbar.timeToHold --How long the castbar should stay visible after being interrupted, in seconds
|
||||
castBar.interrupted = true
|
||||
|
||||
resetAttributes(castBar)
|
||||
castBar:SetValue(castBar.max)
|
||||
end
|
||||
elseif event == "UNIT_SPELLCAST_DELAYED" or event == "UNIT_SPELLCAST_CHANNEL_UPDATE" then
|
||||
if frame:IsShown() then
|
||||
local name, startTime, endTime, _
|
||||
if event == "UNIT_SPELLCAST_DELAYED" then
|
||||
name, _, _, _, startTime, endTime = UnitCastingInfo(unit)
|
||||
else
|
||||
name, _, _, _, startTime, endTime = UnitChannelInfo(unit)
|
||||
end
|
||||
|
||||
if not name then
|
||||
resetAttributes(castBar)
|
||||
castBar:Hide()
|
||||
return
|
||||
end
|
||||
|
||||
endTime = endTime / 1000
|
||||
startTime = startTime / 1000
|
||||
|
||||
local delta
|
||||
if castBar.casting then
|
||||
delta = startTime - castBar.startTime
|
||||
castBar.value = GetTime() - startTime
|
||||
else
|
||||
delta = castBar.startTime - startTime
|
||||
castBar.value = endTime - GetTime()
|
||||
end
|
||||
|
||||
if delta < 0 then
|
||||
delta = 0
|
||||
end
|
||||
|
||||
castBar.Name:SetText(name)
|
||||
castBar.max = endTime - startTime
|
||||
castBar.startTime = startTime
|
||||
castBar.delay = castBar.delay + delta
|
||||
castBar:SetMinMaxValues(0, castBar.max)
|
||||
castBar:SetValue(castBar.value)
|
||||
end
|
||||
elseif event == "UNIT_SPELLCAST_INTERRUPTIBLE" or event == "UNIT_SPELLCAST_NOT_INTERRUPTIBLE" then
|
||||
castBar.notInterruptible = event == "UNIT_SPELLCAST_NOT_INTERRUPTIBLE"
|
||||
end
|
||||
|
||||
if not castBar.notInterruptible then
|
||||
if castBar.interrupted then
|
||||
castBar:SetStatusBarColor(self.db.colors.castInterruptedColor.r, self.db.colors.castInterruptedColor.g, self.db.colors.castInterruptedColor.b)
|
||||
if db.textPosition == 'BELOW' then
|
||||
castbar.Time:Point('TOPRIGHT', castbar, 'BOTTOMRIGHT', db.timeXOffset, db.timeYOffset)
|
||||
castbar.Text:Point('TOPLEFT', castbar, 'BOTTOMLEFT', db.textXOffset, db.textYOffset)
|
||||
elseif db.textPosition == 'ABOVE' then
|
||||
castbar.Time:Point('BOTTOMRIGHT', castbar, 'TOPRIGHT', db.timeXOffset, db.timeYOffset)
|
||||
castbar.Text:Point('BOTTOMLEFT', castbar, 'TOPLEFT', db.textXOffset, db.textYOffset)
|
||||
else
|
||||
castBar:SetStatusBarColor(self.db.colors.castColor.r, self.db.colors.castColor.g, self.db.colors.castColor.b)
|
||||
end
|
||||
castBar.Icon.texture:SetDesaturated(false)
|
||||
else
|
||||
castBar:SetStatusBarColor(self.db.colors.castNoInterruptColor.r, self.db.colors.castNoInterruptColor.g, self.db.colors.castNoInterruptColor.b)
|
||||
|
||||
if self.db.colors.castbarDesaturate then
|
||||
castBar.Icon.texture:SetDesaturated(true)
|
||||
end
|
||||
end
|
||||
|
||||
self:StyleFilterUpdate(frame, "FAKE_Casting")
|
||||
end
|
||||
|
||||
function NP:Configure_CastBarScale(frame, scale, noPlayAnimation)
|
||||
if frame.currentScale == scale then return end
|
||||
local db = self.db.units[frame.UnitType].castbar
|
||||
if not db.enable then return end
|
||||
|
||||
local castBar = frame.CastBar
|
||||
|
||||
if noPlayAnimation then
|
||||
castBar:SetSize(db.width * scale, db.height * scale)
|
||||
castBar.Icon:SetSize(db.iconSize * scale, db.iconSize * scale)
|
||||
else
|
||||
if castBar.scale:IsPlaying() or castBar.Icon.scale:IsPlaying() then
|
||||
castBar.scale:Stop()
|
||||
castBar.Icon.scale:Stop()
|
||||
castbar.Time:Point('RIGHT', castbar, 'RIGHT', db.timeXOffset, db.timeYOffset)
|
||||
castbar.Text:Point('LEFT', castbar, 'LEFT', db.textXOffset, db.textYOffset)
|
||||
end
|
||||
|
||||
castBar.scale.width:SetChange(db.width * scale)
|
||||
castBar.scale.height:SetChange(db.height * scale)
|
||||
castBar.scale:Play()
|
||||
if db.hideTime then
|
||||
castbar.Time:Hide()
|
||||
else
|
||||
castbar.Time:FontTemplate(LSM:Fetch('font', db.font), db.fontSize, db.fontOutline)
|
||||
castbar.Time:Show()
|
||||
end
|
||||
|
||||
castBar.Icon.scale.width:SetChange(db.iconSize * scale)
|
||||
castBar.Icon.scale.height:SetChange(db.iconSize * scale)
|
||||
castBar.Icon.scale:Play()
|
||||
if db.hideSpellName then
|
||||
castbar.Text:Hide()
|
||||
else
|
||||
castbar.Text:FontTemplate(LSM:Fetch('font', db.font), db.fontSize, db.fontOutline)
|
||||
castbar.Text:Show()
|
||||
end
|
||||
elseif nameplate:IsElementEnabled('Castbar') then
|
||||
nameplate:DisableElement('Castbar')
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Configure_CastBar(frame, configuring)
|
||||
local db = self.db.units[frame.UnitType].castbar
|
||||
local castBar = frame.CastBar
|
||||
|
||||
castBar:SetPoint("TOP", frame.Health, "BOTTOM", db.xOffset, db.yOffset)
|
||||
|
||||
if db.showIcon then
|
||||
castBar.Icon:ClearAllPoints()
|
||||
castBar.Icon:SetPoint(db.iconPosition == "RIGHT" and "BOTTOMLEFT" or "BOTTOMRIGHT", castBar, db.iconPosition == "RIGHT" and "BOTTOMRIGHT" or "BOTTOMLEFT", db.iconOffsetX, db.iconOffsetY)
|
||||
castBar.Icon:Show()
|
||||
else
|
||||
castBar.Icon:Hide()
|
||||
end
|
||||
|
||||
castBar.Time:ClearAllPoints()
|
||||
castBar.Name:ClearAllPoints()
|
||||
|
||||
castBar.Spark:SetPoint("CENTER", castBar:GetStatusBarTexture(), "RIGHT", 0, 0)
|
||||
castBar.Spark:SetHeight(db.height * 2)
|
||||
|
||||
if db.textPosition == "BELOW" then
|
||||
castBar.Time:SetPoint("TOPRIGHT", castBar, "BOTTOMRIGHT")
|
||||
castBar.Name:SetPoint("TOPLEFT", castBar, "BOTTOMLEFT")
|
||||
elseif db.textPosition == "ABOVE" then
|
||||
castBar.Time:SetPoint("BOTTOMRIGHT", castBar, "TOPRIGHT")
|
||||
castBar.Name:SetPoint("BOTTOMLEFT", castBar, "TOPLEFT")
|
||||
else
|
||||
castBar.Time:SetPoint("RIGHT", castBar, "RIGHT", -4, 0)
|
||||
castBar.Name:SetPoint("LEFT", castBar, "LEFT", 4, 0)
|
||||
end
|
||||
|
||||
if configuring then
|
||||
self:Configure_CastBarScale(frame, frame.currentScale or 1, configuring)
|
||||
end
|
||||
|
||||
castBar.Name:FontTemplate(LSM:Fetch("font", db.font), db.fontSize, db.fontOutline)
|
||||
castBar.Time:FontTemplate(LSM:Fetch("font", db.font), db.fontSize, db.fontOutline)
|
||||
|
||||
if db.hideSpellName then
|
||||
castBar.Name:Hide()
|
||||
else
|
||||
castBar.Name:Show()
|
||||
end
|
||||
if db.hideTime then
|
||||
castBar.Time:Hide()
|
||||
else
|
||||
castBar.Time:Show()
|
||||
end
|
||||
|
||||
castBar:SetStatusBarTexture(LSM:Fetch("statusbar", self.db.statusbar))
|
||||
|
||||
castBar.castTimeFormat = db.castTimeFormat
|
||||
castBar.channelTimeFormat = db.channelTimeFormat
|
||||
end
|
||||
|
||||
function NP:Construct_CastBar(parent)
|
||||
local frame = CreateFrame("StatusBar", "$parentCastBar", parent)
|
||||
NP:StyleFrame(frame)
|
||||
frame:SetScript("OnUpdate", NP.Update_CastBarOnUpdate)
|
||||
|
||||
frame.Icon = CreateFrame("Frame", nil, frame)
|
||||
frame.Icon.texture = frame.Icon:CreateTexture(nil, "BORDER")
|
||||
frame.Icon.texture:SetAllPoints()
|
||||
frame.Icon.texture:SetTexCoord(unpack(E.TexCoords))
|
||||
NP:StyleFrame(frame.Icon)
|
||||
|
||||
frame.Time = frame:CreateFontString(nil, "OVERLAY")
|
||||
frame.Time:SetJustifyH("RIGHT")
|
||||
frame.Time:SetWordWrap(false)
|
||||
|
||||
frame.Name = frame:CreateFontString(nil, "OVERLAY")
|
||||
frame.Name:SetJustifyH("LEFT")
|
||||
frame.Name:SetWordWrap(false)
|
||||
|
||||
frame.Spark = frame:CreateTexture(nil, "OVERLAY")
|
||||
frame.Spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
|
||||
frame.Spark:SetBlendMode("ADD")
|
||||
frame.Spark:SetSize(15, 15)
|
||||
|
||||
frame.holdTime = 0
|
||||
frame.interrupted = nil
|
||||
|
||||
frame.scale = CreateAnimationGroup(frame)
|
||||
frame.scale.width = frame.scale:CreateAnimation("Width")
|
||||
frame.scale.width:SetDuration(0.2)
|
||||
frame.scale.height = frame.scale:CreateAnimation("Height")
|
||||
frame.scale.height:SetDuration(0.2)
|
||||
|
||||
frame.Icon.scale = CreateAnimationGroup(frame.Icon)
|
||||
frame.Icon.scale.width = frame.Icon.scale:CreateAnimation("Width")
|
||||
frame.Icon.scale.width:SetDuration(0.2)
|
||||
frame.Icon.scale.height = frame.Icon.scale:CreateAnimation("Height")
|
||||
frame.Icon.scale.height:SetDuration(0.2)
|
||||
|
||||
frame:Hide()
|
||||
|
||||
return frame
|
||||
end
|
||||
@@ -0,0 +1,310 @@
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local UF = E:GetModule('UnitFrames')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local _G = _G
|
||||
local max, next, ipairs = max, next, ipairs
|
||||
|
||||
local CreateFrame = CreateFrame
|
||||
local UnitHasVehicleUI = UnitHasVehicleUI
|
||||
local MAX_COMBO_POINTS = MAX_COMBO_POINTS
|
||||
|
||||
local MAX_POINTS = { -- match to UF.classMaxResourceBar
|
||||
DEATHKNIGHT = max(6, MAX_COMBO_POINTS),
|
||||
ROGUE = max(7, MAX_COMBO_POINTS),
|
||||
HERO = max(5, MAX_COMBO_POINTS),
|
||||
DRUID = max(5, MAX_COMBO_POINTS)
|
||||
}
|
||||
|
||||
function NP:ClassPower_SetBarColor(bar, r, g, b)
|
||||
bar:SetStatusBarColor(r, g, b)
|
||||
|
||||
if bar.bg then
|
||||
bar.bg:SetVertexColor(r * NP.multiplier, g * NP.multiplier, b * NP.multiplier)
|
||||
end
|
||||
end
|
||||
|
||||
function NP:ClassPower_UpdateColor(powerType, rune)
|
||||
local isRunes = powerType == 'RUNES'
|
||||
|
||||
local classPower = self.classColor
|
||||
local colors = NP.db.colors.classResources
|
||||
local fallback = NP.db.colors.power[powerType]
|
||||
|
||||
if isRunes and NP.db.colors.chargingRunes then
|
||||
NP:Runes_UpdateCharged(self, rune)
|
||||
elseif isRunes and rune and not classPower then
|
||||
local color = colors.DEATHKNIGHT[rune.runeType or 0]
|
||||
NP:ClassPower_SetBarColor(rune, color.r, color.g, color.b)
|
||||
else
|
||||
local classColor = not classPower and ((isRunes and colors.DEATHKNIGHT) or (powerType == 'COMBO_POINTS' and colors.comboPoints) or (powerType == 'ESSENCE' and colors.EVOKER) or (powerType == 'CHI' and colors.MONK))
|
||||
for i, bar in ipairs(self) do
|
||||
local color = classPower or (isRunes and classColor[bar.runeType or 0]) or (classColor and classColor[i]) or colors[E.myclass] or fallback
|
||||
NP:ClassPower_SetBarColor(bar, color.r, color.g, color.b)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:ClassPower_PostUpdate(Cur, _, needUpdate, powerType, chargedPoints)
|
||||
if Cur and Cur > 0 then
|
||||
self:Show()
|
||||
else
|
||||
self:Hide()
|
||||
end
|
||||
|
||||
if needUpdate then
|
||||
NP:Update_ClassPower(self.__owner)
|
||||
end
|
||||
|
||||
if powerType == 'COMBO_POINTS' and E.myclass == 'ROGUE' then
|
||||
NP.ClassPower_UpdateColor(self, powerType)
|
||||
|
||||
if chargedPoints then
|
||||
local color = NP.db.colors.classResources.chargedComboPoint
|
||||
for _, chargedIndex in next, chargedPoints do
|
||||
self[chargedIndex]:SetStatusBarColor(color.r, color.g, color.b)
|
||||
self[chargedIndex].bg:SetVertexColor(color.r * NP.multiplier, color.g * NP.multiplier, color.b * NP.multiplier)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_ClassPower(nameplate)
|
||||
local frameName = nameplate:GetName()
|
||||
local ClassPower = CreateFrame('Frame', frameName..'ClassPower', nameplate)
|
||||
ClassPower:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
|
||||
ClassPower:Hide()
|
||||
|
||||
local texture = LSM:Fetch('statusbar', NP.db.statusbar)
|
||||
local total = MAX_POINTS[E.myclass] or 0
|
||||
|
||||
for i = 1, total do
|
||||
local bar = CreateFrame('StatusBar', frameName..'ClassPower'..i, ClassPower)
|
||||
bar:SetStatusBarTexture(texture)
|
||||
NP.StatusBars[bar] = true
|
||||
|
||||
bar.bg = ClassPower:CreateTexture(frameName..'ClassPower'..i..'bg', 'BORDER')
|
||||
bar.bg:SetTexture(texture)
|
||||
bar.bg:SetAllPoints()
|
||||
|
||||
if nameplate == _G.ElvNP_Test then
|
||||
local combo = NP.db.colors.classResources.comboPoints[i]
|
||||
bar.bg:SetVertexColor(combo.r, combo.g, combo.b)
|
||||
end
|
||||
|
||||
ClassPower[i] = bar
|
||||
end
|
||||
|
||||
if nameplate == _G.ElvNP_Test then
|
||||
ClassPower.Hide = ClassPower.Show
|
||||
ClassPower:Show()
|
||||
end
|
||||
|
||||
ClassPower.UpdateColor = NP.ClassPower_UpdateColor
|
||||
ClassPower.PostUpdate = NP.ClassPower_PostUpdate
|
||||
|
||||
return ClassPower
|
||||
end
|
||||
|
||||
function NP:Update_ClassPower(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
if nameplate == _G.ElvNP_Test then
|
||||
if not db.nameOnly and db.classpower and db.classpower.enable then
|
||||
NP.ClassPower_UpdateColor(nameplate.ClassPower, 'COMBO_POINTS')
|
||||
nameplate.ClassPower:SetAlpha(1)
|
||||
else
|
||||
nameplate.ClassPower:SetAlpha(0)
|
||||
end
|
||||
end
|
||||
|
||||
local target = nameplate.frameType == 'TARGET'
|
||||
if (target or nameplate.frameType == 'PLAYER') and db.classpower and db.classpower.enable then
|
||||
if not nameplate:IsElementEnabled('ClassPower') then
|
||||
nameplate:EnableElement('ClassPower')
|
||||
end
|
||||
|
||||
local anchor = target and NP:GetClassAnchor()
|
||||
nameplate.ClassPower:ClearAllPoints()
|
||||
nameplate.ClassPower:Point('CENTER', anchor or nameplate, 'CENTER', db.classpower.xOffset, db.classpower.yOffset)
|
||||
nameplate.ClassPower:Size(db.classpower.width, db.classpower.height)
|
||||
|
||||
nameplate.ClassPower.classColor = db.classpower.classColor and RAID_CLASS_COLORS[E.myclass]
|
||||
|
||||
for i = 1, #nameplate.ClassPower do
|
||||
nameplate.ClassPower[i]:Hide()
|
||||
nameplate.ClassPower[i].bg:Hide()
|
||||
end
|
||||
|
||||
local maxButtons = nameplate.ClassPower.__max
|
||||
if maxButtons > 0 then
|
||||
local Width = db.classpower.width / maxButtons
|
||||
for i = 1, maxButtons do
|
||||
local button = nameplate.ClassPower[i]
|
||||
button:Show()
|
||||
button.bg:Show()
|
||||
button:ClearAllPoints()
|
||||
|
||||
if i == 1 then
|
||||
local width = Width - (maxButtons == 6 and 2 or 0)
|
||||
button:Point('LEFT', nameplate.ClassPower, 'LEFT', 0, 0)
|
||||
button:Size(width, db.classpower.height)
|
||||
else
|
||||
button:Point('LEFT', nameplate.ClassPower[i - 1], 'RIGHT', 1, 0)
|
||||
button:Size(Width - 1, db.classpower.height)
|
||||
|
||||
if i == maxButtons then
|
||||
button:Point('RIGHT', nameplate.ClassPower)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if nameplate:IsElementEnabled('ClassPower') then
|
||||
nameplate:DisableElement('ClassPower')
|
||||
end
|
||||
|
||||
nameplate.ClassPower:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Runes_UpdateCharged(runes, rune)
|
||||
local colors = NP.db.colors.classResources.DEATHKNIGHT
|
||||
local classColor = (runes and runes.classColor) or (rune and rune.__owner and rune.__owner.classColor)
|
||||
|
||||
if rune then
|
||||
NP:ClassPower_SetBarColor(rune, UF:Runes_GetColor(rune, colors, classColor))
|
||||
elseif runes then
|
||||
for _, bar in ipairs(runes) do
|
||||
NP:ClassPower_SetBarColor(bar, UF:Runes_GetColor(bar, colors, classColor))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Runes_PostUpdate()
|
||||
self:SetShown(not UnitHasVehicleUI('player'))
|
||||
|
||||
if NP.db.colors.chargingRunes then
|
||||
NP:Runes_UpdateCharged(self)
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Runes_UpdateChargedColor()
|
||||
if NP.db.colors.chargingRunes then
|
||||
NP:Runes_UpdateCharged(nil, self)
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Runes_PostUpdateColor(r, g, b, color, rune)
|
||||
NP.ClassPower_UpdateColor(self, 'RUNES', rune)
|
||||
end
|
||||
|
||||
function NP:Construct_Runes(nameplate)
|
||||
local frameName = nameplate:GetName()
|
||||
local Runes = CreateFrame('Frame', frameName..'Runes', nameplate)
|
||||
Runes:SetFrameStrata("BACKGROUND")
|
||||
Runes:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
|
||||
Runes:Hide()
|
||||
|
||||
Runes.PostUpdate = NP.Runes_PostUpdate
|
||||
Runes.PostUpdateColor = NP.Runes_PostUpdateColor
|
||||
|
||||
local texture = LSM:Fetch('statusbar', NP.db.statusbar)
|
||||
local color = NP.db.colors.classResources.DEATHKNIGHT[0]
|
||||
|
||||
for i = 1, 6 do
|
||||
local rune = CreateFrame('StatusBar', frameName..'Runes'..i, Runes)
|
||||
rune:SetStatusBarTexture(texture)
|
||||
rune:SetStatusBarColor(color.r, color.g, color.b)
|
||||
rune.PostUpdateColor = NP.Runes_UpdateChargedColor
|
||||
rune.__owner = Runes
|
||||
NP.StatusBars[rune] = true
|
||||
|
||||
rune.bg = rune:CreateTexture(frameName..'Runes'..i..'bg', 'BORDER')
|
||||
rune.bg:SetVertexColor(color.r * NP.multiplier, color.g * NP.multiplier, color.b * NP.multiplier)
|
||||
rune.bg:SetTexture(texture)
|
||||
rune.bg:SetAllPoints()
|
||||
rune.bg.multiplier = 0.35
|
||||
|
||||
Runes[i] = rune
|
||||
end
|
||||
|
||||
return Runes
|
||||
end
|
||||
|
||||
function NP:Update_Runes(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
local target = nameplate.frameType == 'TARGET'
|
||||
if (target or nameplate.frameType == 'PLAYER') and db.classpower and db.classpower.enable then
|
||||
if not nameplate:IsElementEnabled('Runes') then
|
||||
nameplate:EnableElement('Runes')
|
||||
end
|
||||
|
||||
local anchor = target and NP:GetClassAnchor()
|
||||
nameplate.Runes:ClearAllPoints()
|
||||
nameplate.Runes:Point('CENTER', anchor or nameplate, 'CENTER', db.classpower.xOffset, db.classpower.yOffset)
|
||||
nameplate.Runes:Show()
|
||||
|
||||
nameplate.Runes.classColor = db.classpower.classColor and RAID_CLASS_COLORS[E.myclass]
|
||||
nameplate.Runes.sortOrder = (db.classpower.sortDirection ~= 'NONE') and db.classpower.sortDirection
|
||||
nameplate.Runes.colorSpec = NP.db.colors.runeBySpec
|
||||
|
||||
local width = db.classpower.width / 6
|
||||
nameplate.Runes:Size(db.classpower.width, db.classpower.height)
|
||||
|
||||
for i = 1, 6 do
|
||||
local rune = nameplate.Runes[i]
|
||||
if i == 1 then
|
||||
rune:Size(width, db.classpower.height)
|
||||
rune:ClearAllPoints()
|
||||
rune:Point('LEFT', nameplate.Runes, 'LEFT', 0, 0)
|
||||
else
|
||||
rune:Size(width - 1, db.classpower.height)
|
||||
rune:ClearAllPoints()
|
||||
rune:Point('LEFT', nameplate.Runes[i-1], 'RIGHT', 1, 0)
|
||||
|
||||
if i == 6 then
|
||||
rune:Point('RIGHT', nameplate.Runes)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if nameplate:IsElementEnabled('Runes') then
|
||||
nameplate:DisableElement('Runes')
|
||||
end
|
||||
|
||||
nameplate.Runes:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_Stagger(nameplate)
|
||||
local Stagger = CreateFrame('StatusBar', nameplate:GetName()..'Stagger', nameplate)
|
||||
Stagger:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
|
||||
Stagger:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
|
||||
Stagger:Hide()
|
||||
|
||||
NP.StatusBars[Stagger] = true
|
||||
|
||||
return Stagger
|
||||
end
|
||||
|
||||
function NP:Update_Stagger(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
local target = nameplate.frameType == 'TARGET'
|
||||
if (target or nameplate.frameType == 'PLAYER') and db.classpower and db.classpower.enable then
|
||||
if not nameplate:IsElementEnabled('Stagger') then
|
||||
nameplate:EnableElement('Stagger')
|
||||
end
|
||||
|
||||
local anchor = target and NP:GetClassAnchor()
|
||||
nameplate.Stagger:ClearAllPoints()
|
||||
nameplate.Stagger:Point('CENTER', anchor or nameplate, 'CENTER', db.classpower.xOffset, db.classpower.yOffset)
|
||||
|
||||
nameplate.Stagger:Size(db.classpower.width, db.classpower.height)
|
||||
elseif nameplate:IsElementEnabled('Stagger') then
|
||||
nameplate:DisableElement('Stagger')
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,302 @@
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local UF = E:GetModule('UnitFrames')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local ipairs = ipairs
|
||||
local unpack = unpack
|
||||
local UnitPlayerControlled = UnitPlayerControlled
|
||||
local UnitClass = UnitClass
|
||||
local UnitReaction = UnitReaction
|
||||
local UnitIsConnected = UnitIsConnected
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
function NP:Health_UpdateColor(_, unit)
|
||||
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
|
||||
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
|
||||
if isUnit then
|
||||
unit = self.unit
|
||||
end
|
||||
end
|
||||
if not unit or self.unit ~= unit then return end
|
||||
local element = self.Health
|
||||
|
||||
local r, g, b, t
|
||||
if element.colorDisconnected and not UnitIsConnected(unit) then
|
||||
t = self.colors.disconnected
|
||||
elseif (element.colorClass and self.isPlayer) or (element.colorClassNPC and not self.isPlayer) or (element.colorClassPet and UnitPlayerControlled(unit) and not self.isPlayer) then
|
||||
local _, class = UnitClass(unit)
|
||||
t = self.colors.class[class]
|
||||
elseif element.colorReaction and UnitReaction(unit, 'player') then
|
||||
local reaction = UnitReaction(unit, 'player')
|
||||
t = NP.db.colors.reactions[reaction == 4 and 'neutral' or reaction <= 3 and 'bad' or 'good']
|
||||
elseif element.colorSmooth then
|
||||
r, g, b = self:ColorGradient(element.cur or 1, element.max or 1, unpack(element.smoothGradient or self.colors.smooth))
|
||||
elseif element.colorHealth then
|
||||
t = NP.db.colors.health
|
||||
end
|
||||
|
||||
if t then
|
||||
r, g, b = t.r, t.g, t.b
|
||||
element.r, element.g, element.b = r, g, b -- save these for the style filter to switch back
|
||||
end
|
||||
|
||||
local sf = NP:StyleFilterChanges(self)
|
||||
if sf.HealthColor then
|
||||
r, g, b = sf.HealthColor.r, sf.HealthColor.g, sf.HealthColor.b
|
||||
end
|
||||
|
||||
if b then
|
||||
element:SetStatusBarColor(r, g, b)
|
||||
|
||||
if element.bg then
|
||||
element.bg:SetVertexColor(r * NP.multiplier, g * NP.multiplier, b * NP.multiplier)
|
||||
end
|
||||
end
|
||||
|
||||
if element.PostUpdateColor then
|
||||
element:PostUpdateColor(unit, r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_Health(nameplate)
|
||||
local Health = CreateFrame('StatusBar', nameplate:GetName()..'Health', nameplate)
|
||||
Health:SetParent(nameplate)
|
||||
Health:CreateBackdrop('Transparent', nil, nil, nil, nil, true, true)
|
||||
Health:SetStatusBarTexture(LSM:Fetch('statusbar', NP.db.statusbar))
|
||||
Health.considerSelectionInCombatHostile = true
|
||||
Health.UpdateColor = NP.Health_UpdateColor
|
||||
|
||||
NP.StatusBars[Health] = true
|
||||
|
||||
local statusBarTexture = Health:GetStatusBarTexture()
|
||||
local healthFlashTexture = Health:CreateTexture(nameplate:GetName()..'FlashTexture', 'OVERLAY')
|
||||
healthFlashTexture:SetTexture(LSM:Fetch('background', 'ElvUI Blank'))
|
||||
healthFlashTexture:Point('BOTTOMLEFT', statusBarTexture, 'BOTTOMLEFT')
|
||||
healthFlashTexture:Point('TOPRIGHT', statusBarTexture, 'TOPRIGHT')
|
||||
healthFlashTexture:Hide()
|
||||
nameplate.HealthFlashTexture = healthFlashTexture
|
||||
|
||||
local clipFrame = CreateFrame("Frame", nil, Health)
|
||||
clipFrame:SetScript("OnUpdate", UF.HealthClipFrame_OnUpdate)
|
||||
clipFrame:SetAllPoints()
|
||||
clipFrame:EnableMouse(false)
|
||||
clipFrame.__frame = Health
|
||||
Health.ClipFrame = clipFrame
|
||||
|
||||
return Health
|
||||
end
|
||||
|
||||
function NP:Health_SetColors(nameplate, threatColors)
|
||||
if threatColors then -- managed by ThreatIndicator_PostUpdate
|
||||
nameplate.Health:SetColorTapping(nil)
|
||||
nameplate.Health:SetColorSelection(nil)
|
||||
nameplate.Health.colorReaction = nil
|
||||
nameplate.Health.colorClass = nil
|
||||
else
|
||||
local db = NP:PlateDB(nameplate)
|
||||
nameplate.Health:SetColorTapping(true)
|
||||
nameplate.Health:SetColorSelection(true)
|
||||
nameplate.Health.colorReaction = true
|
||||
nameplate.Health.colorClass = db.health and db.health.useClassColor
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Update_Health(nameplate, skipUpdate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
NP:Health_SetColors(nameplate)
|
||||
|
||||
if skipUpdate then return end
|
||||
|
||||
if db.health.enable then
|
||||
if not nameplate:IsElementEnabled('Health') then
|
||||
nameplate:EnableElement('Health')
|
||||
end
|
||||
|
||||
nameplate.Health:Point('CENTER')
|
||||
nameplate.Health:Point('LEFT')
|
||||
nameplate.Health:Point('RIGHT')
|
||||
|
||||
E:SetSmoothing(nameplate.Health, NP.db.smoothbars)
|
||||
elseif nameplate:IsElementEnabled('Health') then
|
||||
nameplate:DisableElement('Health')
|
||||
end
|
||||
|
||||
nameplate.Health.width = db.health.width
|
||||
nameplate.Health.height = db.health.height
|
||||
nameplate.Health:Height(db.health.height)
|
||||
end
|
||||
|
||||
function NP:Update_HealComm(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
if db.health.enable and db.health.healPrediction then
|
||||
if not nameplate:IsElementEnabled('HealCommBar') then
|
||||
nameplate:EnableElement('HealCommBar')
|
||||
end
|
||||
|
||||
nameplate.HealCommBar.myBar:SetStatusBarColor(NP.db.colors.healPrediction.personal.r, NP.db.colors.healPrediction.personal.g, NP.db.colors.healPrediction.personal.b)
|
||||
nameplate.HealCommBar.otherBar:SetStatusBarColor(NP.db.colors.healPrediction.others.r, NP.db.colors.healPrediction.others.g, NP.db.colors.healPrediction.others.b)
|
||||
elseif nameplate:IsElementEnabled('HealCommBar') then
|
||||
nameplate:DisableElement('HealCommBar')
|
||||
end
|
||||
end
|
||||
|
||||
function NP.HealthClipFrame_HealComm(frame)
|
||||
local pred = frame.HealCommBar
|
||||
if pred then
|
||||
NP:SetAlpha_HealComm(pred, true)
|
||||
NP:SetVisibility_HealComm(pred)
|
||||
end
|
||||
end
|
||||
|
||||
function NP:SetAlpha_HealComm(obj, show)
|
||||
obj.myBar:SetAlpha(show and 1 or 0)
|
||||
obj.otherBar:SetAlpha(show and 1 or 0)
|
||||
end
|
||||
|
||||
function NP:SetVisibility_HealComm(obj)
|
||||
-- the first update is from `HealthClipFrame_HealComm`
|
||||
-- we set this variable to allow `Configure_HealComm` to
|
||||
-- update the elements overflow lock later on by option
|
||||
if not obj.allowClippingUpdate then
|
||||
obj.allowClippingUpdate = true
|
||||
end
|
||||
|
||||
if obj.maxOverflow > 1 then
|
||||
obj.myBar:SetParent(obj.health)
|
||||
obj.otherBar:SetParent(obj.health)
|
||||
else
|
||||
obj.myBar:SetParent(obj.parent)
|
||||
obj.otherBar:SetParent(obj.parent)
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_HealComm(frame)
|
||||
local health = frame.Health
|
||||
local parent = health.ClipFrame
|
||||
|
||||
local myBar = CreateFrame("StatusBar", nil, parent)
|
||||
local otherBar = CreateFrame("StatusBar", nil, parent)
|
||||
|
||||
myBar:SetFrameLevel(health:GetFrameLevel()+1)
|
||||
otherBar:SetFrameLevel(health:GetFrameLevel()+1)
|
||||
|
||||
NP.StatusBars[myBar] = true
|
||||
NP.StatusBars[otherBar] = true
|
||||
|
||||
local healPrediction = {
|
||||
myBar = myBar,
|
||||
otherBar = otherBar,
|
||||
PostUpdate = NP.UpdateHealComm,
|
||||
maxOverflow = 1,
|
||||
health = health,
|
||||
parent = parent,
|
||||
frame = frame
|
||||
}
|
||||
|
||||
NP:SetAlpha_HealComm(healPrediction)
|
||||
|
||||
return healPrediction
|
||||
end
|
||||
|
||||
function NP:Configure_HealComm(frame)
|
||||
local db = NP:PlateDB(frame)
|
||||
|
||||
if db.health.enable and db.health.healPrediction then
|
||||
if not frame:IsElementEnabled('HealComm4') then
|
||||
frame:EnableElement('HealComm4')
|
||||
end
|
||||
|
||||
local healPrediction = frame.HealCommBar
|
||||
local c = db.colors.healPrediction
|
||||
healPrediction.maxOverflow = 1 + (c.maxOverflow or 0)
|
||||
|
||||
if healPrediction.allowClippingUpdate then
|
||||
NP:SetVisibility_HealComm(healPrediction)
|
||||
end
|
||||
|
||||
local health = frame.Health
|
||||
local orientation = health:GetOrientation()
|
||||
|
||||
local myBar = healPrediction.myBar
|
||||
local otherBar = healPrediction.otherBar
|
||||
|
||||
myBar:SetOrientation(orientation)
|
||||
otherBar:SetOrientation(orientation)
|
||||
|
||||
if orientation == "HORIZONTAL" then
|
||||
local width = health:GetWidth()
|
||||
width = (width > 0 and width) or health.WIDTH
|
||||
local healthTexture = health:GetStatusBarTexture()
|
||||
|
||||
myBar:Size(width, 0)
|
||||
myBar:ClearAllPoints()
|
||||
myBar:Point("TOP", health, "TOP")
|
||||
myBar:Point("BOTTOM", health, "BOTTOM")
|
||||
myBar:Point("LEFT", healthTexture, "RIGHT")
|
||||
|
||||
otherBar:Size(width, 0)
|
||||
otherBar:ClearAllPoints()
|
||||
otherBar:Point("TOP", health, "TOP")
|
||||
otherBar:Point("BOTTOM", health, "BOTTOM")
|
||||
otherBar:Point("LEFT", myBar:GetStatusBarTexture(), "RIGHT")
|
||||
else
|
||||
local height = health:GetHeight()
|
||||
height = (height > 0 and height) or health.HEIGHT
|
||||
local healthTexture = health:GetStatusBarTexture()
|
||||
|
||||
myBar:Size(0, height)
|
||||
myBar:ClearAllPoints()
|
||||
myBar:Point("LEFT", health, "LEFT")
|
||||
myBar:Point("RIGHT", health, "RIGHT")
|
||||
myBar:Point("BOTTOM", healthTexture, "TOP")
|
||||
|
||||
otherBar:Size(0, height)
|
||||
otherBar:ClearAllPoints()
|
||||
otherBar:Point("LEFT", health, "LEFT")
|
||||
otherBar:Point("RIGHT", health, "RIGHT")
|
||||
otherBar:Point("BOTTOM", myBar:GetStatusBarTexture(), "TOP")
|
||||
end
|
||||
|
||||
frame.HealCommBar.myBar:SetStatusBarColor(NP.db.colors.healPrediction.personal.r, NP.db.colors.healPrediction.personal.g, NP.db.colors.healPrediction.personal.b)
|
||||
frame.HealCommBar.otherBar:SetStatusBarColor(NP.db.colors.healPrediction.others.r, NP.db.colors.healPrediction.others.g, NP.db.colors.healPrediction.others.b)
|
||||
elseif frame:IsElementEnabled('HealComm4') then
|
||||
frame:DisableElement('HealComm4')
|
||||
end
|
||||
end
|
||||
|
||||
local function UpdateFillBar(frame, previousTexture, bar, amount)
|
||||
if amount == 0 then
|
||||
bar:Hide()
|
||||
return previousTexture
|
||||
end
|
||||
|
||||
local orientation = frame:GetOrientation()
|
||||
bar:ClearAllPoints()
|
||||
if orientation == "HORIZONTAL" then
|
||||
bar:SetPoint("TOPLEFT", previousTexture, "TOPRIGHT")
|
||||
bar:SetPoint("BOTTOMLEFT", previousTexture, "BOTTOMRIGHT")
|
||||
else
|
||||
bar:SetPoint("BOTTOMRIGHT", previousTexture, "TOPRIGHT")
|
||||
bar:SetPoint("BOTTOMLEFT", previousTexture, "TOPLEFT")
|
||||
end
|
||||
|
||||
local totalWidth, totalHeight = frame:GetSize()
|
||||
if orientation == "HORIZONTAL" then
|
||||
bar:Width(totalWidth)
|
||||
else
|
||||
bar:Height(totalHeight)
|
||||
end
|
||||
|
||||
return bar:GetStatusBarTexture()
|
||||
end
|
||||
|
||||
function NP:UpdateHealComm(_, myIncomingHeal, allIncomingHeal)
|
||||
local health = self.health
|
||||
local previousTexture = health:GetStatusBarTexture()
|
||||
|
||||
previousTexture = UpdateFillBar(health, previousTexture, self.myBar, myIncomingHeal)
|
||||
UpdateFillBar(health, previousTexture, self.otherBar, allIncomingHeal)
|
||||
end
|
||||
@@ -0,0 +1,313 @@
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
local strfind = strfind
|
||||
local ipairs, unpack = ipairs, unpack
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
local targetIndicators = {'Spark', 'TopIndicator', 'LeftIndicator', 'RightIndicator'}
|
||||
|
||||
function NP:Construct_QuestIcons(nameplate)
|
||||
local QuestIcons = CreateFrame('Frame', nameplate:GetName() .. 'QuestIcons', nameplate)
|
||||
QuestIcons:Size(20)
|
||||
QuestIcons:Hide()
|
||||
|
||||
for _, object in ipairs(NP.QuestIcons.iconTypes) do
|
||||
local icon = QuestIcons:CreateTexture(nil, 'BORDER', nil, 1)
|
||||
icon.Text = QuestIcons:CreateFontString(nil, 'OVERLAY')
|
||||
icon.Text:FontTemplate()
|
||||
icon:Hide()
|
||||
|
||||
QuestIcons[object] = icon
|
||||
end
|
||||
|
||||
QuestIcons.Item:SetTexCoord(unpack(E.TexCoords))
|
||||
QuestIcons.Chat:SetTexture([[Interface\WorldMap\ChatBubble_64.PNG]])
|
||||
QuestIcons.Chat:SetTexCoord(0, 0.5, 0.5, 1)
|
||||
|
||||
return QuestIcons
|
||||
end
|
||||
|
||||
function NP:Update_QuestIcons(nameplate)
|
||||
local plateDB = NP:PlateDB(nameplate)
|
||||
local db = plateDB.questIcon
|
||||
|
||||
if db and db.enable and (nameplate.frameType == 'FRIENDLY_NPC' or nameplate.frameType == 'ENEMY_NPC') then
|
||||
if not nameplate:IsElementEnabled('QuestIcons') then
|
||||
nameplate:EnableElement('QuestIcons')
|
||||
end
|
||||
|
||||
nameplate.QuestIcons:ClearAllPoints()
|
||||
nameplate.QuestIcons:Point(E.InversePoints[db.position], nameplate, db.position, db.xOffset, db.yOffset)
|
||||
|
||||
for _, object in ipairs(NP.QuestIcons.iconTypes) do
|
||||
local icon = nameplate.QuestIcons[object]
|
||||
icon:Size(db.size, db.size)
|
||||
icon:SetAlpha(db.hideIcon and 0 or 1)
|
||||
|
||||
local xoffset = strfind(db.textPosition, 'LEFT') and -2 or 2
|
||||
local yoffset = strfind(db.textPosition, 'BOTTOM') and 2 or -2
|
||||
icon.Text:ClearAllPoints()
|
||||
icon.Text:Point('CENTER', icon, db.textPosition, xoffset, yoffset)
|
||||
icon.Text:FontTemplate(LSM:Fetch('font', db.font), db.fontSize, db.fontOutline)
|
||||
icon.Text:SetJustifyH('CENTER')
|
||||
|
||||
icon.size, icon.position = db.size, db.position
|
||||
end
|
||||
elseif nameplate:IsElementEnabled('QuestIcons') then
|
||||
nameplate:DisableElement('QuestIcons')
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_ClassificationIndicator(nameplate)
|
||||
return nameplate:CreateTexture(nameplate:GetName() .. 'ClassificationIndicator', 'OVERLAY')
|
||||
end
|
||||
|
||||
function NP:Update_ClassificationIndicator(nameplate)
|
||||
local plateDB = NP:PlateDB(nameplate)
|
||||
local db = plateDB.eliteIcon
|
||||
|
||||
if db and db.enable and (nameplate.frameType == 'FRIENDLY_NPC' or nameplate.frameType == 'ENEMY_NPC') then
|
||||
if not nameplate:IsElementEnabled('ClassificationIndicator') then
|
||||
nameplate:EnableElement('ClassificationIndicator')
|
||||
end
|
||||
|
||||
nameplate.ClassificationIndicator:ClearAllPoints()
|
||||
nameplate.ClassificationIndicator:Size(db.size, db.size)
|
||||
nameplate.ClassificationIndicator:Point(E.InversePoints[db.position], nameplate, db.position, db.xOffset, db.yOffset)
|
||||
elseif nameplate:IsElementEnabled('ClassificationIndicator') then
|
||||
nameplate:DisableElement('ClassificationIndicator')
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_TargetIndicator(nameplate)
|
||||
local TargetIndicator = CreateFrame('Frame', nameplate:GetName() .. 'TargetIndicator', nameplate)
|
||||
TargetIndicator:SetFrameLevel(nameplate:GetFrameLevel()-1)
|
||||
|
||||
TargetIndicator.Shadow = CreateFrame('Frame', nil, TargetIndicator)
|
||||
TargetIndicator.Shadow:Hide()
|
||||
|
||||
for _, object in ipairs(targetIndicators) do
|
||||
local indicator = TargetIndicator:CreateTexture(nil, 'BACKGROUND')
|
||||
indicator:Hide()
|
||||
|
||||
TargetIndicator[object] = indicator
|
||||
end
|
||||
|
||||
return TargetIndicator
|
||||
end
|
||||
|
||||
function NP:Update_TargetIndicator(nameplate)
|
||||
local enabled = nameplate:IsElementEnabled('TargetIndicator')
|
||||
if nameplate.frameType == 'PLAYER' then
|
||||
if enabled then
|
||||
nameplate:DisableElement('TargetIndicator')
|
||||
end
|
||||
|
||||
return
|
||||
elseif not enabled then
|
||||
nameplate:EnableElement('TargetIndicator')
|
||||
end
|
||||
|
||||
local tdb = NP.db.units.TARGET
|
||||
local indicator = nameplate.TargetIndicator
|
||||
indicator.arrow = E.Media.Textures[NP.db.units.TARGET.arrow] or E.Media.Textures.TopIndicator
|
||||
indicator.lowHealthThreshold = NP.db.lowHealthThreshold
|
||||
indicator.preferGlowColor = NP.db.colors.preferGlowColor
|
||||
indicator.style = tdb.glowStyle
|
||||
|
||||
if indicator.style ~= 'none' then
|
||||
local style, color, size, spacing = tdb.glowStyle, NP.db.colors.glowColor, tdb.arrowSize, tdb.arrowSpacing
|
||||
local r, g, b, a = color.r, color.g, color.b, color.a
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
-- background glow is 2, 6, and 8; 2 is background glow only
|
||||
if not db.health.enable and (style ~= 'style2' and style ~= 'style6' and style ~= 'style8') then
|
||||
style = 'style2'
|
||||
indicator.style = style
|
||||
end
|
||||
|
||||
-- top arrow is 3, 5, 6
|
||||
if indicator.TopIndicator and (style == 'style3' or style == 'style5' or style == 'style6') then
|
||||
indicator.TopIndicator:Point('BOTTOM', nameplate.Health, 'TOP', 0, spacing)
|
||||
indicator.TopIndicator:SetVertexColor(r, g, b, a)
|
||||
indicator.TopIndicator:SetSize(size, size)
|
||||
end
|
||||
|
||||
-- side arrows are 4, 7, 8
|
||||
if indicator.LeftIndicator and indicator.RightIndicator and (style == 'style4' or style == 'style7' or style == 'style8') then
|
||||
indicator.LeftIndicator:Point('LEFT', nameplate.Health, 'RIGHT', spacing, 0)
|
||||
indicator.RightIndicator:Point('RIGHT', nameplate.Health, 'LEFT', -spacing, 0)
|
||||
indicator.LeftIndicator:SetVertexColor(r, g, b, a)
|
||||
indicator.RightIndicator:SetVertexColor(r, g, b, a)
|
||||
indicator.LeftIndicator:SetSize(size, size)
|
||||
indicator.RightIndicator:SetSize(size, size)
|
||||
end
|
||||
|
||||
-- border glow is 1, 5, 7
|
||||
if indicator.Shadow and (style == 'style1' or style == 'style5' or style == 'style7') then
|
||||
indicator.Shadow:SetOutside(nameplate.Health, E.PixelMode and 6 or 8, E.PixelMode and 6 or 8, nil, true)
|
||||
indicator.Shadow:SetBackdropBorderColor(r, g, b)
|
||||
indicator.Shadow:SetAlpha(a)
|
||||
end
|
||||
|
||||
-- background glow is 2, 6, and 8
|
||||
if indicator.Spark and (style == 'style2' or style == 'style6' or style == 'style8') then
|
||||
local size
|
||||
if db.health.enable and not (db.nameOnly or nameOnlySF) then
|
||||
parent = nameplate.Health
|
||||
size = E.Border + 14
|
||||
else
|
||||
parent = nameplate
|
||||
size = -(E.Border + 4)
|
||||
end
|
||||
indicator.Spark:Point('TOPLEFT', parent, 'TOPLEFT', -(size * 2), size)
|
||||
indicator.Spark:Point('BOTTOMRIGHT', parent, 'BOTTOMRIGHT', (size * 2), -size)
|
||||
indicator.Spark:SetVertexColor(r, g, b, a)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_Highlight(nameplate)
|
||||
Highlight = nameplate.nameplateAnchor.blizzHighlight
|
||||
return Highlight
|
||||
end
|
||||
|
||||
function NP:Update_Highlight(nameplate, nameOnlySF)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
if NP.db.highlight and db.enable then
|
||||
if not nameplate:IsElementEnabled('Highlight') then
|
||||
nameplate:EnableElement('Highlight')
|
||||
end
|
||||
|
||||
local highlight = nameplate.Highlight
|
||||
if highlight:GetParent() ~= nameplate then
|
||||
highlight:SetParent(nameplate)
|
||||
end
|
||||
|
||||
if highlight:GetDrawLayer() ~= "OVERLAY" then
|
||||
Highlight:SetDrawLayer("OVERLAY")
|
||||
end
|
||||
|
||||
highlight:SetTexture(E.Media.Textures.Spark)
|
||||
highlight:SetAllPoints(nameplate)
|
||||
|
||||
if db.health.enable and not (db.nameOnly or nameOnlySF) then
|
||||
highlight:SetAlpha(0.75)
|
||||
else
|
||||
highlight:SetAlpha(0.50)
|
||||
end
|
||||
elseif nameplate:IsElementEnabled('Highlight') then
|
||||
nameplate:DisableElement('Highlight')
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_PVPRole(nameplate)
|
||||
local texture = nameplate:CreateTexture(nameplate:GetName() .. 'PVPRole', 'OVERLAY', nil, 1)
|
||||
texture:Size(40)
|
||||
texture.HealerTexture = E.Media.Textures.Healer
|
||||
texture.TankTexture = E.Media.Textures.Tank
|
||||
texture:SetTexture(texture.HealerTexture)
|
||||
|
||||
texture:Hide()
|
||||
|
||||
return texture
|
||||
end
|
||||
|
||||
function NP:Update_PVPRole(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
|
||||
if (nameplate.frameType == 'FRIENDLY_PLAYER' or nameplate.frameType == 'ENEMY_PLAYER') and (db.markHealers or db.markTanks) then
|
||||
if not nameplate:IsElementEnabled('PVPRole') then
|
||||
nameplate:EnableElement('PVPRole')
|
||||
end
|
||||
|
||||
nameplate.PVPRole.ShowHealers = db.markHealers
|
||||
nameplate.PVPRole.ShowTanks = db.markTanks
|
||||
|
||||
nameplate.PVPRole:Point('RIGHT', nameplate.Health, 'LEFT', -6, 0)
|
||||
elseif nameplate:IsElementEnabled('PVPRole') then
|
||||
nameplate:DisableElement('PVPRole')
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Update_Fader(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
local vis = db.visibility
|
||||
|
||||
if not vis or vis.showAlways then
|
||||
if nameplate:IsElementEnabled('Fader') then
|
||||
nameplate:DisableElement('Fader')
|
||||
|
||||
NP:PlateFade(nameplate, 0.5, nameplate:GetAlpha(), 1)
|
||||
end
|
||||
elseif db.enable then
|
||||
if not nameplate.Fader then
|
||||
nameplate.Fader = {}
|
||||
end
|
||||
|
||||
if not nameplate:IsElementEnabled('Fader') then
|
||||
nameplate:EnableElement('Fader')
|
||||
|
||||
nameplate.Fader:SetOption('MinAlpha', 0)
|
||||
nameplate.Fader:SetOption('Smooth', 0.3)
|
||||
nameplate.Fader:SetOption('Hover', true)
|
||||
--nameplate.Fader:SetOption('Power', true)
|
||||
nameplate.Fader:SetOption('Health', true)
|
||||
nameplate.Fader:SetOption('Casting', true)
|
||||
end
|
||||
|
||||
nameplate.Fader:SetOption('Combat', vis.showInCombat)
|
||||
nameplate.Fader:SetOption('PlayerTarget', vis.showWithTarget)
|
||||
nameplate.Fader:SetOption('DelayAlpha', (vis.alphaDelay > 0 and vis.alphaDelay) or nil)
|
||||
nameplate.Fader:SetOption('Delay', (vis.hideDelay > 0 and vis.hideDelay) or nil)
|
||||
|
||||
nameplate.Fader:ForceUpdate()
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_Cutaway(nameplate)
|
||||
local frameName = nameplate:GetName()
|
||||
local Cutaway = {}
|
||||
|
||||
Cutaway.Health = nameplate.Health.ClipFrame:CreateTexture(frameName .. 'CutawayHealth')
|
||||
local healthTexture = nameplate.Health:GetStatusBarTexture()
|
||||
Cutaway.Health:Point('TOPLEFT', healthTexture, 'TOPRIGHT')
|
||||
Cutaway.Health:Point('BOTTOMLEFT', healthTexture, 'BOTTOMRIGHT')
|
||||
|
||||
-- Cutaway.Power = nameplate.Power.ClipFrame:CreateTexture(frameName .. 'CutawayPower')
|
||||
-- local powerTexture = nameplate.Power:GetStatusBarTexture()
|
||||
-- Cutaway.Power:Point('TOPLEFT', powerTexture, 'TOPRIGHT')
|
||||
-- Cutaway.Power:Point('BOTTOMLEFT', powerTexture, 'BOTTOMRIGHT')
|
||||
|
||||
return Cutaway
|
||||
end
|
||||
|
||||
function NP:Update_Cutaway(nameplate)
|
||||
local eitherEnabled = NP.db.cutaway.health.enabled or NP.db.cutaway.power.enabled
|
||||
if not eitherEnabled then
|
||||
if nameplate:IsElementEnabled('Cutaway') then
|
||||
nameplate:DisableElement('Cutaway')
|
||||
end
|
||||
else
|
||||
if not nameplate:IsElementEnabled('Cutaway') then
|
||||
nameplate:EnableElement('Cutaway')
|
||||
end
|
||||
|
||||
nameplate.Cutaway:UpdateConfigurationValues(NP.db.cutaway)
|
||||
|
||||
if NP.db.cutaway.health.forceBlankTexture then
|
||||
nameplate.Cutaway.Health:SetTexture(E.media.blankTex)
|
||||
else
|
||||
nameplate.Cutaway.Health:SetTexture(LSM:Fetch('statusbar', NP.db.statusbar))
|
||||
end
|
||||
|
||||
-- if NP.db.cutaway.power.forceBlankTexture then
|
||||
-- nameplate.Cutaway.Power:SetTexture(E.media.blankTex)
|
||||
-- else
|
||||
-- nameplate.Cutaway.Power:SetTexture(LSM:Fetch('statusbar', NP.db.statusbar))
|
||||
-- end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,66 @@
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local NP = E:GetModule('NamePlates')
|
||||
|
||||
local _G = _G
|
||||
local unpack = unpack
|
||||
local hooksecurefunc = hooksecurefunc
|
||||
|
||||
function NP:Portrait_PostUpdate()
|
||||
local nameplate = self.__owner
|
||||
local db = NP:PlateDB(nameplate)
|
||||
local sf = NP:StyleFilterChanges(nameplate)
|
||||
|
||||
if sf.Portrait or (db.portrait and db.portrait.enable) then
|
||||
if db.portrait.classicon and nameplate.isPlayer then
|
||||
self:SetTexture([[Interface\WorldStateFrame\Icons-Classes]])
|
||||
self:SetTexCoord(unpack(_G.CLASS_ICON_TCOORDS[nameplate.classFile]))
|
||||
self.backdrop:Hide()
|
||||
else
|
||||
self:SetTexCoord(.18, .82, .18, .82)
|
||||
self.backdrop:Show()
|
||||
end
|
||||
else
|
||||
self.backdrop:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Update_PortraitBackdrop()
|
||||
if self.backdrop then
|
||||
self.backdrop:SetShown(self:IsShown())
|
||||
end
|
||||
end
|
||||
|
||||
function NP:Construct_Portrait(nameplate)
|
||||
local Portrait = nameplate:CreateTexture(nameplate:GetName() .. 'Portrait', 'OVERLAY', nil, 2)
|
||||
Portrait:SetTexCoord(.18, .82, .18, .82)
|
||||
Portrait:CreateBackdrop(nil, nil, nil, nil, nil, true, true)
|
||||
Portrait:Hide()
|
||||
|
||||
Portrait.PostUpdate = NP.Portrait_PostUpdate
|
||||
hooksecurefunc(Portrait, 'Hide', NP.Update_PortraitBackdrop)
|
||||
hooksecurefunc(Portrait, 'Show', NP.Update_PortraitBackdrop)
|
||||
|
||||
return Portrait
|
||||
end
|
||||
|
||||
function NP:Update_Portrait(nameplate)
|
||||
local db = NP:PlateDB(nameplate)
|
||||
local sf = NP:StyleFilterChanges(nameplate)
|
||||
|
||||
if sf.Portrait or (db.portrait and db.portrait.enable) then
|
||||
if not nameplate:IsElementEnabled('Portrait') then
|
||||
nameplate:EnableElement('Portrait')
|
||||
nameplate.Portrait:ForceUpdate()
|
||||
end
|
||||
|
||||
nameplate.Portrait:Size(db.portrait.width, db.portrait.height)
|
||||
|
||||
-- These values are forced in name only mode inside of DisablePlate
|
||||
if not (db.nameOnly or sf.NameOnly) then
|
||||
nameplate.Portrait:ClearAllPoints()
|
||||
nameplate.Portrait:Point(E.InversePoints[db.portrait.position], nameplate, db.portrait.position, db.portrait.xOffset, db.portrait.yOffset)
|
||||
end
|
||||
elseif nameplate:IsElementEnabled('Portrait') then
|
||||
nameplate:DisableElement('Portrait')
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,17 +1,19 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Script file="Nameplates.lua"/>
|
||||
<Script file="StyleFilter.lua"/>
|
||||
<Script file="Elements\Auras.lua"/>
|
||||
<Script file="Elements\CastBar.lua"/>
|
||||
<Script file="Elements\ComboPoints.lua"/>
|
||||
<Script file="Elements\Glow.lua"/>
|
||||
<Script file="Elements\HealthBar.lua"/>
|
||||
<Script file="Elements\CutawayHealth.lua"/>
|
||||
<Script file="Elements\Level.lua"/>
|
||||
<Script file="Elements\Name.lua"/>
|
||||
<Script file="Elements\RaidIcon.lua"/>
|
||||
<Script file="Elements\HealerIcon.lua"/>
|
||||
<Script file="Elements\Elite.lua"/>
|
||||
<Script file="Elements\Highlight.lua"/>
|
||||
<Script file="Elements\IconFrame.lua"/>
|
||||
</Ui>
|
||||
<Ui xmlns='http://www.blizzard.com/wow/ui/'>
|
||||
<Script file='Nameplates.lua'/>
|
||||
<Script file='StyleFilter.lua'/>
|
||||
<Script file='Elements\Auras.lua'/>
|
||||
<Script file='Elements\BossMods.lua'/>
|
||||
<Script file='Elements\CastBar.lua'/>
|
||||
<Script file='Elements\ClassPower.lua'/>
|
||||
<Script file='Elements\Health.lua'/>
|
||||
<Script file='Elements\Plugins.lua'/>
|
||||
<Script file='Elements\Power.lua'/>
|
||||
<Script file='Elements\Portraits.lua'/>
|
||||
<Script file='Elements\PvP.lua'/>
|
||||
<Script file='Elements\RaidTargetIndicator.lua'/>
|
||||
<Script file='Elements\Tags.lua'/>
|
||||
<Script file='Elements\Threat.lua'/>
|
||||
<Script file='Plugins\ClassificationIndicator.lua'/>
|
||||
<Script file='Plugins\QuestIcons.lua'/>
|
||||
<Script file='Plugins\TargetIndicator.lua'/>
|
||||
</Ui>
|
||||
|
||||
+640
-1048
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,60 @@
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local oUF = E.oUF
|
||||
|
||||
local function Update(self)
|
||||
local element = self.ClassificationIndicator
|
||||
|
||||
if element.PreUpdate then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local classification = self.classification
|
||||
if classification == 'elite' or classification == 'worldboss' then
|
||||
element:SetAtlas('nameplates-icon-elite-gold')
|
||||
element:Show()
|
||||
elseif classification == 'rareelite' or classification == 'rare' then
|
||||
element:SetAtlas('nameplates-icon-elite-silver')
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
if element.PostUpdate then
|
||||
return element:PostUpdate(classification)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
return (self.ClassificationIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.ClassificationIndicator
|
||||
if element then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
if element:IsObjectType('Texture') and not element:GetTexture() then
|
||||
element:SetTexture([[Interface\TARGETINGFRAME\Nameplates]])
|
||||
end
|
||||
|
||||
self:RegisterEvent('UNIT_CLASSIFICATION_CHANGED', Path)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.ClassificationIndicator
|
||||
if element then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_CLASSIFICATION_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('ClassificationIndicator', Path, Enable, Disable)
|
||||
@@ -0,0 +1,77 @@
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local oUF = E.oUF
|
||||
|
||||
local UnitExists = UnitExists
|
||||
local UnitIsUnit = UnitIsUnit
|
||||
|
||||
local function MouseOnUnit(frame)
|
||||
if frame and frame:IsVisible() and UnitExists('mouseover') then
|
||||
return frame.unit and UnitIsUnit('mouseover', frame.unit)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function OnUpdate(self, elapsed)
|
||||
if self.elapsed and self.elapsed > 0.1 then
|
||||
if not MouseOnUnit(self) then
|
||||
self:Hide()
|
||||
self:ForceUpdate()
|
||||
end
|
||||
|
||||
self.elapsed = 0
|
||||
else
|
||||
self.elapsed = (self.elapsed or 0) + elapsed
|
||||
end
|
||||
end
|
||||
|
||||
local function Update(self)
|
||||
local element = self.Highlight
|
||||
|
||||
if element.PreUpdate then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
if MouseOnUnit(self) then
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
if element.PostUpdate then
|
||||
return element:PostUpdate(element:IsShown())
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
return (self.Highlight.Override or Update)(self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.Highlight
|
||||
if element then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
element:SetScript('OnUpdate', OnUpdate)
|
||||
|
||||
self:RegisterEvent('UPDATE_MOUSEOVER_UNIT', Path, true)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.Highlight
|
||||
if element then
|
||||
element:Hide()
|
||||
element:SetScript('OnUpdate', nil)
|
||||
|
||||
self:UnregisterEvent('UPDATE_MOUSEOVER_UNIT', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Highlight', Path, Enable, Disable)
|
||||
@@ -0,0 +1,315 @@
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local oUF = E.oUF
|
||||
|
||||
local _G = _G
|
||||
local pairs, ipairs, ceil, floor, tonumber = pairs, ipairs, ceil, floor, tonumber
|
||||
local wipe, strmatch, strlower, strfind = wipe, strmatch, strlower, strfind
|
||||
|
||||
local IsInInstance = IsInInstance
|
||||
local UnitIsPlayer = UnitIsPlayer
|
||||
local GetQuestLogSpecialItemInfo = GetQuestLogSpecialItemInfo
|
||||
local GetQuestLogTitle = GetQuestLogTitle
|
||||
local GetNumQuestLogEntries = GetNumQuestLogEntries
|
||||
local C_Quest_GetQuestID = GenerateClosure(C_Quest.GetQuestID, C_Quest)
|
||||
local ThreatTooltip = THREAT_TOOLTIP:gsub('%%d', '%%d-')
|
||||
|
||||
local questIcons = {
|
||||
iconTypes = { 'Default', 'Item', 'Skull', 'Chat' },
|
||||
indexByID = {}, --[questID] = questIndex
|
||||
activeQuests = {} --[questTitle] = questID
|
||||
}
|
||||
|
||||
NP.QuestIcons = questIcons
|
||||
|
||||
local typesLocalized = {
|
||||
enUS = {
|
||||
--- short matching applies here so,
|
||||
-- kill: killed, destory: destoryed, etc ...
|
||||
KILL = {'slain', 'destroy', 'eliminate', 'repel', 'kill', 'defeat'},
|
||||
CHAT = {'speak', 'talk'}
|
||||
},
|
||||
deDE = {
|
||||
KILL = {'besiegen', 'besiegt', 'getötet', 'töten', 'tötet', 'vernichtet', 'zerstört', 'genährt'},
|
||||
CHAT = {'befragt', 'sprecht'}
|
||||
},
|
||||
ruRU = {
|
||||
KILL = {'убит', 'уничтож', 'разбомблен', 'разбит', 'сразит'},
|
||||
CHAT = {'поговорит', 'спрашивать'}
|
||||
},
|
||||
esMX = {
|
||||
-- asesinad: asesinado, asesinados, asesinada, asesinadas
|
||||
-- derrota: derrotar, derrotado, derrotados, derrotada, derrotadas
|
||||
-- destrui: destruir, destruido, destruidos, destruida, destruidas
|
||||
-- elimin: eliminar, elimine, eliminadas, eliminada, eliminados, eliminado
|
||||
-- repel: repele, repelido, repelidos, repelida, repelidas
|
||||
KILL = {'asesinad', 'destrui', 'elimin', 'repel', 'derrota'},
|
||||
CHAT = {'habla', 'pídele'}
|
||||
},
|
||||
ptBR = {
|
||||
-- destrui: above but also destruição
|
||||
-- repel: repelir, repelido, repelidos, repelida, repelidas
|
||||
KILL = {'morto', 'morta', 'matar', 'destrui', 'elimin', 'repel', 'derrota'},
|
||||
CHAT = {'falar', 'pedir'}
|
||||
},
|
||||
frFR = {
|
||||
-- tué: tués, tuée, tuées
|
||||
-- abattu: abattus, abattue
|
||||
-- détrui: détruite, détruire, détruit, détruits, détruites
|
||||
-- repouss: repousser, repoussés, repoussée, repoussées
|
||||
-- élimin: éliminer, éliminé, éliminés, éliminée, éliminées
|
||||
KILL = {'tué', 'tuer', 'attaqué', 'attaque', 'abattre', 'abattu', 'détrui', 'élimin', 'repouss', 'vaincu', 'vaincre'},
|
||||
-- demande: demander, demandez
|
||||
-- parle: parler, parlez
|
||||
CHAT = {'parle', 'demande'}
|
||||
},
|
||||
koKR = {
|
||||
KILL = {'쓰러뜨리기', '물리치기', '공격', '파괴'},
|
||||
CHAT = {'대화'}
|
||||
},
|
||||
zhCN = {
|
||||
KILL = {'消灭', '摧毁', '击败', '毁灭', '击退'},
|
||||
CHAT = {'交谈', '谈一谈'}
|
||||
},
|
||||
zhTW = {
|
||||
KILL = {'毀滅', '擊退', '殺死'},
|
||||
CHAT = {'交談', '說話'}
|
||||
},
|
||||
}
|
||||
|
||||
local questTypes = typesLocalized[E.locale] or typesLocalized.enUS
|
||||
|
||||
local function CheckTextForQuest(text)
|
||||
local x, y = strmatch(text, '(%d+)/(%d+)')
|
||||
if x and y then
|
||||
local diff = floor(y - x)
|
||||
if diff > 0 then
|
||||
return diff
|
||||
end
|
||||
elseif not strmatch(text, ThreatTooltip) then
|
||||
local progress = tonumber(strmatch(text, '([%d%.]+)%%'))
|
||||
if progress and progress <= 100 then
|
||||
return ceil(100 - progress), true
|
||||
end
|
||||
end
|
||||
end
|
||||
NP.QuestIcons.CheckTextForQuest = CheckTextForQuest
|
||||
|
||||
local function GetQuests(unitID)
|
||||
if IsInInstance() then return end
|
||||
|
||||
E.ScanTooltip:SetOwner(_G.UIParent, 'ANCHOR_NONE')
|
||||
E.ScanTooltip:SetUnit(unitID)
|
||||
E.ScanTooltip:Show()
|
||||
|
||||
local QuestList, notMyQuest, activeID
|
||||
for i = 3, E.ScanTooltip:NumLines() do
|
||||
local str = _G['ElvUI_ScanTooltipTextLeft' .. i]
|
||||
local text = str and str:GetText()
|
||||
if not text or text == '' then return end
|
||||
|
||||
if UnitIsPlayer(text) then
|
||||
notMyQuest = text ~= E.myname
|
||||
elseif text and not notMyQuest then
|
||||
local count, percent = CheckTextForQuest(text)
|
||||
|
||||
-- this line comes from one line up in the tooltip
|
||||
local activeQuest = questIcons.activeQuests[text]
|
||||
if activeQuest then activeID = activeQuest end
|
||||
|
||||
if count then
|
||||
local type, index, texture, _
|
||||
if activeID then
|
||||
index = questIcons.indexByID[activeID]
|
||||
_, texture = GetQuestLogSpecialItemInfo(index)
|
||||
end
|
||||
|
||||
if texture then
|
||||
type = 'QUEST_ITEM'
|
||||
else
|
||||
local lowerText = strlower(text)
|
||||
|
||||
-- check kill type first
|
||||
for _, listText in ipairs(questTypes.KILL) do
|
||||
if strfind(lowerText, listText, nil, true) then
|
||||
type = 'KILL'
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- check chat type if kill type doesn't exist
|
||||
if not type then
|
||||
for _, listText in ipairs(questTypes.CHAT) do
|
||||
if strfind(lowerText, listText, nil, true) then
|
||||
type = 'CHAT'
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not QuestList then QuestList = {} end
|
||||
QuestList[#QuestList + 1] = {
|
||||
isPercent = percent,
|
||||
itemTexture = texture,
|
||||
objectiveCount = count,
|
||||
questType = type or 'DEFAULT',
|
||||
-- below keys are currently unused
|
||||
questLogIndex = index,
|
||||
questID = activeID
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
E.ScanTooltip:Hide()
|
||||
return QuestList
|
||||
end
|
||||
|
||||
local function hideIcons(element)
|
||||
for _, object in pairs(questIcons.iconTypes) do
|
||||
local icon = element[object]
|
||||
icon:Hide()
|
||||
|
||||
if icon.Text then
|
||||
icon.Text:SetText('')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function Update(self, event, arg1)
|
||||
local element = self.QuestIcons
|
||||
if not element then return end
|
||||
|
||||
local unit = (event == 'UNIT_NAME_UPDATE' and arg1) or self.unit
|
||||
if unit ~= self.unit then return end
|
||||
|
||||
if element.PreUpdate then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
hideIcons(element)
|
||||
|
||||
local QuestList = GetQuests(unit)
|
||||
if QuestList then
|
||||
element:Show()
|
||||
else
|
||||
element:Hide()
|
||||
return
|
||||
end
|
||||
|
||||
local shownCount
|
||||
for i = 1, #QuestList do
|
||||
local quest = QuestList[i]
|
||||
local objectiveCount = quest.objectiveCount
|
||||
local questType = quest.questType
|
||||
local isPercent = quest.isPercent
|
||||
|
||||
if isPercent or objectiveCount > 0 then
|
||||
local icon
|
||||
if questType == 'DEFAULT' then
|
||||
icon = element.Default
|
||||
elseif questType == 'KILL' then
|
||||
icon = element.Skull
|
||||
elseif questType == 'CHAT' then
|
||||
icon = element.Chat
|
||||
elseif questType == 'QUEST_ITEM' then
|
||||
icon = element.Item
|
||||
end
|
||||
|
||||
if icon and not icon:IsShown() then
|
||||
shownCount = (shownCount and shownCount + 1) or 0
|
||||
|
||||
local size = icon.size or 25
|
||||
local setPosition = icon.position or 'TOPLEFT'
|
||||
local newPosition = E.InversePoints[setPosition]
|
||||
local offset = shownCount * (5 + size)
|
||||
|
||||
icon:Show()
|
||||
icon:ClearAllPoints()
|
||||
icon:Point(newPosition, element, newPosition, (strmatch(setPosition, 'LEFT') and -offset) or offset, 0)
|
||||
|
||||
if questType ~= 'CHAT' and icon.Text and (isPercent or objectiveCount > 1) then
|
||||
icon.Text:SetText((isPercent and objectiveCount..'%') or objectiveCount)
|
||||
end
|
||||
|
||||
if questType == 'QUEST_ITEM' then
|
||||
element.Item:SetTexture(quest.itemTexture)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if element.PostUpdate then
|
||||
return element:PostUpdate()
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
return (self.QuestIcons.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.QuestIcons
|
||||
if element then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
if element.Default:IsObjectType('Texture') and not element.Default:GetAtlas() then
|
||||
element.Default:SetAtlas('SmallQuestBang')
|
||||
end
|
||||
if element.Skull:IsObjectType('Texture') and not element.Skull:GetTexture() then
|
||||
element.Skull:SetTexture(E.Media.Textures.SkullIcon)
|
||||
end
|
||||
if element.Chat:IsObjectType('StatusBar') and not element.Chat:GetTexture() then
|
||||
element.Chat:SetTexture([[Interface\WorldMap\ChatBubble_64.PNG]])
|
||||
end
|
||||
|
||||
self:RegisterEvent('QUEST_LOG_UPDATE', Path, true)
|
||||
self:RegisterEvent('UNIT_NAME_UPDATE', Path, true)
|
||||
self:RegisterEvent('PLAYER_ENTERING_WORLD', Path, true)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.QuestIcons
|
||||
if element then
|
||||
element:Hide()
|
||||
hideIcons(element)
|
||||
|
||||
self:UnregisterEvent('QUEST_LOG_UPDATE', Path)
|
||||
self:UnregisterEvent('UNIT_NAME_UPDATE', Path)
|
||||
self:UnregisterEvent('PLAYER_ENTERING_WORLD', Path)
|
||||
end
|
||||
end
|
||||
|
||||
local frame = CreateFrame('Frame')
|
||||
frame:RegisterEvent('QUEST_ACCEPTED')
|
||||
frame:RegisterEvent('QUEST_REMOVED')
|
||||
frame:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
frame:SetScript('OnEvent', function(self, event)
|
||||
wipe(questIcons.indexByID)
|
||||
wipe(questIcons.activeQuests)
|
||||
|
||||
for i = 1, GetNumQuestLogEntries() do
|
||||
local id = C_Quest_GetQuestID(i)
|
||||
if id and id > 0 then
|
||||
questIcons.indexByID[id] = i
|
||||
|
||||
local title = GetQuestLogTitle(i)
|
||||
if title then questIcons.activeQuests[title] = id end
|
||||
end
|
||||
end
|
||||
|
||||
if event == 'PLAYER_ENTERING_WORLD' then
|
||||
self:UnregisterEvent(event)
|
||||
end
|
||||
end)
|
||||
|
||||
oUF:AddElement('QuestIcons', Path, Enable, Disable)
|
||||
@@ -0,0 +1,152 @@
|
||||
local E, L, V, P, G = unpack(ElvUI)
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local ElvUF = E.oUF
|
||||
|
||||
local UnitHealth = UnitHealth
|
||||
local UnitIsUnit = UnitIsUnit
|
||||
local UnitHealthMax = UnitHealthMax
|
||||
|
||||
--[[ Target Glow Style Option Variables
|
||||
style1:'Border',
|
||||
style2:'Background',
|
||||
style3:'Top Arrow Only',
|
||||
style4:'Side Arrows Only',
|
||||
style5:'Border + Top Arrow',
|
||||
style6:'Background + Top Arrow',
|
||||
style7:'Border + Side Arrows',
|
||||
style8:'Background + Side Arrows'
|
||||
]]
|
||||
|
||||
local function HideIndicators(element)
|
||||
if element.TopIndicator then element.TopIndicator:Hide() end
|
||||
if element.LeftIndicator then element.LeftIndicator:Hide() end
|
||||
if element.RightIndicator then element.RightIndicator:Hide() end
|
||||
if element.Shadow then element.Shadow:Hide() end
|
||||
if element.Spark then element.Spark:Hide() end
|
||||
end
|
||||
|
||||
local function ShowIndicators(element, isTarget, color)
|
||||
if isTarget then
|
||||
if element.TopIndicator and (element.style == 'style3' or element.style == 'style5' or element.style == 'style6') then
|
||||
element.TopIndicator:SetVertexColor(color.r, color.g, color.b)
|
||||
element.TopIndicator:SetTexture(element.arrow)
|
||||
element.TopIndicator:Show()
|
||||
end
|
||||
|
||||
if element.LeftIndicator and element.RightIndicator and (element.style == 'style4' or element.style == 'style7' or element.style == 'style8') then
|
||||
element.LeftIndicator:SetVertexColor(color.r, color.g, color.b)
|
||||
element.RightIndicator:SetVertexColor(color.r, color.g, color.b)
|
||||
element.LeftIndicator:SetTexture(element.arrow)
|
||||
element.RightIndicator:SetTexture(element.arrow)
|
||||
element.RightIndicator:Show()
|
||||
element.LeftIndicator:Show()
|
||||
end
|
||||
end
|
||||
|
||||
if element.Shadow and (element.style == 'style1' or element.style == 'style5' or element.style == 'style7') then
|
||||
element.Shadow:SetBackdropBorderColor(color.r, color.g, color.b)
|
||||
element.Shadow:Show()
|
||||
end
|
||||
|
||||
if element.Spark and (element.style == 'style2' or element.style == 'style6' or element.style == 'style8') then
|
||||
element.Spark:SetVertexColor(color.r, color.g, color.b)
|
||||
element.Spark:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local function Update(self)
|
||||
local element = self.TargetIndicator
|
||||
if element.PreUpdate then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
HideIndicators(element)
|
||||
|
||||
if element.style ~= 'none' then
|
||||
local isTarget = UnitIsUnit(self.unit, 'target')
|
||||
local lowHealth = element.lowHealthThreshold > 0
|
||||
if isTarget and (element.preferGlowColor or not lowHealth) then
|
||||
ShowIndicators(element, isTarget, NP.db.colors.glowColor)
|
||||
elseif lowHealth then
|
||||
local health, maxHealth = UnitHealth(self.unit), UnitHealthMax(self.unit)
|
||||
local perc = (maxHealth > 0 and health/maxHealth) or 0
|
||||
|
||||
-- color tables are class updated in UpdateMedia
|
||||
if perc <= element.lowHealthThreshold * 0.5 then
|
||||
ShowIndicators(element, isTarget, NP.db.colors.lowHealthHalf)
|
||||
elseif perc <= element.lowHealthThreshold then
|
||||
ShowIndicators(element, isTarget, NP.db.colors.lowHealthColor)
|
||||
elseif isTarget then
|
||||
ShowIndicators(element, isTarget, NP.db.colors.glowColor)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if element.PostUpdate then
|
||||
return element:PostUpdate(self.unit)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
return (self.TargetIndicator.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local element = self.TargetIndicator
|
||||
if element then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
if not element.style then element.style = 'style1' end
|
||||
if not element.preferGlowColor then element.preferGlowColor = true end
|
||||
if not element.lowHealthThreshold then element.lowHealthThreshold = .4 end
|
||||
|
||||
if element.Shadow and element.Shadow:IsObjectType('Frame') and not element.Shadow:GetBackdrop() then
|
||||
element.Shadow:SetBackdrop({edgeFile = E.Media.Textures.GlowTex, edgeSize = 5})
|
||||
end
|
||||
|
||||
if element.Spark and element.Spark:IsObjectType('Texture') and not element.Spark:GetTexture() then
|
||||
element.Spark:SetTexture(E.Media.Textures.Spark)
|
||||
end
|
||||
|
||||
if element.TopIndicator and element.TopIndicator:IsObjectType('Texture') and not element.TopIndicator:GetTexture() then
|
||||
element.TopIndicator:SetTexture(E.Media.Textures.ArrowUp)
|
||||
element.TopIndicator:SetTexCoord(1, 1, 1, 0, 0, 1, 0, 0) --Rotates texture 180 degress (Up arrow to face down)
|
||||
end
|
||||
|
||||
if element.LeftIndicator and element.LeftIndicator:IsObjectType('Texture') and not element.LeftIndicator:GetTexture() then
|
||||
element.LeftIndicator:SetTexture(E.Media.Textures.ArrowUp)
|
||||
element.LeftIndicator:SetTexCoord(1, 0, 0, 0, 1, 1, 0, 1) --Rotates texture 90 degrees clockwise (Up arrow to face right)
|
||||
end
|
||||
|
||||
if element.RightIndicator and element.RightIndicator:IsObjectType('Texture') and not element.RightIndicator:GetTexture() then
|
||||
element.RightIndicator:SetTexture(E.Media.Textures.ArrowUp)
|
||||
element.RightIndicator:SetTexCoord(1, 1, 0, 1, 1, 0, 0, 0) --Flips texture horizontally (Right facing arrow to face left)
|
||||
end
|
||||
|
||||
self:RegisterEvent('UNIT_HEALTH', Path)
|
||||
|
||||
self:RegisterEvent('UNIT_MAXHEALTH', Path)
|
||||
self:RegisterEvent('PLAYER_TARGET_CHANGED', Path, true)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local element = self.TargetIndicator
|
||||
if element then
|
||||
HideIndicators(element)
|
||||
|
||||
self:UnregisterEvent('UNIT_HEALTH', Path)
|
||||
|
||||
self:UnregisterEvent('UNIT_MAXHEALTH', Path)
|
||||
self:UnregisterEvent('PLAYER_TARGET_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
ElvUF:AddElement('TargetIndicator', Path, Enable, Disable)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -137,6 +137,9 @@ S:AddCallback("Skin_BlizzardOptions", function()
|
||||
"InterfaceOptionsCombatPanelTargetOfTarget",
|
||||
"InterfaceOptionsCombatPanelEnemyCastBarsOnPortrait",
|
||||
"InterfaceOptionsCombatPanelEnemyCastBarsOnNameplates",
|
||||
"InterfaceOptionsCombatPanelAoEIndicatorsSelf",
|
||||
"InterfaceOptionsCombatPanelAoEIndicatorsEnemies",
|
||||
"InterfaceOptionsCombatPanelAoEIndicatorsFriendly",
|
||||
"InterfaceOptionsDisplayPanelShowCloak",
|
||||
"InterfaceOptionsDisplayPanelShowHelm",
|
||||
"InterfaceOptionsDisplayPanelShowAggroPercentage",
|
||||
@@ -257,7 +260,11 @@ S:AddCallback("Skin_BlizzardOptions", function()
|
||||
"InterfaceOptionsAscensionLoseControlPanelEnableSlow",
|
||||
"InterfaceOptionsAscensionLoseControlPanelEnableStun",
|
||||
"InterfaceOptionsAscensionLoseControlPanelEnablePacify",
|
||||
|
||||
"InterfaceOptionsDraftPanelAutoPopupDraft",
|
||||
"InterfaceOptionsDraftPanelAutoRevealDraft",
|
||||
"InterfaceOptionsDraftPanelSkipDraftConfirmation",
|
||||
"InterfaceOptionsDraftPanelSkipDraftSacrificeConfirmation",
|
||||
"InterfaceOptionsDraftPanelShowBuildDraftSpellCards",
|
||||
|
||||
"AudioOptionsSoundPanelEnableSound",
|
||||
"AudioOptionsSoundPanelSoundEffects",
|
||||
@@ -306,7 +313,9 @@ S:AddCallback("Skin_BlizzardOptions", function()
|
||||
"InterfaceOptionsCombatPanelSpellActivationOverlayAlpha",
|
||||
"InterfaceOptionsMousePanelMouseLookSpeedSlider",
|
||||
"InterfaceOptionsMousePanelMouseSensitivitySlider",
|
||||
|
||||
"InterfaceOptionsCombatPanelNameplateDistance",
|
||||
"InterfaceOptionsCombatPanelNameplateZ",
|
||||
|
||||
"AudioOptionsSoundPanelSoundQuality",
|
||||
"AudioOptionsSoundPanelSoundChannels",
|
||||
"AudioOptionsSoundPanelMasterVolume",
|
||||
|
||||
@@ -21,7 +21,6 @@ S:AddCallback("Skin_LFD", function()
|
||||
AscensionLFGFrameContent:StripTextures(true)
|
||||
AscensionLFGFrameMenu:StripTextures(true)
|
||||
AscensionLFGFrameInset:StripTextures(true)
|
||||
AscensionLFGFrameInset:CreateBackdrop("Transparent")
|
||||
AscensionLFGFrameInsetNineSlice:StripTextures(true)
|
||||
AscensionLFGFrameNineSlice:StripTextures(true)
|
||||
AscensionLFGFrameMenuNineSlice:StripTextures(true)
|
||||
|
||||
@@ -77,47 +77,29 @@ local function createConfigEnv()
|
||||
__newindex = function(_, key, value) _G[key] = value end,
|
||||
})
|
||||
|
||||
overrideFuncs["namecolor"] = ElvUF.Tags.Methods["namecolor"]
|
||||
overrideFuncs["name:veryshort"] = ElvUF.Tags.Methods["name:veryshort"]
|
||||
overrideFuncs["name:short"] = ElvUF.Tags.Methods["name:short"]
|
||||
overrideFuncs["name:medium"] = ElvUF.Tags.Methods["name:medium"]
|
||||
overrideFuncs["name:long"] = ElvUF.Tags.Methods["name:long"]
|
||||
overrideFuncs['classcolor'] = ElvUF.Tags.Methods['classcolor']
|
||||
overrideFuncs['name:veryshort'] = ElvUF.Tags.Methods['name:veryshort']
|
||||
overrideFuncs['name:short'] = ElvUF.Tags.Methods['name:short']
|
||||
overrideFuncs['name:medium'] = ElvUF.Tags.Methods['name:medium']
|
||||
overrideFuncs['name:long'] = ElvUF.Tags.Methods['name:long']
|
||||
|
||||
overrideFuncs["healthcolor"] = ElvUF.Tags.Methods["healthcolor"]
|
||||
overrideFuncs["health:current"] = ElvUF.Tags.Methods["health:current"]
|
||||
overrideFuncs["health:deficit"] = ElvUF.Tags.Methods["health:deficit"]
|
||||
overrideFuncs["health:current-percent"] = ElvUF.Tags.Methods["health:current-percent"]
|
||||
overrideFuncs["health:current-max"] = ElvUF.Tags.Methods["health:current-max"]
|
||||
overrideFuncs["health:current-max-percent"] = ElvUF.Tags.Methods["health:current-max-percent"]
|
||||
overrideFuncs["health:max"] = ElvUF.Tags.Methods["health:max"]
|
||||
overrideFuncs["health:percent"] = ElvUF.Tags.Methods["health:percent"]
|
||||
overrideFuncs['healthcolor'] = ElvUF.Tags.Methods['healthcolor']
|
||||
overrideFuncs['health:current'] = ElvUF.Tags.Methods['health:current']
|
||||
overrideFuncs['health:deficit'] = ElvUF.Tags.Methods['health:deficit']
|
||||
overrideFuncs['health:current-percent'] = ElvUF.Tags.Methods['health:current-percent']
|
||||
overrideFuncs['health:current-max'] = ElvUF.Tags.Methods['health:current-max']
|
||||
overrideFuncs['health:current-max-percent'] = ElvUF.Tags.Methods['health:current-max-percent']
|
||||
overrideFuncs['health:max'] = ElvUF.Tags.Methods['health:max']
|
||||
overrideFuncs['health:percent'] = ElvUF.Tags.Methods['health:percent']
|
||||
|
||||
overrideFuncs["powercolor"] = ElvUF.Tags.Methods["powercolor"]
|
||||
overrideFuncs["power:current"] = ElvUF.Tags.Methods["power:current"]
|
||||
overrideFuncs["power:deficit"] = ElvUF.Tags.Methods["power:deficit"]
|
||||
overrideFuncs["power:current-percent"] = ElvUF.Tags.Methods["power:current-percent"]
|
||||
overrideFuncs["power:current-max"] = ElvUF.Tags.Methods["power:current-max"]
|
||||
overrideFuncs["power:current-max-percent"] = ElvUF.Tags.Methods["power:current-max-percent"]
|
||||
overrideFuncs["power:max"] = ElvUF.Tags.Methods["power:max"]
|
||||
overrideFuncs["power:percent"] = ElvUF.Tags.Methods["power:percent"]
|
||||
|
||||
overrideFuncs["energycolor"] = ElvUF.Tags.Methods["energycolor"]
|
||||
overrideFuncs["energy:current"] = ElvUF.Tags.Methods["energy:current"]
|
||||
overrideFuncs["energy:deficit"] = ElvUF.Tags.Methods["energy:deficit"]
|
||||
overrideFuncs["energy:current-percent"] = ElvUF.Tags.Methods["energy:current-percent"]
|
||||
overrideFuncs["energy:current-max"] = ElvUF.Tags.Methods["energy:current-max"]
|
||||
overrideFuncs["energy:current-max-percent"] = ElvUF.Tags.Methods["energy:current-max-percent"]
|
||||
overrideFuncs["energy:max"] = ElvUF.Tags.Methods["energy:max"]
|
||||
overrideFuncs["energy:percent"] = ElvUF.Tags.Methods["energy:percent"]
|
||||
|
||||
overrideFuncs["ragecolor"] = ElvUF.Tags.Methods["ragecolor"]
|
||||
overrideFuncs["rage:current"] = ElvUF.Tags.Methods["rage:current"]
|
||||
overrideFuncs["rage:deficit"] = ElvUF.Tags.Methods["rage:deficit"]
|
||||
overrideFuncs["rage:current-percent"] = ElvUF.Tags.Methods["rage:current-percent"]
|
||||
overrideFuncs["rage:current-max"] = ElvUF.Tags.Methods["rage:current-max"]
|
||||
overrideFuncs["rage:current-max-percent"] = ElvUF.Tags.Methods["rage:current-max-percent"]
|
||||
overrideFuncs["rage:max"] = ElvUF.Tags.Methods["rage:max"]
|
||||
overrideFuncs["rage:percent"] = ElvUF.Tags.Methods["rage:percent"]
|
||||
overrideFuncs['powercolor'] = ElvUF.Tags.Methods['powercolor']
|
||||
overrideFuncs['power:current'] = ElvUF.Tags.Methods['power:current']
|
||||
overrideFuncs['power:deficit'] = ElvUF.Tags.Methods['power:deficit']
|
||||
overrideFuncs['power:current-percent'] = ElvUF.Tags.Methods['power:current-percent']
|
||||
overrideFuncs['power:current-max'] = ElvUF.Tags.Methods['power:current-max']
|
||||
overrideFuncs['power:current-max-percent'] = ElvUF.Tags.Methods['power:current-max-percent']
|
||||
overrideFuncs['power:max'] = ElvUF.Tags.Methods['power:max']
|
||||
overrideFuncs['power:percent'] = ElvUF.Tags.Methods['power:percent']
|
||||
end
|
||||
|
||||
function UF:ForceShow(frame)
|
||||
|
||||
@@ -173,6 +173,33 @@ function UF.SortAuraBarName(a, b)
|
||||
return a.name > b.name
|
||||
end
|
||||
|
||||
function UF:ConvertFilters(auras, priority)
|
||||
if not priority or priority == '' then return end
|
||||
|
||||
local list = auras.filterList or {}
|
||||
if next(list) then wipe(list) end
|
||||
|
||||
local special, filters = G.unitframe.specialFilters, E.global.unitframe.aurafilters
|
||||
|
||||
for _, name in next, { strsplit(',', priority) } do
|
||||
local friend, enemy = strmatch(name, '^Friendly:([^,]*)'), strmatch(name, '^Enemy:([^,]*)')
|
||||
local real = friend or enemy or name
|
||||
local custom = filters[real]
|
||||
|
||||
if special[real] or custom then
|
||||
tinsert(list, {
|
||||
name = real,
|
||||
custom = custom,
|
||||
status = (friend and 1) or (enemy and 2)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if next(list) then
|
||||
return list
|
||||
end
|
||||
end
|
||||
|
||||
function UF:CheckFilter(name, caster, spellID, isFriend, isPlayer, isUnit, allowDuration, noDuration, canDispell, ...)
|
||||
for i = 1, select("#", ...) do
|
||||
local filterName = select(i, ...)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
||||
local UF = E:GetModule("UnitFrames")
|
||||
local NP = E:GetModule('NamePlates')
|
||||
local LSM = E.Libs.LSM
|
||||
|
||||
--Lua functions
|
||||
@@ -16,6 +17,58 @@ local UnitCanAttack = UnitCanAttack
|
||||
local UnitIsFriend = UnitIsFriend
|
||||
local UnitIsUnit = UnitIsUnit
|
||||
|
||||
UF.MatchGrowthY = { TOP = 'TOP', BOTTOM = 'BOTTOM' }
|
||||
UF.MatchGrowthX = { LEFT = 'LEFT', RIGHT = 'RIGHT' }
|
||||
|
||||
UF.SortAuraFuncs = {
|
||||
TIME_REMAINING = function(a, b, dir)
|
||||
local A = a.noTime and huge or a.expiration or -huge
|
||||
local B = b.noTime and huge or b.expiration or -huge
|
||||
if dir == 'DESCENDING' then return A < B else return A > B end
|
||||
end,
|
||||
DURATION = function(a, b, dir)
|
||||
local A = a.noTime and huge or a.duration or -huge
|
||||
local B = b.noTime and huge or b.duration or -huge
|
||||
if dir == 'DESCENDING' then return A < B else return A > B end
|
||||
end,
|
||||
NAME = function(a, b, dir)
|
||||
local A, B = a.name or '', b.name or ''
|
||||
if dir == 'DESCENDING' then return A < B else return A > B end
|
||||
end,
|
||||
PLAYER = function(a, b, dir)
|
||||
local A, B = a.isPlayer or false, b.isPlayer or false
|
||||
if dir == 'DESCENDING' then return A and not B else return not A and B end
|
||||
end,
|
||||
}
|
||||
|
||||
UF.SmartPosition = {
|
||||
BUFFS_ON_DEBUFFS = {
|
||||
from = 'BUFFS', to = 'Debuffs',
|
||||
warning = format(L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."], L["Buffs"], L["Debuffs"], L["Frame"]),
|
||||
func = function(db, buffs, debuffs)
|
||||
db.buffs.attachTo = 'DEBUFFS'
|
||||
buffs.attachTo = debuffs
|
||||
|
||||
buffs.PostUpdate = nil
|
||||
debuffs.PostUpdate = UF.UpdateAuraSmartPoisition
|
||||
end
|
||||
},
|
||||
DEBUFFS_ON_BUFFS = {
|
||||
from = 'DEBUFFS', to = 'Buffs',
|
||||
warning = format(L["This setting caused a conflicting anchor point, where '%s' would be attached to itself. Please check your anchor points. Setting '%s' to be attached to '%s'."], L["Debuffs"], L["Buffs"], L["Frame"]),
|
||||
func = function(db, buffs, debuffs)
|
||||
db.debuffs.attachTo = 'BUFFS'
|
||||
debuffs.attachTo = buffs
|
||||
|
||||
debuffs.PostUpdate = nil
|
||||
buffs.PostUpdate = UF.UpdateAuraSmartPoisition
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
UF.SmartPosition.FLUID_BUFFS_ON_DEBUFFS = E:CopyTable({fluid = true}, UF.SmartPosition.BUFFS_ON_DEBUFFS)
|
||||
UF.SmartPosition.FLUID_DEBUFFS_ON_BUFFS = E:CopyTable({fluid = true}, UF.SmartPosition.DEBUFFS_ON_BUFFS)
|
||||
|
||||
function UF:Construct_Buffs(frame)
|
||||
local buffs = CreateFrame("Frame", frame:GetName().."Buffs", frame)
|
||||
buffs.spacing = E.Spacing
|
||||
@@ -134,6 +187,48 @@ function UF:UpdateAuraCooldownPosition(button)
|
||||
button.needsUpdateCooldownPosition = nil
|
||||
end
|
||||
|
||||
function UF:GetAuraElements(frame)
|
||||
if frame.isNamePlate then
|
||||
return frame.Buffs_, frame.Debuffs_
|
||||
else
|
||||
return frame.Buffs, frame.Debuffs
|
||||
end
|
||||
end
|
||||
|
||||
function UF:SetSmartPosition(frame, db)
|
||||
if frame.isNamePlate then db = NP:PlateDB(frame) end
|
||||
|
||||
local position, fluid = db.smartAuraPosition
|
||||
local buffs, debuffs = UF:GetAuraElements(frame)
|
||||
local info = UF.SmartPosition[position]
|
||||
if info then
|
||||
local TO = db[strlower(info.to)]
|
||||
if TO.attachTo == info.from then
|
||||
TO.attachTo = 'FRAME'
|
||||
|
||||
E:Print(info.warning)
|
||||
|
||||
local element = (info.to == 'Debuffs' and debuffs) or buffs
|
||||
element.attachTo = frame
|
||||
element:ClearAllPoints()
|
||||
element:Point(element.initialAnchor, element.attachTo, element.anchorPoint, element.xOffset, element.yOffset)
|
||||
end
|
||||
|
||||
fluid = info.fluid
|
||||
info.func(db, buffs, debuffs, info.isFuild)
|
||||
else
|
||||
buffs.PostUpdate = nil
|
||||
debuffs.PostUpdate = nil
|
||||
end
|
||||
|
||||
if db.debuffs.attachTo == 'BUFFS' and db.buffs.attachTo == 'DEBUFFS' then
|
||||
E:Print(format(L["%s frame has a conflicting anchor point. Forcing the Buffs to be attached to the main unitframe."], E:StringTitle(frame:GetName())))
|
||||
db.buffs.attachTo = 'FRAME'
|
||||
end
|
||||
|
||||
return position, fluid
|
||||
end
|
||||
|
||||
function UF:Configure_Auras(frame, auraType)
|
||||
if not frame.VARIABLES_SET then return end
|
||||
|
||||
@@ -382,6 +477,31 @@ function UF:PostUpdateAura(unit, button)
|
||||
end
|
||||
end
|
||||
|
||||
function UF:GetSmartAuraElements(auras)
|
||||
local Buffs, Debuffs = UF:GetAuraElements(auras:GetParent())
|
||||
if auras == Buffs then
|
||||
return Debuffs, Buffs, auras.visibleBuffs
|
||||
else
|
||||
return Buffs, Debuffs, auras.visibleDebuffs
|
||||
end
|
||||
end
|
||||
|
||||
function UF:UpdateAuraSmartPoisition()
|
||||
local element, other, visible = UF:GetSmartAuraElements(self)
|
||||
|
||||
if visible == 0 then
|
||||
if self.smartFluid then
|
||||
element:ClearAllPoints()
|
||||
element:Point(other.initialAnchor, other.attachTo, other.anchorPoint, other.xOffset, other.yOffset)
|
||||
else
|
||||
other:Height(UF:GetAuraPosition(other, true))
|
||||
end
|
||||
else
|
||||
element:ClearAllPoints()
|
||||
element:Point(element.initialAnchor, element.attachTo, element.anchorPoint, element.xOffset, element.yOffset)
|
||||
end
|
||||
end
|
||||
|
||||
function UF:AuraFilter(unit, button, name, _, _, _, debuffType, duration, expiration, caster, isStealable, _, spellID)
|
||||
if not name then return end -- checking for an aura that is not there, pass nil to break while loop
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ function UF:Construct_Cutaway(frame)
|
||||
|
||||
if frame.Power then
|
||||
local powerTexture = frame.Power:GetStatusBarTexture()
|
||||
local cutawayPower = frame.Power.ClipFrame:CreateTexture(frameName.."CutawayPower")
|
||||
local cutawayPower = frame.Power:CreateTexture(frameName.."CutawayPower")
|
||||
cutawayPower:SetPoint("TOPLEFT", powerTexture, "TOPRIGHT")
|
||||
cutawayPower:SetPoint("BOTTOMLEFT", powerTexture, "BOTTOMRIGHT")
|
||||
cutawayPower:SetTexture(E.media.blankTex)
|
||||
@@ -18,7 +18,7 @@ function UF:Construct_Cutaway(frame)
|
||||
end
|
||||
|
||||
local healthTexture = frame.Health:GetStatusBarTexture()
|
||||
local cutawayHealth = frame.Health.ClipFrame:CreateTexture(frameName.."CutawayHealth")
|
||||
local cutawayHealth = frame.Health:CreateTexture(frameName.."CutawayHealth")
|
||||
cutawayHealth:SetPoint("TOPLEFT", healthTexture, "TOPRIGHT")
|
||||
cutawayHealth:SetPoint("BOTTOMLEFT", healthTexture, "BOTTOMRIGHT")
|
||||
cutawayHealth:SetTexture(E.media.blankTex)
|
||||
|
||||
@@ -65,6 +65,12 @@ function UF:Configure_Happiness(frame)
|
||||
end
|
||||
|
||||
function UF:HappinessOverride(event, unit)
|
||||
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
|
||||
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
|
||||
if isUnit then
|
||||
unit = self.unit
|
||||
end
|
||||
end
|
||||
if not unit or self.unit ~= unit then return end
|
||||
|
||||
local db = self.db
|
||||
|
||||
@@ -60,7 +60,7 @@ function UF:Configure_Energy(frame)
|
||||
local energy = frame.Energy
|
||||
energy.origParent = frame
|
||||
|
||||
if frame.USE_ENERGYBAR then
|
||||
if frame.USE_ENERGYBAR and C_Player:IsHero() then
|
||||
if not frame:IsElementEnabled("Energy") then
|
||||
frame:EnableElement("Energy")
|
||||
energy:Show()
|
||||
|
||||
@@ -60,7 +60,7 @@ function UF:Configure_Rage(frame)
|
||||
local rage = frame.Rage
|
||||
rage.origParent = frame
|
||||
|
||||
if frame.USE_RAGEBAR then
|
||||
if frame.USE_RAGEBAR and C_Player:IsHero() then
|
||||
if not frame:IsElementEnabled("Rage") then
|
||||
frame:EnableElement("Rage")
|
||||
rage:Show()
|
||||
|
||||
@@ -30,6 +30,12 @@ function UF:Configure_PVPIcon(frame)
|
||||
end
|
||||
|
||||
function UF:UpdateOverridePvP(event, unit)
|
||||
if unit and self.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
|
||||
local isUnit = self.unit and UnitIsUnit(self.unit, unit)
|
||||
if isUnit then
|
||||
unit = self.unit
|
||||
end
|
||||
end
|
||||
if not unit or self.unit ~= unit then return end
|
||||
|
||||
local element = self.PvPIndicator
|
||||
|
||||
@@ -95,7 +95,12 @@ end
|
||||
|
||||
function UF:UpdateThreat(unit, status, r, g, b)
|
||||
local parent = self:GetParent()
|
||||
|
||||
if unit and parent.isNamePlate and unit:sub(1, 9) ~= "nameplate" then
|
||||
local isUnit = parent.unit and UnitIsUnit(parent.unit, unit)
|
||||
if isUnit then
|
||||
unit = parent.unit
|
||||
end
|
||||
end
|
||||
if (parent.unit ~= unit) or not unit then return end
|
||||
|
||||
local db = parent.db
|
||||
|
||||
@@ -461,6 +461,21 @@ function UF:Configure_Fader(frame)
|
||||
end
|
||||
end
|
||||
|
||||
function UF:Construct_ClipFrame(frame, bar)
|
||||
|
||||
local clipFrame = CreateFrame('ScrollFrame', nil, bar)
|
||||
clipFrame:SetAllPoints()
|
||||
clipFrame:EnableMouse(false)
|
||||
|
||||
local child = CreateFrame("Frame", nil, clipFrame)
|
||||
child:SetPoint("CENTER")
|
||||
child:SetSize(clipFrame:GetSize())
|
||||
child.__frame = frame
|
||||
bar.ClipFrame = child
|
||||
|
||||
return child
|
||||
end
|
||||
|
||||
function UF:Configure_FontString(obj)
|
||||
UF.fontstrings[obj] = true
|
||||
obj:FontTemplate() --This is temporary.
|
||||
|
||||
Reference in New Issue
Block a user