304 lines
10 KiB
Lua
304 lines
10 KiB
Lua
--[[
|
|
# Element: Alternative Power Bar
|
|
|
|
Handles the visibility and updating of a status bar that displays encounter- or quest-related power information, such as
|
|
the number of hour glass charges during the Murozond encounter in the dungeon End Time.
|
|
|
|
## Widget
|
|
|
|
AlternativePower - A `StatusBar` used to represent the unit's alternative power.
|
|
|
|
## Notes
|
|
|
|
If mouse interactivity is enabled for the widget, `OnEnter` and/or `OnLeave` handlers will be set to display a tooltip.
|
|
A default texture will be applied if the widget is a StatusBar and doesn't have a texture set.
|
|
|
|
## Options
|
|
|
|
.smoothGradient - 9 color values to be used with the .colorSmooth option (table)
|
|
.considerSelectionInCombatHostile - Indicates whether selection should be considered hostile while the unit is in
|
|
combat with the player (boolean)
|
|
|
|
The following options are listed by priority. The first check that returns true decides the color of the bar.
|
|
|
|
.colorThreat - Use `self.colors.threat[threat]` to color the bar based on the unit's threat status. `threat` is
|
|
defined by the first return of [UnitThreatSituation](https://wow.gamepedia.com/API_UnitThreatSituation) (boolean)
|
|
.colorPower - Use `self.colors.power[token]` to color the bar based on the unit's alternative power type
|
|
(boolean)
|
|
.colorClass - Use `self.colors.class[class]` to color the bar based on unit class. `class` is defined by the
|
|
second return of [UnitClass](http://wowprogramming.com/docs/api/UnitClass.html) (boolean)
|
|
.colorClassNPC - Use `self.colors.class[class]` to color the bar if the unit is a NPC (boolean)
|
|
.colorSelection - Use `self.colors.selection[selection]` to color the bar based on the unit's selection color.
|
|
`selection` is defined by the return value of Private.unitSelectionType, a wrapper function
|
|
for [UnitSelectionType](https://wow.gamepedia.com/API_UnitSelectionType) (boolean)
|
|
.colorReaction - Use `self.colors.reaction[reaction]` to color the bar based on the player's reaction towards the
|
|
unit. `reaction` is defined by the return value of
|
|
[UnitReaction](http://wowprogramming.com/docs/api/UnitReaction.html) (boolean)
|
|
.colorSmooth - Use `self.colors.smooth` to color the bar with a smooth gradient based on the unit's current
|
|
alternative power percentage (boolean)
|
|
|
|
## Examples
|
|
|
|
-- Position and size
|
|
local AlternativePower = CreateFrame('StatusBar', nil, self)
|
|
AlternativePower:SetHeight(20)
|
|
AlternativePower:SetPoint('BOTTOM')
|
|
AlternativePower:SetPoint('LEFT')
|
|
AlternativePower:SetPoint('RIGHT')
|
|
|
|
-- Register with oUF
|
|
self.AlternativePower = AlternativePower
|
|
--]]
|
|
|
|
local _, ns = ...
|
|
local oUF = ns.oUF
|
|
local Private = oUF.Private
|
|
|
|
local unitSelectionType = Private.unitSelectionType
|
|
|
|
-- sourced from FrameXML/UnitPowerBarAlt.lua
|
|
local ALTERNATE_POWER_INDEX = Enum.PowerType.Alternate or 10
|
|
local ALTERNATE_POWER_NAME = 'ALTERNATE'
|
|
local GameTooltip = GameTooltip
|
|
|
|
local function updateTooltip(self)
|
|
if GameTooltip:IsForbidden() then return end
|
|
|
|
local name, tooltip = GetUnitPowerBarStringsByID(self.__barID)
|
|
GameTooltip:SetText(name or '', 1, 1, 1)
|
|
GameTooltip:AddLine(tooltip or '', nil, nil, nil, true)
|
|
GameTooltip:Show()
|
|
end
|
|
|
|
local function onEnter(self)
|
|
if GameTooltip:IsForbidden() or not self:IsVisible() then return end
|
|
|
|
GameTooltip:ClearAllPoints()
|
|
GameTooltip_SetDefaultAnchor(GameTooltip, self)
|
|
self:UpdateTooltip()
|
|
end
|
|
|
|
local function onLeave()
|
|
if GameTooltip:IsForbidden() then return end
|
|
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
local function UpdateColor(self, event, unit, powerType)
|
|
if(self.unit ~= unit or powerType ~= ALTERNATE_POWER_NAME) then return end
|
|
local element = self.AlternativePower
|
|
|
|
local r, g, b, t
|
|
if(element.colorThreat and not UnitPlayerControlled(unit) and UnitThreatSituation('player', unit)) then
|
|
t = self.colors.threat[UnitThreatSituation('player', unit)]
|
|
elseif(element.colorPower) then
|
|
t = self.colors.power[ALTERNATE_POWER_INDEX]
|
|
elseif(element.colorClass and UnitIsPlayer(unit))
|
|
or (element.colorClassNPC and not UnitIsPlayer(unit)) then
|
|
local _, class = UnitClass(unit)
|
|
t = self.colors.class[class]
|
|
elseif(element.colorSelection and unitSelectionType(unit, element.considerSelectionInCombatHostile)) then
|
|
t = self.colors.selection[unitSelectionType(unit, element.considerSelectionInCombatHostile)]
|
|
elseif(element.colorReaction and UnitReaction(unit, 'player')) then
|
|
t = self.colors.reaction[UnitReaction(unit, 'player')]
|
|
elseif(element.colorSmooth) then
|
|
local adjust = 0 - (element.min or 0)
|
|
r, g, b = self:ColorGradient((element.cur or 1) + adjust, (element.max or 1) + adjust, unpack(element.smoothGradient or self.colors.smooth))
|
|
end
|
|
|
|
if(t) then
|
|
r, g, b = t[1], t[2], t[3]
|
|
end
|
|
|
|
if(b) then
|
|
element:SetStatusBarColor(r, g, b)
|
|
|
|
local bg = element.bg
|
|
if(bg) then
|
|
local mu = bg.multiplier or 1
|
|
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
|
end
|
|
end
|
|
|
|
--[[ Callback: AlternativePower:PostUpdateColor(unit, r, g, b)
|
|
Called after the element color has been updated.
|
|
|
|
* self - the AlternativePower element
|
|
* unit - the unit for which the update has been triggered (string)
|
|
* 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(unit, r, g, b)
|
|
end
|
|
end
|
|
|
|
local function Update(self, event, unit, powerType)
|
|
if(self.unit ~= unit or powerType ~= ALTERNATE_POWER_NAME) then return end
|
|
local element = self.AlternativePower
|
|
|
|
--[[ Callback: AlternativePower:PreUpdate()
|
|
Called before the element has been updated.
|
|
|
|
* self - the AlternativePower element
|
|
--]]
|
|
if(element.PreUpdate) then
|
|
element:PreUpdate()
|
|
end
|
|
|
|
local min, max, cur = 0
|
|
local barInfo = element.__barInfo
|
|
if(barInfo) then
|
|
cur = UnitPower(unit, ALTERNATE_POWER_INDEX)
|
|
max = UnitPowerMax(unit, ALTERNATE_POWER_INDEX)
|
|
|
|
if barInfo.minPower then
|
|
min = barInfo.minPower
|
|
end
|
|
|
|
element:SetMinMaxValues(min, max)
|
|
element:SetValue(cur)
|
|
end
|
|
|
|
element.cur = cur
|
|
element.min = min
|
|
element.max = max
|
|
|
|
--[[ Callback: AlternativePower:PostUpdate(unit, cur, min, max)
|
|
Called after the element has been updated.
|
|
|
|
* self - the AlternativePower element
|
|
* unit - the unit for which the update has been triggered (string)
|
|
* cur - the current value of the unit's alternative power (number?)
|
|
* min - the minimum value of the unit's alternative power (number?)
|
|
* max - the maximum value of the unit's alternative power (number?)
|
|
--]]
|
|
if(element.PostUpdate) then
|
|
return element:PostUpdate(unit, cur, min, max)
|
|
end
|
|
end
|
|
|
|
local function Path(self, ...)
|
|
--[[ Override: AlternativePower.Override(self, event, unit, ...)
|
|
Used to completely override the element's update process.
|
|
|
|
* self - the parent object
|
|
* event - the event triggering the update (string)
|
|
* unit - the unit accompanying the event (string)
|
|
* ... - the arguments accompanying the event
|
|
--]]
|
|
(self.AlternativePower.Override or Update) (self, ...);
|
|
|
|
--[[ Override: AlternativePower.UpdateColor(self, event, unit, ...)
|
|
Used to completely override the internal function for updating the widgets' colors.
|
|
|
|
* self - the parent object
|
|
* event - the event triggering the update (string)
|
|
* unit - the unit accompanying the event (string)
|
|
* ... - the arguments accompanying the event
|
|
--]]
|
|
(self.AlternativePower.UpdateColor or UpdateColor) (self, ...)
|
|
end
|
|
|
|
local function Visibility(self, event, unit)
|
|
if(unit ~= self.unit) then return end
|
|
local element = self.AlternativePower
|
|
|
|
local barID = UnitPowerBarID(unit)
|
|
local barInfo = GetUnitPowerBarInfoByID(barID)
|
|
element.__barID = barID
|
|
element.__barInfo = barInfo
|
|
if(barInfo and (barInfo.showOnRaid and (UnitInParty(unit) or UnitInRaid(unit))
|
|
or not barInfo.hideFromOthers
|
|
or UnitIsUnit(unit, 'player')))
|
|
then
|
|
self:RegisterEvent('UNIT_POWER_UPDATE', Path)
|
|
self:RegisterEvent('UNIT_MAXPOWER', Path)
|
|
|
|
element:Show()
|
|
Path(self, event, unit, ALTERNATE_POWER_NAME)
|
|
else
|
|
self:UnregisterEvent('UNIT_POWER_UPDATE', Path)
|
|
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
|
|
|
element:Hide()
|
|
Path(self, event, unit, ALTERNATE_POWER_NAME)
|
|
end
|
|
end
|
|
|
|
local function VisibilityPath(self, ...)
|
|
--[[ Override: AlternativePower.OverrideVisibility(self, event, unit)
|
|
Used to completely override the element's visibility update process.
|
|
|
|
* self - the parent object
|
|
* event - the event triggering the update (string)
|
|
* unit - the unit accompanying the event (string)
|
|
--]]
|
|
return (self.AlternativePower.OverrideVisibility or Visibility) (self, ...)
|
|
end
|
|
|
|
local function ForceUpdate(element)
|
|
return VisibilityPath(element.__owner, 'ForceUpdate', element.__owner.unit)
|
|
end
|
|
|
|
local function Enable(self, unit)
|
|
local element = self.AlternativePower
|
|
if(element) then
|
|
element.__owner = self
|
|
element.ForceUpdate = ForceUpdate
|
|
|
|
self:RegisterEvent('UNIT_POWER_BAR_SHOW', VisibilityPath)
|
|
self:RegisterEvent('UNIT_POWER_BAR_HIDE', VisibilityPath)
|
|
|
|
if(element:IsObjectType('StatusBar') and not (element:GetStatusBarTexture() or element:GetStatusBarAtlas())) then
|
|
element:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
|
end
|
|
|
|
if(element:IsMouseEnabled()) then
|
|
if(not element:GetScript('OnEnter')) then
|
|
element:SetScript('OnEnter', onEnter)
|
|
end
|
|
|
|
if(not element:GetScript('OnLeave')) then
|
|
element:SetScript('OnLeave', onLeave)
|
|
end
|
|
|
|
--[[ Override: AlternativePower:UpdateTooltip()
|
|
Called when the mouse is over the widget. Used to populate its tooltip.
|
|
|
|
* self - the AlternativePower element
|
|
--]]
|
|
if(not element.UpdateTooltip) then
|
|
element.UpdateTooltip = updateTooltip
|
|
end
|
|
end
|
|
|
|
if(unit == 'player') then
|
|
PlayerPowerBarAlt:UnregisterEvent('UNIT_POWER_BAR_SHOW')
|
|
PlayerPowerBarAlt:UnregisterEvent('UNIT_POWER_BAR_HIDE')
|
|
PlayerPowerBarAlt:UnregisterEvent('PLAYER_ENTERING_WORLD')
|
|
end
|
|
|
|
return true
|
|
end
|
|
end
|
|
|
|
local function Disable(self, unit)
|
|
local element = self.AlternativePower
|
|
if(element) then
|
|
element:Hide()
|
|
|
|
self:UnregisterEvent('UNIT_POWER_BAR_SHOW', VisibilityPath)
|
|
self:UnregisterEvent('UNIT_POWER_BAR_HIDE', VisibilityPath)
|
|
|
|
if(unit == 'player') then
|
|
PlayerPowerBarAlt:RegisterEvent('UNIT_POWER_BAR_SHOW')
|
|
PlayerPowerBarAlt:RegisterEvent('UNIT_POWER_BAR_HIDE')
|
|
PlayerPowerBarAlt:RegisterEvent('PLAYER_ENTERING_WORLD')
|
|
end
|
|
end
|
|
end
|
|
|
|
oUF:AddElement('AlternativePower', VisibilityPath, Enable, Disable)
|