Files
coa-elvui/ElvUI/Libraries/oUF/elements/classpower.lua
T
2023-06-01 14:40:10 -07:00

313 lines
8.6 KiB
Lua

--[[
# Element: ClassPower
Handles the visibility and updating of the player's class resources (like Chi Orbs or Holy Power) and combo points.
## Widget
ClassPower - An `table` consisting of as many StatusBars as the theoretical maximum return of [UnitPowerMax](http://wowprogramming.com/docs/api/UnitPowerMax.html).
## Sub-Widgets
.bg - A `Texture` used as a background. It will inherit the color of the main StatusBar.
## Sub-Widget Options
.multiplier - Used to tint the background based on the widget's R, G and B values. Defaults to 1 (number)[0-1]
## Notes
A default texture will be applied if the sub-widgets are StatusBars and don't have a texture set.
If the sub-widgets are StatusBars, their minimum and maximum values will be set to 0 and 1 respectively.
Supported class powers:
- All - Combo Points
- Mage - Arcane Charges
- Monk - Chi Orbs
- Paladin - Holy Power
- Warlock - Soul Shards
## Examples
local ClassPower = {}
for index = 1, 10 do
local Bar = CreateFrame('StatusBar', nil, self)
-- Position and size.
Bar:SetSize(16, 16)
Bar:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', (index - 1) * Bar:GetWidth(), 0)
ClassPower[index] = Bar
end
-- Register with oUF
self.ClassPower = ClassPower
--]]
local _, ns = ...
local oUF = ns.oUF
local _, PlayerClass = UnitClass('player')
-- sourced from FrameXML/Constants.lua
local SPELL_POWER_ENERGY = 3
local COMBO_POINTS_ID = 4
-- Holds the class specific stuff.
local ClassPowerID, ClassPowerType
local ClassPowerEnable, ClassPowerDisable
local RequireSpec, RequirePower, RequireSpell
local function UpdateColor(element, powerType)
local color = element.__owner.colors.power[powerType]
local r, g, b = color.r, color.g, color.b
for i = 1, #element do
local bar = element[i]
bar:SetStatusBarColor(r, g, b)
local bg = bar.bg
if(bg) then
local mu = bg.multiplier or 1
bg:SetVertexColor(r * mu, g * mu, b * mu)
end
end
--[[ Callback: ClassPower:PostUpdateColor(r, g, b)
Called after the element color has been updated.
* self - the ClassPower element
* r - the red component of the used color (number)[0-1]
* g - the green component of the used color (number)[0-1]
* b - the blue component of the used color (number)[0-1]
--]]
if(element.PostUpdateColor) then
element:PostUpdateColor(r, g, b)
end
end
local function Update(self, event, unit, powerType)
if(not (unit and (UnitIsUnit(unit, 'player') and (not powerType or powerType == ClassPowerType)
or unit == 'vehicle' and powerType == 'COMBO_POINTS'))) then
return
end
local element = self.ClassPower
--[[ Callback: ClassPower:PreUpdate(event)
Called before the element has been updated.
* self - the ClassPower element
]]
if(element.PreUpdate) then
element:PreUpdate()
end
local cur, max, oldMax
if(event ~= 'ClassPowerDisable') then
local powerID = unit == 'vehicle' and COMBO_POINTS_ID or ClassPowerID
powerType = powerType or ClassPowerType
max = powerType == 'COMBO_POINTS' and GetComboPoints(unit, 'target') or UnitPower(unit, powerID)
cur = powerType == 'COMBO_POINTS' and GetComboPoints(unit, 'target') or UnitPower(unit, powerID)
local numActive = cur + 0.9
for i = 1, max do
if(i > numActive) then
element[i]:Hide()
element[i]:SetValue(0)
else
element[i]:Show()
element[i]:SetValue(cur - i + 1)
end
end
oldMax = element.__max
if(max ~= oldMax) then
if(max < oldMax) then
for i = max + 1, oldMax do
element[i]:Hide()
element[i]:SetValue(0)
end
end
element.__max = max
end
end
--[[ Callback: ClassPower:PostUpdate(cur, max, hasMaxChanged, powerType)
Called after the element has been updated.
* self - the ClassPower element
* cur - the current amount of power (number)
* max - the maximum amount of power (number)
* hasMaxChanged - indicates whether the maximum amount has changed since the last update (boolean)
* powerType - the active power type (string)
--]]
if(element.PostUpdate) then
return element:PostUpdate(cur, max, oldMax ~= max, powerType)
end
end
local function Path(self, ...)
--[[ Override: ClassPower.Override(self, event, unit, ...)
Used to completely override the internal update function.
* self - the parent object
* event - the event triggering the update (string)
* unit - the unit accompanying the event (string)
* ... - the arguments accompanying the event
--]]
return (self.ClassPower.Override or Update) (self, ...)
end
local function Visibility(self, event, unit)
local element = self.ClassPower
local shouldEnable
if UnitHasVehicleUI('player') then
shouldEnable = true
unit = 'vehicle'
elseif(not RequirePower or RequirePower == UnitPowerType('player')) then
if(not RequireSpell or IsSpellKnown(RequireSpell)) then
self:UnregisterEvent('SPELLS_CHANGED', Visibility)
shouldEnable = true
unit = 'player'
else
self:RegisterEvent('SPELLS_CHANGED', Visibility, true)
end
end
local isEnabled = element.__isEnabled
local powerType = unit == 'vehicle' and 'COMBO_POINTS' or ClassPowerType
if(shouldEnable) then
--[[ Override: ClassPower:UpdateColor(powerType)
Used to completely override the internal function for updating the widgets' colors.
* self - the ClassPower element
* powerType - the active power type (string)
--]]
(element.UpdateColor or UpdateColor) (element, powerType)
end
if(shouldEnable and not isEnabled) then
ClassPowerEnable(self)
--[[ Callback: ClassPower:PostVisibility(isVisible)
Called after the element's visibility has been changed.
* self - the ClassPower element
* isVisible - the current visibility state of the element (boolean)
--]]
if(element.PostVisibility) then
element:PostVisibility(true)
end
elseif(not shouldEnable and (isEnabled or isEnabled == nil)) then
ClassPowerDisable(self)
if(element.PostVisibility) then
element:PostVisibility(false)
end
elseif(shouldEnable and isEnabled) then
Path(self, event, unit, powerType)
end
end
local function VisibilityPath(self, ...)
--[[ Override: ClassPower.OverrideVisibility(self, event, unit)
Used to completely override the internal visibility function.
* self - the parent object
* event - the event triggering the update (string)
* unit - the unit accompanying the event (string)
--]]
return (self.ClassPower.OverrideVisibility or Visibility) (self, ...)
end
local function ForceUpdate(element)
return VisibilityPath(element.__owner, 'ForceUpdate', element.__owner.unit)
end
do
function ClassPowerEnable(self)
self:RegisterEvent('UNIT_MAXPOWER', Path)
self:RegisterEvent('UNIT_POWER_UPDATE', Path)
self:RegisterEvent('PLAYER_TARGET_CHANGED', VisibilityPath, true)
self.ClassPower.__isEnabled = true
if UnitHasVehicleUI('player') then
Path(self, 'ClassPowerEnable', 'vehicle', 'COMBO_POINTS')
end
end
function ClassPowerDisable(self)
self:UnregisterEvent('UNIT_POWER_UPDATE', Path)
self:UnregisterEvent('UNIT_MAXPOWER', Path)
self:UnregisterEvent('PLAYER_TARGET_CHANGED', VisibilityPath)
local element = self.ClassPower
for i = 1, #element do
element[i]:Hide()
end
element.__isEnabled = false
Path(self, 'ClassPowerDisable', 'player', ClassPowerType)
end
if(PlayerClass == 'ROGUE' or PlayerClass == 'DRUID' or PlayerClass == 'HERO') then
ClassPowerType = 'COMBO_POINTS'
if(PlayerClass == 'DRUID') then
RequirePower = SPELL_POWER_ENERGY
RequireSpell = 768 -- cat form
end
end
end
local function Enable(self, unit)
local element = self.ClassPower
if(element and UnitIsUnit(unit, 'player')) then
element.__owner = self
element.__max = #element
element.ForceUpdate = ForceUpdate
if (RequireSpell and not IsSpellKnown(RequireSpell)) then
self:RegisterEvent('SPELLS_CHANGED', VisibilityPath, true)
end
if(RequirePower) then
self:RegisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
end
self:RegisterEvent('UNIT_COMBO_POINTS', VisibilityPath)
element.ClassPowerEnable = ClassPowerEnable
element.ClassPowerDisable = ClassPowerDisable
for i = 1, #element do
local bar = element[i]
if bar:IsObjectType('StatusBar') then
if not bar:GetStatusBarTexture() then
bar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
end
bar:SetMinMaxValues(0, 1)
end
end
return true
end
end
local function Disable(self)
if(self.ClassPower) then
ClassPowerDisable(self)
self:UnregisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
self:UnregisterEvent('SPELLS_CHANGED', Visibility)
self:RegisterEvent('UNIT_COMBO_POINTS', VisibilityPath)
end
end
oUF:AddElement('ClassPower', VisibilityPath, Enable, Disable)