/
local hook |
local _E |
local pipe = function(self) |
local id = self:GetID() |
local name = self:GetName() |
local size = self.size |
for i = 1, size do |
local bid = size - i + 1 |
local slotFrame = _G[name.."Item"..bid] |
local slotLink = GetContainerItemLink(id, i) |
oGlow:CallFilters("bags", slotFrame, _E and slotLink) |
end |
end |
local update = function(self) |
local frame = _G["ContainerFrame1"] |
local i = 2 |
while(frame and frame.size) do |
pipe(frame) |
frame = _G["ContainerFrame"..i] |
i = i + 1 |
end |
end |
local enable = function(self) |
_E = true |
if not hook then |
hooksecurefunc("ContainerFrame_Update", pipe) |
hook = true |
end |
end |
local disable = function(self) |
_E = nil |
end |
oGlow:RegisterPipe("bags", enable, disable, update, "Bag containers") |
local _E |
local update = function(self) |
if not IsAddOnLoaded("Blizzard_GuildBankUI") then return end |
local tab = GetCurrentGuildBankTab() |
for i = 1, MAX_GUILDBANK_SLOTS_PER_TAB or 98 do |
local index = math.fmod(i, 14) |
if index == 0 then |
index = 14 |
end |
local column = math.ceil((i - 0.5) / 14) |
local slotLink = GetGuildBankItemLink(tab, i) |
local slotFrame = _G["GuildBankColumn"..column.."Button"..index] |
self:CallFilters("gbank", slotFrame, _E and slotLink) |
end |
end |
local enable = function(self) |
_E = true |
self:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED", update) |
self:RegisterEvent("GUILDBANKFRAME_OPENED", update) |
end |
local disable = function(self) |
_E = nil |
self:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED", update) |
self:UnregisterEvent("GUILDBANKFRAME_OPENED", update) |
end |
oGlow:RegisterPipe("gbank", enable, disable, update, "Guild bank frame") |
<Ui xmlns="http://www.blizzard.com/wow/ui/"> |
<Script file="oGlow.lua" /> |
<Script file="Pipes\Bags.lua" /> |
<Script file="Pipes\Char.lua" /> |
<Script file="Pipes\Inspect.lua" /> |
<Script file="Pipes\Bank.lua" /> |
<Script file="Pipes\GBank.lua" /> |
<Script file="Pipes\Trade.lua" /> |
<Script file="Pipes\TradeSkill.lua" /> |
<Script file="Pipes\Merchant.lua" /> |
<Script file="Pipes\Mail.lua" /> |
<Script file="Pipes\CharFlyout.lua" /> |
<Script file="Pipes\VoidStorage.lua" /> |
<Script file="Pipes\Loot.lua" /> |
<Script file="Displays\Border.lua" /> |
<Script file="Filters\Quality.lua" /> |
</Ui> |
local error = function(...) print("|cffff0000Error:|r "..string.format(...)) end |
local pipesTable = {} |
local filtersTable = {} |
local displaysTable = {} |
local numPipes = 0 |
local numFilters = 0 |
local activeFilters = {} |
local event_metatable = { |
__call = function(funcs, self, ...) |
for _, func in pairs(funcs) do |
func(self, ...) |
end |
end, |
} |
local oGlow = CreateFrame("Frame", "oGlow") |
function oGlow:ADDON_LOADED(event, addon) |
for pipe in next, pipesTable do |
self:EnablePipe(pipe) |
for filter in next, filtersTable do |
self:RegisterFilterOnPipe(pipe, filter) |
end |
end |
self:UnregisterEvent(event, self.ADDON_LOADED) |
end |
-- Event API |
local RegisterEvent = oGlow.RegisterEvent |
function oGlow:RegisterEvent(event, func) |
if type(func) == "string" and type(self[func]) == "function" then |
func = self[func] |
end |
local curev = self[event] |
if curev and func then |
if type(curev) == "function" then |
self[event] = setmetatable({curev, func}, event_metatable) |
else |
for _, infunc in next, curev do |
if infunc == func then return end |
end |
table.insert(curev, func) |
end |
elseif self:IsEventRegistered(event) then |
return |
else |
if func then |
self[event] = func |
elseif not self[event] then |
return error("Handler for event [%s] does not exist.", event) |
end |
RegisterEvent(self, event) |
end |
end |
local UnregisterEvent = oGlow.UnregisterEvent |
function oGlow:UnregisterEvent(event, func) |
local curev = self[event] |
if type(curev) == "table" and func then |
for k, infunc in next, curev do |
if infunc == func then |
curev[k] = nil |
if #curev == 0 then |
table.remove(curev, k) |
UnregisterEvent(self, event) |
end |
break |
end |
end |
else |
self[event] = nil |
UnregisterEvent(self, event) |
end |
end |
oGlow:SetScript("OnEvent", function(self, event, ...) |
return self[event](self, event, ...) |
end) |
-- Pipe API |
function oGlow:RegisterPipe(pipe, enable, disable, update, name) |
if pipesTable[pipe] then |
return nil, string.format("Pipe [%s] is already registered.") |
else |
numPipes = numPipes + 1 |
pipesTable[pipe] = { |
enable = enable; |
disable = disable; |
name = name; |
update = update; |
} |
end |
return true |
end |
do |
local function iter(_, n) |
local n, t = next(pipesTable, n) |
if t then |
return n, t.isActive, t.name |
end |
end |
function oGlow.IteratePipes() |
return iter, nil, nil |
end |
end |
function oGlow:EnablePipe(pipe) |
local ref = pipesTable[pipe] |
if ref and not ref.isActive then |
ref.enable(self) |
ref.isActive = true |
return true |
end |
end |
function oGlow:DisablePipe(pipe) |
local ref = pipesTable[pipe] |
if ref and ref.isActive then |
if ref.disable then ref.disable(self) end |
ref.isActive = nil |
return true |
end |
end |
function oGlow:IsPipeEnabled(pipe) |
return pipesTable[pipe].isActive |
end |
function oGlow:UpdatePipe(pipe) |
local ref = pipesTable[pipe] |
if ref and ref.isActive then |
ref.update(self) |
return true |
end |
end |
function oGlow:GetNumPipes() |
return numPipes |
end |
-- Filter API |
function oGlow:RegisterFilter(name, type, filter) |
if filtersTable[name] then return nil, "Filter function is already registered." end |
filtersTable[name] = {type, filter, name} |
numFilters = numFilters + 1 |
return true |
end |
do |
local function iter(_, n) |
local n, t = next(filtersTable, n) |
if t then |
return n, t[1], t[4] |
end |
end |
function oGlow.IterateFilters() |
return iter, nil, nil |
end |
end |
function oGlow:RegisterFilterOnPipe(pipe, filter) |
if not pipesTable[pipe] then return nil, "Pipe does not exist." end |
if not filtersTable[filter] then return nil, "Filter does not exist." end |
if not activeFilters[pipe] then |
local filterTable = filtersTable[filter] |
local display = filterTable[1] |
activeFilters[pipe] = {} |
activeFilters[pipe][display] = {} |
table.insert(activeFilters[pipe][display], filterTable) |
else |
local filterTable = filtersTable[filter] |
local ref = activeFilters[pipe][filterTable[1]] |
for _, func in next, ref do |
if func == filter then |
return nil, "Filter function is already registered." |
end |
end |
table.insert(ref, filterTable) |
end |
return true |
end |
-- Display API |
function oGlow:RegisterDisplay(name, display) |
displaysTable[name] = display |
end |
-- General API |
function oGlow:CallFilters(pipe, frame, ...) |
if not pipesTable[pipe] then return nil, "Pipe does not exist." end |
local ref = activeFilters[pipe] |
if ref then |
for display, filters in next, ref do |
if not displaysTable[display] then return nil, "Display does not exist." end |
for i = 1, #filters do |
local func = filters[i][2] |
if (displaysTable[display](frame, func(...))) then break end |
end |
end |
end |
end |
oGlow:RegisterEvent("ADDON_LOADED") |
local colorTable = setmetatable( |
{}, |
{__index = function(self, val) |
local r, g, b = GetItemQualityColor(val) |
rawset(self, val, {r, g, b}) |
return self[val] |
end} |
) |
local createBorder = function(self, point) |
local bc = self.oGlowBorder |
if not bc then |
if not self:IsObjectType("Frame") then |
bc = CreateFrame("Frame", nil, self:GetParent()) |
else |
bc = CreateFrame("Frame", nil, self) |
end |
bc:SetBackdrop({ |
bgFile = "", |
edgeFile = "Interface\\AddOns\\QulightUI\\Root\\Media\\glowTex", |
edgeSize = 3, |
insets = { left = 3, right = 3, top = 3, bottom = 3 } |
}) |
if self.backdrop then |
bc:SetPoint("TOPLEFT", 2, 0) |
bc:SetPoint("BOTTOMRIGHT", 0, 0) |
else |
bc:SetPoint("TOPLEFT", point or self, -2, 2) |
bc:SetPoint("BOTTOMRIGHT", point or self, 2, -2) |
end |
self.oGlowBorder = bc |
end |
return bc |
end |
local borderDisplay = function(frame, color) |
if color then |
local bc = createBorder(frame) |
local rgb = colorTable[color] |
if rgb then |
bc:SetBackdropBorderColor(rgb[1], rgb[2], rgb[3]) |
if bc.backdrop then |
bc.backdrop:SetBackdropBorderColor(rgb[1], rgb[2], rgb[3]) |
end |
bc:Show() |
end |
return true |
elseif frame.oGlowBorder then |
frame.oGlowBorder:Hide() |
end |
end |
function oGlow:RegisterColor(name, r, g, b) |
if(rawget(colorTable, name)) then |
return nil, string.format("Color [%s] is already registered.", name) |
else |
rawset(colorTable, name, {r, g, b}) |
end |
return true |
end |
oGlow:RegisterDisplay("Border", borderDisplay) |
local quality = function(...) |
local quality = -1 |
for i = 1, select("#", ...) do |
local itemLink = select(i, ...) |
if itemLink then |
local _, _, itemQuality = GetItemInfo(itemLink) |
if itemQuality then |
quality = math.max(quality, itemQuality) |
end |
end |
end |
if quality > 1 then |
return quality |
end |
end |
oGlow:RegisterFilter("Quality border", "Border", quality) |
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) |
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() 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 |
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 |
<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\cpoints.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\picon.lua' /> |
<Script file='elements\readycheck.lua' /> |
<Script file='elements\qicon.lua' /> |
<Script file='elements\eclipsebar.lua' /> |
<Script file='elements\altpowerbar.lua' /> |
<Script file='elements\totems.lua' /> |
<Script file='elements\resurrect.lua' /> |
<Script file='elements\druidmana.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" 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" hidden="true" 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" hidden="true" 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> |
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 = {}, {} |
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 |
-- Drop out if the event unit doesn't match any of the frame units. |
if(not UnitExists(modUnit) or unit and unit ~= realUnit and unit ~= 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{ |
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)) 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 |
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, true) |
object:RegisterEvent('UNIT_EXITED_VEHICLE', updateActiveUnit, true) |
-- 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 |
-- 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) |
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, "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 |
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 |
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 |
--[[ Element: Range Fader |
Widget |
Range - A table containing opacity values. |
Options |
.outsideAlpha - Opacity when the unit is out of range. Values 0 (fully |
transparent) - 1 (fully opaque). |
.insideAlpha - Opacity when the unit is within range. Values 0 (fully |
transparent) - 1 (fully opaque). |
Examples |
-- Register with oUF |
self.Range = { |
insideAlpha = 1, |
outsideAlpha = 1/2, |
} |
Hooks |
]] |
local parent, ns = ... |
local oUF = ns.oUF |
local _FRAMES = {} |
local OnRangeFrame |
local UnitInRange, UnitIsConnected = UnitInRange, UnitIsConnected |
-- 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 |
if(UnitIsConnected(object.unit)) then |
local inRange, checkedRange = UnitInRange(object.unit) |
if(checkedRange and not inRange) then |
if(range.Override) then |
--[[ .Override(self, status) |
A function used to override the calls to :SetAlpha(). |
Arguments |
self - The unit object. |
status - The range status of the unit. Either `inside` or |
`outside`. |
]] |
range.Override(object, 'outside') |
else |
object:SetAlpha(range.outsideAlpha) |
end |
else |
if(range.Override) then |
range.Override(object, 'inside') |
elseif(object:GetAlpha() ~= range.insideAlpha) then |
object:SetAlpha(range.insideAlpha) |
end |
end |
else |
if(range.Override) then |
range.Override(object, 'offline') |
elseif(object:GetAlpha() ~= range.insideAlpha) then |
object:SetAlpha(range.insideAlpha) |
end |
end |
end |
end |
timer = 0 |
end |
end |
local Enable = function(self) |
local range = self.Range |
if(range and range.insideAlpha and range.outsideAlpha) then |
table.insert(_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 |
table.remove(_FRAMES, k) |
break |
end |
end |
self:SetAlpha(1) |
if(#_FRAMES == 0) then |
OnRangeFrame:Hide() |
end |
end |
end |
oUF:AddElement('Range', nil, Enable, Disable) |
--[[ 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) |
--[[ 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) |
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) |
--[[ Element: Runes Bar |
Handle updating and visibility of the Death Knight's Rune indicators. |
Widget |
Runes - An array holding six 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 |
]] |
if select(2, UnitClass("player")) ~= "DEATHKNIGHT" then return end |
local parent, ns = ... |
local oUF = ns.oUF |
oUF.colors.runes = { |
{1, 0, 0}, -- blood |
{0, .5, 0}, -- unholy |
{0, 1, 1}, -- frost |
{.9, .1, 1}, -- death |
} |
local runemap = { 1, 2, 5, 6, 3, 4 } |
local OnUpdate = function(self, elapsed) |
local duration = self.duration + elapsed |
if(duration >= self.max) then |
return self:SetScript("OnUpdate", nil) |
else |
self.duration = duration |
return self:SetValue(duration) |
end |
end |
local UpdateType = function(self, event, rid, alt) |
local runes = self.Runes |
local rune = runes[runemap[rid]] |
local colors = self.colors.runes[GetRuneType(rid) or alt] |
local r, g, b = colors[1], colors[2], colors[3] |
rune:SetStatusBarColor(r, g, b) |
if(rune.bg) then |
local mu = rune.bg.multiplier or 1 |
rune.bg:SetVertexColor(r * mu, g * mu, b * mu) |
end |
if(runes.PostUpdateType) then |
return runes:PostUpdateType(rune, rid, alt) |
end |
end |
local UpdateRune = function(self, event, rid) |
local runes = self.Runes |
local rune = runes[runemap[rid]] |
if(not rune) then return end |
local start, duration, runeReady = GetRuneCooldown(rid) |
if(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 |
if(runes.PostUpdateRune) then |
return runes:PostUpdateRune(rune, rid, start, duration, runeReady) |
end |
end |
local Update = function(self, event) |
for i=1, 6 do |
UpdateRune(self, event, i) |
end |
end |
local ForceUpdate = function(element) |
return Update(element.__owner, 'ForceUpdate') |
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, 6 do |
local rune = runes[runemap[i]] |
if(rune:IsObjectType'StatusBar' and not rune:GetStatusBarTexture()) then |
rune:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]] |
end |
-- From my minor testing this is a okey solution. A full login always remove |
-- the death runes, or at least the clients knowledge about them. |
UpdateType(self, nil, i, math.floor((i+1)/2)) |
end |
self:RegisterEvent("RUNE_POWER_UPDATE", UpdateRune, true) |
self:RegisterEvent("RUNE_TYPE_UPDATE", UpdateType, true) |
-- oUF leaves the vehicle events registered on the player frame, so |
-- buffs and such are correctly updated when entering/exiting vehicles. |
-- |
-- This however makes the code also show/hide the RuneFrame. |
RuneFrame.Show = RuneFrame.Hide |
RuneFrame:Hide() |
return true |
end |
end |
local Disable = function(self) |
RuneFrame.Show = nil |
RuneFrame:Show() |
self:UnregisterEvent("RUNE_POWER_UPDATE", UpdateRune) |
self:UnregisterEvent("RUNE_TYPE_UPDATE", UpdateType) |
end |
oUF:AddElement("Runes", Update, Enable, Disable) |
--[[ 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) |
--[[ Element: Class Icons |
Toggles the visibility of icons depending on the player's class and |
specialization. |
Widget |
ClassIcons - An array consisting of five UI Textures. |
Notes |
Monk - Harmony Orbs |
Paladin - Holy Power |
Priest - Shadow Orbs |
Warlock - Soul Shards |
Examples |
local ClassIcons = {} |
for index = 1, 5 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 |
]] |
local parent, ns = ... |
local oUF = ns.oUF |
local PlayerClass = select(2, UnitClass'player') |
-- Holds the class specific stuff. |
local ClassPowerType, ClassPowerTypes |
local ClassPowerEnable, ClassPowerDisable |
local RequireSpec, RequireSpell |
local UpdateTexture = function(element) |
local red, green, blue, desaturated |
if(PlayerClass == 'MONK') then |
red, green, blue = 0, 1, .59 |
desaturated = true |
elseif(PlayerClass == 'WARLOCK') then |
red, green, blue = 1, .5, 1 |
desaturated = true |
elseif(PlayerClass == 'PRIEST') then |
red, green, blue = 1, 1, 1 |
elseif(PlayerClass == 'PALADIN') then |
red, green, blue = 1, .96, .41 |
desaturated = true |
end |
for i=1, 5 do |
if(element[i].SetDesaturated) then |
element[i]:SetDesaturated(desaturated) |
end |
element[i]:SetVertexColor(red, green, blue) |
end |
end |
local ToggleVehicle = function(self, state) |
local element = self.ClassIcons |
for i=1, 5 do |
element[i]:Hide() |
end |
(element.UpdateTexture or UpdateTexture) (element) |
if(state) then |
ClassPowerDisable(self) |
else |
ClassPowerEnable(self) |
end |
end |
local Update = function(self, event, unit, powerType) |
local element = self.ClassIcons |
local hasVehicle = UnitHasVehicleUI('player') |
if(element.__inVehicle ~= hasVehicle) then |
element.__inVehicle = hasVehicle |
ToggleVehicle(self, hasVehicle) |
-- Continue the update if we left a vehicle. |
if(hasVehicle) then return end |
end |
if((unit and unit ~= 'player') or (powerType and not ClassPowerTypes[powerType])) then |
return |
end |
if(element.PreUpdate) then |
element:PreUpdate() |
end |
local cur = UnitPower('player', ClassPowerType) |
local max = UnitPowerMax('player', ClassPowerType) |
for i=1, max do |
if(i <= cur) then |
element[i]:Show() |
else |
element[i]:Hide() |
end |
end |
local oldMax = element.__max |
if(max ~= element.__max) then |
if(max < element.__max) then |
for i=max + 1, element.__max do |
element[i]:Hide() |
end |
end |
element.__max = max |
end |
if(element.PostUpdate) then |
return element:PostUpdate(cur, max, oldMax ~= max) |
end |
end |
local Path = function(self, ...) |
return (self.ClassIcons.Override or Update) (self, ...) |
end |
local Visibility = function(self, event, unit) |
local element = self.ClassIcons |
if( |
(RequireSpec and RequireSpec ~= GetSpecialization()) |
or (RequireSpell and not IsPlayerSpell(RequireSpell))) then |
for i=1, 5 do |
element[i]:Hide() |
end |
ClassPowerDisable(self) |
else |
ClassPowerEnable(self) |
return Path(self, 'UpdateVisibility') |
end |
end |
local ForceUpdate = function(element) |
return Path(element.__owner, 'ForceUpdate', element.__owner.unit) |
end |
do |
local _ClassPowerEnable = function(self) |
self:RegisterEvent('UNIT_DISPLAYPOWER', Update) |
self:RegisterEvent('UNIT_POWER_FREQUENT', Update) |
end |
local _ClassPowerDisable = function(self) |
self:UnregisterEvent('UNIT_DISPLAYPOWER', Update) |
self:UnregisterEvent('UNIT_POWER_FREQUENT', Update) |
end |
if(PlayerClass == 'MONK') then |
ClassPowerType = SPELL_POWER_CHI |
ClassPowerTypes = { |
['CHI'] = true, |
['DARK_FORCE'] = true, |
} |
ClassPowerEnable = _ClassPowerEnable |
ClassPowerDisable = _ClassPowerDisable |
elseif(PlayerClass == 'PALADIN') then |
ClassPowerType = SPELL_POWER_HOLY_POWER |
ClassPowerTypes = { |
HOLY_POWER = true, |
} |
ClassPowerEnable = _ClassPowerEnable |
ClassPowerDisable = _ClassPowerDisable |
elseif(PlayerClass == 'PRIEST') then |
ClassPowerType = SPELL_POWER_SHADOW_ORBS |
ClassPowerTypes = { |
SHADOW_ORBS = true, |
} |
RequireSpec = SPEC_PRIEST_SHADOW |
ClassPowerEnable = function(self) |
self:RegisterEvent('PLAYER_TALENT_UPDATE', Visibility, true) |
return _ClassPowerEnable(self) |
end |
ClassPowerDisable = function(self) |
self:UnregisterEvent('PLAYER_TALENT_UPDATE', Visibility) |
return _ClassPowerDisable(self) |
end |
elseif(PlayerClass == 'WARLOCK') then |
ClassPowerType = SPELL_POWER_SOUL_SHARDS |
ClassPowerTypes = { |
SOUL_SHARDS = true, |
} |
RequireSpell = WARLOCK_SOULBURN |
ClassPowerEnable = function(self) |
self:RegisterEvent('SPELLS_CHANGED', Visibility, true) |
return _ClassPowerEnable(self) |
end |
ClassPowerDisable = function(self) |
self:UnregisterEvent('SPELLS_CHANGED', Visibility) |
return _ClassPowerDisable(self) |
end |
end |
end |
local Enable = function(self, unit) |
local element = self.ClassIcons |
if(not element) then return end |
element.__owner = self |
element.__max = 0 |
element.ForceUpdate = ForceUpdate |
if(ClassPowerEnable) then |
ClassPowerEnable(self) |
for i=1, 5 do |
local icon = element[i] |
if(icon:IsObjectType'Texture' and not icon:GetTexture()) then |
icon:SetTexCoord(0.45703125, 0.60546875, 0.44531250, 0.73437500) |
icon:SetTexture([[Interface\PlayerFrame\Priest-ShadowUI]]) |
end |
end |
(element.UpdateTexture or UpdateTexture) (element) |
return true |
end |
end |
local Disable = function(self) |
local element = self.ClassIcons |
if(not element) then return end |
ClassPowerDisable(self) |
end |
oUF:AddElement('ClassIcons', Update, Enable, Disable) |
--[[ 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. |
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 _TIMERS = {} |
local ReadyCheckFrame |
local removeEntry = function(icon) |
_TIMERS[icon] = nil |
if(not next(_TIMERS)) then |
return ReadyCheckFrame:Hide() |
end |
end |
local Start = function(self) |
removeEntry(self) |
self:SetTexture(READY_CHECK_WAITING_TEXTURE) |
self.state = 'waiting' |
self:SetAlpha(1) |
self:Show() |
end |
local Confirm = function(self, ready) |
removeEntry(self) |
if(ready) then |
self:SetTexture(READY_CHECK_READY_TEXTURE) |
self.state = 'ready' |
else |
self:SetTexture(READY_CHECK_NOT_READY_TEXTURE) |
self.state = 'notready' |
end |
self:SetAlpha(1) |
self:Show() |
end |
local Finish = function(self) |
if(self.state == 'waiting') then |
self:SetTexture(READY_CHECK_AFK_TEXTURE) |
self.state = 'afk' |
end |
self.finishedTimer = self.finishedTime or 10 |
self.fadeTimer = self.fadeTime or 1.5 |
_TIMERS[self] = true |
ReadyCheckFrame:Show() |
end |
local OnUpdate = function(self, elapsed) |
for icon in next, _TIMERS do |
if(icon.finishedTimer) then |
icon.finishedTimer = icon.finishedTimer - elapsed |
if(icon.finishedTimer <= 0) then |
icon.finishedTimer = nil |
end |
elseif(icon.fadeTimer) then |
icon.fadeTimer = icon.fadeTimer - elapsed |
icon:SetAlpha(icon.fadeTimer / (icon.fadeTime or 1.5)) |
if(icon.fadeTimer <= 0) then |
icon:Hide() |
removeEntry(icon) |
end |
end |
end |
end |
local Update = function(self, event) |
local unit = self.unit |
local readyCheck = self.ReadyCheck |
if(event == 'READY_CHECK_FINISHED') then |
Finish(readyCheck) |
else |
local status = GetReadyCheckStatus(unit) |
if(UnitExists(unit) and status) then |
if(status == 'ready') then |
Confirm(readyCheck, 1) |
elseif(status == 'notready') then |
Confirm(readyCheck) |
else |
Start(readyCheck) |
end |
end |
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 readyCheck = self.ReadyCheck |
if(readyCheck and (unit and (unit:sub(1, 5) == 'party' or unit:sub(1,4) == 'raid'))) then |
readyCheck.__owner = self |
readyCheck.ForceUpdate = ForceUpdate |
if(not ReadyCheckFrame) then |
ReadyCheckFrame = CreateFrame'Frame' |
ReadyCheckFrame:SetScript('OnUpdate', OnUpdate) |
end |
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 readyCheck = self.ReadyCheck |
if(readyCheck) then |
readyCheck: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) |
--[[ Element: Harmony Orbs |
Toggles visibility of the players Chi. |
Widget |
Harmomy - An array consisting of four UI widgets. |
Notes |
The default harmony orb texture will be applied to textures within the Harmony |
array that don't have a texture or color defined. |
Examples |
local Harmony = {} |
for index = 1, UnitPowerMax('player', SPELL_POWER_LIGHT_FORCE) do |
local Chi = self:CreateTexture(nil, 'BACKGROUND') |
-- Position and size of the chi orbs. |
Chi:SetSize(14, 14) |
Chi:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', index * Chi:GetWidth(), 0) |
Harmony[index] = Chi |
end |
-- Register with oUF |
self.Harmony = Harmony |
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 SPELL_POWER_LIGHT_FORCE = SPELL_POWER_LIGHT_FORCE |
local Update = function(self, event, unit) |
if(unit ~= 'player') then return end |
local element = self.Harmony |
if(element.PreUpdate) then |
element:PreUpdate() |
end |
local chi = UnitPower(unit, SPELL_POWER_LIGHT_FORCE) |
for index = 1, UnitPowerMax(unit, SPELL_POWER_LIGHT_FORCE) do |
if(index <= chi) then |
element[index]:Show() |
else |
element[index]:Hide() |
end |
end |
if(element.PostUpdate) then |
return element:PostUpdate(chi) |
end |
end |
local Path = function(self, ...) |
return (self.Harmony.Override or Update) (self, ...) |
end |
local ForceUpdate = function(element) |
return Path(element.__owner, 'ForceUpdate', element.__owner.unit) |
end |
local Enable = function(self, unit) |
local element = self.Harmony |
if(element and unit == 'player') then |
element.__owner = self |
element.ForceUpdate = ForceUpdate |
self:RegisterEvent('UNIT_POWER', Path, true) |
self:RegisterEvent('UNIT_DISPLAYPOWER', Path, true) |
for index = 1, UnitPowerMax(unit, SPELL_POWER_LIGHT_FORCE) do |
local chi = element[index] |
if(chi:IsObjectType'Texture' and not chi:GetTexture()) then |
chi:SetTexture[[Interface\PlayerFrame\MonkUI]] |
chi:SetTexCoord(0.00390625, 0.08593750, 0.71093750, 0.87500000) |
end |
end |
return true |
end |
end |
local Disable = function(self) |
local element = self.Harmony |
if(element) then |
self:UnregisterEvent('UNIT_POWER', Path) |
self:UnregisterEvent('UNIT_DISPLAYPOWER', Path) |
end |
end |
oUF:AddElement('Harmony', Path, Enable, Disable) |
--[[ Element: PvP Icon |
Handles updating and toggles visibility based upon the units PvP status. |
Widget |
PvP - A Texture used to display the faction or FFA icon. |
Notes |
This element updates by changing the texture. |
Examples |
-- Position and size |
local PvP = self:CreateTexture(nil, 'OVERLAY') |
PvP:SetSize(16, 16) |
PvP:SetPoint('TOPRIGHT', self) |
-- Register it with oUF |
self.PvP = PvP |
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 pvp = self.PvP |
if(pvp.PreUpdate) then |
pvp:PreUpdate() |
end |
local status |
local factionGroup = UnitFactionGroup(unit) |
if(UnitIsPVPFreeForAll(unit)) then |
pvp:SetTexture[[Interface\TargetingFrame\UI-PVP-FFA]] |
status = 'ffa' |
-- XXX - WoW5: UnitFactionGroup() can return Neutral as well. |
elseif(factionGroup and factionGroup ~= 'Neutral' and UnitIsPVP(unit)) then |
pvp:SetTexture([[Interface\TargetingFrame\UI-PVP-]]..factionGroup) |
status = factionGroup |
end |
if(status) then |
pvp:Show() |
else |
pvp:Hide() |
end |
if(pvp.PostUpdate) then |
return pvp:PostUpdate(status) |
end |
end |
local Path = function(self, ...) |
return (self.PvP.Override or Update) (self, ...) |
end |
local ForceUpdate = function(element) |
return Path(element.__owner, 'ForceUpdate', element.__owner.unit) |
end |
local Enable = function(self) |
local pvp = self.PvP |
if(pvp) then |
pvp.__owner = self |
pvp.ForceUpdate = ForceUpdate |
self:RegisterEvent("UNIT_FACTION", Path) |
return true |
end |
end |
local Disable = function(self) |
local pvp = self.PvP |
if(pvp) then |
pvp:Hide() |
self:UnregisterEvent("UNIT_FACTION", Path) |
end |
end |
oUF:AddElement('PvP', Path, Enable, Disable) |
--[[ 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) |
--[[ 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) |
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) |
--[[ 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) |
--[[ Element: Eclipse Bar |
Handle updating and visibility of the Druid eclipse state status bars. |
Widget |
EclipseBar - A table to hold the sub-widgets. |
Sub-Widgets |
LunarBar - A StatusBar used to represent the lunar power state. |
SolarBar - A StatusBar used to represent the solar power state. |
Notes |
The default StatusBar texture will be applied if the UI widget doesn't have a |
status bar texture or color defined. |
Examples |
-- Position and size |
local LunarBar = CreateFrame('StatusBar', nil, self) |
LunarBar:SetPoint('LEFT') |
LunarBar:SetSize(160, 20) |
local SolarBar = CreateFrame('StatusBar', nil, self) |
SolarBar:SetPoint('LEFT', LunarBar:GetStatusBarTexture(), 'RIGHT') |
SolarBar:SetSize(160, 20) |
-- Register with oUF |
self.EclipseBar = { |
LunarBar = LunarBar, |
SolarBar = SolarBar, |
} |
Hooks and Callbacks |
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')) ~= 'DRUID') then return end |
local parent, ns = ... |
local oUF = ns.oUF |
local ECLIPSE_BAR_SOLAR_BUFF_ID = ECLIPSE_BAR_SOLAR_BUFF_ID |
local ECLIPSE_BAR_LUNAR_BUFF_ID = ECLIPSE_BAR_LUNAR_BUFF_ID |
local SPELL_POWER_ECLIPSE = SPELL_POWER_ECLIPSE |
local MOONKIN_FORM = MOONKIN_FORM |
local UNIT_POWER = function(self, event, unit, powerType) |
if(self.unit ~= unit or (event == 'UNIT_POWER' and powerType ~= 'ECLIPSE')) then return end |
local eb = self.EclipseBar |
local power = UnitPower('player', SPELL_POWER_ECLIPSE) |
local maxPower = UnitPowerMax('player', SPELL_POWER_ECLIPSE) |
if(eb.LunarBar) then |
eb.LunarBar:SetMinMaxValues(-maxPower, maxPower) |
eb.LunarBar:SetValue(power) |
end |
if(eb.SolarBar) then |
eb.SolarBar:SetMinMaxValues(-maxPower, maxPower) |
eb.SolarBar:SetValue(power * -1) |
end |
if(eb.PostUpdatePower) then |
--[[ :PostUpdatePower(unit) |
Callback which is called after lunar and solar bar was updated. |
Arguments |
self - The widget that holds the eclipse frame. |
unit - The unit that has the widget. |
]] |
return eb:PostUpdatePower(unit) |
end |
end |
local UPDATE_VISIBILITY = function(self, event) |
local eb = self.EclipseBar |
-- check form/mastery |
local showBar |
local form = GetShapeshiftFormID() |
if(not form) then |
local ptt = GetSpecialization() |
if(ptt and ptt == 1) then -- player has balance spec |
showBar = true |
end |
elseif(form == MOONKIN_FORM) then |
showBar = true |
end |
if(showBar) then |
eb:Show() |
else |
eb:Hide() |
end |
if(eb.PostUpdateVisibility) then |
--[[ :PostUpdateVisibility(unit) |
Callback which is called after the eclipse frame was shown or hidden. |
Arguments |
self - The widget that holds the eclipse frame. |
unit - The unit that has the widget. |
]] |
return eb:PostUpdateVisibility(self.unit) |
end |
end |
local UNIT_AURA = function(self, event, unit) |
if(self.unit ~= unit) then return end |
local i = 1 |
local hasSolarEclipse, hasLunarEclipse |
repeat |
local _, _, _, _, _, _, _, _, _, _, spellID = UnitAura(unit, i, 'HELPFUL') |
if(spellID == ECLIPSE_BAR_SOLAR_BUFF_ID) then |
hasSolarEclipse = true |
elseif(spellID == ECLIPSE_BAR_LUNAR_BUFF_ID) then |
hasLunarEclipse = true |
end |
i = i + 1 |
until not spellID |
local eb = self.EclipseBar |
eb.hasSolarEclipse = hasSolarEclipse |
eb.hasLunarEclipse = hasLunarEclipse |
if(eb.PostUnitAura) then |
--[[ :PostUnitAura(unit) |
Callback which is called after the eclipse state was checked. |
Arguments |
self - The widget that holds the eclipse frame. |
unit - The unit that has the widget. |
]] |
return eb:PostUnitAura(unit) |
end |
end |
local ECLIPSE_DIRECTION_CHANGE = function(self, event, isLunar) |
local eb = self.EclipseBar |
eb.directionIsLunar = isLunar |
if(eb.PostDirectionChange) then |
--[[ :PostDirectionChange(unit) |
Callback which is called after eclipse direction was changed. |
Arguments |
self - The widget that holds the eclipse frame. |
unit - The unit that has the widget. |
]] |
return eb:PostDirectionChange(self.unit) |
end |
end |
local Update = function(self, ...) |
UNIT_POWER(self, ...) |
UNIT_AURA(self, ...) |
return UPDATE_VISIBILITY(self, ...) |
end |
local ForceUpdate = function(element) |
return Update(element.__owner, 'ForceUpdate', element.__owner.unit, 'ECLIPSE') |
end |
local function Enable(self) |
local eb = self.EclipseBar |
if(eb) then |
eb.__owner = self |
eb.ForceUpdate = ForceUpdate |
if(eb.LunarBar and eb.LunarBar:IsObjectType'StatusBar' and not eb.LunarBar:GetStatusBarTexture()) then |
eb.LunarBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]]) |
end |
if(eb.SolarBar and eb.SolarBar:IsObjectType'StatusBar' and not eb.SolarBar:GetStatusBarTexture()) then |
eb.SolarBar:SetStatusBarTexture([[Interface\TargetingFrame\UI-StatusBar]]) |
end |
self:RegisterEvent('ECLIPSE_DIRECTION_CHANGE', ECLIPSE_DIRECTION_CHANGE, true) |
self:RegisterEvent('PLAYER_TALENT_UPDATE', UPDATE_VISIBILITY, true) |
self:RegisterEvent('UNIT_AURA', UNIT_AURA) |
self:RegisterEvent('UNIT_POWER', UNIT_POWER) |
self:RegisterEvent('UPDATE_SHAPESHIFT_FORM', UPDATE_VISIBILITY, true) |
return true |
end |
end |
local function Disable(self) |
local eb = self.EclipseBar |
if(eb) then |
eb:Hide() |
self:UnregisterEvent('ECLIPSE_DIRECTION_CHANGE', ECLIPSE_DIRECTION_CHANGE) |
self:UnregisterEvent('PLAYER_TALENT_UPDATE', UPDATE_VISIBILITY) |
self:UnregisterEvent('UNIT_AURA', UNIT_AURA) |
self:UnregisterEvent('UNIT_POWER', UNIT_POWER) |
self:UnregisterEvent('UPDATE_SHAPESHIFT_FORM', UPDATE_VISIBILITY) |
end |
end |
oUF:AddElement('EclipseBar', Update, Enable, Disable) |
--[[ 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) |
if(select(2, UnitClass('player')) ~= 'PRIEST') then return end |
local parent, ns = ... |
local oUF = ns.oUF |
local PRIEST_BAR_NUM_ORBS = PRIEST_BAR_NUM_ORBS |
local SPELL_POWER_SHADOW_ORBS = SPELL_POWER_SHADOW_ORBS |
local function Update(self, event, unit, powerType) |
if(self.unit ~= unit or (powerType and powerType ~= 'SHADOW_ORBS')) then return end |
local sb = self.ShadowOrbsBar |
if(sb.PreUpdate) then |
sb:PreUpdate(unit) |
end |
local numOrbs = UnitPower('player', SPELL_POWER_SHADOW_ORBS) |
for i = 1, PRIEST_BAR_NUM_ORBS do |
if i <= numOrbs then |
sb[i]:SetAlpha(1) |
else |
sb[i]:SetAlpha(.2) |
end |
end |
if(sb.PostUpdate) then |
return sb:PostUpdate(numOrbs) |
end |
end |
local Path = function(self, ...) |
return (self.ShadowOrbsBar.Override or Update) (self, ...) |
end |
local ForceUpdate = function(element) |
return Path(element.__owner, 'ForceUpdate', element.__owner.unit, 'SHADOW_ORBS') |
end |
local function Visibility(self, event, unit) |
local sb = self.ShadowOrbsBar |
local spec = GetSpecialization() |
if spec == SPEC_PRIEST_SHADOW then |
sb:Show() |
if self.Debuffs then self.Debuffs:SetPoint("BOTTOMRIGHT", self, "TOPRIGHT", 2, 19) end |
else |
sb:Hide() |
if self.Debuffs then self.Debuffs:SetPoint("BOTTOMRIGHT", self, "TOPRIGHT", 2, 5) end |
end |
end |
local function Enable(self, unit) |
local sb = self.ShadowOrbsBar |
if(sb) and unit == 'player' then |
sb.__owner = self |
sb.ForceUpdate = ForceUpdate |
self:RegisterEvent('UNIT_POWER', Path) |
self:RegisterEvent('UNIT_DISPLAYPOWER', Path) |
sb.Visibility = CreateFrame("Frame", nil, sb) |
sb.Visibility:RegisterEvent("PLAYER_TALENT_UPDATE") |
sb.Visibility:SetScript("OnEvent", function(frame, event, unit) Visibility(self, event, unit) end) |
return true |
end |
end |
local function Disable(self) |
local sb = self.ShadowOrbsBar |
if(sb) then |
self:UnregisterEvent('UNIT_POWER', Path) |
self:UnregisterEvent('UNIT_DISPLAYPOWER', Path) |
sb.Visibility:UnregisterEvent("PLAYER_TALENT_UPDATE") |
end |
end |
oUF:AddElement('ShadowOrbsBar', Path, Enable, Disable) |
--[[ 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) |
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 |
-- Order the list based upon the default UIs priorities. |
local priorities = STANDARD_TOTEM_PRIORITIES |
if(select(2, UnitClass'player') == 'SHAMAN') then |
priorities = SHAMAN_TOTEM_PRIORITIES |
end |
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) |
if(slot > MAX_TOTEMS) then return end |
local totems = self.Totems |
if(totems.PreUpdate) then totems:PreUpdate(priorities[slot]) end |
local totem = totems[priorities[slot]] |
local haveTotem, name, start, duration, icon = GetTotemInfo(slot) |
if(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(priorities[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, MAX_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.__map = { unpack(priorities) } |
totems.ForceUpdate = ForceUpdate |
for i = 1, MAX_TOTEMS do |
local totem = totems[i] |
totem:SetID(priorities[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.Show = TotemFrame.Hide |
TotemFrame:Hide() |
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) |
if(self.Totems) then |
for i = 1, MAX_TOTEMS do |
self.Totems[i]:Hide() |
end |
TotemFrame.Show = nil |
TotemFrame:Show() |
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) |
--[[ 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. |
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 parent, ns = ... |
local oUF = ns.oUF |
local UnitName = UnitName |
local GetTime = GetTime |
local UnitCastingInfo = UnitCastingInfo |
local UnitChannelInfo = UnitChannelInfo |
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_START = function(self, event, unit, spell) |
if(self.unit ~= unit) then return end |
local castbar = self.Castbar |
local name, _, text, texture, startTime, endTime, _, castid, interrupt = UnitCastingInfo(unit) |
if(not name) then |
castbar:Hide() |
return |
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 = interrupt |
castbar:SetMinMaxValues(0, max) |
castbar:SetValue(0) |
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 interrupt) 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) |
end |
castbar:Show() |
end |
local UNIT_SPELLCAST_FAILED = function(self, event, unit, spellname, _, castid) |
if(self.unit ~= unit) then return end |
local castbar = self.Castbar |
if(castbar.castid ~= castid) then |
return |
end |
castbar.casting = nil |
castbar.interrupt = nil |
castbar:SetValue(0) |
castbar:Hide() |
if(castbar.PostCastFailed) then |
return castbar:PostCastFailed(unit, spellname, castid) |
end |
end |
local UNIT_SPELLCAST_INTERRUPTED = function(self, event, unit, spellname, _, castid) |
if(self.unit ~= unit) then return end |
local castbar = self.Castbar |
if(castbar.castid ~= castid) then |
return |
end |
castbar.casting = nil |
castbar.channeling = nil |
castbar:SetValue(0) |
castbar:Hide() |
if(castbar.PostCastInterrupted) then |
return castbar:PostCastInterrupted(unit, spellname, castid) |
end |
end |
local UNIT_SPELLCAST_INTERRUPTIBLE = function(self, event, unit) |
if(self.unit ~= unit) then return end |
local shield = self.Castbar.Shield |
if(shield) then |
shield:Hide() |
end |
local castbar = self.Castbar |
if(castbar.PostCastInterruptible) then |
return castbar:PostCastInterruptible(unit) |
end |
end |
local UNIT_SPELLCAST_NOT_INTERRUPTIBLE = function(self, event, unit) |
if(self.unit ~= unit) then return end |
local shield = self.Castbar.Shield |
if(shield) then |
shield:Show() |
end |
local castbar = self.Castbar |
if(castbar.PostCastNotInterruptible) then |
return castbar:PostCastNotInterruptible(unit) |
end |
end |
local UNIT_SPELLCAST_DELAYED = function(self, event, unit, spellname, _, castid) |
if(self.unit ~= unit) then return end |
local castbar = self.Castbar |
local name, _, text, texture, startTime, endTime = 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) |
end |
end |
local UNIT_SPELLCAST_STOP = function(self, event, unit, spellname, _, castid) |
if(self.unit ~= unit) then return end |
local castbar = self.Castbar |
if(castbar.castid ~= castid) then |
return |
end |
castbar.casting = nil |
castbar.interrupt = nil |
castbar:SetValue(0) |
castbar:Hide() |
if(castbar.PostCastStop) then |
return castbar:PostCastStop(unit, spellname, castid) |
end |
end |
local UNIT_SPELLCAST_CHANNEL_START = function(self, event, unit, spellname) |
if(self.unit ~= unit) then return end |
local castbar = self.Castbar |
local name, _, text, texture, startTime, endTime, isTrade, interrupt = 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.channeling = true |
castbar.interrupt = interrupt |
-- 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 interrupt) 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) end |
castbar:Show() |
end |
local UNIT_SPELLCAST_CHANNEL_UPDATE = function(self, event, unit, spellname) |
if(self.unit ~= unit) then return end |
local castbar = self.Castbar |
local name, _, text, texture, startTime, endTime, oldStart = UnitChannelInfo(unit) |
if(not name or not castbar:IsShown()) then |
return |
end |
local duration = (endTime / 1000) - GetTime() |
castbar.delay = castbar.delay + castbar.duration - duration |
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) |
end |
end |
local UNIT_SPELLCAST_CHANNEL_STOP = function(self, event, unit, spellname) |
if(self.unit ~= unit) then return end |
local castbar = self.Castbar |
if(castbar:IsShown()) then |
castbar.channeling = nil |
castbar.interrupt = nil |
castbar:SetValue(castbar.max) |
castbar:Hide() |
if(castbar.PostChannelStop) then |
return castbar:PostChannelStop(unit, spellname) |
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 |
else |
self.unitName = nil |
self.casting = nil |
self.castid = nil |
self.channeling = nil |
self:SetValue(1) |
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(object, unit) |
local castbar = object.Castbar |
if(castbar) then |
castbar.__owner = object |
castbar.ForceUpdate = ForceUpdate |
if(not (unit and unit:match'%wtarget$')) then |
object:RegisterEvent("UNIT_SPELLCAST_START", UNIT_SPELLCAST_START) |
object:RegisterEvent("UNIT_SPELLCAST_FAILED", UNIT_SPELLCAST_FAILED) |
object:RegisterEvent("UNIT_SPELLCAST_STOP", UNIT_SPELLCAST_STOP) |
object:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED", UNIT_SPELLCAST_INTERRUPTED) |
object:RegisterEvent("UNIT_SPELLCAST_INTERRUPTIBLE", UNIT_SPELLCAST_INTERRUPTIBLE) |
object:RegisterEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE", UNIT_SPELLCAST_NOT_INTERRUPTIBLE) |
object:RegisterEvent("UNIT_SPELLCAST_DELAYED", UNIT_SPELLCAST_DELAYED) |
object:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START", UNIT_SPELLCAST_CHANNEL_START) |
object:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", UNIT_SPELLCAST_CHANNEL_UPDATE) |
object:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", UNIT_SPELLCAST_CHANNEL_STOP) |
end |
castbar:SetScript("OnUpdate", castbar.OnUpdate or onUpdate) |
if(object.unit == "player") then |
CastingBarFrame:UnregisterAllEvents() |
CastingBarFrame.Show = CastingBarFrame.Hide |
CastingBarFrame:Hide() |
elseif(object.unit == 'pet') then |
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:SetTexture(1, 0, 0) |
end |
castbar:Hide() |
return true |
end |
end |
local Disable = function(object, unit) |
local castbar = object.Castbar |
if(castbar) then |
castbar:Hide() |
object:UnregisterEvent("UNIT_SPELLCAST_START", UNIT_SPELLCAST_START) |
object:UnregisterEvent("UNIT_SPELLCAST_FAILED", UNIT_SPELLCAST_FAILED) |
object:UnregisterEvent("UNIT_SPELLCAST_STOP", UNIT_SPELLCAST_STOP) |
object:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED", UNIT_SPELLCAST_INTERRUPTED) |
object:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTIBLE", UNIT_SPELLCAST_INTERRUPTIBLE) |
object:UnregisterEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE", UNIT_SPELLCAST_NOT_INTERRUPTIBLE) |
object:UnregisterEvent("UNIT_SPELLCAST_DELAYED", UNIT_SPELLCAST_DELAYED) |
object:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START", UNIT_SPELLCAST_CHANNEL_START) |
object:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", UNIT_SPELLCAST_CHANNEL_UPDATE) |
object:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", UNIT_SPELLCAST_CHANNEL_STOP) |
castbar:SetScript("OnUpdate", nil) |
end |
end |
oUF:AddElement('Castbar', Update, Enable, Disable) |
--[[ Element: Combo Point Icons |
Toggles visibility of the player and vehicles combo points. |
Widget |
CPoints - An array consisting of five UI widgets. |
Notes |
The default combo point texture will be applied to textures within the CPoints |
array that don't have a texture or color defined. |
Examples |
local CPoints = {} |
for index = 1, MAX_COMBO_POINTS do |
local CPoint = self:CreateTexture(nil, 'BACKGROUND') |
-- Position and size of the combo point. |
CPoint:SetSize(12, 16) |
CPoint:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', index * CPoint:GetWidth(), 0) |
CPoints[index] = CPoint |
end |
-- Register with oUF |
self.CPoints = CPoints |
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 GetComboPoints = GetComboPoints |
local MAX_COMBO_POINTS = MAX_COMBO_POINTS |
local Update = function(self, event, unit) |
if(unit == 'pet') then return end |
local cpoints = self.CPoints |
if(cpoints.PreUpdate) then |
cpoints:PreUpdate() |
end |
local cp |
if(UnitHasVehicleUI'player') then |
cp = GetComboPoints('vehicle', 'target') |
else |
cp = GetComboPoints('player', 'target') |
end |
for i=1, MAX_COMBO_POINTS do |
if(i <= cp) then |
cpoints[i]:Show() |
else |
cpoints[i]:Hide() |
end |
end |
if(cpoints.PostUpdate) then |
return cpoints:PostUpdate(cp) |
end |
end |
local Path = function(self, ...) |
return (self.CPoints.Override or Update) (self, ...) |
end |
local ForceUpdate = function(element) |
return Path(element.__owner, 'ForceUpdate', element.__owner.unit) |
end |
local Enable = function(self) |
local cpoints = self.CPoints |
if(cpoints) then |
cpoints.__owner = self |
cpoints.ForceUpdate = ForceUpdate |
self:RegisterEvent('UNIT_COMBO_POINTS', Path, true) |
self:RegisterEvent('PLAYER_TARGET_CHANGED', Path, true) |
for index = 1, MAX_COMBO_POINTS do |
local cpoint = cpoints[index] |
if(cpoint:IsObjectType'Texture' and not cpoint:GetTexture()) then |
cpoint:SetTexture[[Interface\ComboFrame\ComboPoint]] |
cpoint:SetTexCoord(0, 0.375, 0, 1) |
end |
end |
return true |
end |
end |
local Disable = function(self) |
local cpoints = self.CPoints |
if(cpoints) then |
for index = 1, MAX_COMBO_POINTS do |
cpoints[index]:Hide() |
end |
self:UnregisterEvent('UNIT_COMBO_POINTS', Path) |
self:UnregisterEvent('PLAYER_TARGET_CHANGED', Path) |
end |
end |
oUF:AddElement('CPoints', Path, Enable, Disable) |
--[[ 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(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) |
--[[ 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') 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) 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 |
altpowerbar:SetScript('OnLeave', OnLeave) |
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) |
--[[ Element: Sould Shards Indicator |
Toggles the visibility of the player's should shard indicator. |
Widget |
SoulShards - An array consisting of three UI widgets. |
Examples |
local SoulShards = {} |
for index = 1, SHARD_BAR_NUM_SHARDS do |
local Shard = self:CreateTexture(nil, 'BACKGROUND') |
-- Position and size |
Shard:SetSize(16, 16) |
Shard:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', index * Shard:GetWidth(), 0) |
SoulShards[index] = Shard |
end |
-- Register with oUF |
self.SoulShards = SoulShards |
]] |
if(select(2, UnitClass('player')) ~= 'WARLOCK') then return end |
local parent, ns = ... |
local oUF = ns.oUF |
local SPELL_POWER_SOUL_SHARDS = SPELL_POWER_SOUL_SHARDS |
local SHARD_BAR_NUM_SHARDS = SHARD_BAR_NUM_SHARDS |
local Update = function(self, event, unit, powerType) |
if(self.unit ~= unit or (powerType and powerType ~= 'SOUL_SHARDS')) then return end |
local ss = self.SoulShards |
if(ss.PreUpdate) then ss:PreUpdate() end |
local num = UnitPower('player', SPELL_POWER_SOUL_SHARDS) |
for i = 1, SHARD_BAR_NUM_SHARDS do |
if(i <= num) then |
ss[i]:Show() |
else |
ss[i]:Hide() |
end |
end |
if(ss.PostUpdate) then |
return ss:PostUpdate(num) |
end |
end |
local Path = function(self, ...) |
return (self.SoulShards.Override or Update) (self, ...) |
end |
local ForceUpdate = function(element) |
return Path(element.__owner, 'ForceUpdate', element.__owner.unit, 'SOUL_SHARDS') |
end |
local function Enable(self) |
local ss = self.SoulShards |
if(ss) then |
ss.__owner = self |
ss.ForceUpdate = ForceUpdate |
self:RegisterEvent('UNIT_POWER_FREQUENT', Path) |
return true |
end |
end |
local function Disable(self) |
local ss = self.SoulShards |
if(ss) then |
self:UnregisterEvent('UNIT_POWER_FREQUENT', Path) |
end |
end |
oUF:AddElement('SoulShards', Path, Enable, Disable) |
--[[ 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 |
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 |
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 |
end |
else |
SetPortraitTexture(portrait, unit) |
end |
if(portrait.PostUpdate) then |
return portrait:PostUpdate(unit) |
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) |
--[[ 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) |
--[[ 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) |
icons.createdIcons = icons.createdIcons + 1 |
local button = CreateFrame("Button", nil, icons) |
button:RegisterForClicks'RightButtonUp' |
local cd = CreateFrame("Cooldown", nil, button) |
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) |
table.insert(icons, button) |
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, rank, texture, count, dtype, duration, timeLeft, caster) |
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, dtype, duration, timeLeft, caster, isStealable, shouldConsolidate, spellID, canApplyAura, isBossDebuff = UnitAura(unit, index, filter) |
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. |
]] |
icon = (icons.CreateIcon or createAuraIcon) (icons, n) |
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 = (icons.CustomFilter or customFilter) (icons, unit, icon, name, rank, texture, count, dtype, duration, timeLeft, caster, isStealable, shouldConsolidate, spellID, canApplyAura, isBossDebuff) |
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(timeLeft - 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[dtype] 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] or (auras.CreateIcon or createAuraIcon) (auras, visibleBuffs) |
-- 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) |
if(select(2, UnitClass('player')) ~= 'PALADIN') then return end |
local parent, ns = ... |
local oUF = ns.oUF |
local SPELL_POWER_HOLY_POWER = SPELL_POWER_HOLY_POWER |
local Update = function(self, event, unit, powerType) |
if(self.unit ~= unit or (powerType and powerType ~= 'HOLY_POWER')) then return end |
local hp = self.HolyPower |
if(hp.PreUpdate) then hp:PreUpdate() end |
local maxHolyPower = UnitPowerMax('player', SPELL_POWER_HOLY_POWER) |
local num = UnitPower('player', SPELL_POWER_HOLY_POWER) |
for i = 1, maxHolyPower do |
if(i <= num) then |
hp[i]:Show() |
else |
hp[i]:Hide() |
end |
end |
if(hp.PostUpdate) then |
return hp:PostUpdate(num) |
end |
end |
local Path = function(self, ...) |
return (self.HolyPower.Override or Update) (self, ...) |
end |
local ForceUpdate = function(element) |
return Path(element.__owner, 'ForceUpdate', element.__owner.unit, 'HOLY_POWER') |
end |
local function Enable(self) |
local hp = self.HolyPower |
if(hp) then |
hp.__owner = self |
hp.ForceUpdate = ForceUpdate |
self:RegisterEvent('UNIT_POWER', Path) |
return true |
end |
end |
local function Disable(self) |
local hp = self.HolyPower |
if(hp) then |
self:UnregisterEvent('UNIT_POWER', Path) |
end |
end |
oUF:AddElement('HolyPower', Path, Enable, Disable) |
--[[ 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) then return end |
local hp = self.HealPrediction |
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, overAbsorb, overHealAbsorb) |
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) |
--[[ 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 GREEN_INDEX = 1; |
local YELLOW_INDEX = 2; |
local RED_INDEX = 3; |
local STANCE_OF_THE_STURY_OX_ID = 23 |
local UnitHealthMax = UnitHealthMax |
local UnitStagger = UnitStagger |
local _, playerClass = UnitClass("player") |
-- TODO: fix color in the power element |
oUF.colors.power[BREWMASTER_POWER_BAR_NAME] = { |
{0.52, 1.0, 0.52}, |
{1.0, 0.98, 0.72}, |
{1.0, 0.42, 0.42}, |
} |
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") |
local staggerPercent = stagger / maxHealth |
element:SetMinMaxValues(0, maxHealth) |
element:SetValue(stagger) |
local rgb |
if(staggerPercent >= STAGGER_RED_TRANSITION) then |
rgb = color[RED_INDEX] |
elseif(staggerPercent > STAGGER_YELLOW_TRANSITION) then |
rgb = color[YELLOW_INDEX] |
else |
rgb = color[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) |
if(STANCE_OF_THE_STURY_OX_ID ~= GetShapeshiftFormID() or UnitHasVehiclePlayerFrameUI("player")) then |
if self.Stagger:IsShown() then |
self.Stagger:Hide() |
self:UnregisterEvent('UNIT_AURA', Path) |
end |
elseif not self.Stagger:IsShown() then |
self.Stagger:Show() |
self:RegisterEvent('UNIT_AURA', Path) |
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 |
color = self.colors.power[BREWMASTER_POWER_BAR_NAME] |
self:RegisterEvent('UNIT_DISPLAYPOWER', VisibilityPath) |
self:RegisterEvent('UPDATE_SHAPESHIFT_FORM', VisibilityPath) |
if(element:IsObjectType'StatusBar' and not element:GetStatusBarTexture()) then |
element:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]] |
end |
MonkStaggerBar.Show = MonkStaggerBar.Hide |
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('UPDATE_SHAPESHIFT_FORM', VisibilityPath) |
MonkStaggerBar.Show = nil |
MonkStaggerBar:Show() |
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) |
--[[ 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. |
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. |
.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 |
oUF.colors.power = {} |
for power, color in next, PowerBarColor do |
if (type(power) == "string") then |
oUF.colors.power[power] = {color.r, color.g, color.b} |
end |
end |
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["CHI"] |
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["ECLIPSE"] |
oUF.colors.power[9] = oUF.colors.power["HOLY_POWER"] |
local GetDisplayPower = function(power, unit) |
local _, _, _, _, _, _, showOnRaid = UnitAlternatePowerInfo(unit) |
if(showOnRaid) then |
return ALTERNATE_POWER_INDEX |
end |
end |
local Update = function(self, event, unit) |
if(self.unit ~= unit) then return end |
local power = self.Power |
if(power.PreUpdate) then power:PreUpdate(unit) end |
local displayType = power.displayAltPower and GetDisplayPower(power, unit) |
local min, max = UnitPower(unit, displayType), UnitPowerMax(unit, displayType) |
local disconnected = not UnitIsConnected(unit) |
power:SetMinMaxValues(0, max) |
if(disconnected) then |
power:SetValue(max) |
else |
power:SetValue(min) |
end |
power.disconnected = disconnected |
local r, g, b, t |
if(power.colorTapping and not UnitPlayerControlled(unit) and |
UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) and not |
UnitIsTappedByAllThreatList(unit)) then |
t = self.colors.tapped |
elseif(power.colorDisconnected and not UnitIsConnected(unit)) then |
t = self.colors.disconnected |
elseif(power.colorPower) then |
local ptype, ptoken, altR, altG, altB = UnitPowerType(unit) |
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 |
r, g, b = altR, altG, altB |
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 |
r, g, b = self.ColorGradient(min, max, unpack(power.smoothGradient or self.colors.smooth)) |
end |
if(t) then |
r, g, b = t[1], t[2], t[3] |
end |
if(b) then |
power:SetStatusBarColor(r, g, b) |
local bg = power.bg |
if(bg) then |
local mu = bg.multiplier or 1 |
bg:SetVertexColor(r * mu, g * mu, b * mu) |
end |
end |
if(power.PostUpdate) then |
return power:PostUpdate(unit, min, max) |
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 |
local Enable = function(self, unit) |
local power = self.Power |
if(power) then |
power.__owner = self |
power.ForceUpdate = ForceUpdate |
if(power.frequentUpdates and (unit == 'player' or unit == 'pet')) then |
self:RegisterEvent('UNIT_POWER_FREQUENT', Path) |
else |
self:RegisterEvent('UNIT_POWER', Path) |
end |
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' and not power:GetStatusBarTexture()) then |
power:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]] |
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) |
--[[ |
-- Credits: Vika, Cladhaire, Tekkub |
]] |
local parent, ns = ... |
local oUF = ns.oUF |
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 |
return string.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(GetQuestDifficultyColor((l > 0) and l or 99)) |
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 = string.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]], |
['pereclipse'] = [[function(u) |
local m = UnitPowerMax('player', SPELL_POWER_ECLIPSE) |
if(m == 0) then |
return 0 |
else |
return math.abs(UnitPower('player', SPELL_POWER_ECLIPSE)/m*100) |
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() |
local num = UnitPower('player', SPELL_POWER_HOLY_POWER) |
if(num > 0) then |
return num |
end |
end]], |
['chi'] = [[function() |
local num = UnitPower('player', SPELL_POWER_CHI) |
if(num > 0) then |
return num |
end |
end]], |
['shadoworbs'] = [[function() |
local num = UnitPower('player', SPELL_POWER_SHADOW_ORBS) |
if(num > 0) then |
return num |
end |
end]], |
['affix'] = [[function(u) |
local c = UnitClassification(u) |
if(c == 'minus') then |
return 'Affix' |
end |
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", |
["pereclipse"] = 'UNIT_POWER', |
['curmana'] = 'UNIT_POWER UNIT_MAXPOWER', |
['maxmana'] = 'UNIT_POWER UNIT_MAXPOWER', |
['soulshards'] = 'UNIT_POWER', |
['holypower'] = 'UNIT_POWER', |
['chi'] = 'UNIT_POWER', |
['shadoworbs'] = 'UNIT_POWER', |
} |
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:IsShown() 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) |
table.insert(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 |
table.remove(data, k) |
end |
end |
end |
end |
local tagPool = {} |
local funcPool = {} |
local tmp = {} |
local Tag = function(self, fs, tagstr) |
if(not fs or not tagstr) then return end |
if(not self.__tags) then |
self.__tags = {} |
table.insert(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 |
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 |
table.insert(args, tagFunc) |
else |
return error(('Attempted to use invalid tag %s.'):format(bracket), 3) |
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 |
else |
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 |
tagPool[tagstr] = func |
end |
fs.UpdateTag = func |
local unit = self.unit |
if((unit and unit:match'%w+target') or fs.frequentUpdates) then |
local timer |
if(type(fs.frequentUpdates) == 'number') then |
timer = fs.frequentUpdates |
else |
timer = .5 |
end |
if(not eventlessUnits[timer]) then eventlessUnits[timer] = {} end |
table.insert(eventlessUnits[timer], fs) |
createOnUpdate(timer) |
else |
RegisterEvents(fs, tagstr) |
end |
table.insert(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 |
table.remove(timers, k) |
end |
end |
end |
for k, fontstr in next, self.__tags do |
if(fontstr == fs) then |
table.remove(self.__tags, k) |
end |
end |
fs.UpdateTag = nil |
end |
oUF.Tags = { |
Methods = tags, |
Events = tagEvents, |
SharedEvents = unitlessEvents, |
} |
oUF:RegisterMetaFunction('Tag', Tag) |
oUF:RegisterMetaFunction('Untag', Untag) |
--[[ Element: Druid Mana Bar |
Handles updating and visibility of a status bar displaying the druid's mana |
while outside of caster form. |
Widget |
DruidMana - 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. This will |
always use DRUID as class. |
.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 DruidMana = CreateFrame("StatusBar", nil, self) |
DruidMana:SetSize(20, 20) |
DruidMana:SetPoint('TOP') |
DruidMana:SetPoint('LEFT') |
DruidMana:SetPoint('RIGHT') |
-- Add a background |
local Background = DruidMana:CreateTexture(nil, 'BACKGROUND') |
Background:SetAllPoints(DruidMana) |
Background:SetTexture(1, 1, 1, .5) |
-- Register it with oUF |
self.DruidMana = DruidMana |
self.DruidMana.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. |
]] |
if(select(2, UnitClass('player')) ~= 'DRUID') then return end |
local _, ns = ... |
local oUF = ns.oUF |
local function Update(self, event, unit, powertype) |
if(unit ~= 'player' or (powertype and powertype ~= 'MANA')) then return end |
local druidmana = self.DruidMana |
if(druidmana.PreUpdate) then druidmana:PreUpdate(unit) end |
-- Hide the bar if the active power type is mana. |
if(UnitPowerType('player') == SPELL_POWER_MANA) then |
return druidmana:Hide() |
else |
druidmana:Show() |
end |
local min, max = UnitPower('player', SPELL_POWER_MANA), UnitPowerMax('player', SPELL_POWER_MANA) |
druidmana:SetMinMaxValues(0, max) |
druidmana:SetValue(min) |
local r, g, b, t |
if(druidmana.colorClass) then |
t = self.colors.class['DRUID'] |
elseif(druidmana.colorSmooth) then |
r, g, b = self.ColorGradient(min, max, unpack(druidmana.smoothGradient or self.colors.smooth)) |
elseif(druidmana.colorPower) then |
t = self.colors.power['MANA'] |
end |
if(t) then |
r, g, b = t[1], t[2], t[3] |
end |
if(b) then |
druidmana:SetStatusBarColor(r, g, b) |
local bg = druidmana.bg |
if(bg) then |
local mu = bg.multiplier or 1 |
bg:SetVertexColor(r * mu, g * mu, b * mu) |
end |
end |
if(druidmana.PostUpdate) then |
return druidmana:PostUpdate(unit, min, max) |
end |
end |
local function Path(self, ...) |
return (self.DruidMana.Override or Update) (self, ...) |
end |
local function ForceUpdate(element) |
return Path(element.__owner, 'ForceUpdate', element.__owner.unit) |
end |
local OnDruidManaUpdate |
do |
local UnitPower = UnitPower |
OnDruidManaUpdate = function(self) |
local unit = self.__owner.unit |
local mana = UnitPower(unit, SPELL_POWER_MANA) |
if(mana ~= self.min) then |
self.min = mana |
return Path(self.__owner, 'OnDruidManaUpdate', unit) |
end |
end |
end |
local Enable = function(self, unit) |
local druidmana = self.DruidMana |
if(druidmana and unit == 'player') then |
druidmana.__owner = self |
druidmana.ForceUpdate = ForceUpdate |
if(druidmana.frequentUpdates) then |
druidmana:SetScript('OnUpdate', OnDruidManaUpdate) |
else |
self:RegisterEvent('UNIT_POWER', Path) |
end |
self:RegisterEvent('UNIT_DISPLAYPOWER', Path) |
self:RegisterEvent('UNIT_MAXPOWER', Path) |
if(druidmana:IsObjectType'StatusBar' and not druidmana:GetStatusBarTexture()) then |
druidmana:SetStatusBarTexture[[Interface\TargetingFrame\UI-StatusBar]] |
end |
return true |
end |
end |
local Disable = function(self) |
local druidmana = self.DruidMana |
if(druidmana) then |
if(druidmana:GetScript'OnUpdate') then |
druidmana:SetScript("OnUpdate", nil) |
else |
self:UnregisterEvent('UNIT_POWER', Path) |
end |
self:UnregisterEvent('UNIT_DISPLAYPOWER', Path) |
self:UnregisterEvent('UNIT_MAXPOWER', Path) |
end |
end |
oUF:AddElement('DruidMana', Path, Enable, Disable) |
--[[ 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:SetHeight(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 |
oUF.colors.health = {49/255, 207/255, 37/255} |
local Update = function(self, event, unit) |
if(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 |
local r, g, b, t |
if(health.colorTapping and not UnitPlayerControlled(unit) and |
UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) and not |
UnitIsTappedByAllThreatList(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 |
local Enable = function(self, unit) |
local health = self.Health |
if(health) then |
health.__owner = self |
health.ForceUpdate = ForceUpdate |
if(health.frequentUpdates) then |
self:RegisterEvent('UNIT_HEALTH_FREQUENT', Path) |
else |
self:RegisterEvent('UNIT_HEALTH', Path) |
end |
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) |
--[[ 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) |
--[[ 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) |
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) |
--[[ 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) then return end |
local threat = self.Threat |
if(threat.PreUpdate) then threat:PreUpdate(unit) end |
unit = unit or self.unit |
local status = UnitThreatSituation(unit) |
local r, g, b |
if(status and status > 0) then |
r, g, b = GetThreatStatusColor(status) |
threat:SetVertexColor(r, g, b) |
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) |
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) |
end |
end |
oUF:AddElement('Threat', Path, Enable, Disable) |
## Interface: 50400 |
## Title: oUF |
## Author: Haste |
## Version: 1.6.6 |
## OptionalDeps: Clique |
## X-eMail: troeks@gmail.com |
## X-oUF: oUF |
## Notes: Unit frame framework. Does nothing by itself. |
## Notes-ruRU: ÐаÑÐºÐ°Ñ Ð´Ð»Ñ Ð¼Ð¾Ð´Ð¸ÑикаÑии ÑÑеймов игÑоков. Сам по Ñебе не Ð´ÐµÐ»Ð°ÐµÑ Ð½Ð¸Ñего. |
oUF.xml |
#!/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 : |
#!/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 |
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, 4 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, 4 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 |
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 |
local function GetY(r, g, b) |
return 0.3 * r + 0.59 * g + 0.11 * 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 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 |
end |
local m = luma - GetY(r, g, b) |
return r + m, g + m, b + m |
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 |
local parent, ns = ... |
-- It's named Private for a reason! |
ns.oUF.Private = nil |
Copyright (c) 2006-2012 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. |
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 |
local parent, ns = ... |
ns.oUF = {} |
ns.oUF.Private = {} |
local lib = LibStub:NewLibrary("LibCooldown", 1.0) |
if not lib then return end |
lib.startcalls = {} |
lib.stopcalls = {} |
function lib:RegisterCallback(event, func) |
assert(type(event)=="string" and type(func)=="function", "Usage: lib:RegisterCallback(event{string}, func{function})") |
if event=="start" then |
tinsert(lib.startcalls, func) |
elseif event=="stop" then |
tinsert(lib.stopcalls, func) |
else |
error("Argument 1 must be a string containing \"start\" or \"stop\"") |
end |
end |
local addon = CreateFrame("Frame") |
local band = bit.band |
local mine = COMBATLOG_OBJECT_AFFILIATION_MINE |
local spells = {} |
local items = {} |
local watched = {} |
local nextupdate, lastupdate = 0, 0 |
local function stop(id, class) |
watched[id] = nil |
for _, func in next, lib.stopcalls do |
func(id, class) |
end |
end |
local function update() |
for id, tab in next, watched do |
local duration = watched[id].dur - lastupdate |
if duration < 0 then |
stop(id, watched[id].class) |
else |
watched[id].dur = duration |
if nextupdate <= 0 or duration < nextupdate then |
nextupdate = duration |
end |
end |
end |
lastupdate = 0 |
if nextupdate < 0 then addon:Hide() end |
end |
local function start(id, starttime, duration, class) |
update() |
watched[id] = { |
["start"] = starttime, |
["dur"] = duration, |
["class"] = class, |
} |
addon:Show() |
for _, func in next, lib.startcalls do |
func(id, duration, class) |
end |
update() |
end |
local numTabs, totalspellnum |
local function parsespellbook(spellbook) |
i = 1 |
while true do |
skilltype, id = GetSpellBookItemInfo(i, spellbook) |
name = GetSpellBookItemName(i, spellbook) |
if name and skilltype == "SPELL" and spellbook == BOOKTYPE_SPELL and not IsPassiveSpell(i, spellbook) then |
spells[id] = true |
end |
i = i + 1 |
if i >= totalspellnum then i = 1 break end |
if (id == 88625 or id == 88625 or id == 88625) and (skilltype == "SPELL" and spellbook == BOOKTYPE_SPELL) then |
spells[88625] = true |
spells[88684] = true |
spells[88685] = true |
end |
end |
end |
-- events -- |
function addon:LEARNED_SPELL_IN_TAB() |
numTabs = GetNumSpellTabs() |
totalspellnum = 0 |
for i=1,numTabs do |
local numSpells = select(4, GetSpellTabInfo(i)) |
totalspellnum = totalspellnum + numSpells |
end |
parsespellbook(BOOKTYPE_SPELL) |
end |
function addon:SPELL_UPDATE_COOLDOWN() |
now = GetTime() |
for id in next, spells do |
local starttime, duration, enabled = GetSpellCooldown(id) |
if starttime == nil then |
watched[id] = nil |
elseif starttime == 0 and watched[id] then |
stop(id, "spell") |
elseif starttime ~= 0 then |
local timeleft = starttime + duration - now |
if enabled == 1 and timeleft > 1.51 then |
if not watched[id] or watched[id].start ~= starttime then |
start(id, starttime, timeleft, "spell") |
end |
elseif enabled == 1 and watched[id] and timeleft <= 0 then |
stop(id, "spell") |
end |
end |
end |
end |
function addon:BAG_UPDATE_COOLDOWN() |
for id in next, items do |
local starttime, duration, enabled = GetItemCooldown(id) |
if enabled == 1 and duration > 10 then |
start(id, starttime, duration, "item") |
elseif enabled == 1 and watched[id] and duration <= 0 then |
stop(id, "item") |
end |
end |
end |
function addon:PLAYER_ENTERING_WORLD() |
addon:LEARNED_SPELL_IN_TAB() |
addon:BAG_UPDATE_COOLDOWN() |
addon:SPELL_UPDATE_COOLDOWN() |
end |
hooksecurefunc("UseInventoryItem", function(slot) |
local link = GetInventoryItemLink("player", slot) or "" |
local id = string.match(link, ":(%w+).*|h%[(.+)%]|h") |
if id and not items[id] then |
items[id] = true |
end |
end) |
hooksecurefunc("UseContainerItem", function(bag, slot) |
local link = GetContainerItemLink(bag, slot) or "" |
local id = string.match(link, ":(%w+).*|h%[(.+)%]|h") |
if id and not items[id] then |
items[id] = true |
end |
end) |
for slot=1, 120 do |
local action, id = GetActionInfo(slot) |
if action == "item" then |
items[id] = true |
end |
end |
function addon:ACTION_BAR_SLOT_CHANGED(slot) |
local action, id = GetActionInfo(slot) |
if action == "item" then |
items[id] = true |
end |
end |
local function onupdate(self, elapsed) |
nextupdate = nextupdate - elapsed |
lastupdate = lastupdate + elapsed |
if nextupdate > 0 then return end |
update(self) |
end |
addon:Hide() |
addon:SetScript("OnUpdate", onupdate) |
addon:SetScript("OnEvent", function(self, event, ...) self[event](self, ...) end) |
addon:RegisterEvent("LEARNED_SPELL_IN_TAB") |
addon:RegisterEvent("SPELL_UPDATE_COOLDOWN") |
addon:RegisterEvent("BAG_UPDATE_COOLDOWN") |
addon:RegisterEvent("PLAYER_ENTERING_WORLD") |
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info |
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke |
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! |
local LibStub = _G[LIBSTUB_MAJOR] |
if not LibStub or LibStub.minor < LIBSTUB_MINOR then |
LibStub = LibStub or {libs = {}, minors = {} } |
_G[LIBSTUB_MAJOR] = LibStub |
LibStub.minor = LIBSTUB_MINOR |
function LibStub:NewLibrary(major, minor) |
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") |
minor = assert(tonumber(string.match(minor, "%d+")), "Minor version must either be a number or contain a number.") |
local oldminor = self.minors[major] |
if oldminor and oldminor >= minor then return nil end |
self.minors[major], self.libs[major] = minor, self.libs[major] or {} |
return self.libs[major], oldminor |
end |
function LibStub:GetLibrary(major, silent) |
if not self.libs[major] and not silent then |
error(("Cannot find a library instance of %q."):format(tostring(major)), 2) |
end |
return self.libs[major], self.minors[major] |
end |
function LibStub:IterateLibraries() return pairs(self.libs) end |
setmetatable(LibStub, { __call = LibStub.GetLibrary }) |
end |
<Ui xmlns="http://www.blizzard.com/wow/ui/"> |
<Script file="Config\variables.lua"/> |
<Script file="Config\config.lua"/> |
<Script file="Config\configui.lua"/> |
<Script file="Core\Log.lua"/> |
<Script file="Core\Move.lua"/> |
<Script file="Libs\LibStub.lua"/> |
<Script file="Libs\LibCooldown.lua"/> |
<Script file="Core\Func.lua"/> |
<Script file="Core\Scripts.lua"/> |
<Script file="Core\Fonts.lua"/> |
<Script file="Core\Layout.lua"/> |
<Script file="Core\Tweaks.lua"/> |
<Script file="Core\TimeTracker.lua"/> |
<Script file="Core\Mirror.lua"/> |
<Script file="Modules\General\AddonManager.lua"/> |
<Script file="Modules\General\Store.lua"/> |
<Script file="Modules\Minimap\sMinimap.lua"/> |
<Script file="Modules\General\WatchFrame.lua"/> |
<Script file="Modules\General\Interrupts.lua"/> |
<Script file="Modules\Automation\AchievementSS.lua"/> |
<Script file="Modules\Automation\AutoDE.lua"/> |
<Script file="Modules\Automation\AutoGreed.lua"/> |
<Script file="Modules\Automation\LogCombat.lua"/> |
</Ui> |
local LSM = LibStub("LibSharedMedia-3.0") |
-------------------------------------------------------------- |
-- Load Shared Media |
-------------------------------------------------------------- |
-- Fonts |
-------------------------------------------------------------- |
Soop["media"].font = LSM:Fetch("font", Soop["media"].font) |
-- Minimap Media |
Soop["minimap"].border = LSM:Fetch("border", Soop["minimap"].border) |
-- Skins |
-------------------------------------------------------------- |
-- -- Chat Media |
-- C["chat"].border = LSM:Fetch("border", C["chat"].border) |
-- C["chat"].background = LSM:Fetch("background", C["chat"].background) |
-- C["chat"].editboxborder = LSM:Fetch("border", C["chat"].editboxborder) |
-- C["chat"].editboxbackground = LSM:Fetch("background", C["chat"].editboxbackground) |
-- C["chat"].sound = LSM:Fetch("sound", C["chat"].sound) |
-- Datatext Media |
-- C["datatext"].border = LSM:Fetch("border", C["datatext"].border) |
-- C["datatext"].background = LSM:Fetch("background", C["datatext"].background) |
local LSM = LibStub("LibSharedMedia-3.0") |
if LSM == nil then return end |
-------------------------------------------------------------- |
-- Borders |
-------------------------------------------------------------- |
LSM:Register("background", "Black", [[Interface\Addons\SoopUI\Media\Textures\BLACK8X8.blp]]) |
LSM:Register("border", "Fer07", [[Interface\Addons\SoopUI\Media\Border\Fer07.tga]]) |
LSM:Register("border9", "Fer09", [[Interface\Addons\SoopUI\Media\Border\Fer09.tga]]) |
LSM:Register("border2", "Fer02", [[Interface\Addons\SoopUI\Media\Border\Fer02.tga]]) |
LSM:Register("border3", "Fer03", [[Interface\Addons\SoopUI\Media\Border\Fer03.tga]]) |
LSM:Register("border7", "Fer07", [[Interface\Addons\SoopUI\Media\Border\Fer07.tga]]) |
-------------------------------------------------------------- |
-- Font |
-------------------------------------------------------------- |
LSM:Register("font", "Adventure", [[Interface\Addons\SoopUI\Media\Fonts\Adventure.ttf]]) |
LSM:Register("font", "Bazooka", [[Interface\Addons\SoopUI\Media\Fonts\Bazooka.ttf]]) |
LSM:Register("font", "BigNoodleTitling", [[Interface\Addons\SoopUI\Media\Fonts\BigNoodleTitling.ttf]]) |
LSM:Register("font", "Expressway", [[Interface\Addons\SoopUI\Media\Fonts\Expressway.ttf]]) |
LSM:Register("font", "Enigmatic", [[Interface\Addons\SoopUI\Media\Fonts\Enigma__2.ttf]]) |
LSM:Register("font", "Vera Serif", [[Interface\Addons\SoopUI\Media\Fonts\VeraSe.ttf]]) |
LSM:Register("font", "Yellowjacket", [[Interface\Addons\SoopUI\Media\Fonts\YELLOWJACKET.ttf]]) |
LSM:Register("font", "DorisPP", [[Interface\Addons\SoopUI\Media\Fonts\DORISPP.ttf]]) |
LSM:Register("font", "Fitzgerald", [[Interface\Addons\SoopUI\Media\Fonts\Fitzgerald.ttf]]) |
LSM:Register("font", "Gentium", [[Interface\Addons\SoopUI\Media\Fonts\Gentium.ttf]]) |
LSM:Register("font", "Hooked Up", [[Interface\Addons\SoopUI\Media\Fonts\HookedUp.ttf]]) |
LSM:Register("font", "Liberation Sans", [[Interface\Addons\SoopUI\Media\Fonts\LiberationSans.ttf]]) |
LSM:Register("font", "semplice", [[Interface\Addons\SoopUI\Media\Fonts\semplice.ttf.ttf]]) |
LSM:Register("font", "Covington", [[Interface\Addons\SoopUI\Media\Fonts\SFCovington.ttf]]) |
LSM:Register("font", "Wonder Comic", [[Interface\Addons\SoopUI\Media\Fonts\SFWonderComic.ttf]]) |
LSM:Register("font", "swf!t", [[Interface\Addons\SoopUI\Media\Fonts\swfit.ttf]]) |
-------------------------------------------------------------- |
-- Sound |
-------------------------------------------------------------- |
LSM:Register("sound", "Warning", [[Interface\Addons\SoopUI\Media\Sound\Warning.mp3]]) |
LSM:Register("sound", "Whisper", [[Interface\Addons\SoopUI\Media\Sound\Whisper.mp3]]) |
## Interface: 50400 |
## Title: SoopUI |
## Notes: SoopUI |
## Version: 3.0.0 |
## Credits to: Phanx, Qulight, Monolit, Shestak, Hanomi, Alza, AlleyKat, Fernir, affli, Nightcracker, Allez, haste, Zork, Tekkub, Tuller, Freebaser, Haleth, drakull, P3lim, Dawn, Tukz. |
## Author: Soopie |
## Dependencies: Soop_ConfigureUI, Reflux |
## SavedVariables: SoopData, sLoaderN |
## SavedVariablesPerCharacter: SoopDataPerChar, UISavedPositions |
## OptionalDeps: Dominos, Skada, VuhDo |
SoopUI.xml |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- SoopUI Configuration |
---------------------------------------------------------------------------- |
Soop["media"] = { |
["font"] = "Interface\\Addons\\SoopUI\\Media\\Fonts\\Expressway.ttf", -- The font SoopUI uses |
["fontsize"] = 12, -- Font size |
["texture"] = "Interface\\AddOns\\SoopUI\\Media\\statusbar4", -- Texture |
["blank"] = "Interface\\Buttons\\WHITE8x8", -- Blank texture |
} |
Soop["general"] = { |
["AutoScale"] = false, |
["UiScale"] = 0.64, -- Values between 0.64 and 1 (uiScale must be disabled) |
["MultisampleProtect"] = false, -- 1x anti-aliasing |
["addonmanager"] = true, -- Use built in addon manager? cmd /aload |
["centerpanel"] = true, |
["BlizzardsErrorFrameHiding"] = true, -- Hide blizzard errors |
} |
Soop["minimap"] = { |
["enable"] = true, -- Enable/Disable minimap |
["size"] = 100, -- Size of minimap |
["hideincombat"] = true, |
} |
Soop["automation"] = { |
["AutoRepair"] = true, -- Repair automatically |
["AutoGreed"] = true, -- Auto greed on greens |
["autoinvite"] = true, -- Auto accept invites from friends |
["AutoDisenchant"] = true, -- Auto disenchant green items |
["AutoScreen"] = true, -- Automatically take a screenshot upon achievement |
["LogCombat"] = true, -- Automatically log raids |
} |
Soop["help"] = { |
["one"] = true, |
["two"] = true, |
} |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- SoopUI Variables |
---------------------------------------------------------------------------- |
Soop = { } |
_, myclass = UnitClass("player") |
local myPlayerName = UnitName("player") |
---------------------------------------------------------------------------- |
resolution = GetCurrentResolution() -- Get the users resolution for scaling |
getscreenresolution = select(resolution, GetScreenResolutions()) |
---------------------------------------------------------------------------- |
version = GetAddOnMetadata("SoopUI", "Version") |
dummy = function() return end -- Dummy frame |
---------------------------------------------------------------------------- |
client = GetLocale() -- For those outside the US 'Murica |
incombat = UnitAffectingCombat("player") |
patch = GetBuildInfo() |
level = UnitLevel("player") |
local myPlayerRealm = GetRealmName() |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- SoopUI Configuration GUI |
---------------------------------------------------------------------------- |
local myPlayerRealm = GetRealmName() |
local myPlayerName = UnitName("player") |
if not IsAddOnLoaded("Soop_ConfigureUI") then return end |
if not SoopConfigureAll then SoopConfigureAll = {} end |
if (SoopConfigureAll[myPlayerRealm] == nil) then SoopConfigureAll[myPlayerRealm] = {} end |
if (SoopConfigureAll[myPlayerRealm][myPlayerName] == nil) then SoopConfigureAll[myPlayerRealm][myPlayerName] = false end |
if SoopConfigureAll[myPlayerRealm][myPlayerName] == true and not SoopConfigure then return end |
if SoopConfigureAll[myPlayerRealm][myPlayerName] == false and not SoopConfigureSettings then return end |
if SoopConfigureAll[myPlayerRealm][myPlayerName] == true then |
for group,options in pairs(SoopConfigure) do |
if Soop[group] then |
local count = 0 |
for option,value in pairs(options) do |
if Soop[group][option] ~= nil then |
if Soop[group][option] == value then |
SoopConfigure[group][option] = nil |
else |
count = count+1 |
Soop[group][option] = value |
end |
end |
end |
if count == 0 then SoopConfigure[group] = nil end |
else |
SoopConfigure[group] = nil |
end |
end |
else |
for group,options in pairs(SoopConfigureSettings) do |
if Soop[group] then |
local count = 0 |
for option,value in pairs(options) do |
if Soop[group][option] ~= nil then |
if Soop[group][option] == value then |
SoopConfigureSettings[group][option] = nil |
else |
count = count+1 |
Soop[group][option] = value |
end |
end |
end |
if count == 0 then SoopConfigureSettings[group] = nil end |
else |
SoopConfigureSettings[group] = nil |
end |
end |
end |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- SoopUI Frame Layouts |
---------------------------------------------------------------------------- |
-- Datatext backgrounds |
---------------------------------------------------------------------------- |
if Soop["general"].centerpanel then |
local BottomPanel = CreateFrame("Frame", "BottomPanel", UIParent) |
CreatePanel(BottomPanel, 275, 25, "BOTTOM", 0, -5) |
CreateShadow(BottomPanel) |
BottomPanel:SetFrameLevel(0) |
BottomPanel:SetAlpha(0.75) |
BottomPanel: |
SetBackdrop({edgeFile = "Interface\\Addons\\SoopUI\\Media\\Textures\\fer9", |
edgeSize = 8, insets = { left = 2, right = 2, top = 2, bottom = 2 } |
}) |
BottomPanel:RegisterEvent("PLAYER_REGEN_ENABLED") |
BottomPanel:RegisterEvent("PLAYER_REGEN_DISABLED") |
BottomPanel:HookScript("OnEvent", function(self, event) |
if event == "PLAYER_REGEN_ENABLED" then |
BottomPanel:Show() |
elseif event == "PLAYER_REGEN_DISABLED" then |
BottomPanel:Hide() |
end |
end) |
end |
if Soop["general"].centerpanel then |
local LeftInfoPanel = CreateFrame("Frame", "DataLeftPanel", UIParent) |
CreatePanel(LeftInfoPanel, 350, 25, "BOTTOMLEFT", 0, -5) |
CreateShadow(LeftInfoPanel) |
LeftInfoPanel:SetFrameLevel(0) |
LeftInfoPanel: |
SetBackdrop({edgeFile = "Interface\\Addons\\SoopUI\\Media\\Textures\\fer9", |
edgeSize = 8, insets = { left = 2, right = 2, top = 2, bottom = 2 } |
}) |
LeftInfoPanel:RegisterEvent("PLAYER_REGEN_ENABLED") |
LeftInfoPanel:RegisterEvent("PLAYER_REGEN_DISABLED") |
LeftInfoPanel:HookScript("OnEvent", function(self, event) |
if event == "PLAYER_REGEN_ENABLED" then |
LeftInfoPanel:Show() |
elseif event == "PLAYER_REGEN_DISABLED" then |
LeftInfoPanel:Hide() |
end |
end) |
end |
---------------------------------------------------------------------------- |
-- Minimap |
---------------------------------------------------------------------------- |
Anchorminimaplol = CreateFrame("Frame","Move_minimaplol",UIParent) |
Anchorminimaplol:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 3, -3) |
CreateAnchor(Anchorminimaplol, "Move minimap", Soop["minimap"].size+2, Soop["minimap"].size+2) |
local minimaplol = CreateFrame("Frame", "minimaplol", UIParent) |
CreatePanel(minimaplol, Soop["minimap"].size+2, Soop["minimap"].size+2, "BOTTOMRIGHT", Anchorminimaplol) |
CreateShadow(minimaplol) |
minimaplol:SetFrameLevel(2) |
minimaplol:RegisterEvent("PLAYER_REGEN_ENABLED") |
minimaplol:RegisterEvent("PLAYER_REGEN_DISABLED") |
minimaplol:HookScript("OnEvent", function(self, event) |
if event == "PLAYER_REGEN_ENABLED" then |
minimaplol:Show() |
elseif event == "PLAYER_REGEN_DISABLED" then |
minimaplol:Hide() |
end |
end) |
-- Later Version |
-- Anchorchatbgdummy = CreateFrame("Frame","Move_chatbgdummy",UIParent) |
-- Anchorchatbgdummy:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", 3, 3) |
-- CreateAnchor(Anchorchatbgdummy, "Move Chat", 440, 172) |
-- local ChatPanel = CreateFrame("Frame", "ChatBackground", UIParent) |
-- CreatePanel(ChatPanel, 440, 172, "BOTTOMLEFT", Anchorchatbgdummy) |
-- CreateShadow(ChatPanel) |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- SoopUI Tweaks |
---------------------------------------------------------------------------- |
-- Quest level(yQuestLevel by yleaf) |
---------------------------------------------------------------------------- |
local function update() |
local buttons = QuestLogScrollFrame.buttons |
local numButtons = #buttons |
local scrollOffset = HybridScrollFrame_GetOffset(QuestLogScrollFrame) |
local numEntries, numQuests = GetNumQuestLogEntries() |
for i = 1, numButtons do |
local questIndex = i + scrollOffset |
local questLogTitle = buttons[i] |
if questIndex <= numEntries then |
local title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily = GetQuestLogTitle(questIndex) |
if not isHeader then |
questLogTitle:SetText("[" .. level .. "] " .. title) |
QuestLogTitleButton_Resize(questLogTitle) |
end |
end |
end |
end |
hooksecurefunc("QuestLog_Update", update) |
QuestLogScrollFrameScrollBar:HookScript("OnValueChanged", update) |
-- Clear UIErrors frame(ncError by Nightcracker) |
---------------------------------------------------------------------------- |
if Soop["general"].BlizzardsErrorFrameHiding then |
local f, o, ncErrorDB = CreateFrame("Frame"), "No error ye", { |
["Inventory is full"] = true, |
} |
f:SetScript("OnEvent", function(self, event, error) |
if ncErrorDB[error] then |
UIErrorsFrame:AddMessage(error) |
else |
o = error |
end |
end) |
SLASH_NCERROR1 = "/error" |
function SlashCmdLisNCERROR() print(o) end |
UIErrorsFrame:UnregisterEvent("UI_ERROR_MESSAGE") |
f:RegisterEvent("UI_ERROR_MESSAGE") |
end |
-- Hide Blizzard raid frames |
---------------------------------------------------------------------------- |
local irp = 0; |
function HideBlizzardRaidFrameOnEvent(event) |
if event == "RAID_ROSTER_UPDATE" then |
if ((GetNumRaidMembers() > 0) and (irp == 0) and (CompactRaidFrameContainer:IsShown())) then |
CompactRaidFrameManagerDisplayFrameHiddenModeToggle:Click(); |
irp = 1; |
elseif (GetNumRaidMembers() == 0) then |
irp = 0; |
end |
end |
if event == "PARTY_MEMBERS_CHANGED" then |
if ((GetNumPartyMembers() > 0) and (irp == 0) and (CompactRaidFrameContainer:IsShown())) then |
CompactRaidFrameManagerDisplayFrameHiddenModeToggle:Click(); |
irp = 1; |
elseif (GetNumPartyMembers() == 0) then |
irp = 0; |
end |
end |
end |
local HideBlizzardRaidFrameHiddenFrame = CreateFrame("FRAME", "HideBlizzardRaidFrameHiddenFrame", UIParent); |
HideBlizzardRaidFrameHiddenFrame:RegisterEvent("RAID_ROSTER_UPDATE"); |
HideBlizzardRaidFrameHiddenFrame:RegisterEvent("PARTY_MEMBERS_CHANGED"); |
HideBlizzardRaidFrameHiddenFrame:SetScript("OnEvent", function(self, event, arg1, ...) |
HideBlizzardRaidFrameOnEvent(event); |
end); |
HideBlizzardRaidFrameHiddenFrame:Hide(); |
-- Hide boss frames |
---------------------------------------------------------------------------- |
function hideBossFrames() |
for i = 1, 4 do |
local frame = _G["Boss"..i.."TargetFrame"] |
frame:UnregisterAllEvents() |
frame:Hide() |
frame.Show = function () end |
end |
end |
-- Call the hide function |
hideBossFrames() |
-- Repair |
---------------------------------------------------------------------------- |
local f = CreateFrame("Frame") |
f:SetScript("OnEvent", function() |
local c = 0 |
for b=0,4 do |
for s=1,GetContainerNumSlots(b) do |
local l = GetContainerItemLink(b, s) |
if l then |
local p = select(11, GetItemInfo(l))*select(2, GetContainerItemInfo(b, s)) |
if select(3, GetItemInfo(l))==0 then |
UseContainerItem(b, s) |
PickupMerchantItem() |
c = c+p |
end |
end |
end |
end |
if c>0 then |
local g, s, c = math.floor(c/10000) or 0, math.floor((c%10000)/100) or 0, c%100 |
DEFAULT_CHAT_FRAME:AddMessage("Your vendor trash has been sold and you earned".." |cffffffff"..g.."|cffffd700g|r".." |cffffffff"..s.."|cffc7c7cfs|r".." |cffffffff"..c.."|cffeda55fc|r"..".",255,255,0) |
end |
if Soop["general"].AutoRepair then |
cost, possible = GetRepairAllCost() |
if cost>0 then |
if possible then |
RepairAllItems() |
local c = cost%100 |
local s = math.floor((cost%10000)/100) |
local g = math.floor(cost/10000) |
DEFAULT_CHAT_FRAME:AddMessage("Your items have been repaired for".." |cffffffff"..g.."|cffffd700g|r".." |cffffffff"..s.."|cffc7c7cfs|r".." |cffffffff"..c.."|cffeda55fc|r"..".",255,255,0) |
else |
DEFAULT_CHAT_FRAME:AddMessage("You don't have enough money for repair!",255,0,0) |
end |
end |
end |
end) |
f:RegisterEvent("MERCHANT_SHOW") |
local savedMerchantItemButton_OnModifiedClick = MerchantItemButton_OnModifiedClick |
function MerchantItemButton_OnModifiedClick(self, ...) |
if ( IsAltKeyDown() ) then |
local maxStack = select(8, GetItemInfo(GetMerchantItemLink(self:GetID()))) |
local name, texture, price, quantity, numAvailable, isUsable, extendedCost = GetMerchantItemInfo(self:GetID()) |
if ( maxStack and maxStack > 1 ) then |
BuyMerchantItem(self:GetID(), floor(maxStack / quantity)) |
end |
end |
savedMerchantItemButton_OnModifiedClick(self, ...) |
end |
-- Raid Boss Emotes |
---------------------------------------------------------------------------- |
RaidBossEmoteFrame:ClearAllPoints() |
RaidBossEmoteFrame:SetPoint("TOP", UIParent, "TOP", 0, -200) |
RaidBossEmoteFrame:SetScale(.9) |
RaidWarningFrame:ClearAllPoints() |
RaidWarningFrame:SetPoint("TOP", UIParent, "TOP", 0, -260) |
RaidWarningFrame:SetScale(.8) |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- Fires immediately upon player login |
---------------------------------------------------------------------------- |
-- CVars |
---------------------------------------------------------------------------- |
local csf = CreateFrame("Frame") |
csf:SetScript("OnEvent", function() |
SetCVar("cameraDistanceMax", 50) |
SetCVar("cameraDistanceMaxFactor", 3.4) |
SetCVar("consolidateBuffs", 0) |
SetCVar("ShowClassColorInNameplate", 1) |
SetCVar("consolidateBuffs",0) |
SetCVar("buffDurations",1) |
end) |
csf:RegisterEvent("PLAYER_LOGIN") |
-- Launch |
---------------------------------------------------------------------------- |
local function positionsetup() |
SoopDataPerChar = {} |
end |
local SoopOnLogon = CreateFrame("Frame") |
SoopOnLogon:RegisterEvent("PLAYER_ENTERING_WORLD") |
SoopOnLogon:SetScript("OnEvent", function(self, event) |
self:UnregisterEvent("PLAYER_ENTERING_WORLD") |
if (SoopData == nil) then SoopData = {} end |
if (SoopDataPerChar == nil) then SoopDataPerChar = {} end |
SetCVar("useUiScale", 1) |
if Soop["general"].MultisampleProtect == true then |
SetMultisampleFormat(1) |
end |
if Soop["general"].UiScale > 1 then Soop["general"].UiScale = 1 end |
if Soop["general"].UiScale < 0.64 then Soop["general"].UiScale = 0.64 end |
SetCVar("uiScale", Soop["general"].UiScale) |
print("Welcome to |cFF00A2FFSoopUI|r 3.0.0 Beta 1") |
print("|cFF00A2FFSoopUI.TopShelfSargeras.com|r - for help;") |
print("|cFF00A2FF/config |r - SoopUI settings;") |
print("|cFF00A2FF/ui |r - Move things around.") |
print("|cFF00A2FF/ui reset |r - Reset default UI positions.") |
end) |
local frame = CreateFrame("FRAME"); |
frame:RegisterEvent("VARIABLES_LOADED"); |
-- BEGIN USER OPTIONS -- |
-- InterfaceName = Name to describe your UI |
-- ProfileName = Addon profile name to use with /reflux switch |
local InterfaceName = "SoopUI 3.0" |
local ProfileName = "SoopUI" |
local UseClassProfiles = false -- Use specific profile names for different classes |
local LocalizedMessages = { |
["enUS"] = { |
[1] = "New character detected! Do you wish to load the settings for %s?", |
[2] = "Yes", |
[3] = "No", |
}, |
} |
local CID, CE, HasAdded = "", false, false |
local function AddChar() |
if (CID ~= "") and not HasAdded then |
tinsert(sLoaderN, CID) |
HasAdded = true |
end |
end |
local function CharAnswered(ans) |
AddChar() |
if ans then |
local _, class = UnitClass("player") |
local NewProfile = ProfileName |
local RefluxArg = string.format("%s %s", "switch", NewProfile) |
SlashCmdList.REFLUX(RefluxArg) -- This will cause a UI reload |
end |
end |
local function AskNewChar() |
local Locale = GetLocale() or "enUS" |
local MsgTexts = LocalizedMessages[Locale] or LocalizedMessages["enUS"] |
StaticPopupDialogs["PUDASKNEWCHAR"] = { |
text = MsgTexts[1], |
button1 = MsgTexts[2], |
button2 = MsgTexts[3], |
OnAccept = function() |
CharAnswered(true) |
end, |
OnCancel = function() |
CharAnswered(false) |
end, |
timeout = 0, |
whileDead = true, |
hideOnEscape = false, |
notClosableByLogout = true, |
} |
StaticPopup_Show ("PUDASKNEWCHAR", InterfaceName); |
end |
local function CheckNewChar() |
CID = string.format("%s - %s", GetRealmName(), UnitName("player")) |
CE = false |
if (sLoaderN == nil) then sLoaderN = { }; end |
for i,v in pairs(sLoaderN) do |
if (v == CID) then CE = true; end |
end |
if not CE then AskNewChar(); end |
end |
local function eventHandler(self, event, ...) |
if (event == "VARIABLES_LOADED") then |
CheckNewChar() |
end |
end |
frame:SetScript("OnEvent", eventHandler); |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- Unlock and Move Frames |
---------------------------------------------------------------------------- |
local t_unlock = false |
AnchorFrames = {} |
UISavedPositions = {} |
local SetPosition = function(anch) |
local ap, _, rp, x, y = anch:GetPoint() |
UISavedPositions[anch:GetName()] = {ap, "UIParent", rp, x, y} |
end |
local OnDragStart = function(self) |
self:StartMoving() |
end |
local OnDragStop = function(self) |
self:StopMovingOrSizing() |
SetPosition(self) |
end |
local shadows = { |
bgFile = "Interface\\AddOns\\SoopUI\\Media\\Textures\\statusbar4", |
edgeFile = "Interface\\AddOns\\SoopUI\\Media\\Textures\\glowTex", |
edgeSize = 2, |
insets = { left = 2, right = 2, top = 2, bottom = 2 } |
} |
function CreateShadowmove(f) -- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(29) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -2, 2) |
shadow:SetPoint("BOTTOMRIGHT", 2, -2) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor( .05,.05,.05, 1) |
shadow:SetBackdropBorderColor(.23,.45,.13, 0) |
f.shadow = shadow |
return shadow |
end |
function framemove(f) |
f:SetBackdrop({ |
bgFile = [=[Interface\ChatFrame\ChatFrameBackground]=], |
edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = 1, |
insets = {left = -1, right = -1, top = -1, bottom = -1} |
}) |
f:SetBackdropColor(.05,.05,.05,0.5) |
f:SetBackdropBorderColor(.23,.45,.13, 1) |
end |
function CreateAnchor(f, text, width, height) |
f:SetScale(1) |
f:SetFrameStrata("TOOLTIP") |
f:SetScript("OnDragStart", OnDragStart) |
f:SetScript("OnDragStop", OnDragStop) |
f:SetWidth(width) |
f:SetHeight(height) |
local h = CreateFrame("Frame", nil) |
h:SetFrameLevel(30) |
h:SetAllPoints(f) |
f.dragtexture = h |
local v = CreateFrame("Frame", nil, h) |
v:SetPoint("TOPLEFT",0,0) |
v:SetPoint("BOTTOMRIGHT",0,0) |
framemove(v) |
f:SetMovable(true) |
f.dragtexture:SetAlpha(0) |
f:EnableMouse(nil) |
f:RegisterForDrag(nil) |
f.text = f:CreateFontString(nil, "OVERLAY") |
f.text:SetFont(Soop["media"].font, 12, "OUTLINE") |
f.text:SetJustifyH("LEFT") |
f.text:SetShadowColor(0, 0, 0) |
f.text:SetShadowOffset(1, -1) |
f.text:SetAlpha(0) |
f.text:SetPoint("CENTER") |
f.text:SetText(text) |
tinsert(AnchorFrames, f:GetName()) |
end |
function AnchorsUnlock() |
print("UI: all frames unlocked") |
for _, v in pairs(AnchorFrames) do |
f = _G[v] |
f.dragtexture:SetAlpha(1) |
f.text:SetAlpha(1) |
f:EnableMouse(true) |
f:RegisterForDrag("LeftButton") |
end |
end |
function AnchorsLock() |
print("UI: all frames locked") |
for _, v in pairs(AnchorFrames) do |
f = _G[v] |
f.dragtexture:SetAlpha(0) |
f.text:SetAlpha(0) |
f:EnableMouse(nil) |
f:SetUserPlaced(false) |
f:RegisterForDrag(nil) |
end |
end |
function AnchorsReset() |
if(UISavedPositions) then UISavedPositions = nil end |
ReloadUI() |
end |
-- Alignment Grid |
---------------------------------------------------------------------------- |
local grid |
local boxSize = 64 |
function Grid_Show() |
if not grid then |
Grid_Create() |
elseif grid.boxSize ~= boxSize then |
grid:Hide() |
Grid_Create() |
else |
grid:Show() |
end |
end |
function Grid_Hide() |
if grid then |
grid:Hide() |
end |
end |
function Grid_Create() |
grid = CreateFrame('Frame', nil, UIParent) |
grid.boxSize = boxSize |
grid:SetAllPoints(UIParent) |
local size = 2 |
local width = GetScreenWidth() |
local ratio = width / GetScreenHeight() |
local height = GetScreenHeight() * ratio |
local wStep = width / boxSize |
local hStep = height / boxSize |
for i = 0, boxSize do |
local tx = grid:CreateTexture(nil, 'BACKGROUND') |
if i == boxSize / 2 then |
tx:SetTexture(1, 0, 0, 0.5) |
else |
tx:SetTexture(0, 0, 0, 0.5) |
end |
tx:SetPoint("TOPLEFT", grid, "TOPLEFT", i*wStep - (size/2), 0) |
tx:SetPoint('BOTTOMRIGHT', grid, 'BOTTOMLEFT', i*wStep + (size/2), 0) |
end |
height = GetScreenHeight() |
do |
local tx = grid:CreateTexture(nil, 'BACKGROUND') |
tx:SetTexture(1, 0, 0, 0.5) |
tx:SetPoint("TOPLEFT", grid, "TOPLEFT", 0, -(height/2) + (size/2)) |
tx:SetPoint('BOTTOMRIGHT', grid, 'TOPRIGHT', 0, -(height/2 + size/2)) |
end |
for i = 1, math.floor((height/2)/hStep) do |
local tx = grid:CreateTexture(nil, 'BACKGROUND') |
tx:SetTexture(0, 0, 0, 0.5) |
tx:SetPoint("TOPLEFT", grid, "TOPLEFT", 0, -(height/2+i*hStep) + (size/2)) |
tx:SetPoint('BOTTOMRIGHT', grid, 'TOPRIGHT', 0, -(height/2+i*hStep + size/2)) |
tx = grid:CreateTexture(nil, 'BACKGROUND') |
tx:SetTexture(0, 0, 0, 0.5) |
tx:SetPoint("TOPLEFT", grid, "TOPLEFT", 0, -(height/2-i*hStep) + (size/2)) |
tx:SetPoint('BOTTOMRIGHT', grid, 'TOPRIGHT', 0, -(height/2-i*hStep + size/2)) |
end |
end |
-------------------------------------------------------------------------------------- |
local function SlashCmd(cmd) |
if InCombatLockdown() then print(ERR_NOT_IN_COMBAT) return end |
if (cmd:match"reset") then |
AnchorsReset() |
else |
if t_unlock == false then |
t_unlock = true |
AnchorsUnlock() |
boxSize = (math.ceil((tonumber(arg) or boxSize) / 32) * 32) |
Grid_Show() |
isAligning = true |
elseif t_unlock == true then |
t_unlock = false |
AnchorsLock() |
Grid_Hide() |
isAligning = false |
end |
end |
end |
local RestoreUI = function(self) |
if InCombatLockdown() then |
if not self.shedule then self.shedule = CreateFrame("Frame", nil, self) end |
self.shedule:RegisterEvent("PLAYER_REGEN_ENABLED") |
self.shedule:SetScript("OnEvent", function(self) |
RestoreUI(self:GetParent()) |
self:UnregisterEvent("PLAYER_REGEN_ENABLED") |
self:SetScript("OnEvent", nil) |
end) |
return |
end |
for frame_name, SetPoint in pairs(UISavedPositions) do |
if _G[frame_name] then |
_G[frame_name]:ClearAllPoints() |
_G[frame_name]:SetPoint(unpack(SetPoint)) |
end |
end |
end |
local frame = CreateFrame("Frame") |
frame:RegisterEvent("PLAYER_ENTERING_WORLD") |
frame:SetScript("OnEvent", function(self, event) |
self:UnregisterEvent(event) |
RestoreUI(self) |
end) |
SlashCmdList["ui"] = SlashCmd; |
SLASH_ui1 = "/ui"; |
-- Anchors |
---------------------------------------------------------------------------- |
AnchorWatchFrame = CreateFrame("Frame","Move_WatchFrame",UIParent) |
AnchorWatchFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 3, -210) |
CreateAnchor(AnchorWatchFrame, "Move watch frame", 250, 300) |
-- Anchorplayer = CreateFrame("Frame","Move_player",UIParent) |
-- Anchorplayer:SetPoint("TOPRIGHT", UIParent, "BOTTOM", -200, 389) |
-- CreateAnchor(Anchorplayer, "Move player", 220, 38) |
-- Anchortarget = CreateFrame("Frame","Move_target",UIParent) |
-- Anchortarget:SetPoint("TOPLEFT", UIParent, "BOTTOM", 200, 389) |
-- CreateAnchor(Anchortarget, "Move target", 220, 38) |
-- Anchorraid = CreateFrame("Frame","Move_raid",UIParent) |
-- Anchorraid:SetPoint("TOPLEFT", 150, -5) |
-- CreateAnchor(Anchorraid, "Move raid", 370, 170) |
-- Anchortot = CreateFrame("Frame","Move_tot",UIParent) |
-- Anchortot:SetPoint("TOPLEFT", UIParent, "BOTTOM", 425, 389) |
-- CreateAnchor(Anchortot, "Move tot", 100, 28) |
-- Anchorpet = CreateFrame("Frame","Move_pet",UIParent) |
-- Anchorpet:SetPoint("TOPRIGHT", UIParent, "BOTTOM", -425, 389) |
-- CreateAnchor(Anchorpet, "Move pet", 100, 28) |
-- Anchorfocus = CreateFrame("Frame","Move_focus",UIParent) |
-- Anchorfocus:SetPoint("BOTTOMLEFT", 240, 450) |
-- CreateAnchor(Anchorfocus, "Move focus", 180, 34) |
-- Anchorfocuscastbar = CreateFrame("Frame","Move_focuscastbar",UIParent) |
-- Anchorfocuscastbar:SetPoint("BOTTOMLEFT", 262, 490) |
-- CreateAnchor(Anchorfocuscastbar, "Move focuscastbar", 155, 13) |
-- Anchortank = CreateFrame("Frame","Move_tank",UIParent) |
-- Anchortank:SetPoint("BOTTOMLEFT", 250, 420) |
-- CreateAnchor(Anchortank, "Move tank", 80, 18) |
-- Anchorboss = CreateFrame("Frame","Move_boss",UIParent) |
-- Anchorboss:SetPoint("BOTTOMRIGHT", -350, 450) |
-- CreateAnchor(Anchorboss, "Move boss", 150, 200) |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- SoopUI Functions |
---------------------------------------------------------------------------- |
-- Slash Commands |
---------------------------------------------------------------------------- |
SlashCmdList["FRAME"] = function() print(GetMouseFocus():GetName()) end |
SLASH_FRAME1 = "/gn" |
SLASH_FRAME2 = "/frame" |
SlashCmdList["GETPARENT"] = function() print(GetMouseFocus():GetParent():GetName()) end |
SLASH_GETPARENT1 = "/gp" |
SLASH_GETPARENT2 = "/parent" |
SlashCmdList["RELOADUI"] = function() ReloadUI() end |
SLASH_RELOADUI1 = "/rl" |
SlashCmdList["RCSLASH"] = function() DoReadyCheck() end |
SLASH_RCSLASH1 = "/rc" |
SLASH_RCSLASH2 = "/readyc" |
SlashCmdList["CHECKROLE"] = function() InitiateRolePoll() end |
SLASH_CHECKROLE1 = '/cr' |
SlashCmdList["TICKET"] = function() ToggleHelpFrame() end |
SLASH_TICKET1 = "/ticket" |
SLASH_TICKET2 = "/gm" |
-- /Frame is used to identify frames from within the game |
---------------------------------------------------------------------------- |
SLASH_FRAME1 = "/frame" |
SlashCmdList["FRAME"] = function(arg) |
if arg ~= "" then |
arg = _G[arg] |
else |
arg = GetMouseFocus() |
end |
if arg ~= nil and arg:GetName() ~= nil then |
local SetPoint, relativeTo, relativePoint, xOfs, yOfs = arg:GetPoint() |
ChatFrame1:AddMessage("|cffCC0000----------------------------") |
ChatFrame1:AddMessage("Name: |cffFFD100"..arg:GetName()) |
if arg:GetParent() and arg:GetParent():GetName() then |
ChatFrame1:AddMessage("Parent: |cffFFD100"..arg:GetParent():GetName()) |
end |
ChatFrame1:AddMessage("Width: |cffFFD100"..format("%.2f",arg:GetWidth())) |
ChatFrame1:AddMessage("Height: |cffFFD100"..format("%.2f",arg:GetHeight())) |
ChatFrame1:AddMessage("Strata: |cffFFD100"..arg:GetFrameStrata()) |
ChatFrame1:AddMessage("Level: |cffFFD100"..arg:GetFrameLevel()) |
if xOfs then |
ChatFrame1:AddMessage("X: |cffFFD100"..format("%.2f",xOfs)) |
end |
if yOfs then |
ChatFrame1:AddMessage("Y: |cffFFD100"..format("%.2f",yOfs)) |
end |
if relativeTo and relativeTo:GetName() then |
ChatFrame1:AddMessage("SetPoint: |cffFFD100"..SetPoint.."|r anchored to "..relativeTo:GetName().."'s |cffFFD100"..relativePoint) |
end |
ChatFrame1:AddMessage("|cffCC0000----------------------------") |
elseif arg == nil then |
ChatFrame1:AddMessage("Invalid frame name") |
else |
ChatFrame1:AddMessage("Could not find frame info") |
end |
end |
-- Role Check |
---------------------------------------------------------------------------- |
CheckRole = function() |
local role = "" |
local tree = GetSpecialization() |
if tree then |
role = select(6, GetSpecializationInfo(tree)) |
end |
return role |
end |
-- Wait |
---------------------------------------------------------------------------- |
local waitTable = {} |
local waitFrame |
function Delay(delay, func, ...) |
if(type(delay)~="number" or type(func)~="function") then |
return false |
end |
if(waitFrame == nil) then |
waitFrame = CreateFrame("Frame","WaitFrame", UIParent) |
waitFrame:SetScript("onUpdate",function (self,elapse) |
local count = #waitTable |
local i = 1 |
while(i<=count) do |
local waitRecord = tremove(waitTable,i) |
local d = tremove(waitRecord,1) |
local f = tremove(waitRecord,1) |
local p = tremove(waitRecord,1) |
if(d>elapse) then |
tinsert(waitTable,i,{d-elapse,f,p}) |
i = i + 1 |
else |
count = count - 1 |
f(unpack(p)) |
end |
end |
end) |
end |
tinsert(waitTable,{delay,func,{...}}) |
return true |
end |
-- Move Achievements to a more logical position |
---------------------------------------------------------------------------- |
local AchievementAnchor = CreateFrame("Frame", "AchievementAnchor", UIParent) |
AchievementAnchor:SetWidth(DungeonCompletionAlertFrame1:GetWidth() - 36) |
AchievementAnchor:SetHeight(DungeonCompletionAlertFrame1:GetHeight() - 4) |
AchievementAnchor:SetPoint("CENTER", 0, 0) |
local POSITION, ANCHOR_POINT, YOFFSET = "BOTTOM", "TOP", -9 |
local function fixAnchors() |
local point = select(1, AchievementAnchor:GetPoint()) |
if string.find(point, "TOP") or point == "CENTER" or point == "LEFT" or point == "RIGHT" then |
POSITION = "TOP" |
ANCHOR_POINT = "BOTTOM" |
YOFFSET = 9 |
else |
POSITION = "BOTTOM" |
ANCHOR_POINT = "TOP" |
YOFFSET = -9 |
end |
AlertFrame:ClearAllPoints() |
AlertFrame:SetPoint(POSITION, AchievementAnchor, POSITION, 2, YOFFSET) |
GroupLootContainer:ClearAllPoints() |
GroupLootContainer:SetPoint(POSITION, AlertFrame, ANCHOR_POINT, -100, YOFFSET) |
end |
hooksecurefunc("AlertFrame_FixAnchors", fixAnchors) |
local function AlertFrame_SetLootAnchors(alertAnchor) |
if MissingLootFrame:IsShown() then |
MissingLootFrame:ClearAllPoints() |
MissingLootFrame:SetPoint(POSITION, alertAnchor, ANCHOR_POINT, 0, YOFFSET) |
if GroupLootContainer:IsShown() then |
GroupLootContainer:ClearAllPoints() |
GroupLootContainer:SetPoint(POSITION, MissingLootFrame, ANCHOR_POINT, 0, YOFFSET) |
end |
elseif GroupLootContainer:IsShown() then |
GroupLootContainer:ClearAllPoints() |
GroupLootContainer:SetPoint(POSITION, alertAnchor, ANCHOR_POINT, 0, YOFFSET) |
end |
end |
hooksecurefunc("AlertFrame_SetLootAnchors", AlertFrame_SetLootAnchors) |
local function AlertFrame_SetLootWonAnchors(alertAnchor) |
for i = 1, #LOOT_WON_ALERT_FRAMES do |
local frame = LOOT_WON_ALERT_FRAMES[i] |
if frame:IsShown() then |
frame:ClearAllPoints() |
frame:SetPoint(POSITION, alertAnchor, ANCHOR_POINT, 0, YOFFSET) |
alertAnchor = frame |
end |
end |
end |
hooksecurefunc("AlertFrame_SetLootWonAnchors", AlertFrame_SetLootWonAnchors) |
local function AlertFrame_SetMoneyWonAnchors(alertAnchor) |
for i = 1, #MONEY_WON_ALERT_FRAMES do |
local frame = MONEY_WON_ALERT_FRAMES[i] |
if frame:IsShown() then |
frame:ClearAllPoints() |
frame:SetPoint(POSITION, alertAnchor, ANCHOR_POINT, 0, YOFFSET) |
alertAnchor = frame |
end |
end |
end |
hooksecurefunc("AlertFrame_SetMoneyWonAnchors", AlertFrame_SetMoneyWonAnchors) |
local function AlertFrame_SetAchievementAnchors(alertAnchor) |
if AchievementAlertFrame1 then |
for i = 1, MAX_ACHIEVEMENT_ALERTS do |
local frame = _G["AchievementAlertFrame"..i] |
if frame and frame:IsShown() then |
frame:ClearAllPoints() |
frame:SetPoint(POSITION, alertAnchor, ANCHOR_POINT, 0, YOFFSET) |
alertAnchor = frame |
end |
end |
end |
end |
hooksecurefunc("AlertFrame_SetAchievementAnchors", AlertFrame_SetAchievementAnchors) |
local function AlertFrame_SetCriteriaAnchors(alertAnchor) |
if CriteriaAlertFrame1 then |
for i = 1, MAX_ACHIEVEMENT_ALERTS do |
local frame = _G["CriteriaAlertFrame"..i] |
if frame and frame:IsShown() then |
frame:ClearAllPoints() |
frame:SetPoint(POSITION, alertAnchor, ANCHOR_POINT, 0, YOFFSET) |
alertAnchor = frame |
end |
end |
end |
end |
hooksecurefunc("AlertFrame_SetCriteriaAnchors", AlertFrame_SetCriteriaAnchors) |
local function AlertFrame_SetChallengeModeAnchors(alertAnchor) |
local frame = ChallengeModeAlertFrame1 |
if frame:IsShown() then |
frame:ClearAllPoints() |
frame:SetPoint(POSITION, alertAnchor, ANCHOR_POINT, 0, YOFFSET) |
end |
end |
hooksecurefunc("AlertFrame_SetChallengeModeAnchors", AlertFrame_SetChallengeModeAnchors) |
local function AlertFrame_SetDungeonCompletionAnchors(alertAnchor) |
local frame = DungeonCompletionAlertFrame1 |
if frame:IsShown() then |
frame:ClearAllPoints() |
frame:SetPoint(POSITION, alertAnchor, ANCHOR_POINT, 0, YOFFSET) |
end |
end |
hooksecurefunc("AlertFrame_SetDungeonCompletionAnchors", AlertFrame_SetDungeonCompletionAnchors) |
local function AlertFrame_SetScenarioAnchors(alertAnchor) |
local frame = ScenarioAlertFrame1 |
if frame:IsShown() then |
frame:ClearAllPoints() |
frame:SetPoint(POSITION, alertAnchor, ANCHOR_POINT, 0, YOFFSET) |
end |
end |
hooksecurefunc("AlertFrame_SetScenarioAnchors", AlertFrame_SetScenarioAnchors) |
local function AlertFrame_SetGuildChallengeAnchors(alertAnchor) |
local frame = GuildChallengeAlertFrame |
if frame:IsShown() then |
frame:ClearAllPoints() |
frame:SetPoint(POSITION, alertAnchor, ANCHOR_POINT, 0, YOFFSET) |
end |
end |
hooksecurefunc("AlertFrame_SetGuildChallengeAnchors", AlertFrame_SetGuildChallengeAnchors) |
hooksecurefunc(GroupLootContainer, "SetPoint", function(self, point, anchorTo, attachPoint, xOffset, yOffset) |
if _G[anchorTo] == UIParent or _G[anchorTo] == AchievementAnchor then |
fixAnchors() |
end |
end) |
-- Auto invite |
---------------------------------------------------------------------------- |
if Soop["automation"].autoinvite then |
local CheckFriend = function(name) |
for i = 1, GetNumFriends() do |
if GetFriendInfo(i) == name then |
return true |
end |
end |
for i = 1, select(2, BNGetNumFriends()) do |
local presenceID, _, _, _, _, _, client, isOnline = BNGetFriendInfo(i) |
if client == "WoW" and isOnline then |
local _, toonName, _, realmName = BNGetToonInfo(presenceID) |
if name == toonName or name == toonName.."-"..realmName then |
return true |
end |
end |
end |
if IsInGuild() then |
for i = 1, GetNumGuildMembers() do |
if GetGuildRosterInfo(i) == name then |
return true |
end |
end |
end |
end |
local ai = CreateFrame("Frame") |
ai:RegisterEvent("PARTY_INVITE_REQUEST") |
ai:SetScript("OnEvent", function(self, event, name) |
if QueueStatusMinimapButton:IsShown() or GetNumGroupMembers() > 0 then return end |
if CheckFriend(name) then |
RaidNotice_AddMessage(RaidWarningFrame, "Accepted invite from: "..name, {r = 0.41, g = 0.8, b = 0.94}, 3) |
print(format("|cffffff00".."Accepted invite from: "..name..".")) |
AcceptGroup() |
for i = 1, STATICPOPUP_NUMDIALOGS do |
local frame = _G["StaticPopup"..i] |
if frame:IsVisible() and frame.which == "PARTY_INVITE" then |
frame.inviteAccepted = 1 |
StaticPopup_Hide("PARTY_INVITE") |
return |
elseif frame:IsVisible() and frame.which == "PARTY_INVITE_XREALM" then |
frame.inviteAccepted = 1 |
StaticPopup_Hide("PARTY_INVITE_XREALM") |
return |
end |
end |
else |
SendWho(name) |
end |
end) |
end |
-- Hides nasty blizzard taint errors |
---------------------------------------------------------------------------- |
local function ForceTaintPopupHide() |
if GetBuildInfo == "5.4.1" then |
hooksecurefunc("StaticPopup_Show", function(which) |
if (which == "ADDON_ACTION_FORBIDDEN") then |
StaticPopup_Hide(which) |
end |
end) |
end |
end |
local Fixes = CreateFrame("Frame") |
Fixes:RegisterEvent("PLAYER_ENTERING_WORLD") |
Fixes:SetScript("OnEvent", function(self, event, ...) |
if event == "PLAYER_ENTERING_WORLD" then |
ForceTaintPopupHide() |
self:UnregisterEvent("PLAYER_ENTERING_WORLD") |
end |
end) |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- Font settings |
---------------------------------------------------------------------------- |
do |
SetFontString = function(parent, fontName, fontHeight, fontStyle) |
local fs = parent:CreateFontString(nil, "OVERLAY") |
fs:SetFont(Soop["media"].font, fontHeight, fontStyle, "OUTLINE") |
fs:SetJustifyH("LEFT") |
fs:SetShadowColor(0, 0, 0) |
fs:SetShadowOffset(1.25, -1.25) |
return fs |
end |
end |
local Fonts = CreateFrame("Frame", nil, UIParent) |
SetFont = function(obj, font, size, style, r, g, b, sr, sg, sb, sox, soy) |
obj:SetFont(font, size, style) |
if sr and sg and sb then obj:SetShadowColor(sr, sg, sb) end |
if sox and soy then obj:SetShadowOffset(sox, soy) end |
if r and g and b then obj:SetTextColor(r, g, b) |
elseif r then obj:SetAlpha(r) end |
end |
Fonts:RegisterEvent("ADDON_LOADED") |
Fonts:SetScript("OnEvent", function(self, event, addon) |
local NORMAL = Soop["media"].font |
local COMBAT = Soop["media"].font |
local NUMBER = Soop["media"].font |
local _, editBoxFontSize, _, _, _, _, _, _, _, _ = GetChatWindowInfo(1) |
UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT = 12 |
CHAT_FONT_HEIGHTS = {12, 13, 14, 15, 16, 17, 18, 19, 20} |
UNIT_NAME_FONT = NORMAL |
NAMEPLATE_FONT = NORMAL |
DAMAGE_TEXT_FONT = COMBAT |
STANDARD_TEXT_FONT = NORMAL |
SetFont(GameTooltipHeader, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(NumberFont_OutlineThick_Mono_Small, NUMBER, Soop["media"].fontsize, "OUTLINE") |
SetFont(NumberFont_Outline_Huge, NUMBER, 28, "THICKOUTLINE", 28) |
SetFont(NumberFont_Outline_Large, NUMBER, 15, "OUTLINE") |
SetFont(NumberFont_Outline_Med, Soop["media"].font, Soop["media"].fontsize, "OUTLINE") |
SetFont(NumberFont_Shadow_Med, NORMAL, Soop["media"].fontsize+1) --Chat edit box |
SetFont(NumberFont_Shadow_Small, NORMAL, Soop["media"].fontsize) |
SetFont(QuestFont, NORMAL, Soop["media"].fontsize) |
SetFont(QuestFont_Large, NORMAL, 14, "OUTLINE") |
SetFont(SystemFont_Large, NORMAL, 15, "OUTLINE") |
SetFont(SystemFont_Shadow_Huge1, NORMAL, 20, "THINOUTLINE") -- Raid Warning |
SetFont(SystemFont_Med1, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(SystemFont_Med3, NORMAL, Soop["media"].fontsize*1.1, "OUTLINE") |
SetFont(SystemFont_OutlineThick_Huge2, NORMAL, 20, "THICKOUTLINE") |
SetFont(SystemFont_Outline_Small, NUMBER, Soop["media"].fontsize, "OUTLINE") |
SetFont(SystemFont_Shadow_Large, NORMAL, 15, "OUTLINE") |
SetFont(SystemFont_Shadow_Med1, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(SystemFont_Shadow_Med3, NORMAL, Soop["media"].fontsize*1.1) |
SetFont(SystemFont_Shadow_Outline_Huge2, NORMAL, 20, "OUTLINE") |
SetFont(SystemFont_Shadow_Small, NORMAL, Soop["media"].fontsize*0.9, "OUTLINE") |
SetFont(SystemFont_Small, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(SystemFont_Tiny, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(Tooltip_Med, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(Tooltip_Small, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(ZoneTextString, NORMAL, 32, "OUTLINE") |
SetFont(SubZoneTextString, NORMAL, 25, "OUTLINE") |
SetFont(PVPInfoTextString, NORMAL, 22, "THINOUTLINE") |
SetFont(PVPArenaTextString, NORMAL, 22, "THINOUTLINE") |
SetFont(CombatTextFont, COMBAT, 100, "THINOUTLINE") -- Increases font quality |
SetFont(InvoiceFont_Med, NORMAL, 13, "OUTLINE") |
SetFont(InvoiceFont_Small, NORMAL, 12, "OUTLINE") |
SetFont(MailFont_Large, NORMAL, 15, "OUTLINE") |
SetFont(QuestFont_Shadow_Huge, NORMAL, 19, "OUTLINE") |
SetFont(QuestFont_Shadow_Small, NORMAL, 15, "OUTLINE") |
SetFont(ReputationDetailFont, NORMAL, 12, "OUTLINE") |
SetFont(SpellFont_Small, NORMAL, 12, "OUTLINE") |
SetFont(FriendsFont_Small, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(FriendsFont_Normal, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(FriendsFont_Large, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(FriendsFont_UserText, NORMAL, Soop["media"].fontsize, "OUTLINE") |
SetFont(ChatBubbleFont, NORMAL, Soop["media"].fontsize, "OUTLINE") |
end) |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- Mirror |
---------------------------------------------------------------------------- |
local _, settings = ... |
local _DEFAULTS = { |
width = 220, |
height = 18, |
texture = Soop["media"].texture, |
position = { |
["BREATH"] = 'TOP#UIParent#TOP#0#-96'; |
["EXHAUSTION"] = 'TOP#UIParent#TOP#0#-119'; |
["FEIGNDEATH"] = 'TOP#UIParent#TOP#0#-142'; |
}; |
colors = { |
EXHAUSTION = {1, .9, 0}; |
BREATH = {0.31, 0.45, 0.63}; |
DEATH = {1, .7, 0}; |
FEIGNDEATH = {1, .7, 0}; |
}; |
} |
do |
settings = setmetatable(settings, {__index = _DEFAULTS}) |
for k,v in next, settings do |
if(type(v) == 'table') then |
settings[k] = setmetatable(settings[k], {__index = _DEFAULTS[k]}) |
end |
end |
end |
local Spawn, PauseAll |
do |
local barPool = {} |
local loadPosition = function(self) |
local pos = settings.position[self.type] |
local p1, frame, p2, x, y = strsplit("#", pos) |
return self:SetPoint(p1, frame, p2, x, y) |
end |
local OnUpdate = function(self, elapsed) |
if(self.paused) then return end |
self:SetValue(GetMirrorTimerProgress(self.type) / 1e3) |
end |
local Start = function(self, value, maxvalue, scale, paused, text) |
if(paused > 0) then |
self.paused = 1 |
elseif(self.paused) then |
self.paused = nil |
end |
self.text:SetText(text) |
self:SetMinMaxValues(0, maxvalue / 1e3) |
self:SetValue(value / 1e3) |
if(not self:IsShown()) then self:Show() end |
end |
function Spawn(type) |
if(barPool[type]) then return barPool[type] end |
local frame = CreateFrame('StatusBar', nil, UIParent) |
frame:SetScript("OnUpdate", OnUpdate) |
local r, g, b = unpack(settings.colors[type]) |
local bg = frame:CreateTexture(nil, 'BACKGROUND') |
bg:SetAllPoints(frame) |
bg:SetTexture(Soop["media"].blank) |
bg:SetVertexColor(r * .5, g * .5, b * .5) |
local border = CreateFrame("Frame", nil, frame) |
border:SetPoint("TOPLEFT", frame, -2, 2) |
border:SetPoint("BOTTOMRIGHT", frame, 2, -2) |
CreateShadow(border) |
border:SetFrameLevel(0) |
local text = frame:CreateFontString(nil, 'OVERLAY') |
text:SetFont(Soop["media"].font, Soop["media"].fontsize, "THINOUTLINE") |
text:SetShadowOffset(1, -1) |
text:SetShadowColor(0, 0, 0, 1) |
text:SetJustifyH'CENTER' |
text:SetTextColor(1, 1, 1) |
text:SetPoint('LEFT', frame) |
text:SetPoint('RIGHT', frame) |
text:SetPoint('TOP', frame, 0, 2) |
text:SetPoint('BOTTOM', frame) |
frame:SetSize(settings.width, settings.height) |
frame:SetStatusBarTexture(settings.texture) |
frame:SetStatusBarColor(r, g, b) |
frame.type = type |
frame.text = text |
frame.Start = Start |
frame.Stop = Stop |
loadPosition(frame) |
barPool[type] = frame |
return frame |
end |
function PauseAll(val) |
for _, bar in next, barPool do |
bar.paused = val |
end |
end |
end |
local frame = CreateFrame'Frame' |
frame:SetScript('OnEvent', function(self, event, ...) |
return self[event](self, ...) |
end) |
function frame:ADDON_LOADED(addon) |
UIParent:UnregisterEvent'MIRROR_TIMER_START' |
self:UnregisterEvent'ADDON_LOADED' |
self.ADDON_LOADED = nil |
end |
frame:RegisterEvent'ADDON_LOADED' |
function frame:PLAYER_ENTERING_WORLD() |
for i=1, MIRRORTIMER_NUMTIMERS do |
local type, value, maxvalue, scale, paused, text = GetMirrorTimerInfo(i) |
if(type ~= 'UNKNOWN') then |
Spawn(type):Start(value, maxvalue, scale, paused, text) |
end |
end |
end |
frame:RegisterEvent'PLAYER_ENTERING_WORLD' |
function frame:MIRROR_TIMER_START(type, value, maxvalue, scale, paused, text) |
return Spawn(type):Start(value, maxvalue, scale, paused, text) |
end |
frame:RegisterEvent'MIRROR_TIMER_START' |
function frame:MIRROR_TIMER_STOP(type) |
return Spawn(type):Hide() |
end |
frame:RegisterEvent'MIRROR_TIMER_STOP' |
function frame:MIRROR_TIMER_PAUSE(duration) |
return PauseAll((duration > 0 and duration) or nil) |
end |
frame:RegisterEvent'MIRROR_TIMER_PAUSE' |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- Timer |
---------------------------------------------------------------------------- |
local function SkinIt(bar) |
local _, originalPoint, _, _, _ = bar:GetPoint() |
bar:ClearAllPoints() |
bar:SetPoint("TOPLEFT", originalPoint, "TOPLEFT", 2, -2) |
bar:SetPoint("BOTTOMRIGHT", originalPoint, "BOTTOMRIGHT", -2, 2) |
for i=1, bar:GetNumRegions() do |
local region = select(i, bar:GetRegions()) |
if region:GetObjectType() == "Texture" then |
region:SetTexture(nil) |
elseif region:GetObjectType() == "FontString" then |
region:SetFont(Soop["media"].font, 12, "THINOUTLINE") |
region:SetShadowColor(0,0,0,0) |
end |
end |
bar:SetStatusBarTexture(Soop["media"].texture) |
bar:SetStatusBarColor(170/255, 10/255, 10/255) |
bar.backdrop = CreateFrame("Frame", nil, bar) |
bar.backdrop:SetFrameLevel(0) |
CreateShadow(bar.backdrop) |
bar.backdrop:SetAllPoints(originalPoint) |
end |
local function SkinBlizzTimer(self, event) |
for _, b in pairs(TimerTracker.timerList) do |
if not b["bar"].skinned then |
SkinIt(b["bar"]) |
b["bar"].skinned = true |
end |
end |
end |
local load = CreateFrame("Frame") |
load:RegisterEvent("START_TIMER") |
load:SetScript("OnEvent", SkinBlizzTimer) |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- SoopUI Functions |
---------------------------------------------------------------------------- |
-- Scale |
---------------------------------------------------------------------------- |
function UIScale() |
if Soop["general"].AutoScale == true then |
Soop["general"].UiScale = min(2, max(.64, 768/string.match(({GetScreenResolutions()})[GetCurrentResolution()], "%d+x(%d+)"))) |
end |
end |
UIScale() |
-- Pixel Perfect |
---------------------------------------------------------------------------- |
local mult = 768/string.match(GetCVar("gxResolution"), "%d+x(%d+)")/Soop["general"].UiScale |
local function scale(x) |
return mult*math.floor(x/mult+.5) |
end |
function Scale(x) return scale(x) end |
mult = mult |
-- Borders and Backdrops |
---------------------------------------------------------------------------- |
function CreatePanel(f, w, h, a1, p, a2, x, y) |
local _, class = UnitClass("player") |
local r, g, b = RAID_CLASS_COLORS[class].r, RAID_CLASS_COLORS[class].g, RAID_CLASS_COLORS[class].b |
sh = scale(h) |
sw = scale(w) |
f:SetFrameLevel(1) |
f:SetHeight(sh) |
f:SetWidth(sw) |
f:SetFrameStrata("BACKGROUND") |
f:SetPoint(a1, p, a2, x, y) |
f:SetBackdrop({ |
bgFile = [=[Interface\ChatFrame\ChatFrameBackground]=], |
edgeFile = "Interface\\Buttons\\WHITE8x8", |
tile = false, tileSize = 0, edgeSize = mult, |
insets = { left = -mult, right = -mult, top = -mult, bottom = -mult} |
}) |
f:SetBackdropColor(.05,.05,.05,0) |
f:SetBackdropBorderColor(.15,.15,.15,0) |
end |
function SimpleBackground(f, w, h, a1, p, a2, x, y) |
local _, class = UnitClass("player") |
local r, g, b = RAID_CLASS_COLORS[class].r, RAID_CLASS_COLORS[class].g, RAID_CLASS_COLORS[class].b |
sh = scale(h) |
sw = scale(w) |
f:SetFrameLevel(1) |
f:SetHeight(sh) |
f:SetWidth(sw) |
f:SetFrameStrata("BACKGROUND") |
f:SetPoint(a1, p, a2, x, y) |
f:SetBackdrop({ |
bgFile = "Interface\\AddOns\\SoopUI\\Media\\statusbar4", |
edgeFile = "Interface\\AddOns\\SoopUI\\Media\\statusbar4", |
tile = false, tileSize = 0, edgeSize = mult, |
insets = { left = mult, right = mult, top = mult, bottom = mult} |
}) |
f:SetBackdropColor(.07,.07,.07, 1) |
f:SetBackdropBorderColor(0, 0, 0, 1) |
end |
local forInfoPanel = { |
bgFile = "Interface\\AddOns\\SoopUI\\Media\\statusbar4", |
edgeFile = "Interface\\AddOns\\SoopUI\\Media\\glowTex", |
edgeSize = 4, |
insets = { left = 2, right = 2, top = 2, bottom = 2 } |
} |
function CreateShadowforInfoPanel(f) |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -2, 2) |
shadow:SetPoint("BOTTOMRIGHT", 2, -2) |
shadow:SetBackdrop(forInfoPanel) |
shadow:SetBackdropColor(.05,.05,.05, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 1) |
f.shadow = shadow |
return shadow |
end |
local shadows = { |
bgFile = "Interface\\AddOns\\SoopUI\\Media\\statusbar4", |
edgeFile = "Interface\\AddOns\\SoopUI\\Media\\glowTex", |
edgeSize = 4, |
insets = { left = 3, right = 3, top = 3, bottom = 3 } |
} |
function CreateShadow(f) -- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -2, 2) |
shadow:SetPoint("BOTTOMRIGHT", 2, -2) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor(.08,.08,.08, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 1) |
f.shadow = shadow |
return shadow |
end |
function CreateShadowraid(f) -- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -4, 4) |
shadow:SetPoint("BOTTOMRIGHT", 4, -4) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor(.08,.08,.08, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 1) |
f.shadow = shadow |
return shadow |
end |
local shadows12345 = { |
bgFile = "Interface\\AddOns\\SoopUI\\Media\\statusbar4", |
edgeFile = "Interface\\AddOns\\SoopUI\\Media\\glowTex", |
edgeSize = 4, |
insets = { left = 3, right = 3, top = 3, bottom = 3 } |
} |
function CreateShadow12345(f) -- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -2, 2) |
shadow:SetPoint("BOTTOMRIGHT", 2, -2) |
shadow:SetBackdrop(shadows12345) |
shadow:SetBackdropColor(.05,.05,.05, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 0.5) |
f.shadow = shadow |
return shadow |
end |
function CreateShadowclassbar(f) -- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(5) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -2, 2) |
shadow:SetPoint("BOTTOMRIGHT", 2, -2) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor(.05,.05,.05, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 0.6) |
f.shadow = shadow |
return shadow |
end |
function CreateShadowclassbar2(f) -- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(1) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -4, 4) |
shadow:SetPoint("BOTTOMRIGHT", 4, -4) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor(.05,.05,.05, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 0.6) |
f.shadow = shadow |
return shadow |
end |
function CreateShadowclassbar4(f) -- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(5) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -4, 4) |
shadow:SetPoint("BOTTOMRIGHT", 4, -4) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor(.05,.05,.05, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 0.6) |
f.shadow = shadow |
return shadow |
end |
function SimpleShadow(f) -- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -2, 2) |
shadow:SetPoint("BOTTOMRIGHT", 2, -2) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor(.05,.05,.05, 1) |
shadow:SetBackdropBorderColor(0, 0, 0, 0) |
f.shadow = shadow |
return shadow |
end |
function frame1px(f) |
f:SetBackdrop({ |
bgFile = [=[Interface\ChatFrame\ChatFrameBackground]=], |
edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = mult, |
insets = {left = -mult, right = -mult, top = -mult, bottom = -mult} |
}) |
f:SetBackdropColor(.05,.05,.05,0) |
f:SetBackdropBorderColor(.15,.15,.15,0) |
end |
function CreateShadowConfig(f)-- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -2, 2) |
shadow:SetPoint("BOTTOMRIGHT", 2, -2) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor( .05,.05,.05, 0) |
shadow:SetBackdropBorderColor(0, 0, 0, 1) |
f.shadow = shadow |
return shadow |
end |
function CreateShadowback(f) |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -2, 2) |
shadow:SetPoint("BOTTOMRIGHT", 2, -2) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor( .05,.05,.05, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 1) |
f.shadow = shadow |
return shadow |
end |
function CreateShadow3(f)-- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -3, 3) |
shadow:SetPoint("BOTTOMRIGHT", 3, -3) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor( .05,.05,.05, 0) |
shadow:SetBackdropBorderColor(0, 0, 0, 1) |
f.shadow = shadow |
return shadow |
end |
function CreateShadowNameplates(f) |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -4, 4) |
shadow:SetPoint("BOTTOMRIGHT", 4, -4) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor( .05,.05,.05, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 1) |
f.shadow = shadow |
return shadow |
end |
function CreateShadow2(f)-- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", -5, 5) |
shadow:SetPoint("BOTTOMRIGHT", 5, -5) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor( .05,.05,.05, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 1) |
f.shadow = shadow |
return shadow |
end |
function CreateShadow0(f)-- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(0) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", 1, -1) |
shadow:SetPoint("BOTTOMRIGHT", -1, 1) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor( .05,.05,.05, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 1) |
f.shadow = shadow |
return shadow |
end |
function CreateShadow00(f)-- |
if f.shadow then return end |
local shadow = CreateFrame("Frame", nil, f) |
shadow:SetFrameLevel(4) |
shadow:SetFrameStrata(f:GetFrameStrata()) |
shadow:SetPoint("TOPLEFT", 1, -1) |
shadow:SetPoint("BOTTOMRIGHT", -1, 1) |
shadow:SetBackdrop(shadows) |
shadow:SetBackdropColor( .05,.05,.05, .9) |
shadow:SetBackdropBorderColor(0, 0, 0, 0.6) |
f.shadow = shadow |
return shadow |
end |
function CreateShadow1(f) |
if f.frameBD==nil then |
local frameBD = CreateFrame("Frame", nil, f) |
frameBD = CreateFrame("Frame", nil, f) |
frameBD:SetFrameLevel(5) |
frameBD:SetFrameStrata(f:GetFrameStrata()) |
frameBD:SetPoint("TOPLEFT", 1, -1) |
frameBD:SetPoint("BOTTOMLEFT", 1, 1) |
frameBD:SetPoint("TOPRIGHT", -1, -1) |
frameBD:SetPoint("BOTTOMRIGHT", -1, 1) |
frameBD:SetBackdrop( { |
edgeFile = "Interface\\AddOns\\SoopUI\\Media\\glowTex", edgeSize = 4, |
insets = {left = 3, right = 3, top = 3, bottom = 3}, |
tile = false, tileSize = 0, |
}) |
frameBD:SetBackdropColor( .05,.05,.05, .9) |
frameBD:SetBackdropBorderColor(0, 0, 0, 0.6) |
f.frameBD = frameBD |
end |
end |
-- ___ ___ ___ ___ ___ |
-- / /\ / /\ / /\ / /\ /__/\ ___ |
-- / /:/_ / /::\ / /::\ / /::\ \ \:\ / /\ |
-- / /:/ /\ / /:/\:\ / /:/\:\ / /:/\:\ \ \:\ / /:/ |
-- / /:/ /::\ / /:/ \:\ / /:/ \:\ / /:/~/:___ \ \:\/__/::\ |
-- /__/:/ /:/\:/__/:/ \__\:/__/:/ \__\:/__/:/ /:/__/\ \__\:\__\/\:\__ |
-- \ \:\/:/~/:\ \:\ / /:\ \:\ / /:\ \:\/:/\ \:\ / /:/ \ \:\/\ |
-- \ \::/ /:/ \ \:\ /:/ \ \:\ /:/ \ \::/ \ \:\ /:/ \__\::/ |
-- \__\/ /:/ \ \:\/:/ \ \:\/:/ \ \:\ \ \:\/:/ /__/:/ |
-- /__/:/ \ \::/ \ \::/ \ \:\ \ \::/ \__\/ |
-- \__\/ \__\/ \__\/ \__\/ \__\/ |
-- v * e * r * s * i * o * n * 3 |
---------------------------------------------------------------------------- |
-- sMinimap |
---------------------------------------------------------------------------- |
if not Soop["minimap"].enable == true then return end |
local font = Soop["media"].font |
local fontsize = 10 |
local fontflag = "OUTLINE" |
local Scale = 1 |
local classcolors = true -- class color text |
Minimap:ClearAllPoints() |
Minimap:SetPoint("CENTER", minimaplol, "CENTER", 0, 0) |
MinimapCluster:EnableMouse(false) |
Minimap:SetSize(Soop["minimap"].size,Soop["minimap"].size) |
Minimap:SetMaskTexture('Interface\\ChatFrame\\ChatFrameBackground') |
Minimap:SetHitRectInsets(0, 0, 24*Scale, 24*Scale) |
Minimap:SetFrameLevel(4) |
Minimap:SetScale(Scale) |
Minimap:SetArchBlobRingScalar(0); |
Minimap:SetQuestBlobRingScalar(0); |
if(IsAddOnLoaded('!ClassColors') and CUSTOM_CLASS_COLORS) then |
color = CUSTOM_CLASS_COLORS[select(2, UnitClass("player"))] |
end |
if classcolors == true then |
color = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[select(2,UnitClass("player"))] |
else |
color = {r=255/255, g=255/255, b=255/255 } |
end |
-- Hide in Combat |
---------------------------------------------------------------------------- |
if Soop["minimap"].hideincombat then |
local mmd = CreateFrame("Frame") |
mmd:RegisterEvent("PLAYER_REGEN_ENABLED") |
mmd:RegisterEvent("PLAYER_REGEN_DISABLED") |
mmd:HookScript("OnEvent", function(self, event) |
if event == "PLAYER_REGEN_ENABLED" then |
MinimapCluster:Show() |
elseif event == "PLAYER_REGEN_DISABLED" then |
MinimapCluster:Hide() |
end |
end) |
end |
local oldOnClick = Minimap:GetScript("OnMouseUp") |
Minimap:SetScript("OnMouseUp", function(self,click) |
if(click=="RightButton") then |
ToggleDropDownMenu(1, nil, MiniMapTrackingDropDown, "cursor", 0, 0) |
elseif(click=="MiddleButton") then |
if (not CalendarFrame) then LoadAddOn("Blizzard_Calendar") end Calendar_Toggle() |
else |
oldOnClick(self) |
end |
end) |
-- Dungeon Difficulty |
---------------------------------------------------------------------------- |
local rd = CreateFrame("Frame", nil, Minimap) |
rd:SetSize(24, 8) |
rd:RegisterEvent("PLAYER_ENTERING_WORLD") |
rd:RegisterEvent("PLAYER_DIFFICULTY_CHANGED") |
rd:RegisterEvent("GUILD_PARTY_STATE_UPDATED") |
local rdt = rd:CreateFontString(nil, "OVERLAY") |
rdt:SetPoint("TOP", Minimap, "TOP", 0, -5) |
rdt:SetFont(font, fontsize, fontflag) |
rd:SetScript("OnEvent", function() |
local _, _, difficulty, _, maxPlayers = GetInstanceInfo() |
if difficulty == 0 then |
rdt:SetText("") |
elseif maxPlayers == 3 then |
rdt:SetText("3") |
elseif difficulty == 1 then |
rdt:SetText("5") |
elseif difficulty == 2 then |
rdt:SetText("5H") |
elseif difficulty == 3 then |
rdt:SetText("10") |
elseif difficulty == 4 then |
rdt:SetText("25") |
elseif difficulty == 5 then |
rdt:SetText("10H") |
elseif difficulty == 6 then |
rdt:SetText("25H") |
elseif difficulty == 7 then |
rdt:SetText("LFR") |
elseif difficulty == 8 then |
rdt:SetText("5CM") |
elseif difficulty == 9 then |
rdt:SetText("40") |
end |
if GuildInstanceDifficulty:IsShown() then |
rdt:SetTextColor(color.r, color.g, color.b) |
else |
rdt:SetTextColor(color.r, color.g, color.b) |
end |
end) |
local function StripTextures(object, kill) |
for i=1, object:GetNumRegions() do |
local region = select(i, object:GetRegions()) |
if region:GetObjectType() == "Texture" then |
if kill then |
region:Hide() |
else |
region:SetTexture(nil) |
end |
end |
end |
end |
-- Battleground queue |
---------------------------------------------------------------------------- |
QueueStatusMinimapButton:SetParent(Minimap) |
QueueStatusMinimapButton:ClearAllPoints() |
QueueStatusMinimapButton:SetPoint("TOPRIGHT", 0, 0) |
QueueStatusMinimapButtonBorder:Hide() |
StripTextures(QueueStatusFrame) |
CreateShadow(QueueStatusFrame) |
MiniMapWorldMapButton:Hide() |
local function UpdateLFGTooltip() |
QueueStatusFrame:ClearAllPoints() |
QueueStatusFrame:SetPoint("TOPRIGHT", QueueStatusMinimapButton, "TOPLEFT", 0, 0) |
end |
QueueStatusFrame:HookScript("OnShow", UpdateLFGTooltip) |
QueueStatusFrame:SetFrameStrata("TOOLTIP") |
MiniMapMailFrame:ClearAllPoints() |
MiniMapMailFrame:SetPoint("BOTTOMRIGHT", Minimap, 0, 0) |
MiniMapMailFrame:SetFrameStrata("LOW") |
MiniMapMailIcon:SetTexture("Interface\\AddOns\\SoopUI\\Media\\mail.tga") |
MiniMapMailBorder:Hide() |
MiniMapTracking:ClearAllPoints() |
MiniMapTracking:SetParent(Minimap) |
MiniMapTracking:SetPoint('TOPLEFT', 0, 0) |
MiniMapTracking:SetAlpha(0) |
MiniMapTrackingBackground:Hide() |
MiniMapTrackingButtonBorder:SetTexture(nil) |
MiniMapTrackingButton:SetHighlightTexture(nil) |
MiniMapTrackingIconOverlay:SetTexture(nil) |
MiniMapTrackingIcon:SetTexCoord(0.065, 0.935, 0.065, 0.935) |
MiniMapTrackingIcon:SetWidth(20) |
MiniMapTrackingIcon:SetHeight(20) |
-- Minimap frame |
---------------------------------------------------------------------------- |
sMinimap = CreateFrame("Frame", "sMinimap", UIParent) |
sMinimap:RegisterEvent("ADDON_LOADED") |
sMinimap:SetScript("OnEvent", function(self, event, addon) |
sMinimap.tracking = CreateFrame("Frame", nil, Minimap) |
MiniMapTrackingButton:SetScript("OnEnter",function() |
MiniMapTracking:SetAlpha(1) |
sMinimap.tracking:SetAlpha(1) |
end) |
Minimap:SetScript("OnLeave", function() |
MiniMapTracking:SetAlpha(0) |
sMinimap.tracking:SetAlpha(0) |
end) |
MiniMapTrackingButton:SetScript("OnLeave", function() |
MiniMapTracking:SetAlpha(0) |
sMinimap.tracking:SetAlpha(0) |
end) |
MiniMapTrackingButton:SetScript("OnMouseUp", function(self,click) |
if(click=="RightButton") then |
ToggleDropDownMenu(1, nil, MiniMapTrackingDropDown, "cursor", 0, 0) |
elseif(click=="MiddleButton") then |
if (not CalendarFrame) then LoadAddOn("Blizzard_Calendar") end Calendar_Toggle() |
end |