commit from backup
This commit is contained in:
22
Libraries/oUF/LICENSE
Normal file
22
Libraries/oUF/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2006-2014 Trond A Ekseth <troeks@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
102
Libraries/oUF/blizzard.lua
Normal file
102
Libraries/oUF/blizzard.lua
Normal file
@@ -0,0 +1,102 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local hiddenParent = CreateFrame("Frame")
|
||||
hiddenParent:Hide()
|
||||
|
||||
local HandleFrame = function(baseName)
|
||||
local frame
|
||||
if(type(baseName) == 'string') then
|
||||
frame = _G[baseName]
|
||||
else
|
||||
frame = baseName
|
||||
end
|
||||
|
||||
if(frame) then
|
||||
frame:UnregisterAllEvents()
|
||||
frame:Hide()
|
||||
|
||||
-- Keep frame hidden without causing taint
|
||||
frame:SetParent(hiddenParent)
|
||||
|
||||
local health = frame.healthbar
|
||||
if(health) then
|
||||
health:UnregisterAllEvents()
|
||||
end
|
||||
|
||||
local power = frame.manabar
|
||||
if(power) then
|
||||
power:UnregisterAllEvents()
|
||||
end
|
||||
|
||||
local spell = frame.spellbar
|
||||
if(spell) then
|
||||
spell:UnregisterAllEvents()
|
||||
end
|
||||
|
||||
local altpowerbar = frame.powerBarAlt
|
||||
if(altpowerbar) then
|
||||
altpowerbar:UnregisterAllEvents()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function oUF:DisableBlizzard(unit)
|
||||
if(not unit) then return end
|
||||
|
||||
if(unit == 'player') then
|
||||
HandleFrame(PlayerFrame)
|
||||
|
||||
-- For the damn vehicle support:
|
||||
PlayerFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
|
||||
PlayerFrame:RegisterEvent('UNIT_ENTERING_VEHICLE')
|
||||
PlayerFrame:RegisterEvent('UNIT_ENTERED_VEHICLE')
|
||||
PlayerFrame:RegisterEvent('UNIT_EXITING_VEHICLE')
|
||||
PlayerFrame:RegisterEvent('UNIT_EXITED_VEHICLE')
|
||||
|
||||
-- User placed frames don't animate
|
||||
PlayerFrame:SetUserPlaced(true)
|
||||
PlayerFrame:SetDontSavePosition(true)
|
||||
elseif(unit == 'pet') then
|
||||
HandleFrame(PetFrame)
|
||||
elseif(unit == 'target') then
|
||||
HandleFrame(TargetFrame)
|
||||
HandleFrame(ComboFrame)
|
||||
elseif(unit == 'focus') then
|
||||
HandleFrame(FocusFrame)
|
||||
HandleFrame(TargetofFocusFrame)
|
||||
elseif(unit == 'targettarget') then
|
||||
HandleFrame(TargetFrameToT)
|
||||
elseif(unit:match'(boss)%d?$' == 'boss') then
|
||||
local id = unit:match'boss(%d)'
|
||||
if(id) then
|
||||
HandleFrame('Boss' .. id .. 'TargetFrame')
|
||||
else
|
||||
for i=1, 5 do
|
||||
HandleFrame(('Boss%dTargetFrame'):format(i))
|
||||
end
|
||||
end
|
||||
elseif(unit:match'(party)%d?$' == 'party') then
|
||||
local id = unit:match'party(%d)'
|
||||
if(id) then
|
||||
HandleFrame('PartyMemberFrame' .. id)
|
||||
else
|
||||
for i=1, 4 do
|
||||
HandleFrame(('PartyMemberFrame%d'):format(i))
|
||||
end
|
||||
end
|
||||
elseif(unit:match'(arena)%d?$' == 'arena') then
|
||||
local id = unit:match'arena(%d)'
|
||||
if(id) then
|
||||
HandleFrame('ArenaEnemyFrame' .. id)
|
||||
else
|
||||
for i=1, 5 do
|
||||
HandleFrame(('ArenaEnemyFrame%d'):format(i))
|
||||
end
|
||||
end
|
||||
|
||||
-- Blizzard_ArenaUI should not be loaded
|
||||
Arena_LoadUI = function() end
|
||||
SetCVar('showArenaEnemyFrames', '0', 'SHOW_ARENA_ENEMY_FRAMES_TEXT')
|
||||
end
|
||||
end
|
||||
168
Libraries/oUF/colors.lua
Normal file
168
Libraries/oUF/colors.lua
Normal file
@@ -0,0 +1,168 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local frame_metatable = Private.frame_metatable
|
||||
|
||||
local colors = {
|
||||
smooth = {
|
||||
1, 0, 0,
|
||||
1, 1, 0,
|
||||
0, 1, 0
|
||||
},
|
||||
disconnected = {.6, .6, .6},
|
||||
tapped = {.6,.6,.6},
|
||||
class = {},
|
||||
reaction = {},
|
||||
}
|
||||
|
||||
-- We do this because people edit the vars directly, and changing the default
|
||||
-- globals makes SPICE FLOW!
|
||||
local customClassColors = function()
|
||||
if(CUSTOM_CLASS_COLORS) then
|
||||
local updateColors = function()
|
||||
for eclass, color in next, CUSTOM_CLASS_COLORS do
|
||||
colors.class[eclass] = {color.r, color.g, color.b}
|
||||
end
|
||||
|
||||
for _, obj in next, oUF.objects do
|
||||
obj:UpdateAllElements("CUSTOM_CLASS_COLORS")
|
||||
end
|
||||
end
|
||||
|
||||
updateColors()
|
||||
CUSTOM_CLASS_COLORS:RegisterCallback(updateColors)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
if not customClassColors() then
|
||||
for eclass, color in next, RAID_CLASS_COLORS do
|
||||
colors.class[eclass] = {color.r, color.g, color.b}
|
||||
end
|
||||
|
||||
local f = CreateFrame("Frame")
|
||||
f:RegisterEvent("ADDON_LOADED")
|
||||
f:SetScript("OnEvent", function()
|
||||
if customClassColors() then
|
||||
f:UnregisterEvent("ADDON_LOADED")
|
||||
f:SetScript("OnEvent", nil)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
for eclass, color in next, FACTION_BAR_COLORS do
|
||||
colors.reaction[eclass] = {color.r, color.g, color.b}
|
||||
end
|
||||
|
||||
local function ColorsAndPercent(a, b, ...)
|
||||
if a <= 0 or b == 0 then
|
||||
return nil, ...
|
||||
elseif a >= b then
|
||||
return nil, select(select('#', ...) - 2, ...)
|
||||
end
|
||||
|
||||
local num = select('#', ...) / 3
|
||||
local segment, relperc = math.modf((a/b)*(num-1))
|
||||
return relperc, select((segment*3)+1, ...)
|
||||
end
|
||||
|
||||
-- http://www.wowwiki.com/ColorGradient
|
||||
local RGBColorGradient = function(...)
|
||||
local relperc, r1, g1, b1, r2, g2, b2 = ColorsAndPercent(...)
|
||||
if relperc then
|
||||
return r1 + (r2-r1)*relperc, g1 + (g2-g1)*relperc, b1 + (b2-b1)*relperc
|
||||
else
|
||||
return r1, g1, b1
|
||||
end
|
||||
end
|
||||
|
||||
-- HCY functions are based on http://www.chilliant.com/rgb2hsv.html
|
||||
local function GetY(r, g, b)
|
||||
return 0.299 * r + 0.587 * g + 0.114 * b
|
||||
end
|
||||
|
||||
local function RGBToHCY(r, g, b)
|
||||
local min, max = min(r, g, b), max(r, g, b)
|
||||
local chroma = max - min
|
||||
local hue
|
||||
if chroma > 0 then
|
||||
if r == max then
|
||||
hue = ((g - b) / chroma) % 6
|
||||
elseif g == max then
|
||||
hue = (b - r) / chroma + 2
|
||||
elseif b == max then
|
||||
hue = (r - g) / chroma + 4
|
||||
end
|
||||
hue = hue / 6
|
||||
end
|
||||
return hue, chroma, GetY(r, g, b)
|
||||
end
|
||||
|
||||
local abs = math.abs
|
||||
local function HCYtoRGB(hue, chroma, luma)
|
||||
local r, g, b = 0, 0, 0
|
||||
if hue and luma > 0 then
|
||||
local h2 = hue * 6
|
||||
local x = chroma * (1 - abs(h2 % 2 - 1))
|
||||
if h2 < 1 then
|
||||
r, g, b = chroma, x, 0
|
||||
elseif h2 < 2 then
|
||||
r, g, b = x, chroma, 0
|
||||
elseif h2 < 3 then
|
||||
r, g, b = 0, chroma, x
|
||||
elseif h2 < 4 then
|
||||
r, g, b = 0, x, chroma
|
||||
elseif h2 < 5 then
|
||||
r, g, b = x, 0, chroma
|
||||
else
|
||||
r, g, b = chroma, 0, x
|
||||
end
|
||||
local y = GetY(r, g, b)
|
||||
if luma < y then
|
||||
chroma = chroma * (luma / y)
|
||||
elseif y < 1 then
|
||||
chroma = chroma * (1 - luma) / (1 - y)
|
||||
end
|
||||
r = (r - y) * chroma + luma
|
||||
g = (g - y) * chroma + luma
|
||||
b = (b - y) * chroma + luma
|
||||
end
|
||||
return r, g, b
|
||||
end
|
||||
|
||||
local HCYColorGradient = function(...)
|
||||
local relperc, r1, g1, b1, r2, g2, b2 = ColorsAndPercent(...)
|
||||
if not relperc then return r1, g1, b1 end
|
||||
local h1, c1, y1 = RGBToHCY(r1, g1, b1)
|
||||
local h2, c2, y2 = RGBToHCY(r2, g2, b2)
|
||||
local c = c1 + (c2-c1) * relperc
|
||||
local y = y1 + (y2-y1) * relperc
|
||||
if h1 and h2 then
|
||||
local dh = h2 - h1
|
||||
if dh < -0.5 then
|
||||
dh = dh + 1
|
||||
elseif dh > 0.5 then
|
||||
dh = dh - 1
|
||||
end
|
||||
return HCYtoRGB((h1 + dh * relperc) % 1, c, y)
|
||||
else
|
||||
return HCYtoRGB(h1 or h2, c, y)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local ColorGradient = function(...)
|
||||
return (oUF.useHCYColorGradient and HCYColorGradient or RGBColorGradient)(...)
|
||||
end
|
||||
|
||||
Private.colors = colors
|
||||
|
||||
oUF.colors = colors
|
||||
oUF.ColorGradient = ColorGradient
|
||||
oUF.RGBColorGradient = RGBColorGradient
|
||||
oUF.HCYColorGradient = HCYColorGradient
|
||||
oUF.useHCYColorGradient = false
|
||||
|
||||
frame_metatable.__index.colors = colors
|
||||
frame_metatable.__index.ColorGradient = ColorGradient
|
||||
194
Libraries/oUF/elements/additionalpower.lua
Normal file
194
Libraries/oUF/elements/additionalpower.lua
Normal file
@@ -0,0 +1,194 @@
|
||||
--[[ Element: Additional Power Bar
|
||||
Handles updating and visibility of a status bar displaying the player's
|
||||
alternate/additional power, such as Mana for Balance druids.
|
||||
|
||||
Widget
|
||||
|
||||
AdditionalPower - A StatusBar to represent current caster mana.
|
||||
|
||||
Sub-Widgets
|
||||
|
||||
.bg - A Texture which functions as a background. It will inherit the color of
|
||||
the main StatusBar.
|
||||
|
||||
Notes
|
||||
|
||||
The default StatusBar texture will be applied if the UI widget doesn't have a
|
||||
status bar texture or color defined.
|
||||
|
||||
Options
|
||||
|
||||
.colorClass - Use `self.colors.class[class]` to color the bar.
|
||||
.colorSmooth - Use `self.colors.smooth` to color the bar with a smooth
|
||||
gradient based on the players current mana percentage.
|
||||
.colorPower - Use `self.colors.power[token]` to color the bar. This will
|
||||
always use MANA as token.
|
||||
|
||||
Sub-Widget Options
|
||||
|
||||
.multiplier - Defines a multiplier, which is used to tint the background based
|
||||
on the main widgets R, G and B values. Defaults to 1 if not
|
||||
present.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local AdditionalPower = CreateFrame("StatusBar", nil, self)
|
||||
AdditionalPower:SetSize(20, 20)
|
||||
AdditionalPower:SetPoint('TOP')
|
||||
AdditionalPower:SetPoint('LEFT')
|
||||
AdditionalPower:SetPoint('RIGHT')
|
||||
|
||||
-- Add a background
|
||||
local Background = AdditionalPower:CreateTexture(nil, 'BACKGROUND')
|
||||
Background:SetAllPoints(AdditionalPower)
|
||||
Background:SetTexture(1, 1, 1, .5)
|
||||
|
||||
-- Register it with oUF
|
||||
self.AdditionalPower = AdditionalPower
|
||||
self.AdditionalPower.bg = Background
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
|
||||
]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local playerClass = select(2, UnitClass('player'))
|
||||
|
||||
local ADDITIONAL_POWER_BAR_NAME = ADDITIONAL_POWER_BAR_NAME
|
||||
local ADDITIONAL_POWER_BAR_INDEX = ADDITIONAL_POWER_BAR_INDEX
|
||||
|
||||
local function Update(self, event, unit, powertype)
|
||||
if(unit ~= 'player' or (powertype and powertype ~= ADDITIONAL_POWER_BAR_NAME)) then return end
|
||||
|
||||
local element = self.AdditionalPower
|
||||
if(element.PreUpdate) then element:PreUpdate(unit) end
|
||||
|
||||
local cur = UnitPower('player', ADDITIONAL_POWER_BAR_INDEX)
|
||||
local max = UnitPowerMax('player', ADDITIONAL_POWER_BAR_INDEX)
|
||||
element:SetMinMaxValues(0, max)
|
||||
element:SetValue(cur)
|
||||
|
||||
local r, g, b, t
|
||||
if(element.colorClass) then
|
||||
t = self.colors.class[playerClass]
|
||||
elseif(element.colorSmooth) then
|
||||
r, g, b = self.ColorGradient(cur, max, unpack(element.smoothGradient or self.colors.smooth))
|
||||
elseif(element.colorPower) then
|
||||
t = self.colors.power[ADDITIONAL_POWER_BAR_NAME]
|
||||
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
|
||||
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(unit, cur, max, event)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
return (self.AdditionalPower.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ElementEnable(self)
|
||||
self:RegisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', Path)
|
||||
self:RegisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
self.AdditionalPower:Show()
|
||||
|
||||
if self.AdditionalPower.PostUpdateVisibility then
|
||||
self.AdditionalPower:PostUpdateVisibility(true, not self.AdditionalPower.isEnabled)
|
||||
end
|
||||
|
||||
self.AdditionalPower.isEnabled = true
|
||||
|
||||
Path(self, 'ElementEnable', 'player', ADDITIONAL_POWER_BAR_NAME)
|
||||
end
|
||||
|
||||
local function ElementDisable(self)
|
||||
self:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', Path)
|
||||
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
self.AdditionalPower:Hide()
|
||||
|
||||
if self.AdditionalPower.PostUpdateVisibility then
|
||||
self.AdditionalPower:PostUpdateVisibility(false, self.AdditionalPower.isEnabled)
|
||||
end
|
||||
|
||||
self.AdditionalPower.isEnabled = nil
|
||||
|
||||
Path(self, 'ElementDisable', 'player', ADDITIONAL_POWER_BAR_NAME)
|
||||
end
|
||||
|
||||
local function Visibility(self, event, unit)
|
||||
local shouldEnable
|
||||
|
||||
if(not UnitHasVehicleUI('player')) then
|
||||
if(UnitPowerMax(unit, ADDITIONAL_POWER_BAR_INDEX) ~= 0) then
|
||||
if(ALT_MANA_BAR_PAIR_DISPLAY_INFO[playerClass]) then
|
||||
local powerType = UnitPowerType(unit)
|
||||
shouldEnable = ALT_MANA_BAR_PAIR_DISPLAY_INFO[playerClass][powerType]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(shouldEnable) then
|
||||
ElementEnable(self)
|
||||
else
|
||||
ElementDisable(self)
|
||||
end
|
||||
end
|
||||
|
||||
local VisibilityPath = function(self, ...)
|
||||
return (self.AdditionalPower.OverrideVisibility or Visibility) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return VisibilityPath(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
local element = self.AdditionalPower
|
||||
if(element and unit == 'player') then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
|
||||
if(element:IsObjectType'StatusBar' and not element:GetStatusBarTexture()) then
|
||||
element:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]]
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local element = self.AdditionalPower
|
||||
if(element) then
|
||||
ElementDisable(self)
|
||||
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('AdditionalPower', VisibilityPath, Enable, Disable)
|
||||
203
Libraries/oUF/elements/altpowerbar.lua
Normal file
203
Libraries/oUF/elements/altpowerbar.lua
Normal file
@@ -0,0 +1,203 @@
|
||||
--[[ Element: Alternative Power Bar
|
||||
|
||||
Handles visibility and updating of the alternative power bar.
|
||||
|
||||
This bar is used to display encounter/quest related power information, such as
|
||||
the number of hour glass uses left on the end boss in End Time.
|
||||
|
||||
Widget
|
||||
|
||||
AltPowerBar - A StatusBar to represent alternative power.
|
||||
|
||||
Options
|
||||
|
||||
.colorTexture - Use the vertex color values returned by
|
||||
UnitAlternatePowerTextureInfo to color the bar.
|
||||
|
||||
Notes
|
||||
|
||||
OnEnter and OnLeave handlers to display a tooltip will be set on the widget if
|
||||
it is mouse enabled.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local AltPowerBar = CreateFrame('StatusBar', nil, self)
|
||||
AltPowerBar:SetHeight(20)
|
||||
AltPowerBar:SetPoint('BOTTOM')
|
||||
AltPowerBar:SetPoint('LEFT')
|
||||
AltPowerBar:SetPoint('RIGHT')
|
||||
|
||||
-- Register with oUF
|
||||
self.AltPowerBar = AltPowerBar
|
||||
|
||||
Callbacks
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local ALTERNATE_POWER_INDEX = ALTERNATE_POWER_INDEX
|
||||
|
||||
--[[ :UpdateTooltip()
|
||||
|
||||
The function called when the widget is hovered. Used to populate the tooltip.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The AltPowerBar element.
|
||||
]]
|
||||
local UpdateTooltip = function(self)
|
||||
GameTooltip:SetText(self.powerName, 1, 1, 1)
|
||||
GameTooltip:AddLine(self.powerTooltip, nil, nil, nil, 1)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
|
||||
local OnEnter = function(self)
|
||||
if(not self:IsVisible()) then return end
|
||||
|
||||
GameTooltip_SetDefaultAnchor(GameTooltip, self)
|
||||
self:UpdateTooltip()
|
||||
end
|
||||
|
||||
local OnLeave = function()
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
local UpdatePower = function(self, event, unit, powerType)
|
||||
if(self.unit ~= unit or powerType ~= 'ALTERNATE') or not unit then return end
|
||||
|
||||
local altpowerbar = self.AltPowerBar
|
||||
|
||||
--[[ :PreUpdate()
|
||||
|
||||
Called before the element has been updated.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The AltPowerBar element.
|
||||
]]
|
||||
if(altpowerbar.PreUpdate) then
|
||||
altpowerbar:PreUpdate()
|
||||
end
|
||||
|
||||
local _, r, g, b
|
||||
if(altpowerbar.colorTexture) then
|
||||
_, r, g, b = UnitAlternatePowerTextureInfo(unit, 2)
|
||||
end
|
||||
|
||||
local cur = UnitPower(unit, ALTERNATE_POWER_INDEX)
|
||||
local max = UnitPowerMax(unit, ALTERNATE_POWER_INDEX)
|
||||
|
||||
local barType, min, _, _, _, _, _, _, _, _, powerName, powerTooltip = UnitAlternatePowerInfo(unit)
|
||||
altpowerbar.barType = barType
|
||||
altpowerbar.powerName = powerName
|
||||
altpowerbar.powerTooltip = powerTooltip
|
||||
altpowerbar:SetMinMaxValues(min, max)
|
||||
altpowerbar:SetValue(math.min(math.max(cur, min), max))
|
||||
|
||||
if(b) then
|
||||
altpowerbar:SetStatusBarColor(r, g, b)
|
||||
end
|
||||
|
||||
--[[ :PostUpdate(min, cur, max)
|
||||
|
||||
Called after the element has been updated.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The AltPowerBar element.
|
||||
min - The minimum possible power value for the active type.
|
||||
cur - The current power value.
|
||||
max - The maximum possible power value for the active type.
|
||||
]]
|
||||
if(altpowerbar.PostUpdate) then
|
||||
return altpowerbar:PostUpdate(min, cur, max)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[ Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
local Path = function(self, ...)
|
||||
return (self.AltPowerBar.Override or UpdatePower)(self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit, 'ALTERNATE')
|
||||
end
|
||||
|
||||
local Toggler = function(self, event, unit)
|
||||
if(unit ~= self.unit) or not unit then return end
|
||||
local altpowerbar = self.AltPowerBar
|
||||
|
||||
local barType, _, _, _, _, hideFromOthers, showOnRaid = UnitAlternatePowerInfo(unit)
|
||||
if(barType and (showOnRaid and (UnitInParty(unit) or UnitInRaid(unit)) or not hideFromOthers or unit == 'player' or self.realUnit == 'player')) then
|
||||
self:RegisterEvent('UNIT_POWER', Path)
|
||||
self:RegisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
ForceUpdate(altpowerbar)
|
||||
altpowerbar:Show()
|
||||
else
|
||||
self:UnregisterEvent('UNIT_POWER', Path)
|
||||
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
altpowerbar:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
local altpowerbar = self.AltPowerBar
|
||||
if(altpowerbar) then
|
||||
altpowerbar.__owner = self
|
||||
altpowerbar.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_POWER_BAR_SHOW', Toggler)
|
||||
self:RegisterEvent('UNIT_POWER_BAR_HIDE', Toggler)
|
||||
|
||||
altpowerbar:Hide()
|
||||
|
||||
if(altpowerbar:IsMouseEnabled()) then
|
||||
if(not altpowerbar:GetScript('OnEnter')) then
|
||||
altpowerbar:SetScript('OnEnter', OnEnter)
|
||||
end
|
||||
|
||||
if(not altpowerbar:GetScript('OnLeave')) then
|
||||
altpowerbar:SetScript('OnLeave', OnLeave)
|
||||
end
|
||||
|
||||
if(not altpowerbar.UpdateTooltip) then
|
||||
altpowerbar.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 Disable = function(self, unit)
|
||||
local altpowerbar = self.AltPowerBar
|
||||
if(altpowerbar) then
|
||||
altpowerbar:Hide()
|
||||
self:UnregisterEvent('UNIT_POWER_BAR_SHOW', Toggler)
|
||||
self:UnregisterEvent('UNIT_POWER_BAR_HIDE', Toggler)
|
||||
|
||||
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('AltPowerBar', Toggler, Enable, Disable)
|
||||
112
Libraries/oUF/elements/assistant.lua
Normal file
112
Libraries/oUF/elements/assistant.lua
Normal file
@@ -0,0 +1,112 @@
|
||||
--[[ Element: Assistant Icon
|
||||
Toggles visibility of `self.Assistant` based on the units raid officer status.
|
||||
|
||||
Widget
|
||||
|
||||
Assistant - Any UI widget.
|
||||
|
||||
Notes
|
||||
|
||||
The default assistant icon will be applied if the UI widget is a texture and
|
||||
doesn't have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local Assistant = self:CreateTexture(nil, "OVERLAY")
|
||||
Assistant:SetSize(16, 16)
|
||||
Assistant:SetPoint('TOP', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.Assistant = Assistant
|
||||
|
||||
Hooks and Callbacks
|
||||
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event)
|
||||
if not self.unit then return; end
|
||||
local assistant = self.Assistant
|
||||
|
||||
--[[ :PreUpdate()
|
||||
|
||||
Called before the element has been updated.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The Assistant element.
|
||||
]]
|
||||
if(assistant.PreUpdate) then
|
||||
assistant:PreUpdate()
|
||||
end
|
||||
|
||||
local unit = self.unit
|
||||
local isAssistant = UnitInRaid(unit) and UnitIsGroupAssistant(unit) and not UnitIsGroupLeader(unit)
|
||||
if(isAssistant) then
|
||||
assistant:Show()
|
||||
else
|
||||
assistant:Hide()
|
||||
end
|
||||
|
||||
--[[ :PostUpdate(isAssistant)
|
||||
|
||||
Called after the element has been updated.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The Assistant element.
|
||||
isAssistant - A boolean holding whether the unit is a raid officer or not.
|
||||
]]
|
||||
if(assistant.PostUpdate) then
|
||||
return assistant:PostUpdate(isAssistant)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
--[[ :Override(self, event, ...)
|
||||
|
||||
Used to completely override the internal update function. Removing the
|
||||
table key entry will make the element fall-back to its internal function
|
||||
again.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The Assistant element.
|
||||
event - The UI event that fired.
|
||||
... - A vararg with the arguments that accompany the event.
|
||||
]]
|
||||
return (self.Assistant.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local assistant = self.Assistant
|
||||
if(assistant) then
|
||||
self:RegisterEvent("GROUP_ROSTER_UPDATE", Path, true)
|
||||
|
||||
if(assistant:IsObjectType"Texture" and not assistant:GetTexture()) then
|
||||
assistant:SetTexture[[Interface\GroupFrame\UI-Group-AssistantIcon]]
|
||||
end
|
||||
|
||||
assistant.__owner = self
|
||||
assistant.ForceUpdate = ForceUpdate
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local assistant = self.Assistant
|
||||
if(assistant) then
|
||||
self:UnregisterEvent("GROUP_ROSTER_UPDATE", Path)
|
||||
assistant:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Assistant', Path, Enable, Disable)
|
||||
525
Libraries/oUF/elements/aura.lua
Normal file
525
Libraries/oUF/elements/aura.lua
Normal file
@@ -0,0 +1,525 @@
|
||||
--[[ Element: Auras
|
||||
|
||||
Handles creation and updating of aura icons.
|
||||
|
||||
Widget
|
||||
|
||||
Auras - A Frame to hold icons representing both buffs and debuffs.
|
||||
Buffs - A Frame to hold icons representing buffs.
|
||||
Debuffs - A Frame to hold icons representing debuffs.
|
||||
|
||||
Options
|
||||
|
||||
.disableCooldown - Disables the cooldown spiral. Defaults to false.
|
||||
.size - Aura icon size. Defaults to 16.
|
||||
.onlyShowPlayer - Only show auras created by player/vehicle.
|
||||
.showStealableBuffs - Display the stealable texture on buffs that can be
|
||||
stolen.
|
||||
.spacing - Spacing between each icon. Defaults to 0.
|
||||
.['spacing-x'] - Horizontal spacing between each icon. Takes priority over
|
||||
`spacing`.
|
||||
.['spacing-y'] - Vertical spacing between each icon. Takes priority over
|
||||
`spacing`.
|
||||
.['growth-x'] - Horizontal growth direction. Defaults to RIGHT.
|
||||
.['growth-y'] - Vertical growth direction. Defaults to UP.
|
||||
.initialAnchor - Anchor point for the icons. Defaults to BOTTOMLEFT.
|
||||
.filter - Custom filter list for auras to display. Defaults to
|
||||
HELPFUL on buffs and HARMFUL on debuffs.
|
||||
|
||||
Options Auras
|
||||
|
||||
.numBuffs - The maximum number of buffs to display. Defaults to 32.
|
||||
.numDebuffs - The maximum number of debuffs to display. Defaults to 40.
|
||||
.gap - Controls the creation of an invisible icon between buffs and
|
||||
debuffs. Defaults to false.
|
||||
.buffFilter - Custom filter list for buffs to display. Takes priority over
|
||||
`filter`.
|
||||
.debuffFilter - Custom filter list for debuffs to display. Takes priority over
|
||||
`filter`.
|
||||
|
||||
Options Buffs
|
||||
|
||||
.num - Number of buffs to display. Defaults to 32.
|
||||
|
||||
Options Debuffs
|
||||
|
||||
.num - Number of debuffs to display. Defaults to 40.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local Buffs = CreateFrame("Frame", nil, self)
|
||||
Buffs:SetPoint("RIGHT", self, "LEFT")
|
||||
Buffs:SetSize(16 * 2, 16 * 16)
|
||||
|
||||
-- Register with oUF
|
||||
self.Buffs = Buffs
|
||||
|
||||
Hooks and Callbacks
|
||||
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local VISIBLE = 1
|
||||
local HIDDEN = 0
|
||||
|
||||
local UpdateTooltip = function(self)
|
||||
GameTooltip:SetUnitAura(self:GetParent().__owner.unit, self:GetID(), self.filter)
|
||||
end
|
||||
|
||||
local OnEnter = function(self)
|
||||
if(not self:IsVisible()) then return end
|
||||
|
||||
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")
|
||||
self:UpdateTooltip()
|
||||
end
|
||||
|
||||
local OnLeave = function()
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
local createAuraIcon = function(icons, index)
|
||||
local button = CreateFrame("Button", icons:GetDebugName().."Button"..index, icons)
|
||||
button:RegisterForClicks'RightButtonUp'
|
||||
|
||||
local cd = CreateFrame("Cooldown", "$parentCooldown", button, "CooldownFrameTemplate")
|
||||
cd:SetAllPoints(button)
|
||||
|
||||
local icon = button:CreateTexture(nil, "BORDER")
|
||||
icon:SetAllPoints(button)
|
||||
|
||||
local count = button:CreateFontString(nil, "OVERLAY")
|
||||
count:SetFontObject(NumberFontNormal)
|
||||
count:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -1, 0)
|
||||
|
||||
local overlay = button:CreateTexture(nil, "OVERLAY")
|
||||
overlay:SetTexture"Interface\\Buttons\\UI-Debuff-Overlays"
|
||||
overlay:SetAllPoints(button)
|
||||
overlay:SetTexCoord(.296875, .5703125, 0, .515625)
|
||||
button.overlay = overlay
|
||||
|
||||
local stealable = button:CreateTexture(nil, 'OVERLAY')
|
||||
stealable:SetTexture[[Interface\TargetingFrame\UI-TargetingFrame-Stealable]]
|
||||
stealable:SetPoint('TOPLEFT', -3, 3)
|
||||
stealable:SetPoint('BOTTOMRIGHT', 3, -3)
|
||||
stealable:SetBlendMode'ADD'
|
||||
button.stealable = stealable
|
||||
|
||||
button.UpdateTooltip = UpdateTooltip
|
||||
button:SetScript("OnEnter", OnEnter)
|
||||
button:SetScript("OnLeave", OnLeave)
|
||||
|
||||
|
||||
button.icon = icon
|
||||
button.count = count
|
||||
button.cd = cd
|
||||
|
||||
--[[ :PostCreateIcon(button)
|
||||
|
||||
Callback which is called after a new aura icon button has been created.
|
||||
|
||||
Arguments
|
||||
|
||||
button - The newly created aura icon button.
|
||||
]]
|
||||
if(icons.PostCreateIcon) then icons:PostCreateIcon(button) end
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
local customFilter = function(icons, unit, icon, name)
|
||||
if((icons.onlyShowPlayer and icon.isPlayer) or (not icons.onlyShowPlayer and name)) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local updateIcon = function(unit, icons, index, offset, filter, isDebuff, visible)
|
||||
local name, rank, texture, count, dispelType, duration, expiration, caster, isStealable,
|
||||
nameplateShowSelf, spellID, canApply, isBossDebuff, casterIsPlayer, nameplateShowAll,
|
||||
timeMod, effect1, effect2, effect3 = UnitAura(unit, index, filter)
|
||||
|
||||
if icons.forceShow then
|
||||
spellID = 47540
|
||||
name, rank, texture = GetSpellInfo(spellID)
|
||||
count, dispelType, duration, expiration, caster, isStealable, nameplateShowSelf, canApplyAura, isBossDebuff = 5, 'Magic', 0, 60, 'player', nil, nil, nil, nil
|
||||
end
|
||||
|
||||
if(name) then
|
||||
local n = visible + offset + 1
|
||||
local icon = icons[n]
|
||||
if(not icon) then
|
||||
--[[ :CreateIcon(index)
|
||||
|
||||
A function which creates the aura icon for a given index.
|
||||
|
||||
Arguments
|
||||
|
||||
index - The offset the icon should be created at.
|
||||
|
||||
Returns
|
||||
|
||||
A button used to represent aura icons.
|
||||
]]
|
||||
local prev = icons.createdIcons
|
||||
icon = (icons.CreateIcon or createAuraIcon) (icons, n)
|
||||
|
||||
-- XXX: Update the counters if the layout doesn't.
|
||||
if(prev == icons.createdIcons) then
|
||||
table.insert(icons, icon)
|
||||
icons.createdIcons = icons.createdIcons + 1
|
||||
end
|
||||
end
|
||||
|
||||
local isPlayer
|
||||
if(caster == 'player' or caster == 'vehicle') then
|
||||
isPlayer = true
|
||||
end
|
||||
|
||||
icon.owner = caster
|
||||
icon.filter = filter
|
||||
icon.isDebuff = isDebuff
|
||||
icon.isPlayer = isPlayer
|
||||
|
||||
|
||||
--[[ :CustomFilter(unit, icon, ...)
|
||||
|
||||
Defines a custom filter which controls if the aura icon should be shown
|
||||
or not.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The widget that holds the aura icon.
|
||||
unit - The unit that has the aura.
|
||||
icon - The button displaying the aura.
|
||||
... - The return values from
|
||||
[UnitAura](http://wowprogramming.com/docs/api/UnitAura).
|
||||
|
||||
Returns
|
||||
|
||||
A boolean value telling the aura element if it should be show the icon
|
||||
or not.
|
||||
]]
|
||||
local show = true
|
||||
if not icons.forceShow then
|
||||
show = (icons.CustomFilter or customFilter) (icons, unit, icon, name, rank, texture,
|
||||
count, dispelType, duration, expiration, caster, isStealable, nameplateShowSelf, spellID,
|
||||
canApply, isBossDebuff, casterIsPlayer, nameplateShowAll,timeMod, effect1, effect2, effect3)
|
||||
end
|
||||
|
||||
if(show) then
|
||||
-- We might want to consider delaying the creation of an actual cooldown
|
||||
-- object to this point, but I think that will just make things needlessly
|
||||
-- complicated.
|
||||
local cd = icon.cd
|
||||
if(cd and not icons.disableCooldown) then
|
||||
if(duration and duration > 0) then
|
||||
cd:SetCooldown(expiration - duration, duration)
|
||||
cd:Show()
|
||||
else
|
||||
cd:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
if((isDebuff and icons.showDebuffType) or (not isDebuff and icons.showBuffType) or icons.showType) then
|
||||
local color = DebuffTypeColor[dispelType] or DebuffTypeColor.none
|
||||
|
||||
icon.overlay:SetVertexColor(color.r, color.g, color.b)
|
||||
icon.overlay:Show()
|
||||
else
|
||||
icon.overlay:Hide()
|
||||
end
|
||||
|
||||
local stealable = not isDebuff and isStealable
|
||||
if(stealable and icons.showStealableBuffs and not UnitIsUnit('player', unit)) then
|
||||
icon.stealable:Show()
|
||||
else
|
||||
icon.stealable:Hide()
|
||||
end
|
||||
|
||||
icon.icon:SetTexture(texture)
|
||||
icon.count:SetText((count > 1 and count))
|
||||
|
||||
local size = icons.size or 16
|
||||
icon:SetSize(size, size)
|
||||
|
||||
icon:EnableMouse(true)
|
||||
icon:SetID(index)
|
||||
icon:Show()
|
||||
|
||||
--[[ :PostUpdateIcon(unit, icon, index, offest)
|
||||
|
||||
Callback which is called after the aura icon was updated.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The widget that holds the aura icon.
|
||||
unit - The unit that has the aura.
|
||||
icon - The button that was updated.
|
||||
index - The index of the aura.
|
||||
offset - The offset the button was created at.
|
||||
]]
|
||||
if(icons.PostUpdateIcon) then
|
||||
icons:PostUpdateIcon(unit, icon, index, n)
|
||||
end
|
||||
|
||||
return VISIBLE
|
||||
else
|
||||
return HIDDEN
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ :SetPosition(from, to)
|
||||
|
||||
Function used to (re-)anchor aura icons. This function is only called when
|
||||
new aura icons have been created or if :PreSetPosition is defined.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The widget that holds the aura icons.
|
||||
from - The aura icon before the new aura icon.
|
||||
to - The current number of created icons.
|
||||
]]
|
||||
local SetPosition = function(icons, from, to)
|
||||
local sizex = (icons.size or 16) + (icons['spacing-x'] or icons.spacing or 0)
|
||||
local sizey = (icons.size or 16) + (icons['spacing-y'] or icons.spacing or 0)
|
||||
local anchor = icons.initialAnchor or "BOTTOMLEFT"
|
||||
local growthx = (icons["growth-x"] == "LEFT" and -1) or 1
|
||||
local growthy = (icons["growth-y"] == "DOWN" and -1) or 1
|
||||
local cols = math.floor(icons:GetWidth() / sizex + .5)
|
||||
|
||||
for i = from, to do
|
||||
local button = icons[i]
|
||||
|
||||
-- Bail out if the to range is out of scope.
|
||||
if(not button) then break end
|
||||
local col = (i - 1) % cols
|
||||
local row = math.floor((i - 1) / cols)
|
||||
|
||||
button:ClearAllPoints()
|
||||
button:SetPoint(anchor, icons, anchor, col * sizex * growthx, row * sizey * growthy)
|
||||
end
|
||||
end
|
||||
|
||||
local filterIcons = function(unit, icons, filter, limit, isDebuff, offset, dontHide)
|
||||
if(not offset) then offset = 0 end
|
||||
local index = 1
|
||||
local visible = 0
|
||||
local hidden = 0
|
||||
while(visible < limit) do
|
||||
local result = updateIcon(unit, icons, index, offset, filter, isDebuff, visible)
|
||||
if(not result) then
|
||||
break
|
||||
elseif(result == VISIBLE) then
|
||||
visible = visible + 1
|
||||
elseif(result == HIDDEN) then
|
||||
hidden = hidden + 1
|
||||
end
|
||||
|
||||
index = index + 1
|
||||
end
|
||||
|
||||
if(not dontHide) then
|
||||
for i = visible + offset + 1, #icons do
|
||||
icons[i]:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
return visible, hidden
|
||||
end
|
||||
|
||||
local UpdateAuras = function(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local auras = self.Auras
|
||||
if(auras) then
|
||||
if(auras.PreUpdate) then auras:PreUpdate(unit) end
|
||||
|
||||
local numBuffs = auras.numBuffs or 32
|
||||
local numDebuffs = auras.numDebuffs or 40
|
||||
local max = numBuffs + numDebuffs
|
||||
|
||||
local visibleBuffs, hiddenBuffs = filterIcons(unit, auras, auras.buffFilter or auras.filter or 'HELPFUL', numBuffs, nil, 0, true)
|
||||
|
||||
local hasGap
|
||||
if(visibleBuffs ~= 0 and auras.gap) then
|
||||
hasGap = true
|
||||
visibleBuffs = visibleBuffs + 1
|
||||
|
||||
local icon = auras[visibleBuffs]
|
||||
if(not icon) then
|
||||
local prev = auras.createdIcons
|
||||
icon = (auras.CreateIcon or createAuraIcon) (auras, visibleBuffs)
|
||||
-- XXX: Update the counters if the layout doesn't.
|
||||
if(prev == auras.createdIcons) then
|
||||
table.insert(auras, icon)
|
||||
auras.createdIcons = auras.createdIcons + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Prevent the icon from displaying anything.
|
||||
if(icon.cd) then icon.cd:Hide() end
|
||||
icon:EnableMouse(false)
|
||||
icon.icon:SetTexture()
|
||||
icon.overlay:Hide()
|
||||
icon.stealable:Hide()
|
||||
icon.count:SetText()
|
||||
icon:Show()
|
||||
|
||||
--[[ :PostUpdateGapIcon(unit, icon, visibleBuffs)
|
||||
|
||||
Callback which is called after an invisible aura icon has been
|
||||
created. This is only used by Auras when the `gap` option is enabled.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The widget that holds the aura icon.
|
||||
unit - The unit that has the aura icon.
|
||||
icon - The invisible aura icon / gap.
|
||||
visibleBuffs - The number of currently visible buffs.
|
||||
]]
|
||||
if(auras.PostUpdateGapIcon) then
|
||||
auras:PostUpdateGapIcon(unit, icon, visibleBuffs)
|
||||
end
|
||||
end
|
||||
|
||||
local visibleDebuffs, hiddenDebuffs = filterIcons(unit, auras, auras.debuffFilter or auras.filter or 'HARMFUL', numDebuffs, true, visibleBuffs)
|
||||
auras.visibleDebuffs = visibleDebuffs
|
||||
|
||||
if(hasGap and visibleDebuffs == 0) then
|
||||
auras[visibleBuffs]:Hide()
|
||||
visibleBuffs = visibleBuffs - 1
|
||||
end
|
||||
|
||||
auras.visibleBuffs = visibleBuffs
|
||||
auras.visibleAuras = auras.visibleBuffs + auras.visibleDebuffs
|
||||
|
||||
local fromRange, toRange
|
||||
if(auras.PreSetPosition) then
|
||||
fromRange, toRange = auras:PreSetPosition(max)
|
||||
end
|
||||
|
||||
if(fromRange or auras.createdIcons > auras.anchoredIcons) then
|
||||
(auras.SetPosition or SetPosition) (auras, fromRange or auras.anchoredIcons + 1, toRange or auras.createdIcons)
|
||||
auras.anchoredIcons = auras.createdIcons
|
||||
end
|
||||
|
||||
if(auras.PostUpdate) then auras:PostUpdate(unit) end
|
||||
end
|
||||
|
||||
local buffs = self.Buffs
|
||||
if(buffs) then
|
||||
if(buffs.PreUpdate) then buffs:PreUpdate(unit) end
|
||||
|
||||
local numBuffs = buffs.num or 32
|
||||
local visibleBuffs, hiddenBuffs = filterIcons(unit, buffs, buffs.filter or 'HELPFUL', numBuffs)
|
||||
buffs.visibleBuffs = visibleBuffs
|
||||
|
||||
local fromRange, toRange
|
||||
if(buffs.PreSetPosition) then
|
||||
fromRange, toRange = buffs:PreSetPosition(numBuffs)
|
||||
end
|
||||
|
||||
if(fromRange or buffs.createdIcons > buffs.anchoredIcons) then
|
||||
(buffs.SetPosition or SetPosition) (buffs, fromRange or buffs.anchoredIcons + 1, toRange or buffs.createdIcons)
|
||||
buffs.anchoredIcons = buffs.createdIcons
|
||||
end
|
||||
|
||||
if(buffs.PostUpdate) then buffs:PostUpdate(unit) end
|
||||
end
|
||||
|
||||
local debuffs = self.Debuffs
|
||||
if(debuffs) then
|
||||
if(debuffs.PreUpdate) then debuffs:PreUpdate(unit) end
|
||||
|
||||
local numDebuffs = debuffs.num or 40
|
||||
local visibleDebuffs, hiddenDebuffs = filterIcons(unit, debuffs, debuffs.filter or 'HARMFUL', numDebuffs, true)
|
||||
debuffs.visibleDebuffs = visibleDebuffs
|
||||
|
||||
local fromRange, toRange
|
||||
if(debuffs.PreSetPosition) then
|
||||
fromRange, toRange = debuffs:PreSetPosition(numDebuffs)
|
||||
end
|
||||
|
||||
if(fromRange or debuffs.createdIcons > debuffs.anchoredIcons) then
|
||||
(debuffs.SetPosition or SetPosition) (debuffs, fromRange or debuffs.anchoredIcons + 1, toRange or debuffs.createdIcons)
|
||||
debuffs.anchoredIcons = debuffs.createdIcons
|
||||
end
|
||||
|
||||
if(debuffs.PostUpdate) then debuffs:PostUpdate(unit) end
|
||||
end
|
||||
end
|
||||
|
||||
local Update = function(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
UpdateAuras(self, event, unit)
|
||||
|
||||
-- Assume no event means someone wants to re-anchor things. This is usually
|
||||
-- done by UpdateAllElements and :ForceUpdate.
|
||||
if(event == 'ForceUpdate' or not event) then
|
||||
local buffs = self.Buffs
|
||||
if(buffs) then
|
||||
(buffs.SetPosition or SetPosition) (buffs, 1, buffs.createdIcons)
|
||||
end
|
||||
|
||||
local debuffs = self.Debuffs
|
||||
if(debuffs) then
|
||||
(debuffs.SetPosition or SetPosition) (debuffs, 1, debuffs.createdIcons)
|
||||
end
|
||||
|
||||
local auras = self.Auras
|
||||
if(auras) then
|
||||
(auras.SetPosition or SetPosition) (auras, 1, auras.createdIcons)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Update(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
if(self.Buffs or self.Debuffs or self.Auras) then
|
||||
self:RegisterEvent("UNIT_AURA", UpdateAuras)
|
||||
|
||||
local buffs = self.Buffs
|
||||
if(buffs) then
|
||||
buffs.__owner = self
|
||||
buffs.ForceUpdate = ForceUpdate
|
||||
|
||||
buffs.createdIcons = 0
|
||||
buffs.anchoredIcons = 0
|
||||
end
|
||||
|
||||
local debuffs = self.Debuffs
|
||||
if(debuffs) then
|
||||
debuffs.__owner = self
|
||||
debuffs.ForceUpdate = ForceUpdate
|
||||
|
||||
debuffs.createdIcons = 0
|
||||
debuffs.anchoredIcons = 0
|
||||
end
|
||||
|
||||
local auras = self.Auras
|
||||
if(auras) then
|
||||
auras.__owner = self
|
||||
auras.ForceUpdate = ForceUpdate
|
||||
|
||||
auras.createdIcons = 0
|
||||
auras.anchoredIcons = 0
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
if(self.Buffs or self.Debuffs or self.Auras) then
|
||||
self:UnregisterEvent("UNIT_AURA", UpdateAuras)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Aura', Update, Enable, Disable)
|
||||
602
Libraries/oUF/elements/castbar.lua
Normal file
602
Libraries/oUF/elements/castbar.lua
Normal file
@@ -0,0 +1,602 @@
|
||||
--[[ Element: Castbar
|
||||
|
||||
Handles updating and visibility of unit castbars.
|
||||
|
||||
Widget
|
||||
|
||||
Castbar - A StatusBar to represent spell progress.
|
||||
|
||||
Sub-Widgets
|
||||
|
||||
.Text - A FontString to represent spell name.
|
||||
.Icon - A Texture to represent spell icon.
|
||||
.Time - A FontString to represent spell duration.
|
||||
.Shield - A Texture to represent if it's possible to interrupt or spell
|
||||
steal.
|
||||
.SafeZone - A Texture to represent latency.
|
||||
|
||||
Options
|
||||
|
||||
.timeToHold - A Number to indicate for how many seconds the castbar should be
|
||||
visible after a _FAILED or _INTERRUPTED event. Defaults to 0.
|
||||
|
||||
Credits
|
||||
|
||||
Based upon oUF_Castbar by starlon.
|
||||
|
||||
Notes
|
||||
|
||||
The default texture will be applied if the UI widget doesn't have a texture or
|
||||
color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local Castbar = CreateFrame("StatusBar", nil, self)
|
||||
Castbar:SetSize(20, 20)
|
||||
Castbar:SetPoint('TOP')
|
||||
Castbar:SetPoint('LEFT')
|
||||
Castbar:SetPoint('RIGHT')
|
||||
|
||||
-- Add a background
|
||||
local Background = Castbar:CreateTexture(nil, 'BACKGROUND')
|
||||
Background:SetAllPoints(Castbar)
|
||||
Background:SetTexture(1, 1, 1, .5)
|
||||
|
||||
-- Add a spark
|
||||
local Spark = Castbar:CreateTexture(nil, "OVERLAY")
|
||||
Spark:SetSize(20, 20)
|
||||
Spark:SetBlendMode("ADD")
|
||||
|
||||
-- Add a timer
|
||||
local Time = Castbar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
||||
Time:SetPoint("RIGHT", Castbar)
|
||||
|
||||
-- Add spell text
|
||||
local Text = Castbar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
||||
Text:SetPoint("LEFT", Castbar)
|
||||
|
||||
-- Add spell icon
|
||||
local Icon = Castbar:CreateTexture(nil, "OVERLAY")
|
||||
Icon:SetSize(20, 20)
|
||||
Icon:SetPoint("TOPLEFT", Castbar, "TOPLEFT")
|
||||
|
||||
-- Add Shield
|
||||
local Shield = Castbar:CreateTexture(nil, "OVERLAY")
|
||||
Shield:SetSize(20, 20)
|
||||
Shield:SetPoint("CENTER", Castbar)
|
||||
|
||||
-- Add safezone
|
||||
local SafeZone = Castbar:CreateTexture(nil, "OVERLAY")
|
||||
|
||||
-- Register it with oUF
|
||||
self.Castbar = Castbar
|
||||
self.Castbar.bg = Background
|
||||
self.Castbar.Spark = Spark
|
||||
self.Castbar.Time = Time
|
||||
self.Castbar.Text = Text
|
||||
self.Castbar.Icon = Icon
|
||||
self.Castbar.SafeZone = SafeZone
|
||||
|
||||
Hooks and Callbacks
|
||||
|
||||
]]
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local GetNetStats = GetNetStats
|
||||
local GetTime = GetTime
|
||||
local UnitCastingInfo = UnitCastingInfo
|
||||
local UnitChannelInfo = UnitChannelInfo
|
||||
local tradeskillCurrent, tradeskillTotal, mergeTradeskill = 0, 0, false
|
||||
|
||||
local updateSafeZone = function(self)
|
||||
local sz = self.SafeZone
|
||||
local width = self:GetWidth()
|
||||
local _, _, _, ms = GetNetStats()
|
||||
|
||||
-- Guard against GetNetStats returning latencies of 0.
|
||||
if(ms ~= 0) then
|
||||
-- MADNESS!
|
||||
local safeZonePercent = (width / self.max) * (ms / 1e5)
|
||||
if(safeZonePercent > 1) then safeZonePercent = 1 end
|
||||
sz:SetWidth(width * safeZonePercent)
|
||||
sz:Show()
|
||||
else
|
||||
sz:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_SENT = function (self, event, unit, spell, rank, target, castid)
|
||||
local castbar = self.Castbar
|
||||
castbar.curTarget = (target and target ~= "") and target or nil
|
||||
|
||||
if castbar.isTradeSkill then
|
||||
castbar.tradeSkillCastId = castid
|
||||
end
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_START = function(self, event, unit)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
local name, _, text, texture, startTime, endTime, isTradeSkill, castid, notInterruptible, spellid = UnitCastingInfo(unit)
|
||||
if(not name) then
|
||||
return castbar:Hide()
|
||||
end
|
||||
|
||||
endTime = endTime / 1e3
|
||||
startTime = startTime / 1e3
|
||||
local max = endTime - startTime
|
||||
|
||||
castbar.castid = castid
|
||||
castbar.duration = GetTime() - startTime
|
||||
castbar.max = max
|
||||
castbar.delay = 0
|
||||
castbar.casting = true
|
||||
castbar.interrupt = notInterruptible -- NOTE: deprecated; to be removed
|
||||
castbar.notInterruptible = notInterruptible
|
||||
castbar.holdTime = 0
|
||||
castbar.isTradeSkill = isTradeSkill
|
||||
|
||||
if(mergeTradeskill and isTradeSkill and UnitIsUnit(unit, "player")) then
|
||||
castbar.duration = castbar.duration + (castbar.max * tradeskillCurrent);
|
||||
castbar.max = max * tradeskillTotal;
|
||||
|
||||
if(unit == "player") then
|
||||
tradeskillCurrent = tradeskillCurrent + 1;
|
||||
end
|
||||
castbar:SetValue(castbar.duration)
|
||||
else
|
||||
castbar:SetValue(0)
|
||||
end
|
||||
castbar:SetValue(0)
|
||||
|
||||
castbar:SetMinMaxValues(0, castbar.max)
|
||||
|
||||
if(castbar.Text) then castbar.Text:SetText(text) end
|
||||
if(castbar.Icon) then castbar.Icon:SetTexture(texture) end
|
||||
if(castbar.Time) then castbar.Time:SetText() end
|
||||
|
||||
local shield = castbar.Shield
|
||||
if(shield and notInterruptible) then
|
||||
shield:Show()
|
||||
elseif(shield) then
|
||||
shield:Hide()
|
||||
end
|
||||
|
||||
local sf = castbar.SafeZone
|
||||
if(sf) then
|
||||
sf:ClearAllPoints()
|
||||
sf:SetPoint'RIGHT'
|
||||
sf:SetPoint'TOP'
|
||||
sf:SetPoint'BOTTOM'
|
||||
updateSafeZone(castbar)
|
||||
end
|
||||
|
||||
if(castbar.PostCastStart) then
|
||||
castbar:PostCastStart(unit, name, castid, spellid)
|
||||
end
|
||||
castbar:Show()
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_FAILED = function(self, event, unit, spellname, _, castid, spellid)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
if (castbar.castid ~= castid) and (castbar.tradeSkillCastId ~= castid) then
|
||||
return
|
||||
end
|
||||
|
||||
if(mergeTradeskill and UnitIsUnit(unit, "player")) then
|
||||
mergeTradeskill = false;
|
||||
castbar.tradeSkillCastId = nil
|
||||
end
|
||||
|
||||
local text = castbar.Text
|
||||
if(text) then
|
||||
text:SetText(FAILED)
|
||||
end
|
||||
|
||||
castbar.casting = nil
|
||||
castbar.interrupt = nil -- NOTE: deprecated; to be removed
|
||||
castbar.notInterruptible = nil
|
||||
castbar.holdTime = castbar.timeToHold or 0
|
||||
|
||||
if(castbar.PostCastFailed) then
|
||||
return castbar:PostCastFailed(unit, spellname, castid, spellid)
|
||||
end
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_FAILED_QUIET = function(self, event, unit, spellname, _, castid)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
if (castbar.castid ~= castid) and (castbar.tradeSkillCastId ~= castid) then
|
||||
return
|
||||
end
|
||||
|
||||
if(mergeTradeskill and UnitIsUnit(unit, "player")) then
|
||||
mergeTradeskill = false;
|
||||
castbar.tradeSkillCastId = nil
|
||||
end
|
||||
|
||||
castbar.casting = nil
|
||||
castbar.interrupt = nil -- NOTE: deprecated; to be removed
|
||||
castbar.notInterruptible = nil
|
||||
castbar:SetValue(0)
|
||||
castbar:Hide()
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_INTERRUPTED = function(self, event, unit, spellname, _, castid, spellid)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
if (castbar.castid ~= castid) then
|
||||
return
|
||||
end
|
||||
|
||||
local text = castbar.Text
|
||||
if(text) then
|
||||
text:SetText(INTERRUPTED)
|
||||
end
|
||||
|
||||
castbar.casting = nil
|
||||
castbar.channeling = nil
|
||||
castbar.holdTime = castbar.timeToHold or 0
|
||||
|
||||
if(castbar.PostCastInterrupted) then
|
||||
return castbar:PostCastInterrupted(unit, spellname, castid, spellid)
|
||||
end
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_INTERRUPTIBLE = function(self, event, unit)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
local shield = castbar.Shield
|
||||
if(shield) then
|
||||
shield:Hide()
|
||||
end
|
||||
|
||||
castbar.interrupt = nil -- NOTE: deprecated; to be removed
|
||||
castbar.notInterruptible = nil
|
||||
|
||||
if(castbar.PostCastInterruptible) then
|
||||
return castbar:PostCastInterruptible(unit)
|
||||
end
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_NOT_INTERRUPTIBLE = function(self, event, unit)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
local shield = castbar.Shield
|
||||
if(shield) then
|
||||
shield:Show()
|
||||
end
|
||||
|
||||
castbar.interrupt = nil -- NOTE: deprecated; to be removed
|
||||
castbar.notInterruptible = nil
|
||||
|
||||
if(castbar.PostCastNotInterruptible) then
|
||||
return castbar:PostCastNotInterruptible(unit)
|
||||
end
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_DELAYED = function(self, event, unit, _, _, _, spellid)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
local name, _, _, _, startTime, _, _, castid = UnitCastingInfo(unit)
|
||||
if(not startTime or not castbar:IsShown()) then return end
|
||||
|
||||
local duration = GetTime() - (startTime / 1000)
|
||||
if(duration < 0) then duration = 0 end
|
||||
|
||||
castbar.delay = castbar.delay + castbar.duration - duration
|
||||
castbar.duration = duration
|
||||
|
||||
castbar:SetValue(duration)
|
||||
|
||||
if(castbar.PostCastDelayed) then
|
||||
return castbar:PostCastDelayed(unit, name, castid, spellid)
|
||||
end
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_STOP = function(self, event, unit, spellname, _, castid, spellid)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
if (castbar.castid ~= castid) then
|
||||
return
|
||||
end
|
||||
|
||||
if(mergeTradeskill and UnitIsUnit(unit, "player")) then
|
||||
if(tradeskillCurrent == tradeskillTotal) then
|
||||
mergeTradeskill = false;
|
||||
end
|
||||
else
|
||||
castbar.casting = nil
|
||||
castbar.interrupt = nil -- NOTE: deprecated; to be removed
|
||||
castbar.notInterruptible = nil
|
||||
end
|
||||
|
||||
if(castbar.PostCastStop) then
|
||||
return castbar:PostCastStop(unit, spellname, castid, spellid)
|
||||
end
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_CHANNEL_START = function(self, event, unit, _, _, _, spellid)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
local name, _, _, texture, startTime, endTime, _, notInterruptible = UnitChannelInfo(unit)
|
||||
if(not name) then
|
||||
return
|
||||
end
|
||||
|
||||
endTime = endTime / 1e3
|
||||
startTime = startTime / 1e3
|
||||
local max = (endTime - startTime)
|
||||
local duration = endTime - GetTime()
|
||||
|
||||
castbar.duration = duration
|
||||
castbar.max = max
|
||||
castbar.delay = 0
|
||||
castbar.startTime = startTime
|
||||
castbar.endTime = endTime
|
||||
castbar.extraTickRatio = 0
|
||||
castbar.channeling = true
|
||||
castbar.interrupt = notInterruptible -- NOTE: deprecated; to be removed
|
||||
castbar.notInterruptible = notInterruptible
|
||||
castbar.holdTime = 0
|
||||
|
||||
-- We have to do this, as it's possible for spell casts to never have _STOP
|
||||
-- executed or be fully completed by the OnUpdate handler before CHANNEL_START
|
||||
-- is called.
|
||||
castbar.casting = nil
|
||||
castbar.castid = nil
|
||||
|
||||
castbar:SetMinMaxValues(0, max)
|
||||
castbar:SetValue(duration)
|
||||
|
||||
if(castbar.Text) then castbar.Text:SetText(name) end
|
||||
if(castbar.Icon) then castbar.Icon:SetTexture(texture) end
|
||||
if(castbar.Time) then castbar.Time:SetText() end
|
||||
|
||||
local shield = castbar.Shield
|
||||
if(shield and notInterruptible) then
|
||||
shield:Show()
|
||||
elseif(shield) then
|
||||
shield:Hide()
|
||||
end
|
||||
|
||||
local sf = castbar.SafeZone
|
||||
if(sf) then
|
||||
sf:ClearAllPoints()
|
||||
sf:SetPoint'LEFT'
|
||||
sf:SetPoint'TOP'
|
||||
sf:SetPoint'BOTTOM'
|
||||
updateSafeZone(castbar)
|
||||
end
|
||||
|
||||
if(castbar.PostChannelStart) then castbar:PostChannelStart(unit, name, spellid) end
|
||||
castbar:Show()
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_CHANNEL_UPDATE = function(self, event, unit, _, _, _, spellid)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
local name, _, _, _, startTime, endTime = UnitChannelInfo(unit)
|
||||
if(not name or not castbar:IsShown()) then
|
||||
return
|
||||
end
|
||||
|
||||
local duration = (endTime / 1000) - GetTime()
|
||||
local startDelay = castbar.startTime - startTime / 1000
|
||||
castbar.startTime = startTime / 1000
|
||||
castbar.endTime = endTime / 1000
|
||||
castbar.delay = castbar.delay + startDelay
|
||||
|
||||
castbar.duration = duration
|
||||
castbar.max = (endTime - startTime) / 1000
|
||||
|
||||
castbar:SetMinMaxValues(0, castbar.max)
|
||||
castbar:SetValue(duration)
|
||||
|
||||
if(castbar.PostChannelUpdate) then
|
||||
return castbar:PostChannelUpdate(unit, name, spellid)
|
||||
end
|
||||
end
|
||||
|
||||
local UNIT_SPELLCAST_CHANNEL_STOP = function(self, event, unit, spellname, _, _, spellid)
|
||||
if(self.unit ~= unit and self.realUnit ~= unit) then return end
|
||||
|
||||
local castbar = self.Castbar
|
||||
if(castbar:IsShown()) then
|
||||
castbar.channeling = nil
|
||||
castbar.interrupt = nil -- NOTE: deprecated; to be removed
|
||||
castbar.notInterruptible = nil
|
||||
|
||||
if(castbar.PostChannelStop) then
|
||||
return castbar:PostChannelStop(unit, spellname, spellid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local onUpdate = function(self, elapsed)
|
||||
if(self.casting) then
|
||||
local duration = self.duration + elapsed
|
||||
if(duration >= self.max) then
|
||||
self.casting = nil
|
||||
self:Hide()
|
||||
|
||||
if(self.PostCastStop) then self:PostCastStop(self.__owner.unit) end
|
||||
return
|
||||
end
|
||||
|
||||
if(self.Time) then
|
||||
if(self.delay ~= 0) then
|
||||
if(self.CustomDelayText) then
|
||||
self:CustomDelayText(duration)
|
||||
else
|
||||
self.Time:SetFormattedText("%.1f|cffff0000-%.1f|r", duration, self.delay)
|
||||
end
|
||||
else
|
||||
if(self.CustomTimeText) then
|
||||
self:CustomTimeText(duration)
|
||||
else
|
||||
self.Time:SetFormattedText("%.1f", duration)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.duration = duration
|
||||
self:SetValue(duration)
|
||||
|
||||
if(self.Spark) then
|
||||
self.Spark:SetPoint("CENTER", self, "LEFT", (duration / self.max) * self:GetWidth(), 0)
|
||||
end
|
||||
elseif(self.channeling) then
|
||||
local duration = self.duration - elapsed
|
||||
|
||||
if(duration <= 0) then
|
||||
self.channeling = nil
|
||||
self:Hide()
|
||||
|
||||
if(self.PostChannelStop) then self:PostChannelStop(self.__owner.unit) end
|
||||
return
|
||||
end
|
||||
|
||||
if(self.Time) then
|
||||
if(self.delay ~= 0) then
|
||||
if(self.CustomDelayText) then
|
||||
self:CustomDelayText(duration)
|
||||
else
|
||||
self.Time:SetFormattedText("%.1f|cffff0000-%.1f|r", duration, self.delay)
|
||||
end
|
||||
else
|
||||
if(self.CustomTimeText) then
|
||||
self:CustomTimeText(duration)
|
||||
else
|
||||
self.Time:SetFormattedText("%.1f", duration)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.duration = duration
|
||||
self:SetValue(duration)
|
||||
if(self.Spark) then
|
||||
self.Spark:SetPoint("CENTER", self, "LEFT", (duration / self.max) * self:GetWidth(), 0)
|
||||
end
|
||||
elseif(self.holdTime > 0) then
|
||||
self.holdTime = self.holdTime - elapsed
|
||||
else
|
||||
self.casting = nil
|
||||
self.castid = nil
|
||||
self.channeling = nil
|
||||
|
||||
self:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local Update = function(self, ...)
|
||||
UNIT_SPELLCAST_START(self, ...)
|
||||
return UNIT_SPELLCAST_CHANNEL_START(self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Update(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
local castbar = self.Castbar
|
||||
|
||||
if(castbar) then
|
||||
castbar.__owner = self
|
||||
castbar.ForceUpdate = ForceUpdate
|
||||
|
||||
if(not (unit and unit:match'%wtarget$')) then
|
||||
self:RegisterEvent("UNIT_SPELLCAST_SENT", UNIT_SPELLCAST_SENT, true)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_START", UNIT_SPELLCAST_START)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_FAILED", UNIT_SPELLCAST_FAILED)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_FAILED_QUIET", UNIT_SPELLCAST_FAILED_QUIET)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_STOP", UNIT_SPELLCAST_STOP)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED", UNIT_SPELLCAST_INTERRUPTED)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTIBLE", UNIT_SPELLCAST_INTERRUPTIBLE)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE", UNIT_SPELLCAST_NOT_INTERRUPTIBLE)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_DELAYED", UNIT_SPELLCAST_DELAYED)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START", UNIT_SPELLCAST_CHANNEL_START)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", UNIT_SPELLCAST_CHANNEL_UPDATE)
|
||||
self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", UNIT_SPELLCAST_CHANNEL_STOP)
|
||||
end
|
||||
|
||||
castbar.holdTime = 0
|
||||
castbar:SetScript("OnUpdate", castbar.OnUpdate or onUpdate)
|
||||
|
||||
if(self.unit == "player") then
|
||||
CastingBarFrame:UnregisterAllEvents()
|
||||
CastingBarFrame.Show = CastingBarFrame.Hide
|
||||
CastingBarFrame:Hide()
|
||||
|
||||
PetCastingBarFrame:UnregisterAllEvents()
|
||||
PetCastingBarFrame.Show = PetCastingBarFrame.Hide
|
||||
PetCastingBarFrame:Hide()
|
||||
end
|
||||
|
||||
if(castbar:IsObjectType'StatusBar' and not castbar:GetStatusBarTexture()) then
|
||||
castbar:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]]
|
||||
end
|
||||
|
||||
local spark = castbar.Spark
|
||||
if(spark and spark:IsObjectType'Texture' and not spark:GetTexture()) then
|
||||
spark:SetTexture[[Interface\CastingBar\UI-CastingBar-Spark]]
|
||||
end
|
||||
|
||||
local shield = castbar.Shield
|
||||
if(shield and shield:IsObjectType'Texture' and not shield:GetTexture()) then
|
||||
shield:SetTexture[[Interface\CastingBar\UI-CastingBar-Small-Shield]]
|
||||
end
|
||||
|
||||
local sz = castbar.SafeZone
|
||||
if(sz and sz:IsObjectType'Texture' and not sz:GetTexture()) then
|
||||
sz:SetColorTexture(1, 0, 0)
|
||||
end
|
||||
|
||||
castbar:Hide()
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local castbar = self.Castbar
|
||||
|
||||
if(castbar) then
|
||||
castbar:Hide()
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_SENT", UNIT_SPELLCAST_SENT)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_START", UNIT_SPELLCAST_START)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_FAILED", UNIT_SPELLCAST_FAILED)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_FAILED_QUIET", UNIT_SPELLCAST_FAILED_QUIET)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_STOP", UNIT_SPELLCAST_STOP)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED", UNIT_SPELLCAST_INTERRUPTED)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTIBLE", UNIT_SPELLCAST_INTERRUPTIBLE)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE", UNIT_SPELLCAST_NOT_INTERRUPTIBLE)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_DELAYED", UNIT_SPELLCAST_DELAYED)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START", UNIT_SPELLCAST_CHANNEL_START)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", UNIT_SPELLCAST_CHANNEL_UPDATE)
|
||||
self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", UNIT_SPELLCAST_CHANNEL_STOP)
|
||||
|
||||
castbar:SetScript("OnUpdate", nil)
|
||||
end
|
||||
end
|
||||
|
||||
hooksecurefunc(C_TradeSkillUI, "CraftRecipe", function(_, num)
|
||||
tradeskillCurrent = 0
|
||||
tradeskillTotal = num or 1
|
||||
mergeTradeskill = true
|
||||
end)
|
||||
|
||||
oUF:AddElement('Castbar', Update, Enable, Disable)
|
||||
291
Libraries/oUF/elements/classicons.lua
Normal file
291
Libraries/oUF/elements/classicons.lua
Normal file
@@ -0,0 +1,291 @@
|
||||
--[[ Element: Class Icons
|
||||
|
||||
Toggles the visibility of icons depending on the player's class and
|
||||
specialization.
|
||||
|
||||
Widget
|
||||
|
||||
ClassIcons - An array consisting of as many UI Textures as the theoretical
|
||||
maximum return of `UnitPowerMax`.
|
||||
|
||||
Notes
|
||||
|
||||
All - Combo Points
|
||||
Mage - Arcane Charges
|
||||
Monk - Chi Orbs
|
||||
Paladin - Holy Power
|
||||
Warlock - Soul Shards
|
||||
|
||||
Examples
|
||||
|
||||
local ClassIcons = {}
|
||||
for index = 1, 6 do
|
||||
local Icon = self:CreateTexture(nil, 'BACKGROUND')
|
||||
|
||||
-- Position and size.
|
||||
Icon:SetSize(16, 16)
|
||||
Icon:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', index * Icon:GetWidth(), 0)
|
||||
|
||||
ClassIcons[index] = Icon
|
||||
end
|
||||
|
||||
-- Register with oUF
|
||||
self.ClassIcons = ClassIcons
|
||||
|
||||
Hooks
|
||||
|
||||
OverrideVisibility(self) - Used to completely override the internal visibility
|
||||
function. Removing the table key entry will make
|
||||
the element fall-back to its internal function
|
||||
again.
|
||||
Override(self) - Used to completely override the internal update
|
||||
function. Removing the table key entry will make the
|
||||
element fall-back to its internal function again.
|
||||
UpdateTexture(element) - Used to completely override the internal function
|
||||
for updating the power icon textures. Removing the
|
||||
table key entry will make the element fall-back to
|
||||
its internal function again.
|
||||
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local _, PlayerClass = UnitClass'player'
|
||||
|
||||
-- Holds the class specific stuff.
|
||||
local ClassPowerID, ClassPowerType
|
||||
local ClassPowerEnable, ClassPowerDisable
|
||||
local RequireSpec, RequireSpell, RequireFormID
|
||||
|
||||
local UpdateTexture = function(element)
|
||||
local color = oUF.colors.power[ClassPowerType or 'COMBO_POINTS']
|
||||
for i = 1, #element do
|
||||
local icon = element[i]
|
||||
if(icon.SetDesaturated) then
|
||||
icon:SetDesaturated(PlayerClass ~= 'PRIEST')
|
||||
end
|
||||
|
||||
icon:SetVertexColor(color[1], color[2], color[3])
|
||||
end
|
||||
end
|
||||
|
||||
local Update = function(self, event, unit, powerType)
|
||||
if(not (unit == 'player' and powerType == ClassPowerType
|
||||
or unit == 'vehicle' and powerType == 'COMBO_POINTS')) then
|
||||
return
|
||||
end
|
||||
|
||||
local element = self.ClassIcons
|
||||
|
||||
--[[ :PreUpdate()
|
||||
|
||||
Called before the element has been updated
|
||||
|
||||
Arguments
|
||||
|
||||
self - The ClassIcons element
|
||||
event - The event, that the update is being triggered for
|
||||
]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate(event)
|
||||
end
|
||||
|
||||
local cur, max, oldMax
|
||||
if(event ~= 'ClassPowerDisable') then
|
||||
if(unit == 'vehicle') then
|
||||
-- XXX: UnitPower is bugged for vehicles, always returns 0 combo points
|
||||
cur = GetComboPoints(unit)
|
||||
max = MAX_COMBO_POINTS
|
||||
else
|
||||
cur = UnitPower('player', ClassPowerID)
|
||||
max = UnitPowerMax('player', ClassPowerID)
|
||||
end
|
||||
|
||||
for i = 1, max do
|
||||
if(i <= cur) then
|
||||
element[i]:Show()
|
||||
else
|
||||
element[i]:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
oldMax = element.__max
|
||||
if(max ~= oldMax) then
|
||||
if(max < oldMax) then
|
||||
for i = max + 1, oldMax do
|
||||
element[i]:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
element.__max = max
|
||||
end
|
||||
end
|
||||
--[[ :PostUpdate(cur, max, hasMaxChanged, event)
|
||||
|
||||
Called after the element has been updated
|
||||
|
||||
Arguments
|
||||
|
||||
self - The ClassIcons element
|
||||
cur - The current amount of power
|
||||
max - The maximum amount of power
|
||||
hasMaxChanged - Shows if the maximum amount has changed since the last
|
||||
update
|
||||
powerType - The type of power used
|
||||
event - The event, which the update happened for
|
||||
]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(cur, max, oldMax ~= max, powerType, event)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.ClassIcons.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function Visibility(self, event, unit)
|
||||
local element = self.ClassIcons
|
||||
local shouldEnable
|
||||
|
||||
if(UnitHasVehicleUI('player')) then
|
||||
shouldEnable = true
|
||||
unit = 'vehicle'
|
||||
elseif(ClassPowerID) then
|
||||
if(not RequireSpec or RequireSpec == GetSpecialization()) then
|
||||
if(not RequireFormID or RequireFormID == GetShapeshiftFormID()) then
|
||||
if(not RequireSpell or IsPlayerSpell(RequireSpell)) then
|
||||
if(not RequirePower or RequirePower == UnitPowerType('player')) then
|
||||
self:UnregisterEvent('SPELLS_CHANGED', Visibility)
|
||||
shouldEnable = true
|
||||
else
|
||||
self:RegisterEvent('SPELLS_CHANGED', Visibility, true)
|
||||
end
|
||||
else
|
||||
self:RegisterEvent('SPELLS_CHANGED', Visibility, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local isEnabled = element.isEnabled
|
||||
if(shouldEnable and not isEnabled) then
|
||||
ClassPowerEnable(self)
|
||||
elseif(not shouldEnable and (isEnabled or isEnabled == nil)) then
|
||||
ClassPowerDisable(self)
|
||||
elseif(shouldEnable and isEnabled) then
|
||||
Path(self, event, unit, unit == 'vehicle' and 'COMBO_POINTS' or ClassPowerType)
|
||||
end
|
||||
end
|
||||
|
||||
local VisibilityPath = function(self, ...)
|
||||
return (self.ClassIcons.OverrideVisibility or Visibility) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return VisibilityPath(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
do
|
||||
ClassPowerEnable = function(self)
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
self:RegisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:RegisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
if(UnitHasVehicleUI('player')) then
|
||||
Path(self, 'ClassPowerEnable', 'vehicle', 'COMBO_POINTS')
|
||||
else
|
||||
Path(self, 'ClassPowerEnable', 'player', ClassPowerType)
|
||||
end
|
||||
self.ClassIcons.isEnabled = true
|
||||
end
|
||||
|
||||
ClassPowerDisable = function(self)
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
self:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
local element = self.ClassIcons
|
||||
for i = 1, #element do
|
||||
element[i]:Hide()
|
||||
end
|
||||
|
||||
Path(self, 'ClassPowerDisable', 'player', ClassPowerType)
|
||||
self.ClassIcons.isEnabled = false
|
||||
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"
|
||||
RequireSpec = SPEC_PALADIN_RETRIBUTION
|
||||
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
|
||||
RequireFormID = 1 --CAT_FORM
|
||||
RequireSpell = 5221 -- Shred
|
||||
end
|
||||
elseif(PlayerClass == 'MAGE') then
|
||||
ClassPowerID = SPELL_POWER_ARCANE_CHARGES
|
||||
ClassPowerType = 'ARCANE_CHARGES'
|
||||
RequireSpec = SPEC_MAGE_ARCANE
|
||||
end
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
if(unit ~= 'player') then return end
|
||||
|
||||
local element = self.ClassIcons
|
||||
if(not element) then return end
|
||||
|
||||
element.__owner = self
|
||||
element.__max = #element
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
if(RequireSpec or RequireSpell) then
|
||||
self:RegisterEvent('PLAYER_TALENT_UPDATE', VisibilityPath, true)
|
||||
end
|
||||
|
||||
if(RequireFormID) then
|
||||
self:RegisterEvent('UPDATE_SHAPESHIFT_FORM', VisibilityPath, true)
|
||||
end
|
||||
|
||||
element.ClassPowerEnable = ClassPowerEnable
|
||||
element.ClassPowerDisable = ClassPowerDisable
|
||||
|
||||
local isChildrenTextures
|
||||
for i = 1, #element do
|
||||
local icon = element[i]
|
||||
if(icon:IsObjectType'Texture') then
|
||||
if(not icon:GetTexture()) then
|
||||
icon:SetTexCoord(0.45703125, 0.60546875, 0.44531250, 0.73437500)
|
||||
icon:SetTexture([[Interface\PlayerFrame\Priest-ShadowUI]])
|
||||
end
|
||||
|
||||
isChildrenTextures = true
|
||||
end
|
||||
end
|
||||
|
||||
if(isChildrenTextures) then
|
||||
(element.UpdateTexture or UpdateTexture) (element)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local element = self.ClassIcons
|
||||
if(not element) then return end
|
||||
|
||||
ClassPowerDisable(self)
|
||||
end
|
||||
|
||||
oUF:AddElement('ClassIcons', VisibilityPath, Enable, Disable)
|
||||
86
Libraries/oUF/elements/combat.lua
Normal file
86
Libraries/oUF/elements/combat.lua
Normal file
@@ -0,0 +1,86 @@
|
||||
--[[ Element: Combat Icon
|
||||
Toggles the visibility of `self.Combat` based on the player's combat status.
|
||||
|
||||
Widget
|
||||
|
||||
Combat - Any UI widget.
|
||||
|
||||
Notes
|
||||
|
||||
The default assistant icon will be applied if the UI widget is a texture and
|
||||
doesn't have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local Combat = self:CreateTexture(nil, "OVERLAY")
|
||||
Combat:SetSize(16, 16)
|
||||
Combat:SetPoint('TOP', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.Combat = Combat
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event)
|
||||
local combat = self.Combat
|
||||
if(combat.PreUpdate) then
|
||||
combat:PreUpdate()
|
||||
end
|
||||
|
||||
local inCombat = UnitAffectingCombat('player')
|
||||
if(inCombat) then
|
||||
combat:Show()
|
||||
else
|
||||
combat:Hide()
|
||||
end
|
||||
|
||||
if(combat.PostUpdate) then
|
||||
return combat:PostUpdate(inCombat)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.Combat.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
local combat = self.Combat
|
||||
if(combat and unit == 'player') then
|
||||
combat.__owner = self
|
||||
combat.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent("PLAYER_REGEN_DISABLED", Path, true)
|
||||
self:RegisterEvent("PLAYER_REGEN_ENABLED", Path, true)
|
||||
|
||||
if(combat:IsObjectType"Texture" and not combat:GetTexture()) then
|
||||
combat:SetTexture[[Interface\CharacterFrame\UI-StateIcon]]
|
||||
combat:SetTexCoord(.5, 1, 0, .49)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
if(self.Combat) then
|
||||
self.Combat:Hide()
|
||||
self:UnregisterEvent("PLAYER_REGEN_DISABLED", Path)
|
||||
self:UnregisterEvent("PLAYER_REGEN_ENABLED", Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Combat', Path, Enable, Disable)
|
||||
239
Libraries/oUF/elements/healprediction.lua
Normal file
239
Libraries/oUF/elements/healprediction.lua
Normal file
@@ -0,0 +1,239 @@
|
||||
--[[ Element: Heal Prediction Bar
|
||||
Handle updating and visibility of the heal prediction status bars.
|
||||
|
||||
Widget
|
||||
|
||||
HealPrediction - A table containing `myBar` and `otherBar`.
|
||||
|
||||
Sub-Widgets
|
||||
|
||||
myBar - A StatusBar used to represent your incoming heals.
|
||||
otherBar - A StatusBar used to represent other peoples incoming heals.
|
||||
absorbBar - A StatusBar used to represent total absorbs.
|
||||
healAbsorbBar - A StatusBar used to represent heal absorbs.
|
||||
|
||||
Notes
|
||||
|
||||
The default StatusBar texture will be applied if the UI widget doesn't have a
|
||||
status bar texture or color defined.
|
||||
|
||||
Options
|
||||
|
||||
.maxOverflow - Defines the maximum amount of overflow past the end of the
|
||||
health bar.
|
||||
.frequentUpdates - Update on UNIT_HEALTH_FREQUENT instead of UNIT_HEALTH. Use
|
||||
this if .frequentUpdates is also set on the Health element.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local myBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
myBar:SetPoint('TOP')
|
||||
myBar:SetPoint('BOTTOM')
|
||||
myBar:SetPoint('LEFT', self.Health:GetStatusBarTexture(), 'RIGHT')
|
||||
myBar:SetWidth(200)
|
||||
|
||||
local otherBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
otherBar:SetPoint('TOP')
|
||||
otherBar:SetPoint('BOTTOM')
|
||||
otherBar:SetPoint('LEFT', self.Health:GetStatusBarTexture(), 'RIGHT')
|
||||
otherBar:SetWidth(200)
|
||||
|
||||
local absorbBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
absorbBar:SetPoint('TOP')
|
||||
absorbBar:SetPoint('BOTTOM')
|
||||
absorbBar:SetPoint('LEFT', self.Health:GetStatusBarTexture(), 'RIGHT')
|
||||
absorbBar:SetWidth(200)
|
||||
|
||||
local healAbsorbBar = CreateFrame('StatusBar', nil, self.Health)
|
||||
healAbsorbBar:SetPoint('TOP')
|
||||
healAbsorbBar:SetPoint('BOTTOM')
|
||||
healAbsorbBar:SetPoint('LEFT', self.Health:GetStatusBarTexture(), 'RIGHT')
|
||||
healAbsorbBar:SetWidth(200)
|
||||
|
||||
-- Register with oUF
|
||||
self.HealPrediction = {
|
||||
myBar = myBar,
|
||||
otherBar = otherBar,
|
||||
absorbBar = absorbBar,
|
||||
healAbsorbBar = healAbsorbBar,
|
||||
maxOverflow = 1.05,
|
||||
frequentUpdates = true,
|
||||
}
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(self.unit ~= unit) or not unit then return end
|
||||
|
||||
local hp = self.HealPrediction
|
||||
hp.parent = self
|
||||
if(hp.PreUpdate) then hp:PreUpdate(unit) end
|
||||
|
||||
local myIncomingHeal = UnitGetIncomingHeals(unit, 'player') or 0
|
||||
local allIncomingHeal = UnitGetIncomingHeals(unit) or 0
|
||||
local totalAbsorb = UnitGetTotalAbsorbs(unit) or 0
|
||||
local myCurrentHealAbsorb = UnitGetTotalHealAbsorbs(unit) or 0
|
||||
local health, maxHealth = UnitHealth(unit), UnitHealthMax(unit)
|
||||
|
||||
local overHealAbsorb = false
|
||||
if(health < myCurrentHealAbsorb) then
|
||||
overHealAbsorb = true
|
||||
myCurrentHealAbsorb = health
|
||||
end
|
||||
|
||||
if(health - myCurrentHealAbsorb + allIncomingHeal > maxHealth * hp.maxOverflow) then
|
||||
allIncomingHeal = maxHealth * hp.maxOverflow - health + myCurrentHealAbsorb
|
||||
end
|
||||
|
||||
local otherIncomingHeal = 0
|
||||
if(allIncomingHeal < myIncomingHeal) then
|
||||
myIncomingHeal = allIncomingHeal
|
||||
else
|
||||
otherIncomingHeal = allIncomingHeal - myIncomingHeal
|
||||
end
|
||||
|
||||
local overAbsorb = false
|
||||
if(health - myCurrentHealAbsorb + allIncomingHeal + totalAbsorb >= maxHealth or health + totalAbsorb >= maxHealth) then
|
||||
if(totalAbsorb > 0) then
|
||||
overAbsorb = true
|
||||
end
|
||||
|
||||
|
||||
if(allIncomingHeal > myCurrentHealAbsorb) then
|
||||
totalAbsorb = max(0, maxHealth - (health - myCurrentHealAbsorb + allIncomingHeal))
|
||||
else
|
||||
totalAbsorb = max(0, maxHealth - health)
|
||||
end
|
||||
end
|
||||
|
||||
if(myCurrentHealAbsorb > allIncomingHeal) then
|
||||
myCurrentHealAbsorb = myCurrentHealAbsorb - allIncomingHeal
|
||||
else
|
||||
myCurrentHealAbsorb = 0
|
||||
end
|
||||
|
||||
if(hp.myBar) then
|
||||
hp.myBar:SetMinMaxValues(0, maxHealth)
|
||||
hp.myBar:SetValue(myIncomingHeal)
|
||||
hp.myBar:Show()
|
||||
end
|
||||
|
||||
if(hp.otherBar) then
|
||||
hp.otherBar:SetMinMaxValues(0, maxHealth)
|
||||
hp.otherBar:SetValue(otherIncomingHeal)
|
||||
hp.otherBar:Show()
|
||||
end
|
||||
|
||||
if(hp.absorbBar) then
|
||||
hp.absorbBar:SetMinMaxValues(0, maxHealth)
|
||||
hp.absorbBar:SetValue(totalAbsorb)
|
||||
hp.absorbBar:Show()
|
||||
end
|
||||
|
||||
if(hp.healAbsorbBar) then
|
||||
hp.healAbsorbBar:SetMinMaxValues(0, maxHealth)
|
||||
hp.healAbsorbBar:SetValue(myCurrentHealAbsorb)
|
||||
hp.healAbsorbBar:Show()
|
||||
end
|
||||
|
||||
if(hp.PostUpdate) then
|
||||
return hp:PostUpdate(unit, myIncomingHeal, allIncomingHeal, totalAbsorb, myCurrentHealAbsorb)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
return (self.HealPrediction.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local hp = self.HealPrediction
|
||||
if(hp) then
|
||||
hp.__owner = self
|
||||
hp.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_HEAL_PREDICTION', Path)
|
||||
self:RegisterEvent('UNIT_MAXHEALTH', Path)
|
||||
if(hp.frequentUpdates) then
|
||||
self:RegisterEvent('UNIT_HEALTH_FREQUENT', Path)
|
||||
else
|
||||
self:RegisterEvent('UNIT_HEALTH', Path)
|
||||
end
|
||||
self:RegisterEvent('UNIT_ABSORB_AMOUNT_CHANGED', Path)
|
||||
self:RegisterEvent('UNIT_HEAL_ABSORB_AMOUNT_CHANGED', Path)
|
||||
|
||||
if(not hp.maxOverflow) then
|
||||
hp.maxOverflow = 1.05
|
||||
end
|
||||
|
||||
if(hp.myBar) then
|
||||
if(hp.myBar:IsObjectType'StatusBar' and not hp.myBar:GetStatusBarTexture()) then
|
||||
hp.myBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
hp.myBar:Show()
|
||||
end
|
||||
if(hp.otherBar) then
|
||||
if(hp.otherBar:IsObjectType'StatusBar' and not hp.otherBar:GetStatusBarTexture()) then
|
||||
hp.otherBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
hp.otherBar:Show()
|
||||
end
|
||||
if(hp.absorbBar) then
|
||||
if(hp.absorbBar:IsObjectType'StatusBar' and not hp.absorbBar:GetStatusBarTexture()) then
|
||||
hp.absorbBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
hp.absorbBar:Show()
|
||||
end
|
||||
if(hp.healAbsorbBar) then
|
||||
if(hp.healAbsorbBar:IsObjectType'StatusBar' and not hp.healAbsorbBar:GetStatusBarTexture()) then
|
||||
hp.healAbsorbBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
|
||||
hp.healAbsorbBar:Show()
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local hp = self.HealPrediction
|
||||
if(hp) then
|
||||
if(hp.myBar) then
|
||||
hp.myBar:Hide()
|
||||
end
|
||||
if(hp.otherBar) then
|
||||
hp.otherBar:Hide()
|
||||
end
|
||||
if(hp.absorbBar) then
|
||||
hp.absorbBar:Hide()
|
||||
end
|
||||
if(hp.healAbsorbBar) then
|
||||
hp.healAbsorbBar:Hide()
|
||||
end
|
||||
|
||||
self:UnregisterEvent('UNIT_HEAL_PREDICTION', Path)
|
||||
self:UnregisterEvent('UNIT_MAXHEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_HEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_HEALTH_FREQUENT', Path)
|
||||
self:UnregisterEvent('UNIT_ABSORB_AMOUNT_CHANGED', Path)
|
||||
self:UnregisterEvent('UNIT_HEAL_ABSORB_AMOUNT_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('HealPrediction', Path, Enable, Disable)
|
||||
215
Libraries/oUF/elements/health.lua
Normal file
215
Libraries/oUF/elements/health.lua
Normal file
@@ -0,0 +1,215 @@
|
||||
--[[ Element: Health Bar
|
||||
|
||||
Handles updating of `self.Health` based on the units health.
|
||||
|
||||
Widget
|
||||
|
||||
Health - A StatusBar used to represent current unit health.
|
||||
|
||||
Sub-Widgets
|
||||
|
||||
.bg - A Texture which functions as a background. It will inherit the color of
|
||||
the main StatusBar.
|
||||
|
||||
Notes
|
||||
|
||||
The default StatusBar texture will be applied if the UI widget doesn't have a
|
||||
status bar texture or color defined.
|
||||
|
||||
Options
|
||||
|
||||
The following options are listed by priority. The first check that returns
|
||||
true decides the color of the bar.
|
||||
|
||||
.colorTapping - Use `self.colors.tapping` to color the bar if the unit
|
||||
isn't tapped by the player.
|
||||
.colorDisconnected - Use `self.colors.disconnected` to color the bar if the
|
||||
unit is offline.
|
||||
.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).
|
||||
.colorClassNPC - Use `self.colors.class[class]` to color the bar if the
|
||||
unit is a NPC.
|
||||
.colorClassPet - Use `self.colors.class[class]` to color the bar if the
|
||||
unit is player controlled, but not a player.
|
||||
.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).
|
||||
.colorSmooth - Use `self.colors.smooth` to color the bar with a smooth
|
||||
gradient based on the player's current health percentage.
|
||||
.colorHealth - Use `self.colors.health` to color the bar. This flag is
|
||||
used to reset the bar color back to default if none of the
|
||||
above conditions are met.
|
||||
|
||||
Sub-Widgets Options
|
||||
|
||||
.multiplier - Defines a multiplier, which is used to tint the background based
|
||||
on the main widgets R, G and B values. Defaults to 1 if not
|
||||
present.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local Health = CreateFrame("StatusBar", nil, self)
|
||||
Health:Height(20)
|
||||
Health:SetPoint('TOP')
|
||||
Health:SetPoint('LEFT')
|
||||
Health:SetPoint('RIGHT')
|
||||
|
||||
-- Add a background
|
||||
local Background = Health:CreateTexture(nil, 'BACKGROUND')
|
||||
Background:SetAllPoints(Health)
|
||||
Background:SetTexture(1, 1, 1, .5)
|
||||
|
||||
-- Options
|
||||
Health.frequentUpdates = true
|
||||
Health.colorTapping = true
|
||||
Health.colorDisconnected = true
|
||||
Health.colorClass = true
|
||||
Health.colorReaction = true
|
||||
Health.colorHealth = true
|
||||
|
||||
-- Make the background darker.
|
||||
Background.multiplier = .5
|
||||
|
||||
-- Register it with oUF
|
||||
self.Health = Health
|
||||
self.Health.bg = Background
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local updateFrequentUpdates
|
||||
|
||||
oUF.colors.health = {49/255, 207/255, 37/255}
|
||||
|
||||
local Update = function(self, event, unit)
|
||||
if(not unit or self.unit ~= unit) then return end
|
||||
local health = self.Health
|
||||
|
||||
if(health.PreUpdate) then health:PreUpdate(unit) end
|
||||
|
||||
local min, max = UnitHealth(unit), UnitHealthMax(unit)
|
||||
local disconnected = not UnitIsConnected(unit)
|
||||
health:SetMinMaxValues(0, max)
|
||||
|
||||
if(disconnected) then
|
||||
health:SetValue(max)
|
||||
else
|
||||
health:SetValue(min)
|
||||
end
|
||||
|
||||
health.disconnected = disconnected
|
||||
|
||||
if health.frequentUpdates ~= health.__frequentUpdates then
|
||||
health.__frequentUpdates = health.frequentUpdates
|
||||
updateFrequentUpdates(self)
|
||||
end
|
||||
|
||||
local r, g, b, t
|
||||
if(health.colorTapping and not UnitPlayerControlled(unit) and UnitIsTapDenied(unit)) then
|
||||
t = self.colors.tapped
|
||||
elseif(health.colorDisconnected and not UnitIsConnected(unit)) then
|
||||
t = self.colors.disconnected
|
||||
elseif(health.colorClass and UnitIsPlayer(unit)) or
|
||||
(health.colorClassNPC and not UnitIsPlayer(unit)) or
|
||||
(health.colorClassPet and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then
|
||||
local _, class = UnitClass(unit)
|
||||
t = self.colors.class[class]
|
||||
elseif(health.colorReaction and UnitReaction(unit, 'player')) then
|
||||
t = self.colors.reaction[UnitReaction(unit, "player")]
|
||||
elseif(health.colorSmooth) then
|
||||
r, g, b = self.ColorGradient(min, max, unpack(health.smoothGradient or self.colors.smooth))
|
||||
elseif(health.colorHealth) then
|
||||
t = self.colors.health
|
||||
end
|
||||
|
||||
if(t) then
|
||||
r, g, b = t[1], t[2], t[3]
|
||||
end
|
||||
|
||||
if(b) then
|
||||
health:SetStatusBarColor(r, g, b)
|
||||
|
||||
local bg = health.bg
|
||||
if(bg) then local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
end
|
||||
|
||||
if(health.PostUpdate) then
|
||||
return health:PostUpdate(unit, min, max)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.Health.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
function updateFrequentUpdates(self)
|
||||
local health = self.Health
|
||||
if health.frequentUpdates and not self:IsEventRegistered("UNIT_HEALTH_FREQUENT") then
|
||||
if GetCVarBool("predictedHealth") ~= true then
|
||||
SetCVar("predictedHealth", "1")
|
||||
end
|
||||
|
||||
self:RegisterEvent('UNIT_HEALTH_FREQUENT', Path)
|
||||
|
||||
if self:IsEventRegistered("UNIT_HEALTH") then
|
||||
self:UnregisterEvent("UNIT_HEALTH", Path)
|
||||
end
|
||||
elseif not self:IsEventRegistered("UNIT_HEALTH") then
|
||||
self:RegisterEvent('UNIT_HEALTH', Path)
|
||||
|
||||
if self:IsEventRegistered("UNIT_HEALTH_FREQUENT") then
|
||||
self:UnregisterEvent("UNIT_HEALTH_FREQUENT", Path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
local health = self.Health
|
||||
if(health) then
|
||||
health.__owner = self
|
||||
health.ForceUpdate = ForceUpdate
|
||||
health.__frequentUpdates = health.frequentUpdates
|
||||
updateFrequentUpdates(self)
|
||||
|
||||
self:RegisterEvent("UNIT_MAXHEALTH", Path)
|
||||
self:RegisterEvent('UNIT_CONNECTION', Path)
|
||||
|
||||
-- For tapping.
|
||||
self:RegisterEvent('UNIT_FACTION', Path)
|
||||
|
||||
if(health:IsObjectType'StatusBar' and not health:GetStatusBarTexture()) then
|
||||
health:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]]
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local health = self.Health
|
||||
if(health) then
|
||||
health:Hide()
|
||||
self:UnregisterEvent('UNIT_HEALTH_FREQUENT', Path)
|
||||
self:UnregisterEvent('UNIT_HEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_MAXHEALTH', Path)
|
||||
self:UnregisterEvent('UNIT_CONNECTION', Path)
|
||||
|
||||
self:UnregisterEvent('UNIT_FACTION', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Health', Path, Enable, Disable)
|
||||
87
Libraries/oUF/elements/leader.lua
Normal file
87
Libraries/oUF/elements/leader.lua
Normal file
@@ -0,0 +1,87 @@
|
||||
--[[ Element: Leader Icon
|
||||
|
||||
Toggles visibility based on the units leader status.
|
||||
|
||||
Widget
|
||||
|
||||
Leader - Any UI widget.
|
||||
|
||||
Notes
|
||||
|
||||
The default leader icon will be applied if the UI widget is a texture and
|
||||
doesn't have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local Leader = self:CreateTexture(nil, "OVERLAY")
|
||||
Leader:SetSize(16, 16)
|
||||
Leader:SetPoint("BOTTOM", self, "TOP")
|
||||
|
||||
-- Register it with oUF
|
||||
self.Leader = Leadera
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event)
|
||||
local leader = self.Leader
|
||||
if(leader.PreUpdate) then
|
||||
leader:PreUpdate()
|
||||
end
|
||||
|
||||
local unit = self.unit
|
||||
local isLeader = (UnitInParty(unit) or UnitInRaid(unit)) and UnitIsGroupLeader(unit)
|
||||
if(isLeader) then
|
||||
leader:Show()
|
||||
else
|
||||
leader:Hide()
|
||||
end
|
||||
|
||||
if(leader.PostUpdate) then
|
||||
return leader:PostUpdate(isLeader)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.Leader.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local leader = self.Leader
|
||||
if(leader) then
|
||||
leader.__owner = self
|
||||
leader.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent("PARTY_LEADER_CHANGED", Path, true)
|
||||
self:RegisterEvent("GROUP_ROSTER_UPDATE", Path, true)
|
||||
|
||||
if(leader:IsObjectType"Texture" and not leader:GetTexture()) then
|
||||
leader:SetTexture[[Interface\GroupFrame\UI-Group-LeaderIcon]]
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local leader = self.Leader
|
||||
if(leader) then
|
||||
leader:Hide()
|
||||
self:UnregisterEvent("PARTY_LEADER_CHANGED", Path)
|
||||
self:UnregisterEvent("GROUP_ROSTER_UPDATE", Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Leader', Path, Enable, Disable)
|
||||
94
Libraries/oUF/elements/lfdrole.lua
Normal file
94
Libraries/oUF/elements/lfdrole.lua
Normal file
@@ -0,0 +1,94 @@
|
||||
--[[ Element: LFD Role Icon
|
||||
|
||||
Toggles visibility of the LFD role icon based upon the units current dungeon
|
||||
role.
|
||||
|
||||
Widget
|
||||
|
||||
LFDRole - A Texture containing the LFD role icons at specific locations. Look
|
||||
at the default LFD role icon texture for an example of this.
|
||||
Alternatively you can look at the return values of
|
||||
GetTexCoordsForRoleSmallCircle(role).
|
||||
|
||||
Notes
|
||||
|
||||
The default LFD role texture will be applied if the UI widget is a texture and
|
||||
doesn't have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local LFDRole = self:CreateTexture(nil, "OVERLAY")
|
||||
LFDRole:SetSize(16, 16)
|
||||
LFDRole:SetPoint("LEFT", self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.LFDRole = LFDRole
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event)
|
||||
local lfdrole = self.LFDRole
|
||||
if(lfdrole.PreUpdate) then
|
||||
lfdrole:PreUpdate()
|
||||
end
|
||||
|
||||
local role = UnitGroupRolesAssigned(self.unit)
|
||||
if(role == 'TANK' or role == 'HEALER' or role == 'DAMAGER') then
|
||||
lfdrole:SetTexCoord(GetTexCoordsForRoleSmallCircle(role))
|
||||
lfdrole:Show()
|
||||
else
|
||||
lfdrole:Hide()
|
||||
end
|
||||
|
||||
if(lfdrole.PostUpdate) then
|
||||
return lfdrole:PostUpdate(role)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.LFDRole.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local lfdrole = self.LFDRole
|
||||
if(lfdrole) then
|
||||
lfdrole.__owner = self
|
||||
lfdrole.ForceUpdate = ForceUpdate
|
||||
|
||||
if(self.unit == "player") then
|
||||
self:RegisterEvent("PLAYER_ROLES_ASSIGNED", Path, true)
|
||||
else
|
||||
self:RegisterEvent("GROUP_ROSTER_UPDATE", Path, true)
|
||||
end
|
||||
|
||||
if(lfdrole:IsObjectType"Texture" and not lfdrole:GetTexture()) then
|
||||
lfdrole:SetTexture[[Interface\LFGFrame\UI-LFG-ICON-PORTRAITROLES]]
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local lfdrole = self.LFDRole
|
||||
if(lfdrole) then
|
||||
lfdrole:Hide()
|
||||
self:UnregisterEvent("PLAYER_ROLES_ASSIGNED", Path)
|
||||
self:UnregisterEvent("GROUP_ROSTER_UPDATE", Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('LFDRole', Path, Enable, Disable)
|
||||
106
Libraries/oUF/elements/masterlooter.lua
Normal file
106
Libraries/oUF/elements/masterlooter.lua
Normal file
@@ -0,0 +1,106 @@
|
||||
--[[ Element: Master Looter Icon
|
||||
|
||||
Toggles visibility of the master looter icon.
|
||||
|
||||
Widget
|
||||
|
||||
MasterLooter - Any UI widget.
|
||||
|
||||
Notes
|
||||
|
||||
The default master looter icon will be applied if the UI widget is a texture
|
||||
and doesn't have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local MasterLooter = self:CreateTexture(nil, 'OVERLAY')
|
||||
MasterLooter:SetSize(16, 16)
|
||||
MasterLooter:SetPoint('TOPRIGHT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.MasterLooter = MasterLooter
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event)
|
||||
local unit = self.unit
|
||||
local masterlooter = self.MasterLooter
|
||||
if(not (UnitInParty(unit) or UnitInRaid(unit))) then
|
||||
return masterlooter:Hide()
|
||||
end
|
||||
|
||||
if(masterlooter.PreUpdate) then
|
||||
masterlooter:PreUpdate()
|
||||
end
|
||||
|
||||
local method, pid, rid = GetLootMethod()
|
||||
if(method == 'master') then
|
||||
local mlUnit
|
||||
if(pid) then
|
||||
if(pid == 0) then
|
||||
mlUnit = 'player'
|
||||
else
|
||||
mlUnit = 'party'..pid
|
||||
end
|
||||
elseif(rid) then
|
||||
mlUnit = 'raid'..rid
|
||||
end
|
||||
|
||||
if(unit and mlUnit and UnitIsUnit(unit, mlUnit)) then
|
||||
masterlooter:Show()
|
||||
elseif(masterlooter:IsShown()) then
|
||||
masterlooter:Hide()
|
||||
end
|
||||
else
|
||||
masterlooter:Hide()
|
||||
end
|
||||
|
||||
if(masterlooter.PostUpdate) then
|
||||
return masterlooter:PostUpdate(masterlooter:IsShown())
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.MasterLooter.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local function Enable(self, unit)
|
||||
local masterlooter = self.MasterLooter
|
||||
if(masterlooter) then
|
||||
masterlooter.__owner = self
|
||||
masterlooter.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('PARTY_LOOT_METHOD_CHANGED', Path, true)
|
||||
self:RegisterEvent('GROUP_ROSTER_UPDATE', Path, true)
|
||||
|
||||
if(masterlooter:IsObjectType('Texture') and not masterlooter:GetTexture()) then
|
||||
masterlooter:SetTexture([[Interface\GroupFrame\UI-Group-MasterLooter]])
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
if(self.MasterLooter) then
|
||||
self.MasterLooter:Hide()
|
||||
self:UnregisterEvent('PARTY_LOOT_METHOD_CHANGED', Path)
|
||||
self:UnregisterEvent('GROUP_ROSTER_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('MasterLooter', Path, Enable, Disable)
|
||||
85
Libraries/oUF/elements/picon.lua
Normal file
85
Libraries/oUF/elements/picon.lua
Normal file
@@ -0,0 +1,85 @@
|
||||
--[[ Element: Phasing Icon
|
||||
|
||||
Toggles visibility of the phase icon based on the units phasing compared to the
|
||||
player.
|
||||
|
||||
Widget
|
||||
|
||||
PhaseIcon - Any UI widget.
|
||||
|
||||
Notes
|
||||
|
||||
The default phasing icon will be used if the UI widget is a texture and doesn't
|
||||
have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local PhaseIcon = self:CreateTexture(nil, 'OVERLAY')
|
||||
PhaseIcon:SetSize(16, 16)
|
||||
PhaseIcon:SetPoint('TOPLEFT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.PhaseIcon = PhaseIcon
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event)
|
||||
local picon = self.PhaseIcon
|
||||
if(picon.PreUpdate) then
|
||||
picon:PreUpdate()
|
||||
end
|
||||
|
||||
local inPhase = UnitInPhase(self.unit)
|
||||
if(inPhase) then
|
||||
picon:Hide()
|
||||
else
|
||||
picon:Show()
|
||||
end
|
||||
|
||||
if(picon.PostUpdate) then
|
||||
return picon:PostUpdate(inPhase)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.PhaseIcon.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local picon = self.PhaseIcon
|
||||
if(picon) then
|
||||
picon.__owner = self
|
||||
picon.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_PHASE', Path, true)
|
||||
|
||||
if(picon:IsObjectType'Texture' and not picon:GetTexture()) then
|
||||
picon:SetTexture[[Interface\TargetingFrame\UI-PhasingIcon]]
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local picon = self.PhaseIcon
|
||||
if(picon) then
|
||||
picon:Hide()
|
||||
self:UnregisterEvent('UNIT_PHASE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('PhaseIcon', Path, Enable, Disable)
|
||||
122
Libraries/oUF/elements/portraits.lua
Normal file
122
Libraries/oUF/elements/portraits.lua
Normal file
@@ -0,0 +1,122 @@
|
||||
--[[ Element: Portraits
|
||||
|
||||
Handles updating of the unit's portrait.
|
||||
|
||||
Widget
|
||||
|
||||
Portrait - A PlayerModel or Texture used to represent the unit's portrait.
|
||||
|
||||
Notes
|
||||
|
||||
The quest delivery question mark will be used instead of the unit's model when
|
||||
the client doesn't have the model information for the unit.
|
||||
|
||||
Examples
|
||||
|
||||
-- 3D Portrait
|
||||
-- Position and size
|
||||
local Portrait = CreateFrame('PlayerModel', nil, self)
|
||||
Portrait:SetSize(32, 32)
|
||||
Portrait:SetPoint('RIGHT', self, 'LEFT')
|
||||
|
||||
-- Register it with oUF
|
||||
self.Portrait = Portrait
|
||||
|
||||
-- 2D Portrait
|
||||
local Portrait = self:CreateTexture(nil, 'OVERLAY')
|
||||
Portrait:SetSize(32, 32)
|
||||
Portrait:SetPoint('RIGHT', self, 'LEFT')
|
||||
|
||||
-- Register it with oUF
|
||||
self.Portrait = Portrait
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event, unit)
|
||||
if(not unit or not UnitIsUnit(self.unit, unit)) then return end
|
||||
|
||||
local portrait = self.Portrait
|
||||
local modelUpdated = false
|
||||
if(portrait.PreUpdate) then portrait:PreUpdate(unit) end
|
||||
|
||||
if(portrait:IsObjectType'Model') then
|
||||
local guid = UnitGUID(unit)
|
||||
if(not UnitExists(unit) or not UnitIsConnected(unit) or not UnitIsVisible(unit)) then
|
||||
portrait:SetCamDistanceScale(0.25)
|
||||
portrait:SetPortraitZoom(0)
|
||||
portrait:SetPosition(0,0,0.5)
|
||||
portrait:ClearModel()
|
||||
portrait:SetModel('interface\\buttons\\talktomequestionmark.m2')
|
||||
portrait.guid = nil
|
||||
modelUpdated = true
|
||||
elseif(portrait.guid ~= guid or event == 'UNIT_MODEL_CHANGED') then
|
||||
portrait:SetCamDistanceScale(1)
|
||||
portrait:SetPortraitZoom(1)
|
||||
portrait:SetPosition(0,0,0)
|
||||
portrait:ClearModel()
|
||||
portrait:SetUnit(unit)
|
||||
portrait.guid = guid
|
||||
modelUpdated = true
|
||||
end
|
||||
else
|
||||
SetPortraitTexture(portrait, unit)
|
||||
end
|
||||
|
||||
if(portrait.PostUpdate) then
|
||||
return portrait:PostUpdate(unit, event, modelUpdated)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.Portrait.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
local portrait = self.Portrait
|
||||
if(portrait) then
|
||||
portrait:Show()
|
||||
portrait.__owner = self
|
||||
portrait.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent("UNIT_PORTRAIT_UPDATE", Path)
|
||||
self:RegisterEvent("UNIT_MODEL_CHANGED", Path)
|
||||
self:RegisterEvent('UNIT_CONNECTION', Path)
|
||||
|
||||
-- The quest log uses PARTY_MEMBER_{ENABLE,DISABLE} to handle updating of
|
||||
-- party members overlapping quests. This will probably be enough to handle
|
||||
-- model updating.
|
||||
--
|
||||
-- DISABLE isn't used as it fires when we most likely don't have the
|
||||
-- information we want.
|
||||
if(unit == 'party') then
|
||||
self:RegisterEvent('PARTY_MEMBER_ENABLE', Path)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local portrait = self.Portrait
|
||||
if(portrait) then
|
||||
portrait:Hide()
|
||||
self:UnregisterEvent("UNIT_PORTRAIT_UPDATE", Path)
|
||||
self:UnregisterEvent("UNIT_MODEL_CHANGED", Path)
|
||||
self:UnregisterEvent('PARTY_MEMBER_ENABLE', Path)
|
||||
self:UnregisterEvent('UNIT_CONNECTION', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Portrait', Path, Enable, Disable)
|
||||
318
Libraries/oUF/elements/power.lua
Normal file
318
Libraries/oUF/elements/power.lua
Normal file
@@ -0,0 +1,318 @@
|
||||
--[[ Element: Power Bar
|
||||
|
||||
Handles updating of `self.Power` based upon the units power.
|
||||
|
||||
Widget
|
||||
|
||||
Power - A StatusBar used to represent mana.
|
||||
|
||||
Sub-Widgets
|
||||
|
||||
.bg - A Texture which functions as a background. It will inherit the color of
|
||||
the main StatusBar.
|
||||
|
||||
Notes
|
||||
|
||||
The default StatusBar texture will be applied if the UI widget doesn't have a
|
||||
status bar texture or color defined.
|
||||
|
||||
Options
|
||||
|
||||
.displayAltPower - Use this to let the widget display alternate power if the
|
||||
unit has one. If no alternate power the display will fall
|
||||
back to primary power.
|
||||
.useAtlas - Use this to let the widget use an atlas for its texture if
|
||||
`.atlas` is defined on the widget or an atlas is present in
|
||||
`self.colors.power` for the appropriate power type.
|
||||
.atlas - A custom atlas
|
||||
|
||||
The following options are listed by priority. The first check that returns
|
||||
true decides the color of the bar.
|
||||
|
||||
.colorTapping - Use `self.colors.tapping` to color the bar if the unit
|
||||
isn't tapped by the player.
|
||||
.colorDisconnected - Use `self.colors.disconnected` to color the bar if the
|
||||
unit is offline.
|
||||
.altPowerColor - A table containing the RGB values to use for a fixed
|
||||
color if the alt power bar is being displayed instead
|
||||
.colorPower - Use `self.colors.power[token]` to color the bar based on
|
||||
the unit's power type. This method will fall-back to
|
||||
`:GetAlternativeColor()` if it can't find a color matching
|
||||
the token. If this function isn't defined, then it will
|
||||
attempt to color based upon the alternative power colors
|
||||
returned by [UnitPowerType](http://wowprogramming.com/docs/api/UnitPowerType).
|
||||
Finally, if these aren't defined, then it will attempt to
|
||||
color the bar based upon `self.colors.power[type]`.
|
||||
.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).
|
||||
.colorClassNPC - Use `self.colors.class[class]` to color the bar if the
|
||||
unit is a NPC.
|
||||
.colorClassPet - Use `self.colors.class[class]` to color the bar if the
|
||||
unit is player controlled, but not a player.
|
||||
.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).
|
||||
.colorSmooth - Use `self.colors.smooth` to color the bar with a smooth
|
||||
gradient based on the player's current health percentage.
|
||||
|
||||
Sub-Widget Options
|
||||
|
||||
.multiplier - Defines a multiplier, which is used to tint the background based
|
||||
on the main widgets R, G and B values. Defaults to 1 if not
|
||||
present.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local Power = CreateFrame("StatusBar", nil, self)
|
||||
Power:SetHeight(20)
|
||||
Power:SetPoint('BOTTOM')
|
||||
Power:SetPoint('LEFT')
|
||||
Power:SetPoint('RIGHT')
|
||||
|
||||
-- Add a background
|
||||
local Background = Power:CreateTexture(nil, 'BACKGROUND')
|
||||
Background:SetAllPoints(Power)
|
||||
Background:SetTexture(1, 1, 1, .5)
|
||||
|
||||
-- Options
|
||||
Power.frequentUpdates = true
|
||||
Power.colorTapping = true
|
||||
Power.colorDisconnected = true
|
||||
Power.colorPower = true
|
||||
Power.colorClass = true
|
||||
Power.colorReaction = true
|
||||
|
||||
-- Make the background darker.
|
||||
Background.multiplier = .5
|
||||
|
||||
-- Register it with oUF
|
||||
self.Power = Power
|
||||
self.Power.bg = Background
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local updateFrequentUpdates
|
||||
oUF.colors.power = {}
|
||||
for power, color in next, PowerBarColor do
|
||||
if (type(power) == "string") then
|
||||
if(type(select(2, next(color))) == 'table') then
|
||||
oUF.colors.power[power] = {}
|
||||
|
||||
for index, color in next, color do
|
||||
oUF.colors.power[power][index] = {color.r, color.g, color.b}
|
||||
end
|
||||
else
|
||||
oUF.colors.power[power] = {color.r, color.g, color.b, atlas = color.atlas}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- sourced from FrameXML/Constants.lua
|
||||
oUF.colors.power[0] = oUF.colors.power.MANA
|
||||
oUF.colors.power[1] = oUF.colors.power.RAGE
|
||||
oUF.colors.power[2] = oUF.colors.power.FOCUS
|
||||
oUF.colors.power[3] = oUF.colors.power.ENERGY
|
||||
oUF.colors.power[4] = oUF.colors.power.COMBO_POINTS
|
||||
oUF.colors.power[5] = oUF.colors.power.RUNES
|
||||
oUF.colors.power[6] = oUF.colors.power.RUNIC_POWER
|
||||
oUF.colors.power[7] = oUF.colors.power.SOUL_SHARDS
|
||||
oUF.colors.power[8] = oUF.colors.power.LUNAR_POWER
|
||||
oUF.colors.power[9] = oUF.colors.power.HOLY_POWER
|
||||
oUF.colors.power[11] = oUF.colors.power.MAELSTROM
|
||||
oUF.colors.power[12] = oUF.colors.power.CHI
|
||||
oUF.colors.power[13] = oUF.colors.power.INSANITY
|
||||
oUF.colors.power[16] = oUF.colors.power.ARCANE_CHARGES
|
||||
oUF.colors.power[17] = oUF.colors.power.FURY
|
||||
oUF.colors.power[18] = oUF.colors.power.PAIN
|
||||
|
||||
local GetDisplayPower = function(unit)
|
||||
if not unit then return; end
|
||||
local _, min, _, _, _, _, showOnRaid = UnitAlternatePowerInfo(unit)
|
||||
if(showOnRaid) then
|
||||
return ALTERNATE_POWER_INDEX, min
|
||||
end
|
||||
end
|
||||
|
||||
local Update = function(self, event, unit)
|
||||
if(self.unit ~= unit) or not unit then return end
|
||||
local power = self.Power
|
||||
|
||||
if(power.PreUpdate) then power:PreUpdate(unit) end
|
||||
|
||||
local displayType, min
|
||||
if power.displayAltPower then
|
||||
displayType, min = GetDisplayPower(unit)
|
||||
end
|
||||
local cur, max = UnitPower(unit, displayType), UnitPowerMax(unit, displayType)
|
||||
local disconnected = not UnitIsConnected(unit)
|
||||
local tapped = not UnitPlayerControlled(unit) and UnitIsTapDenied(unit)
|
||||
|
||||
if max == 0 then
|
||||
max = 1
|
||||
end
|
||||
|
||||
power:SetMinMaxValues(min or 0, max)
|
||||
|
||||
if(disconnected) then
|
||||
power:SetValue(max)
|
||||
else
|
||||
power:SetValue(cur)
|
||||
end
|
||||
|
||||
power.disconnected = disconnected
|
||||
power.tapped = tapped
|
||||
|
||||
if power.frequentUpdates ~= power.__frequentUpdates then
|
||||
power.__frequentUpdates = power.frequentUpdates
|
||||
updateFrequentUpdates(self)
|
||||
end
|
||||
|
||||
local ptype, ptoken, altR, altG, altB = UnitPowerType(unit)
|
||||
local r, g, b, t
|
||||
|
||||
if(power.colorTapping and not UnitPlayerControlled(unit) and UnitIsTapDenied(unit)) then
|
||||
t = self.colors.tapped
|
||||
elseif(power.colorDisconnected and disconnected) then
|
||||
t = self.colors.disconnected
|
||||
elseif(displayType == ALTERNATE_POWER_INDEX and power.altPowerColor) then
|
||||
t = power.altPowerColor
|
||||
elseif(power.colorPower) then
|
||||
t = self.colors.power[ptoken]
|
||||
if(not t) then
|
||||
if(power.GetAlternativeColor) then
|
||||
r, g, b = power:GetAlternativeColor(unit, ptype, ptoken, altR, altG, altB)
|
||||
elseif(altR) then
|
||||
-- As of 7.0.3, altR, altG, altB may be in 0-1 or 0-255 range.
|
||||
if(altR > 1) or (altG > 1) or (altB > 1) then
|
||||
r, g, b = altR / 255, altG / 255, altB / 255
|
||||
else
|
||||
r, g, b = altR, altG, altB
|
||||
end
|
||||
else
|
||||
t = self.colors.power[ptype]
|
||||
end
|
||||
end
|
||||
elseif(power.colorClass and UnitIsPlayer(unit)) or
|
||||
(power.colorClassNPC and not UnitIsPlayer(unit)) or
|
||||
(power.colorClassPet and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then
|
||||
local _, class = UnitClass(unit)
|
||||
t = self.colors.class[class]
|
||||
elseif(power.colorReaction and UnitReaction(unit, 'player')) then
|
||||
t = self.colors.reaction[UnitReaction(unit, "player")]
|
||||
elseif(power.colorSmooth) then
|
||||
local adjust = 0 - (min or 0)
|
||||
r, g, b = self.ColorGradient(cur + adjust, max + adjust, unpack(power.smoothGradient or self.colors.smooth))
|
||||
end
|
||||
|
||||
if(t) then
|
||||
r, g, b = t[1], t[2], t[3]
|
||||
end
|
||||
|
||||
t = self.colors.power[ptoken or ptype]
|
||||
local atlas = power.atlas or (t and t.atlas)
|
||||
if(power.useAtlas and atlas and displayType ~= ALTERNATE_POWER_INDEX) then
|
||||
power:SetStatusBarAtlas(atlas)
|
||||
power:SetStatusBarColor(1, 1, 1)
|
||||
if(power.colorTapping or power.colorDisconnected) then
|
||||
t = disconnected and self.colors.disconnected or self.colors.tapped
|
||||
power:GetStatusBarTexture():SetDesaturated(disconnected or tapped)
|
||||
end
|
||||
if(t and b) then
|
||||
r, g, b = t[1], t[2], t[3]
|
||||
end
|
||||
else
|
||||
power:SetStatusBarTexture(power.texture)
|
||||
if(b) then
|
||||
power:SetStatusBarColor(r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local bg = power.bg
|
||||
if(bg and b) then
|
||||
local mu = bg.multiplier or 1
|
||||
bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
|
||||
if(power.PostUpdate) then
|
||||
return power:PostUpdate(unit, cur, max, min, ptoken, ptype)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.Power.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
function updateFrequentUpdates(self)
|
||||
local power = self.Power
|
||||
if power.frequentUpdates and not self:IsEventRegistered('UNIT_POWER_FREQUENT') then
|
||||
self:RegisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
|
||||
if self:IsEventRegistered('UNIT_POWER') then
|
||||
self:UnregisterEvent('UNIT_POWER', Path)
|
||||
end
|
||||
elseif not self:IsEventRegistered('UNIT_POWER') then
|
||||
self:RegisterEvent('UNIT_POWER', Path)
|
||||
|
||||
if self:IsEventRegistered('UNIT_POWER_FREQUENT') then
|
||||
self:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
local power = self.Power
|
||||
if(power) then
|
||||
power.__owner = self
|
||||
power.ForceUpdate = ForceUpdate
|
||||
|
||||
power.__frequentUpdates = power.frequentUpdates
|
||||
updateFrequentUpdates(self)
|
||||
|
||||
self:RegisterEvent('UNIT_POWER_BAR_SHOW', Path)
|
||||
self:RegisterEvent('UNIT_POWER_BAR_HIDE', Path)
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', Path)
|
||||
self:RegisterEvent('UNIT_CONNECTION', Path)
|
||||
self:RegisterEvent('UNIT_MAXPOWER', Path)
|
||||
|
||||
-- For tapping.
|
||||
self:RegisterEvent('UNIT_FACTION', Path)
|
||||
|
||||
if(power:IsObjectType'StatusBar') then
|
||||
power.texture = power:GetStatusBarTexture() and power:GetStatusBarTexture():GetTexture() or [[Interface\TargetingFrame\UI-StatusBar]]
|
||||
power:SetStatusBarTexture(power.texture)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local power = self.Power
|
||||
if(power) then
|
||||
self:UnregisterEvent('UNIT_POWER_FREQUENT', Path)
|
||||
self:UnregisterEvent('UNIT_POWER', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_BAR_SHOW', Path)
|
||||
self:UnregisterEvent('UNIT_POWER_BAR_HIDE', Path)
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', Path)
|
||||
self:UnregisterEvent('UNIT_CONNECTION', Path)
|
||||
self:UnregisterEvent('UNIT_MAXPOWER', Path)
|
||||
self:UnregisterEvent('UNIT_FACTION', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Power', Path, Enable, Disable)
|
||||
169
Libraries/oUF/elements/powerprediction.lua
Normal file
169
Libraries/oUF/elements/powerprediction.lua
Normal file
@@ -0,0 +1,169 @@
|
||||
--[[ Element: Power Prediction Bar
|
||||
Handles updating and visibility of the power prediction status bars.
|
||||
|
||||
Widget
|
||||
|
||||
PowerPrediction - A table containing `mainBar` and `altBar`.
|
||||
|
||||
Sub-Widgets
|
||||
|
||||
mainBar - A StatusBar used to represent power cost of spells, that consume
|
||||
your main power, e.g. mana for mages;
|
||||
altBar - A StatusBar used to represent power cost of spells, that consume
|
||||
your additional power, e.g. mana for balance druids.
|
||||
|
||||
Notes
|
||||
|
||||
The default StatusBar texture will be applied if the UI widget doesn't have a
|
||||
status bar texture.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local mainBar = CreateFrame('StatusBar', nil, self.Power)
|
||||
mainBar:SetReverseFill(true)
|
||||
mainBar:SetPoint('TOP')
|
||||
mainBar:SetPoint('BOTTOM')
|
||||
mainBar:SetPoint('RIGHT', self.Power:GetStatusBarTexture(), 'RIGHT')
|
||||
mainBar:SetWidth(200)
|
||||
|
||||
local altBar = CreateFrame('StatusBar', nil, self.AdditionalPower)
|
||||
altBar:SetReverseFill(true)
|
||||
altBar:SetPoint('TOP')
|
||||
altBar:SetPoint('BOTTOM')
|
||||
altBar:SetPoint('RIGHT', self.AdditionalPower:GetStatusBarTexture(), 'RIGHT')
|
||||
altBar:SetWidth(200)
|
||||
|
||||
-- Register with oUF
|
||||
self.PowerPrediction = {
|
||||
mainBar = mainBar,
|
||||
altBar = altBar
|
||||
}
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local _, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local playerClass = select(2, UnitClass('player'))
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(self.unit ~= unit) then return end
|
||||
|
||||
local pp = self.PowerPrediction
|
||||
|
||||
if(pp.PreUpdate) then
|
||||
pp:PreUpdate(unit)
|
||||
end
|
||||
|
||||
local _, _, _, _, startTime, endTime, _, _, _, spellID = UnitCastingInfo(unit)
|
||||
local mainPowerType = UnitPowerType(unit)
|
||||
local hasAltManaBar = ALT_MANA_BAR_PAIR_DISPLAY_INFO[playerClass] and ALT_MANA_BAR_PAIR_DISPLAY_INFO[playerClass][mainPowerType]
|
||||
local mainCost, altCost = 0, 0
|
||||
|
||||
if(event == 'UNIT_SPELLCAST_START' or startTime ~= endTime) then
|
||||
local costTable = GetSpellPowerCost(spellID)
|
||||
|
||||
for _, costInfo in pairs(costTable) do
|
||||
--[[costInfo content:
|
||||
-- name: string (powerToken)
|
||||
-- type: number (powerType)
|
||||
-- cost: number
|
||||
-- costPercent: number
|
||||
-- costPerSec: number
|
||||
-- minCost: number
|
||||
-- hasRequiredAura: boolean
|
||||
-- requiredAuraID: number
|
||||
]]
|
||||
if(costInfo.type == mainPowerType) then
|
||||
mainCost = costInfo.cost
|
||||
|
||||
break
|
||||
elseif(costInfo.type == ADDITIONAL_POWER_BAR_INDEX) then
|
||||
altCost = costInfo.cost
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(pp.mainBar) then
|
||||
pp.mainBar:SetMinMaxValues(0, UnitPowerMax(unit, mainPowerType))
|
||||
pp.mainBar:SetValue(mainCost)
|
||||
pp.mainBar:Show()
|
||||
end
|
||||
|
||||
if(pp.altBar and hasAltManaBar) then
|
||||
pp.altBar:SetMinMaxValues(0, UnitPowerMax(unit, ADDITIONAL_POWER_BAR_INDEX))
|
||||
pp.altBar:SetValue(altCost)
|
||||
pp.altBar:Show()
|
||||
end
|
||||
|
||||
if(pp.PostUpdate) then
|
||||
return pp:PostUpdate(unit, mainCost, altCost, hasAltManaBar)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
return (self.PowerPrediction.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local pp = self.PowerPrediction
|
||||
|
||||
if(pp) then
|
||||
pp.__owner = self
|
||||
pp.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_SPELLCAST_START', Path)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_STOP', Path)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_FAILED', Path)
|
||||
self:RegisterEvent('UNIT_SPELLCAST_SUCCEEDED', Path)
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', Path)
|
||||
|
||||
if(pp.mainBar) then
|
||||
if(pp.mainBar:IsObjectType('StatusBar') and not pp.mainBar:GetStatusBarTexture()) then
|
||||
pp.mainBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
if(pp.altBar) then
|
||||
if(pp.altBar:IsObjectType('StatusBar') and not pp.altBar:GetStatusBarTexture()) then
|
||||
pp.altBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]])
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local pp = self.PowerPrediction
|
||||
|
||||
if(pp) then
|
||||
if(pp.mainBar) then
|
||||
pp.mainBar:Hide()
|
||||
end
|
||||
|
||||
if(pp.altBar) then
|
||||
pp.altBar:Hide()
|
||||
end
|
||||
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_START', Path)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_STOP', Path)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_FAILED', Path)
|
||||
self:UnregisterEvent('UNIT_SPELLCAST_SUCCEEDED', Path)
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('PowerPrediction', Path, Enable, Disable)
|
||||
160
Libraries/oUF/elements/pvp.lua
Normal file
160
Libraries/oUF/elements/pvp.lua
Normal file
@@ -0,0 +1,160 @@
|
||||
--[[ Element: PvP and Prestige Icons
|
||||
|
||||
Handles updating and visibility of PvP and prestige icons based on unit's PvP
|
||||
status and prestige level.
|
||||
|
||||
Widget
|
||||
|
||||
PvP - A Texture used to display faction, FFA PvP status or prestige icon.
|
||||
|
||||
Sub-Widgets
|
||||
|
||||
Prestige - A Texture used to display prestige background image.
|
||||
|
||||
Notes
|
||||
|
||||
This element updates by changing the texture;
|
||||
`Prestige` texture has to be on a lower sub-layer than `PvP` texture.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local PvP = self:CreateTexture(nil, 'ARTWORK', nil, 1)
|
||||
PvP:SetSize(30, 30)
|
||||
PvP:SetPoint('RIGHT', self, 'LEFT')
|
||||
|
||||
local Prestige = self:CreateTexture(nil, 'ARTWORK')
|
||||
Prestige:SetSize(50, 52)
|
||||
Prestige:SetPoint('CENTER', PvP, 'CENTER')
|
||||
|
||||
-- Register it with oUF
|
||||
self.PvP = PvP
|
||||
self.PvP.Prestige = Prestige
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function Update(self, event, unit)
|
||||
if(unit ~= self.unit) then return end
|
||||
|
||||
local pvp = self.PvP
|
||||
|
||||
if(pvp.PreUpdate) then
|
||||
pvp:PreUpdate(unit)
|
||||
end
|
||||
|
||||
local status
|
||||
local hasPrestige
|
||||
local level = UnitPrestige(unit)
|
||||
local factionGroup = UnitFactionGroup(unit)
|
||||
|
||||
if(UnitIsPVPFreeForAll(unit)) then
|
||||
if(level > 0 and pvp.Prestige) then
|
||||
pvp:SetTexture(GetPrestigeInfo(level))
|
||||
pvp:SetTexCoord(0, 1, 0, 1)
|
||||
|
||||
pvp.Prestige:SetAtlas('honorsystem-portrait-neutral', false)
|
||||
|
||||
hasPrestige = true
|
||||
else
|
||||
pvp:SetTexture('Interface\\TargetingFrame\\UI-PVP-FFA')
|
||||
pvp:SetTexCoord(0, 0.65625, 0, 0.65625)
|
||||
end
|
||||
|
||||
status = 'ffa'
|
||||
elseif(factionGroup and factionGroup ~= 'Neutral' and UnitIsPVP(unit)) then
|
||||
if(UnitIsMercenary(unit)) then
|
||||
if(factionGroup == 'Horde') then
|
||||
factionGroup = 'Alliance'
|
||||
elseif(factionGroup == 'Alliance') then
|
||||
factionGroup = 'Horde'
|
||||
end
|
||||
end
|
||||
|
||||
if(level > 0 and pvp.Prestige) then
|
||||
pvp:SetTexture(GetPrestigeInfo(level))
|
||||
pvp:SetTexCoord(0, 1, 0, 1)
|
||||
|
||||
pvp.Prestige:SetAtlas('honorsystem-portrait-'..factionGroup, false)
|
||||
|
||||
hasPrestige = true
|
||||
else
|
||||
pvp:SetTexture('Interface\\TargetingFrame\\UI-PVP-'..factionGroup)
|
||||
pvp:SetTexCoord(0, 0.65625, 0, 0.65625)
|
||||
end
|
||||
|
||||
status = factionGroup
|
||||
end
|
||||
|
||||
if(status) then
|
||||
pvp:Show()
|
||||
|
||||
if(pvp.Prestige) then
|
||||
if(hasPrestige) then
|
||||
pvp.Prestige:Show()
|
||||
else
|
||||
pvp.Prestige:Hide()
|
||||
end
|
||||
end
|
||||
else
|
||||
pvp:Hide()
|
||||
|
||||
if(pvp.Prestige) then
|
||||
pvp.Prestige:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
if(pvp.PostUpdate) then
|
||||
return pvp:PostUpdate(unit, status, hasPrestige, level)
|
||||
end
|
||||
end
|
||||
|
||||
local function Path(self, ...)
|
||||
return (self.PvP.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local function ForceUpdate(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local function Enable(self)
|
||||
local pvp = self.PvP
|
||||
|
||||
if(pvp) then
|
||||
pvp.__owner = self
|
||||
pvp.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_FACTION', Path)
|
||||
|
||||
if(pvp.Prestige) then
|
||||
self:RegisterEvent('HONOR_PRESTIGE_UPDATE', Path)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function Disable(self)
|
||||
local pvp = self.PvP
|
||||
|
||||
if(pvp) then
|
||||
pvp:Hide()
|
||||
|
||||
self:UnregisterEvent('UNIT_FACTION', Path)
|
||||
|
||||
if(pvp.Prestige) then
|
||||
pvp.Prestige:Hide()
|
||||
|
||||
self:UnregisterEvent('HONOR_PRESTIGE_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('PvP', Path, Enable, Disable)
|
||||
86
Libraries/oUF/elements/qicon.lua
Normal file
86
Libraries/oUF/elements/qicon.lua
Normal file
@@ -0,0 +1,86 @@
|
||||
--[[ Element: Quest Icon
|
||||
|
||||
Handles updating and toggles visibility based upon the units connection to a
|
||||
quest.
|
||||
|
||||
Widget
|
||||
|
||||
QuestIcon - Any UI widget.
|
||||
|
||||
Notes
|
||||
|
||||
The default quest icon will be used if the UI widget is a texture and doesn't
|
||||
have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local QuestIcon = self:CreateTexture(nil, 'OVERLAY')
|
||||
QuestIcon:SetSize(16, 16)
|
||||
QuestIcon:SetPoint('TOPRIGHT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.QuestIcon = QuestIcon
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event, unit)
|
||||
if(unit ~= self.unit) then return end
|
||||
|
||||
local qicon = self.QuestIcon
|
||||
if(qicon.PreUpdate) then
|
||||
qicon:PreUpdate()
|
||||
end
|
||||
|
||||
local isQuestBoss = UnitIsQuestBoss(unit)
|
||||
if(isQuestBoss) then
|
||||
qicon:Show()
|
||||
else
|
||||
qicon:Hide()
|
||||
end
|
||||
|
||||
if(qicon.PostUpdate) then
|
||||
return qicon:PostUpdate(isQuestBoss)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.QuestIcon.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local qicon = self.QuestIcon
|
||||
if(qicon) then
|
||||
qicon.__owner = self
|
||||
qicon.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('UNIT_CLASSIFICATION_CHANGED', Path)
|
||||
|
||||
if(qicon:IsObjectType'Texture' and not qicon:GetTexture()) then
|
||||
qicon:SetTexture[[Interface\TargetingFrame\PortraitQuestBadge]]
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
if(self.QuestIcon) then
|
||||
self.QuestIcon:Hide()
|
||||
self:UnregisterEvent('UNIT_CLASSIFICATION_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('QuestIcon', Path, Enable, Disable)
|
||||
89
Libraries/oUF/elements/raidrole.lua
Normal file
89
Libraries/oUF/elements/raidrole.lua
Normal file
@@ -0,0 +1,89 @@
|
||||
--[[ Element: Raid Role Icon
|
||||
|
||||
Handles visibility and updating of `self.RaidRole` based upon the units
|
||||
party assignment.
|
||||
|
||||
Widget
|
||||
|
||||
RaidRole - A Texture representing the units party assignment. This is can be
|
||||
main tank, main assist or blank.
|
||||
|
||||
Notes
|
||||
|
||||
This element updates by changing the texture.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local RaidRole = self:CreateTexture(nil, 'OVERLAY')
|
||||
RaidRole:SetSize(16, 16)
|
||||
RaidRole:SetPoint('TOPLEFT')
|
||||
|
||||
-- Register it with oUF
|
||||
self.RaidRole = RaidRole
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event)
|
||||
local unit = self.unit
|
||||
if(not UnitInRaid(unit)) then return end
|
||||
|
||||
local raidrole = self.RaidRole
|
||||
if(raidrole.PreUpdate) then
|
||||
raidrole:PreUpdate()
|
||||
end
|
||||
|
||||
local inVehicle = UnitHasVehicleUI(unit)
|
||||
if(GetPartyAssignment('MAINTANK', unit) and not inVehicle) then
|
||||
raidrole:Show()
|
||||
raidrole:SetTexture[[Interface\GROUPFRAME\UI-GROUP-MAINTANKICON]]
|
||||
elseif(GetPartyAssignment('MAINASSIST', unit) and not inVehicle) then
|
||||
raidrole:Show()
|
||||
raidrole:SetTexture[[Interface\GROUPFRAME\UI-GROUP-MAINASSISTICON]]
|
||||
else
|
||||
raidrole:Hide()
|
||||
end
|
||||
|
||||
if(raidrole.PostUpdate) then
|
||||
return raidrole:PostUpdate(rinfo)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.RaidRole.Override or Update)(self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local raidrole = self.RaidRole
|
||||
|
||||
if(raidrole) then
|
||||
raidrole.__owner = self
|
||||
raidrole.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('GROUP_ROSTER_UPDATE', Path, true)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local raidrole = self.RaidRole
|
||||
|
||||
if(raidrole) then
|
||||
self:UnregisterEvent('GROUP_ROSTER_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('RaidRole', Path, Enable, Disable)
|
||||
250
Libraries/oUF/elements/range.lua
Normal file
250
Libraries/oUF/elements/range.lua
Normal file
@@ -0,0 +1,250 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local _FRAMES = {}
|
||||
local OnRangeFrame
|
||||
|
||||
local UnitIsConnected = UnitIsConnected
|
||||
local tinsert, tremove, twipe = table.insert, table.remove, table.wipe
|
||||
|
||||
local friendlySpells, resSpells, longEnemySpells, enemySpells, petSpells = {}, {}, {}, {}, {}
|
||||
local addSpellRetry = {}
|
||||
|
||||
local SpellRange = LibStub("SpellRange-1.0")
|
||||
|
||||
local function AddSpell(table, spellID)
|
||||
table[#table + 1] = spellID
|
||||
end
|
||||
|
||||
local _,class = UnitClass("player")
|
||||
do
|
||||
if class == "PRIEST" then
|
||||
AddSpell(enemySpells, 585) -- Smite (40 yards)
|
||||
AddSpell(enemySpells, 589) -- Shadow Word: Pain (40 yards)
|
||||
AddSpell(friendlySpells, 2061) -- Flash Heal (40 yards)
|
||||
AddSpell(friendlySpells, 17) -- Power Word: Shield (40 yards)
|
||||
AddSpell(resSpells, 2006) -- Resurrection (40 yards)
|
||||
elseif class == "DRUID" then
|
||||
AddSpell(enemySpells, 8921) -- Moonfire (40 yards, all specs, lvl 3)
|
||||
AddSpell(friendlySpells, 8936) -- Regrowth (40 yards, all specs, lvl 5)
|
||||
AddSpell(resSpells, 50769) -- Revive (40 yards, all specs, lvl 14)
|
||||
elseif class == "PALADIN" then
|
||||
AddSpell(enemySpells, 20271) -- Judgement (30 yards)
|
||||
AddSpell(longEnemySpells, 20473) -- Holy Shock (40 yards)
|
||||
AddSpell(friendlySpells, 19750) -- Flash of Light (40 yards)
|
||||
AddSpell(resSpells, 7328) -- Redemption (40 yards)
|
||||
elseif class == "SHAMAN" then
|
||||
AddSpell(enemySpells, 188196) -- Lightning Bolt (Elemental) (40 yards)
|
||||
AddSpell(enemySpells, 187837) -- Lightning Bolt (Enhancement) (40 yards)
|
||||
AddSpell(enemySpells, 403) -- Lightning Bolt (Resto) (40 yards)
|
||||
AddSpell(friendlySpells, 8004) -- Healing Surge (Resto/Elemental) (40 yards)
|
||||
AddSpell(friendlySpells, 188070) -- Healing Surge (Enhancement) (40 yards)
|
||||
AddSpell(resSpells, 2008) -- Ancestral Spirit (40 yards)
|
||||
elseif class == "WARLOCK" then
|
||||
AddSpell(enemySpells, 5782) -- Fear (30 yards)
|
||||
AddSpell(longEnemySpells, 234153) -- Drain Life (40 yards)
|
||||
AddSpell(longEnemySpells, 198590) --Drain Soul (40 yards)
|
||||
AddSpell(longEnemySpells, 232670) --Shadow Bolt (40 yards, lvl 1 spell)
|
||||
AddSpell(petSpells, 755) -- Health Funnel (45 yards)
|
||||
AddSpell(friendlySpells, 20707) -- Soulstone (40 yards)
|
||||
elseif class == "MAGE" then
|
||||
AddSpell(enemySpells, 118) -- Polymorph (30 yards)
|
||||
AddSpell(longEnemySpells, 116) -- Frostbolt (Frost) (40 yards)
|
||||
AddSpell(longEnemySpells, 44425) -- Arcane Barrage (Arcane) (40 yards)
|
||||
AddSpell(longEnemySpells, 133) -- Fireball (Fire) (40 yards)
|
||||
AddSpell(friendlySpells, 130) -- Slow Fall (40 yards)
|
||||
elseif class == "HUNTER" then
|
||||
AddSpell(petSpells, 982) -- Mend Pet (45 yards)
|
||||
AddSpell(enemySpells, 75) -- Auto Shot (40 yards)
|
||||
elseif class == "DEATHKNIGHT" then
|
||||
AddSpell(enemySpells, 49576) -- Death Grip
|
||||
AddSpell(longEnemySpells, 47541) -- Death Coil (Unholy) (40 yards)
|
||||
AddSpell(resSpells, 61999) -- Raise Ally (40 yards)
|
||||
elseif class == "ROGUE" then
|
||||
AddSpell(enemySpells, 185565) -- Poisoned Knife (Assassination) (30 yards)
|
||||
AddSpell(enemySpells, 185763) -- Pistol Shot (Outlaw) (20 yards)
|
||||
AddSpell(enemySpells, 114014) -- Shuriken Toss (Sublety) (30 yards)
|
||||
AddSpell(enemySpells, 1725) -- Distract (30 yards)
|
||||
AddSpell(friendlySpells, 57934) -- Tricks of the Trade (100 yards)
|
||||
elseif class == "WARRIOR" then
|
||||
AddSpell(enemySpells, 5246) -- Intimidating Shout (Arms/Fury) (8 yards)
|
||||
AddSpell(enemySpells, 100) -- Charge (Arms/Fury) (8-25 yards)
|
||||
AddSpell(longEnemySpells, 355) -- Taunt (30 yards)
|
||||
elseif class == "MONK" then
|
||||
AddSpell(enemySpells, 115546) -- Provoke (30 yards)
|
||||
AddSpell(longEnemySpells, 117952) -- Crackling Jade Lightning (40 yards)
|
||||
AddSpell(friendlySpells, 116694) -- Effuse (40 yards)
|
||||
AddSpell(resSpells, 115178) -- Resuscitate (40 yards)
|
||||
elseif class == "DEMONHUNTER" then
|
||||
AddSpell(enemySpells, 183752) -- Consume Magic (20 yards)
|
||||
AddSpell(longEnemySpells, 185123) -- Throw Glaive (Havoc) (30 yards)
|
||||
AddSpell(longEnemySpells, 204021) -- Fiery Brand (Vengeance) (30 yards)
|
||||
end
|
||||
end
|
||||
|
||||
local function getUnit(unit)
|
||||
if not unit:find("party") or not unit:find("raid") then
|
||||
for i=1, 4 do
|
||||
if UnitIsUnit(unit, "party"..i) then
|
||||
return "party"..i
|
||||
end
|
||||
end
|
||||
|
||||
for i=1, 40 do
|
||||
if UnitIsUnit(unit, "raid"..i) then
|
||||
return "raid"..i
|
||||
end
|
||||
end
|
||||
else
|
||||
return unit
|
||||
end
|
||||
end
|
||||
|
||||
local function friendlyIsInRange(unit)
|
||||
if CheckInteractDistance(unit, 1) and UnitInPhase(unit) then --Inspect (28 yards) and same phase as you
|
||||
return true
|
||||
end
|
||||
|
||||
if UnitIsDeadOrGhost(unit) and #resSpells > 0 then
|
||||
for _, spellID in ipairs(resSpells) do
|
||||
if SpellRange.IsSpellInRange(spellID, unit) == 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
if #friendlySpells == 0 and (UnitInRaid(unit) or UnitInParty(unit)) then
|
||||
unit = getUnit(unit)
|
||||
return unit and UnitInRange(unit)
|
||||
else
|
||||
for _, spellID in ipairs(friendlySpells) do
|
||||
if SpellRange.IsSpellInRange(spellID, unit) == 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function petIsInRange(unit)
|
||||
if CheckInteractDistance(unit, 2) then
|
||||
return true
|
||||
end
|
||||
|
||||
for _, spellID in ipairs(friendlySpells) do
|
||||
if SpellRange.IsSpellInRange(spellID, unit) == 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
for _, spellID in ipairs(petSpells) do
|
||||
if SpellRange.IsSpellInRange(spellID, unit) == 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function enemyIsInRange(unit)
|
||||
if CheckInteractDistance(unit, 2) then
|
||||
return true
|
||||
end
|
||||
|
||||
for _, spellID in ipairs(enemySpells) do
|
||||
if SpellRange.IsSpellInRange(spellID, unit) == 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function enemyIsInLongRange(unit)
|
||||
for _, spellID in ipairs(longEnemySpells) do
|
||||
if SpellRange.IsSpellInRange(spellID, unit) == 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- updating of range.
|
||||
local timer = 0
|
||||
local OnRangeUpdate = function(self, elapsed)
|
||||
timer = timer + elapsed
|
||||
|
||||
if(timer >= .20) then
|
||||
for _, object in next, _FRAMES do
|
||||
if(object:IsShown()) then
|
||||
local range = object.Range
|
||||
local unit = object.unit
|
||||
if(unit) then
|
||||
if UnitCanAttack("player", unit) then
|
||||
if enemyIsInRange(unit) then
|
||||
object:SetAlpha(range.insideAlpha)
|
||||
elseif enemyIsInLongRange(unit) then
|
||||
object:SetAlpha(range.insideAlpha)
|
||||
else
|
||||
object:SetAlpha(range.outsideAlpha)
|
||||
end
|
||||
elseif UnitIsUnit(unit, "pet") then
|
||||
if petIsInRange(unit) then
|
||||
object:SetAlpha(range.insideAlpha)
|
||||
else
|
||||
object:SetAlpha(range.outsideAlpha)
|
||||
end
|
||||
else
|
||||
if friendlyIsInRange(unit) and UnitIsConnected(unit) then
|
||||
object:SetAlpha(range.insideAlpha)
|
||||
else
|
||||
object:SetAlpha(range.outsideAlpha)
|
||||
end
|
||||
end
|
||||
else
|
||||
object:SetAlpha(range.insideAlpha)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
timer = 0
|
||||
end
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local range = self.Range
|
||||
if(range and range.insideAlpha and range.outsideAlpha) then
|
||||
tinsert(_FRAMES, self)
|
||||
|
||||
if(not OnRangeFrame) then
|
||||
OnRangeFrame = CreateFrame"Frame"
|
||||
OnRangeFrame:SetScript("OnUpdate", OnRangeUpdate)
|
||||
end
|
||||
|
||||
OnRangeFrame:Show()
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local range = self.Range
|
||||
if(range) then
|
||||
for k, frame in next, _FRAMES do
|
||||
if(frame == self) then
|
||||
tremove(_FRAMES, k)
|
||||
frame:SetAlpha(1)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if(#_FRAMES == 0) then
|
||||
OnRangeFrame:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Range', nil, Enable, Disable)
|
||||
159
Libraries/oUF/elements/readycheck.lua
Normal file
159
Libraries/oUF/elements/readycheck.lua
Normal file
@@ -0,0 +1,159 @@
|
||||
--[[ Element: Ready Check Icon
|
||||
|
||||
Handles updating and visibility of `self.ReadyCheck` based upon the units
|
||||
ready check status.
|
||||
|
||||
Widget
|
||||
|
||||
ReadyCheck - A Texture representing ready check status.
|
||||
|
||||
Notes
|
||||
|
||||
This element updates by changing the texture.
|
||||
|
||||
Options
|
||||
|
||||
.finishedTime - The number of seconds the icon should stick after a check has
|
||||
completed. Defaults to 10 seconds.
|
||||
.fadeTime - The number of seconds the icon should used to fade away after
|
||||
the stick duration has completed. Defaults to 1.5 seconds.
|
||||
.readyTexture - Path to alternate texture for the ready check "ready" status.
|
||||
.notReadyTexture - Path to alternate texture for the ready check "notready" status.
|
||||
.waitingTexture - Path to alternate texture for the ready check "waiting" status.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local ReadyCheck = self:CreateTexture(nil, 'OVERLAY')
|
||||
ReadyCheck:SetSize(16, 16)
|
||||
ReadyCheck:SetPoint('TOP')
|
||||
|
||||
-- Register with oUF
|
||||
self.ReadyCheck = ReadyCheck
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local function OnFinished(self)
|
||||
local element = self:GetParent()
|
||||
element:Hide()
|
||||
|
||||
--[[ :PostUpdateFadeOut()
|
||||
|
||||
Called after the element has been faded out.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The ReadyCheck element.
|
||||
]]
|
||||
if(element.PostUpdateFadeOut) then
|
||||
element:PostUpdateFadeOut()
|
||||
end
|
||||
end
|
||||
|
||||
local Update = function(self, event)
|
||||
local element = self.ReadyCheck
|
||||
|
||||
--[[ :PreUpdate()
|
||||
|
||||
Called before the element has been updated.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The ReadyCheck element.
|
||||
]]
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
local unit = self.unit
|
||||
local status = GetReadyCheckStatus(unit)
|
||||
if(UnitExists(unit) and status) then
|
||||
if(status == 'ready') then
|
||||
element:SetTexture(element.readyTexture or READY_CHECK_READY_TEXTURE)
|
||||
elseif(status == 'notready') then
|
||||
element:SetTexture(element.notReadyTexture or READY_CHECK_NOT_READY_TEXTURE)
|
||||
else
|
||||
element:SetTexture(element.waitingTexture or READY_CHECK_WAITING_TEXTURE)
|
||||
end
|
||||
|
||||
element.status = status
|
||||
element:Show()
|
||||
elseif(event ~= 'READY_CHECK_FINISHED') then
|
||||
element.status = nil
|
||||
element:Hide()
|
||||
end
|
||||
|
||||
if(event == 'READY_CHECK_FINISHED') then
|
||||
if(element.status == 'waiting') then
|
||||
element:SetTexture(element.notReadyTexture or READY_CHECK_NOT_READY_TEXTURE)
|
||||
end
|
||||
|
||||
element.Animation:Play()
|
||||
end
|
||||
|
||||
--[[ :PostUpdate(status)
|
||||
|
||||
Called after the element has been updated.
|
||||
|
||||
Arguments
|
||||
|
||||
self - The ReadyCheck element.
|
||||
status - The units ready check status, if any.
|
||||
]]
|
||||
if(element.PostUpdate) then
|
||||
return element:PostUpdate(status)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.ReadyCheck.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
local element = self.ReadyCheck
|
||||
if(element and (unit and (unit:sub(1, 5) == 'party' or unit:sub(1,4) == 'raid'))) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
|
||||
local AnimationGroup = element:CreateAnimationGroup()
|
||||
AnimationGroup:HookScript('OnFinished', OnFinished)
|
||||
element.Animation = AnimationGroup
|
||||
|
||||
local Animation = AnimationGroup:CreateAnimation('Alpha')
|
||||
Animation:SetFromAlpha(1)
|
||||
Animation:SetToAlpha(0)
|
||||
Animation:SetDuration(element.fadeTime or 1.5)
|
||||
Animation:SetStartDelay(element.finishedTime or 10)
|
||||
|
||||
self:RegisterEvent('READY_CHECK', Path, true)
|
||||
self:RegisterEvent('READY_CHECK_CONFIRM', Path, true)
|
||||
self:RegisterEvent('READY_CHECK_FINISHED', Path, true)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local element = self.ReadyCheck
|
||||
if(element) then
|
||||
element:Hide()
|
||||
|
||||
self:UnregisterEvent('READY_CHECK', Path)
|
||||
self:UnregisterEvent('READY_CHECK_CONFIRM', Path)
|
||||
self:UnregisterEvent('READY_CHECK_FINISHED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('ReadyCheck', Path, Enable, Disable)
|
||||
85
Libraries/oUF/elements/resting.lua
Normal file
85
Libraries/oUF/elements/resting.lua
Normal file
@@ -0,0 +1,85 @@
|
||||
--[[ Element: Resting Icon
|
||||
|
||||
Toggles visibility of the resting icon.
|
||||
|
||||
Widget
|
||||
|
||||
Resting - Any UI widget.
|
||||
|
||||
Notes
|
||||
|
||||
The default resting icon will be used if the UI widget is a texture and doesn't
|
||||
have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local Resting = self:CreateTexture(nil, 'OVERLAY')
|
||||
Resting:SetSize(16, 16)
|
||||
Resting:SetPoint('TOPLEFT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.Resting = Resting
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event)
|
||||
local resting = self.Resting
|
||||
if(resting.PreUpdate) then
|
||||
resting:PreUpdate()
|
||||
end
|
||||
|
||||
local isResting = IsResting()
|
||||
if(isResting) then
|
||||
resting:Show()
|
||||
else
|
||||
resting:Hide()
|
||||
end
|
||||
|
||||
if(resting.PostUpdate) then
|
||||
return resting:PostUpdate(isResting)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.Resting.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
local resting = self.Resting
|
||||
if(resting and unit == 'player') then
|
||||
resting.__owner = self
|
||||
resting.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent("PLAYER_UPDATE_RESTING", Path, true)
|
||||
|
||||
if(resting:IsObjectType"Texture" and not resting:GetTexture()) then
|
||||
resting:SetTexture[[Interface\CharacterFrame\UI-StateIcon]]
|
||||
resting:SetTexCoord(0, .5, 0, .421875)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local resting = self.Resting
|
||||
if(resting) then
|
||||
resting:Hide()
|
||||
self:UnregisterEvent("PLAYER_UPDATE_RESTING", Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Resting', Path, Enable, Disable)
|
||||
85
Libraries/oUF/elements/resurrect.lua
Normal file
85
Libraries/oUF/elements/resurrect.lua
Normal file
@@ -0,0 +1,85 @@
|
||||
--[[ Element: Resurrect Icon
|
||||
|
||||
Handles updating and toggles visibility of incoming resurrect icon.
|
||||
|
||||
Widget
|
||||
|
||||
ResurrectIcon - A Texture used to display if the unit has an incoming
|
||||
resurrect.
|
||||
|
||||
Notes
|
||||
|
||||
The default resurrect icon will be used if the UI widget is a texture and
|
||||
doesn't have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local ResurrectIcon = self:CreateTexture(nil, 'OVERLAY')
|
||||
ResurrectIcon:SetSize(16, 16)
|
||||
ResurrectIcon:SetPoint('TOPRIGHT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.ResurrectIcon = ResurrectIcon
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event)
|
||||
if not self.unit then return; end
|
||||
local resurrect = self.ResurrectIcon
|
||||
if(resurrect.PreUpdate) then
|
||||
resurrect:PreUpdate()
|
||||
end
|
||||
|
||||
local incomingResurrect = UnitHasIncomingResurrection(self.unit)
|
||||
if(incomingResurrect) then
|
||||
resurrect:Show()
|
||||
else
|
||||
resurrect:Hide()
|
||||
end
|
||||
|
||||
if(resurrect.PostUpdate) then
|
||||
return resurrect:PostUpdate(incomingResurrect)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.ResurrectIcon.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local resurrect = self.ResurrectIcon
|
||||
if(resurrect) then
|
||||
resurrect.__owner = self
|
||||
resurrect.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent('INCOMING_RESURRECT_CHANGED', Path, true)
|
||||
|
||||
if(resurrect:IsObjectType('Texture') and not resurrect:GetTexture()) then
|
||||
resurrect:SetTexture[[Interface\RaidFrame\Raid-Icon-Rez]]
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local resurrect = self.ResurrectIcon
|
||||
if(resurrect) then
|
||||
self:UnregisterEvent('INCOMING_RESURRECT_CHANGED', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('ResurrectIcon', Path, Enable, Disable)
|
||||
92
Libraries/oUF/elements/ricons.lua
Normal file
92
Libraries/oUF/elements/ricons.lua
Normal file
@@ -0,0 +1,92 @@
|
||||
--[[ Element: Raid Icon
|
||||
|
||||
Handles updating and toggles visibility of raid target icons.
|
||||
|
||||
Widget
|
||||
|
||||
RaidIcon - A Texture used to display the raid target icon.
|
||||
|
||||
Notes
|
||||
|
||||
This element updates by changing the texture.
|
||||
|
||||
The default raid icons will be used if the UI widget is a texture and doesn't
|
||||
have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local RaidIcon = self:CreateTexture(nil, 'OVERLAY')
|
||||
RaidIcon:SetSize(16, 16)
|
||||
RaidIcon:SetPoint('TOPRIGHT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.RaidIcon = RaidIcon
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local GetRaidTargetIndex = GetRaidTargetIndex
|
||||
local SetRaidTargetIconTexture = SetRaidTargetIconTexture
|
||||
|
||||
local Update = function(self, event)
|
||||
if not self.unit then return end
|
||||
local icon = self.RaidIcon
|
||||
if(icon.PreUpdate) then
|
||||
icon:PreUpdate()
|
||||
end
|
||||
|
||||
local index = GetRaidTargetIndex(self.unit)
|
||||
if(index) then
|
||||
SetRaidTargetIconTexture(icon, index)
|
||||
icon:Show()
|
||||
else
|
||||
icon:Hide()
|
||||
end
|
||||
|
||||
if(icon.PostUpdate) then
|
||||
return icon:PostUpdate(index)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.RaidIcon.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
if(not element.__owner.unit) then return end
|
||||
return Path(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local ricon = self.RaidIcon
|
||||
if(ricon) then
|
||||
ricon.__owner = self
|
||||
ricon.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent("RAID_TARGET_UPDATE", Path, true)
|
||||
|
||||
if(ricon:IsObjectType"Texture" and not ricon:GetTexture()) then
|
||||
ricon:SetTexture[[Interface\TargetingFrame\UI-RaidTargetingIcons]]
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local ricon = self.RaidIcon
|
||||
if(ricon) then
|
||||
ricon:Hide()
|
||||
self:UnregisterEvent("RAID_TARGET_UPDATE", Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('RaidIcon', Path, Enable, Disable)
|
||||
191
Libraries/oUF/elements/runebar.lua
Normal file
191
Libraries/oUF/elements/runebar.lua
Normal file
@@ -0,0 +1,191 @@
|
||||
--[[ Element: Runes Bar
|
||||
|
||||
Handle updating and visibility of the Death Knight's Rune indicators.
|
||||
|
||||
Widget
|
||||
|
||||
Runes - An array holding StatusBar's.
|
||||
|
||||
Sub-Widgets
|
||||
|
||||
.bg - A Texture which functions as a background. It will inherit the color of
|
||||
the main StatusBar.
|
||||
|
||||
Notes
|
||||
|
||||
The default StatusBar texture will be applied if the UI widget doesn't have a
|
||||
status bar texture or color defined.
|
||||
|
||||
Sub-Widgets Options
|
||||
|
||||
.multiplier - Defines a multiplier, which is used to tint the background based
|
||||
on the main widgets R, G and B values. Defaults to 1 if not
|
||||
present.
|
||||
|
||||
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
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update
|
||||
function. Removing the table key entry will make the
|
||||
element fall-back to its internal function again.
|
||||
|
||||
]]
|
||||
|
||||
if select(2, UnitClass("player")) ~= "DEATHKNIGHT" then return end
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local OnUpdate = function(self, elapsed)
|
||||
local duration = self.duration + elapsed
|
||||
self.duration = duration
|
||||
self:SetValue(duration)
|
||||
end
|
||||
|
||||
local Update = function(self, event, rid, energized)
|
||||
local runes = self.Runes
|
||||
local rune = runes[rid]
|
||||
if(not rune) then return end
|
||||
|
||||
local start, duration, runeReady
|
||||
if(UnitHasVehicleUI'player') then
|
||||
rune:Hide()
|
||||
else
|
||||
start, duration, runeReady = GetRuneCooldown(rid)
|
||||
if(not start) then return end
|
||||
|
||||
if(energized or runeReady) then
|
||||
rune:SetMinMaxValues(0, 1)
|
||||
rune:SetValue(1)
|
||||
rune:SetScript("OnUpdate", nil)
|
||||
else
|
||||
rune.duration = GetTime() - start
|
||||
rune.max = duration
|
||||
rune:SetMinMaxValues(1, duration)
|
||||
rune:SetScript("OnUpdate", OnUpdate)
|
||||
end
|
||||
|
||||
rune:Show()
|
||||
end
|
||||
|
||||
if(runes.PostUpdate) then
|
||||
return runes:PostUpdate(rune, rid, energized and 0 or start, duration, energized or runeReady)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, event, ...)
|
||||
local runes = self.Runes
|
||||
local UpdateMethod = runes.Override or Update
|
||||
if(event == 'RUNE_POWER_UPDATE') then
|
||||
return UpdateMethod(self, event, ...)
|
||||
else
|
||||
for index = 1, #runes do
|
||||
UpdateMethod(self, event, index)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function RunesEnable(self)
|
||||
self:RegisterEvent('UNIT_ENTERED_VEHICLE', VisibilityPath)
|
||||
self:UnregisterEvent("UNIT_EXITED_VEHICLE", VisibilityPath)
|
||||
|
||||
self.Runes:Show()
|
||||
|
||||
if self.Runes.PostUpdateVisibility then
|
||||
self.Runes:PostUpdateVisibility(true, not self.Runes.isEnabled)
|
||||
end
|
||||
|
||||
self.Runes.isEnabled = true
|
||||
|
||||
Path(self, 'RunesEnable')
|
||||
end
|
||||
|
||||
local function RunesDisable(self)
|
||||
self:UnregisterEvent('UNIT_ENTERED_VEHICLE', VisibilityPath)
|
||||
self:RegisterEvent("UNIT_EXITED_VEHICLE", VisibilityPath)
|
||||
|
||||
self.Runes:Hide()
|
||||
|
||||
if self.Runes.PostUpdateVisibility then
|
||||
self.Runes:PostUpdateVisibility(false, self.Runes.isEnabled)
|
||||
end
|
||||
|
||||
self.Runes.isEnabled = false
|
||||
|
||||
Path(self, 'RunesDisable')
|
||||
end
|
||||
|
||||
local function Visibility(self, event, ...)
|
||||
local element = self.Runes
|
||||
local shouldEnable
|
||||
|
||||
if not (UnitHasVehicleUI('player')) then
|
||||
shouldEnable = true
|
||||
end
|
||||
|
||||
local isEnabled = element.isEnabled
|
||||
if(shouldEnable and not isEnabled) then
|
||||
RunesEnable(self)
|
||||
elseif(not shouldEnable and (isEnabled or isEnabled == nil)) then
|
||||
RunesDisable(self)
|
||||
elseif(shouldEnable and isEnabled) then
|
||||
Path(self, event, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local VisibilityPath = function(self, ...)
|
||||
return (self.Runes.OverrideVisibility or Visibility) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return VisibilityPath(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
local runes = self.Runes
|
||||
if(runes and unit == 'player') then
|
||||
runes.__owner = self
|
||||
runes.ForceUpdate = ForceUpdate
|
||||
|
||||
for i = 1, #runes do
|
||||
local rune = runes[i]
|
||||
|
||||
local r, g, b = unpack(self.colors.power.RUNES)
|
||||
if(rune:IsObjectType'StatusBar' and not rune:GetStatusBarTexture()) then
|
||||
rune:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]]
|
||||
rune:SetStatusBarColor(r, g, b)
|
||||
end
|
||||
|
||||
if(rune.bg) then
|
||||
local mu = rune.bg.multiplier or 1
|
||||
rune.bg:SetVertexColor(r * mu, g * mu, b * mu)
|
||||
end
|
||||
end
|
||||
|
||||
self:RegisterEvent("RUNE_POWER_UPDATE", Path, true)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
self:UnregisterEvent("RUNE_POWER_UPDATE", Path)
|
||||
|
||||
RunesDisable(self)
|
||||
end
|
||||
|
||||
oUF:AddElement("Runes", VisibilityPath, Enable, Disable)
|
||||
188
Libraries/oUF/elements/stagger.lua
Normal file
188
Libraries/oUF/elements/stagger.lua
Normal file
@@ -0,0 +1,188 @@
|
||||
--[[ Element: Monk Stagger Bar
|
||||
|
||||
Handles updating and visibility of the monk's stagger bar.
|
||||
|
||||
Widget
|
||||
|
||||
Stagger - A StatusBar
|
||||
|
||||
Sub-Widgets
|
||||
|
||||
.bg - A Texture that functions as a background. It will inherit the color
|
||||
of the main StatusBar.
|
||||
|
||||
Notes
|
||||
|
||||
The default StatusBar texture will be applied if the UI widget doesn't have a
|
||||
status bar texture or color defined.
|
||||
|
||||
In order to override the internal update define the 'OnUpdate' script on the
|
||||
widget in the layout
|
||||
|
||||
Sub-Widgets Options
|
||||
|
||||
.multiplier - Defines a multiplier, which is used to tint the background based
|
||||
on the main widgets R, G and B values. Defaults to 1 if not
|
||||
present.
|
||||
|
||||
Examples
|
||||
|
||||
local Stagger = CreateFrame('StatusBar', nil, self)
|
||||
Stagger:SetSize(120, 20)
|
||||
Stagger:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', 0, 0)
|
||||
|
||||
-- Register with oUF
|
||||
self.Stagger = Stagger
|
||||
|
||||
Hooks
|
||||
|
||||
OverrideVisibility(self) - Used to completely override the internal visibility
|
||||
function. Removing the table key entry will make
|
||||
the element fall-back to its internal function
|
||||
again.
|
||||
Override(self) - Used to completely override the internal
|
||||
update function. Removing the table key entry will
|
||||
make the element fall-back to its internal function
|
||||
again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
-- percentages at which the bar should change color
|
||||
local STAGGER_YELLOW_TRANSITION = STAGGER_YELLOW_TRANSITION
|
||||
local STAGGER_RED_TRANSITION = STAGGER_RED_TRANSITION
|
||||
|
||||
-- table indices of bar colors
|
||||
local STAGGER_GREEN_INDEX = STAGGER_GREEN_INDEX or 1
|
||||
local STAGGER_YELLOW_INDEX = STAGGER_YELLOW_INDEX or 2
|
||||
local STAGGER_RED_INDEX = STAGGER_RED_INDEX or 3
|
||||
|
||||
local UnitHealthMax = UnitHealthMax
|
||||
local UnitStagger = UnitStagger
|
||||
|
||||
local _, playerClass = UnitClass("player")
|
||||
local color
|
||||
|
||||
local Update = function(self, event, unit)
|
||||
if unit and unit ~= self.unit then return end
|
||||
local element = self.Stagger
|
||||
|
||||
if(element.PreUpdate) then
|
||||
element:PreUpdate()
|
||||
end
|
||||
|
||||
|
||||
local maxHealth = UnitHealthMax("player")
|
||||
local stagger = UnitStagger("player") or 0 --For some reason stagger sometimes is nil
|
||||
local staggerPercent = stagger / maxHealth
|
||||
|
||||
element:SetMinMaxValues(0, maxHealth)
|
||||
element:SetValue(stagger)
|
||||
|
||||
local rgb
|
||||
if(staggerPercent >= STAGGER_RED_TRANSITION) then
|
||||
rgb = color[STAGGER_RED_INDEX]
|
||||
elseif(staggerPercent > STAGGER_YELLOW_TRANSITION) then
|
||||
rgb = color[STAGGER_YELLOW_INDEX]
|
||||
else
|
||||
rgb = color[STAGGER_GREEN_INDEX]
|
||||
end
|
||||
|
||||
local r, g, b = rgb[1], rgb[2], rgb[3]
|
||||
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
|
||||
|
||||
if(element.PostUpdate) then
|
||||
element:PostUpdate(maxHealth, stagger, staggerPercent, r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.Stagger.Override or Update)(self, ...)
|
||||
end
|
||||
|
||||
local Visibility = function(self, event, unit)
|
||||
local isShown = self.Stagger:IsShown()
|
||||
local stateChanged = false
|
||||
if(SPEC_MONK_BREWMASTER ~= GetSpecialization() or UnitHasVehiclePlayerFrameUI('player')) then
|
||||
if isShown then
|
||||
self.Stagger:Hide()
|
||||
self:UnregisterEvent('UNIT_AURA', Path)
|
||||
stateChanged = true
|
||||
end
|
||||
|
||||
if(self.Stagger.PostUpdateVisibility) then
|
||||
self.Stagger.PostUpdateVisibility(self, event, unit, false, stateChanged)
|
||||
end
|
||||
else
|
||||
if(not isShown) then
|
||||
self.Stagger:Show()
|
||||
self:RegisterEvent('UNIT_AURA', Path)
|
||||
stateChanged = true
|
||||
end
|
||||
|
||||
if(self.Stagger.PostUpdateVisibility) then
|
||||
self.Stagger.PostUpdateVisibility(self, event, unit, true, stateChanged)
|
||||
end
|
||||
|
||||
return Path(self, event, unit)
|
||||
end
|
||||
end
|
||||
|
||||
local VisibilityPath = function(self, ...)
|
||||
return (self.Stagger.OverrideVisibility or Visibility)(self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return VisibilityPath(element.__owner, "ForceUpdate", element.__owner.unit)
|
||||
end
|
||||
|
||||
local Enable = function(self, unit)
|
||||
if(playerClass ~= "MONK") then return end
|
||||
|
||||
local element = self.Stagger
|
||||
if(element) then
|
||||
element.__owner = self
|
||||
element.ForceUpdate = ForceUpdate
|
||||
element:Hide()
|
||||
|
||||
color = self.colors.power[BREWMASTER_POWER_BAR_NAME]
|
||||
|
||||
self:RegisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
self:RegisterEvent('PLAYER_TALENT_UPDATE', VisibilityPath, true)
|
||||
|
||||
if(element:IsObjectType'StatusBar' and not element:GetStatusBarTexture()) then
|
||||
element:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]]
|
||||
end
|
||||
|
||||
MonkStaggerBar:UnregisterEvent'PLAYER_ENTERING_WORLD'
|
||||
MonkStaggerBar:UnregisterEvent'PLAYER_SPECIALIZATION_CHANGED'
|
||||
MonkStaggerBar:UnregisterEvent'UNIT_DISPLAYPOWER'
|
||||
MonkStaggerBar:UnregisterEvent'UPDATE_VEHICLE_ACTION_BAR'
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local element = self.Stagger
|
||||
if(element) then
|
||||
element:Hide()
|
||||
self:UnregisterEvent('UNIT_AURA', Path)
|
||||
self:UnregisterEvent('UNIT_DISPLAYPOWER', VisibilityPath)
|
||||
self:UnregisterEvent('PLAYER_TALENT_UPDATE', VisibilityPath)
|
||||
|
||||
MonkStaggerBar:UnregisterEvent'PLAYER_ENTERING_WORLD'
|
||||
MonkStaggerBar:UnregisterEvent'PLAYER_SPECIALIZATION_CHANGED'
|
||||
MonkStaggerBar:UnregisterEvent'UNIT_DISPLAYPOWER'
|
||||
MonkStaggerBar:UnregisterEvent'UPDATE_VEHICLE_ACTION_BAR'
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement("Stagger", VisibilityPath, Enable, Disable)
|
||||
781
Libraries/oUF/elements/tags.lua
Normal file
781
Libraries/oUF/elements/tags.lua
Normal file
@@ -0,0 +1,781 @@
|
||||
--[[
|
||||
-- Credits: Vika, Cladhaire, Tekkub
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local format = string.format
|
||||
local tinsert, tremove = table.insert, table.remove
|
||||
|
||||
local _PATTERN = '%[..-%]+'
|
||||
|
||||
local _ENV = {
|
||||
Hex = function(r, g, b)
|
||||
if type(r) == "table" then
|
||||
if r.r then r, g, b = r.r, r.g, r.b else r, g, b = unpack(r) end
|
||||
end
|
||||
if not r or type(r) == 'string' then --wtf?
|
||||
return '|cffFFFFFF'
|
||||
end
|
||||
return format("|cff%02x%02x%02x", r*255, g*255, b*255)
|
||||
end,
|
||||
ColorGradient = oUF.ColorGradient,
|
||||
}
|
||||
local _PROXY = setmetatable(_ENV, {__index = _G})
|
||||
|
||||
local tagStrings = {
|
||||
["creature"] = [[function(u)
|
||||
return UnitCreatureFamily(u) or UnitCreatureType(u)
|
||||
end]],
|
||||
|
||||
["dead"] = [[function(u)
|
||||
if(UnitIsDead(u)) then
|
||||
return 'Dead'
|
||||
elseif(UnitIsGhost(u)) then
|
||||
return 'Ghost'
|
||||
end
|
||||
end]],
|
||||
|
||||
["difficulty"] = [[function(u)
|
||||
if UnitCanAttack("player", u) then
|
||||
local l = UnitLevel(u)
|
||||
return Hex(GetCreatureDifficultyColor((l > 0) and l or 999))
|
||||
end
|
||||
end]],
|
||||
|
||||
["leader"] = [[function(u)
|
||||
if(UnitIsGroupLeader(u)) then
|
||||
return 'L'
|
||||
end
|
||||
end]],
|
||||
|
||||
["leaderlong"] = [[function(u)
|
||||
if(UnitIsGroupLeader(u)) then
|
||||
return 'Leader'
|
||||
end
|
||||
end]],
|
||||
|
||||
["level"] = [[function(u)
|
||||
local l = UnitLevel(u)
|
||||
if(UnitIsWildBattlePet(u) or UnitIsBattlePetCompanion(u)) then
|
||||
l = UnitBattlePetLevel(u)
|
||||
end
|
||||
|
||||
if(l > 0) then
|
||||
return l
|
||||
else
|
||||
return '??'
|
||||
end
|
||||
end]],
|
||||
|
||||
["missinghp"] = [[function(u)
|
||||
local current = UnitHealthMax(u) - UnitHealth(u)
|
||||
if(current > 0) then
|
||||
return current
|
||||
end
|
||||
end]],
|
||||
|
||||
["missingpp"] = [[function(u)
|
||||
local current = UnitPowerMax(u) - UnitPower(u)
|
||||
if(current > 0) then
|
||||
return current
|
||||
end
|
||||
end]],
|
||||
|
||||
["name"] = [[function(u, r)
|
||||
return UnitName(r or u)
|
||||
end]],
|
||||
|
||||
["offline"] = [[function(u)
|
||||
if(not UnitIsConnected(u)) then
|
||||
return 'Offline'
|
||||
end
|
||||
end]],
|
||||
|
||||
["perhp"] = [[function(u)
|
||||
local m = UnitHealthMax(u)
|
||||
if(m == 0) then
|
||||
return 0
|
||||
else
|
||||
return math.floor(UnitHealth(u)/m*100+.5)
|
||||
end
|
||||
end]],
|
||||
|
||||
["perpp"] = [[function(u)
|
||||
local m = UnitPowerMax(u)
|
||||
if(m == 0) then
|
||||
return 0
|
||||
else
|
||||
return math.floor(UnitPower(u)/m*100+.5)
|
||||
end
|
||||
end]],
|
||||
|
||||
["plus"] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'elite' or c == 'rareelite') then
|
||||
return '+'
|
||||
end
|
||||
end]],
|
||||
|
||||
["pvp"] = [[function(u)
|
||||
if(UnitIsPVP(u)) then
|
||||
return 'PvP'
|
||||
end
|
||||
end]],
|
||||
|
||||
["raidcolor"] = [[function(u)
|
||||
local _, x = UnitClass(u)
|
||||
if(x) then
|
||||
return Hex(_COLORS.class[x])
|
||||
end
|
||||
end]],
|
||||
|
||||
["rare"] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'rare' or c == 'rareelite') then
|
||||
return 'Rare'
|
||||
end
|
||||
end]],
|
||||
|
||||
["resting"] = [[function(u)
|
||||
if(u == 'player' and IsResting()) then
|
||||
return 'zzz'
|
||||
end
|
||||
end]],
|
||||
|
||||
["sex"] = [[function(u)
|
||||
local s = UnitSex(u)
|
||||
if(s == 2) then
|
||||
return 'Male'
|
||||
elseif(s == 3) then
|
||||
return 'Female'
|
||||
end
|
||||
end]],
|
||||
|
||||
["smartclass"] = [[function(u)
|
||||
if(UnitIsPlayer(u)) then
|
||||
return _TAGS['class'](u)
|
||||
end
|
||||
|
||||
return _TAGS['creature'](u)
|
||||
end]],
|
||||
|
||||
["status"] = [[function(u)
|
||||
if(UnitIsDead(u)) then
|
||||
return 'Dead'
|
||||
elseif(UnitIsGhost(u)) then
|
||||
return 'Ghost'
|
||||
elseif(not UnitIsConnected(u)) then
|
||||
return 'Offline'
|
||||
else
|
||||
return _TAGS['resting'](u)
|
||||
end
|
||||
end]],
|
||||
|
||||
["threat"] = [[function(u)
|
||||
local s = UnitThreatSituation(u)
|
||||
if(s == 1) then
|
||||
return '++'
|
||||
elseif(s == 2) then
|
||||
return '--'
|
||||
elseif(s == 3) then
|
||||
return 'Aggro'
|
||||
end
|
||||
end]],
|
||||
|
||||
["threatcolor"] = [[function(u)
|
||||
return Hex(GetThreatStatusColor(UnitThreatSituation(u)))
|
||||
end]],
|
||||
|
||||
["cpoints"] = [[function(u)
|
||||
local cp
|
||||
if(UnitHasVehicleUI'player') then
|
||||
cp = GetComboPoints('vehicle', 'target')
|
||||
else
|
||||
cp = GetComboPoints('player', 'target')
|
||||
end
|
||||
|
||||
if(cp > 0) then
|
||||
return cp
|
||||
end
|
||||
end]],
|
||||
|
||||
['smartlevel'] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'worldboss') then
|
||||
return 'Boss'
|
||||
else
|
||||
local plus = _TAGS['plus'](u)
|
||||
local level = _TAGS['level'](u)
|
||||
if(plus) then
|
||||
return level .. plus
|
||||
else
|
||||
return level
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
["classification"] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'rare') then
|
||||
return 'Rare'
|
||||
elseif(c == 'rareelite') then
|
||||
return 'Rare Elite'
|
||||
elseif(c == 'elite') then
|
||||
return 'Elite'
|
||||
elseif(c == 'worldboss') then
|
||||
return 'Boss'
|
||||
elseif(c == 'minus') then
|
||||
return 'Affix'
|
||||
end
|
||||
end]],
|
||||
|
||||
["shortclassification"] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'rare') then
|
||||
return 'R'
|
||||
elseif(c == 'rareelite') then
|
||||
return 'R+'
|
||||
elseif(c == 'elite') then
|
||||
return '+'
|
||||
elseif(c == 'worldboss') then
|
||||
return 'B'
|
||||
elseif(c == 'minus') then
|
||||
return '-'
|
||||
end
|
||||
end]],
|
||||
|
||||
["group"] = [[function(unit)
|
||||
local name, server = UnitName(unit)
|
||||
if(server and server ~= "") then
|
||||
name = format("%s-%s", name, server)
|
||||
end
|
||||
|
||||
for i=1, GetNumGroupMembers() do
|
||||
local raidName, _, group = GetRaidRosterInfo(i)
|
||||
if( raidName == name ) then
|
||||
return group
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
["deficit:name"] = [[function(u)
|
||||
local missinghp = _TAGS['missinghp'](u)
|
||||
if(missinghp) then
|
||||
return '-' .. missinghp
|
||||
else
|
||||
return _TAGS['name'](u)
|
||||
end
|
||||
end]],
|
||||
|
||||
['curmana'] = [[function(unit)
|
||||
return UnitPower(unit, SPELL_POWER_MANA)
|
||||
end]],
|
||||
|
||||
['maxmana'] = [[function(unit)
|
||||
return UnitPowerMax(unit, SPELL_POWER_MANA)
|
||||
end]],
|
||||
|
||||
['soulshards'] = [[function()
|
||||
local num = UnitPower('player', SPELL_POWER_SOUL_SHARDS)
|
||||
if(num > 0) then
|
||||
return num
|
||||
end
|
||||
end]],
|
||||
|
||||
['holypower'] = [[function()
|
||||
if(GetSpecialization() == SPEC_PALADIN_RETRIBUTION) then
|
||||
local num = UnitPower('player', SPELL_POWER_HOLY_POWER)
|
||||
if(num > 0) then
|
||||
return num
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
['chi'] = [[function()
|
||||
if(GetSpecialization() == SPEC_MONK_WINDWALKER) then
|
||||
local num = UnitPower('player', SPELL_POWER_CHI)
|
||||
if(num > 0) then
|
||||
return num
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
['arcanecharges'] = [[function()
|
||||
if(GetSpecialization() == SPEC_MAGE_ARCANE) then
|
||||
local num = UnitPower('player', SPELL_POWER_ARCANE_CHARGES)
|
||||
if(num > 0) then
|
||||
return num
|
||||
end
|
||||
end
|
||||
end]],
|
||||
|
||||
['affix'] = [[function(u)
|
||||
local c = UnitClassification(u)
|
||||
if(c == 'minus') then
|
||||
return 'Affix'
|
||||
end
|
||||
end]],
|
||||
|
||||
['powercolor'] = [[function(u)
|
||||
local pType, pToken, altR, altG, altB = UnitPowerType(u)
|
||||
local t = _COLORS.power[pToken]
|
||||
|
||||
if(not t) then
|
||||
if(altR) then
|
||||
if(altR > 1 or altG > 1 or altB > 1) then
|
||||
return Hex(altR / 255, altG / 255, altB / 255)
|
||||
else
|
||||
return Hex(altR, altG, altB)
|
||||
end
|
||||
else
|
||||
return Hex(_COLORS.power[pType])
|
||||
end
|
||||
end
|
||||
|
||||
return Hex(t)
|
||||
end]],
|
||||
}
|
||||
|
||||
local tags = setmetatable(
|
||||
{
|
||||
curhp = UnitHealth,
|
||||
curpp = UnitPower,
|
||||
maxhp = UnitHealthMax,
|
||||
maxpp = UnitPowerMax,
|
||||
class = UnitClass,
|
||||
faction = UnitFactionGroup,
|
||||
race = UnitRace,
|
||||
},
|
||||
|
||||
{
|
||||
__index = function(self, key)
|
||||
local tagFunc = tagStrings[key]
|
||||
if(tagFunc) then
|
||||
local func, err = loadstring('return ' .. tagFunc)
|
||||
if(func) then
|
||||
func = func()
|
||||
|
||||
-- Want to trigger __newindex, so no rawset.
|
||||
self[key] = func
|
||||
tagStrings[key] = nil
|
||||
|
||||
return func
|
||||
else
|
||||
error(err, 3)
|
||||
end
|
||||
end
|
||||
end,
|
||||
__newindex = function(self, key, val)
|
||||
if(type(val) == 'string') then
|
||||
tagStrings[key] = val
|
||||
elseif(type(val) == 'function') then
|
||||
-- So we don't clash with any custom envs.
|
||||
if(getfenv(val) == _G) then
|
||||
setfenv(val, _PROXY)
|
||||
end
|
||||
|
||||
rawset(self, key, val)
|
||||
end
|
||||
end,
|
||||
}
|
||||
)
|
||||
|
||||
_ENV._TAGS = tags
|
||||
|
||||
local tagEvents = {
|
||||
["curhp"] = "UNIT_HEALTH",
|
||||
["dead"] = "UNIT_HEALTH",
|
||||
["leader"] = "PARTY_LEADER_CHANGED",
|
||||
["leaderlong"] = "PARTY_LEADER_CHANGED",
|
||||
["level"] = "UNIT_LEVEL PLAYER_LEVEL_UP",
|
||||
["maxhp"] = "UNIT_MAXHEALTH",
|
||||
["missinghp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
|
||||
["name"] = "UNIT_NAME_UPDATE",
|
||||
["perhp"] = "UNIT_HEALTH UNIT_MAXHEALTH",
|
||||
["pvp"] = "UNIT_FACTION",
|
||||
["resting"] = "PLAYER_UPDATE_RESTING",
|
||||
["smartlevel"] = "UNIT_LEVEL PLAYER_LEVEL_UP UNIT_CLASSIFICATION_CHANGED",
|
||||
["threat"] = "UNIT_THREAT_SITUATION_UPDATE",
|
||||
["threatcolor"] = "UNIT_THREAT_SITUATION_UPDATE",
|
||||
['cpoints'] = 'UNIT_COMBO_POINTS PLAYER_TARGET_CHANGED',
|
||||
['affix'] = 'UNIT_CLASSIFICATION_CHANGED',
|
||||
['plus'] = 'UNIT_CLASSIFICATION_CHANGED',
|
||||
['rare'] = 'UNIT_CLASSIFICATION_CHANGED',
|
||||
['classification'] = 'UNIT_CLASSIFICATION_CHANGED',
|
||||
['shortclassification'] = 'UNIT_CLASSIFICATION_CHANGED',
|
||||
["group"] = "GROUP_ROSTER_UPDATE",
|
||||
["curpp"] = 'UNIT_POWER',
|
||||
["maxpp"] = 'UNIT_MAXPOWER',
|
||||
["missingpp"] = 'UNIT_MAXPOWER UNIT_POWER',
|
||||
["perpp"] = 'UNIT_MAXPOWER UNIT_POWER',
|
||||
["offline"] = "UNIT_HEALTH UNIT_CONNECTION",
|
||||
["status"] = "UNIT_HEALTH PLAYER_UPDATE_RESTING UNIT_CONNECTION",
|
||||
['curmana'] = 'UNIT_POWER UNIT_MAXPOWER',
|
||||
['maxmana'] = 'UNIT_POWER UNIT_MAXPOWER',
|
||||
['soulshards'] = 'UNIT_POWER',
|
||||
['holypower'] = 'UNIT_POWER SPELLS_CHANGED',
|
||||
['chi'] = 'UNIT_POWER SPELLS_CHANGED',
|
||||
['arcanecharges'] = 'UNIT_POWER SPELLS_CHANGED',
|
||||
['powercolor'] = 'UNIT_DISPLAYPOWER',
|
||||
}
|
||||
|
||||
local unitlessEvents = {
|
||||
PLAYER_LEVEL_UP = true,
|
||||
PLAYER_UPDATE_RESTING = true,
|
||||
PLAYER_TARGET_CHANGED = true,
|
||||
|
||||
PARTY_LEADER_CHANGED = true,
|
||||
|
||||
GROUP_ROSTER_UPDATE = true,
|
||||
|
||||
UNIT_COMBO_POINTS = true
|
||||
}
|
||||
|
||||
local events = {}
|
||||
local frame = CreateFrame"Frame"
|
||||
frame:SetScript('OnEvent', function(self, event, unit)
|
||||
local strings = events[event]
|
||||
if(strings) then
|
||||
for k, fontstring in next, strings do
|
||||
if(fontstring:IsVisible() and (unitlessEvents[event] or fontstring.parent.unit == unit)) then
|
||||
fontstring:UpdateTag()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local OnUpdates = {}
|
||||
local eventlessUnits = {}
|
||||
|
||||
local createOnUpdate = function(timer)
|
||||
local OnUpdate = OnUpdates[timer]
|
||||
|
||||
if(not OnUpdate) then
|
||||
local total = timer
|
||||
local frame = CreateFrame'Frame'
|
||||
local strings = eventlessUnits[timer]
|
||||
|
||||
frame:SetScript('OnUpdate', function(self, elapsed)
|
||||
if(total >= timer) then
|
||||
for k, fs in next, strings do
|
||||
if(fs.parent:IsVisible() and UnitExists(fs.parent.unit)) then
|
||||
fs:UpdateTag()
|
||||
end
|
||||
end
|
||||
|
||||
total = 0
|
||||
end
|
||||
|
||||
total = total + elapsed
|
||||
end)
|
||||
|
||||
OnUpdates[timer] = frame
|
||||
end
|
||||
end
|
||||
|
||||
local OnShow = function(self)
|
||||
for _, fs in next, self.__tags do
|
||||
fs:UpdateTag()
|
||||
end
|
||||
end
|
||||
|
||||
local getTagName = function(tag)
|
||||
local s = (tag:match('>+()') or 2)
|
||||
local e = tag:match('.*()<+')
|
||||
e = (e and e - 1) or -2
|
||||
|
||||
return tag:sub(s, e), s, e
|
||||
end
|
||||
|
||||
local RegisterEvent = function(fontstr, event)
|
||||
if(not events[event]) then events[event] = {} end
|
||||
|
||||
frame:RegisterEvent(event)
|
||||
tinsert(events[event], fontstr)
|
||||
end
|
||||
|
||||
local RegisterEvents = function(fontstr, tagstr)
|
||||
for tag in tagstr:gmatch(_PATTERN) do
|
||||
tag = getTagName(tag)
|
||||
local tagevents = tagEvents[tag]
|
||||
if(tagevents) then
|
||||
for event in tagevents:gmatch'%S+' do
|
||||
RegisterEvent(fontstr, event)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local UnregisterEvents = function(fontstr)
|
||||
for event, data in pairs(events) do
|
||||
for k, tagfsstr in pairs(data) do
|
||||
if(tagfsstr == fontstr) then
|
||||
if(#data == 1) then
|
||||
frame:UnregisterEvent(event)
|
||||
end
|
||||
|
||||
tremove(data, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local OnEnter = function(self)
|
||||
for _, fs in pairs(self.__mousetags) do
|
||||
fs:SetAlpha(1)
|
||||
end
|
||||
end
|
||||
|
||||
local OnLeave = function(self)
|
||||
for _, fs in pairs(self.__mousetags) do
|
||||
fs:SetAlpha(0)
|
||||
end
|
||||
end
|
||||
|
||||
local onUpdateDelay = {}
|
||||
local tagPool = {}
|
||||
local funcPool = {}
|
||||
local tmp = {}
|
||||
local escapeSequences = {
|
||||
["||c"] = "|c",
|
||||
["||r"] = "|r",
|
||||
["||T"] = "|T",
|
||||
["||t"] = "|t",
|
||||
}
|
||||
|
||||
local Tag = function(self, fs, tagstr)
|
||||
if(not fs or not tagstr) then return end
|
||||
|
||||
if(not self.__tags) then
|
||||
self.__tags = {}
|
||||
self.__mousetags = {}
|
||||
tinsert(self.__elements, OnShow)
|
||||
else
|
||||
-- Since people ignore everything that's good practice - unregister the tag
|
||||
-- if it already exists.
|
||||
for _, tag in pairs(self.__tags) do
|
||||
if(fs == tag) then
|
||||
-- We don't need to remove it from the __tags table as Untag handles
|
||||
-- that for us.
|
||||
self:Untag(fs)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
fs.parent = self
|
||||
|
||||
for escapeSequence, replacement in pairs(escapeSequences) do
|
||||
while tagstr:find(escapeSequence) do
|
||||
tagstr = tagstr:gsub(escapeSequence, replacement)
|
||||
end
|
||||
end
|
||||
|
||||
if tagstr:find('%[mouseover%]') then
|
||||
tinsert(self.__mousetags, fs)
|
||||
fs:SetAlpha(0)
|
||||
if not self.__HookFunc then
|
||||
self:HookScript('OnEnter', OnEnter)
|
||||
self:HookScript('OnLeave', OnLeave)
|
||||
self.__HookFunc = true;
|
||||
end
|
||||
tagstr = tagstr:gsub('%[mouseover%]', '')
|
||||
else
|
||||
for index, fontString in pairs(self.__mousetags) do
|
||||
if fontString == fs then
|
||||
self.__mousetags[index] = nil;
|
||||
fs:SetAlpha(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local containsOnUpdate
|
||||
for tag in tagstr:gmatch(_PATTERN) do
|
||||
if not tagEvents[tag:sub(2, -2)] then
|
||||
containsOnUpdate = onUpdateDelay[tag:sub(2, -2)] or 0.15;
|
||||
end
|
||||
end
|
||||
|
||||
local func = tagPool[tagstr]
|
||||
if(not func) then
|
||||
local format, numTags = tagstr:gsub('%%', '%%%%'):gsub(_PATTERN, '%%s')
|
||||
local args = {}
|
||||
|
||||
for bracket in tagstr:gmatch(_PATTERN) do
|
||||
local tagFunc = funcPool[bracket] or tags[bracket:sub(2, -2)]
|
||||
if(not tagFunc) then
|
||||
local tagName, s, e = getTagName(bracket)
|
||||
|
||||
local tag = tags[tagName]
|
||||
if(tag) then
|
||||
s = s - 2
|
||||
e = e + 2
|
||||
|
||||
if(s ~= 0 and e ~= 0) then
|
||||
local pre = bracket:sub(2, s)
|
||||
local ap = bracket:sub(e, -2)
|
||||
|
||||
tagFunc = function(u,r)
|
||||
local str = tag(u,r)
|
||||
if(str) then
|
||||
return pre..str..ap
|
||||
end
|
||||
end
|
||||
elseif(s ~= 0) then
|
||||
local pre = bracket:sub(2, s)
|
||||
|
||||
tagFunc = function(u,r)
|
||||
local str = tag(u,r)
|
||||
if(str) then
|
||||
return pre..str
|
||||
end
|
||||
end
|
||||
elseif(e ~= 0) then
|
||||
local ap = bracket:sub(e, -2)
|
||||
|
||||
tagFunc = function(u,r)
|
||||
local str = tag(u,r)
|
||||
if(str) then
|
||||
return str..ap
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
funcPool[bracket] = tagFunc
|
||||
end
|
||||
end
|
||||
|
||||
if(tagFunc) then
|
||||
tinsert(args, tagFunc)
|
||||
else
|
||||
numTags = -1
|
||||
func = function(self)
|
||||
return self:SetFormattedText('[invalid tag]')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(numTags == 1) then
|
||||
func = function(self)
|
||||
local parent = self.parent
|
||||
local realUnit
|
||||
if(self.overrideUnit) then
|
||||
realUnit = parent.realUnit
|
||||
end
|
||||
|
||||
_ENV._COLORS = parent.colors
|
||||
return self:SetFormattedText(
|
||||
format,
|
||||
args[1](parent.unit, realUnit) or ''
|
||||
)
|
||||
end
|
||||
elseif(numTags == 2) then
|
||||
func = function(self)
|
||||
local parent = self.parent
|
||||
local unit = parent.unit
|
||||
local realUnit
|
||||
if(self.overrideUnit) then
|
||||
realUnit = parent.realUnit
|
||||
end
|
||||
|
||||
_ENV._COLORS = parent.colors
|
||||
return self:SetFormattedText(
|
||||
format,
|
||||
args[1](unit, realUnit) or '',
|
||||
args[2](unit, realUnit) or ''
|
||||
)
|
||||
end
|
||||
elseif(numTags == 3) then
|
||||
func = function(self)
|
||||
local parent = self.parent
|
||||
local unit = parent.unit
|
||||
local realUnit
|
||||
if(self.overrideUnit) then
|
||||
realUnit = parent.realUnit
|
||||
end
|
||||
|
||||
_ENV._COLORS = parent.colors
|
||||
return self:SetFormattedText(
|
||||
format,
|
||||
args[1](unit, realUnit) or '',
|
||||
args[2](unit, realUnit) or '',
|
||||
args[3](unit, realUnit) or ''
|
||||
)
|
||||
end
|
||||
elseif numTags ~= -1 then
|
||||
func = function(self)
|
||||
local parent = self.parent
|
||||
local unit = parent.unit
|
||||
local realUnit
|
||||
if(self.overrideUnit) then
|
||||
realUnit = parent.realUnit
|
||||
end
|
||||
|
||||
_ENV._COLORS = parent.colors
|
||||
for i, func in next, args do
|
||||
tmp[i] = func(unit, realUnit) or ''
|
||||
end
|
||||
|
||||
-- We do 1, numTags because tmp can hold several unneeded variables.
|
||||
return self:SetFormattedText(format, unpack(tmp, 1, numTags))
|
||||
end
|
||||
end
|
||||
|
||||
if numTags ~= -1 then
|
||||
tagPool[tagstr] = func
|
||||
end
|
||||
end
|
||||
fs.UpdateTag = func
|
||||
|
||||
local unit = self.unit
|
||||
if(self.__eventless or fs.frequentUpdates) or containsOnUpdate then
|
||||
local timer
|
||||
if(type(fs.frequentUpdates) == 'number') then
|
||||
timer = fs.frequentUpdates
|
||||
elseif containsOnUpdate then
|
||||
timer = containsOnUpdate
|
||||
else
|
||||
timer = .5
|
||||
end
|
||||
|
||||
if(not eventlessUnits[timer]) then eventlessUnits[timer] = {} end
|
||||
tinsert(eventlessUnits[timer], fs)
|
||||
|
||||
createOnUpdate(timer)
|
||||
else
|
||||
RegisterEvents(fs, tagstr)
|
||||
end
|
||||
|
||||
tinsert(self.__tags, fs)
|
||||
end
|
||||
|
||||
local Untag = function(self, fs)
|
||||
if(not fs) then return end
|
||||
|
||||
UnregisterEvents(fs)
|
||||
for _, timers in next, eventlessUnits do
|
||||
for k, fontstr in next, timers do
|
||||
if(fs == fontstr) then
|
||||
tremove(timers, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k, fontstr in next, self.__tags do
|
||||
if(fontstr == fs) then
|
||||
tremove(self.__tags, k)
|
||||
end
|
||||
end
|
||||
|
||||
fs.UpdateTag = nil
|
||||
end
|
||||
|
||||
oUF.Tags = {
|
||||
Methods = tags,
|
||||
Events = tagEvents,
|
||||
SharedEvents = unitlessEvents,
|
||||
OnUpdateThrottle = onUpdateDelay,
|
||||
}
|
||||
oUF:RegisterMetaFunction('Tag', Tag)
|
||||
oUF:RegisterMetaFunction('Untag', Untag)
|
||||
97
Libraries/oUF/elements/threat.lua
Normal file
97
Libraries/oUF/elements/threat.lua
Normal file
@@ -0,0 +1,97 @@
|
||||
--[[ Element: Threat Icon
|
||||
|
||||
Handles updating and toggles visibility of current threat level icon.
|
||||
|
||||
Widget
|
||||
|
||||
Threat - A Texture used to display the current threat level.
|
||||
|
||||
Notes
|
||||
|
||||
This element updates by changing colors of the texture.
|
||||
|
||||
The default threat icon will be used if the UI widget is a texture and doesn't
|
||||
have a texture or color defined.
|
||||
|
||||
Examples
|
||||
|
||||
-- Position and size
|
||||
local Threat = self:CreateTexture(nil, 'OVERLAY')
|
||||
Threat:SetSize(16, 16)
|
||||
Threat:SetPoint('TOPRIGHT', self)
|
||||
|
||||
-- Register it with oUF
|
||||
self.Threat = Threat
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local Update = function(self, event, unit)
|
||||
if(unit ~= self.unit) or not unit or not IsLoggedIn() then return end
|
||||
|
||||
local threat = self.Threat
|
||||
if(threat.PreUpdate) then threat:PreUpdate(unit) end
|
||||
|
||||
local status = UnitThreatSituation(unit)
|
||||
|
||||
local r, g, b
|
||||
if(status and status > 0) then
|
||||
r, g, b = GetThreatStatusColor(status)
|
||||
|
||||
if threat:IsObjectType"Texture" then
|
||||
threat:SetVertexColor(r, g, b)
|
||||
end
|
||||
threat:Show()
|
||||
else
|
||||
threat:Hide()
|
||||
end
|
||||
|
||||
if(threat.PostUpdate) then
|
||||
return threat:PostUpdate(unit, status, r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.Threat.Override or Update) (self, ...)
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Path(element.__owner, 'ForceUpdate', element.__owner.unit)
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local threat = self.Threat
|
||||
if(threat) then
|
||||
threat.__owner = self
|
||||
threat.ForceUpdate = ForceUpdate
|
||||
|
||||
self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE", Path)
|
||||
self:RegisterEvent("UNIT_THREAT_LIST_UPDATE", Path)
|
||||
|
||||
if(threat:IsObjectType"Texture" and not threat:GetTexture()) then
|
||||
threat:SetTexture[[Interface\Minimap\ObjectIcons]]
|
||||
threat:SetTexCoord(6/8, 7/8, 1/8, 2/8)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local threat = self.Threat
|
||||
if(threat) then
|
||||
threat:Hide()
|
||||
self:UnregisterEvent("UNIT_THREAT_SITUATION_UPDATE", Path)
|
||||
self:UnregisterEvent("UNIT_THREAT_LIST_UPDATE", Path)
|
||||
threat:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement('Threat', Path, Enable, Disable)
|
||||
167
Libraries/oUF/elements/totems.lua
Normal file
167
Libraries/oUF/elements/totems.lua
Normal file
@@ -0,0 +1,167 @@
|
||||
--[[ Element: Totem Indicator
|
||||
|
||||
Handles updating and visibility of Shaman totems, Druid mushrooms and Death
|
||||
Knight ghouls.
|
||||
|
||||
Widget
|
||||
|
||||
Totems - A table to hold sub-widgets.
|
||||
|
||||
Sub-Widgets
|
||||
|
||||
Totem - Any UI widget.
|
||||
.Icon - A Texture representing the totem icon.
|
||||
.Cooldown - A Cooldown representing the duration of the totem.
|
||||
|
||||
Notes
|
||||
|
||||
OnEnter and OnLeave will be set to display the default Tooltip, if the
|
||||
`Totem` widget is mouse enabled.
|
||||
|
||||
Options
|
||||
|
||||
:UpdateTooltip - The function that should populate the tooltip, when the
|
||||
`Totem` widget is hovered. A default function, which calls
|
||||
`:SetTotem(id)`, will be used if none is defined.
|
||||
|
||||
Examples
|
||||
|
||||
local Totems = {}
|
||||
for index = 1, MAX_TOTEMS do
|
||||
-- Position and size of the totem indicator
|
||||
local Totem = CreateFrame('Button', nil, self)
|
||||
Totem:SetSize(40, 40)
|
||||
Totem:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', index * Totem:GetWidth(), 0)
|
||||
|
||||
local Icon = Totem:CreateTexture(nil, "OVERLAY")
|
||||
Icon:SetAllPoints()
|
||||
|
||||
local Cooldown = CreateFrame("Cooldown", nil, Totem, "CooldownFrameTemplate")
|
||||
Cooldown:SetAllPoints()
|
||||
|
||||
Totem.Icon = Icon
|
||||
Totem.Cooldown = Cooldown
|
||||
|
||||
Totems[index] = Totem
|
||||
end
|
||||
|
||||
-- Register with oUF
|
||||
self.Totems = Totems
|
||||
|
||||
Hooks
|
||||
|
||||
Override(self) - Used to completely override the internal update function.
|
||||
Removing the table key entry will make the element fall-back
|
||||
to its internal function again.
|
||||
]]
|
||||
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
|
||||
local UpdateTooltip = function(self)
|
||||
GameTooltip:SetTotem(self:GetID())
|
||||
end
|
||||
|
||||
local OnEnter = function(self)
|
||||
if(not self:IsVisible()) then return end
|
||||
|
||||
GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT')
|
||||
self:UpdateTooltip()
|
||||
end
|
||||
|
||||
local OnLeave = function()
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
local UpdateTotem = function(self, event, slot)
|
||||
local totems = self.Totems
|
||||
if(slot > #totems) then return end
|
||||
|
||||
if(totems.PreUpdate) then totems:PreUpdate(slot) end
|
||||
|
||||
local totem = totems[slot]
|
||||
local haveTotem, name, start, duration, icon = GetTotemInfo(slot)
|
||||
if(haveTotem and duration > 0) then
|
||||
if(totem.Icon) then
|
||||
totem.Icon:SetTexture(icon)
|
||||
end
|
||||
|
||||
if(totem.Cooldown) then
|
||||
totem.Cooldown:SetCooldown(start, duration)
|
||||
end
|
||||
|
||||
totem:Show()
|
||||
else
|
||||
totem:Hide()
|
||||
end
|
||||
|
||||
if(totems.PostUpdate) then
|
||||
return totems:PostUpdate(slot, haveTotem, name, start, duration, icon)
|
||||
end
|
||||
end
|
||||
|
||||
local Path = function(self, ...)
|
||||
return (self.Totems.Override or UpdateTotem) (self, ...)
|
||||
end
|
||||
|
||||
local Update = function(self, event)
|
||||
for i = 1, #self.Totems do
|
||||
Path(self, event, i)
|
||||
end
|
||||
end
|
||||
|
||||
local ForceUpdate = function(element)
|
||||
return Update(element.__owner, 'ForceUpdate')
|
||||
end
|
||||
|
||||
local Enable = function(self)
|
||||
local totems = self.Totems
|
||||
|
||||
if(totems) then
|
||||
totems.__owner = self
|
||||
totems.ForceUpdate = ForceUpdate
|
||||
|
||||
for i = 1, #totems do
|
||||
local totem = totems[i]
|
||||
|
||||
totem:SetID(i)
|
||||
|
||||
if(totem:IsMouseEnabled()) then
|
||||
totem:SetScript('OnEnter', OnEnter)
|
||||
totem:SetScript('OnLeave', OnLeave)
|
||||
|
||||
if(not totem.UpdateTooltip) then
|
||||
totem.UpdateTooltip = UpdateTooltip
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:RegisterEvent('PLAYER_TOTEM_UPDATE', Path, true)
|
||||
|
||||
TotemFrame:UnregisterEvent"PLAYER_TOTEM_UPDATE"
|
||||
TotemFrame:UnregisterEvent"PLAYER_ENTERING_WORLD"
|
||||
TotemFrame:UnregisterEvent"UPDATE_SHAPESHIFT_FORM"
|
||||
TotemFrame:UnregisterEvent"PLAYER_TALENT_UPDATE"
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local Disable = function(self)
|
||||
local totems = self.Totems
|
||||
|
||||
if(totems) then
|
||||
for i = 1, #totems do
|
||||
totems[i]:Hide()
|
||||
end
|
||||
|
||||
TotemFrame:RegisterEvent"PLAYER_TOTEM_UPDATE"
|
||||
TotemFrame:RegisterEvent"PLAYER_ENTERING_WORLD"
|
||||
TotemFrame:RegisterEvent"UPDATE_SHAPESHIFT_FORM"
|
||||
TotemFrame:RegisterEvent"PLAYER_TALENT_UPDATE"
|
||||
|
||||
self:UnregisterEvent('PLAYER_TOTEM_UPDATE', Path)
|
||||
end
|
||||
end
|
||||
|
||||
oUF:AddElement("Totems", Update, Enable, Disable)
|
||||
127
Libraries/oUF/events.lua
Normal file
127
Libraries/oUF/events.lua
Normal file
@@ -0,0 +1,127 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local argcheck = Private.argcheck
|
||||
local error = Private.error
|
||||
local frame_metatable = Private.frame_metatable
|
||||
|
||||
-- Original event methods
|
||||
local RegisterEvent = frame_metatable.__index.RegisterEvent
|
||||
local RegisterUnitEvent = frame_metatable.__index.RegisterUnitEvent
|
||||
local UnregisterEvent = frame_metatable.__index.UnregisterEvent
|
||||
local IsEventRegistered = frame_metatable.__index.IsEventRegistered
|
||||
|
||||
local unitEvents = {}
|
||||
|
||||
Private.UpdateUnits = function(frame, unit, realUnit)
|
||||
if unit == realUnit then
|
||||
realUnit = nil
|
||||
end
|
||||
if frame.unit ~= unit or frame.realUnit ~= realUnit then
|
||||
for event in next, unitEvents do
|
||||
-- IsEventRegistered returns the units in case of an event
|
||||
-- registered with RegisterUnitEvent
|
||||
local registered, unit1 = IsEventRegistered(frame, event)
|
||||
if registered and unit1 ~= unit then
|
||||
-- RegisterUnitEvent erases previously registered units so
|
||||
-- do not bother to unregister it
|
||||
RegisterUnitEvent(frame, event, unit, realUnit)
|
||||
end
|
||||
end
|
||||
frame.unit = unit
|
||||
frame.realUnit = realUnit
|
||||
frame.id = unit:match'^.-(%d+)'
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local OnEvent = function(self, event, ...)
|
||||
if self:IsVisible() or event == 'UNIT_COMBO_POINTS' then
|
||||
return self[event](self, event, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local event_metatable = {
|
||||
__call = function(funcs, self, ...)
|
||||
for _, func in next, funcs do
|
||||
func(self, ...)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
function frame_metatable.__index:RegisterEvent(event, func, unitless)
|
||||
-- Block OnUpdate polled frames from registering events.
|
||||
if(self.__eventless) then return end
|
||||
|
||||
argcheck(event, 2, 'string')
|
||||
|
||||
if(type(func) == 'string' and type(self[func]) == 'function') then
|
||||
func = self[func]
|
||||
end
|
||||
|
||||
-- TODO: should warn the user.
|
||||
if not unitless and not (unitEvents[event] or event:match'^UNIT_') then
|
||||
unitless = true
|
||||
end
|
||||
|
||||
local curev = self[event]
|
||||
local kind = type(curev)
|
||||
if(curev and func) then
|
||||
if(kind == 'function' and curev ~= func) then
|
||||
self[event] = setmetatable({curev, func}, event_metatable)
|
||||
elseif(kind == 'table') then
|
||||
for _, infunc in next, curev do
|
||||
if(infunc == func) then return end
|
||||
end
|
||||
|
||||
table.insert(curev, func)
|
||||
end
|
||||
elseif(IsEventRegistered(self, event)) then
|
||||
return
|
||||
else
|
||||
if(type(func) == 'function') then
|
||||
self[event] = func
|
||||
elseif(not self[event]) then
|
||||
return error("Style [%s] attempted to register event [%s] on unit [%s] with a handler that doesn't exist.", self.style, event, self.unit or 'unknown')
|
||||
end
|
||||
|
||||
if not self:GetScript('OnEvent') then
|
||||
self:SetScript('OnEvent', OnEvent)
|
||||
end
|
||||
|
||||
if unitless then
|
||||
RegisterEvent(self, event)
|
||||
else
|
||||
unitEvents[event] = true
|
||||
RegisterUnitEvent(self, event, self.unit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function frame_metatable.__index:UnregisterEvent(event, func)
|
||||
argcheck(event, 2, 'string')
|
||||
|
||||
local curev = self[event]
|
||||
if(type(curev) == 'table' and func) then
|
||||
for k, infunc in next, curev do
|
||||
if(infunc == func) then
|
||||
table.remove(curev, k)
|
||||
|
||||
local n = #curev
|
||||
if(n == 1) then
|
||||
local _, handler = next(curev)
|
||||
self[event] = handler
|
||||
elseif(n == 0) then
|
||||
-- This should not happen
|
||||
UnregisterEvent(self, event)
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif(curev == func) then
|
||||
self[event] = nil
|
||||
UnregisterEvent(self, event)
|
||||
end
|
||||
end
|
||||
48
Libraries/oUF/factory.lua
Normal file
48
Libraries/oUF/factory.lua
Normal file
@@ -0,0 +1,48 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local argcheck = Private.argcheck
|
||||
|
||||
local _QUEUE = {}
|
||||
local _FACTORY = CreateFrame'Frame'
|
||||
_FACTORY:SetScript('OnEvent', function(self, event, ...)
|
||||
return self[event](self, event, ...)
|
||||
end)
|
||||
|
||||
_FACTORY:RegisterEvent'PLAYER_LOGIN'
|
||||
_FACTORY.active = true
|
||||
|
||||
function _FACTORY:PLAYER_LOGIN()
|
||||
if(not self.active) then return end
|
||||
|
||||
for _, func in next, _QUEUE do
|
||||
func(oUF)
|
||||
end
|
||||
|
||||
-- Avoid creating dupes.
|
||||
wipe(_QUEUE)
|
||||
end
|
||||
|
||||
function oUF:Factory(func)
|
||||
argcheck(func, 2, 'function')
|
||||
|
||||
-- Call the function directly if we're active and logged in.
|
||||
if(IsLoggedIn() and _FACTORY.active) then
|
||||
return func(self)
|
||||
else
|
||||
table.insert(_QUEUE, func)
|
||||
end
|
||||
end
|
||||
|
||||
function oUF:EnableFactory()
|
||||
_FACTORY.active = true
|
||||
end
|
||||
|
||||
function oUF:DisableFactory()
|
||||
_FACTORY.active = nil
|
||||
end
|
||||
|
||||
function oUF:RunFactoryQueue()
|
||||
_FACTORY:PLAYER_LOGIN()
|
||||
end
|
||||
4
Libraries/oUF/finalize.lua
Normal file
4
Libraries/oUF/finalize.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
local parent, ns = ...
|
||||
|
||||
-- It's named Private for a reason!
|
||||
ns.oUF.Private = nil
|
||||
3
Libraries/oUF/init.lua
Normal file
3
Libraries/oUF/init.lua
Normal file
@@ -0,0 +1,3 @@
|
||||
local parent, ns = ...
|
||||
ns.oUF = {}
|
||||
ns.oUF.Private = {}
|
||||
11
Libraries/oUF/oUF.toc
Normal file
11
Libraries/oUF/oUF.toc
Normal file
@@ -0,0 +1,11 @@
|
||||
## Interface: 60000
|
||||
## Title: oUF
|
||||
## Author: Haste
|
||||
## Version: 1.6.8
|
||||
## OptionalDeps: Clique
|
||||
## X-eMail: troeks@gmail.com
|
||||
## X-oUF: oUF
|
||||
## Notes: Unit frame framework. Does nothing by itself.
|
||||
## Notes-ruRU: Каркас для модификации фреймов игроков. Сам по себе не делает ничего.
|
||||
|
||||
oUF.xml
|
||||
101
Libraries/oUF/oUF.xml
Normal file
101
Libraries/oUF/oUF.xml
Normal file
@@ -0,0 +1,101 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Script file='init.lua' />
|
||||
<Script file='private.lua' />
|
||||
<Script file='ouf.lua' />
|
||||
<Script file='events.lua'/>
|
||||
<Script file='factory.lua' />
|
||||
<Script file='blizzard.lua' />
|
||||
<Script file='units.lua' />
|
||||
<Script file='colors.lua' />
|
||||
<Script file='finalize.lua' />
|
||||
|
||||
<Script file='elements\power.lua' />
|
||||
<Script file='elements\aura.lua' />
|
||||
<Script file='elements\health.lua' />
|
||||
<Script file='elements\ricons.lua' />
|
||||
<Script file='elements\leader.lua' />
|
||||
<Script file='elements\combat.lua' />
|
||||
<Script file='elements\resting.lua' />
|
||||
<Script file='elements\pvp.lua' />
|
||||
<Script file='elements\portraits.lua' />
|
||||
<Script file='elements\range.lua' />
|
||||
<Script file='elements\castbar.lua' />
|
||||
<Script file='elements\threat.lua' />
|
||||
<Script file='elements\tags.lua' />
|
||||
<Script file='elements\masterlooter.lua' />
|
||||
<Script file='elements\assistant.lua' />
|
||||
<Script file='elements\runebar.lua' />
|
||||
<Script file='elements\lfdrole.lua' />
|
||||
<Script file='elements\healprediction.lua' />
|
||||
<Script file='elements\powerprediction.lua' />
|
||||
<Script file='elements\picon.lua' />
|
||||
<Script file='elements\readycheck.lua' />
|
||||
<Script file='elements\qicon.lua' />
|
||||
<Script file='elements\altpowerbar.lua' />
|
||||
<Script file='elements\totems.lua' />
|
||||
<Script file='elements\resurrect.lua' />
|
||||
<Script file='elements\raidrole.lua' />
|
||||
<Script file='elements\additionalpower.lua' />
|
||||
<Script file='elements\classicons.lua' />
|
||||
<Script file='elements\stagger.lua' />
|
||||
|
||||
<!-- Clique support -->
|
||||
<Button name="oUF_ClickCastUnitTemplate" virtual="true" inherits="SecureUnitButtonTemplate,SecureHandlerEnterLeaveTemplate">
|
||||
<Attributes>
|
||||
<Attribute name="_onenter" type="string" value="local snippet = self:GetAttribute('clickcast_onenter'); if snippet then self:Run(snippet) end"/>
|
||||
<Attribute name="_onleave" type="string" value="local snippet = self:GetAttribute('clickcast_onleave'); if snippet then self:Run(snippet) end"/>
|
||||
</Attributes>
|
||||
</Button>
|
||||
|
||||
<!-- Pet Battle Hider Frame -->
|
||||
<Frame name="oUF_PetBattleFrameHider" frameStrata="LOW" inherits="SecureHandlerStateTemplate" parent="UIParent" setAllPoints="true">
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
RegisterStateDriver(self, "visibility", "[petbattle] hide; show")
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
|
||||
<!--
|
||||
Sub-object as a child of the parent unit frame:
|
||||
<Button name="oUF_HeaderTargetTemplate" inherits="SecureUnitButtonTemplate" virtual="true">
|
||||
<Frames>
|
||||
<Button name="$parentTarget" inherits="SecureUnitButtonTemplate">
|
||||
<Attributes>
|
||||
<Attribute name="unitsuffix" type="string" value="target"/>
|
||||
<Attribute name="useparent-unit" type="boolean" value="true"/>
|
||||
</Attributes>
|
||||
</Button>
|
||||
</Frames>
|
||||
</Button>
|
||||
|
||||
Separate unit template example:
|
||||
<Button name="oUF_HeaderSeparateSubOjectsTemplate" inherits="SecureUnitButtonTemplate" virtual="true">
|
||||
<Attributes>
|
||||
<Attribute name="oUF-onlyProcessChildren" type="boolean" value="true"/>
|
||||
</Attributes>
|
||||
|
||||
<Frames>
|
||||
<Button name="$parentUnit" inherits="SecureUnitButtonTemplate">
|
||||
<Attributes>
|
||||
<Attribute name="useparent-unit" type="boolean" value="true"/>
|
||||
</Attributes>
|
||||
</Button>
|
||||
|
||||
<Button name="$parentPet" inherits="SecureUnitButtonTemplate">
|
||||
<Attributes>
|
||||
<Attribute name="unitsuffix" type="string" value="pet"/>
|
||||
<Attribute name="useparent-unit" type="boolean" value="true"/>
|
||||
</Attributes>
|
||||
</Button>
|
||||
|
||||
<Button name="$parentTarget" inherits="SecureUnitButtonTemplate">
|
||||
<Attributes>
|
||||
<Attribute name="unitsuffix" type="string" value="target"/>
|
||||
<Attribute name="useparent-unit" type="boolean" value="true"/>
|
||||
</Attributes>
|
||||
</Button>
|
||||
</Frames>
|
||||
</Button>
|
||||
-->
|
||||
</Ui>
|
||||
599
Libraries/oUF/ouf.lua
Normal file
599
Libraries/oUF/ouf.lua
Normal file
@@ -0,0 +1,599 @@
|
||||
local parent, ns = ...
|
||||
local global = GetAddOnMetadata(parent, 'X-oUF')
|
||||
local _VERSION = GetAddOnMetadata(parent, 'version')
|
||||
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local argcheck = Private.argcheck
|
||||
|
||||
local print = Private.print
|
||||
local error = Private.error
|
||||
|
||||
local styles, style = {}
|
||||
local callback, objects, headers = {}, {}, {}
|
||||
|
||||
local elements = {}
|
||||
local activeElements = {}
|
||||
|
||||
-- updating of "invalid" units.
|
||||
local enableTargetUpdate = function(object)
|
||||
object.onUpdateFrequency = object.onUpdateFrequency or .5
|
||||
object.__eventless = true
|
||||
|
||||
local total = 0
|
||||
object:SetScript('OnUpdate', function(self, elapsed)
|
||||
if(not self.unit) then
|
||||
return
|
||||
elseif(total > self.onUpdateFrequency) then
|
||||
self:UpdateAllElements'OnUpdate'
|
||||
total = 0
|
||||
end
|
||||
|
||||
total = total + elapsed
|
||||
end)
|
||||
end
|
||||
Private.enableTargetUpdate = enableTargetUpdate
|
||||
|
||||
local updateActiveUnit = function(self, event, unit)
|
||||
-- Calculate units to work with
|
||||
local realUnit, modUnit = SecureButton_GetUnit(self), SecureButton_GetModifiedUnit(self)
|
||||
|
||||
-- _GetUnit() doesn't rewrite playerpet -> pet like _GetModifiedUnit does.
|
||||
if(realUnit == 'playerpet') then
|
||||
realUnit = 'pet'
|
||||
elseif(realUnit == 'playertarget') then
|
||||
realUnit = 'target'
|
||||
end
|
||||
|
||||
if(modUnit == 'pet' and realUnit ~= 'pet') then
|
||||
modUnit = 'vehicle'
|
||||
end
|
||||
|
||||
if(not UnitExists(modUnit)) then return end
|
||||
|
||||
-- Change the active unit and run a full update.
|
||||
if Private.UpdateUnits(self, modUnit, realUnit) then
|
||||
self:UpdateAllElements('RefreshUnit')
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local iterateChildren = function(...)
|
||||
for l = 1, select("#", ...) do
|
||||
local obj = select(l, ...)
|
||||
|
||||
if(type(obj) == 'table' and obj.isChild) then
|
||||
updateActiveUnit(obj, "iterateChildren")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local OnAttributeChanged = function(self, name, value)
|
||||
if(name == "unit" and value) then
|
||||
if(self.hasChildren) then
|
||||
iterateChildren(self:GetChildren())
|
||||
end
|
||||
|
||||
if(not self:GetAttribute'oUF-onlyProcessChildren') then
|
||||
updateActiveUnit(self, "OnAttributeChanged")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local frame_metatable = {
|
||||
__index = CreateFrame"Button"
|
||||
}
|
||||
Private.frame_metatable = frame_metatable
|
||||
|
||||
for k, v in pairs{
|
||||
UpdateElement = function(self, name)
|
||||
local unit = self.unit
|
||||
if(not unit or not UnitExists(unit)) then return end
|
||||
|
||||
local element = elements[name]
|
||||
if(not element or not self:IsElementEnabled(name) or not activeElements[self]) then return end
|
||||
if(element.update) then
|
||||
element.update(self, 'OnShow', unit)
|
||||
end
|
||||
end,
|
||||
|
||||
EnableElement = function(self, name, unit)
|
||||
argcheck(name, 2, 'string')
|
||||
argcheck(unit, 3, 'string', 'nil')
|
||||
|
||||
local element = elements[name]
|
||||
if(not element or self:IsElementEnabled(name) or not activeElements[self]) then return end
|
||||
|
||||
if(element.enable(self, unit or self.unit)) then
|
||||
activeElements[self][name] = true
|
||||
|
||||
if(element.update) then
|
||||
table.insert(self.__elements, element.update)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
DisableElement = function(self, name)
|
||||
argcheck(name, 2, 'string')
|
||||
|
||||
local enabled = self:IsElementEnabled(name)
|
||||
if(not enabled) then return end
|
||||
|
||||
local update = elements[name].update
|
||||
for k, func in next, self.__elements do
|
||||
if(func == update) then
|
||||
table.remove(self.__elements, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
activeElements[self][name] = nil
|
||||
|
||||
-- We need to run a new update cycle in-case we knocked ourself out of sync.
|
||||
-- The main reason we do this is to make sure the full update is completed
|
||||
-- if an element for some reason removes itself _during_ the update
|
||||
-- progress.
|
||||
self:UpdateAllElements('DisableElement', name)
|
||||
|
||||
return elements[name].disable(self)
|
||||
end,
|
||||
|
||||
IsElementEnabled = function(self, name)
|
||||
argcheck(name, 2, 'string')
|
||||
|
||||
local element = elements[name]
|
||||
if(not element) then return end
|
||||
|
||||
local active = activeElements[self]
|
||||
return active and active[name]
|
||||
end,
|
||||
|
||||
Enable = RegisterUnitWatch,
|
||||
Disable = function(self)
|
||||
UnregisterUnitWatch(self)
|
||||
self:Hide()
|
||||
end,
|
||||
|
||||
UpdateAllElements = function(self, event)
|
||||
local unit = self.unit
|
||||
if(not UnitExists(unit)) then return end
|
||||
|
||||
assert(type(event) == 'string', 'Invalid argument "event" in UpdateAllElements.')
|
||||
|
||||
if(self.PreUpdate) then
|
||||
self:PreUpdate(event)
|
||||
end
|
||||
|
||||
for _, func in next, self.__elements do
|
||||
func(self, event, unit)
|
||||
end
|
||||
|
||||
if(self.PostUpdate) then
|
||||
self:PostUpdate(event)
|
||||
end
|
||||
end,
|
||||
} do
|
||||
frame_metatable.__index[k] = v
|
||||
end
|
||||
|
||||
local OnShow = function(self)
|
||||
if(not updateActiveUnit(self, 'OnShow')) then
|
||||
return self:UpdateAllElements'OnShow'
|
||||
end
|
||||
end
|
||||
|
||||
local UpdatePet = function(self, event, unit)
|
||||
local petUnit
|
||||
if(unit == 'target') then
|
||||
return
|
||||
elseif(unit == 'player') then
|
||||
petUnit = 'pet'
|
||||
else
|
||||
-- Convert raid26 -> raidpet26
|
||||
petUnit = unit:gsub('^(%a+)(%d+)', '%1pet%2')
|
||||
end
|
||||
|
||||
if(self.unit ~= petUnit) then return end
|
||||
if(not updateActiveUnit(self, event)) then
|
||||
return self:UpdateAllElements(event)
|
||||
end
|
||||
end
|
||||
|
||||
local initObject = function(unit, style, styleFunc, header, ...)
|
||||
local num = select('#', ...)
|
||||
for i=1, num do
|
||||
local object = select(i, ...)
|
||||
local objectUnit = object:GetAttribute'oUF-guessUnit' or unit
|
||||
local suffix = object:GetAttribute'unitsuffix'
|
||||
|
||||
object.__elements = {}
|
||||
object.style = style
|
||||
object = setmetatable(object, frame_metatable)
|
||||
|
||||
-- Expose the frame through oUF.objects.
|
||||
table.insert(objects, object)
|
||||
|
||||
-- We have to force update the frames when PEW fires.
|
||||
object:RegisterEvent("PLAYER_ENTERING_WORLD", object.UpdateAllElements)
|
||||
|
||||
-- Handle the case where someone has modified the unitsuffix attribute in
|
||||
-- oUF-initialConfigFunction.
|
||||
if(suffix and not objectUnit:match(suffix)) then
|
||||
objectUnit = objectUnit .. suffix
|
||||
end
|
||||
|
||||
if(not (suffix == 'target' or objectUnit and objectUnit:match'target')) then
|
||||
object:RegisterEvent('UNIT_ENTERED_VEHICLE', updateActiveUnit)
|
||||
object:RegisterEvent('UNIT_EXITED_VEHICLE', updateActiveUnit)
|
||||
|
||||
-- We don't need to register UNIT_PET for the player unit. We register it
|
||||
-- mainly because UNIT_EXITED_VEHICLE and UNIT_ENTERED_VEHICLE doesn't always
|
||||
-- have pet information when they fire for party and raid units.
|
||||
if(objectUnit ~= 'player') then
|
||||
object:RegisterEvent('UNIT_PET', UpdatePet, true)
|
||||
end
|
||||
end
|
||||
|
||||
if(not header) then
|
||||
-- No header means it's a frame created through :Spawn().
|
||||
object:SetAttribute("*type1", "target")
|
||||
object:SetAttribute('*type2', 'togglemenu')
|
||||
|
||||
-- No need to enable this for *target frames.
|
||||
if(not (unit:match'target' or suffix == 'target')) then
|
||||
object:SetAttribute('toggleForVehicle', true)
|
||||
end
|
||||
|
||||
-- Other boss and target units are handled by :HandleUnit().
|
||||
if(suffix == 'target') then
|
||||
enableTargetUpdate(object)
|
||||
else
|
||||
oUF:HandleUnit(object)
|
||||
end
|
||||
else
|
||||
-- Used to update frames when they change position in a group.
|
||||
object:RegisterEvent('GROUP_ROSTER_UPDATE', object.UpdateAllElements)
|
||||
|
||||
if(num > 1) then
|
||||
if(object:GetParent() == header) then
|
||||
object.hasChildren = true
|
||||
else
|
||||
object.isChild = true
|
||||
end
|
||||
end
|
||||
|
||||
if(suffix == 'target') then
|
||||
enableTargetUpdate(object)
|
||||
end
|
||||
end
|
||||
|
||||
Private.UpdateUnits(object, objectUnit)
|
||||
|
||||
styleFunc(object, objectUnit, not header)
|
||||
|
||||
object:SetScript("OnAttributeChanged", OnAttributeChanged)
|
||||
object:SetScript("OnShow", OnShow)
|
||||
|
||||
activeElements[object] = {}
|
||||
for element in next, elements do
|
||||
object:EnableElement(element, objectUnit)
|
||||
end
|
||||
|
||||
for _, func in next, callback do
|
||||
func(object)
|
||||
end
|
||||
|
||||
-- Make Clique happy
|
||||
_G.ClickCastFrames = ClickCastFrames or {}
|
||||
ClickCastFrames[object] = true
|
||||
end
|
||||
end
|
||||
|
||||
local walkObject = function(object, unit)
|
||||
local parent = object:GetParent()
|
||||
local style = parent.style or style
|
||||
local styleFunc = styles[style]
|
||||
|
||||
local header = parent:GetAttribute'oUF-headerType' and parent
|
||||
|
||||
-- Check if we should leave the main frame blank.
|
||||
if(object:GetAttribute'oUF-onlyProcessChildren') then
|
||||
object.hasChildren = true
|
||||
object:SetScript('OnAttributeChanged', OnAttributeChanged)
|
||||
return initObject(unit, style, styleFunc, header, object:GetChildren())
|
||||
end
|
||||
|
||||
return initObject(unit, style, styleFunc, header, object, object:GetChildren())
|
||||
end
|
||||
|
||||
function oUF:RegisterInitCallback(func)
|
||||
table.insert(callback, func)
|
||||
end
|
||||
|
||||
function oUF:RegisterMetaFunction(name, func)
|
||||
argcheck(name, 2, 'string')
|
||||
argcheck(func, 3, 'function', 'table')
|
||||
|
||||
if(frame_metatable.__index[name]) then
|
||||
return
|
||||
end
|
||||
|
||||
frame_metatable.__index[name] = func
|
||||
end
|
||||
|
||||
function oUF:RegisterStyle(name, func)
|
||||
argcheck(name, 2, 'string')
|
||||
argcheck(func, 3, 'function', 'table')
|
||||
|
||||
if(styles[name]) then return error("Style [%s] already registered.", name) end
|
||||
if(not style) then style = name end
|
||||
|
||||
styles[name] = func
|
||||
end
|
||||
|
||||
function oUF:SetActiveStyle(name)
|
||||
argcheck(name, 2, 'string')
|
||||
if(not styles[name]) then return error("Style [%s] does not exist.", name) end
|
||||
|
||||
style = name
|
||||
end
|
||||
|
||||
do
|
||||
local function iter(_, n)
|
||||
-- don't expose the style functions.
|
||||
return (next(styles, n))
|
||||
end
|
||||
|
||||
function oUF.IterateStyles()
|
||||
return iter, nil, nil
|
||||
end
|
||||
end
|
||||
|
||||
local getCondition
|
||||
do
|
||||
local conditions = {
|
||||
raid40 = '[@raid26,exists] show;',
|
||||
raid25 = '[@raid11,exists] show;',
|
||||
raid10 = '[@raid6,exists] show;',
|
||||
raid = '[group:raid] show;',
|
||||
party = '[group:party,nogroup:raid] show;',
|
||||
solo = '[@player,exists,nogroup:party] show;',
|
||||
}
|
||||
|
||||
function getCondition(...)
|
||||
local cond = ''
|
||||
|
||||
for i=1, select('#', ...) do
|
||||
local short = select(i, ...)
|
||||
|
||||
local condition = conditions[short]
|
||||
if(condition) then
|
||||
cond = cond .. condition
|
||||
end
|
||||
end
|
||||
|
||||
return cond .. 'hide'
|
||||
end
|
||||
end
|
||||
|
||||
local generateName = function(unit, ...)
|
||||
local name = 'oUF_' .. style:gsub('[^%a%d_]+', '')
|
||||
|
||||
local raid, party, groupFilter
|
||||
for i=1, select('#', ...), 2 do
|
||||
local att, val = select(i, ...)
|
||||
if(att == 'showRaid') then
|
||||
raid = true
|
||||
elseif(att == 'showParty') then
|
||||
party = true
|
||||
elseif(att == 'groupFilter') then
|
||||
groupFilter = val
|
||||
end
|
||||
end
|
||||
|
||||
local append
|
||||
if(raid) then
|
||||
if(groupFilter) then
|
||||
if(type(groupFilter) == 'number' and groupFilter > 0) then
|
||||
append = groupFilter
|
||||
elseif(groupFilter:match'TANK') then
|
||||
append = 'MainTank'
|
||||
elseif(groupFilter:match'ASSIST') then
|
||||
append = 'MainAssist'
|
||||
else
|
||||
local _, count = groupFilter:gsub(',', '')
|
||||
if(count == 0) then
|
||||
append = 'Raid' .. groupFilter
|
||||
else
|
||||
append = 'Raid'
|
||||
end
|
||||
end
|
||||
else
|
||||
append = 'Raid'
|
||||
end
|
||||
elseif(party) then
|
||||
append = 'Party'
|
||||
elseif(unit) then
|
||||
append = unit:gsub("^%l", string.upper)
|
||||
end
|
||||
|
||||
if(append) then
|
||||
name = name .. append
|
||||
end
|
||||
|
||||
-- Change oUF_LilyRaidRaid into oUF_LilyRaid
|
||||
name = name:gsub('(%u%l+)([%u%l]*)%1', '%1')
|
||||
-- Change oUF_LilyTargettarget into oUF_LilyTargetTarget
|
||||
name = name:gsub('t(arget)', 'T%1')
|
||||
|
||||
local base = name
|
||||
local i = 2
|
||||
while(_G[name]) do
|
||||
name = base .. i
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
return name
|
||||
end
|
||||
|
||||
do
|
||||
local styleProxy = function(self, frame, ...)
|
||||
return walkObject(_G[frame])
|
||||
end
|
||||
|
||||
-- There has to be an easier way to do this.
|
||||
local initialConfigFunction = [[
|
||||
local header = self:GetParent()
|
||||
local frames = table.new()
|
||||
table.insert(frames, self)
|
||||
self:GetChildList(frames)
|
||||
for i=1, #frames do
|
||||
local frame = frames[i]
|
||||
local unit
|
||||
-- There's no need to do anything on frames with onlyProcessChildren
|
||||
if(not frame:GetAttribute'oUF-onlyProcessChildren') then
|
||||
RegisterUnitWatch(frame)
|
||||
|
||||
-- Attempt to guess what the header is set to spawn.
|
||||
local groupFilter = header:GetAttribute'groupFilter'
|
||||
|
||||
if(type(groupFilter) == 'string' and groupFilter:match('MAIN[AT]')) then
|
||||
local role = groupFilter:match('MAIN([AT])')
|
||||
if(role == 'T') then
|
||||
unit = 'maintank'
|
||||
else
|
||||
unit = 'mainassist'
|
||||
end
|
||||
elseif(header:GetAttribute'showRaid') then
|
||||
unit = 'raid'
|
||||
elseif(header:GetAttribute'showParty') then
|
||||
unit = 'party'
|
||||
end
|
||||
|
||||
local headerType = header:GetAttribute'oUF-headerType'
|
||||
local suffix = frame:GetAttribute'unitsuffix'
|
||||
if(unit and suffix) then
|
||||
if(headerType == 'pet' and suffix == 'target') then
|
||||
unit = unit .. headerType .. suffix
|
||||
else
|
||||
unit = unit .. suffix
|
||||
end
|
||||
elseif(unit and headerType == 'pet') then
|
||||
unit = unit .. headerType
|
||||
end
|
||||
|
||||
frame:SetAttribute('*type1', 'target')
|
||||
frame:SetAttribute('*type2', 'togglemenu')
|
||||
frame:SetAttribute('toggleForVehicle', true)
|
||||
frame:SetAttribute('oUF-guessUnit', unit)
|
||||
end
|
||||
|
||||
local body = header:GetAttribute'oUF-initialConfigFunction'
|
||||
if(body) then
|
||||
frame:Run(body, unit)
|
||||
end
|
||||
end
|
||||
|
||||
header:CallMethod('styleFunction', self:GetName())
|
||||
|
||||
local clique = header:GetFrameRef("clickcast_header")
|
||||
if(clique) then
|
||||
clique:SetAttribute("clickcast_button", self)
|
||||
clique:RunAttribute("clickcast_register")
|
||||
end
|
||||
]]
|
||||
|
||||
function oUF:SpawnHeader(overrideName, template, visibility, ...)
|
||||
if(not style) then return error("Unable to create frame. No styles have been registered.") end
|
||||
|
||||
template = (template or 'SecureGroupHeaderTemplate')
|
||||
|
||||
local isPetHeader = template:match'PetHeader'
|
||||
local name = overrideName or generateName(nil, ...)
|
||||
local header = CreateFrame('Frame', name, oUF_PetBattleFrameHider, template)
|
||||
|
||||
header:SetAttribute("template", "oUF_ClickCastUnitTemplate")
|
||||
for i=1, select("#", ...), 2 do
|
||||
local att, val = select(i, ...)
|
||||
if(not att) then break end
|
||||
header:SetAttribute(att, val)
|
||||
end
|
||||
|
||||
header.style = style
|
||||
header.styleFunction = styleProxy
|
||||
|
||||
-- Expose the header through oUF.headers.
|
||||
table.insert(headers, header)
|
||||
|
||||
-- We set it here so layouts can't directly override it.
|
||||
header:SetAttribute('initialConfigFunction', initialConfigFunction)
|
||||
header:SetAttribute('oUF-headerType', isPetHeader and 'pet' or 'group')
|
||||
|
||||
if(Clique) then
|
||||
SecureHandlerSetFrameRef(header, 'clickcast_header', Clique.header)
|
||||
end
|
||||
|
||||
if(header:GetAttribute'showParty') then
|
||||
self:DisableBlizzard'party'
|
||||
end
|
||||
|
||||
if(visibility) then
|
||||
local type, list = string.split(' ', visibility, 2)
|
||||
if(list and type == 'custom') then
|
||||
RegisterAttributeDriver(header, 'state-visibility', list)
|
||||
else
|
||||
local condition = getCondition(string.split(',', visibility))
|
||||
RegisterAttributeDriver(header, 'state-visibility', condition)
|
||||
end
|
||||
end
|
||||
|
||||
return header
|
||||
end
|
||||
end
|
||||
|
||||
function oUF:Spawn(unit, overrideName, overrideTemplate)
|
||||
argcheck(unit, 2, 'string')
|
||||
if(not style) then return error("Unable to create frame. No styles have been registered.") end
|
||||
|
||||
unit = unit:lower()
|
||||
|
||||
local name = overrideName or generateName(unit)
|
||||
local object = CreateFrame("Button", name, oUF_PetBattleFrameHider, overrideTemplate or "SecureUnitButtonTemplate")
|
||||
Private.UpdateUnits(object, unit)
|
||||
|
||||
self:DisableBlizzard(unit)
|
||||
walkObject(object, unit)
|
||||
|
||||
object:SetAttribute("unit", unit)
|
||||
RegisterUnitWatch(object)
|
||||
|
||||
return object
|
||||
end
|
||||
|
||||
function oUF:AddElement(name, update, enable, disable)
|
||||
argcheck(name, 2, 'string')
|
||||
argcheck(update, 3, 'function', 'nil')
|
||||
argcheck(enable, 4, 'function', 'nil')
|
||||
argcheck(disable, 5, 'function', 'nil')
|
||||
|
||||
if(elements[name]) then return error('Element [%s] is already registered.', name) end
|
||||
elements[name] = {
|
||||
update = update;
|
||||
enable = enable;
|
||||
disable = disable;
|
||||
}
|
||||
end
|
||||
|
||||
oUF.version = _VERSION
|
||||
oUF.objects = objects
|
||||
oUF.headers = headers
|
||||
|
||||
if(global) then
|
||||
if(parent ~= 'oUF' and global == 'oUF') then
|
||||
error("%s is doing it wrong and setting its global to oUF.", parent)
|
||||
else
|
||||
_G[global] = oUF
|
||||
end
|
||||
end
|
||||
22
Libraries/oUF/private.lua
Normal file
22
Libraries/oUF/private.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
local parent, ns = ...
|
||||
local Private = ns.oUF.Private
|
||||
|
||||
function Private.argcheck(value, num, ...)
|
||||
assert(type(num) == 'number', "Bad argument #2 to 'argcheck' (number expected, got "..type(num)..")")
|
||||
|
||||
for i=1,select("#", ...) do
|
||||
if type(value) == select(i, ...) then return end
|
||||
end
|
||||
|
||||
local types = strjoin(", ", ...)
|
||||
local name = string.match(debugstack(2,2,0), ": in function [`<](.-)['>]")
|
||||
error(("Bad argument #%d to '%s' (%s expected, got %s"):format(num, name, types, type(value)), 3)
|
||||
end
|
||||
|
||||
function Private.print(...)
|
||||
print("|cff33ff99oUF:|r", ...)
|
||||
end
|
||||
|
||||
function Private.error(...)
|
||||
Private.print("|cffff0000Error:|r "..string.format(...))
|
||||
end
|
||||
23
Libraries/oUF/units.lua
Normal file
23
Libraries/oUF/units.lua
Normal file
@@ -0,0 +1,23 @@
|
||||
local parent, ns = ...
|
||||
local oUF = ns.oUF
|
||||
local Private = oUF.Private
|
||||
|
||||
local enableTargetUpdate = Private.enableTargetUpdate
|
||||
|
||||
-- Handles unit specific actions.
|
||||
function oUF:HandleUnit(object, unit)
|
||||
local unit = object.unit or unit
|
||||
|
||||
if(unit == 'target') then
|
||||
object:RegisterEvent('PLAYER_TARGET_CHANGED', object.UpdateAllElements)
|
||||
elseif(unit == 'mouseover') then
|
||||
object:RegisterEvent('UPDATE_MOUSEOVER_UNIT', object.UpdateAllElements)
|
||||
elseif(unit == 'focus') then
|
||||
object:RegisterEvent('PLAYER_FOCUS_CHANGED', object.UpdateAllElements)
|
||||
elseif(unit:match'(boss)%d?$' == 'boss') then
|
||||
object:RegisterEvent('INSTANCE_ENCOUNTER_ENGAGE_UNIT', object.UpdateAllElements, true)
|
||||
object:RegisterEvent('UNIT_TARGETABLE_CHANGED', object.UpdateAllElements)
|
||||
elseif(unit:match'%w+target') then
|
||||
enableTargetUpdate(object)
|
||||
end
|
||||
end
|
||||
84
Libraries/oUF/utils/changelog
Normal file
84
Libraries/oUF/utils/changelog
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local tags = {}
|
||||
do
|
||||
for tag in io.popen('git tag'):lines() do
|
||||
local split = tag:gmatch('[^.]+')
|
||||
local release, api, bugfix = split(), split(), split() or 0
|
||||
table.insert(
|
||||
tags,
|
||||
{
|
||||
string = tag,
|
||||
release = release,
|
||||
api = api,
|
||||
bugfix = bugfix,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
table.sort(tags, function(a,b)
|
||||
a = a.release * 1e4 + a.api * 100 + a.bugfix
|
||||
b = b.release * 1e4 + b.api * 100 + b.bugfix
|
||||
|
||||
return a > b
|
||||
end)
|
||||
end
|
||||
|
||||
local generateLog = function(prevTag, currentTag)
|
||||
local ti = table.insert
|
||||
local sf = string.format
|
||||
|
||||
local out = {}
|
||||
|
||||
ti(out, sf('[b]Changes in %s:[/b]', currentTag))
|
||||
ti(out, '[list]')
|
||||
|
||||
for line in io.popen(sf('git shortlog %s..%s', prevTag, currentTag)):lines() do
|
||||
if(line:sub(1, 6) == ' ') then
|
||||
local offset = line:match('() ', 7)
|
||||
if(offset) then
|
||||
line = line:sub(7, offset - 1)
|
||||
else
|
||||
line = line:sub(7)
|
||||
end
|
||||
|
||||
ti(out, sf(' [*] %s', line))
|
||||
elseif(#line == 0) then
|
||||
ti(out, ' [/list]')
|
||||
else
|
||||
ti(out, sf(' [*][i]%s[/i]', line))
|
||||
ti(out, ' [list=1]')
|
||||
end
|
||||
end
|
||||
|
||||
ti(out, '[/list]')
|
||||
|
||||
local p = assert(io.popen(sf('git diff --shortstat %s..%s', prevTag, currentTag)))
|
||||
local stat = p:read'*a'
|
||||
p:close()
|
||||
|
||||
ti(out, sf('[indent]%s[/indent]', stat:sub(2, -2)))
|
||||
|
||||
return table.concat(out, '\n')
|
||||
end
|
||||
|
||||
local stop
|
||||
local to = ...
|
||||
if(to) then
|
||||
for i=1, #tags do
|
||||
if(tags[i].string == to) then
|
||||
stop = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
if(not stop) then stop = #tags end
|
||||
else
|
||||
stop = #tags
|
||||
end
|
||||
|
||||
for i=2, stop do
|
||||
local current, prev = tags[i -1], tags[i]
|
||||
print(generateLog(prev.string, current.string))
|
||||
end
|
||||
|
||||
-- vim: set filetype=lua :
|
||||
254
Libraries/oUF/utils/docs
Normal file
254
Libraries/oUF/utils/docs
Normal file
@@ -0,0 +1,254 @@
|
||||
#!/usr/bin/env lua
|
||||
-- docs
|
||||
-- oUF documentation generator
|
||||
--
|
||||
-- This is really just a quick and dirty way of generating documentation for
|
||||
-- oUF[1]. The syntax is inspired by TomDoc[2], but a lot of the non-oUF and
|
||||
-- non-Lua things aren't implemented.
|
||||
--
|
||||
-- Why implement my own documentation generator?
|
||||
-- It was mainly done because oUF is kind-of special, but also because the
|
||||
-- available alternatives aren't good enough or have issues I can't workaround.
|
||||
--
|
||||
-- Things that need fixing:
|
||||
-- - No highlighting of Lua code.
|
||||
-- - Doesn't validate that comments are documentation strings.
|
||||
-- - Doesn't parse its own documentation header.
|
||||
-- - Close to zero error handling.
|
||||
--
|
||||
-- Usage
|
||||
--
|
||||
-- docs [docs path] [file...]
|
||||
--
|
||||
-- Links
|
||||
--
|
||||
-- [1] https://github.com/haste/oUF
|
||||
-- [2] http://tomdoc.org/
|
||||
|
||||
local out
|
||||
local lines
|
||||
|
||||
local tisf = function(fmt, ...)
|
||||
table.insert(out, fmt:format(...))
|
||||
end
|
||||
|
||||
local trim = function(str)
|
||||
return str:match('^()%s*$') and '' or str:match('^%s*(.*%S)')
|
||||
end
|
||||
|
||||
local findNextEmpty = function(start, stop)
|
||||
for i=start, stop or #lines do
|
||||
if(lines[i] == '') then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local findNextHeader = function(offest)
|
||||
for i=offest, #lines do
|
||||
local pre, header, post = unpack(lines, i, i + 2)
|
||||
-- Single lines without punctuation are headers.
|
||||
if(pre == '' and post == '' and not header:match'%.') then
|
||||
return i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local findNextArguent = function(start, stop, padding, pattern)
|
||||
for i=start, stop do
|
||||
local match, pad = lines[i]:match(pattern)
|
||||
if(match and pad == padding) then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local replaceMarkup = function(str)
|
||||
return str
|
||||
-- `in-line code` to <code>in-line code</code>
|
||||
:gsub('`([^`]+)`', '<code>%1</code>')
|
||||
-- [Link](http://example.com) to <a href="http://example.com">Link</a>
|
||||
:gsub('%[([^%]]+)%]%(([^)]+)%)', '<a href="%2">%1</a>')
|
||||
end
|
||||
|
||||
local handleArguments = function(start, stop, pattern)
|
||||
tisf('<dl>')
|
||||
repeat
|
||||
-- Tear out the argument name and offset of where the description begins.
|
||||
local def, padding, offset = lines[start]:match(pattern)
|
||||
tisf('<dt>%s</dt>', def)
|
||||
|
||||
-- Insert the first line of the description.
|
||||
tisf('<dd>')
|
||||
tisf(lines[start]:sub(offset))
|
||||
|
||||
-- Find the next argument in the list or continue to the end of the
|
||||
-- current section.
|
||||
local nextarg = findNextArguent(start + 1, stop, padding, pattern)
|
||||
nextarg = (nextarg or stop + 1) - 1
|
||||
for i=start + 1, nextarg do
|
||||
tisf(trim(lines[i]))
|
||||
end
|
||||
tisf('</dd>')
|
||||
|
||||
start = nextarg + 1
|
||||
until start > stop
|
||||
tisf('</dl>')
|
||||
end
|
||||
|
||||
local handleExamples = function(start, stop)
|
||||
-- An extra line gets added if we don't do this.
|
||||
tisf('<pre><code>%s', lines[start]:sub(3))
|
||||
for i=start + 1, stop do
|
||||
tisf(lines[i]:sub(3))
|
||||
end
|
||||
tisf('</code></pre>')
|
||||
end
|
||||
|
||||
local handleParagraph = function(start, stop)
|
||||
tisf('<p>')
|
||||
for i=start, stop do
|
||||
tisf(trim(lines[i]))
|
||||
end
|
||||
tisf('</p>')
|
||||
end
|
||||
|
||||
local handleSection = function(start, stop)
|
||||
while(start) do
|
||||
-- Find the next empty line or continue until the end of the section.
|
||||
-- findNextEmpty() returns the position of the empty line, so we need to
|
||||
-- subtract one from it.
|
||||
local nextEmpty = findNextEmpty(start + 1, stop)
|
||||
if(nextEmpty) then
|
||||
nextEmpty = nextEmpty - 1
|
||||
else
|
||||
nextEmpty = stop
|
||||
end
|
||||
|
||||
local line = lines[start]
|
||||
if(not line) then
|
||||
return
|
||||
elseif(line:match('^%S+%s*%- ')) then
|
||||
handleArguments(start, nextEmpty, '(%S+)%s*()%- ()')
|
||||
elseif(line:sub(1, 2) == ' ') then
|
||||
handleExamples(start, nextEmpty)
|
||||
else
|
||||
handleParagraph(start, nextEmpty)
|
||||
end
|
||||
|
||||
start = findNextEmpty(nextEmpty, stop)
|
||||
if(start) then start = start + 1 end
|
||||
end
|
||||
end
|
||||
|
||||
local generateDocs = function(str, level)
|
||||
lines = {}
|
||||
out = {}
|
||||
|
||||
for line in str:gmatch('([^\n]*)\n') do
|
||||
table.insert(lines, line:gsub('\t*', ''):sub(2))
|
||||
end
|
||||
|
||||
-- The first line is always the main header.
|
||||
tisf('<h%d>%s</h%d>', level, lines[1], level)
|
||||
|
||||
-- Then comes the main description.
|
||||
local offset = findNextHeader(1)
|
||||
|
||||
-- Continue until two lines before the header or to the end of the comment.
|
||||
if(offset) then
|
||||
offset = offset - 2
|
||||
else
|
||||
offset = #lines
|
||||
end
|
||||
|
||||
local init = findNextEmpty(1) + 1
|
||||
if(init > offset) then
|
||||
init = 2
|
||||
end
|
||||
|
||||
handleSection(init, offset)
|
||||
|
||||
while(true) do
|
||||
offset = findNextHeader(offset)
|
||||
if(not offset) then break end
|
||||
|
||||
-- Every section has a header.
|
||||
tisf('<h%d>%s</h%d>', level + 1, lines[offset], level + 1)
|
||||
|
||||
-- Find out the size of the section.
|
||||
local start = findNextEmpty(offset) + 1
|
||||
if(not lines[start]) then
|
||||
-- There's no section here, only a headline.
|
||||
break
|
||||
end
|
||||
|
||||
local stop
|
||||
local nextHeader = findNextHeader(start)
|
||||
if(nextHeader) then
|
||||
stop = nextHeader - 2
|
||||
else
|
||||
local nextEmpty = findNextEmpty(start)
|
||||
if(nextEmpty) then
|
||||
stop = nextEmpty - 1
|
||||
else
|
||||
stop = #lines
|
||||
end
|
||||
end
|
||||
|
||||
handleSection(start, stop)
|
||||
offset = stop + 1
|
||||
end
|
||||
|
||||
return table.concat(out, '\n')
|
||||
end
|
||||
|
||||
local handleFile = function(path)
|
||||
local file = io.open(path, 'r')
|
||||
local content = file:read'*a'
|
||||
file:close()
|
||||
|
||||
local out = {}
|
||||
local init = 1
|
||||
repeat
|
||||
local _, comStart, depth = content:find('%-%-%[(=*)%[ ', init)
|
||||
if(comStart) then
|
||||
local comEnd = content:find('%]' .. depth .. '%]', comStart)
|
||||
local comment = content:sub(comStart, comEnd - 1)
|
||||
|
||||
-- Convert markup to html.
|
||||
comment = replaceMarkup(comment)
|
||||
|
||||
-- The first comment uses h1 and h2, while the subsequent ones uses h3
|
||||
-- and h4.
|
||||
local level = init == 1 and 1 or 3
|
||||
table.insert(out, generateDocs(comment, init == 1 and 1 or 3))
|
||||
|
||||
init = comEnd
|
||||
end
|
||||
until not comStart
|
||||
|
||||
return table.concat(out, '\n')
|
||||
end
|
||||
|
||||
local destination = (...)
|
||||
for i=2, select('#', ...) do
|
||||
local file = select(i, ...)
|
||||
local path, filename = file:match('(.+)/(.+)$')
|
||||
|
||||
if(path:sub(1,3) == '../') then
|
||||
path = path:sub(4)
|
||||
end
|
||||
|
||||
if(#path == 0) then path = nil end
|
||||
filename = filename:gsub('lua', 'html')
|
||||
|
||||
local doc = handleFile(file)
|
||||
if(doc) then
|
||||
local dfPath = string.format('%s/%s', destination, path or '')
|
||||
os.execute(string.format('mkdir -p %s', dfPath))
|
||||
local docFile = io.open(string.format('%s/%s', dfPath, filename), 'w+')
|
||||
docFile:write(doc)
|
||||
docFile:close()
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user