df7cc26a64
Fix remaining lua errors covered by ascension patches Add Addon Skins Add Enhanced Friends List
425 lines
14 KiB
Lua
425 lines
14 KiB
Lua
local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
|
local UF = E:GetModule("UnitFrames")
|
|
|
|
--Lua functions
|
|
local unpack = unpack
|
|
local abs, min = math.abs, math.min
|
|
--WoW API / Variables
|
|
local CreateFrame = CreateFrame
|
|
local UnitIsPlayer = UnitIsPlayer
|
|
local UnitReaction = UnitReaction
|
|
local UnitCanAttack = UnitCanAttack
|
|
|
|
local _, ns = ...
|
|
local ElvUF = ns.oUF
|
|
assert(ElvUF, "ElvUI was unable to locate oUF.")
|
|
|
|
local INVERT_ANCHORPOINT = {
|
|
TOPLEFT = "BOTTOMRIGHT",
|
|
LEFT = "RIGHT",
|
|
BOTTOMLEFT = "TOPRIGHT",
|
|
RIGHT = "LEFT",
|
|
TOPRIGHT = "BOTTOMLEFT",
|
|
BOTTOMRIGHT = "TOPLEFT",
|
|
CENTER = "CENTER",
|
|
TOP = "BOTTOM",
|
|
BOTTOM = "TOP"
|
|
}
|
|
|
|
local ticks = {}
|
|
|
|
function UF:Construct_Castbar(frame, moverName)
|
|
local castbar = CreateFrame("StatusBar", nil, frame)
|
|
castbar:SetFrameLevel(frame.RaisedElementParent:GetFrameLevel() + 30) --Make it appear above everything else
|
|
self.statusbars[castbar] = true
|
|
castbar.CustomDelayText = self.CustomCastDelayText
|
|
castbar.CustomTimeText = self.CustomTimeText
|
|
castbar.PostCastStart = self.PostCastStart
|
|
castbar.PostCastStop = self.PostCastStop
|
|
castbar.PostCastInterruptible = self.PostCastInterruptible
|
|
castbar:SetClampedToScreen(true)
|
|
castbar:CreateBackdrop(nil, nil, nil, self.thinBorders, true)
|
|
|
|
castbar.Time = castbar:CreateFontString(nil, "OVERLAY")
|
|
self:Configure_FontString(castbar.Time)
|
|
castbar.Time:Point("RIGHT", castbar, "RIGHT", -4, 0)
|
|
castbar.Time:SetTextColor(0.84, 0.75, 0.65)
|
|
castbar.Time:SetJustifyH("RIGHT")
|
|
|
|
castbar.Text = castbar:CreateFontString(nil, "OVERLAY")
|
|
self:Configure_FontString(castbar.Text)
|
|
castbar.Text:Point("LEFT", castbar, "LEFT", 4, 0)
|
|
castbar.Text:SetTextColor(0.84, 0.75, 0.65)
|
|
castbar.Text:SetJustifyH("LEFT")
|
|
castbar.Text:SetWordWrap(false)
|
|
|
|
castbar.Spark_ = castbar:CreateTexture(nil, "OVERLAY")
|
|
castbar.Spark_:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
|
|
castbar.Spark_:SetBlendMode("ADD")
|
|
castbar.Spark_:SetVertexColor(1, 1, 1)
|
|
castbar.Spark_:Size(20, 40)
|
|
|
|
--Set to castbar.SafeZone
|
|
castbar.LatencyTexture = castbar:CreateTexture(nil, "OVERLAY")
|
|
castbar.LatencyTexture:SetTexture(E.media.blankTex)
|
|
castbar.LatencyTexture:SetVertexColor(0.69, 0.31, 0.31, 0.75)
|
|
|
|
castbar.bg = castbar:CreateTexture(nil, "BORDER")
|
|
castbar.bg:SetAllPoints()
|
|
castbar.bg:SetTexture(E.media.blankTex)
|
|
castbar.bg:Show()
|
|
|
|
local button = CreateFrame("Frame", nil, castbar)
|
|
local holder = CreateFrame("Frame", nil, castbar)
|
|
button:SetTemplate(nil, nil, nil, self.thinBorders, true)
|
|
|
|
castbar.Holder = holder
|
|
--these are placeholder so the mover can be created.. it will be changed.
|
|
castbar.Holder:Point("TOPLEFT", frame, "BOTTOMLEFT", 0, -(frame.BORDER - frame.SPACING))
|
|
castbar:Point("BOTTOMLEFT", castbar.Holder, "BOTTOMLEFT", frame.BORDER, frame.BORDER)
|
|
button:Point("RIGHT", castbar, "LEFT", -E.Spacing*3, 0)
|
|
|
|
if moverName then
|
|
local name = frame:GetName()
|
|
local configName = string.lower(string.gsub(name, "^ElvUF_", ""))
|
|
E:CreateMover(castbar.Holder, name.."CastbarMover", moverName, nil, -6, nil, "ALL,SOLO", nil, "unitframe,"..configName..",castbar")
|
|
end
|
|
|
|
local icon = button:CreateTexture(nil, "ARTWORK")
|
|
local offset = frame.BORDER --use frame.BORDER since it may be different from E.Border due to forced thin borders
|
|
icon:SetInside(nil, offset, offset)
|
|
icon.bg = button
|
|
|
|
--Set to castbar.Icon
|
|
castbar.ButtonIcon = icon
|
|
|
|
return castbar
|
|
end
|
|
|
|
function UF:Configure_Castbar(frame)
|
|
if not frame.VARIABLES_SET then return end
|
|
local castbar = frame.Castbar
|
|
local db = frame.db
|
|
|
|
if db.castbar.enable then
|
|
if not frame:IsElementEnabled("Castbar") then
|
|
frame:EnableElement("Castbar")
|
|
end
|
|
|
|
castbar:Width(db.castbar.width - ((frame.BORDER+frame.SPACING)*2))
|
|
castbar:Height(db.castbar.height - ((frame.BORDER+frame.SPACING)*2))
|
|
castbar.Holder:Width(db.castbar.width)
|
|
castbar.Holder:Height(db.castbar.height)
|
|
|
|
local color = E.db.unitframe.colors.borderColor
|
|
castbar.ButtonIcon.bg:SetBackdropBorderColor(color.r, color.g, color.b)
|
|
|
|
local oSC = castbar.Holder:GetScript("OnSizeChanged")
|
|
if oSC then oSC(castbar.Holder) end
|
|
|
|
if db.castbar.strataAndLevel and db.castbar.strataAndLevel.useCustomStrata then
|
|
castbar:SetFrameStrata(db.castbar.strataAndLevel.frameStrata)
|
|
end
|
|
|
|
if db.castbar.strataAndLevel and db.castbar.strataAndLevel.useCustomLevel then
|
|
castbar:SetFrameLevel(db.castbar.strataAndLevel.frameLevel)
|
|
end
|
|
|
|
castbar.timeToHold = db.castbar.timeToHold
|
|
|
|
--Latency
|
|
if db.castbar.latency then
|
|
castbar.SafeZone = castbar.LatencyTexture
|
|
castbar.LatencyTexture:Show()
|
|
else
|
|
castbar.SafeZone = nil
|
|
castbar.LatencyTexture:Hide()
|
|
end
|
|
|
|
--Icon
|
|
if db.castbar.icon then
|
|
castbar.Icon = castbar.ButtonIcon
|
|
castbar.Icon:SetTexCoord(unpack(E.TexCoords))
|
|
|
|
if not db.castbar.iconAttached then
|
|
castbar.Icon.bg:Size(db.castbar.iconSize)
|
|
else
|
|
if db.castbar.insideInfoPanel and frame.USE_INFO_PANEL then
|
|
castbar.Icon.bg:Size(db.infoPanel.height - frame.SPACING*2)
|
|
else
|
|
castbar.Icon.bg:Size(db.castbar.height - frame.SPACING*2)
|
|
end
|
|
|
|
castbar:Width(db.castbar.width - castbar.Icon.bg:GetWidth() - (frame.BORDER + frame.SPACING*5))
|
|
end
|
|
|
|
castbar.Icon.bg:Show()
|
|
else
|
|
castbar.ButtonIcon.bg:Hide()
|
|
castbar.Icon = nil
|
|
end
|
|
|
|
if db.castbar.spark then
|
|
castbar.Spark = castbar.Spark_
|
|
castbar.Spark:Point("CENTER", castbar:GetStatusBarTexture(), "RIGHT", 0, 0)
|
|
castbar.Spark:Height(db.castbar.height * 2)
|
|
elseif castbar.Spark then
|
|
castbar.Spark:Hide()
|
|
castbar.Spark = nil
|
|
end
|
|
|
|
castbar:ClearAllPoints()
|
|
if db.castbar.insideInfoPanel and frame.USE_INFO_PANEL then
|
|
if not db.castbar.iconAttached then
|
|
castbar:SetInside(frame.InfoPanel, 0, 0)
|
|
else
|
|
local iconWidth = db.castbar.icon and (castbar.Icon.bg:GetWidth() - frame.BORDER) or 0
|
|
if frame.ORIENTATION == "RIGHT" then
|
|
castbar:Point("TOPLEFT", frame.InfoPanel, "TOPLEFT")
|
|
castbar:Point("BOTTOMRIGHT", frame.InfoPanel, "BOTTOMRIGHT", -iconWidth - frame.SPACING*3, 0)
|
|
else
|
|
castbar:Point("TOPLEFT", frame.InfoPanel, "TOPLEFT", iconWidth + frame.SPACING*3, 0)
|
|
castbar:Point("BOTTOMRIGHT", frame.InfoPanel, "BOTTOMRIGHT")
|
|
end
|
|
end
|
|
|
|
if db.castbar.spark then
|
|
castbar.Spark:Height(db.infoPanel and db.infoPanel.height * 2) -- Grab the height from the infopanel.
|
|
end
|
|
|
|
if castbar.Holder.mover then
|
|
E:DisableMover(castbar.Holder.mover:GetName())
|
|
end
|
|
else
|
|
local isMoved = E:HasMoverBeenMoved(frame:GetName().."CastbarMover") or not castbar.Holder.mover
|
|
if not isMoved then
|
|
castbar.Holder.mover:ClearAllPoints()
|
|
end
|
|
|
|
castbar:ClearAllPoints()
|
|
if frame.ORIENTATION ~= "RIGHT" then
|
|
castbar:Point("BOTTOMRIGHT", castbar.Holder, "BOTTOMRIGHT", -(frame.BORDER+frame.SPACING), frame.BORDER+frame.SPACING)
|
|
if not isMoved then
|
|
castbar.Holder.mover:Point("TOPRIGHT", frame, "BOTTOMRIGHT", 0, -(frame.BORDER - frame.SPACING))
|
|
end
|
|
else
|
|
castbar:Point("BOTTOMLEFT", castbar.Holder, "BOTTOMLEFT", frame.BORDER+frame.SPACING, frame.BORDER+frame.SPACING)
|
|
if not isMoved then
|
|
castbar.Holder.mover:Point("TOPLEFT", frame, "BOTTOMLEFT", 0, -(frame.BORDER - frame.SPACING))
|
|
end
|
|
end
|
|
|
|
if castbar.Holder.mover then
|
|
E:EnableMover(castbar.Holder.mover:GetName())
|
|
end
|
|
end
|
|
|
|
if not db.castbar.iconAttached and db.castbar.icon then
|
|
local attachPoint = db.castbar.iconAttachedTo == "Frame" and frame or frame.Castbar
|
|
local anchorPoint = db.castbar.iconPosition
|
|
castbar.Icon.bg:ClearAllPoints()
|
|
castbar.Icon.bg:Point(INVERT_ANCHORPOINT[anchorPoint], attachPoint, anchorPoint, db.castbar.iconXOffset, db.castbar.iconYOffset)
|
|
elseif db.castbar.icon then
|
|
castbar.Icon.bg:ClearAllPoints()
|
|
if frame.ORIENTATION == "RIGHT" then
|
|
castbar.Icon.bg:Point("LEFT", castbar, "RIGHT", frame.SPACING*3, 0)
|
|
else
|
|
castbar.Icon.bg:Point("RIGHT", castbar, "LEFT", -frame.SPACING*3, 0)
|
|
end
|
|
end
|
|
|
|
--Adjust tick heights
|
|
castbar.tickHeight = castbar:GetHeight()
|
|
|
|
if db.castbar.ticks then --Only player unitframe has this
|
|
--Set tick width and color
|
|
castbar.tickWidth = db.castbar.tickWidth
|
|
castbar.tickColor = db.castbar.tickColor
|
|
|
|
for i = 1, #ticks do
|
|
ticks[i]:SetVertexColor(castbar.tickColor.r, castbar.tickColor.g, castbar.tickColor.b, castbar.tickColor.a)
|
|
ticks[i]:Width(castbar.tickWidth)
|
|
end
|
|
end
|
|
|
|
castbar.custom_backdrop = UF.db.colors.customcastbarbackdrop and UF.db.colors.castbar_backdrop
|
|
UF:ToggleTransparentStatusBar(UF.db.colors.transparentCastbar, castbar, castbar.bg, nil, UF.db.colors.invertCastbar)
|
|
else
|
|
if not db.castbar.enable and frame:IsElementEnabled("Castbar") then
|
|
frame:DisableElement("Castbar")
|
|
|
|
if castbar.Holder.mover then
|
|
E:DisableMover(castbar.Holder.mover:GetName())
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function UF:CustomCastDelayText(duration)
|
|
local db = self:GetParent().db
|
|
if not (db and db.castbar) then return end
|
|
db = db.castbar.format
|
|
|
|
if self.channeling then
|
|
if db == "CURRENT" then
|
|
self.Time:SetFormattedText("%.1f |cffaf5050%.2f|r", abs(duration - self.max), self.delay)
|
|
elseif db == "CURRENTMAX" then
|
|
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%.2f|r", abs(duration - self.max), self.max, self.delay)
|
|
elseif db == "REMAINING" then
|
|
self.Time:SetFormattedText("%.1f |cffaf5050%.2f|r", duration, self.delay)
|
|
elseif db == "REMAININGMAX" then
|
|
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%.2f|r", duration, self.max, self.delay)
|
|
end
|
|
else
|
|
if db == "CURRENT" then
|
|
self.Time:SetFormattedText("%.1f |cffaf5050%s %.2f|r", duration, "+", self.delay)
|
|
elseif db == "CURRENTMAX" then
|
|
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%s %.2f|r", duration, self.max, "+", self.delay)
|
|
elseif db == "REMAINING" then
|
|
self.Time:SetFormattedText("%.1f |cffaf5050%s %.2f|r", abs(duration - self.max), "+", self.delay)
|
|
elseif db == "REMAININGMAX" then
|
|
self.Time:SetFormattedText("%.1f / %.2f |cffaf5050%s %.2f|r", abs(duration - self.max), self.max, "+", self.delay)
|
|
end
|
|
end
|
|
end
|
|
|
|
function UF:CustomTimeText(duration)
|
|
local db = self:GetParent().db
|
|
if not (db and db.castbar) then return end
|
|
db = db.castbar.format
|
|
|
|
if self.channeling then
|
|
if db == "CURRENT" then
|
|
self.Time:SetFormattedText("%.1f", abs(duration - self.max))
|
|
elseif db == "CURRENTMAX" then
|
|
self.Time:SetFormattedText("%.1f / %.2f", abs(duration - self.max), self.max)
|
|
elseif db == "REMAINING" then
|
|
self.Time:SetFormattedText("%.1f", duration)
|
|
elseif db == "REMAININGMAX" then
|
|
self.Time:SetFormattedText("%.1f / %.2f", duration, self.max)
|
|
end
|
|
else
|
|
if db == "CURRENT" then
|
|
self.Time:SetFormattedText("%.1f", duration)
|
|
elseif db == "CURRENTMAX" then
|
|
self.Time:SetFormattedText("%.1f / %.2f", duration, self.max)
|
|
elseif db == "REMAINING" then
|
|
self.Time:SetFormattedText("%.1f", abs(duration - self.max))
|
|
elseif db == "REMAININGMAX" then
|
|
self.Time:SetFormattedText("%.1f / %.2f", abs(duration - self.max), self.max)
|
|
end
|
|
end
|
|
end
|
|
|
|
function UF:HideTicks()
|
|
for i = 1, #ticks do
|
|
ticks[i]:Hide()
|
|
end
|
|
end
|
|
|
|
function UF:SetCastTicks(frame, numTicks)
|
|
UF:HideTicks()
|
|
if numTicks and numTicks <= 0 then return end
|
|
local w = frame:GetWidth()
|
|
local d = w / numTicks
|
|
|
|
for i = 1, numTicks do
|
|
if not ticks[i] then
|
|
ticks[i] = frame:CreateTexture(nil, "OVERLAY")
|
|
ticks[i]:SetTexture(E.media.normTex)
|
|
E:RegisterStatusBar(ticks[i])
|
|
ticks[i]:SetVertexColor(frame.tickColor.r, frame.tickColor.g, frame.tickColor.b, frame.tickColor.a)
|
|
ticks[i]:Width(frame.tickWidth)
|
|
end
|
|
|
|
ticks[i]:Height(frame.tickHeight)
|
|
ticks[i]:ClearAllPoints()
|
|
ticks[i]:Point("RIGHT", frame, "LEFT", d * i, 0)
|
|
ticks[i]:Show()
|
|
end
|
|
end
|
|
|
|
function UF:PostCastStart(unit)
|
|
local db = self:GetParent().db
|
|
if not db or not db.castbar then return end
|
|
|
|
if unit == "vehicle" then unit = "player" end
|
|
|
|
if db.castbar.displayTarget and self.curTarget then
|
|
self.Text:SetText(self.spellName.." > "..self.curTarget)
|
|
end
|
|
|
|
-- Get length of Time, then calculate available length for Text
|
|
local timeWidth = self.Time:GetStringWidth()
|
|
local textWidth = self:GetWidth() - timeWidth - 10
|
|
local textStringWidth = self.Text:GetStringWidth()
|
|
|
|
if timeWidth == 0 or textStringWidth == 0 then
|
|
E:Delay(0.05, function() -- Delay may need tweaking
|
|
textWidth = self:GetWidth() - self.Time:GetStringWidth() - 10
|
|
textStringWidth = self.Text:GetStringWidth()
|
|
if textWidth > 0 then self.Text:Width(min(textWidth, textStringWidth)) end
|
|
end)
|
|
else
|
|
self.Text:Width(min(textWidth, textStringWidth))
|
|
end
|
|
|
|
self.unit = unit
|
|
|
|
if self.channeling and db.castbar.ticks and unit == "player" then
|
|
local unitframe = E.global.unitframe
|
|
local baseTicks = unitframe.ChannelTicks[self.spellName]
|
|
|
|
if baseTicks then
|
|
UF:SetCastTicks(self, baseTicks)
|
|
self.hadTicks = true
|
|
else
|
|
UF:HideTicks()
|
|
end
|
|
end
|
|
|
|
local colors = ElvUF.colors
|
|
local r, g, b = colors.castColor[1], colors.castColor[2], colors.castColor[3]
|
|
|
|
if (self.notInterruptible and unit ~= "player") and UnitCanAttack("player", unit) then
|
|
r, g, b = colors.castNoInterrupt[1], colors.castNoInterrupt[2], colors.castNoInterrupt[3]
|
|
elseif UF.db.colors.castClassColor and UnitIsPlayer(unit) then
|
|
local _, class = UnitClass(unit)
|
|
local t = UnitIsUnit("player", unit) and E.media.herocolor or RAID_CLASS_COLORS[class]
|
|
if t then r, g, b = t[1], t[2], t[3] end
|
|
elseif UF.db.colors.castReactionColor then
|
|
local Reaction = UnitReaction(unit, "player")
|
|
local t = Reaction and ElvUF.colors.reaction[Reaction]
|
|
if t then r, g, b = t[1], t[2], t[3] end
|
|
end
|
|
|
|
self:SetStatusBarColor(r, g, b)
|
|
end
|
|
|
|
function UF:PostCastStop(unit)
|
|
if self.hadTicks and unit == "player" then
|
|
UF:HideTicks()
|
|
self.hadTicks = false
|
|
end
|
|
end
|
|
|
|
function UF:PostCastInterruptible(unit)
|
|
if unit == "vehicle" or unit == "player" then return end
|
|
|
|
local colors = ElvUF.colors
|
|
local r, g, b = colors.castColor[1], colors.castColor[2], colors.castColor[3]
|
|
|
|
if self.notInterruptible and UnitCanAttack("player", unit) then
|
|
r, g, b = colors.castNoInterrupt[1], colors.castNoInterrupt[2], colors.castNoInterrupt[3]
|
|
elseif UF.db.colors.castClassColor and UnitIsPlayer(unit) then
|
|
local _, class = UnitClass(unit)
|
|
local t = UnitIsUnit("player", unit) and E.media.herocolor or RAID_CLASS_COLORS[class]
|
|
if t then r, g, b = t[1], t[2], t[3] end
|
|
elseif UF.db.colors.castReactionColor then
|
|
local Reaction = UnitReaction(unit, "player")
|
|
local t = Reaction and ElvUF.colors.reaction[Reaction]
|
|
if t then r, g, b = t[1], t[2], t[3] end
|
|
end
|
|
|
|
self:SetStatusBarColor(r, g, b)
|
|
end |