2020-11-13 14:27:50 -05:00

246 lines
6.2 KiB
Lua

--[[
# Element: Runes
Handles the visibility and updating of Death Knight's runes.
## Widget
Runes - An `table` holding `StatusBar`s.
## Sub-Widgets
.bg - A `Texture` used as a background. It will inherit the color of the main StatusBar.
## Notes
A default texture will be applied if the sub-widgets are StatusBars and don't have a texture set.
## Options
.colorSpec - Use `self.colors.runes[specID]` to color the bar based on player's spec. `specID` is defined by the return
value of [GetSpecialization](http://wowprogramming.com/docs/api/GetSpecialization.html) (boolean)
.sortOrder - Sorting order. Sorts by the remaining cooldown time, 'asc' - from the least cooldown time remaining (fully
charged) to the most (fully depleted), 'desc' - the opposite (string?)['asc', 'desc']
## Sub-Widgets Options
.multiplier - Used to tint the background based on the main widgets R, G and B values. Defaults to 1 (number)[0-1]
## Examples
local Runes = {}
for index = 1, 6 do
-- Position and size of the rune bar indicators
local Rune = CreateFrame('StatusBar', nil, self)
Rune:SetSize(120 / 6, 20)
Rune:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', index * 120 / 6, 0)
Runes[index] = Rune
end
-- Register with oUF
self.Runes = Runes
--]]
if(select(2, UnitClass('player')) ~= 'DEATHKNIGHT') then return end
local _, ns = ...
local oUF = ns.oUF
local runemap = {1, 2, 3, 4, 5, 6}
local hasSortOrder = false
local function onUpdate(self, elapsed)
local duration = self.duration + elapsed
self.duration = duration
self:SetValue(duration)
end
local function ascSort(runeAID, runeBID)
local runeAStart, _, runeARuneReady = GetRuneCooldown(runeAID)
local runeBStart, _, runeBRuneReady = GetRuneCooldown(runeBID)
if(runeARuneReady ~= runeBRuneReady) then
return runeARuneReady
elseif(runeAStart ~= runeBStart) then
return runeAStart < runeBStart
else
return runeAID < runeBID
end
end
local function descSort(runeAID, runeBID)
local runeAStart, _, runeARuneReady = GetRuneCooldown(runeAID)
local runeBStart, _, runeBRuneReady = GetRuneCooldown(runeBID)
if(runeARuneReady ~= runeBRuneReady) then
return runeBRuneReady
elseif(runeAStart ~= runeBStart) then
return runeAStart > runeBStart
else
return runeAID > runeBID
end
end
local function UpdateColor(self, event)
local element = self.Runes
local spec = GetSpecialization() or 0
local color
if(spec > 0 and spec < 4 and element.colorSpec) then
color = self.colors.runes[spec]
else
color = self.colors.power.RUNES
end
local r, g, b = color[1], color[2], color[3]
for index = 1, #element do
element[index]:SetStatusBarColor(r, g, b)
local bg = element[index].bg
if(bg) then
local mu = bg.multiplier or 1
bg:SetVertexColor(r * mu, g * mu, b * mu)
end
end
--[[ Callback: Runes:PostUpdateColor(r, g, b)
Called after the element color has been updated.
* self - the Runes 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 ColorPath(self, ...)
--[[ Override: Runes.UpdateColor(self, event, ...)
Used to completely override the internal function for updating the widgets' colors.
* self - the parent object
* event - the event triggering the update (string)
* ... - the arguments accompanying the event
--]]
(self.Runes.UpdateColor or UpdateColor) (self, ...)
end
local function Update(self, event)
local element = self.Runes
if(element.sortOrder == 'asc') then
table.sort(runemap, ascSort)
hasSortOrder = true
elseif(element.sortOrder == 'desc') then
table.sort(runemap, descSort)
hasSortOrder = true
elseif(hasSortOrder) then
table.sort(runemap)
hasSortOrder = false
end
local rune, start, duration, runeReady
for index, runeID in next, runemap do
rune = element[index]
if(not rune) then break end
if(UnitHasVehicleUI('player')) then
rune:Hide()
else
start, duration, runeReady = GetRuneCooldown(runeID)
if(runeReady) then
rune:SetMinMaxValues(0, 1)
rune:SetValue(1)
rune:SetScript('OnUpdate', nil)
elseif(start) then
rune.duration = GetTime() - start
rune:SetMinMaxValues(0, duration)
rune:SetValue(0)
rune:SetScript('OnUpdate', onUpdate)
end
rune:Show()
end
end
--[[ Callback: Runes:PostUpdate(runemap)
Called after the element has been updated.
* self - the Runes element
* runemap - the ordered list of runes' indices (table)
--]]
if(element.PostUpdate) then
return element:PostUpdate(runemap)
end
end
local function Path(self, ...)
--[[ Override: Runes.Override(self, event, ...)
Used to completely override the internal update function.
* self - the parent object
* event - the event triggering the update (string)
* ... - the arguments accompanying the event
--]]
(self.Runes.Override or Update) (self, ...)
end
local function AllPath(...)
Path(...)
ColorPath(...)
end
local function ForceUpdate(element)
Path(element.__owner, 'ForceUpdate')
ColorPath(element.__owner, 'ForceUpdate')
end
local function Enable(self, unit)
local element = self.Runes
if(element and UnitIsUnit(unit, 'player')) then
element.__owner = self
element.ForceUpdate = ForceUpdate
for i = 1, #element do
local rune = element[i]
if(rune:IsObjectType('StatusBar') and not (rune:GetStatusBarTexture() or rune:GetStatusBarAtlas())) then
rune:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
end
end
-- ElvUI block
if element.IsObjectType and element:IsObjectType("Frame") then
element:Show()
end
-- end block
self:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED', ColorPath)
self:RegisterEvent('RUNE_POWER_UPDATE', Path, true)
return true
end
end
local function Disable(self)
local element = self.Runes
if(element) then
for i = 1, #element do
element[i]:Hide()
end
-- ElvUI block
if element.IsObjectType and element:IsObjectType("Frame") then
element:Hide()
end
-- end block
self:UnregisterEvent('PLAYER_SPECIALIZATION_CHANGED', ColorPath)
self:UnregisterEvent('RUNE_POWER_UPDATE', Path)
end
end
oUF:AddElement('Runes', AllPath, Enable, Disable)