initial commit
This commit is contained in:
357
Libraries/oUF/elements/classpower.lua
Normal file
357
Libraries/oUF/elements/classpower.lua
Normal file
@@ -0,0 +1,357 @@
|
||||
--[[
|
||||
# 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 SPEC_MAGE_ARCANE = SPEC_MAGE_ARCANE or 1
|
||||
local SPEC_MONK_WINDWALKER = SPEC_MONK_WINDWALKER or 3
|
||||
local SPEC_PALADIN_RETRIBUTION = SPEC_PALADIN_RETRIBUTION or 3
|
||||
local SPEC_WARLOCK_DESTRUCTION = SPEC_WARLOCK_DESTRUCTION or 3
|
||||
local SPELL_POWER_ENERGY = Enum.PowerType.Energy or 3
|
||||
local SPELL_POWER_COMBO_POINTS = Enum.PowerType.ComboPoints or 4
|
||||
local SPELL_POWER_SOUL_SHARDS = Enum.PowerType.SoulShards or 7
|
||||
local SPELL_POWER_HOLY_POWER = Enum.PowerType.HolyPower or 9
|
||||
local SPELL_POWER_CHI = Enum.PowerType.Chi or 12
|
||||
local SPELL_POWER_ARCANE_CHARGES = Enum.PowerType.ArcaneCharges or 16
|
||||
|
||||
-- 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[1], color[2], color[3]
|
||||
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, mod, oldMax, chargedIndex
|
||||
if(event ~= 'ClassPowerDisable') then
|
||||
local powerID = unit == 'vehicle' and SPELL_POWER_COMBO_POINTS or ClassPowerID
|
||||
cur = UnitPower(unit, powerID, true)
|
||||
max = UnitPowerMax(unit, powerID)
|
||||
mod = UnitPowerDisplayMod(powerID)
|
||||
|
||||
-- mod should never be 0, but according to Blizz code it can actually happen
|
||||
cur = mod == 0 and 0 or cur / mod
|
||||
|
||||
-- BUG: Destruction is supposed to show partial soulshards, but Affliction and Demonology should only show full ones
|
||||
if(ClassPowerType == 'SOUL_SHARDS' and GetSpecialization() ~= SPEC_WARLOCK_DESTRUCTION) then
|
||||
cur = cur - cur % 1
|
||||
end
|
||||
|
||||
if(PlayerClass == 'ROGUE') then
|
||||
local chargedPoints = GetUnitChargedPowerPoints(unit)
|
||||
-- according to Blizzard there will only be one
|
||||
chargedIndex = chargedPoints and chargedPoints[1]
|
||||
end
|
||||
|
||||
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)
|
||||
* chargedIndex - the index of the currently charged power point (number?)
|
||||
--]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(cur, max, oldMax ~= max, powerType, chargedIndex)
|
||||
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 = PlayerVehicleHasComboPoints()
|
||||
unit = 'vehicle'
|
||||
elseif(ClassPowerID) then
|
||||
if(not RequireSpec or RequireSpec == GetSpecialization()) then
|
||||
-- use 'player' instead of unit because 'SPELLS_CHANGED' is a unitless event
|
||||
if(not RequirePower or RequirePower == UnitPowerType('player')) then
|
||||
if(not RequireSpell or IsPlayerSpell(RequireSpell)) then
|
||||
self:UnregisterEvent('SPELLS_CHANGED', Visibility)
|
||||
shouldEnable = true
|
||||
unit = 'player'
|
||||
else
|
||||
self:RegisterEvent('SPELLS_CHANGED', Visibility, true)
|
||||
end
|
||||
end
|
||||
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_POWER_FREQUENT', Path)
|
||||
self:RegisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
if(PlayerClass == 'ROGUE') then
|
||||
self:RegisterEvent('UNIT_POWER_POINT_CHARGE', Path)
|
||||
end
|
||||
|
||||
self.ClassPower.__isEnabled = true
|
||||
|
||||
if(UnitHasVehicleUI('player')) then
|
||||
Path(self, 'ClassPowerEnable', 'vehicle', 'COMBO_POINTS')
|
||||
else
|
||||
Path(self, 'ClassPowerEnable', 'player', ClassPowerType)
|
||||
end
|
||||
end
|
||||
|
||||
function ClassPowerDisable(self)
|
||||
self:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_POINT_CHARGE', Path)
|
||||
|
||||
local element = self.ClassPower
|
||||
for i = 1, #element do
|
||||
element[i]:Hide()
|
||||
end
|
||||
|
||||
element.__isEnabled = false
|
||||
Path(self, 'ClassPowerDisable', 'player', ClassPowerType)
|
||||
end
|
||||
|
||||
if(PlayerClass == 'MONK') then
|
||||
ClassPowerID = SPELL_POWER_CHI
|
||||
ClassPowerType = 'CHI'
|
||||
RequireSpec = SPEC_MONK_WINDWALKER
|
||||
elseif(PlayerClass == 'PALADIN') then
|
||||
ClassPowerID = SPELL_POWER_HOLY_POWER
|
||||
ClassPowerType = 'HOLY_POWER'
|
||||
elseif(PlayerClass == 'WARLOCK') then
|
||||
ClassPowerID = SPELL_POWER_SOUL_SHARDS
|
||||
ClassPowerType = 'SOUL_SHARDS'
|
||||
elseif(PlayerClass == 'ROGUE' or PlayerClass == 'DRUID') then
|
||||
ClassPowerID = SPELL_POWER_COMBO_POINTS
|
||||
ClassPowerType = 'COMBO_POINTS'
|
||||
|
||||
if(PlayerClass == 'DRUID') then
|
||||
RequirePower = SPELL_POWER_ENERGY
|
||||
RequireSpell = 5221 -- Shred
|
||||
end
|
||||
elseif(PlayerClass == 'MAGE') then
|
||||
ClassPowerID = SPELL_POWER_ARCANE_CHARGES
|
||||
ClassPowerType = 'ARCANE_CHARGES'
|
||||
RequireSpec = SPEC_MAGE_ARCANE
|
||||
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(RequireSpec or RequireSpell) then
|
||||
self:RegisterEvent('PLAYER_TALENT_UPDATE', VisibilityPath, true)
|
||||
end
|
||||
|
||||
if(RequirePower) then
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
end
|
||||
|
||||
element.ClassPowerEnable = ClassPowerEnable
|
||||
element.ClassPowerDisable = ClassPowerDisable
|
||||
|
||||
for i = 1, #element do
|
||||
local bar = element[i]
|
||||
if(bar:IsObjectType('StatusBar')) then
|
||||
if(not (bar:GetStatusBarTexture() or bar:GetStatusBarAtlas())) 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('PLAYER_TALENT_UPDATE', VisibilityPath)
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
self:UnregisterEvent('SPELLS_CHANGED', Visibility)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('ClassPower', VisibilityPath, Enable, Disable)
|
||||
Reference in New Issue
Block a user