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.
853 lines
35 KiB
853 lines
35 KiB
--========================================================--
|
|
-- Scorpio UnitFrame Indicator --
|
|
-- --
|
|
-- Author : kurapica125@outlook.com --
|
|
-- Create Date : 2020/11/25 --
|
|
--========================================================--
|
|
|
|
--========================================================--
|
|
Scorpio "Scorpio.Secure.UnitFrame.Indicator" "1.0.0"
|
|
--========================================================--
|
|
|
|
namespace "Scorpio.Secure.UnitFrame"
|
|
|
|
------------------------------------------------------------
|
|
-- Indicator --
|
|
------------------------------------------------------------
|
|
__ChildProperty__(UnitFrame, "NameLabel")
|
|
__ChildProperty__(InSecureUnitFrame, "NameLabel")
|
|
__Sealed__() class "NameLabel" { FontString }
|
|
|
|
__ChildProperty__(UnitFrame, "LevelLabel")
|
|
__ChildProperty__(InSecureUnitFrame, "LevelLabel")
|
|
__Sealed__() class "LevelLabel" { FontString }
|
|
|
|
__ChildProperty__(UnitFrame, "HealthLabel")
|
|
__ChildProperty__(InSecureUnitFrame, "HealthLabel")
|
|
__Sealed__() class "HealthLabel" { FontString }
|
|
|
|
__ChildProperty__(UnitFrame, "PowerLabel")
|
|
__ChildProperty__(InSecureUnitFrame, "PowerLabel")
|
|
__Sealed__() class "PowerLabel" { FontString }
|
|
|
|
__ChildProperty__(UnitFrame, "HealthBar")
|
|
__ChildProperty__(InSecureUnitFrame, "HealthBar")
|
|
__Sealed__() class "HealthBar" { StatusBar }
|
|
|
|
__ChildProperty__(UnitFrame, "PowerBar")
|
|
__ChildProperty__(InSecureUnitFrame, "PowerBar")
|
|
__Sealed__() class "PowerBar" { StatusBar }
|
|
|
|
__ChildProperty__(UnitFrame, "ClassPowerBar")
|
|
__ChildProperty__(InSecureUnitFrame, "ClassPowerBar")
|
|
__Sealed__() class "ClassPowerBar" { StatusBar }
|
|
|
|
__ChildProperty__(UnitFrame, "HiddenManaBar")
|
|
__ChildProperty__(InSecureUnitFrame, "HiddenManaBar")
|
|
__Sealed__() class "HiddenManaBar" { StatusBar }
|
|
|
|
__ChildProperty__(UnitFrame, "DisconnectIcon")
|
|
__ChildProperty__(InSecureUnitFrame, "DisconnectIcon")
|
|
__Sealed__() class "DisconnectIcon" { Texture }
|
|
|
|
__ChildProperty__(UnitFrame, "CombatIcon")
|
|
__ChildProperty__(InSecureUnitFrame, "CombatIcon")
|
|
__Sealed__() class "CombatIcon" { Texture }
|
|
|
|
__ChildProperty__(UnitFrame, "ResurrectIcon")
|
|
__ChildProperty__(InSecureUnitFrame, "ResurrectIcon")
|
|
__Sealed__() class "ResurrectIcon" { Texture }
|
|
|
|
__ChildProperty__(UnitFrame, "RaidTargetIcon")
|
|
__ChildProperty__(InSecureUnitFrame, "RaidTargetIcon")
|
|
__Sealed__() class "RaidTargetIcon" { Texture }
|
|
|
|
__ChildProperty__(UnitFrame, "ReadyCheckIcon")
|
|
__ChildProperty__(InSecureUnitFrame, "ReadyCheckIcon")
|
|
__Sealed__() class "ReadyCheckIcon" { Texture }
|
|
|
|
__ChildProperty__(UnitFrame, "RaidRosterIcon")
|
|
__ChildProperty__(InSecureUnitFrame, "RaidRosterIcon")
|
|
__Sealed__() class "RaidRosterIcon" { Texture }
|
|
|
|
__ChildProperty__(UnitFrame, "RoleIcon")
|
|
__ChildProperty__(InSecureUnitFrame, "RoleIcon")
|
|
__Sealed__() class "RoleIcon" { Texture }
|
|
|
|
__ChildProperty__(UnitFrame, "LeaderIcon")
|
|
__ChildProperty__(InSecureUnitFrame, "LeaderIcon")
|
|
__Sealed__() class "LeaderIcon" { Texture }
|
|
|
|
__ChildProperty__(UnitFrame, "CastBar")
|
|
__ChildProperty__(InSecureUnitFrame, "CastBar")
|
|
__Sealed__() class "CastBar" { CooldownStatusBar }
|
|
|
|
__ChildProperty__(UnitFrame, "AuraPanel")
|
|
__ChildProperty__(InSecureUnitFrame,"AuraPanel")
|
|
__Sealed__() class "AuraPanel" (function(_ENV)
|
|
inherit "ElementPanel"
|
|
|
|
import "System.Reactive"
|
|
|
|
local tconcat = table.concat
|
|
local tinsert = table.insert
|
|
local wipe = wipe
|
|
local strtrim = Toolset.trim
|
|
local validate = Enum.ValidateValue
|
|
local shareCooldown = { start = 0, duration = 0 }
|
|
local cache = {}
|
|
|
|
local function refreshAura(self, unit, filter, eleIdx, auraIdx, name, icon, count, dtype, duration, expires, caster, isStealable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff, castByPlayer, ...)
|
|
if not name or eleIdx > self.MaxCount then return eleIdx end
|
|
|
|
if not self.CustomFilter or self.CustomFilter(name, icon, count, dtype, duration, expires, caster, isStealable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff, castByPlayer, ...) then
|
|
self.Elements[eleIdx]:Show()
|
|
|
|
shareCooldown.start = expires - duration
|
|
shareCooldown.duration = duration
|
|
|
|
self.AuraIndex[eleIdx] = auraIdx
|
|
self.AuraName[eleIdx] = name
|
|
self.AuraIcon[eleIdx] = icon
|
|
self.AuraCount[eleIdx] = count
|
|
self.AuraDebuff[eleIdx] = dtype
|
|
self.AuraCooldown[eleIdx] = shareCooldown
|
|
self.AuraStealable[eleIdx] = isStealable and not UnitIsUnit(unit, "player")
|
|
self.AuraSpellID[eleIdx] = spellID
|
|
self.AuraBossDebuff[eleIdx] = isBossDebuff
|
|
self.AuraCastByPlayer[eleIdx] = castByPlayer
|
|
|
|
eleIdx = eleIdx + 1
|
|
end
|
|
|
|
auraIdx = auraIdx + 1
|
|
return refreshAura(self, unit, filter, eleIdx, auraIdx, UnitAura(unit, auraIdx, filter))
|
|
end
|
|
|
|
local function refreshAuraByPriorty(self, unit, filter, priority, auraIdx, name, icon, count, dtype, duration, expires, caster, isStealable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff, castByPlayer, ...)
|
|
if not name then return end
|
|
|
|
if not self.CustomFilter or self.CustomFilter(name, icon, count, dtype, duration, expires, caster, isStealable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff, castByPlayer, ...) then
|
|
local order = priority[name] or priority[spellID]
|
|
if order then
|
|
cache[order] = auraIdx
|
|
else
|
|
tinsert(cache, auraIdx)
|
|
end
|
|
end
|
|
|
|
auraIdx = auraIdx + 1
|
|
return refreshAuraByPriorty(self, unit, filter, priority, auraIdx, UnitAura(unit, auraIdx, filter))
|
|
end
|
|
|
|
local function OnElementCreated(self, ele)
|
|
return ele:InstantApplyStyle()
|
|
end
|
|
|
|
--- The aura filters
|
|
__Sealed__() enum "AuraFilter" { "HELPFUL", "HARMFUL", "PLAYER", "RAID", "CANCELABLE", "NOT_CANCELABLE", "INCLUDE_NAME_PLATE_ONLY" }
|
|
|
|
------------------------------------------------------
|
|
-- Property
|
|
------------------------------------------------------
|
|
--- The aura filter
|
|
property "AuraFilter" {
|
|
type = struct{ AuraFilter } + String,
|
|
field = "__AuraPanel_AuraFilter",
|
|
set = function(self, filter)
|
|
-- No more check, just keep it simple
|
|
if type(filter) == "table" then
|
|
filter = tconcat(filter, "|")
|
|
else
|
|
filter = filter and strtrim(filter) or ""
|
|
end
|
|
|
|
if filter == "" then
|
|
self.Count = 0
|
|
end
|
|
|
|
self.__AuraPanel_AuraFilter = filter
|
|
end,
|
|
}
|
|
|
|
--- The custom filter
|
|
property "CustomFilter" { type = Function }
|
|
|
|
--- The aura priority with order
|
|
property "AuraPriority" { type = struct { String + Number }, handler = function(self, val) self._AuraPriorityCache = {} if val then for i, v in ipairs(val) do self._AuraPriorityCache[v] = i end end end }
|
|
|
|
--- The property to drive the refreshing
|
|
property "Refresh" {
|
|
set = function(self, unit)
|
|
self.Unit = unit
|
|
local filter = self.AuraFilter
|
|
if not filter or filter == "" then return end
|
|
|
|
local auraPriority = self.AuraPriority
|
|
if not auraPriority or #auraPriority == 0 then
|
|
self.Count = refreshAura(self, unit, filter, 1, 1, UnitAura(unit, 1, filter)) - 1
|
|
else
|
|
wipe(cache) for i = 1, #auraPriority do cache[i] = false end
|
|
refreshAuraByPriorty(self, unit, filter, self._AuraPriorityCache, 1, UnitAura(unit, 1, filter))
|
|
|
|
local eleIdx = 1
|
|
for i = 1, #cache do
|
|
local aIdx = cache[i]
|
|
if aIdx then
|
|
local name, icon, count, dtype, duration, expires, caster, isStealable, nameplateShowPersonal, spellID, canApplyAura, isBossDebuff, castByPlayer = UnitAura(unit, aIdx, filter)
|
|
|
|
self.Elements[eleIdx]:Show()
|
|
|
|
shareCooldown.start = expires - duration
|
|
shareCooldown.duration = duration
|
|
|
|
self.AuraIndex[eleIdx] = aIdx
|
|
self.AuraName[eleIdx] = name
|
|
self.AuraIcon[eleIdx] = icon
|
|
self.AuraCount[eleIdx] = count
|
|
self.AuraDebuff[eleIdx] = dtype
|
|
self.AuraCooldown[eleIdx] = shareCooldown
|
|
self.AuraStealable[eleIdx] = isStealable and not UnitIsUnit(unit, "player")
|
|
self.AuraSpellID[eleIdx] = spellID
|
|
self.AuraBossDebuff[eleIdx] = isBossDebuff
|
|
self.AuraCastByPlayer[eleIdx] = castByPlayer
|
|
|
|
eleIdx = eleIdx + 1
|
|
if eleIdx > self.MaxCount then break end
|
|
end
|
|
end
|
|
|
|
self.Count = eleIdx - 1
|
|
end
|
|
end
|
|
}
|
|
|
|
--- The unit of the current aura
|
|
property "Unit" { type = String }
|
|
|
|
------------------------------------------------------
|
|
-- Observable Property
|
|
------------------------------------------------------
|
|
__Indexer__() __Observable__()
|
|
property "AuraIndex" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "AuraName" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "AuraIcon" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "AuraCount" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "AuraDebuff" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "AuraCooldown" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "AuraStealable" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "AuraSpellID" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "AuraBossDebuff" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "AuraCastByPlayer" { set = Toolset.fakefunc }
|
|
|
|
------------------------------------------------------
|
|
-- Constructor
|
|
------------------------------------------------------
|
|
function __ctor(self)
|
|
self.OnElementCreated = self.OnElementCreated + OnElementCreated
|
|
end
|
|
end)
|
|
|
|
__ChildProperty__(UnitFrame, "BuffPanel")
|
|
__ChildProperty__(InSecureUnitFrame, "BuffPanel")
|
|
__Sealed__() class "BuffPanel" { AuraPanel }
|
|
|
|
__ChildProperty__(UnitFrame, "DebuffPanel")
|
|
__ChildProperty__(InSecureUnitFrame, "DebuffPanel")
|
|
__Sealed__() class "DebuffPanel" { AuraPanel }
|
|
|
|
__ChildProperty__(UnitFrame, "ClassBuffPanel")
|
|
__ChildProperty__(InSecureUnitFrame, "ClassBuffPanel")
|
|
__Sealed__() class "ClassBuffPanel" { AuraPanel }
|
|
|
|
__Sealed__() class "AuraPanelIcon" (function(_ENV)
|
|
inherit "Frame"
|
|
|
|
local isObjectType = Class.IsObjectType
|
|
|
|
local function OnEnter(self)
|
|
if self.ShowTooltip and self.AuraIndex then
|
|
local parent = self:GetParent()
|
|
if not parent then return end
|
|
|
|
GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
|
|
GameTooltip:SetUnitAura(parent.Unit, self.AuraIndex, parent.AuraFilter)
|
|
end
|
|
end
|
|
|
|
local function OnLeave(self)
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
property "ShowTooltip" { type = Boolean, default = true }
|
|
|
|
property "AuraIndex" { type = Number }
|
|
|
|
function __ctor(self)
|
|
self.OnEnter = self.OnEnter + OnEnter
|
|
self.OnLeave = self.OnLeave + OnLeave
|
|
end
|
|
end)
|
|
|
|
__ChildProperty__(UnitFrame, "TotemPanel")
|
|
__ChildProperty__(InSecureUnitFrame,"TotemPanel")
|
|
__Sealed__() class "TotemPanel" (function(_ENV)
|
|
inherit "ElementPanel"
|
|
|
|
import "System.Reactive"
|
|
|
|
local MAX_TOTEMS = _G.MAX_TOTEMS
|
|
local SLOT_MAP = {}
|
|
|
|
for slot, index in ipairs(select(2, UnitClass("player")) == "SHAMAN" and _G.SHAMAN_TOTEM_PRIORITIES or _G.STANDARD_TOTEM_PRIORITIES) do
|
|
SLOT_MAP[index] = slot
|
|
end
|
|
|
|
local shareCooldown = { start = 0, duration = 0 }
|
|
|
|
local function OnElementCreated(self, ele)
|
|
return ele:InstantApplyStyle()
|
|
end
|
|
|
|
------------------------------------------------------
|
|
-- Property
|
|
------------------------------------------------------
|
|
property "Refresh" {
|
|
set = function(self, unit)
|
|
local eleIdx = 1
|
|
for i = 1, MAX_TOTEMS do
|
|
local haveTotem, name, startTime, duration, icon = GetTotemInfo(SLOT_MAP[i])
|
|
if haveTotem then
|
|
local ele = self.Elements[eleIdx]
|
|
if not ele then return end
|
|
ele:Show()
|
|
ele.Slot = SLOT_MAP[i]
|
|
|
|
shareCooldown.start = startTime
|
|
shareCooldown.duration = duration
|
|
|
|
self.TotemName[eleIdx] = name
|
|
self.TotemIcon[eleIdx] = icon
|
|
self.TotemCooldown[eleIdx] = shareCooldown
|
|
|
|
eleIdx = eleIdx + 1
|
|
end
|
|
end
|
|
|
|
self.Count = eleIdx - 1
|
|
end
|
|
}
|
|
|
|
------------------------------------------------------
|
|
-- Observable Property
|
|
------------------------------------------------------
|
|
__Indexer__() __Observable__()
|
|
property "TotemName" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "TotemIcon" { set = Toolset.fakefunc }
|
|
|
|
__Indexer__() __Observable__()
|
|
property "TotemCooldown" { set = Toolset.fakefunc }
|
|
|
|
------------------------------------------------------
|
|
-- Constructor
|
|
------------------------------------------------------
|
|
function __ctor(self)
|
|
self.OnElementCreated = self.OnElementCreated + OnElementCreated
|
|
end
|
|
end)
|
|
|
|
__Sealed__() class "TotemPanelIcon" (function(_ENV)
|
|
inherit "Frame"
|
|
|
|
local function OnEnter(self)
|
|
if self.ShowTooltip then
|
|
GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
|
|
GameTooltip:SetTotem(self.Slot)
|
|
end
|
|
end
|
|
|
|
local function OnLeave(self)
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
property "Slot" { type = Number }
|
|
property "ShowTooltip" { type = Boolean, default = true }
|
|
|
|
function __ctor(self)
|
|
self.OnEnter = self.OnEnter + OnEnter
|
|
self.OnLeave = self.OnLeave + OnLeave
|
|
end
|
|
end)
|
|
|
|
-- A health bar with prediction elements
|
|
__ChildProperty__(UnitFrame, "PredictionHealthBar")
|
|
__ChildProperty__(InSecureUnitFrame,"PredictionHealthBar")
|
|
__Sealed__() class "PredictionHealthBar" (function(_ENV)
|
|
inherit "StatusBar"
|
|
|
|
local function updateFillBar(self, previousTexture, bar, amount, barOffsetXPercent)
|
|
local totalWidth, totalHeight = self:GetSize()
|
|
|
|
if ( totalWidth == 0 or amount == 0 ) then
|
|
bar:Hide()
|
|
if ( bar.overlay ) then
|
|
bar.overlay:Hide()
|
|
end
|
|
return previousTexture
|
|
end
|
|
|
|
local barOffsetX = 0
|
|
if ( barOffsetXPercent ) then
|
|
barOffsetX = totalWidth * barOffsetXPercent
|
|
end
|
|
|
|
bar:ClearAllPoints()
|
|
bar:SetPoint("TOPLEFT", previousTexture, "TOPRIGHT", barOffsetX, 0)
|
|
bar:SetPoint("BOTTOMLEFT", previousTexture, "BOTTOMRIGHT", barOffsetX, 0)
|
|
|
|
local _, totalMax = self:GetMinMaxValues()
|
|
|
|
local barSize = (amount / totalMax) * totalWidth
|
|
bar:SetWidth(barSize)
|
|
bar:Show()
|
|
if ( bar.overlay ) then
|
|
bar.overlay:SetTexCoord(0, Clamp(barSize / bar.overlay.tileSize, 0, 1), 0, Clamp(totalHeight / bar.overlay.tileSize, 0, 1))
|
|
bar.overlay:Show()
|
|
end
|
|
return bar
|
|
end
|
|
|
|
property "HealPrediction" {
|
|
set = function(self, unit)
|
|
local maxHealth = unit and UnitHealthMax(unit) or 0
|
|
|
|
if maxHealth <= 0 then
|
|
self.myHealPrediction:Hide()
|
|
self.otherHealPrediction:Hide()
|
|
self.totalAbsorb:Hide()
|
|
self.totalAbsorbOverlay:Hide()
|
|
self.myHealAbsorb:Hide()
|
|
self.myHealAbsorbLeftShadow:Hide()
|
|
self.overAbsorbGlow:Hide()
|
|
self.overHealAbsorbGlow:Hide()
|
|
return
|
|
end
|
|
|
|
local health = unit and UnitHealth(unit)
|
|
|
|
local myIncomingHeal = UnitGetIncomingHeals(unit, "player") or 0
|
|
local allIncomingHeal = UnitGetIncomingHeals(unit) or 0
|
|
local totalAbsorb = UnitGetTotalAbsorbs(unit) or 0
|
|
local totalHealAbsorb = UnitGetTotalHealAbsorbs(unit) or 0
|
|
local otherIncomingHeal = 0
|
|
local overHealAbsorb = false
|
|
local overAbsorb = false
|
|
|
|
if health < totalHealAbsorb then
|
|
totalHealAbsorb = health
|
|
overHealAbsorb = true
|
|
end
|
|
|
|
if health - totalHealAbsorb + allIncomingHeal > maxHealth * self.MaxHealOverflowRatio then
|
|
allIncomingHeal = maxHealth * self.MaxHealOverflowRatio - health + totalHealAbsorb
|
|
end
|
|
|
|
--Split up incoming heals.
|
|
if allIncomingHeal >= myIncomingHeal then
|
|
otherIncomingHeal = allIncomingHeal - myIncomingHeal
|
|
else
|
|
myIncomingHeal = allIncomingHeal
|
|
end
|
|
|
|
if health - totalHealAbsorb + allIncomingHeal + totalAbsorb >= maxHealth or health + totalAbsorb >= maxHealth then
|
|
overAbsorb = totalAbsorb > 0
|
|
|
|
if allIncomingHeal > totalHealAbsorb then
|
|
totalAbsorb = max(0, maxHealth - (health - totalHealAbsorb + allIncomingHeal))
|
|
else
|
|
totalAbsorb = max(0, maxHealth - health)
|
|
end
|
|
end
|
|
|
|
self.overHealAbsorbGlow:SetShown(overHealAbsorb)
|
|
self.overAbsorbGlow:SetShown(overAbsorb)
|
|
|
|
local healthTexture = self:GetStatusBarTexture()
|
|
local totalHealAbsorbPct = totalHealAbsorb / maxHealth
|
|
|
|
local healAbsorbTexture = nil
|
|
|
|
if totalHealAbsorb > allIncomingHeal then
|
|
local shownHealAbsorb = totalHealAbsorb - allIncomingHeal
|
|
local shownHealAbsorbPercent= shownHealAbsorb / maxHealth
|
|
healAbsorbTexture = updateFillBar(self, healthTexture, self.myHealAbsorb, shownHealAbsorb, -shownHealAbsorbPercent)
|
|
|
|
--If there are incoming heals the left shadow would be overlayed by the incoming heals
|
|
--so it isn't shown.
|
|
if ( allIncomingHeal > 0 ) then
|
|
self.myHealAbsorbLeftShadow:Hide()
|
|
else
|
|
self.myHealAbsorbLeftShadow:ClearAllPoints()
|
|
self.myHealAbsorbLeftShadow:SetPoint("TOPLEFT", healAbsorbTexture, "TOPLEFT", 0, 0)
|
|
self.myHealAbsorbLeftShadow:SetPoint("BOTTOMLEFT", healAbsorbTexture, "BOTTOMLEFT", 0, 0)
|
|
self.myHealAbsorbLeftShadow:Show()
|
|
end
|
|
|
|
-- The right shadow is only shown if there are absorbs on the health bar.
|
|
if ( totalAbsorb > 0 ) then
|
|
self.myHealAbsorbRightShadow:ClearAllPoints()
|
|
self.myHealAbsorbRightShadow:SetPoint("TOPLEFT", healAbsorbTexture, "TOPRIGHT", -8, 0)
|
|
self.myHealAbsorbRightShadow:SetPoint("BOTTOMLEFT", healAbsorbTexture, "BOTTOMRIGHT", -8, 0)
|
|
self.myHealAbsorbRightShadow:Show()
|
|
else
|
|
self.myHealAbsorbRightShadow:Hide()
|
|
end
|
|
else
|
|
self.myHealAbsorb:Hide()
|
|
self.myHealAbsorbRightShadow:Hide()
|
|
self.myHealAbsorbLeftShadow:Hide()
|
|
end
|
|
|
|
--Show myIncomingHeal on the health bar.
|
|
local incomingHealsTexture = updateFillBar(self, healthTexture, self.myHealPrediction, myIncomingHeal, -totalHealAbsorbPct)
|
|
--Append otherIncomingHeal on the health bar.
|
|
incomingHealsTexture = updateFillBar(self, incomingHealsTexture, self.otherHealPrediction, otherIncomingHeal)
|
|
|
|
--Appen absorbs to the correct section of the health bar.
|
|
local appendTexture = nil
|
|
if ( healAbsorbTexture ) then
|
|
--If there is a healAbsorb part shown, append the absorb to the end of that.
|
|
appendTexture = healAbsorbTexture
|
|
else
|
|
--Otherwise, append the absorb to the end of the the incomingHeals part
|
|
appendTexture = incomingHealsTexture
|
|
end
|
|
updateFillBar(self, appendTexture, self.totalAbsorb, totalAbsorb)
|
|
end
|
|
}
|
|
|
|
property "MaxHealOverflowRatio" { type = Number, default = 1.00 }
|
|
|
|
__Template__{
|
|
MyHealPrediction = Texture,
|
|
OtherHealPrediction = Texture,
|
|
TotalAbsorb = Texture,
|
|
TotalAbsorbOverlay = Texture,
|
|
|
|
MyHealAbsorb = Texture,
|
|
MyHealAbsorbLeftShadow = Texture,
|
|
MyHealAbsorbRightShadow = Texture,
|
|
|
|
OverAbsorbGlow = Texture,
|
|
OverHealAbsorbGlow = Texture,
|
|
}
|
|
function __ctor(self)
|
|
self.myHealPrediction = self:GetChild("MyHealPrediction")
|
|
self.otherHealPrediction= self:GetChild("OtherHealPrediction")
|
|
self.totalAbsorb = self:GetChild("TotalAbsorb")
|
|
self.totalAbsorbOverlay = self:GetChild("TotalAbsorbOverlay")
|
|
self.myHealAbsorb = self:GetChild("MyHealAbsorb")
|
|
self.myHealAbsorbLeftShadow = self:GetChild("MyHealAbsorbLeftShadow")
|
|
self.myHealAbsorbRightShadow= self:GetChild("MyHealAbsorbRightShadow")
|
|
self.overAbsorbGlow = self:GetChild("OverAbsorbGlow")
|
|
self.overHealAbsorbGlow = self:GetChild("OverHealAbsorbGlow")
|
|
|
|
self.totalAbsorb.overlay = self.totalAbsorbOverlay
|
|
self.totalAbsorbOverlay.tileSize = 32
|
|
end
|
|
end)
|
|
|
|
------------------------------------------------------------
|
|
-- Default Style --
|
|
------------------------------------------------------------
|
|
local shareRect = RectType()
|
|
|
|
Style.UpdateSkin("Default", {
|
|
[NameLabel] = {
|
|
drawLayer = "BORDER",
|
|
fontObject = GameFontNormalSmall,
|
|
text = Wow.UnitName(true),
|
|
textColor = Wow.UnitColor(),
|
|
},
|
|
[LevelLabel] = {
|
|
drawLayer = "BORDER",
|
|
fontObject = GameFontNormalSmall,
|
|
text = Wow.UnitLevel(),
|
|
vertexColor = Wow.UnitLevelColor(),
|
|
},
|
|
[HealthLabel] = {
|
|
drawLayer = "BORDER",
|
|
fontObject = GameFontNormalSmall,
|
|
text = Wow.UnitHealth(),
|
|
},
|
|
[PowerLabel] = {
|
|
drawLayer = "BORDER",
|
|
fontObject = GameFontNormalSmall,
|
|
text = Wow.UnitPower(),
|
|
},
|
|
[HealthBar] = {
|
|
frameStrata = "LOW",
|
|
enableMouse = false,
|
|
statusBarTexture = {
|
|
file = [[Interface\TargetingFrame\UI-StatusBar]],
|
|
},
|
|
|
|
value = Wow.UnitHealth(),
|
|
minMaxValues = Wow.UnitHealthMax(),
|
|
statusBarColor = Color.GREEN,
|
|
},
|
|
[PowerBar] = {
|
|
frameStrata = "LOW",
|
|
enableMouse = false,
|
|
statusBarTexture = {
|
|
file = [[Interface\TargetingFrame\UI-StatusBar]],
|
|
},
|
|
|
|
value = Wow.UnitPower(),
|
|
minMaxValues = Wow.UnitPowerMax(),
|
|
statusBarColor = Wow.UnitPowerColor(),
|
|
},
|
|
[HiddenManaBar] = {
|
|
frameStrata = "LOW",
|
|
enableMouse = false,
|
|
statusBarTexture = {
|
|
file = [[Interface\TargetingFrame\UI-StatusBar]],
|
|
},
|
|
|
|
value = Wow.UnitMana(),
|
|
minMaxValues = Wow.UnitManaMax(),
|
|
visible = Wow.UnitManaVisible(),
|
|
statusBarColor = Color.MANA,
|
|
},
|
|
[ClassPowerBar] = {
|
|
frameStrata = "LOW",
|
|
enableMouse = false,
|
|
statusBarTexture = {
|
|
file = [[Interface\TargetingFrame\UI-StatusBar]],
|
|
},
|
|
|
|
value = Wow.ClassPower(),
|
|
minMaxValues = Wow.ClassPowerMax(),
|
|
statusBarColor = Wow.ClassPowerColor(),
|
|
visible = Wow.ClassPowerUsable(),
|
|
},
|
|
[DisconnectIcon] = {
|
|
file = [[Interface\CharacterFrame\Disconnect-Icon]],
|
|
size = Size(16, 16),
|
|
visible = Wow.UnitIsDisconnected(),
|
|
},
|
|
[CombatIcon] = {
|
|
file = [[Interface\CharacterFrame\UI-StateIcon]],
|
|
texCoords = RectType(.5, 1, 0, .49),
|
|
size = Size(24, 24),
|
|
visible = Wow.PlayerInCombat(),
|
|
},
|
|
[ResurrectIcon] = {
|
|
file = [[Interface\RaidFrame\Raid-Icon-Rez]],
|
|
size = Size(16, 16),
|
|
visible = Wow.UnitIsResurrect(),
|
|
},
|
|
[RaidTargetIcon] = {
|
|
file = [[Interface\TargetingFrame\UI-RaidTargetingIcons]],
|
|
size = Size(16, 16),
|
|
texCoords = Wow.UnitRaidTargetIndex():Map(function(index)
|
|
if index then
|
|
index = index - 1
|
|
local left, right, top, bottom
|
|
local cIncr = RAID_TARGET_ICON_DIMENSION / RAID_TARGET_TEXTURE_DIMENSION
|
|
left = mod(index , RAID_TARGET_TEXTURE_COLUMNS) * cIncr
|
|
right = left + cIncr
|
|
top = floor(index / RAID_TARGET_TEXTURE_ROWS) * cIncr
|
|
bottom = top + cIncr
|
|
shareRect.left = left
|
|
shareRect.right = right
|
|
shareRect.top = top
|
|
shareRect.bottom= bottom
|
|
end
|
|
return shareRect
|
|
end),
|
|
visible = Wow.UnitRaidTargetIndex():Map(function(val) return val and true or false end),
|
|
},
|
|
[ReadyCheckIcon] = {
|
|
file = Wow.UnitReadyCheck():Map(function(state)
|
|
return state == "ready" and READY_CHECK_READY_TEXTURE
|
|
or state == "notready" and READY_CHECK_NOT_READY_TEXTURE
|
|
or state == "waiting" and READY_CHECK_WAITING_TEXTURE
|
|
or nil
|
|
end),
|
|
visible = Wow.UnitReadyCheckVisible(),
|
|
size = Size(16, 16),
|
|
},
|
|
[RaidRosterIcon] = {
|
|
file = Wow.UnitGroupRoster():Map(function(assign)
|
|
return assign == "MAINTANK" and [[Interface\GROUPFRAME\UI-GROUP-MAINTANKICON]]
|
|
or assign == "MAINASSIST" and [[Interface\GROUPFRAME\UI-GROUP-MAINASSISTICON]]
|
|
or nil
|
|
end),
|
|
size = Size(16, 16),
|
|
},
|
|
[RoleIcon] = {
|
|
file = [[Interface\LFGFrame\UI-LFG-ICON-PORTRAITROLES]],
|
|
texCoords = Wow.UnitRole():Map(function(role)
|
|
if role and role ~= "NONE" then
|
|
local left, right, top, bottom = GetTexCoordsForRoleSmallCircle(role)
|
|
|
|
shareRect.left = left
|
|
shareRect.right = right
|
|
shareRect.top = top
|
|
shareRect.bottom= bottom
|
|
else
|
|
shareRect.left = 0
|
|
shareRect.right = 0
|
|
shareRect.top = 0
|
|
shareRect.bottom= 0
|
|
end
|
|
return shareRect
|
|
end),
|
|
size = Size(16, 16),
|
|
},
|
|
[LeaderIcon] = {
|
|
file = [[Interface\GroupFrame\UI-Group-LeaderIcon]],
|
|
size = Size(16, 16),
|
|
visible = Wow.UnitIsLeader(),
|
|
},
|
|
[CastBar] = {
|
|
cooldown = Wow.UnitCastCooldown(),
|
|
reverse = Wow.UnitCastChannel(),
|
|
showSafeZone = Wow.UnitIsPlayer(),
|
|
},
|
|
[AuraPanel] = {
|
|
refresh = Wow.UnitAura(),
|
|
elementType = AuraPanelIcon,
|
|
|
|
frameStrata = "MEDIUM",
|
|
columnCount = 6,
|
|
rowCount = 6,
|
|
elementWidth = 16,
|
|
elementHeight = 16,
|
|
hSpacing = 2,
|
|
vSpacing = 2,
|
|
enableMouse = false,
|
|
},
|
|
[BuffPanel] = {
|
|
auraFilter = "HELPFUL",
|
|
},
|
|
[DebuffPanel] = {
|
|
auraFilter = "HARMFUL",
|
|
},
|
|
[ClassBuffPanel] = {
|
|
auraFilter = "PLAYER",
|
|
},
|
|
[AuraPanelIcon] = {
|
|
enableMouse = true,
|
|
auraIndex = Wow.FromPanelProperty("AuraIndex"),
|
|
},
|
|
[TotemPanel] = {
|
|
refresh = Wow.UnitTotem(),
|
|
visible = Wow.UnitIsPlayer(),
|
|
elementType = TotemPanelIcon,
|
|
|
|
frameStrata = "MEDIUM",
|
|
columnCount = _G.MAX_TOTEMS,
|
|
rowCount = 1,
|
|
elementWidth = 16,
|
|
elementHeight = 16,
|
|
hSpacing = 2,
|
|
vSpacing = 2,
|
|
enableMouse = false,
|
|
},
|
|
[TotemPanelIcon] = {
|
|
enableMouse = true,
|
|
},
|
|
[PredictionHealthBar] = {
|
|
frameStrata = "LOW",
|
|
enableMouse = false,
|
|
statusBarColor = Wow.UnitConditionColor(true, Color.RED),
|
|
statusBarTexture = {
|
|
file = [[Interface\TargetingFrame\UI-StatusBar]],
|
|
},
|
|
|
|
value = Wow.UnitHealthFrequent(),
|
|
minMaxValues = Wow.UnitHealthMax(),
|
|
healPrediction = Wow.UnitHealPrediction(),
|
|
|
|
MyHealPrediction = {
|
|
drawLayer = "BORDER",
|
|
subLevel = 5,
|
|
color = Color.WHITE,
|
|
gradient = GradientType("VERTICAL", Color(8/255, 93/255, 72/255), Color(11/255, 136/255, 105/255)),
|
|
},
|
|
OtherHealPrediction = {
|
|
drawLayer = "BORDER",
|
|
subLevel = 5,
|
|
color = Color.WHITE,
|
|
gradient = GradientType("VERTICAL", Color(11/255, 53/255, 43/255), Color(21/255, 89/255, 72/255)),
|
|
},
|
|
TotalAbsorb = {
|
|
file = [[Interface\RaidFrame\Shield-Fill]],
|
|
drawLayer = "BORDER",
|
|
subLevel = 5,
|
|
},
|
|
TotalAbsorbOverlay = {
|
|
file = [[Interface\RaidFrame\Shield-Overlay]],
|
|
hWrapMode = "REPEAT",
|
|
vWrapMode = "REPEAT",
|
|
drawLayer = "BORDER",
|
|
subLevel = 6,
|
|
},
|
|
MyHealAbsorb = {
|
|
file = [[Interface\RaidFrame\Absorb-Fill]],
|
|
hWrapMode = "REPEAT",
|
|
vWrapMode = "REPEAT",
|
|
drawLayer = "ARTWORK",
|
|
subLevel = 1,
|
|
},
|
|
MyHealAbsorbLeftShadow = {
|
|
file = [[Interface\RaidFrame\Absorb-Edge]],
|
|
drawLayer = "ARTWORK",
|
|
subLevel = 1,
|
|
},
|
|
MyHealAbsorbRightShadow = {
|
|
file = [[Interface\RaidFrame\Absorb-Edge]],
|
|
drawLayer = "ARTWORK",
|
|
subLevel = 1,
|
|
texCoords = RectType(1, 0, 0, 1),
|
|
},
|
|
OverAbsorbGlow = {
|
|
file = [[Interface\RaidFrame\Shield-Overshield]],
|
|
alphaMode = "ADD",
|
|
drawLayer = "ARTWORK",
|
|
subLevel = 2,
|
|
location = { Anchor("BOTTOMLEFT", -7, 0, nil, "BOTTOMRIGHT"), Anchor("TOPLEFT", -7, 0, nil, "TOPRIGHT") },
|
|
width = 16,
|
|
},
|
|
OverHealAbsorbGlow = {
|
|
file = [[Interface\RaidFrame\Absorb-Overabsorb]],
|
|
alphaMode = "ADD",
|
|
drawLayer = "ARTWORK",
|
|
subLevel = 2,
|
|
location = { Anchor("BOTTOMRIGHT", 7, 0, nil, "BOTTOMLEFT"), Anchor("TOPRIGHT", 7, 0, nil, "TOPLEFT") },
|
|
width = 16,
|
|
},
|
|
},
|
|
})
|
|
|