You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2884 lines
111 KiB
2884 lines
111 KiB
local _, Cell = ...
|
|
local L = Cell.L
|
|
local F = Cell.funcs
|
|
local B = Cell.bFuncs
|
|
local I = Cell.iFuncs
|
|
local U = Cell.uFuncs
|
|
local P = Cell.pixelPerfectFuncs
|
|
local A = Cell.animations
|
|
|
|
local HealComm
|
|
|
|
CELL_FADE_OUT_HEALTH_PERCENT = nil
|
|
|
|
local UnitGUID = UnitGUID
|
|
local UnitClassBase = UnitClassBase
|
|
local UnitHealth = UnitHealth
|
|
local UnitHealthMax = UnitHealthMax
|
|
-- local UnitGetIncomingHeals = UnitGetIncomingHeals
|
|
local UnitIsUnit = UnitIsUnit
|
|
local UnitIsConnected = UnitIsConnected
|
|
local UnitIsAFK = UnitIsAFK
|
|
local UnitIsFeignDeath = UnitIsFeignDeath
|
|
local UnitIsDeadOrGhost = UnitIsDeadOrGhost
|
|
local UnitIsGhost = UnitIsGhost
|
|
local UnitPowerType = UnitPowerType
|
|
local UnitPowerMax = UnitPowerMax
|
|
-- local UnitInRange = UnitInRange
|
|
-- local UnitIsVisible = UnitIsVisible
|
|
local SetRaidTargetIconTexture = SetRaidTargetIconTexture
|
|
local GetTime = GetTime
|
|
local GetRaidTargetIndex = GetRaidTargetIndex
|
|
local GetReadyCheckStatus = GetReadyCheckStatus
|
|
local UnitHasVehicleUI = UnitHasVehicleUI
|
|
-- local UnitInVehicle = UnitInVehicle
|
|
-- local UnitUsingVehicle = UnitUsingVehicle
|
|
local UnitIsCharmed = UnitIsCharmed
|
|
local UnitIsPlayer = UnitIsPlayer
|
|
local UnitThreatSituation = UnitThreatSituation
|
|
local GetThreatStatusColor = GetThreatStatusColor
|
|
local UnitExists = UnitExists
|
|
local UnitIsGroupLeader = UnitIsGroupLeader
|
|
local UnitIsGroupAssistant = UnitIsGroupAssistant
|
|
local InCombatLockdown = InCombatLockdown
|
|
local UnitInPhase = UnitInPhase
|
|
local UnitBuff = UnitBuff
|
|
local UnitDebuff = UnitDebuff
|
|
local IsInRaid = IsInRaid
|
|
local UnitDetailedThreatSituation = UnitDetailedThreatSituation
|
|
local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo
|
|
|
|
local barAnimationType, highlightEnabled, predictionEnabled
|
|
|
|
-------------------------------------------------
|
|
-- unit button func declarations
|
|
-------------------------------------------------
|
|
local UnitButton_UpdateAll
|
|
local UnitButton_UpdateAuras, UnitButton_UpdateAssignment, UnitButton_UpdateLeader, UnitButton_UpdateStatusText
|
|
local UnitButton_UpdateHealthColor, UnitButton_UpdateNameColor
|
|
local UnitButton_UpdatePowerMax, UnitButton_UpdatePower, UnitButton_UpdatePowerType
|
|
|
|
-------------------------------------------------
|
|
-- unit button init indicators
|
|
-------------------------------------------------
|
|
local enabledIndicators, indicatorNums, indicatorCustoms = {}, {}, {}
|
|
|
|
local function UpdateIndicatorParentVisibility(b, indicatorName, enabled)
|
|
if not (indicatorName == "debuffs" or
|
|
indicatorName == "privateAuras" or
|
|
indicatorName == "defensiveCooldowns" or
|
|
indicatorName == "externalCooldowns" or
|
|
indicatorName == "allCooldowns" or
|
|
indicatorName == "dispels" or
|
|
indicatorName == "missingBuffs") then
|
|
return
|
|
end
|
|
|
|
if enabled then
|
|
b.indicators[indicatorName]:Show()
|
|
else
|
|
b.indicators[indicatorName]:Hide()
|
|
end
|
|
end
|
|
|
|
local function ResetIndicators()
|
|
wipe(enabledIndicators)
|
|
wipe(indicatorNums)
|
|
|
|
for _, t in pairs(Cell.vars.currentLayoutTable["indicators"]) do
|
|
-- update enabled
|
|
if t["enabled"] then
|
|
enabledIndicators[t["indicatorName"]] = true
|
|
end
|
|
-- update num
|
|
if t["num"] then
|
|
indicatorNums[t["indicatorName"]] = t["num"]
|
|
end
|
|
-- update statusIcon
|
|
if t["indicatorName"] == "statusIcon" then
|
|
I:EnableStatusIcon(t["enabled"])
|
|
end
|
|
-- update aoehealing
|
|
if t["indicatorName"] == "aoeHealing" then
|
|
I:EnableAoEHealing(t["enabled"])
|
|
end
|
|
-- update targetCounter
|
|
if t["indicatorName"] == "targetCounter" then
|
|
I:UpdateTargetCounterFilters(t["filters"], true)
|
|
I:EnableTargetCounter(t["enabled"])
|
|
end
|
|
-- update targetedSpells
|
|
if t["indicatorName"] == "targetedSpells" then
|
|
I:EnableTargetedSpells(t["enabled"])
|
|
I:ShowAllTargetedSpells(t["showAllSpells"])
|
|
end
|
|
-- update consumables
|
|
if t["indicatorName"] == "consumables" then
|
|
I:EnableConsumables(t["enabled"])
|
|
end
|
|
-- update healthThresholds
|
|
if t["indicatorName"] == "healthThresholds" then
|
|
I:UpdateHealthThresholds()
|
|
end
|
|
-- update missingBuffs
|
|
if t["indicatorName"] == "missingBuffs" then
|
|
I:UpdateMissingBuffsNum(t["num"], true)
|
|
I:UpdateMissingBuffsFilters(t["filters"], true)
|
|
I:EnableMissingBuffs(t["enabled"])
|
|
end
|
|
-- update custom
|
|
if t["dispellableByMe"] ~= nil then
|
|
indicatorCustoms[t["indicatorName"]] = t["dispellableByMe"]
|
|
end
|
|
if t["hideIfEmptyOrFull"] ~= nil then
|
|
indicatorCustoms[t["indicatorName"]] = t["hideIfEmptyOrFull"]
|
|
end
|
|
if t["onlyShowTopGlow"] ~= nil then
|
|
indicatorCustoms[t["indicatorName"]] = t["onlyShowTopGlow"]
|
|
end
|
|
if t["hideInCombat"] ~= nil then
|
|
indicatorCustoms[t["indicatorName"]] = t["hideInCombat"]
|
|
end
|
|
end
|
|
end
|
|
|
|
local function HandleIndicators(b)
|
|
b._indicatorReady = nil
|
|
|
|
-- NOTE: Remove old
|
|
I:RemoveAllCustomIndicators(b)
|
|
|
|
for _, t in pairs(Cell.vars.currentLayoutTable["indicators"]) do
|
|
local indicator = b.indicators[t["indicatorName"]] or I:CreateIndicator(b, t)
|
|
-- update position
|
|
if t["position"] then
|
|
P:ClearPoints(indicator)
|
|
P:Point(indicator, t["position"][1], b, t["position"][2], t["position"][3], t["position"][4])
|
|
end
|
|
-- update anchor
|
|
if t["anchor"] then
|
|
indicator:SetAnchor(t["anchor"])
|
|
end
|
|
-- update frameLevel
|
|
if t["frameLevel"] then
|
|
indicator:SetFrameLevel(indicator:GetParent():GetFrameLevel()+t["frameLevel"])
|
|
end
|
|
-- update size
|
|
if t["size"] then
|
|
-- NOTE: debuffs: ["size"] = {{normalSize}, {bigSize}}
|
|
if t["indicatorName"] == "debuffs" then
|
|
indicator:SetSize(t["size"][1], t["size"][2])
|
|
else
|
|
P:Size(indicator, t["size"][1], t["size"][2])
|
|
end
|
|
end
|
|
-- update thickness
|
|
if t["thickness"] then
|
|
indicator:SetThickness(t["thickness"])
|
|
end
|
|
-- update border
|
|
if t["border"] then
|
|
indicator:SetBorder(t["border"])
|
|
end
|
|
-- update height
|
|
if t["height"] then
|
|
P:Height(indicator, t["height"])
|
|
end
|
|
-- update height
|
|
if t["textWidth"] then
|
|
indicator:UpdateTextWidth(t["textWidth"])
|
|
end
|
|
-- update alpha
|
|
if t["alpha"] then
|
|
indicator:SetAlpha(t["alpha"])
|
|
end
|
|
-- update numPerLine
|
|
if t["numPerLine"] then
|
|
indicator:SetNumPerLine(t["numPerLine"])
|
|
end
|
|
-- update orientation
|
|
if t["orientation"] then
|
|
indicator:SetOrientation(t["orientation"])
|
|
end
|
|
-- update font
|
|
if t["font"] then
|
|
indicator:SetFont(unpack(t["font"]))
|
|
end
|
|
-- update format
|
|
if t["format"] then
|
|
indicator:SetFormat(t["format"])
|
|
B:UpdateHealthText(b)
|
|
end
|
|
-- update color
|
|
if t["color"] and t["indicatorName"] ~= "nameText" then
|
|
indicator:SetColor(unpack(t["color"]))
|
|
end
|
|
-- update colors
|
|
if t["colors"] then
|
|
indicator:SetColors(t["colors"])
|
|
end
|
|
-- update texture
|
|
if t["texture"] then
|
|
indicator:SetTexture(t["texture"])
|
|
end
|
|
-- update dispel highlight
|
|
if t["highlightType"] then
|
|
indicator:UpdateHighlight(t["highlightType"])
|
|
end
|
|
-- update dispel icons
|
|
if type(t["showDispelTypeIcons"]) == "boolean" then
|
|
indicator:ShowIcons(t["showDispelTypeIcons"])
|
|
end
|
|
-- update duration
|
|
if type(t["showDuration"]) == "boolean" or type(t["showDuration"]) == "number" then
|
|
indicator:ShowDuration(t["showDuration"])
|
|
end
|
|
-- update animation
|
|
if type(t["showAnimation"]) == "boolean" then
|
|
indicator:ShowAnimation(t["showAnimation"])
|
|
end
|
|
-- update stack
|
|
if type(t["showStack"]) == "boolean" then
|
|
indicator:ShowStack(t["showStack"])
|
|
end
|
|
-- update duration
|
|
if t["duration"] then
|
|
indicator:SetDuration(t["duration"])
|
|
end
|
|
-- update circled nums
|
|
if type(t["circledStackNums"]) == "boolean" then
|
|
indicator:SetCircledStackNums(t["circledStackNums"])
|
|
end
|
|
-- update groupNumber
|
|
if type(t["showGroupNumber"]) == "boolean" then
|
|
indicator:ShowGroupNumber(t["showGroupNumber"])
|
|
end
|
|
-- update vehicleNamePosition
|
|
if t["vehicleNamePosition"] then
|
|
indicator:UpdateVehicleNamePosition(t["vehicleNamePosition"])
|
|
end
|
|
-- update timer
|
|
if type(t["showTimer"]) == "boolean" then
|
|
indicator:SetShowTimer(t["showTimer"])
|
|
end
|
|
-- update background
|
|
if type(t["showBackground"]) == "boolean" then
|
|
indicator:ShowBackground(t["showBackground"])
|
|
end
|
|
-- tooltip
|
|
if type(t["showTooltip"]) == "boolean" then
|
|
indicator:ShowTooltip(t["showTooltip"])
|
|
end
|
|
-- blacklist shortcut
|
|
if type(t["enableBlacklistShortcut"]) == "boolean" then
|
|
indicator:EnableBlacklistShortcut(t["enableBlacklistShortcut"])
|
|
end
|
|
-- speed
|
|
if t["speed"] then
|
|
indicator:SetSpeed(t["speed"])
|
|
end
|
|
-- update fadeOut
|
|
if type(t["fadeOut"]) == "boolean" then
|
|
indicator:SetFadeOut(t["fadeOut"])
|
|
end
|
|
-- update shape
|
|
if t["shape"] then
|
|
indicator:SetShape(t["shape"])
|
|
end
|
|
-- update glow
|
|
if t["glowOptions"] then
|
|
indicator:UpdateGlowOptions(t["glowOptions"])
|
|
end
|
|
-- update smooth
|
|
if type(t["smooth"]) == "boolean" then
|
|
indicator:EnableSmooth(t["smooth"])
|
|
end
|
|
|
|
-- init
|
|
-- update name visibility
|
|
if t["indicatorName"] == "nameText" then
|
|
if t["enabled"] then
|
|
indicator:Show()
|
|
else
|
|
indicator:Hide()
|
|
end
|
|
elseif t["indicatorName"] == "playerRaidIcon" then
|
|
B:UpdatePlayerRaidIcon(b, t["enabled"])
|
|
elseif t["indicatorName"] == "targetRaidIcon" then
|
|
B:UpdateTargetRaidIcon(b, t["enabled"])
|
|
else
|
|
UpdateIndicatorParentVisibility(b, t["indicatorName"], t["enabled"])
|
|
end
|
|
|
|
-- update pixel perfect for built-in widgets
|
|
-- if t["type"] == "built-in" then
|
|
-- if indicator.UpdatePixelPerfect then
|
|
-- indicator:UpdatePixelPerfect()
|
|
-- end
|
|
-- end
|
|
end
|
|
|
|
--! update pixel perfect for widgets
|
|
B:UpdatePixelPerfect(b, true)
|
|
|
|
b._indicatorReady = 1
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- indicator update queue
|
|
-------------------------------------------------
|
|
local updater = CreateFrame("Frame")
|
|
updater:Hide()
|
|
local queue = {}
|
|
|
|
updater:SetScript("OnUpdate", function()
|
|
local b = queue[1]
|
|
if b then
|
|
if not b._status then
|
|
-- print("processing", GetTime(), b:GetName())
|
|
b._status = "processing"
|
|
HandleIndicators(b)
|
|
UnitButton_UpdateAll(b)
|
|
b._status = "finished"
|
|
elseif b._status == "finished" then
|
|
CellLoadingBar.current = (CellLoadingBar.current or 0) + 1
|
|
CellLoadingBar:SetValue(CellLoadingBar.current)
|
|
tremove(queue, 1)
|
|
b._status = nil
|
|
end
|
|
else
|
|
CellLoadingBar:Hide()
|
|
CellLoadingBar.current = 0
|
|
updater:Hide()
|
|
end
|
|
end)
|
|
|
|
hooksecurefunc(updater, "Show", function()
|
|
CellLoadingBar.total = #queue
|
|
CellLoadingBar:SetMinMaxValues(0, CellLoadingBar.total)
|
|
CellLoadingBar:SetValue(CellLoadingBar.current or 0)
|
|
CellLoadingBar:Show()
|
|
end)
|
|
|
|
local function AddToQueue(b)
|
|
tinsert(queue, b)
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- UpdateIndicators
|
|
-------------------------------------------------
|
|
local indicatorsInitialized
|
|
local previousLayout = {}
|
|
|
|
local function UpdateIndicators(layout, indicatorName, setting, value, value2)
|
|
F:Debug("|cffff7777UpdateIndicators:|r ", layout, indicatorName, setting, value, value2)
|
|
|
|
local INDEX = Cell.vars.groupType == "solo" and "solo" or Cell.vars.layoutGroupType
|
|
|
|
if layout then
|
|
-- Cell:Fire("UpdateIndicators", layout): indicators copy/import
|
|
-- Cell:Fire("UpdateIndicators", xxx, ...): indicator updated
|
|
for k, v in pairs(previousLayout) do
|
|
if v == layout then
|
|
previousLayout[k] = nil -- update required
|
|
F:Debug("UPDATE REQUIRED:", k)
|
|
end
|
|
end
|
|
|
|
--! indicator changed, but not current layout
|
|
if layout ~= Cell.vars.currentLayout then
|
|
F:Debug("NO UPDATE: not active layout")
|
|
return
|
|
end
|
|
|
|
elseif not indicatorName then -- Cell:Fire("UpdateIndicators")
|
|
--! layout/groupType switched, check if update is required
|
|
if previousLayout[INDEX] == Cell.vars.currentLayout then
|
|
F:Debug("NO UPDATE: only reset custom indicator tables")
|
|
I:ResetCustomIndicatorTables()
|
|
ResetIndicators()
|
|
--! update shared buttons: npcs, spotlights
|
|
-- F:IterateSharedUnitButtons(HandleIndicators)
|
|
F:IterateSharedUnitButtons(AddToQueue)
|
|
updater:Show()
|
|
return
|
|
end
|
|
end
|
|
previousLayout[INDEX] = Cell.vars.currentLayout
|
|
|
|
if not indicatorName then -- init
|
|
ResetIndicators()
|
|
|
|
if not indicatorsInitialized then
|
|
-- update indicators
|
|
F:IterateAllUnitButtons(HandleIndicators, indicatorsInitialized) -- -- NOTE: indicatorsInitialized = false, update ALL GROUP TYPE; indicatorsInitialized = true, just update CURRENT GROUP TYPE
|
|
-- update all when indicators update finished
|
|
F:IterateAllUnitButtons(UnitButton_UpdateAll, true)
|
|
else
|
|
F:IterateAllUnitButtons(AddToQueue, indicatorsInitialized)
|
|
updater:Show()
|
|
end
|
|
indicatorsInitialized = true
|
|
|
|
else
|
|
-- changed in IndicatorsTab
|
|
if setting == "enabled" then
|
|
enabledIndicators[indicatorName] = value
|
|
|
|
if indicatorName == "aoeHealing" then
|
|
I:EnableAoEHealing(value)
|
|
elseif indicatorName == "targetCounter" then
|
|
I:EnableTargetCounter(value)
|
|
elseif indicatorName == "targetedSpells" then
|
|
I:EnableTargetedSpells(value)
|
|
elseif indicatorName == "consumables" then
|
|
I:EnableConsumables(value)
|
|
elseif indicatorName == "partyAssignmentIcon" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
UnitButton_UpdateAssignment(b)
|
|
end, true)
|
|
elseif indicatorName == "leaderIcon" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
UnitButton_UpdateLeader(b)
|
|
end, true)
|
|
elseif indicatorName == "playerRaidIcon" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
B:UpdatePlayerRaidIcon(b, value)
|
|
end, true)
|
|
elseif indicatorName == "targetRaidIcon" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
B:UpdateTargetRaidIcon(b, value)
|
|
end, true)
|
|
elseif indicatorName == "nameText" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
if value then
|
|
b.indicators[indicatorName]:Show()
|
|
else
|
|
b.indicators[indicatorName]:Hide()
|
|
end
|
|
end, true)
|
|
elseif indicatorName == "statusText" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
B:UpdateStatusText(b)
|
|
end, true)
|
|
elseif indicatorName == "healthText" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
B:UpdateHealthText(b)
|
|
end, true)
|
|
elseif indicatorName == "healthThresholds" then
|
|
if value then
|
|
I:UpdateHealthThresholds()
|
|
end
|
|
F:IterateAllUnitButtons(function(b)
|
|
B.UpdateHealth(b)
|
|
end, true)
|
|
elseif indicatorName == "missingBuffs" then
|
|
I:EnableMissingBuffs(value)
|
|
F:IterateAllUnitButtons(function(b)
|
|
UpdateIndicatorParentVisibility(b, indicatorName, value)
|
|
end, true)
|
|
else
|
|
-- refresh
|
|
F:IterateAllUnitButtons(function(b)
|
|
UpdateIndicatorParentVisibility(b, indicatorName, value)
|
|
if not value then
|
|
b.indicators[indicatorName]:Hide() -- hide indicators which is shown right now
|
|
end
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
end
|
|
elseif setting == "position" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
P:ClearPoints(indicator)
|
|
P:Point(indicator, value[1], b, value[2], value[3], value[4])
|
|
-- update arrangement
|
|
if indicator.indicatorType == "icons" then
|
|
indicator:SetOrientation(indicator.orientation)
|
|
end
|
|
end, true)
|
|
elseif setting == "anchor" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetAnchor(value)
|
|
end, true)
|
|
elseif setting == "frameLevel" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetFrameLevel(indicator:GetParent():GetFrameLevel()+value)
|
|
end, true)
|
|
elseif setting == "size" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
if indicatorName == "debuffs" then
|
|
indicator:SetSize(value[1], value[2])
|
|
-- update debuffs' normal/big icon sizes
|
|
UnitButton_UpdateAuras(b)
|
|
else
|
|
P:Size(indicator, value[1], value[2])
|
|
end
|
|
end, true)
|
|
elseif setting == "size-border" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
P:Size(indicator, value[1], value[2])
|
|
indicator:SetBorder(value[3])
|
|
end, true)
|
|
elseif setting == "thickness" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetThickness(value)
|
|
end, true)
|
|
elseif setting == "height" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
P:Height(indicator, value)
|
|
end, true)
|
|
elseif setting == "textWidth" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:UpdateTextWidth(value)
|
|
end, true)
|
|
elseif setting == "alpha" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetAlpha(value)
|
|
end, true)
|
|
elseif setting == "orientation" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetOrientation(value)
|
|
end, true)
|
|
elseif setting == "font" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetFont(unpack(value))
|
|
end, true)
|
|
elseif setting == "format" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetFormat(value)
|
|
B:UpdateHealthText(b)
|
|
end, true)
|
|
elseif setting == "color" then
|
|
if indicatorName == "nameText" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
UnitButton_UpdateNameColor(b)
|
|
end, true)
|
|
else
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetColor(unpack(value))
|
|
end, true)
|
|
end
|
|
elseif setting == "customColors" then --! 其他的colors不调用widget.func,不发出通知,因为这些指示器都使用OnUpdate更新颜色。
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetColors(value)
|
|
end, true)
|
|
elseif setting == "vehicleNamePosition" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:UpdateVehicleNamePosition(value)
|
|
end, true)
|
|
elseif setting == "statusColors" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
UnitButton_UpdateStatusText(b)
|
|
end, true)
|
|
elseif setting == "num" then
|
|
indicatorNums[indicatorName] = value
|
|
if indicatorName == "missingBuffs" then
|
|
I:UpdateMissingBuffsNum(value)
|
|
else
|
|
-- refresh
|
|
F:IterateAllUnitButtons(function(b)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
end
|
|
elseif setting == "numPerLine" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetNumPerLine(value)
|
|
end, true)
|
|
elseif setting == "texture" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = b.indicators[indicatorName]
|
|
indicator:SetTexture(value)
|
|
end, true)
|
|
elseif setting == "duration" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif setting == "highlightType" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:UpdateHighlight(value)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif setting == "thresholds" then
|
|
I:UpdateHealthThresholds()
|
|
F:IterateAllUnitButtons(function(b)
|
|
B.UpdateHealth(b)
|
|
end, true)
|
|
elseif setting == "showDuration" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:ShowDuration(value)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif setting == "missingBuffsFilters" then
|
|
I:UpdateMissingBuffsFilters()
|
|
elseif setting == "targetCounterFilters" then
|
|
I:UpdateTargetCounterFilters()
|
|
elseif setting == "glowOptions" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:UpdateGlowOptions(value)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif setting == "checkbutton" then
|
|
if value == "showGroupNumber" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:ShowGroupNumber(value2)
|
|
end, true)
|
|
elseif value == "showTimer" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:SetShowTimer(value2)
|
|
UnitButton_UpdateStatusText(b)
|
|
end, true)
|
|
elseif value == "showBackground" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:ShowBackground(value2)
|
|
end, true)
|
|
elseif value == "hideIfEmptyOrFull" then
|
|
--! 血量文字指示器需要立即被刷新
|
|
indicatorCustoms[indicatorName] = value2
|
|
F:IterateAllUnitButtons(function(b)
|
|
B:UpdateHealthText(b)
|
|
end, true)
|
|
elseif value == "hideInCombat" then
|
|
indicatorCustoms[indicatorName] = value2
|
|
F:IterateAllUnitButtons(function(b)
|
|
UnitButton_UpdateLeader(b)
|
|
end, true)
|
|
elseif value == "showDispelTypeIcons" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:ShowIcons(value2)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif value == "showStack" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:ShowStack(value2)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif value == "showAnimation" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:ShowAnimation(value2)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif value == "trackByName" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif value == "showTooltip" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:ShowTooltip(value2)
|
|
end, true)
|
|
elseif value == "enableBlacklistShortcut" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:EnableBlacklistShortcut(value2)
|
|
end, true)
|
|
elseif value == "circledStackNums" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:SetCircledStackNums(value2)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif value == "fadeOut" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:SetFadeOut(value2)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif value == "smooth" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:EnableSmooth(value2)
|
|
end, true)
|
|
elseif value == "showAllSpells" then
|
|
I:ShowAllTargetedSpells(value2)
|
|
else
|
|
indicatorCustoms[indicatorName] = value2
|
|
end
|
|
elseif setting == "create" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
local indicator = I:CreateIndicator(b, value)
|
|
-- update position
|
|
if value["position"] then
|
|
P:ClearPoints(indicator)
|
|
P:Point(indicator, value["position"][1], b, value["position"][2], value["position"][3], value["position"][4])
|
|
end
|
|
-- update anchor
|
|
if value["anchor"] then
|
|
indicator:SetAnchor(value["anchor"])
|
|
end
|
|
-- update size
|
|
if value["size"] then
|
|
P:Size(indicator, value["size"][1], value["size"][2])
|
|
end
|
|
-- update size
|
|
if value["frameLevel"] then
|
|
indicator:SetFrameLevel(indicator:GetParent():GetFrameLevel()+value["frameLevel"])
|
|
end
|
|
-- update orientation
|
|
if value["orientation"] then
|
|
indicator:SetOrientation(value["orientation"])
|
|
end
|
|
-- update font
|
|
if value["font"] then
|
|
indicator:SetFont(unpack(value["font"]))
|
|
end
|
|
-- update color
|
|
if value["color"] then
|
|
indicator:SetColor(unpack(value["color"]))
|
|
end
|
|
-- update colors
|
|
if value["colors"] then
|
|
indicator:SetColors(value["colors"])
|
|
end
|
|
-- update texture
|
|
if value["texture"] then
|
|
indicator:SetTexture(value["texture"])
|
|
end
|
|
-- update showDuration
|
|
if type(value["showDuration"]) ~= "nil" then
|
|
indicator:ShowDuration(value["showDuration"])
|
|
end
|
|
-- update showAnimation
|
|
if type(value["showAnimation"]) == "boolean" then
|
|
indicator:ShowAnimation(value["showAnimation"])
|
|
end
|
|
-- update showStack
|
|
if value["showStack"] then
|
|
indicator:ShowStack(value["showStack"])
|
|
end
|
|
-- update duration
|
|
if value["duration"] then
|
|
indicator:SetDuration(value["duration"])
|
|
end
|
|
-- update circled nums
|
|
if type(value["circledStackNums"]) == "boolean" then
|
|
indicator:SetCircledStackNums(value["circledStackNums"])
|
|
end
|
|
-- update fadeOut
|
|
if type(value["fadeOut"]) == "boolean" then
|
|
indicator:SetFadeOut(value["fadeOut"])
|
|
end
|
|
-- update glow
|
|
if value["glowOptions"] then
|
|
indicator:UpdateGlowOptions(value["glowOptions"])
|
|
end
|
|
-- FirstRun: Healers
|
|
if value["auras"] and #value["auras"] ~= 0 then
|
|
UnitButton_UpdateAuras(b)
|
|
end
|
|
end, true)
|
|
elseif setting == "remove" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
I:RemoveIndicator(b, indicatorName, value)
|
|
end, true)
|
|
elseif setting == "auras" then
|
|
-- indicator auras changed, hide them all, then recheck whether to show
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:Hide()
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif setting == "debuffBlacklist" or setting == "dispelBlacklist" or setting == "defensives" or setting == "externals" or setting == "bigDebuffs" or setting == "debuffTypeColor" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
UnitButton_UpdateAuras(b)
|
|
end, true)
|
|
elseif setting == "speed" then
|
|
-- only Consumables indicator has this option for now
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:SetSpeed(value)
|
|
end, true)
|
|
elseif setting == "shape" then
|
|
F:IterateAllUnitButtons(function(b)
|
|
b.indicators[indicatorName]:SetShape(value)
|
|
end, true)
|
|
end
|
|
end
|
|
end
|
|
Cell:RegisterCallback("UpdateIndicators", "UnitButton_UpdateIndicators", UpdateIndicators)
|
|
|
|
-------------------------------------------------
|
|
-- debuffs
|
|
-------------------------------------------------
|
|
local function UnitButton_UpdateDebuffs(self)
|
|
local unit = self.state.displayedUnit
|
|
|
|
-- self.state.BGOrb = nil
|
|
|
|
-- user created indicators
|
|
I:ResetCustomIndicators(self, "debuff")
|
|
|
|
local startIndex, raidDebuffsFound, wsFound = 1
|
|
local glowType, glowOptions
|
|
local refreshing = false
|
|
|
|
for i = 1, 40 do
|
|
-- name, icon, count, debuffType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod, ...
|
|
local name, icon, count, debuffType, duration, expirationTime, source, _, _, spellId = UnitDebuff(unit, i)
|
|
if not name then
|
|
break
|
|
end
|
|
|
|
local auraInstanceID = (source or "") .. spellId
|
|
|
|
-- check Bleed
|
|
debuffType = I:CheckDebuffType(debuffType, spellId)
|
|
|
|
if duration then
|
|
if Cell.vars.iconAnimation == "duration" then
|
|
local timeIncreased = self._debuffs_cache[auraInstanceID] and (expirationTime - self._debuffs_cache[auraInstanceID] >= 0.5) or false
|
|
local countIncreased = self._debuffs_count_cache[auraInstanceID] and (count > self._debuffs_count_cache[auraInstanceID]) or false
|
|
refreshing = timeIncreased or countIncreased
|
|
elseif Cell.vars.iconAnimation == "stack" then
|
|
refreshing = self._debuffs_count_cache[auraInstanceID] and (count > self._debuffs_count_cache[auraInstanceID]) or false
|
|
else
|
|
refreshing = false
|
|
end
|
|
|
|
if enabledIndicators["debuffs"] and duration <= 600 and not Cell.vars.debuffBlacklist[spellId] then
|
|
if not indicatorCustoms["debuffs"] then -- all debuffs
|
|
if Cell.vars.bigDebuffs[spellId] then -- isBigDebuff
|
|
self._debuffs_big[i] = refreshing
|
|
startIndex = startIndex + 1
|
|
elseif startIndex <= indicatorNums["debuffs"]+indicatorNums["raidDebuffs"] then -- normal debuffs, may contain topDebuff
|
|
self._debuffs_normal[i] = refreshing
|
|
startIndex = startIndex + 1
|
|
end
|
|
|
|
elseif I:CanDispel(debuffType) then -- only dispellableByMe
|
|
if Cell.vars.bigDebuffs[spellId] then -- isBigDebuff
|
|
self._debuffs_big[i] = refreshing
|
|
startIndex = startIndex + 1
|
|
elseif startIndex <= indicatorNums["debuffs"]+indicatorNums["raidDebuffs"] then -- normal debuffs, may contain topDebuff
|
|
if I:CanDispel(debuffType) then
|
|
self._debuffs_normal[i] = refreshing
|
|
startIndex = startIndex + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- user created indicators
|
|
I:UpdateCustomIndicators(self, "debuff", spellId, name, expirationTime - duration, duration, debuffType or "", icon, count, refreshing)
|
|
|
|
-- prepare raidDebuffs
|
|
if enabledIndicators["raidDebuffs"] and I:GetDebuffOrder(name, spellId, count) then
|
|
raidDebuffsFound = true
|
|
tinsert(self._debuffs_raid, i)
|
|
self._debuffs_raid_refreshing[i] = refreshing -- store all raidDebuffs
|
|
self._debuffs_raid_orders[i] = I:GetDebuffOrder(name, spellId, count)
|
|
|
|
if not indicatorCustoms["raidDebuffs"] then -- glow all matching debuffs
|
|
glowType, glowOptions = I:GetDebuffGlow(name, spellId, count)
|
|
if glowType and glowType ~= "None" then
|
|
self._debuffs_glow_current[glowType] = glowOptions
|
|
self._debuffs_glow_cache[glowType] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
self._debuffs_cache[auraInstanceID] = expirationTime
|
|
self._debuffs_count_cache[auraInstanceID] = count
|
|
self._debuffs_current[auraInstanceID] = i
|
|
|
|
if enabledIndicators["dispels"] and debuffType and debuffType ~= "" then
|
|
-- all dispels / only dispellableByMe
|
|
if not indicatorCustoms["dispels"] or I:CanDispel(debuffType) then
|
|
if Cell.vars.dispelBlacklist[spellId] then
|
|
-- no highlight
|
|
self._debuffs_dispel[debuffType] = false
|
|
else
|
|
self._debuffs_dispel[debuffType] = true
|
|
end
|
|
end
|
|
end
|
|
|
|
-- BG orbs
|
|
-- if spellId == 121164 then
|
|
-- self.state.BGOrb = "blue"
|
|
-- end
|
|
-- if spellId == 121175 then
|
|
-- self.state.BGOrb = "purple"
|
|
-- end
|
|
-- if spellId == 121176 then
|
|
-- self.state.BGOrb = "green"
|
|
-- end
|
|
-- if spellId == 121177 then
|
|
-- self.state.BGOrb = "orange"
|
|
-- end
|
|
end
|
|
end
|
|
|
|
-- update raid debuffs
|
|
if raidDebuffsFound then
|
|
startIndex = 1
|
|
self.indicators.raidDebuffs:Show()
|
|
|
|
-- sort indices
|
|
-- NOTE: self._debuffs_raid_orders = { [index] = debuffOrder } used for sorting
|
|
table.sort(self._debuffs_raid, function(a, b)
|
|
return self._debuffs_raid_orders[a] < self._debuffs_raid_orders[b]
|
|
end)
|
|
|
|
-- show
|
|
local topGlowType, topGlowOptions
|
|
for i = 1, indicatorNums["raidDebuffs"] do
|
|
if self._debuffs_raid[i] then -- self._debuffs_raid[i] -> index
|
|
local name, icon, count, debuffType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId = UnitDebuff(unit, self._debuffs_raid[i])
|
|
if name then
|
|
self.indicators.raidDebuffs[i]:SetCooldown(expirationTime - duration, duration, debuffType or "", icon, count, self._debuffs_raid_refreshing[self._debuffs_raid[i]])
|
|
self.indicators.raidDebuffs[i].index = self._debuffs_raid[i] -- NOTE: for tooltip
|
|
startIndex = startIndex + 1
|
|
-- store debuffs indices shown by raidDebuffs indicator
|
|
self._debuffs_raid_shown[self._debuffs_raid[i]] = true
|
|
|
|
if i == 1 then -- top
|
|
topGlowType, topGlowOptions = I:GetDebuffGlow(name, spellId, count)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- update raidDebuffs
|
|
self.indicators.raidDebuffs:UpdateSize(startIndex - 1)
|
|
for i = startIndex, 3 do
|
|
self.indicators.raidDebuffs[i].index = nil
|
|
end
|
|
|
|
-- update glow
|
|
if not indicatorCustoms["raidDebuffs"] then
|
|
if topGlowType and topGlowType ~= "None" then
|
|
-- to make sure top glow has highest priority
|
|
self._debuffs_glow_current[topGlowType] = topGlowOptions
|
|
end
|
|
for t, o in pairs(self._debuffs_glow_current) do
|
|
self.indicators.raidDebuffs:ShowGlow(t, o, true)
|
|
end
|
|
for t, _ in pairs(self._debuffs_glow_cache) do
|
|
if not self._debuffs_glow_current[t] then
|
|
self.indicators.raidDebuffs:HideGlow(t)
|
|
self._debuffs_glow_cache[t] = nil
|
|
end
|
|
end
|
|
wipe(self._debuffs_glow_current)
|
|
else
|
|
self.indicators.raidDebuffs:ShowGlow(topGlowType, topGlowOptions)
|
|
end
|
|
else
|
|
self.indicators.raidDebuffs:Hide()
|
|
end
|
|
|
|
-- update debuffs
|
|
startIndex = 1
|
|
if enabledIndicators["debuffs"] then
|
|
-- bigDebuffs first
|
|
for debuffIndex, refreshing in pairs(self._debuffs_big) do
|
|
local name, icon, count, debuffType, duration, expirationTime, _, _, _, spellId = UnitDebuff(unit, debuffIndex)
|
|
if name and not self._debuffs_raid_shown[debuffIndex] and startIndex <= indicatorNums["debuffs"] then
|
|
-- start, duration, debuffType, texture, count, refreshing
|
|
self.indicators.debuffs[startIndex]:SetCooldown(expirationTime - duration, duration, debuffType or "", icon, count, refreshing, true)
|
|
self.indicators.debuffs[startIndex].index = debuffIndex -- NOTE: for tooltip
|
|
self.indicators.debuffs[startIndex].spellId = spellId -- NOTE: for blacklist
|
|
startIndex = startIndex + 1
|
|
end
|
|
end
|
|
-- then normal debuffs
|
|
for debuffIndex, refreshing in pairs(self._debuffs_normal) do
|
|
local name, icon, count, debuffType, duration, expirationTime, _, _, _, spellId = UnitDebuff(unit, debuffIndex)
|
|
if name and not self._debuffs_raid_shown[debuffIndex] and startIndex <= indicatorNums["debuffs"] then
|
|
-- start, duration, debuffType, texture, count, refreshing
|
|
self.indicators.debuffs[startIndex]:SetCooldown(expirationTime - duration, duration, debuffType or "", icon, count, refreshing)
|
|
self.indicators.debuffs[startIndex].index = debuffIndex -- NOTE: for tooltip
|
|
self.indicators.debuffs[startIndex].spellId = spellId -- NOTE: for blacklist
|
|
startIndex = startIndex + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
-- update debuffs
|
|
self.indicators.debuffs:UpdateSize(startIndex - 1)
|
|
for i = startIndex, 10 do
|
|
self.indicators.debuffs[i].index = nil
|
|
self.indicators.debuffs[i].spellId = nil
|
|
end
|
|
|
|
-- update dispels
|
|
self.indicators.dispels:SetDispels(self._debuffs_dispel)
|
|
|
|
-- user created indicators
|
|
I:ShowCustomIndicators(self, "debuff")
|
|
|
|
-- update debuffs_cache
|
|
for auraInstanceID, expirationTime in pairs(self._debuffs_cache) do
|
|
-- lost or expired
|
|
if not self._debuffs_current[auraInstanceID] or (expirationTime ~= 0 and GetTime() >= expirationTime) then -- expirationTime == 0: no duration
|
|
self._debuffs_cache[auraInstanceID] = nil
|
|
self._debuffs_count_cache[auraInstanceID] = nil
|
|
end
|
|
end
|
|
|
|
wipe(self._debuffs_current)
|
|
wipe(self._debuffs_normal)
|
|
wipe(self._debuffs_big)
|
|
wipe(self._debuffs_dispel)
|
|
wipe(self._debuffs_raid)
|
|
wipe(self._debuffs_raid_refreshing)
|
|
wipe(self._debuffs_raid_orders)
|
|
wipe(self._debuffs_raid_shown)
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- buffs
|
|
-------------------------------------------------
|
|
local function UnitButton_UpdateBuffs(self)
|
|
local unit = self.state.displayedUnit
|
|
|
|
self.state.BGFlag = nil
|
|
|
|
-- user created indicators
|
|
I:ResetCustomIndicators(self, "buff")
|
|
|
|
local refreshing = false
|
|
local defensiveFound, externalFound, allFound, drinkingFound, pwsFound = 1, 1, 1, false, false
|
|
|
|
for i = 1, 40 do
|
|
-- name, icon, count, debuffType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod, ...
|
|
local name, icon, count, debuffType, duration, expirationTime, source, _, _, spellId, _, _, _, _, _, arg16 = UnitBuff(unit, i)
|
|
if not name then
|
|
break
|
|
end
|
|
|
|
local auraInstanceID = (source or "") .. spellId
|
|
|
|
if duration then
|
|
if Cell.vars.iconAnimation == "duration" then
|
|
local timeIncreased = self._buffs_cache[auraInstanceID] and (expirationTime - self._buffs_cache[auraInstanceID] >= 0.5) or false
|
|
local countIncreased = self._buffs_count_cache[auraInstanceID] and (count > self._buffs_count_cache[auraInstanceID]) or false
|
|
refreshing = timeIncreased or countIncreased
|
|
elseif Cell.vars.iconAnimation == "stack" then
|
|
refreshing = self._buffs_count_cache[auraInstanceID] and (count > self._buffs_count_cache[auraInstanceID]) or false
|
|
else
|
|
refreshing = false
|
|
end
|
|
|
|
-- defensiveCooldowns
|
|
if enabledIndicators["defensiveCooldowns"] and I:IsDefensiveCooldown(name, spellId) and defensiveFound <= indicatorNums["defensiveCooldowns"] then
|
|
-- start, duration, debuffType, texture, count, refreshing
|
|
self.indicators.defensiveCooldowns[defensiveFound]:SetCooldown(expirationTime - duration, duration, nil, icon, count, refreshing)
|
|
defensiveFound = defensiveFound + 1
|
|
end
|
|
|
|
-- externalCooldowns
|
|
if enabledIndicators["externalCooldowns"] and I:IsExternalCooldown(name, spellId, source, unit) and externalFound <= indicatorNums["externalCooldowns"] then
|
|
-- start, duration, debuffType, texture, count, refreshing
|
|
self.indicators.externalCooldowns[externalFound]:SetCooldown(expirationTime - duration, duration, nil, icon, count, refreshing)
|
|
externalFound = externalFound + 1
|
|
end
|
|
|
|
-- allCooldowns
|
|
if enabledIndicators["allCooldowns"] and (I:IsExternalCooldown(name, spellId, source, unit) or I:IsDefensiveCooldown(name, spellId)) and allFound <= indicatorNums["allCooldowns"] then
|
|
-- start, duration, debuffType, texture, count, refreshing
|
|
self.indicators.allCooldowns[allFound]:SetCooldown(expirationTime - duration, duration, nil, icon, count, refreshing)
|
|
allFound = allFound + 1
|
|
end
|
|
|
|
-- drinking
|
|
if enabledIndicators["statusText"] and I:IsDrinking(name) then
|
|
if not self.indicators.statusText:GetStatus() then
|
|
self.indicators.statusText:SetStatus("DRINKING")
|
|
self.indicators.statusText:Show()
|
|
end
|
|
drinkingFound = true
|
|
end
|
|
|
|
-- user created indicators
|
|
I:UpdateCustomIndicators(self, "buff", spellId, name, expirationTime - duration, duration, nil, icon, count, refreshing, source == "player" or source == "pet", arg16)
|
|
|
|
-- check BG flags for statusIcon
|
|
if spellId == 301091 then
|
|
self.state.BGFlag = "alliance"
|
|
end
|
|
if spellId == 301089 then
|
|
self.state.BGFlag = "horde"
|
|
end
|
|
|
|
self._buffs_current[auraInstanceID] = i
|
|
self._buffs_cache[auraInstanceID] = expirationTime
|
|
self._buffs_count_cache[auraInstanceID] = count
|
|
end
|
|
end
|
|
|
|
-- update defensiveCooldowns
|
|
self.indicators.defensiveCooldowns:UpdateSize(defensiveFound - 1)
|
|
|
|
-- update externalCooldowns
|
|
self.indicators.externalCooldowns:UpdateSize(externalFound - 1)
|
|
|
|
-- update allCooldowns
|
|
self.indicators.allCooldowns:UpdateSize(allFound - 1)
|
|
|
|
-- hide drinking
|
|
if not drinkingFound and self.indicators.statusText:GetStatus() == "DRINKING" then
|
|
-- self.indicators.statusText:Hide()
|
|
self.indicators.statusText:SetStatus()
|
|
end
|
|
|
|
-- update buffs_cache
|
|
for auraInstanceID, expirationTime in pairs(self._buffs_cache) do
|
|
-- lost or expired
|
|
if not self._buffs_current[auraInstanceID] or (expirationTime ~= 0 and GetTime() >= expirationTime) then
|
|
self._buffs_cache[auraInstanceID] = nil
|
|
self._buffs_count_cache[auraInstanceID] = nil
|
|
end
|
|
end
|
|
wipe(self._buffs_current)
|
|
|
|
I:ShowCustomIndicators(self, "buff")
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- aura tables
|
|
-------------------------------------------------
|
|
local function InitAuraTables(self)
|
|
-- for icon animation only
|
|
self._buffs_current = {}
|
|
self._buffs_cache = {}
|
|
self._buffs_count_cache = {}
|
|
self._debuffs_current = {}
|
|
self._debuffs_cache = {}
|
|
self._debuffs_count_cache = {}
|
|
|
|
-- debuffs
|
|
self._debuffs_normal = {} -- [auraInstanceID] = refreshing
|
|
self._debuffs_big = {} -- [auraInstanceID] = refreshing
|
|
self._debuffs_dispel = {} -- [debuffType] = true/false
|
|
self._debuffs_raid = {} -- {index1, index2, ...}
|
|
self._debuffs_raid_refreshing = {} -- [auraInstanceID] = refreshing
|
|
self._debuffs_raid_orders = {} -- [auraInstanceID] = order
|
|
self._debuffs_raid_shown = {} -- [auraInstanceID] = true, currently shown by raidDebuffs indicator
|
|
self._debuffs_glow_current = {}
|
|
self._debuffs_glow_cache = {}
|
|
end
|
|
|
|
local function ResetAuraTables(self)
|
|
wipe(self._buffs_current)
|
|
wipe(self._buffs_cache)
|
|
wipe(self._buffs_count_cache)
|
|
wipe(self._debuffs_current)
|
|
wipe(self._debuffs_cache)
|
|
wipe(self._debuffs_count_cache)
|
|
|
|
-- debuffs
|
|
wipe(self._debuffs_normal)
|
|
wipe(self._debuffs_big)
|
|
wipe(self._debuffs_dispel)
|
|
wipe(self._debuffs_raid)
|
|
wipe(self._debuffs_raid_refreshing)
|
|
wipe(self._debuffs_raid_orders)
|
|
wipe(self._debuffs_raid_shown)
|
|
|
|
-- raid debuffs glow
|
|
wipe(self._debuffs_glow_current)
|
|
wipe(self._debuffs_glow_cache)
|
|
if self.indicators.raidDebuffs then
|
|
self.indicators.raidDebuffs:HideGlow()
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- functions
|
|
-------------------------------------------------
|
|
local function UpdateUnitHealthState(self, diff)
|
|
local unit = self.state.displayedUnit
|
|
local guid = self.state.guid
|
|
|
|
local health = UnitHealth(unit) + (diff or 0)
|
|
local healthMax = UnitHealthMax(unit)
|
|
health = min(health, healthMax) --! diff
|
|
|
|
self.state.health = health
|
|
self.state.healthMax = healthMax
|
|
self.state.totalAbsorbs = 0
|
|
|
|
if healthMax == 0 then
|
|
self.state.healthPercent = 0
|
|
else
|
|
self.state.healthPercent = health / healthMax
|
|
end
|
|
|
|
self.state.wasDead = self.state.isDead
|
|
self.state.isDead = health == 0
|
|
if self.state.wasDead ~= self.state.isDead then
|
|
UnitButton_UpdateStatusText(self)
|
|
I.UpdateStatusIcon_Resurrection(self)
|
|
if not self.state.isDead then
|
|
self.state.hasSoulstone = nil
|
|
I.UpdateStatusIcon(self)
|
|
end
|
|
end
|
|
|
|
self.state.wasDeadOrGhost = self.state.isDeadOrGhost
|
|
self.state.isDeadOrGhost = UnitIsDeadOrGhost(unit)
|
|
if self.state.wasDeadOrGhost ~= self.state.isDeadOrGhost then
|
|
I.UpdateStatusIcon_Resurrection(self)
|
|
UnitButton_UpdateHealthColor(self)
|
|
end
|
|
|
|
if enabledIndicators["healthText"] and healthMax ~= 0 then
|
|
if health == healthMax or self.state.isDeadOrGhost then
|
|
if not indicatorCustoms["healthText"] then
|
|
self.indicators.healthText:SetHealth(health, healthMax, self.state.totalAbsorbs)
|
|
self.indicators.healthText:Show()
|
|
else
|
|
self.indicators.healthText:Hide()
|
|
end
|
|
else
|
|
self.indicators.healthText:SetHealth(health, healthMax, self.state.totalAbsorbs)
|
|
self.indicators.healthText:Show()
|
|
end
|
|
else
|
|
self.indicators.healthText:Hide()
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- power filter funcs
|
|
-------------------------------------------------
|
|
local function ShouldShowPowerBar(b)
|
|
if not (b:IsVisible() or b.isPreview) then return end
|
|
if not b.powerSize or b.powerSize == 0 then return end
|
|
|
|
if not b.state.guid then
|
|
return true
|
|
end
|
|
|
|
local class
|
|
if b.state.inVehicle then
|
|
class = "VEHICLE"
|
|
elseif string.find(b.state.guid, "^Player") then
|
|
class = b.state.class
|
|
elseif string.find(b.state.guid, "^Pet") then
|
|
class = "PET"
|
|
elseif string.find(b.state.guid, "^Creature") then
|
|
class = "NPC"
|
|
elseif string.find(b.state.guid, "^Vehicle") then
|
|
class = "VEHICLE"
|
|
end
|
|
|
|
if class then
|
|
return Cell.vars.currentLayoutTable["powerFilters"][class]
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
local function ShowPowerBar(b)
|
|
if b:IsVisible() and not b.isPreview then
|
|
b:RegisterEvent("UNIT_POWER_FREQUENT")
|
|
b:RegisterEvent("UNIT_MAXPOWER")
|
|
b:RegisterEvent("UNIT_DISPLAYPOWER")
|
|
end
|
|
b.widget.powerBar:Show()
|
|
b.widget.powerBarLoss:Show()
|
|
b.widget.gapTexture:Show()
|
|
|
|
P:ClearPoints(b.widget.healthBar)
|
|
P:ClearPoints(b.widget.powerBar)
|
|
if b.orientation == "horizontal" or b.orientation == "vertical_health" then
|
|
P:Point(b.widget.healthBar, "TOPLEFT", b, "TOPLEFT", CELL_BORDER_SIZE, -CELL_BORDER_SIZE)
|
|
P:Point(b.widget.healthBar, "BOTTOMRIGHT", b, "BOTTOMRIGHT", -CELL_BORDER_SIZE, b.powerSize + CELL_BORDER_SIZE * 2)
|
|
P:Point(b.widget.powerBar, "TOPLEFT", b.widget.healthBar, "BOTTOMLEFT", 0, -CELL_BORDER_SIZE)
|
|
P:Point(b.widget.powerBar, "BOTTOMRIGHT", b, "BOTTOMRIGHT", -CELL_BORDER_SIZE, CELL_BORDER_SIZE)
|
|
else
|
|
P:Point(b.widget.healthBar, "TOPLEFT", b, "TOPLEFT", CELL_BORDER_SIZE, -CELL_BORDER_SIZE)
|
|
P:Point(b.widget.healthBar, "BOTTOMRIGHT", b, "BOTTOMRIGHT", -(b.powerSize + CELL_BORDER_SIZE * 2), CELL_BORDER_SIZE)
|
|
P:Point(b.widget.powerBar, "TOPLEFT", b.widget.healthBar, "TOPRIGHT", CELL_BORDER_SIZE, 0)
|
|
P:Point(b.widget.powerBar, "BOTTOMRIGHT", b, "BOTTOMRIGHT", -CELL_BORDER_SIZE, CELL_BORDER_SIZE)
|
|
end
|
|
|
|
if b:IsVisible() then
|
|
-- update now
|
|
UnitButton_UpdatePowerMax(b)
|
|
UnitButton_UpdatePower(b)
|
|
UnitButton_UpdatePowerType(b)
|
|
end
|
|
end
|
|
|
|
local function HidePowerBar(b)
|
|
b:UnregisterEvent("UNIT_POWER_FREQUENT")
|
|
b:UnregisterEvent("UNIT_MAXPOWER")
|
|
b:UnregisterEvent("UNIT_DISPLAYPOWER")
|
|
b.widget.powerBar:Hide()
|
|
b.widget.powerBarLoss:Hide()
|
|
b.widget.gapTexture:Hide()
|
|
|
|
P:ClearPoints(b.widget.healthBar)
|
|
P:Point(b.widget.healthBar, "TOPLEFT", b, "TOPLEFT", CELL_BORDER_SIZE, -CELL_BORDER_SIZE)
|
|
P:Point(b.widget.healthBar, "BOTTOMRIGHT", b, "BOTTOMRIGHT", -CELL_BORDER_SIZE, CELL_BORDER_SIZE)
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- unit button functions
|
|
-------------------------------------------------
|
|
local function UnitButton_UpdateTarget(self)
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
if UnitIsUnit(unit, "target") then
|
|
if highlightEnabled then self.widget.targetHighlight:Show() end
|
|
else
|
|
self.widget.targetHighlight:Hide()
|
|
end
|
|
end
|
|
|
|
local function CheckVehicleRoot(self, petUnit)
|
|
if not petUnit then return end
|
|
|
|
local playerUnit = F:GetPlayerUnit(petUnit)
|
|
|
|
local isRoot
|
|
for i = 1, UnitVehicleSeatCount(playerUnit) do
|
|
local controlType, occupantName, serverName, ejectable, canSwitchSeats = UnitVehicleSeatInfo(playerUnit, i)
|
|
if UnitName(playerUnit) == occupantName then
|
|
isRoot = controlType == "Root"
|
|
break
|
|
end
|
|
end
|
|
|
|
self.indicators.roleIcon:SetRole(isRoot and "VEHICLE" or "NONE")
|
|
end
|
|
|
|
UnitButton_UpdateAssignment = function(self)
|
|
local unit = self.state.unit
|
|
if not unit then return end
|
|
|
|
local partyAssignmentIcon = self.indicators.partyAssignmentIcon
|
|
if enabledIndicators["partyAssignmentIcon"] then
|
|
partyAssignmentIcon:UpdateAssignment(unit)
|
|
|
|
--! check vehicle root
|
|
if self.state.guid and strfind(self.state.guid, "^Vehicle") then
|
|
CheckVehicleRoot(self, unit)
|
|
end
|
|
else
|
|
partyAssignmentIcon:Hide()
|
|
end
|
|
end
|
|
|
|
UnitButton_UpdateLeader = function(self, event)
|
|
local unit = self.state.unit
|
|
if not unit then return end
|
|
|
|
local leaderIcon = self.indicators.leaderIcon
|
|
|
|
if enabledIndicators["leaderIcon"] then
|
|
if indicatorCustoms["leaderIcon"] and (InCombatLockdown() or event == "PLAYER_REGEN_DISABLED") then
|
|
leaderIcon:Hide()
|
|
return
|
|
end
|
|
|
|
local isLeader = UnitIsGroupLeader(unit)
|
|
self.state.isLeader = isLeader
|
|
local isAssistant = UnitIsGroupAssistant(unit) and IsInRaid()
|
|
self.state.isAssistant = isAssistant
|
|
|
|
leaderIcon:SetIcon(isLeader, isAssistant)
|
|
else
|
|
leaderIcon:Hide()
|
|
end
|
|
end
|
|
|
|
local function UnitButton_UpdatePlayerRaidIcon(self)
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
local playerRaidIcon = self.indicators.playerRaidIcon
|
|
|
|
local index = GetRaidTargetIndex(unit)
|
|
|
|
if enabledIndicators["playerRaidIcon"] then
|
|
if index then
|
|
SetRaidTargetIconTexture(playerRaidIcon.tex, index)
|
|
playerRaidIcon:Show()
|
|
else
|
|
playerRaidIcon:Hide()
|
|
end
|
|
else
|
|
playerRaidIcon:Hide()
|
|
end
|
|
end
|
|
|
|
local function UnitButton_UpdateTargetRaidIcon(self)
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
local targetRaidIcon = self.indicators.targetRaidIcon
|
|
|
|
local index = GetRaidTargetIndex(unit.."target")
|
|
|
|
if enabledIndicators["targetRaidIcon"] then
|
|
if index then
|
|
SetRaidTargetIconTexture(targetRaidIcon.tex, index)
|
|
targetRaidIcon:Show()
|
|
else
|
|
targetRaidIcon:Hide()
|
|
end
|
|
else
|
|
targetRaidIcon:Hide()
|
|
end
|
|
end
|
|
|
|
local function UnitButton_UpdateReadyCheck(self)
|
|
local unit = self.state.unit
|
|
if not unit then return end
|
|
|
|
local status = GetReadyCheckStatus(unit)
|
|
self.state.readyCheckStatus = status
|
|
|
|
if status then
|
|
-- self.widget.readyCheckHighlight:SetVertexColor(unpack(READYCHECK_STATUS[status].c))
|
|
-- self.widget.readyCheckHighlight:Show()
|
|
self.indicators.readyCheckIcon:SetStatus(status)
|
|
else
|
|
-- self.widget.readyCheckHighlight:Hide()
|
|
self.indicators.readyCheckIcon:Hide()
|
|
end
|
|
end
|
|
|
|
local function UnitButton_FinishReadyCheck(self)
|
|
if self.state.readyCheckStatus == "waiting" then
|
|
-- self.widget.readyCheckHighlight:SetVertexColor(unpack(READYCHECK_STATUS.notready.c))
|
|
self.indicators.readyCheckIcon:SetStatus("notready")
|
|
end
|
|
C_Timer.After(6, function()
|
|
-- self.widget.readyCheckHighlight:Hide()
|
|
self.indicators.readyCheckIcon:Hide()
|
|
end)
|
|
end
|
|
|
|
UnitButton_UpdatePowerMax = function(self)
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
local value = UnitPowerMax(unit)
|
|
if value < 0 then value = 0 end
|
|
|
|
if barAnimationType == "Smooth" then
|
|
self.widget.powerBar:SetMinMaxSmoothedValue(0, value)
|
|
else
|
|
self.widget.powerBar:SetMinMaxValues(0, value)
|
|
end
|
|
end
|
|
|
|
UnitButton_UpdatePower = function(self)
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
if barAnimationType == "Smooth" then
|
|
self.widget.powerBar:SetSmoothedValue(UnitPower(unit))
|
|
else
|
|
self.widget.powerBar:SetValue(UnitPower(unit))
|
|
end
|
|
end
|
|
|
|
UnitButton_UpdatePowerType = function(self)
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
local r, g, b, lossR, lossG, lossB
|
|
local a = Cell.loaded and CellDB["appearance"]["lossAlpha"] or 1
|
|
|
|
if not UnitIsConnected(unit) then
|
|
r, g, b = 0.5, 0.5, 0.5
|
|
lossR, lossG, lossB = r*0.2, g*0.2, b*0.2
|
|
else
|
|
r, g, b, lossR, lossG, lossB, self.state.powerType = F:GetPowerColor(unit, self.state.class)
|
|
end
|
|
|
|
self.widget.powerBar:SetStatusBarColor(r, g, b)
|
|
self.widget.powerBarLoss:SetVertexColor(lossR, lossG, lossB)
|
|
end
|
|
|
|
local function UnitButton_UpdateHealthMax(self)
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
UpdateUnitHealthState(self)
|
|
|
|
if barAnimationType == "Smooth" then
|
|
self.widget.healthBar:SetMinMaxSmoothedValue(0, self.state.healthMax)
|
|
else
|
|
self.widget.healthBar:SetMinMaxValues(0, self.state.healthMax)
|
|
end
|
|
|
|
if Cell.vars.useGradientColor then
|
|
UnitButton_UpdateHealthColor(self)
|
|
end
|
|
end
|
|
|
|
local function UnitButton_UpdateHealth(self, diff)
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
UpdateUnitHealthState(self, diff)
|
|
local healthPercent = self.state.healthPercent
|
|
|
|
if barAnimationType == "Flash" then
|
|
self.widget.healthBar:SetValue(self.state.health)
|
|
local diff = healthPercent - (self.state.healthPercentOld or healthPercent)
|
|
if diff >= 0 then
|
|
self.func.HideFlash()
|
|
elseif diff <= -0.05 and diff >= -1 then --! player (just joined) UnitHealthMax(unit) may be 1 ====> diff == -maxHealth
|
|
self.func.ShowFlash(abs(diff))
|
|
end
|
|
elseif barAnimationType == "Smooth" then
|
|
self.widget.healthBar:SetSmoothedValue(self.state.health)
|
|
else
|
|
self.widget.healthBar:SetValue(self.state.health)
|
|
end
|
|
|
|
if Cell.vars.useGradientColor then
|
|
UnitButton_UpdateHealthColor(self)
|
|
end
|
|
|
|
self.state.healthPercentOld = healthPercent
|
|
|
|
if enabledIndicators["healthThresholds"] then
|
|
self.indicators.healthThresholds:CheckThreshold(healthPercent)
|
|
else
|
|
self.indicators.healthThresholds:Hide()
|
|
end
|
|
|
|
if CELL_FADE_OUT_HEALTH_PERCENT then
|
|
if self.state.inRange and healthPercent < CELL_FADE_OUT_HEALTH_PERCENT then
|
|
A:FrameFadeIn(self, 0.25, self:GetAlpha(), 1)
|
|
else
|
|
A:FrameFadeOut(self, 0.25, self:GetAlpha(), CellDB["appearance"]["outOfRangeAlpha"])
|
|
end
|
|
end
|
|
end
|
|
|
|
local useLibHealComm = false
|
|
local function UnitButton_UpdateHealPrediction(self)
|
|
if not predictionEnabled then
|
|
self.widget.incomingHeal:Hide()
|
|
return
|
|
end
|
|
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
local value = 0
|
|
|
|
if useLibHealComm and HealComm then
|
|
--! NOTE: use LibHealComm
|
|
if self.__displayedGuid then
|
|
local modifier = HealComm:GetHealModifier(self.__displayedGuid) or 1
|
|
value = (HealComm:GetHealAmount(self.__displayedGuid, HealComm.CASTED_HEALS) or 0) * modifier
|
|
-- local hot = select(3, HealComm:GetNextHealAmount(self.__displayedGuid, HealComm.HOT_HEALS)) or 0
|
|
-- NOTE: hots within 3 seconds
|
|
local hot = (HealComm:GetHealAmount(self.__displayedGuid, HealComm.OVERTIME_AND_BOMB_HEALS, GetTime()+3) or 0) * modifier
|
|
value = value + hot
|
|
end
|
|
else
|
|
value = UnitGetIncomingHeals(unit) or 0
|
|
end
|
|
|
|
if value == 0 then
|
|
self.widget.incomingHeal:Hide()
|
|
return
|
|
end
|
|
|
|
UpdateUnitHealthState(self)
|
|
|
|
self.widget.incomingHeal:SetValue(value / self.state.healthMax)
|
|
end
|
|
|
|
UnitButton_UpdateAuras = function(self)
|
|
if not indicatorsInitialized then return end
|
|
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
UnitButton_UpdateDebuffs(self)
|
|
UnitButton_UpdateBuffs(self)
|
|
I.UpdateStatusIcon(self)
|
|
end
|
|
|
|
local function UnitButton_UpdateThreat(self)
|
|
local unit = self.state.displayedUnit
|
|
if not unit or not UnitExists(unit) then return end
|
|
|
|
local status = UnitThreatSituation(unit)
|
|
if status and status >= 2 then
|
|
if enabledIndicators["aggroBlink"] then
|
|
self.indicators.aggroBlink:ShowAggro(GetThreatStatusColor(status))
|
|
end
|
|
if enabledIndicators["aggroBorder"] then
|
|
self.indicators.aggroBorder:ShowAggro(GetThreatStatusColor(status))
|
|
end
|
|
else
|
|
self.indicators.aggroBlink:Hide()
|
|
self.indicators.aggroBorder:Hide()
|
|
end
|
|
end
|
|
|
|
local function UnitButton_UpdateThreatBar(self)
|
|
if not enabledIndicators["aggroBar"] then
|
|
self.indicators.aggroBar:Hide()
|
|
return
|
|
end
|
|
|
|
local unit = self.state.displayedUnit
|
|
if not unit or not UnitExists(unit) then return end
|
|
|
|
-- isTanking, status, scaledPercentage, rawPercentage, threatValue = UnitDetailedThreatSituation(unit, mobUnit)
|
|
local _, status, scaledPercentage, rawPercentage = UnitDetailedThreatSituation(unit, "target")
|
|
if status then
|
|
self.indicators.aggroBar:Show()
|
|
self.indicators.aggroBar:SetSmoothedValue(scaledPercentage)
|
|
self.indicators.aggroBar:SetStatusBarColor(GetThreatStatusColor(status))
|
|
else
|
|
self.indicators.aggroBar:Hide()
|
|
end
|
|
end
|
|
|
|
local function UnitButton_UpdateInRange(self)
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
local inRange = F:IsInRange(unit)
|
|
|
|
self.state.inRange = inRange
|
|
if Cell.loaded then
|
|
if self.state.inRange ~= self.state.wasInRange then
|
|
if inRange then
|
|
if CELL_FADE_OUT_HEALTH_PERCENT then
|
|
if not self.state.healthPercent or self.state.healthPercent < CELL_FADE_OUT_HEALTH_PERCENT then
|
|
A:FrameFadeIn(self, 0.25, self:GetAlpha(), 1)
|
|
else
|
|
A:FrameFadeOut(self, 0.25, self:GetAlpha(), CellDB["appearance"]["outOfRangeAlpha"])
|
|
end
|
|
else
|
|
A:FrameFadeIn(self, 0.25, self:GetAlpha(), 1)
|
|
end
|
|
else
|
|
A:FrameFadeOut(self, 0.25, self:GetAlpha(), CellDB["appearance"]["outOfRangeAlpha"])
|
|
end
|
|
end
|
|
self.state.wasInRange = inRange
|
|
-- self:SetAlpha(inRange and 1 or CellDB["appearance"]["outOfRangeAlpha"])
|
|
end
|
|
end
|
|
|
|
local function UnitButton_UpdateVehicleStatus(self)
|
|
local unit = self.state.unit
|
|
if not unit then return end
|
|
|
|
if UnitHasVehicleUI(unit) then -- or UnitInVehicle(unit) or UnitUsingVehicle(unit) then
|
|
self.state.inVehicle = true
|
|
if unit == "player" then
|
|
self.state.displayedUnit = "vehicle"
|
|
else
|
|
-- local prefix, id, suffix = strmatch(unit, "([^%d]+)([%d]*)(.*)")
|
|
local prefix, id = strmatch(unit, "([^%d]+)([%d]+)")
|
|
self.state.displayedUnit = prefix.."pet"..id
|
|
end
|
|
self.indicators.nameText:UpdateVehicleName()
|
|
else
|
|
self.state.inVehicle = nil
|
|
self.state.displayedUnit = self.state.unit
|
|
self.indicators.nameText.vehicle:SetText("")
|
|
end
|
|
|
|
if Cell.loaded then
|
|
if ShouldShowPowerBar(self) then
|
|
ShowPowerBar(self)
|
|
else
|
|
HidePowerBar(self)
|
|
end
|
|
end
|
|
end
|
|
|
|
UnitButton_UpdateStatusText = function(self)
|
|
local statusText = self.indicators.statusText
|
|
if not enabledIndicators["statusText"] then
|
|
-- statusText:Hide()
|
|
statusText:SetStatus()
|
|
return
|
|
end
|
|
|
|
local unit = self.state.unit
|
|
if not unit then return end
|
|
|
|
self.state.guid = UnitGUID(unit) -- update!
|
|
if not self.state.guid then return end
|
|
|
|
if not UnitIsConnected(unit) and UnitIsPlayer(unit) then
|
|
statusText:Show()
|
|
statusText:SetStatus("OFFLINE")
|
|
statusText:ShowTimer()
|
|
elseif UnitIsAFK(unit) then
|
|
statusText:Show()
|
|
statusText:SetStatus("AFK")
|
|
statusText:ShowTimer()
|
|
elseif UnitIsFeignDeath(unit) then
|
|
statusText:Show()
|
|
statusText:SetStatus("FEIGN")
|
|
statusText:HideTimer(true)
|
|
elseif UnitIsDeadOrGhost(unit) then
|
|
statusText:Show()
|
|
statusText:HideTimer(true)
|
|
if UnitIsGhost(unit) then
|
|
statusText:SetStatus("GHOST")
|
|
else
|
|
statusText:SetStatus("DEAD")
|
|
end
|
|
elseif statusText:GetStatus() == "DRINKING" then
|
|
-- update colors
|
|
statusText:Show()
|
|
statusText:SetStatus("DRINKING")
|
|
else
|
|
-- statusText:Hide()
|
|
statusText:HideTimer(true)
|
|
statusText:SetStatus()
|
|
end
|
|
end
|
|
|
|
local function UnitButton_UpdateName(self)
|
|
local unit = self.state.unit
|
|
if not unit then return end
|
|
|
|
self.state.name = UnitName(unit)
|
|
self.state.fullName = F:UnitFullName(unit)
|
|
self.state.class = UnitClassBase(unit)
|
|
self.state.guid = UnitGUID(unit)
|
|
self.state.isPlayer = UnitIsPlayer(unit)
|
|
|
|
self.indicators.nameText:UpdateName()
|
|
end
|
|
|
|
UnitButton_UpdateNameColor = function(self)
|
|
local unit = self.state.unit
|
|
if not unit then return end
|
|
|
|
self.state.class = UnitClassBase(unit) --! update class or it may be nil
|
|
|
|
local nameText = self.indicators.nameText
|
|
|
|
if not Cell.loaded then
|
|
nameText:SetColor(1, 1, 1)
|
|
return
|
|
end
|
|
|
|
if UnitIsPlayer(unit) then -- player
|
|
if not UnitIsConnected(unit) then
|
|
nameText:SetColor(F:GetClassColor(self.state.class))
|
|
elseif UnitIsCharmed(unit) then
|
|
nameText:SetColor(F:GetClassColor(self.state.class))
|
|
else
|
|
if Cell.vars.currentLayoutTable["indicators"][1]["color"][1] == "class_color" then
|
|
nameText:SetColor(F:GetClassColor(self.state.class))
|
|
else
|
|
nameText:SetColor(unpack(Cell.vars.currentLayoutTable["indicators"][1]["color"][2]))
|
|
end
|
|
end
|
|
elseif string.find(unit, "pet") then -- pet
|
|
if Cell.vars.currentLayoutTable["indicators"][1]["color"][1] == "class_color" then
|
|
nameText:SetColor(0.5, 0.5, 1)
|
|
else
|
|
nameText:SetColor(unpack(Cell.vars.currentLayoutTable["indicators"][1]["color"][2]))
|
|
end
|
|
else -- npc
|
|
if Cell.vars.currentLayoutTable["indicators"][1]["color"][1] == "class_color" then
|
|
nameText:SetColor(0, 1, 0.2)
|
|
else
|
|
nameText:SetColor(unpack(Cell.vars.currentLayoutTable["indicators"][1]["color"][2]))
|
|
end
|
|
end
|
|
end
|
|
|
|
UnitButton_UpdateHealthColor = function(self)
|
|
local unit = self.state.unit
|
|
if not unit then return end
|
|
|
|
self.state.class = UnitClassBase(unit) --! update class or it may be nil
|
|
|
|
local barR, barG, barB
|
|
local lossR, lossG, lossB
|
|
local barA, lossA = 1, 1
|
|
|
|
if Cell.loaded then
|
|
barA = CellDB["appearance"]["barAlpha"]
|
|
lossA = CellDB["appearance"]["lossAlpha"]
|
|
end
|
|
|
|
if UnitIsPlayer(unit) then -- player
|
|
if not UnitIsConnected(unit) then
|
|
barR, barG, barB = 0.4, 0.4, 0.4
|
|
lossR, lossG, lossB = 0.4, 0.4, 0.4
|
|
elseif UnitIsCharmed(unit) then
|
|
barR, barG, barB = 0.5, 0, 1
|
|
lossR, lossG, lossB = barR*0.2, barG*0.2, barB*0.2
|
|
elseif self.state.inVehicle then
|
|
barR, barG, barB, lossR, lossG, lossB = F:GetHealthColor(self.state.healthPercent, self.state.isDeadOrGhost, 0, 1, 0.2)
|
|
else
|
|
barR, barG, barB, lossR, lossG, lossB = F:GetHealthColor(self.state.healthPercent, self.state.isDeadOrGhost, F:GetClassColor(self.state.class))
|
|
end
|
|
elseif string.find(unit, "pet") then -- pet
|
|
barR, barG, barB, lossR, lossG, lossB = F:GetHealthColor(self.state.healthPercent, self.state.isDeadOrGhost, 0.5, 0.5, 1)
|
|
else -- npc
|
|
barR, barG, barB, lossR, lossG, lossB = F:GetHealthColor(self.state.healthPercent, self.state.isDeadOrGhost, 0, 1, 0.2)
|
|
end
|
|
|
|
-- local r, g, b = RAID_CLASS_COLORS["DEATHKNIGHT"]:GetRGB()
|
|
self.widget.healthBar:SetStatusBarColor(barR, barG, barB, barA)
|
|
self.widget.healthBarLoss:SetVertexColor(lossR, lossG, lossB, lossA)
|
|
|
|
if Cell.loaded and CellDB["appearance"]["healPrediction"][2] then
|
|
self.widget.incomingHeal:SetVertexColor(CellDB["appearance"]["healPrediction"][3][1], CellDB["appearance"]["healPrediction"][3][2], CellDB["appearance"]["healPrediction"][3][3], CellDB["appearance"]["healPrediction"][3][4])
|
|
else
|
|
self.widget.incomingHeal:SetVertexColor(barR, barG, barB, 0.4)
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- LibHealComm
|
|
-------------------------------------------------
|
|
Cell.HealComm = {}
|
|
local function HealComm_UpdateHealPrediction(_, event, casterGUID, spellID, healType, endTime, ...)
|
|
-- print(event, casterGUID, spellID, healType, endTime, ...)
|
|
-- update incomingHeal
|
|
for i = 1, select("#", ...) do
|
|
F:HandleUnitButton("guid", select(i, ...), UnitButton_UpdateHealPrediction)
|
|
end
|
|
end
|
|
Cell.HealComm.HealComm_UpdateHealPrediction = HealComm_UpdateHealPrediction
|
|
|
|
function F:EnableLibHealComm(enabled)
|
|
HealComm = LibStub("LibHealComm-4.0", true)
|
|
if not HealComm then return end
|
|
|
|
useLibHealComm = enabled
|
|
if enabled then
|
|
HealComm.RegisterCallback(Cell.HealComm, "HealComm_HealStarted", "HealComm_UpdateHealPrediction")
|
|
HealComm.RegisterCallback(Cell.HealComm, "HealComm_HealUpdated", "HealComm_UpdateHealPrediction")
|
|
HealComm.RegisterCallback(Cell.HealComm, "HealComm_HealStopped", "HealComm_UpdateHealPrediction")
|
|
HealComm.RegisterCallback(Cell.HealComm, "HealComm_HealDelayed", "HealComm_UpdateHealPrediction")
|
|
HealComm.RegisterCallback(Cell.HealComm, "HealComm_ModifierChanged", "HealComm_UpdateHealPrediction")
|
|
HealComm.RegisterCallback(Cell.HealComm, "HealComm_GUIDDisappeared", "HealComm_UpdateHealPrediction")
|
|
else
|
|
HealComm.UnregisterAllCallbacks(Cell.HealComm)
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- cleu health updater
|
|
-------------------------------------------------
|
|
local cleuHealthUpdater = CreateFrame("Frame", "CellCleuHealthUpdater")
|
|
cleuHealthUpdater:SetScript("OnEvent", function()
|
|
local _, subEvent, _, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20, arg21, arg22 = CombatLogGetCurrentEventInfo()
|
|
|
|
if not F:IsFriend(destFlags) then return end
|
|
|
|
local diff
|
|
if subEvent == "SPELL_HEAL" or subEvent == "SPELL_PERIODIC_HEAL" then
|
|
-- spellId, spellName, spellSchool, amount, overhealing, absorbed, critical
|
|
diff = arg15
|
|
elseif subEvent == "SPELL_DAMAGE" or subEvent == "SPELL_PERIODIC_DAMAGE" then
|
|
-- spellId, spellName, spellSchool, amount, overhealing, absorbed, critical
|
|
diff = -arg15
|
|
elseif subEvent == "SWING_DAMAGE" then
|
|
-- amount
|
|
diff = -arg12
|
|
elseif subEvent == "RANGE_DAMAGE" then
|
|
-- spellId, spellName, spellSchool, amount
|
|
diff = -arg15
|
|
elseif subEvent == "ENVIRONMENTAL_DAMAGE" then
|
|
-- environmentalType, amount
|
|
diff = -arg13
|
|
end
|
|
|
|
if diff and diff ~= 0 then
|
|
F:HandleUnitButton("guid", destGUID, UnitButton_UpdateHealth, diff)
|
|
end
|
|
end)
|
|
|
|
local function UpdateCLEU()
|
|
if CellDB["general"]["useCleuHealthUpdater"] then
|
|
cleuHealthUpdater:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
|
else
|
|
cleuHealthUpdater:UnregisterAllEvents()
|
|
end
|
|
end
|
|
Cell:RegisterCallback("UpdateCLEU", "UnitButton_UpdateCLEU", UpdateCLEU)
|
|
|
|
-------------------------------------------------
|
|
-- translit names
|
|
-------------------------------------------------
|
|
Cell:RegisterCallback("TranslitNames", "UnitButton_TranslitNames", function()
|
|
F:IterateAllUnitButtons(function(b)
|
|
UnitButton_UpdateName(b)
|
|
end, true)
|
|
end)
|
|
|
|
-------------------------------------------------
|
|
-- update all
|
|
-------------------------------------------------
|
|
UnitButton_UpdateAll = function(self)
|
|
if not self:IsVisible() then return end
|
|
|
|
UnitButton_UpdateVehicleStatus(self)
|
|
UnitButton_UpdateName(self)
|
|
UnitButton_UpdateNameColor(self)
|
|
UnitButton_UpdateHealthMax(self)
|
|
UnitButton_UpdateHealth(self)
|
|
UnitButton_UpdateHealPrediction(self)
|
|
UnitButton_UpdateStatusText(self)
|
|
UnitButton_UpdateHealthColor(self)
|
|
UnitButton_UpdateTarget(self)
|
|
UnitButton_UpdatePlayerRaidIcon(self)
|
|
UnitButton_UpdateTargetRaidIcon(self)
|
|
UnitButton_UpdateInRange(self)
|
|
UnitButton_UpdateAssignment(self)
|
|
UnitButton_UpdateLeader(self)
|
|
UnitButton_UpdateReadyCheck(self)
|
|
UnitButton_UpdateThreat(self)
|
|
UnitButton_UpdateThreatBar(self)
|
|
I.UpdateStatusIcon_Resurrection(self)
|
|
|
|
if Cell.loaded and self._powerBarUpdateRequired then
|
|
self._powerBarUpdateRequired = nil
|
|
if ShouldShowPowerBar(self) then
|
|
ShowPowerBar(self)
|
|
else
|
|
HidePowerBar(self)
|
|
end
|
|
else
|
|
UnitButton_UpdatePowerType(self)
|
|
UnitButton_UpdatePowerMax(self)
|
|
UnitButton_UpdatePower(self)
|
|
end
|
|
|
|
UnitButton_UpdateAuras(self)
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- unit button events
|
|
-------------------------------------------------
|
|
local function UnitButton_RegisterEvents(self)
|
|
-- self:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
self:RegisterEvent("GROUP_ROSTER_UPDATE")
|
|
|
|
self:RegisterEvent("UNIT_HEALTH")
|
|
self:RegisterEvent("UNIT_HEALTH_FREQUENT")
|
|
self:RegisterEvent("UNIT_MAXHEALTH")
|
|
|
|
self:RegisterEvent("UNIT_POWER_FREQUENT")
|
|
self:RegisterEvent("UNIT_MAXPOWER")
|
|
self:RegisterEvent("UNIT_DISPLAYPOWER")
|
|
|
|
self:RegisterEvent("UNIT_AURA")
|
|
|
|
self:RegisterEvent("UNIT_HEAL_PREDICTION")
|
|
|
|
self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE")
|
|
self:RegisterEvent("UNIT_THREAT_LIST_UPDATE")
|
|
self:RegisterEvent("UNIT_ENTERED_VEHICLE")
|
|
self:RegisterEvent("UNIT_EXITED_VEHICLE")
|
|
|
|
self:RegisterEvent("UNIT_FLAGS") -- afk
|
|
self:RegisterEvent("UNIT_FACTION") -- mind control
|
|
|
|
self:RegisterEvent("UNIT_CONNECTION") -- offline
|
|
self:RegisterEvent("PLAYER_FLAGS_CHANGED") -- afk
|
|
self:RegisterEvent("UNIT_NAME_UPDATE") -- unknown target
|
|
self:RegisterEvent("ZONE_CHANGED_NEW_AREA") --? update status text
|
|
|
|
-- self:RegisterEvent("PARTY_LEADER_CHANGED") -- GROUP_ROSTER_UPDATE
|
|
-- self:RegisterEvent("PLAYER_ROLES_ASSIGNED") -- GROUP_ROSTER_UPDATE
|
|
self:RegisterEvent("PLAYER_REGEN_ENABLED")
|
|
self:RegisterEvent("PLAYER_REGEN_DISABLED")
|
|
|
|
self:RegisterEvent("PLAYER_TARGET_CHANGED")
|
|
|
|
if Cell.loaded then
|
|
if enabledIndicators["playerRaidIcon"] then
|
|
self:RegisterEvent("RAID_TARGET_UPDATE")
|
|
end
|
|
else
|
|
self:RegisterEvent("RAID_TARGET_UPDATE")
|
|
end
|
|
if Cell.loaded then
|
|
if enabledIndicators["targetRaidIcon"] then
|
|
self:RegisterEvent("UNIT_TARGET")
|
|
end
|
|
else
|
|
self:RegisterEvent("UNIT_TARGET")
|
|
end
|
|
|
|
self:RegisterEvent("READY_CHECK")
|
|
self:RegisterEvent("READY_CHECK_FINISHED")
|
|
self:RegisterEvent("READY_CHECK_CONFIRM")
|
|
|
|
-- self:RegisterEvent("UNIT_PHASE") -- warmode, traditional sources of phasing such as progress through quest chains
|
|
-- self:RegisterEvent("PARTY_MEMBER_DISABLE")
|
|
-- self:RegisterEvent("PARTY_MEMBER_ENABLE")
|
|
-- self:RegisterEvent("INCOMING_RESURRECT_CHANGED")
|
|
|
|
-- self:RegisterEvent("VOICE_CHAT_CHANNEL_ACTIVATED")
|
|
-- self:RegisterEvent("VOICE_CHAT_CHANNEL_DEACTIVATED")
|
|
|
|
-- self:RegisterEvent("UNIT_PET")
|
|
self:RegisterEvent("UNIT_PORTRAIT_UPDATE") -- pet summoned far away
|
|
|
|
pcall(UnitButton_UpdateAll, self)
|
|
end
|
|
|
|
local function UnitButton_UnregisterEvents(self)
|
|
self:UnregisterAllEvents()
|
|
end
|
|
|
|
local function UnitButton_OnEvent(self, event, unit)
|
|
-- print(event, self:GetName(), unit, self.state.displayedUnit, self.state.unit)
|
|
-- if UnitExists(unit) and (UnitIsUnit(unit, self.state.displayedUnit) or UnitIsUnit(unit, self.state.unit)) then
|
|
if unit and (self.state.displayedUnit == unit or self.state.unit == unit) then
|
|
if event == "UNIT_ENTERED_VEHICLE" or event == "UNIT_EXITED_VEHICLE" or event == "UNIT_CONNECTION" then
|
|
self._updateRequired = 1
|
|
self._powerBarUpdateRequired = 1
|
|
|
|
elseif event == "UNIT_NAME_UPDATE" then
|
|
UnitButton_UpdateName(self)
|
|
UnitButton_UpdateNameColor(self)
|
|
UnitButton_UpdateHealthColor(self)
|
|
|
|
elseif event == "UNIT_MAXHEALTH" then
|
|
UnitButton_UpdateHealthMax(self)
|
|
UnitButton_UpdateHealth(self)
|
|
UnitButton_UpdateHealPrediction(self)
|
|
|
|
elseif event == "UNIT_HEALTH" or event == "UNIT_HEALTH_FREQUENT" then
|
|
UnitButton_UpdateHealth(self)
|
|
UnitButton_UpdateHealPrediction(self)
|
|
-- UnitButton_UpdateStatusText(self)
|
|
|
|
elseif event == "UNIT_HEAL_PREDICTION" then
|
|
if not useLibHealComm then
|
|
UnitButton_UpdateHealPrediction(self)
|
|
end
|
|
|
|
elseif event == "UNIT_MAXPOWER" then
|
|
UnitButton_UpdatePowerMax(self)
|
|
UnitButton_UpdatePower(self)
|
|
|
|
elseif event == "UNIT_POWER_FREQUENT" then
|
|
UnitButton_UpdatePower(self)
|
|
|
|
elseif event == "UNIT_DISPLAYPOWER" then
|
|
UnitButton_UpdatePowerMax(self)
|
|
UnitButton_UpdatePower(self)
|
|
UnitButton_UpdatePowerType(self)
|
|
|
|
elseif event == "UNIT_AURA" then
|
|
UnitButton_UpdateAuras(self)
|
|
|
|
elseif event == "UNIT_TARGET" then
|
|
UnitButton_UpdateTargetRaidIcon(self)
|
|
|
|
elseif event == "PLAYER_FLAGS_CHANGED" or event == "UNIT_FLAGS" then
|
|
UnitButton_UpdateStatusText(self)
|
|
|
|
elseif event == "UNIT_FACTION" then -- mind control
|
|
UnitButton_UpdateNameColor(self)
|
|
UnitButton_UpdateHealthColor(self)
|
|
|
|
elseif event == "UNIT_THREAT_SITUATION_UPDATE" then
|
|
UnitButton_UpdateThreat(self)
|
|
|
|
-- elseif event == "INCOMING_RESURRECT_CHANGED" or event == "UNIT_PHASE" or event == "PARTY_MEMBER_DISABLE" or event == "PARTY_MEMBER_ENABLE" then
|
|
-- UnitButton_UpdateStatusIcon(self)
|
|
|
|
elseif event == "READY_CHECK_CONFIRM" then
|
|
UnitButton_UpdateReadyCheck(self)
|
|
|
|
elseif event == "UNIT_PORTRAIT_UPDATE" then -- pet summoned far away
|
|
if self.state.healthMax == 0 then
|
|
self._updateRequired = 1
|
|
self._powerBarUpdateRequired = 1
|
|
end
|
|
end
|
|
|
|
else
|
|
if event == "GROUP_ROSTER_UPDATE" then
|
|
self._updateRequired = 1
|
|
self._powerBarUpdateRequired = 1
|
|
|
|
elseif event == "PLAYER_REGEN_ENABLED" or event == "PLAYER_REGEN_DISABLED" then
|
|
UnitButton_UpdateLeader(self, event)
|
|
|
|
elseif event == "PLAYER_TARGET_CHANGED" then
|
|
UnitButton_UpdateTarget(self)
|
|
UnitButton_UpdateThreatBar(self)
|
|
|
|
elseif event == "UNIT_THREAT_LIST_UPDATE" then
|
|
UnitButton_UpdateThreatBar(self)
|
|
|
|
elseif event == "RAID_TARGET_UPDATE" then
|
|
UnitButton_UpdatePlayerRaidIcon(self)
|
|
UnitButton_UpdateTargetRaidIcon(self)
|
|
|
|
elseif event == "READY_CHECK" then
|
|
UnitButton_UpdateReadyCheck(self)
|
|
|
|
elseif event == "READY_CHECK_FINISHED" then
|
|
UnitButton_FinishReadyCheck(self)
|
|
|
|
elseif event == "ZONE_CHANGED_NEW_AREA" then
|
|
UnitButton_UpdateStatusText(self)
|
|
|
|
-- elseif event == "VOICE_CHAT_CHANNEL_ACTIVATED" or event == "VOICE_CHAT_CHANNEL_DEACTIVATED" then
|
|
-- VOICE_CHAT_CHANNEL_MEMBER_SPEAKING_STATE_CHANGED
|
|
end
|
|
end
|
|
end
|
|
|
|
local timer
|
|
local function EnterLeaveInstance()
|
|
if timer then timer:Cancel() timer=nil end
|
|
timer = C_Timer.NewTimer(1, function()
|
|
F:Debug("|cffff1111*** EnterLeaveInstance:|r UnitButton_UpdateAll")
|
|
F:IterateAllUnitButtons(UnitButton_UpdateAll, true)
|
|
timer = nil
|
|
end)
|
|
end
|
|
Cell:RegisterCallback("EnterInstance", "UnitButton_EnterInstance", EnterLeaveInstance)
|
|
Cell:RegisterCallback("LeaveInstance", "UnitButton_LeaveInstance", EnterLeaveInstance)
|
|
|
|
local function UnitButton_OnAttributeChanged(self, name, value)
|
|
if name == "unit" and not self:GetAttribute("oldUnit") then
|
|
if not value or value ~= self.state.unit then
|
|
-- NOTE: when unitId for this button changes
|
|
if self.__unitGuid then -- self.__unitGuid is deleted when hide
|
|
-- print("deleteUnitGuid:", self:GetName(), self.state.unit, self.__unitGuid)
|
|
Cell.vars.guids[self.__unitGuid] = nil
|
|
self.__unitGuid = nil
|
|
end
|
|
if self.__unitName then
|
|
Cell.vars.names[self.__unitName] = nil
|
|
self.__unitName = nil
|
|
end
|
|
wipe(self.state)
|
|
end
|
|
|
|
if type(value) == "string" then
|
|
self.state.unit = value
|
|
self.state.displayedUnit = value
|
|
if string.find(value, "raid") then Cell.unitButtons.raid.units[value] = self end
|
|
-- for omnicd
|
|
if string.match(value, "raid%d") then
|
|
local i = string.match(value, "%d")
|
|
_G["CellRaidFrameMember"..i] = self
|
|
self.unit = value
|
|
end
|
|
|
|
ResetAuraTables(self)
|
|
end
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- unit button show/hide/enter/leave
|
|
-------------------------------------------------
|
|
Cell.vars.guids = {} -- guid to unitid
|
|
Cell.vars.names = {} -- name to unitid
|
|
|
|
local function UnitButton_OnShow(self)
|
|
self._updateRequired = nil -- prevent UnitButton_UpdateAll twice. when convert party <-> raid, GROUP_ROSTER_UPDATE fired.
|
|
self._powerBarUpdateRequired = 1
|
|
UnitButton_RegisterEvents(self)
|
|
|
|
--[[
|
|
if self.state.unit then
|
|
-- NOTE: update Cell.vars.guids
|
|
local guid = UnitGUID(self.state.unit)
|
|
if guid then
|
|
Cell.vars.guids[guid] = self.state.unit
|
|
end
|
|
--! NOTE: can't get valid name immediately after an unseen player joining into group
|
|
self.__timer = C_Timer.NewTicker(0.5, function()
|
|
local name = GetUnitName(self.state.unit, true)
|
|
if name and name ~= _G.UNKNOWN then
|
|
Cell.vars.names[name] = self.state.unit
|
|
self.__timer:Cancel()
|
|
self.__timer = nil
|
|
end
|
|
end)
|
|
-- print("show", self.state.unit, guid, name)
|
|
end
|
|
]]
|
|
end
|
|
|
|
local function UnitButton_OnHide(self)
|
|
UnitButton_UnregisterEvents(self)
|
|
|
|
ResetAuraTables(self)
|
|
|
|
-- NOTE: update Cell.vars.guids
|
|
-- print("hide", self.state.unit, self.__unitGuid, self.__unitName)
|
|
if self.__unitGuid then
|
|
Cell.vars.guids[self.__unitGuid] = nil
|
|
self.__unitGuid = nil
|
|
end
|
|
if self.__unitName then
|
|
Cell.vars.names[self.__unitName] = nil
|
|
self.__unitName = nil
|
|
end
|
|
self.__displayedGuid = nil
|
|
F:RemoveElementsExceptKeys(self.state, "unit", "displayedUnit")
|
|
end
|
|
|
|
local function UnitButton_OnEnter(self)
|
|
if not IsEncounterInProgress() then UnitButton_UpdateStatusText(self) end
|
|
|
|
if highlightEnabled then self.widget.mouseoverHighlight:Show() end
|
|
|
|
local unit = self.state.displayedUnit
|
|
if not unit then return end
|
|
|
|
F:ShowTooltips(self, "unit", unit)
|
|
end
|
|
|
|
local function UnitButton_OnLeave(self)
|
|
self.widget.mouseoverHighlight:Hide()
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
local UNKNOWN = _G.UNKNOWN
|
|
local UNKNOWNOBJECT = _G.UNKNOWNOBJECT
|
|
local function UnitButton_OnTick(self)
|
|
local e = (self.__tickCount or 0) + 1
|
|
if e >= 2 then -- every 0.5 second
|
|
e = 0
|
|
|
|
if self.state.unit and self.state.displayedUnit then
|
|
local displayedGuid = UnitGUID(self.state.displayedUnit)
|
|
if displayedGuid ~= self.__displayedGuid then
|
|
-- NOTE: displayed unit entity changed
|
|
F:RemoveElementsExceptKeys(self.state, "unit", "displayedUnit")
|
|
self.__displayedGuid = displayedGuid
|
|
self._updateRequired = 1
|
|
self._powerBarUpdateRequired = 1
|
|
end
|
|
|
|
local guid = UnitGUID(self.state.unit)
|
|
if guid and guid ~= self.__unitGuid then
|
|
-- print("guidChanged:", self:GetName(), self.state.unit, guid)
|
|
-- NOTE: unit entity changed
|
|
-- update Cell.vars.guids
|
|
self.__unitGuid = guid
|
|
Cell.vars.guids[guid] = self.state.unit
|
|
|
|
-- NOTE: only save players' names
|
|
if UnitIsPlayer(self.state.unit) then
|
|
-- update Cell.vars.names
|
|
local name = GetUnitName(self.state.unit, true)
|
|
if (name and self.__nameRetries and self.__nameRetries >= 4) or (name and name ~= UNKNOWN and name ~= UNKNOWNOBJECT) then
|
|
self.__unitName = name
|
|
Cell.vars.names[name] = self.state.unit
|
|
self.__nameRetries = nil
|
|
else
|
|
-- NOTE: update on next tick
|
|
-- 国服可以起名为“未知目标”,干!就只多重试4次好了
|
|
self.__nameRetries = (self.__nameRetries or 0) + 1
|
|
self.__unitGuid = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
self.__tickCount = e
|
|
|
|
UnitButton_UpdateInRange(self)
|
|
|
|
if self._updateRequired and self._indicatorReady then
|
|
self._updateRequired = nil
|
|
UnitButton_UpdateAll(self)
|
|
end
|
|
|
|
--! for Xtarget
|
|
if self:GetAttribute("refreshOnUpdate") then
|
|
UnitButton_UpdateAll(self)
|
|
end
|
|
end
|
|
|
|
local function UnitButton_OnUpdate(self, elapsed)
|
|
local e = (self.__updateElapsed or 0) + elapsed
|
|
if e > 0.25 then
|
|
UnitButton_OnTick(self)
|
|
e = 0
|
|
end
|
|
self.__updateElapsed = e
|
|
end
|
|
|
|
-------------------------------------------------
|
|
-- button functions
|
|
-------------------------------------------------
|
|
function B:SetPowerSize(button, size)
|
|
button.powerSize = size
|
|
|
|
if size == 0 then
|
|
HidePowerBar(button)
|
|
else
|
|
if ShouldShowPowerBar(button) then
|
|
ShowPowerBar(button)
|
|
else
|
|
HidePowerBar(button)
|
|
end
|
|
end
|
|
end
|
|
|
|
function B:UpdateShields(button)
|
|
predictionEnabled = CellDB["appearance"]["healPrediction"][1]
|
|
UnitButton_UpdateHealPrediction(button)
|
|
end
|
|
|
|
function B:SetTexture(button, tex)
|
|
button.widget.healthBar:SetStatusBarTexture(tex)
|
|
button.widget.healthBar:GetStatusBarTexture():SetDrawLayer("ARTWORK", -6)
|
|
button.widget.healthBarLoss:SetTexture(tex)
|
|
button.widget.powerBar:SetStatusBarTexture(tex)
|
|
button.widget.powerBar:GetStatusBarTexture():SetDrawLayer("ARTWORK", -6)
|
|
button.widget.powerBarLoss:SetTexture(tex)
|
|
button.widget.incomingHeal:SetTexture(tex)
|
|
button.widget.damageFlashTex:SetTexture(tex)
|
|
end
|
|
|
|
function B:UpdateColor(button)
|
|
UnitButton_UpdateHealthColor(button)
|
|
UnitButton_UpdatePowerType(button)
|
|
button:SetBackdropColor(0, 0, 0, CellDB["appearance"]["bgAlpha"])
|
|
end
|
|
|
|
function B:SetOrientation(button, orientation, rotateTexture)
|
|
local healthBar = button.widget.healthBar
|
|
local healthBarLoss = button.widget.healthBarLoss
|
|
local powerBar = button.widget.powerBar
|
|
local powerBarLoss = button.widget.powerBarLoss
|
|
local incomingHeal = button.widget.incomingHeal
|
|
local damageFlashTex = button.widget.damageFlashTex
|
|
local gapTexture = button.widget.gapTexture
|
|
|
|
gapTexture:SetColorTexture(unpack(CELL_BORDER_COLOR))
|
|
|
|
button.orientation = orientation
|
|
if orientation == "vertical_health" then
|
|
healthBar:SetOrientation("vertical")
|
|
powerBar:SetOrientation("horizontal")
|
|
else
|
|
healthBar:SetOrientation(orientation)
|
|
powerBar:SetOrientation(orientation)
|
|
end
|
|
healthBar:SetRotatesTexture(rotateTexture)
|
|
powerBar:SetRotatesTexture(rotateTexture)
|
|
|
|
button.indicators.healthThresholds:SetOrientation(orientation)
|
|
|
|
if rotateTexture then
|
|
F:RotateTexture(healthBarLoss, 90)
|
|
F:RotateTexture(powerBarLoss, 90)
|
|
F:RotateTexture(incomingHeal, 90)
|
|
F:RotateTexture(damageFlashTex, 90)
|
|
else
|
|
F:RotateTexture(healthBarLoss, 0)
|
|
F:RotateTexture(powerBarLoss, 0)
|
|
F:RotateTexture(incomingHeal, 0)
|
|
F:RotateTexture(damageFlashTex, 0)
|
|
end
|
|
|
|
if orientation == "horizontal" then
|
|
-- update healthBarLoss
|
|
P:ClearPoints(healthBarLoss)
|
|
P:Point(healthBarLoss, "TOPRIGHT", healthBar)
|
|
P:Point(healthBarLoss, "BOTTOMLEFT", healthBar:GetStatusBarTexture(), "BOTTOMRIGHT")
|
|
|
|
-- update powerBarLoss
|
|
P:ClearPoints(powerBarLoss)
|
|
P:Point(powerBarLoss, "TOPRIGHT", powerBar)
|
|
P:Point(powerBarLoss, "BOTTOMLEFT", powerBar:GetStatusBarTexture(), "BOTTOMRIGHT")
|
|
|
|
-- update gapTexture
|
|
P:ClearPoints(gapTexture)
|
|
P:Point(gapTexture, "BOTTOMLEFT", powerBar, "TOPLEFT")
|
|
P:Point(gapTexture, "BOTTOMRIGHT", powerBar, "TOPRIGHT")
|
|
P:Height(gapTexture, CELL_BORDER_SIZE)
|
|
|
|
-- update incomingHeal
|
|
P:ClearPoints(incomingHeal)
|
|
P:Point(incomingHeal, "TOPLEFT", healthBar:GetStatusBarTexture(), "TOPRIGHT")
|
|
P:Point(incomingHeal, "BOTTOMLEFT", healthBar:GetStatusBarTexture(), "BOTTOMRIGHT")
|
|
function incomingHeal:SetValue(incomingPercent)
|
|
local barWidth = healthBar:GetWidth()
|
|
local incomingHealWidth = incomingPercent * barWidth
|
|
local lostHealthWidth = barWidth * (1 - button.state.healthPercent)
|
|
|
|
-- print(incomingPercent, barWidth, incomingHealWidth, lostHealthWidth)
|
|
-- FIXME: if incomingPercent is a very tiny number, like 0.005
|
|
-- P:Scale(incomingHealWidth) ==> 0
|
|
--! if width is set to 0, then the ACTUAL width may be 256!!!
|
|
|
|
if lostHealthWidth == 0 then
|
|
incomingHeal:Hide()
|
|
else
|
|
if lostHealthWidth > incomingHealWidth then
|
|
incomingHeal:SetWidth(incomingHealWidth)
|
|
else
|
|
incomingHeal:SetWidth(lostHealthWidth)
|
|
end
|
|
incomingHeal:Show()
|
|
end
|
|
end
|
|
|
|
-- update damageFlashTex
|
|
P:ClearPoints(damageFlashTex)
|
|
P:Point(damageFlashTex, "TOPLEFT", healthBar:GetStatusBarTexture(), "TOPRIGHT")
|
|
P:Point(damageFlashTex, "BOTTOMLEFT", healthBar:GetStatusBarTexture(), "BOTTOMRIGHT")
|
|
function damageFlashTex:SetValue(lostPercent)
|
|
local barWidth = healthBar:GetWidth()
|
|
damageFlashTex:SetWidth(barWidth * lostPercent)
|
|
end
|
|
else -- vertical
|
|
P:ClearPoints(healthBarLoss)
|
|
P:Point(healthBarLoss, "TOPRIGHT", healthBar)
|
|
P:Point(healthBarLoss, "BOTTOMLEFT", healthBar:GetStatusBarTexture(), "TOPLEFT")
|
|
|
|
if orientation == "vertical" then
|
|
-- update powerBarLoss
|
|
P:ClearPoints(powerBarLoss)
|
|
P:Point(powerBarLoss, "TOPRIGHT", powerBar)
|
|
P:Point(powerBarLoss, "BOTTOMLEFT", powerBar:GetStatusBarTexture(), "TOPLEFT")
|
|
|
|
-- update gapTexture
|
|
P:ClearPoints(gapTexture)
|
|
P:Point(gapTexture, "TOPRIGHT", powerBar, "TOPLEFT")
|
|
P:Point(gapTexture, "BOTTOMRIGHT", powerBar, "BOTTOMLEFT")
|
|
P:Width(gapTexture, CELL_BORDER_SIZE)
|
|
else -- vertical_health
|
|
-- update powerBarLoss
|
|
P:ClearPoints(powerBarLoss)
|
|
P:Point(powerBarLoss, "TOPRIGHT", powerBar)
|
|
P:Point(powerBarLoss, "BOTTOMLEFT", powerBar:GetStatusBarTexture(), "BOTTOMRIGHT")
|
|
|
|
-- update gapTexture
|
|
P:ClearPoints(gapTexture)
|
|
P:Point(gapTexture, "BOTTOMLEFT", powerBar, "TOPLEFT")
|
|
P:Point(gapTexture, "BOTTOMRIGHT", powerBar, "TOPRIGHT")
|
|
P:Height(gapTexture, CELL_BORDER_SIZE)
|
|
end
|
|
|
|
-- update incomingHeal
|
|
P:ClearPoints(incomingHeal)
|
|
P:Point(incomingHeal, "BOTTOMLEFT", healthBar:GetStatusBarTexture(), "TOPLEFT")
|
|
P:Point(incomingHeal, "BOTTOMRIGHT", healthBar:GetStatusBarTexture(), "TOPRIGHT")
|
|
function incomingHeal:SetValue(incomingPercent)
|
|
local barHeight = healthBar:GetHeight()
|
|
local incomingHealHeight = incomingPercent * barHeight
|
|
local lostHealthHeight = barHeight * (1 - button.state.healthPercent)
|
|
|
|
if lostHealthHeight == 0 then
|
|
incomingHeal:Hide()
|
|
else
|
|
if lostHealthHeight > incomingHealHeight then
|
|
incomingHeal:SetHeight(incomingHealHeight)
|
|
else
|
|
incomingHeal:SetHeight(lostHealthHeight)
|
|
end
|
|
incomingHeal:Show()
|
|
end
|
|
end
|
|
|
|
-- update damageFlashTex
|
|
P:ClearPoints(damageFlashTex)
|
|
P:Point(damageFlashTex, "BOTTOMLEFT", healthBar:GetStatusBarTexture(), "TOPLEFT")
|
|
P:Point(damageFlashTex, "BOTTOMRIGHT", healthBar:GetStatusBarTexture(), "TOPRIGHT")
|
|
function damageFlashTex:SetValue(lostPercent)
|
|
local barHeight = healthBar:GetHeight()
|
|
damageFlashTex:SetHeight(barHeight * lostPercent)
|
|
end
|
|
end
|
|
|
|
-- update consumables
|
|
I:UpdateConsumablesOrientation(button, orientation)
|
|
end
|
|
|
|
function B:UpdateHighlightColor(button)
|
|
button.widget.targetHighlight:SetBackdropBorderColor(unpack(CellDB["appearance"]["targetColor"]))
|
|
button.widget.mouseoverHighlight:SetBackdropBorderColor(unpack(CellDB["appearance"]["mouseoverColor"]))
|
|
end
|
|
|
|
function B:UpdateHighlightSize(button)
|
|
local targetHighlight = button.widget.targetHighlight
|
|
local mouseoverHighlight = button.widget.mouseoverHighlight
|
|
|
|
local size = CellDB["appearance"]["highlightSize"]
|
|
|
|
if size ~= 0 then
|
|
highlightEnabled = true
|
|
|
|
P:ClearPoints(targetHighlight)
|
|
P:ClearPoints(mouseoverHighlight)
|
|
|
|
-- update point
|
|
if size < 0 then
|
|
size = abs(size)
|
|
P:Point(targetHighlight, "TOPLEFT", button, "TOPLEFT")
|
|
P:Point(targetHighlight, "BOTTOMRIGHT", button, "BOTTOMRIGHT")
|
|
P:Point(mouseoverHighlight, "TOPLEFT", button, "TOPLEFT")
|
|
P:Point(mouseoverHighlight, "BOTTOMRIGHT", button, "BOTTOMRIGHT")
|
|
else
|
|
P:Point(targetHighlight, "TOPLEFT", button, "TOPLEFT", -size, size)
|
|
P:Point(targetHighlight, "BOTTOMRIGHT", button, "BOTTOMRIGHT", size, -size)
|
|
P:Point(mouseoverHighlight, "TOPLEFT", button, "TOPLEFT", -size, size)
|
|
P:Point(mouseoverHighlight, "BOTTOMRIGHT", button, "BOTTOMRIGHT", size, -size)
|
|
end
|
|
|
|
-- update thickness
|
|
targetHighlight:SetBackdrop({edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = P:Scale(size)})
|
|
mouseoverHighlight:SetBackdrop({edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = P:Scale(size)})
|
|
|
|
-- update color
|
|
targetHighlight:SetBackdropBorderColor(unpack(CellDB["appearance"]["targetColor"]))
|
|
mouseoverHighlight:SetBackdropBorderColor(unpack(CellDB["appearance"]["mouseoverColor"]))
|
|
|
|
UnitButton_UpdateTarget(button) -- 0->!0 show highlight again
|
|
else
|
|
highlightEnabled = false
|
|
targetHighlight:Hide()
|
|
mouseoverHighlight:Hide()
|
|
end
|
|
end
|
|
|
|
-- raidIcons
|
|
function B:UpdatePlayerRaidIcon(button, enabled)
|
|
if not button:IsShown() then return end
|
|
UnitButton_UpdatePlayerRaidIcon(button)
|
|
if enabled then
|
|
button:RegisterEvent("RAID_TARGET_UPDATE")
|
|
else
|
|
button:UnregisterEvent("RAID_TARGET_UPDATE")
|
|
end
|
|
end
|
|
|
|
function B:UpdateTargetRaidIcon(button, enabled)
|
|
if not button:IsShown() then return end
|
|
UnitButton_UpdateTargetRaidIcon(button)
|
|
if enabled then
|
|
button:RegisterEvent("UNIT_TARGET")
|
|
else
|
|
button:UnregisterEvent("UNIT_TARGET")
|
|
end
|
|
end
|
|
|
|
-- healthText
|
|
function B:UpdateHealthText(button)
|
|
if button.state.displayedUnit then
|
|
UpdateUnitHealthState(button)
|
|
end
|
|
end
|
|
|
|
-- statusText
|
|
function B:UpdateStatusText(button)
|
|
UnitButton_UpdateStatusText(button)
|
|
end
|
|
|
|
-- pixel perfect
|
|
function B:UpdatePixelPerfect(button, updateIndicators)
|
|
button:SetBackdrop({bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = P:Scale(CELL_BORDER_SIZE)})
|
|
button:SetBackdropColor(0, 0, 0, CellDB["appearance"]["bgAlpha"])
|
|
button:SetBackdropBorderColor(unpack(CELL_BORDER_COLOR))
|
|
if not InCombatLockdown() then P:Resize(button) end
|
|
|
|
P:Repoint(button.widget.healthBar)
|
|
P:Repoint(button.widget.healthBarLoss)
|
|
P:Repoint(button.widget.powerBar)
|
|
P:Repoint(button.widget.powerBarLoss)
|
|
P:Repoint(button.widget.gapTexture)
|
|
P:Resize(button.widget.gapTexture)
|
|
|
|
P:Repoint(button.widget.incomingHeal)
|
|
P:Repoint(button.widget.damageFlashTex)
|
|
|
|
B:UpdateHighlightSize(button)
|
|
|
|
if updateIndicators then
|
|
-- indicators
|
|
for _, i in pairs(button.indicators) do
|
|
if i.UpdatePixelPerfect then
|
|
i:UpdatePixelPerfect()
|
|
end
|
|
end
|
|
else
|
|
button.indicators.nameText:UpdatePixelPerfect()
|
|
button.indicators.statusText:UpdatePixelPerfect()
|
|
end
|
|
|
|
button.widget.srIcon:UpdatePixelPerfect()
|
|
end
|
|
|
|
B.UpdateAll = UnitButton_UpdateAll
|
|
B.UpdateHealth = UnitButton_UpdateHealth
|
|
B.UpdateHealthMax = UnitButton_UpdateHealthMax
|
|
B.UpdateAuras = UnitButton_UpdateAuras
|
|
B.UpdateName = UnitButton_UpdateName
|
|
|
|
-------------------------------------------------
|
|
-- unit button init
|
|
-------------------------------------------------
|
|
-- local startTimeCache, statusCache = {}, {}
|
|
local startTimeCache = {}
|
|
|
|
-- NOTE: prevent a nil method error
|
|
local DumbFunc = function() end
|
|
|
|
function CellUnitButton_OnLoad(button)
|
|
local name = button:GetName()
|
|
|
|
button.widget = {}
|
|
button.state = {}
|
|
button.func = {}
|
|
button.indicators = {}
|
|
|
|
InitAuraTables(button)
|
|
|
|
-- background
|
|
-- local background = button:CreateTexture(name.."Background", "BORDER")
|
|
-- button.widget.background = background
|
|
-- background:SetAllPoints(button)
|
|
-- background:SetTexture("Interface\\BUTTONS\\WHITE8X8.BLP")
|
|
-- background:SetVertexColor(0, 0, 0, 1)
|
|
|
|
-- backdrop
|
|
button:SetBackdrop({bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = P:Scale(CELL_BORDER_SIZE)})
|
|
button:SetBackdropColor(0, 0, 0, 1)
|
|
button:SetBackdropBorderColor(unpack(CELL_BORDER_COLOR))
|
|
|
|
-- healthbar
|
|
local healthBar = CreateFrame("StatusBar", name.."HealthBar", button)
|
|
button.widget.healthBar = healthBar
|
|
-- P:Point(healthBar, "TOPLEFT", button, "TOPLEFT", 1, -1)
|
|
-- P:Point(healthBar, "BOTTOMRIGHT", button, "BOTTOMRIGHT", -1, 4)
|
|
healthBar:SetStatusBarTexture(Cell.vars.texture)
|
|
healthBar:GetStatusBarTexture():SetDrawLayer("ARTWORK", -6)
|
|
healthBar:SetFrameLevel(button:GetFrameLevel()+5)
|
|
|
|
-- FIXME: fix blizzard shits!
|
|
healthBar:SetScript("OnValueChanged", function(self, value)
|
|
if value == 0 then
|
|
healthBar:SetValue(0.1)
|
|
end
|
|
end)
|
|
|
|
-- hp loss
|
|
local healthBarLoss = button:CreateTexture(name.."HealthBarLoss", "ARTWORK", nil , -7)
|
|
button.widget.healthBarLoss = healthBarLoss
|
|
-- P:Point(healthBarLoss, "TOPRIGHT", healthBar)
|
|
-- P:Point(healthBarLoss, "BOTTOMLEFT", healthBar:GetStatusBarTexture(), "BOTTOMRIGHT")
|
|
healthBarLoss:SetTexture(Cell.vars.texture)
|
|
|
|
-- powerbar
|
|
local powerBar = CreateFrame("StatusBar", name.."PowerBar", button)
|
|
button.widget.powerBar = powerBar
|
|
-- P:Point(powerBar, "TOPLEFT", healthBar, "BOTTOMLEFT", 0, -1)
|
|
-- P:Point(powerBar, "BOTTOMRIGHT", button, "BOTTOMRIGHT", -1, 1)
|
|
powerBar:SetStatusBarTexture(Cell.vars.texture)
|
|
powerBar:GetStatusBarTexture():SetDrawLayer("ARTWORK", -6)
|
|
powerBar:SetFrameLevel(button:GetFrameLevel()+6)
|
|
|
|
local gapTexture = button:CreateTexture(nil, "BORDER")
|
|
button.widget.gapTexture = gapTexture
|
|
-- P:Point(gapTexture, "BOTTOMLEFT", powerBar, "TOPLEFT")
|
|
-- P:Point(gapTexture, "BOTTOMRIGHT", powerBar, "TOPRIGHT")
|
|
-- P:Height(gapTexture, 1)
|
|
gapTexture:SetColorTexture(unpack(CELL_BORDER_COLOR))
|
|
|
|
-- power loss
|
|
local powerBarLoss = button:CreateTexture(name.."PowerBarLoss", "ARTWORK", nil , -7)
|
|
button.widget.powerBarLoss = powerBarLoss
|
|
-- P:Point(powerBarLoss, "TOPRIGHT", powerBar)
|
|
-- P:Point(powerBarLoss, "BOTTOMLEFT", powerBar:GetStatusBarTexture(), "BOTTOMRIGHT")
|
|
powerBarLoss:SetTexture(Cell.vars.texture)
|
|
|
|
-- incoming heal
|
|
local incomingHeal = healthBar:CreateTexture(name.."IncomingHealBar", "ARTWORK", nil, -6)
|
|
button.widget.incomingHeal = incomingHeal
|
|
-- P:Point(incomingHeal, "TOPLEFT", healthBar:GetStatusBarTexture(), "TOPRIGHT")
|
|
-- P:Point(incomingHeal, "BOTTOMLEFT", healthBar:GetStatusBarTexture(), "BOTTOMRIGHT")
|
|
incomingHeal:SetTexture(Cell.vars.texture)
|
|
-- incomingHeal:SetAlpha(0.4)
|
|
incomingHeal:Hide()
|
|
incomingHeal.SetValue = DumbFunc
|
|
|
|
-- shield bar
|
|
local shieldBar = healthBar:CreateTexture(name.."ShieldBar", "ARTWORK", nil, -7)
|
|
button.widget.shieldBar = shieldBar
|
|
shieldBar:SetTexture("Interface\\AddOns\\Cell\\Media\\shield.tga", "REPEAT", "REPEAT")
|
|
shieldBar:SetHorizTile(true)
|
|
shieldBar:SetVertTile(true)
|
|
shieldBar:SetVertexColor(1, 1, 1, 0.4)
|
|
shieldBar:Hide()
|
|
shieldBar.SetValue = DumbFunc
|
|
|
|
-- over-shield glow
|
|
local overShieldGlow = healthBar:CreateTexture(name.."OverShieldGlow", "OVERLAY")
|
|
button.widget.overShieldGlow = overShieldGlow
|
|
overShieldGlow:SetTexture("Interface\\RaidFrame\\Shield-Overshield")
|
|
overShieldGlow:SetBlendMode("ADD")
|
|
overShieldGlow:Hide()
|
|
|
|
-- bar animation
|
|
-- flash
|
|
local damageFlashTex = healthBar:CreateTexture(name.."DamageFlash", "ARTWORK", nil, -6)
|
|
button.widget.damageFlashTex = damageFlashTex
|
|
damageFlashTex:SetTexture("Interface\\BUTTONS\\WHITE8X8")
|
|
damageFlashTex:SetVertexColor(1, 1, 1, 0.7)
|
|
-- P:Point(damageFlashTex, "TOPLEFT", healthBar:GetStatusBarTexture(), "TOPRIGHT")
|
|
-- P:Point(damageFlashTex, "BOTTOMLEFT", healthBar:GetStatusBarTexture(), "BOTTOMRIGHT")
|
|
damageFlashTex:Hide()
|
|
damageFlashTex.SetValue = DumbFunc
|
|
|
|
-- damage flash animation group
|
|
local damageFlashAG = damageFlashTex:CreateAnimationGroup()
|
|
local alpha = damageFlashAG:CreateAnimation("Alpha")
|
|
alpha:SetFromAlpha(0.7)
|
|
alpha:SetToAlpha(0)
|
|
alpha:SetDuration(0.2)
|
|
damageFlashAG:SetScript("OnPlay", function(self)
|
|
damageFlashTex:Show()
|
|
end)
|
|
damageFlashAG:SetScript("OnFinished", function(self)
|
|
damageFlashTex:Hide()
|
|
end)
|
|
|
|
button.func.ShowFlash = function(lostPercent)
|
|
damageFlashTex:SetValue(lostPercent)
|
|
-- damageFlashTex:Show()
|
|
damageFlashAG:Play()
|
|
end
|
|
|
|
button.func.HideFlash = function()
|
|
damageFlashAG:Finish()
|
|
end
|
|
|
|
-- smooth
|
|
Mixin(healthBar, SmoothStatusBarMixin)
|
|
Mixin(powerBar, SmoothStatusBarMixin)
|
|
|
|
button.func.UpdateAnimation = function()
|
|
barAnimationType = CellDB["appearance"]["barAnimation"]
|
|
if aType ~= "Flash" then
|
|
damageFlashAG:Finish()
|
|
end
|
|
end
|
|
|
|
-- target highlight
|
|
local targetHighlight = CreateFrame("Frame", name.."TargetHighlight", button, "BackdropTemplate")
|
|
button.widget.targetHighlight = targetHighlight
|
|
targetHighlight:EnableMouse(false)
|
|
targetHighlight:SetFrameLevel(button:GetFrameLevel()+6)
|
|
-- targetHighlight:SetBackdrop({edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = P:Scale(1)})
|
|
-- P:Point(targetHighlight, "TOPLEFT", button, "TOPLEFT", -1, 1)
|
|
-- P:Point(targetHighlight, "BOTTOMRIGHT", button, "BOTTOMRIGHT", 1, -1)
|
|
targetHighlight:Hide()
|
|
|
|
-- mouseover highlight
|
|
local mouseoverHighlight = CreateFrame("Frame", name.."MouseoverHighlight", button, "BackdropTemplate")
|
|
button.widget.mouseoverHighlight = mouseoverHighlight
|
|
mouseoverHighlight:EnableMouse(false)
|
|
mouseoverHighlight:SetFrameLevel(button:GetFrameLevel()+7)
|
|
-- mouseoverHighlight:SetBackdrop({edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = P:Scale(1)})
|
|
-- P:Point(mouseoverHighlight, "TOPLEFT", button, "TOPLEFT", -1, 1)
|
|
-- P:Point(mouseoverHighlight, "BOTTOMRIGHT", button, "BOTTOMRIGHT", 1, -1)
|
|
mouseoverHighlight:Hide()
|
|
|
|
-- readyCheck highlight
|
|
-- local readyCheckHighlight = button:CreateTexture(name.."ReadyCheckHighlight", "BACKGROUND")
|
|
-- button.widget.readyCheckHighlight = readyCheckHighlight
|
|
-- readyCheckHighlight:SetPoint("TOPLEFT", -1, 1)
|
|
-- readyCheckHighlight:SetPoint("BOTTOMRIGHT", 1, -1)
|
|
-- readyCheckHighlight:SetTexture("Interface\\Buttons\\WHITE8x8")
|
|
-- readyCheckHighlight:Hide()
|
|
|
|
--* tsGlowFrame (Targeted Spells)
|
|
local tsGlowFrame = CreateFrame("Frame", name.."TSGlowFrame", button)
|
|
button.widget.tsGlowFrame = tsGlowFrame
|
|
tsGlowFrame:SetAllPoints(button)
|
|
|
|
--* srGlowFrame (Spell Request)
|
|
local srGlowFrame = CreateFrame("Frame", name.."SRGlowFrame", button)
|
|
button.widget.srGlowFrame = srGlowFrame
|
|
srGlowFrame:SetFrameLevel(button:GetFrameLevel()+120)
|
|
srGlowFrame:SetAllPoints(button)
|
|
|
|
--* drGlowFrame (Dispel Request)
|
|
local drGlowFrame = CreateFrame("Frame", name.."DRGlowFrame", button)
|
|
button.widget.drGlowFrame = drGlowFrame
|
|
drGlowFrame:SetFrameLevel(button:GetFrameLevel()+120)
|
|
drGlowFrame:SetAllPoints(button)
|
|
|
|
--* overlayFrame
|
|
local overlayFrame = CreateFrame("Frame", name.."OverlayFrame", button)
|
|
button.widget.overlayFrame = overlayFrame
|
|
overlayFrame:SetFrameLevel(button:GetFrameLevel()+8) -- button:GetFrameLevel() == 4
|
|
overlayFrame:SetAllPoints(button)
|
|
|
|
-- aggro bar
|
|
local aggroBar = Cell:CreateStatusBar(name.."AggroBar", overlayFrame, 20, 4, 100, true)
|
|
button.indicators.aggroBar = aggroBar
|
|
-- aggroBar:SetPoint("BOTTOMLEFT", overlayFrame, "TOPLEFT", 1, 0)
|
|
aggroBar:Hide()
|
|
|
|
-- indicators
|
|
I:CreateNameText(button)
|
|
I:CreateStatusText(button)
|
|
I:CreateHealthText(button)
|
|
I:CreateStatusIcon(button)
|
|
I:CreatePartyAssignmentIcon(button)
|
|
I:CreateLeaderIcon(button)
|
|
I:CreateReadyCheckIcon(button)
|
|
I:CreateAggroBlink(button)
|
|
I:CreateAggroBorder(button)
|
|
I:CreatePlayerRaidIcon(button)
|
|
I:CreateTargetRaidIcon(button)
|
|
I:CreateAoEHealing(button)
|
|
I:CreateDefensiveCooldowns(button)
|
|
I:CreateExternalCooldowns(button)
|
|
I:CreateAllCooldowns(button)
|
|
I:CreateDispels(button)
|
|
I:CreateDebuffs(button)
|
|
I:CreateRaidDebuffs(button)
|
|
I:CreateTargetCounter(button)
|
|
I:CreateTargetedSpells(button)
|
|
I:CreateConsumables(button)
|
|
I:CreateHealthThresholds(button)
|
|
I:CreateMissingBuffs(button)
|
|
U:CreateSpellRequestIcon(button)
|
|
U:CreateDispelRequestText(button)
|
|
|
|
-- events
|
|
button:SetScript("OnAttributeChanged", UnitButton_OnAttributeChanged) -- init
|
|
button:HookScript("OnShow", UnitButton_OnShow)
|
|
button:HookScript("OnHide", UnitButton_OnHide) -- use _onhide for click-castings
|
|
button:HookScript("OnEnter", UnitButton_OnEnter) -- SecureHandlerEnterLeaveTemplate
|
|
button:HookScript("OnLeave", UnitButton_OnLeave) -- SecureHandlerEnterLeaveTemplate
|
|
button:SetScript("OnUpdate", UnitButton_OnUpdate)
|
|
button:SetScript("OnEvent", UnitButton_OnEvent)
|
|
button:RegisterForClicks("AnyDown")
|
|
end
|