diff --git a/!Compatibility/api/wowAPI.lua b/!Compatibility/api/wowAPI.lua index bdf0ad4..27d8e84 100644 --- a/!Compatibility/api/wowAPI.lua +++ b/!Compatibility/api/wowAPI.lua @@ -10,17 +10,19 @@ local unpack = unpack local find, format, gsub, lower, match, upper = string.find, string.format, string.gsub, string.lower, string.match, string.upper local getn = table.getn --WoW API +local GetInventoryItemTexture = GetInventoryItemTexture local GetItemInfo = GetItemInfo local GetQuestGreenRange = GetQuestGreenRange local GetRealZoneText = GetRealZoneText local IsInInstance = IsInInstance -local UnitBuff = UnitBuff -local UnitDebuff = UnitDebuff +--local UnitBuff = UnitBuff +--local UnitDebuff = UnitDebuff local UnitLevel = UnitLevel --WoW Variables local DUNGEON_DIFFICULTY1 = DUNGEON_DIFFICULTY1 local TIMEMANAGER_AM = gsub(TIME_TWELVEHOURAM, "^.-(%w+)$", "%1") local TIMEMANAGER_PM = gsub(TIME_TWELVEHOURPM, "^.-(%w+)$", "%1") +local DURABILITY_TEMPLATE = gsub(DURABILITY_TEMPLATE, "%%d / %%d", "(%%d+) / (%%d+)") --Libs local LBC = LibStub("LibBabble-Class-3.0"):GetLookupTable() local LBZ = LibStub("LibBabble-Zone-3.0"):GetLookupTable() @@ -145,11 +147,11 @@ function UnitAura(unit, i, filter) end if not filter or match(filter, "(HELPFUL)") then - local name, rank, aura, count, duration, maxDuration = UnitBuff(unit, i, filter) - return name, rank, aura, count, nil, duration or 0, maxDuration or 0 + local texture, count = UnitBuff(unit, i, filter) + return texture, count else - local name, rank, aura, count, dType, duration, maxDuration = UnitDebuff(unit, i, filter) - return name, rank, aura, count, dType, duration or 0, maxDuration or 0 + local texture, count, dType = UnitDebuff(unit, i, filter) + return texture, count, dType end end @@ -271,7 +273,7 @@ function GetPlayerFacing() local obj = Minimap for i = 1, obj:GetNumChildren() do local child = select(i, obj:GetChildren()) - if child and child.GetModel and child:GetModel() == "interface\\minimap\\minimaparrow.m2" then + if child and child.GetModel and child:GetModel() == "Interface\\Minimap\\MinimapArrow" then arrow = child break end @@ -472,4 +474,24 @@ function GetItemCount(itemName) end return count +end + +local scan +function GetInventoryItemDurability(slot) + if not GetInventoryItemTexture("player", slot) then return nil, nil end + + if not scan then + scan = CreateFrame("GameTooltip", "DurabilityScan", nil, "ShoppingTooltipTemplate") + scan:SetOwner(UIParent, "ANCHOR_NONE") + end + + scan:ClearLines() + scan:SetInventoryItem("player", slot) + + for i = 4, scan:NumLines() do + local text = _G[scan:GetName().."TextLeft"..i]:GetText() + for durability, max in string.gfind(text, DURABILITY_TEMPLATE) do + return tonumber(durability), tonumber(max) + end + end end \ No newline at end of file diff --git a/!Compatibility/libs/Classy-1.0.lua b/!Compatibility/libs/Classy-1.0.lua new file mode 100644 index 0000000..237273e --- /dev/null +++ b/!Compatibility/libs/Classy-1.0.lua @@ -0,0 +1,26 @@ +--[[ + Classy.lua + A wrapper for defining classes that inherit from widgets +--]] + +local Classy = LibStub:NewLibrary('Classy-1.0', 0) +if not Classy then return end + +function Classy:New(frameType, parentClass) + local class = CreateFrame(frameType) + class.mt = {__index = class} + + if parentClass then + class = setmetatable(class, {__index = parentClass}) + + class.super = function(self, method, ...) + parentClass[method](self, unpack(arg)) + end + end + + class.Bind = function(self, obj) + return setmetatable(obj, self.mt) + end + + return class +end \ No newline at end of file diff --git a/!Compatibility/libs/Parser.lua b/!Compatibility/libs/Parser.lua new file mode 100644 index 0000000..34ffb15 --- /dev/null +++ b/!Compatibility/libs/Parser.lua @@ -0,0 +1,268 @@ +if not LibStub then return end + +local SD = LibStub:GetLibrary('StateDriver-1.0') +if not SD then return end + +local Parser = SD:New('Parser') + +local IsMounted = IsMounted +local IsStealthed = IsStealthed +local GetShapeshiftForm = GetShapeshiftForm + +local _G = getfenv(0) +local function IsInShapeshiftForm(index) + return GetShapeshiftForm() == tonumber(index) +end + + +function Parser:Initialize() + self.casting = nil + self.channel_spell = nil + self.channeling = nil + + self:RegisterEvent('PLAYER_ENTERING_WORLD') + self:RegisterEvent('SPELLCAST_START') + self:RegisterEvent('SPELLCAST_CHANNEL_START') + self:RegisterEvent('SPELLCAST_STOP') + self:RegisterEvent('SPELLCAST_CHANNEL_STOP') + -- self:SetScript('OnEvent', function() self[event](self) end) +end + +local _CastSpellByName +local Hooked_CastSpellByName = function(spell, unit) + if spell then + self.channel_spell = spell + _CastSpellByName(spell, unit) + end +end + +local HOOKED = false +function Parser:PLAYER_ENTERING_WORLD() + if not HOOKED then + _CastSpellByName = CastSpellByName + CastSpellByName = Hooked_CastSpellByName + HOOKED = true + end +end + +function Parser:SPELLCAST_START() + self.casting = arg1 +end + +function Parser:SPELLCAST_CHANNEL_START() + self.channeling = true +end + +function Parser:SPELLCAST_STOP() + self.casting = false +end + +function Parser:SPELLCAST_CHANNEL_STOP() + self.channel_spell = nil + self.channeling = false +end + +local conditions_map, casting, existence, hostility +do + local function IsChanneling(dependency) + return dependency and dependency == Parser.channeling or Parser.channeling + end + + local function IsCasting(dependency) + return dependency and dependency == Parser.casting or Parser.casting + end + + local function IsMouseOverUnit() + local is_mouseover = false + + is_mouseover = UnitName('mouseover') and 'mouseover' + + local frame = GetMouseFocus() + if frame and frame.GetAttribute then + is_mouseover = is_mouseover or frame:GetAttribute('unit') + end + is_mouseover = is_mouseover or frame and frame.unit + + return is_mouseover + end + + local function modifierCondition(dependency) + dependency = dependency == 'ctrl' and 'control' or dependency + local modifier = string.gsub(dependency, "^%l", string.upper) + return _G['Is' .. modifier .. 'KeyDown']() + end + + -- Rename dependent? + casting = { + ['channeling'] = IsChanneling, + ['nochanneling'] = function(dependency) + return not IsChanneling(dependency) + end, + ['casting'] = IsCasting, + ['nocasting'] = function(dependency) + return not IsCasting(dependency) + end, + ['group'] = function(dependency) + local in_raid = UnitInRaid('player') + -- Player is apparently always in a party... Party Rock Anthem, GO! + local in_party = UnitInParty('party1') + + if dependency then + if dependency == 'raid' then + return in_raid + else + return in_party + end + else + return in_raid or in_party + end + end, + ['nogroup'] = function(dependency) + local in_raid = UnitInRaid('player') + local in_party = UnitInParty('party1') + + if dependency then + if dependency == 'raid' then + return not in_raid + else + return not in_party + end + else + return (not in_raid) and (not in_party) + end + end, + ['mod'] = modifierCondition, + ['modifier'] = modifierCondition, + ['form'] = IsInShapeshiftForm, + ['stance'] = IsInShapeshiftForm + } + + existence = { + ['exists'] = UnitExists, + ['noexists'] = function(unit) + return not UnitExists(unit) + end, + ['dead'] = function(unit) + return UnitIsDead(unit) and not UnitAura(unit, 'Feign Death') + end, + ['nodead'] = function(unit) + return not (UnitIsDead(unit) and not UnitAura(unit, 'Feign Death')) + end, + } + + + hostility = { + ['harm'] = function(unit_one, unit_two) + return UnitExists(unit_two) and (not UnitIsFriend(unit_one, unit_two)) + end, + ['nohelp'] = function(unit_one, unit_two) + return UnitExists(unit_two) and (not UnitIsFriend(unit_one, unit_two)) + end, + ['help'] = UnitIsFriend, + ['noharm'] = UnitIsFriend + } + + + conditions_map = { + -- Targets + ['mouseover'] = IsMouseOverUnit, + + ['pet'] = HasPetUI, + ['nopet'] = function() return not HasPetUI() end, + + ['party'] = UnitInParty, + ['raid'] = UnitInRaid, + + ['combat'] = UnitAffectingCombat, + + ['mounted'] = IsMounted, + -- ['indoors'] = IsIndoors, + -- ['outdoors'] = IsOutdoors, + ['stealth'] = IsStealthed, + -- ['swimming'] = IsSwimming, + + ['bonusbar'] = function(bar_id) + return false + end, + } + + for k, v in next, casting do conditions_map[k] = v end + for k, v in next, existence do conditions_map[k] = v end + for k, v in next, hostility do conditions_map[k] = v end +end + +function CmdOptionParse(command) + -- /action [conditions] + local action, conditions + + -- Accumulating condition + local acc_condition + + -- Condition-mapped function and dependency argument + local func, dependency + + -- [@target] + local target, is_cond_target + + if not string.find(command, ';') then + command = command .. ' ;' + end + + -- Iterate condition cases + for _, cases in { string.split(';', command) } do + conditions, action = string.match(cases, '%[([^%]]+)%]%s*(.+)') + + -- Does the action have any conditions? + if conditions then + conditions = { string.split(',', conditions) } + acc_condition = true + target = nil + for _, cond in conditions do + cond = string.trim(cond) + cond, dependency = string.split(':', cond) + + -- Is the current condition a target command? Usually the first + -- condition is + is_cond_target = + string.match(cond, '@(.*)') or + string.match(cond, 'target=(.*)') + + -- Mouseover has a special condition, since unitframes don't + -- utilise the mouseover unit, in which case it's mapped to + -- player, target, partyN etc. + func = conditions_map[is_cond_target or cond] + + if is_cond_target then + target = func and func() or is_cond_target + else + local res + + if hostility[cond] then + res = func and func('player', target or 'target') + elseif existence[cond] then + res = func and func(target or 'target') + elseif cond == 'combat' then + res = func and func('player') + elseif casting[cond] then + res = func and func(dependency) + else + res = func and func() + end + + acc_condition = acc_condition and res + end + end + + -- Are all conditions met? Then perform that action + if acc_condition then + return string.trim(action), target + end + else + local cases = string.trim(cases) + return cases + end + end +end +SecureCmdOptionParse = CmdOptionParse + +Parser:Initialize() \ No newline at end of file diff --git a/!Compatibility/libs/StateDriver-1.0.lua b/!Compatibility/libs/StateDriver-1.0.lua new file mode 100644 index 0000000..cd759bf --- /dev/null +++ b/!Compatibility/libs/StateDriver-1.0.lua @@ -0,0 +1,513 @@ +--[[ +Name: StateDriver-1.0 +Revision: $Rev: 107 $ +Maintainers: martinjlowm +Website: https://github.com/martinjlowm/StateDriver/ +Dependencies: Classy-1.0 +License: None +]] + +if not LibStub then return end + +local SD = LibStub:NewLibrary('StateDriver-1.0', 0) +if not SD then return end + +local Classy = LibStub('Classy-1.0') + +local _G = getfenv(0) + +function SD:New(name, parent) + self[name] = Classy:New('Frame', parent) + + return self[name] +end + +local function GetAttribute(self, prefix, name, suffix) + local attributes = self.__state_driver.attributes + local value + + if not name and not suffix then + name = prefix + else + value = attributes[prefix .. name .. suffix] + value = value or attributes['*' .. name .. suffix] + value = value or attributes[prefix .. name .. '*'] + value = value or attributes['*' .. name .. '*'] + end + + return value or attributes[name] +end + +local function SetAttribute(self, attr, value) + local old_value = self.__state_driver.attributes[attr] + self.__state_driver.attributes[attr] = value + + local func = self.__state_driver.handlers['OnAttributeChanged'] + if func and type(func) == 'function' and value ~= old_value then + func(self, attr, value) + end +end + + +-- Figure out where to place this +local function initPlayerDrop() + UnitPopup_ShowMenu(PlayerFrameDropDown, "SELF", "player") + if not (UnitInRaid("player") or GetNumPartyMembers() > 0) or UnitIsPartyLeader("player") and PlayerFrameDropDown.init and not CanShowResetInstances() then + UIDropDownMenu_AddButton({text = RESET_INSTANCES, func = ResetInstances, notCheckable = 1}, 1) + PlayerFrameDropDown.init = nil + end +end + + +local ACTIONS = {} + +ACTIONS.target = function(self, unit, button) + if unit then + if unit == 'none' then + ClearTarget(); + elseif ( SpellIsTargeting() ) then + SpellTargetUnit(unit); + elseif ( CursorHasItem() ) then + DropItemOnUnit(unit); + else + TargetUnit(unit); + end + end +end + +ACTIONS.togglemenu = function(self, unit, button) + if UnitIsUnit(unit, 'player') then + UIDropDownMenu_Initialize(PlayerFrameDropDown, initPlayerDrop, 'MENU') + PlayerFrameDropDown.init = true + ToggleDropDownMenu(1, nil, PlayerFrameDropDown, 'cursor') + elseif unit == 'pet' then + ToggleDropDownMenu(1, nil, PetFrameDropDown, 'cursor') + elseif unit == 'target' then + ToggleDropDownMenu(1, nil, TargetFrameDropDown, 'cursor') + elseif string.sub(unit, 1, 5) == 'party' then + ToggleDropDownMenu(1, nil, _G['PartyMemberFrame' .. string.sub(unit,6) .. 'DropDown'], 'cursor') + elseif string.sub(unit, 1, 4) == 'raid' then + HideDropDownMenu(1) + + local menuFrame = FriendsDropDown + menuFrame.displayMode = 'MENU' + menuFrame.id = string.sub(this.unit,5) + menuFrame.unit = unit + menuFrame.name = UnitName(this.unit) + menuFrame.initialize = function() + UnitPopup_ShowMenu(getglobal(UIDROPDOWNMENU_OPEN_MENU), "PARTY", self.unit, self.name, self.id) + end + + ToggleDropDownMenu(1, nil, FriendsDropDown, 'cursor') + end +end + +ACTIONS.macro = function(self, unit, button) + local macro_text = self:GetAttribute('macrotext') + local spell, unit = SecureCmdOptionParse(macro_text) + CastSpellByName(spell, unit) +end + +ACTIONS.spell = function(self, unit, button) + local spell = self:GetAttribute('spell') + CastSpellByName(spell) +end + +ACTIONS.pet = function(self, unit, button) + local index = self:GetAttribute('pet') + CastPetAction(index, unit) +end + +ACTIONS.func = function(self, unit, button) + local func = SlashCmdList[self:GetAttribute('func')] + + if not func then + error(string.format('Slash command `%s` does not exist in SlashCmdList')) + return + end + + func() +end + +local link_pattern = '%[([^%]]+)%]' +local function CmdItemParse(item) + local slot = tonumber(item) + if slot then + return nil, nil, slot + end + + local link, name + for bag = 0, 4 do + for slot = 1, GetContainerNumSlots(bag) do + link = GetContainerItemLink(bag, slot) + + if link then + name = string.match(link, link_pattern) + if name and name == item then + return name, bag, slot + end + end + end + end +end + +ACTIONS.item = function(self, unit, button) + local item = self:GetAttribute('item') + + if item then + local name, bag, slot = CmdItemParse(item) + UseItem(name, bag, slot) + end +end + +function UseItem(name, bag, slot) + if bag then + UseContainerItem(bag, slot) + elseif slot then + UseInventoryItem(slot) + end +end + +ACTIONS.assign = function(self, unit, button) + local macro_text = self:GetAttribute('assign') + local symbol, unit = SecureCmdOptionParse(macro_text) + SetRaidTargetIcon(unit, symbol) +end + +function Button_GetModifierPrefix(frame) + local prefix = '' + prefix = IsShiftKeyDown() and 'shift-' .. prefix or prefix + prefix = IsControlKeyDown() and 'ctrl-' .. prefix or prefix + return IsAltKeyDown() and 'alt-' .. prefix or prefix +end + +function Button_GetButtonSuffix(button) + if button == 'LeftButton' then + return '1' + elseif button == 'RightButton' then + return '2' + elseif button == 'MiddleButton' then + return '3' + end + + return ''; +end + +function Button_GetModifiedAttribute(frame, name, button, prefix, suffix) + if not prefix then + prefix = Button_GetModifierPrefix(frame) + end + if not suffix then + suffix = Button_GetButtonSuffix(button) + end + + return frame:GetAttribute(prefix, name, suffix) +end + +local function OnClick(self, button) + if not self.GetAttribute then return end + + local unit = self:GetAttribute('unit') + + local action_type = Button_GetModifiedAttribute(self, 'type', button) + + if action_type then + local handler = ACTIONS[action_type] + if handler and type(handler) == 'function' then + handler(self, unit, button) + end + end + +end + +local function SetScript(self, handler, func) + if self.__state_driver.handlers[handler] then + if self:HasScript(handler) and handler == 'OnClick' then + self.__state_driver._SetScript(self, handler, function(...) + OnClick(this, arg1) + func() + end) + else + self.__state_driver.handlers[handler] = func + end + else + self.__state_driver._SetScript(self, handler, func) + end +end + +local _CreateFrame = CreateFrame +function CreateFrame(...) + local frame = _CreateFrame(unpack(arg)) + + -- State Driver environment + frame.__state_driver = {} + + frame.__state_driver._SetScript = frame.SetScript + frame.SetScript = SetScript + + frame.__state_driver.attributes = {} + frame.__state_driver.handlers = { + ['OnAttributeChanged'] = true, + ['OnClick'] = true + } + + frame.GetAttribute = GetAttribute + frame.SetAttribute = SetAttribute + + if frame:HasScript('OnClick') and not frame:GetScript('OnClick') then + frame:SetScript('OnClick', NOOP) + end + + return frame +end + +local function Execute(frame, func) + +end + +local function WrapScript(frame, func) + +end + +local function UnwrapScript(frame, func) + +end + +local function ChildUpdate(frame, attr_snippet, value) + local children = { frame:GetChildren() } + local childUpdate + + for _, child in next, children do + if child.GetAttribute then + childUpdate = child:GetAttribute('_childupdate-' .. attr_snippet) + if childUpdate then + childUpdate(child, value) + else + childUpdate = child:GetAttribute('_childupdate') + if childUpdate then + childUpdate(child, value) + end + end + ChildUpdate(child, attr_snippet, value) + end + end +end + +-- +-- SecureStateDriverManager +-- Automatically sets states based on macro options for state driver frames +-- Also handled showing/hiding frames based on unit existence (code originally by Tem) +-- + +-- Register a frame attribute to be set automatically with changes in game state +function RegisterAttributeDriver(frame, attribute, values) + frame.Execute = Execute + frame.WrapScript = WrapScript + frame.UnwrapScript = UnwrapScript + frame.ChildUpdate = ChildUpdate + if attribute and values and string.sub(attribute, 1, 1) ~= '_' then + Manager:SetAttribute('setframe', frame) + Manager:SetAttribute('setstate', attribute .. ' ' .. values) + end +end + +-- Unregister a frame from the state driver manager. +function UnregisterAttributeDriver(frame, attribute) + if attribute then + Manager:SetAttribute('setframe', frame) + Manager:SetAttribute('setstate', attribute) + else + Manager:SetAttribute('delframe', frame) + end +end + +-- Bridge functions for compatibility +function RegisterStateDriver(frame, state, values) + return RegisterAttributeDriver(frame, 'state-' .. state, values) +end + +function UnregisterStateDriver(frame, state) + return UnregisterAttributeDriver(frame, 'state-' .. state) +end + +-- Register a frame to be notified when a unit's existence changes, the +-- unit is obtained from the frame's attributes. If asState is true then +-- notification is via the 'state-unitexists' attribute with values +-- true and false. Otherwise it's via :Show() and :Hide() +function RegisterUnitWatch(frame, asState) + if asState then + Manager:SetAttribute('addwatchstate', frame) + else + Manager:SetAttribute('addwatch', frame) + end +end + +-- Unregister a frame from the unit existence monitor. +function UnregisterUnitWatch(frame) + SecureStateDriverManager:SetAttribute('removewatch', frame) +end + +-- +-- Private implementation +-- +local secureAttributeDrivers = {} +local unitExistsWatchers = {} +local unitExistsCache = setmetatable( + {}, + { __index = function(t,k) + local v = UnitExists(k) or false + t[k] = v + return v + end +}) +local STATE_DRIVER_UPDATE_THROTTLE = 0.1 +local timer = 0 + +local wipe = table.wipe + +-- Check to see if a frame is registered +function UnitWatchRegistered(frame) + return not (unitExistsWatchers[frame] == nil) +end + +local function SecureStateDriverManager_UpdateUnitWatch(frame, doState) + -- Not really so secure, eh? + local unit = frame:GetAttribute('unit') + local exists = (unit and unitExistsCache[unit]) + if doState then + local attr = exists or false + if frame:GetAttribute('state-unitexists') ~= attr then + frame:SetAttribute('state-unitexists', attr) + end + else + if exists then + frame:Show() + frame:SetAttribute('statehidden', nil) + else + frame:Hide() + frame:SetAttribute('statehidden', true) + end + end +end + +local pairs = pairs + +-- consolidate duplicated code for footprint and maintainability +local function resolveDriver(frame, attribute, values) + local newValue = SecureCmdOptionParse(values) + + if attribute == 'state-visibility' then + if newValue == 'show' then + frame:Show() + frame:SetAttribute('statehidden', nil) + elseif newValue == 'hide' then + frame:Hide() + frame:SetAttribute('statehidden', true) + end + elseif newValue then + if newValue == 'nil' then + newValue = nil + else + newValue = tonumber(newValue) or newValue + end + local oldValue = frame:GetAttribute(attribute) + if newValue ~= oldValue then + frame:SetAttribute(attribute, newValue) + local onState = frame:GetAttribute('_on' .. attribute) + if onState then + onState(frame, attribute, newValue) + end + end + end +end + +local function OnUpdate() + local self, elapsed = this, arg1 + + timer = timer - elapsed + if timer <= 0 then + timer = STATE_DRIVER_UPDATE_THROTTLE + + -- Handle state driver updates + for frame, drivers in next, secureAttributeDrivers do + for attribute, values in next, drivers do + resolveDriver(frame, attribute, values) + end + end + + -- Handle unit existence changes + wipe(unitExistsCache) + for k in next, unitExistsCache do + unitExistsCache[k] = nil + end + for frame, doState in next, unitExistsWatchers do + SecureStateDriverManager_UpdateUnitWatch(frame, doState) + end + end +end + +local function OnEvent() + local self, event = this, arg1 + + timer = 0 +end + +local function OnAttributeChanged(self, name, value) + if not value then + return + end + + if name == 'setframe' then + if not secureAttributeDrivers[value] then + secureAttributeDrivers[value] = {} + end + SecureStateDriverManager:Show() + elseif name == 'delframe' then + secureAttributeDrivers[value] = nil + elseif name == 'setstate' then + local frame = self:GetAttribute('setframe') + local attribute, values = string.match(value, '^(%S+)%s*(.*)$') + + if values == '' then + secureAttributeDrivers[frame][attribute] = nil + else + secureAttributeDrivers[frame][attribute] = values + resolveDriver(frame, attribute, values) + end + -- Two frames registering with identical setstate fails unless the value + -- is reset afterwards + self:SetAttribute('setstate', nil) + elseif name == 'addwatch' or name == 'addwatchstate' then + local doState = (name == 'addwatchstate') + unitExistsWatchers[value] = doState + SecureStateDriverManager:Show() + SecureStateDriverManager_UpdateUnitWatch(value, doState) + elseif name == 'removewatch' then + unitExistsWatchers[value] = nil + elseif name == 'updatetime' then + STATE_DRIVER_UPDATE_THROTTLE = value + end +end + + +Manager = SD:New('Manager') +Manager:SetScript('OnUpdate', OnUpdate) +Manager:SetScript('OnEvent', OnEvent) +Manager:SetScript('OnAttributeChanged', OnAttributeChanged) + +-- Events that trigger early rescans +Manager:RegisterEvent('MODIFIER_STATE_CHANGED') +Manager:RegisterEvent('ACTIONBAR_PAGE_CHANGED') +Manager:RegisterEvent('UPDATE_BONUS_ACTIONBAR') +Manager:RegisterEvent('PLAYER_ENTERING_WORLD') +Manager:RegisterEvent('UPDATE_SHAPESHIFT_FORM') +Manager:RegisterEvent('UPDATE_STEALTH') +Manager:RegisterEvent('PLAYER_TARGET_CHANGED') +Manager:RegisterEvent('PLAYER_FOCUS_CHANGED') +Manager:RegisterEvent('PLAYER_REGEN_DISABLED') +Manager:RegisterEvent('PLAYER_REGEN_ENABLED') +Manager:RegisterEvent('UNIT_PET') +Manager:RegisterEvent('GROUP_ROSTER_UPDATE') +-- Deliberately ignoring mouseover and others' target changes because they change so much + +_G['SecureStateDriverManager'] = Manager \ No newline at end of file diff --git a/ElvUI/Core/Movers.lua b/ElvUI/Core/Movers.lua index 59181ca..f9cf335 100644 --- a/ElvUI/Core/Movers.lua +++ b/ElvUI/Core/Movers.lua @@ -6,6 +6,7 @@ local Sticky = LibStub("LibSimpleSticky-1.0"); local _G = _G local type, unpack, pairs = type, unpack, pairs local format, split, find = string.format, string.split, string.find +local tinsert = table.insert --WoW API / Variables local CreateFrame = CreateFrame @@ -72,7 +73,7 @@ local function CreateMover(parent, name, text, overlay, snapOffset, postdrag, sh end E.CreatedMovers[name].mover = f - E["snapBars"][getn(E["snapBars"]) + 1] = f + tinsert(E["snapBars"], f) local fs = f:CreateFontString(nil, "OVERLAY") E:FontTemplate(fs) diff --git a/ElvUI/Core/StaticPopups.lua b/ElvUI/Core/StaticPopups.lua index 6a7167e..ae27dd7 100644 --- a/ElvUI/Core/StaticPopups.lua +++ b/ElvUI/Core/StaticPopups.lua @@ -25,25 +25,21 @@ E.PopupDialogs["ELVUI_UPDATE_AVAILABLE"] = { OnShow = function() this.editBox:SetAutoFocus(false) this.editBox.width = this.editBox:GetWidth() - this.editBox:SetWidth(220) + E:Width(this.editBox, 220) this.editBox:SetText("https://github.com/ElvUI-Vanilla/ElvUI") this.editBox:HighlightText() - -- ChatEdit_FocusActiveWindow() end, OnHide = function() - this.editBox:SetWidth(this.editBox.width or 50) + E:Width(this.editBox, this.editBox.width or 50) this.editBox.width = nil end, hideOnEscape = 1, button1 = OKAY, - button2 = CLOSE, -- Temporary until further fix OnAccept = E.noop, EditBoxOnEnterPressed = function() - -- ChatEdit_FocusActiveWindow() this:GetParent():Hide() end, EditBoxOnEscapePressed = function() - -- ChatEdit_FocusActiveWindow() this:GetParent():Hide() end, EditBoxOnTextChanged = function() @@ -52,7 +48,6 @@ E.PopupDialogs["ELVUI_UPDATE_AVAILABLE"] = { end this:HighlightText() this:ClearFocus() - -- ChatEdit_FocusActiveWindow() end, OnEditFocusGained = function() this:HighlightText() @@ -63,7 +58,6 @@ E.PopupDialogs["ELVUI_UPDATE_AVAILABLE"] = { E.PopupDialogs["CLIQUE_ADVERT"] = { text = L["Using the healer layout it is highly recommended you download the addon Clique if you wish to have the click-to-heal function."], button1 = YES, - button2 = CLOSE, -- Temporary until further fix OnAccept = E.noop, showAlert = 1 } @@ -127,7 +121,6 @@ E.PopupDialogs["INCOMPATIBLE_ADDON"] = { E.PopupDialogs["PIXELPERFECT_CHANGED"] = { text = L["You have changed the Thin Border Theme option. You will have to complete the installation process to remove any graphical bugs."], button1 = ACCEPT, - button2 = CLOSE, -- Temporary until further fix OnAccept = E.noop, timeout = 0, whileDead = 1, @@ -137,7 +130,6 @@ E.PopupDialogs["PIXELPERFECT_CHANGED"] = { E.PopupDialogs["CONFIGAURA_SET"] = { text = L["Because of the mass confusion caused by the new aura system I've implemented a new step to the installation process. This is optional. If you like how your auras are setup go to the last step and click finished to not be prompted again. If for some reason you are prompted repeatedly please restart your game."], button1 = ACCEPT, - button2 = CLOSE, -- Temporary until further fix OnAccept = E.noop, timeout = 0, whileDead = 1, @@ -235,7 +227,6 @@ E.PopupDialogs["BUY_BANK_SLOT"] = { E.PopupDialogs["CANNOT_BUY_BANK_SLOT"] = { text = L["Can't buy anymore slots!"], button1 = ACCEPT, - button2 = CLOSE, -- Temporary until further fix timeout = 0, whileDead = 1 } @@ -243,7 +234,6 @@ E.PopupDialogs["CANNOT_BUY_BANK_SLOT"] = { E.PopupDialogs["NO_BANK_BAGS"] = { text = L["You must purchase a bank slot first!"], button1 = ACCEPT, - button2 = CLOSE, -- Temporary until further fix timeout = 0, whileDead = 1 } @@ -262,7 +252,6 @@ E.PopupDialogs["RESETUI_CHECK"] = { E.PopupDialogs["HARLEM_SHAKE"] = { text = L["ElvUI needs to perform database optimizations please be patient."], button1 = OKAY, - button2 = CLOSE, -- Temporary until further fix OnAccept = function() if E.isMassiveShaking then E:StopHarlemShake() @@ -278,7 +267,6 @@ E.PopupDialogs["HARLEM_SHAKE"] = { E.PopupDialogs["HELLO_KITTY"] = { text = L["ElvUI needs to perform database optimizations please be patient."], button1 = OKAY, - button2 = CLOSE, -- Temporary until further fix OnAccept = function() E:SetupHelloKitty() end, @@ -645,7 +633,7 @@ function E:StaticPopup_Resize(dialog, which) end if width > maxWidthSoFar then - dialog:SetWidth(width) + E:Width(dialog, width) dialog.maxWidthSoFar = width end @@ -657,7 +645,7 @@ function E:StaticPopup_Resize(dialog, which) end if height > maxHeightSoFar then - dialog:SetHeight(height) + E:Height(dialog, height) dialog.maxHeightSoFar = height end end @@ -773,9 +761,9 @@ function E:StaticPopup_Show(which, text_arg1, text_arg2, data) end editBox:SetText("") if info.editBoxWidth then - editBox:SetWidth(info.editBoxWidth) + E:Width(editBox, info.editBoxWidth) else - editBox:SetWidth(130) + E:Width(editBox, 130) end else editBox:Hide() @@ -804,7 +792,9 @@ function E:StaticPopup_Show(which, text_arg1, text_arg2, data) tinsert(tempButtonLocs, button2) for i = getn(tempButtonLocs), 1, -1 do - tempButtonLocs[i]:SetText(info["button"..i]) + if info["button"..i] then + tempButtonLocs[i]:SetText(info["button"..i]) + end tempButtonLocs[i]:Hide() tempButtonLocs[i]:ClearAllPoints() if not (info["button"..i] and (not info["DisplayButton"..i] or info["DisplayButton"..i](dialog))) then @@ -827,9 +817,9 @@ function E:StaticPopup_Show(which, text_arg1, text_arg2, data) local width = tempButtonLocs[i]:GetTextWidth() if width > 110 then - tempButtonLocs[i]:SetWidth(width + 20) + E:Width(tempButtonLocs[i], width + 20) else - tempButtonLocs[i]:SetWidth(120) + E:Width(tempButtonLocs[i], 120) end tempButtonLocs[i]:Enable() tempButtonLocs[i]:Show() diff --git a/ElvUI/Core/core.lua b/ElvUI/Core/core.lua index cd068c3..c1f41a1 100644 --- a/ElvUI/Core/core.lua +++ b/ElvUI/Core/core.lua @@ -15,7 +15,6 @@ local GetActiveTalentGroup = GetActiveTalentGroup local GetCVar = GetCVar local GetFunctionCPUUsage = GetFunctionCPUUsage local GetTalentTabInfo = GetTalentTabInfo -local InCombatLockdown = InCombatLockdown local IsAddOnLoaded = IsAddOnLoaded local IsInInstance, GetNumPartyMembers, GetNumRaidMembers = IsInInstance, GetNumPartyMembers, GetNumRaidMembers local RequestBattlefieldScoreData = RequestBattlefieldScoreData @@ -28,6 +27,8 @@ local RAID_CLASS_COLORS = RAID_CLASS_COLORS _, E.myclass = UnitClass("player") -- Constants _, E.myrace = UnitRace("player") _, E.myfaction = UnitFactionGroup("player") +-- The E.myfaction may error when in GM mode +E.myfaction = E.myfaction or "Others" E.myname = UnitName("player") E.version = GetAddOnMetadata("ElvUI", "Version") E.myrealm = GetRealmName() @@ -425,9 +426,9 @@ end E.UIParent = CreateFrame("Frame", "ElvUIParent", UIParent) E.UIParent:SetFrameLevel(UIParent:GetFrameLevel()) E.UIParent:SetPoint("CENTER", UIParent, "CENTER") -E.UIParent:SetHeight(UIParent:GetHeight()) -E.UIParent:SetWidth(UIParent:GetWidth()) -E["snapBars"][table.getn(E["snapBars"]) + 1] = E.UIParent +E.UIParent:SetHeight(GetScreenHeight()) +E.UIParent:SetWidth(GetScreenWidth()) +tinsert(E["snapBars"], E.UIParent) E.HiddenFrame = CreateFrame("Frame") E.HiddenFrame:Hide() diff --git a/ElvUI/Core/install.lua b/ElvUI/Core/install.lua index 9b36938..93cf099 100644 --- a/ElvUI/Core/install.lua +++ b/ElvUI/Core/install.lua @@ -558,7 +558,7 @@ function E:SetupLayout(layout, noDataReset) E.db.unitframe.units.arena.castbar.width = 200 end - if(layout == "dpsCaster" or layout == "healer" or (layout == "dpsMelee" and E.myclass == "HUNTER")) then + if layout == "dpsCaster" or layout == "healer" or (layout == "dpsMelee" and E.myclass == "HUNTER") then if not E.db.movers then E.db.movers = {} end E.db.unitframe.units.player.castbar.width = E.PixelMode and 406 or 436 E.db.unitframe.units.player.castbar.height = 28 @@ -664,18 +664,6 @@ local function SetupAuras(style) UF:Configure_AuraBars(frame) end - frame = UF["focus"] - E:CopyTable(E.db.unitframe.units.focus.buffs, P.unitframe.units.focus.buffs) - E:CopyTable(E.db.unitframe.units.focus.debuffs, P.unitframe.units.focus.debuffs) - E:CopyTable(E.db.unitframe.units.focus.aurabar, P.unitframe.units.focus.aurabar) - E.db.unitframe.units.focus.smartAuraDisplay = P.unitframe.units.focus.smartAuraDisplay - - if frame then - UF:Configure_Auras(frame, "Buffs") - UF:Configure_Auras(frame, "Debuffs") - UF:Configure_AuraBars(frame) - end - if not style then E.db.unitframe.units.player.buffs.enable = true E.db.unitframe.units.player.buffs.attachTo = "FRAME" @@ -690,7 +678,7 @@ local function SetupAuras(style) E:GetModule("UnitFrames"):CreateAndUpdateUF("target") end - if(InstallStepComplete) then + if InstallStepComplete then InstallStepComplete.message = L["Auras Set"] InstallStepComplete:Show() end diff --git a/ElvUI/Libraries/LibBase64-1.0/LibBase64-1.0.lua b/ElvUI/Libraries/LibBase64-1.0/LibBase64-1.0.lua index 5d27683..daf2ce8 100644 --- a/ElvUI/Libraries/LibBase64-1.0/LibBase64-1.0.lua +++ b/ElvUI/Libraries/LibBase64-1.0/LibBase64-1.0.lua @@ -16,7 +16,7 @@ local byte = string.byte local LibBase64 = LibStub:NewLibrary("LibBase64-1.0", 1) if not LibBase64 then - return + return end local _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" @@ -25,12 +25,12 @@ local byteToNum = {} local numToChar = {} for i = 1, strlen(_chars) do - charTable[i] = sub(_chars, i, i) + charTable[i] = sub(_chars, i, i) end for i = 1, getn(charTable) do - numToChar[i - 1] = sub(_chars, i, i) - byteToNum[byte(_chars, i)] = i - 1 + numToChar[i - 1] = sub(_chars, i, i) + byteToNum[byte(_chars, i)] = i - 1 end _chars = nil @@ -45,10 +45,10 @@ local plus_byte = byte("+") local slash_byte = byte("/") local equals_byte = byte("=") local whitespace = { - [byte(" ")] = true, - [byte("\t")] = true, - [byte("\n")] = true, - [byte("\r")] = true, + [byte(" ")] = true, + [byte("\t")] = true, + [byte("\n")] = true, + [byte("\r")] = true, } local t = {} @@ -60,27 +60,27 @@ local t = {} -- @usage LibBase64.Encode("Hello, how are you doing today?") == "SGVsbG8sIGhvdyBhcmUgeW91IGRvaW5nIHRvZGF5Pw==" -- @return a Base64-encoded string function LibBase64:Encode(text, maxLineLength, lineEnding) - if type(text) ~= "string" then - error(format("Bad argument #1 to `Encode'. Expected %q, got %q", "string", type(text)), 2) - end + if type(text) ~= "string" then + error(format("Bad argument #1 to `Encode'. Expected %q, got %q", "string", type(text)), 2) + end - if maxLineLength == nil then - -- do nothing - elseif type(maxLineLength) ~= "number" then - error(format("Bad argument #2 to `Encode'. Expected %q or %q, got %q", "number", "nil", type(maxLineLength)), 2) - elseif modf(maxLineLength, 4) ~= 0 then - error(format("Bad argument #2 to `Encode'. Expected a multiple of 4, got %s", maxLineLength), 2) - elseif maxLineLength <= 0 then - error(format("Bad argument #2 to `Encode'. Expected a number > 0, got %s", maxLineLength), 2) - end + if maxLineLength == nil then + -- do nothing + elseif type(maxLineLength) ~= "number" then + error(format("Bad argument #2 to `Encode'. Expected %q or %q, got %q", "number", "nil", type(maxLineLength)), 2) + elseif modf(maxLineLength, 4) ~= 0 then + error(format("Bad argument #2 to `Encode'. Expected a multiple of 4, got %s", maxLineLength), 2) + elseif maxLineLength <= 0 then + error(format("Bad argument #2 to `Encode'. Expected a number > 0, got %s", maxLineLength), 2) + end - if lineEnding == nil then - lineEnding = "\r\n" - elseif type(lineEnding) ~= "string" then - error(format("Bad argument #3 to `Encode'. Expected %q, got %q", "string", type(lineEnding)), 2) - end + if lineEnding == nil then + lineEnding = "\r\n" + elseif type(lineEnding) ~= "string" then + error(format("Bad argument #3 to `Encode'. Expected %q, got %q", "string", type(lineEnding)), 2) + end - local currentLength = 0 + local currentLength = 0 for i = 1, getn(text), 3 do local a, b, c = byte(text, i, i+2) @@ -116,7 +116,7 @@ function LibBase64:Encode(text, maxLineLength, lineEnding) currentLength = currentLength + 4 if maxLineLength and modf(currentLength, maxLineLength) == 0 then - t[getn(t)+1] = lineEnding + t[getn(t)+1] = lineEnding end end @@ -136,29 +136,29 @@ local t2 = {} -- @usage LibBase64.Encode("SGVsbG8sIGhvdyBhcmUgeW91IGRvaW5nIHRvZGF5Pw==") == "Hello, how are you doing today?" -- @return a bytestring function LibBase64:Decode(text) - if type(text) ~= "string" then - error(format("Bad argument #1 to `Decode'. Expected %q, got %q", "string", type(text)), 2) - end + if type(text) ~= "string" then + error(format("Bad argument #1 to `Decode'. Expected %q, got %q", "string", type(text)), 2) + end - for i = 1, getn(text) do - local byte = byte(text, i) - if whitespace[byte] or byte == equals_byte then - -- do nothing - else - local num = byteToNum[byte] - if not num then - for i = 1, getn(t2) do - t2[k] = nil - end + for i = 1, getn(text) do + local byte = byte(text, i) + if whitespace[byte] or byte == equals_byte then + -- do nothing + else + local num = byteToNum[byte] + if not num then + for i = 1, getn(t2) do + t2[k] = nil + end - error(format("Bad argument #1 to `Decode'. Received an invalid char: %q", sub(text, i, i)), 2) - end - t2[getn(t2)+1] = num - end - end + error(format("Bad argument #1 to `Decode'. Received an invalid char: %q", sub(text, i, i)), 2) + end + t2[getn(t2)+1] = num + end + end - for i = 1, getn(t2), 4 do - local a, b, c, d = t2[i], t2[i+1], t2[i+2], t2[i+3] + for i = 1, getn(t2), 4 do + local a, b, c, d = t2[i], t2[i+1], t2[i+2], t2[i+3] local nilNum = 0 if not c then diff --git a/ElvUI/Libraries/LibCompress/LibCompress.lua b/ElvUI/Libraries/LibCompress/LibCompress.lua index 5f14835..ebd1f08 100644 --- a/ElvUI/Libraries/LibCompress/LibCompress.lua +++ b/ElvUI/Libraries/LibCompress/LibCompress.lua @@ -137,7 +137,7 @@ function LibCompress:TableToString(t) if t == nil then return nil end if type(t)=="string" then return t end local cache={} - local function sub_mod(t) + local function sub_mod(t) if (type(t)=="table") then for pos,val in pairs(t) do if (type(val)=="table") then @@ -153,8 +153,8 @@ function LibCompress:TableToString(t) else table_insert(cache, tostring(t)) end - end - sub_mod(t) + end + sub_mod(t) return table_concat(cache, ",") -- ? maybe use a different delimiter end @@ -784,10 +784,10 @@ function LibCompress:Compress(data) n = compression_methods[method](self, data) nTable = {} for i = 1, strlen(n) do - nTable[i] = string.sub(n, i, i) + nTable[i] = string.sub(n, i, i) end for i = 1, strlen(result) do - rTable[i] = string.sub(result, i, i) + rTable[i] = string.sub(result, i, i) end if getn(nTable) < getn(rTable) then result = nTable diff --git a/ElvUI/Libraries/LibItemSearch-1.2/CustomSearch-1.0/CustomSearch-1.0.lua b/ElvUI/Libraries/LibItemSearch-1.2/CustomSearch-1.0/CustomSearch-1.0.lua index 610654e..09d2502 100644 --- a/ElvUI/Libraries/LibItemSearch-1.2/CustomSearch-1.0/CustomSearch-1.0.lua +++ b/ElvUI/Libraries/LibItemSearch-1.2/CustomSearch-1.0/CustomSearch-1.0.lua @@ -39,7 +39,7 @@ end function Lib:MatchAll(search) for phrase in gmatch(self:Clean(search), '[^&]+') do if not self:MatchAny(phrase) then - return + return end end @@ -49,7 +49,7 @@ end function Lib:MatchAny(search) for phrase in gmatch(search, '[^|]+') do if self:Match(phrase) then - return true + return true end end end diff --git a/ElvUI/Libraries/LibItemSearch-1.2/LibItemSearch-1.2.lua b/ElvUI/Libraries/LibItemSearch-1.2/LibItemSearch-1.2.lua index 34a7d75..3896aa6 100644 --- a/ElvUI/Libraries/LibItemSearch-1.2/LibItemSearch-1.2.lua +++ b/ElvUI/Libraries/LibItemSearch-1.2/LibItemSearch-1.2.lua @@ -161,10 +161,10 @@ local escapes = { } local function CleanString(str) - for k, v in pairs(escapes) do - str = string.gsub(str, k, v) - end - return str + for k, v in pairs(escapes) do + str = string.gsub(str, k, v) + end + return str end Lib.Filters.tipPhrases = { @@ -203,9 +203,9 @@ Lib.Filters.tipPhrases = { cache = setmetatable({}, {__index = function(t, k) local v = {} t[k] = v return v end}), keywords = { - [lower(ITEM_SOULBOUND)] = ITEM_BIND_ON_PICKUP, - ["bound"] = ITEM_BIND_ON_PICKUP, - ["bop"] = ITEM_BIND_ON_PICKUP, + [lower(ITEM_SOULBOUND)] = ITEM_BIND_ON_PICKUP, + ["bound"] = ITEM_BIND_ON_PICKUP, + ["bop"] = ITEM_BIND_ON_PICKUP, ["boe"] = ITEM_BIND_ON_EQUIP, ["bou"] = ITEM_BIND_ON_USE } diff --git a/ElvUI/Libraries/LibSimpleSticky/LibSimpleSticky.lua b/ElvUI/Libraries/LibSimpleSticky/LibSimpleSticky.lua index f05295d..f7dfe6c 100644 --- a/ElvUI/Libraries/LibSimpleSticky/LibSimpleSticky.lua +++ b/ElvUI/Libraries/LibSimpleSticky/LibSimpleSticky.lua @@ -24,6 +24,8 @@ local StickyFrames, oldminor = LibStub:NewLibrary(MAJOR, MINOR) if not StickyFrames then return end +local ipairs = ipairs + --[[--------------------------------------------------------------------------------- Class declaration, along with a temporary table to hold any existing OnUpdate scripts. @@ -134,8 +136,7 @@ function StickyFrames:GetUpdateFunc(frame, frameList, xoffset, yoffset, left, to frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x+xoffset, y+yoffset) StickyFrames.sticky[frame] = nil - for i = 1, table.getn(frameList) do - local v = frameList[i] + for i, v in ipairs(frameList) do if frame ~= v and frame ~= v:GetParent() and not IsShiftKeyDown() and v:IsVisible() then if self:SnapFrame(frame, v, left, top, right, bottom) then StickyFrames.sticky[frame] = v diff --git a/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua b/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua index da3897f..0b22af2 100644 --- a/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua +++ b/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua @@ -232,8 +232,8 @@ function L_UIDropDownMenu_CreateFrames(level, index) newList:SetWidth(180) newList:SetHeight(10) - --Allow closing with escape - tinsert(UIMenus, "L_DropDownList"..L_UIDROPDOWNMENU_MAXLEVELS) + --Allow closing with escape + tinsert(UIMenus, "L_DropDownList"..L_UIDROPDOWNMENU_MAXLEVELS) for i=L_UIDROPDOWNMENU_MINBUTTONS+1, L_UIDROPDOWNMENU_MAXBUTTONS do local newButton = CreateFrame("Button", "L_DropDownList"..L_UIDROPDOWNMENU_MAXLEVELS.."Button"..i, newList, "L_UIDropDownMenuButtonTemplate"); @@ -292,9 +292,9 @@ function L_UIDropDownMenu_AddButton(info, level) local index = listFrame and (listFrame.numButtons + 1) or 1; local width; - --UIDropDownMenuDelegate:SetAttribute("createframes-level", level); - --UIDropDownMenuDelegate:SetAttribute("createframes-index", index); - --UIDropDownMenuDelegate:SetAttribute("createframes", true); + UIDropDownMenuDelegate:SetAttribute("createframes-level", level); + UIDropDownMenuDelegate:SetAttribute("createframes-index", index); + UIDropDownMenuDelegate:SetAttribute("createframes", true); listFrame = listFrame or _G["L_DropDownList"..level]; local listFrameName = listFrame:GetName(); @@ -789,9 +789,9 @@ function L_ToggleDropDownMenu(level, value, dropDownFrame, anchorName, xOffset, level = 1; end - --UIDropDownMenuDelegate:SetAttribute("createframes-level", level); - --UIDropDownMenuDelegate:SetAttribute("createframes-index", 0); - --UIDropDownMenuDelegate:SetAttribute("createframes", true); + UIDropDownMenuDelegate:SetAttribute("createframes-level", level); + UIDropDownMenuDelegate:SetAttribute("createframes-index", 0); + UIDropDownMenuDelegate:SetAttribute("createframes", true); L_UIDROPDOWNMENU_MENU_LEVEL = level; L_UIDROPDOWNMENU_MENU_VALUE = value; local listFrame = _G["L_DropDownList"..level]; diff --git a/ElvUI/Libraries/LibWho-2.0/LibWho-2.0.lua b/ElvUI/Libraries/LibWho-2.0/LibWho-2.0.lua index 60c2f2a..e7237f3 100644 --- a/ElvUI/Libraries/LibWho-2.0/LibWho-2.0.lua +++ b/ElvUI/Libraries/LibWho-2.0/LibWho-2.0.lua @@ -139,9 +139,9 @@ local queue_quiet = { lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1 function lib:Reset() - self.Queue = {[1]={}, [2]={}, [3]={}} - self.Cache = {} - self.CacheQueue = {} + self.Queue = {[1]={}, [2]={}, [3]={}} + self.Cache = {} + self.CacheQueue = {} end function lib.Who(defhandler, query, opts) @@ -169,10 +169,10 @@ function lib.UserInfo(defhandler, name, opts) local self, args, usage = lib, {}, 'UserInfo(name, [opts])' local now = time() - name = self:CheckArgument(usage, 'name', 'string', name) - if strlen(name) == 0 then return end + name = self:CheckArgument(usage, 'name', 'string', name) + if strlen(name) == 0 then return end - if string.find(name, "%-") then --[[dbg("ignoring xrealm: "..name)]] return end + if string.find(name, "%-") then --[[dbg("ignoring xrealm: "..name)]] return end args.name = self:CapitalizeInitial(name) opts = self:CheckArgument(usage, 'opts', 'table', opts, {}) @@ -218,27 +218,27 @@ function lib.UserInfo(defhandler, name, opts) return nil end if (GetLocale() == "ruRU") then -- in ruRU with n- not show information about player in WIM addon - if args.name and strlen(args.name) > 0 then - local query = 'и-"' .. args.name .. '"' - cachedName.inqueue = true - if(args.callback ~= nil)then - tinsert(cachedName.callback, args) - end - self.CacheQueue[query] = args.name - dbg('Info(' .. args.name ..') added to queue') - self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } ) - end + if args.name and strlen(args.name) > 0 then + local query = 'и-"' .. args.name .. '"' + cachedName.inqueue = true + if(args.callback ~= nil)then + tinsert(cachedName.callback, args) + end + self.CacheQueue[query] = args.name + dbg('Info(' .. args.name ..') added to queue') + self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } ) + end else - if args.name and strlen(args.name) > 0 then - local query = 'n-"' .. args.name .. '"' - cachedName.inqueue = true - if(args.callback ~= nil)then - tinsert(cachedName.callback, args) - end - self.CacheQueue[query] = args.name - dbg('Info(' .. args.name ..') added to queue') - self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } ) - end + if args.name and strlen(args.name) > 0 then + local query = 'n-"' .. args.name .. '"' + cachedName.inqueue = true + if(args.callback ~= nil)then + tinsert(cachedName.callback, args) + end + self.CacheQueue[query] = args.name + dbg('Info(' .. args.name ..') added to queue') + self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } ) + end end return nil end @@ -256,11 +256,11 @@ function lib.CachedUserInfo(_, name) end function lib.GetWhoLibDebug(_, mode) - return lib.Debug + return lib.Debug end function lib.SetWhoLibDebug(_, mode) - lib.Debug = mode + lib.Debug = mode dbg = mode and dbgfunc or NOP end @@ -298,12 +298,12 @@ end --- function lib:AllQueuesEmpty() - local queueCount = getn(self.Queue[1]) + getn(self.Queue[2]) + getn(self.Queue[3]) + getn(self.CacheQueue) + local queueCount = getn(self.Queue[1]) + getn(self.Queue[2]) + getn(self.Queue[3]) + getn(self.CacheQueue) - -- Be sure that we have cleared the in-progress status - if self.WhoInProgress then - queueCount = queueCount + 1 - end + -- Be sure that we have cleared the in-progress status + if self.WhoInProgress then + queueCount = queueCount + 1 + end return queueCount == 0 end @@ -344,19 +344,19 @@ local INSTANT_QUERY_MIN_INTERVAL = 60 -- only once every 1 min function lib:UpdateWeights() local weightsum, sum, count = 0, 0, 0 for k,v in pairs(queue_weights) do - sum = sum + v - weightsum = weightsum + v * getn(self.Queue[k]) + sum = sum + v + weightsum = weightsum + v * getn(self.Queue[k]) end if weightsum == 0 then - for k,v in pairs(queue_weights) do queue_bounds[k] = v end - return + for k,v in pairs(queue_weights) do queue_bounds[k] = v end + return end local adjust = sum / weightsum for k,v in pairs(queue_bounds) do - queue_bounds[k] = queue_weights[k] * adjust * getn(self.Queue[k]) + queue_bounds[k] = queue_weights[k] * adjust * getn(self.Queue[k]) end end @@ -376,17 +376,17 @@ function lib:GetNextFromScheduler() local n,i = math.random(),0 repeat - i=i+1 - n = n - queue_bounds[i] + i=i+1 + n = n - queue_bounds[i] until i >= getn(self.Queue) or n <= 0 dbg(string.format("Q=%d, bound=%d", i, queue_bounds[i])) if getn(self.Queue[i]) > 0 then - dbg(string.format("Q=%d, bound=%d", i, queue_bounds[i])) - return i, self.Queue[i] + dbg(string.format("Q=%d, bound=%d", i, queue_bounds[i])) + return i, self.Queue[i] else - dbg("Queues empty, waiting") + dbg("Queues empty, waiting") end end @@ -424,10 +424,10 @@ function lib:AskWhoNext() self.WhoInProgress = false local v,k,args = nil - local kludge = 10 + local kludge = 10 repeat - k, v = self:GetNextFromScheduler() - if not k then break end + k, v = self:GetNextFromScheduler() + if not k then break end if WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET then break end @@ -435,7 +435,7 @@ function lib:AskWhoNext() args = tremove(v, 1) break end - kludge = kludge - 1 + kludge = kludge - 1 until kludge <= 0 if args then @@ -453,9 +453,9 @@ function lib:AskWhoNext() self.Quiet = false if args.whotoui then - -- self.hooked.SetWhoToUI(args.whotoui) - else - -- self.hooked.SetWhoToUI(args.gui and true or false) + -- self.hooked.SetWhoToUI(args.whotoui) + else + -- self.hooked.SetWhoToUI(args.gui and true or false) end else -- self.hooked.SetWhoToUI(true) @@ -469,11 +469,11 @@ function lib:AskWhoNext() self.WhoInProgress = false end - -- Keep processing the who queue if there is more work + -- Keep processing the who queue if there is more work if not self:AllQueuesEmpty() then self:AskWhoNextIn5sec() - else - dbg("*** Done processing requests ***") + else + dbg("*** Done processing requests ***") end end @@ -486,10 +486,10 @@ function lib:AskWho(args) end function lib:ReturnWho() - if not self.Args then - self.Quiet = nil - return - end + if not self.Args then + self.Quiet = nil + return + end if(self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING)then self.Quiet = nil @@ -723,7 +723,7 @@ end local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)" function lib:CapitalizeInitial(name) - return string.gsub(name, MULTIBYTE_FIRST_CHAR, string.upper, 1) + return string.gsub(name, MULTIBYTE_FIRST_CHAR, string.upper, 1) end --- @@ -736,7 +736,7 @@ lib.PossibleEvents = { } function lib:TriggerEvent(...) - callbacks:Fire(event, unpack(arg)) + callbacks:Fire(event, unpack(arg)) end --- @@ -761,7 +761,7 @@ SlashCmdList['WHOLIB_DEBUG'] = function() -- /wholibdebug: toggle debug on/off local self = lib - self:SetWhoLibDebug(not self.Debug) + self:SetWhoLibDebug(not self.Debug) end SLASH_WHOLIB_DEBUG1 = '/wholibdebug' @@ -889,12 +889,12 @@ end FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE") function lib:WHO_LIST_UPDATE() - if not lib.Quiet then + if not lib.Quiet then WhoList_Update() - FriendsFrame_Update() - end + FriendsFrame_Update() + end - lib:ProcessWhoResults() + lib:ProcessWhoResults() end function lib:ProcessWhoResults() diff --git a/ElvUI/Libraries/Load_Libraries.xml b/ElvUI/Libraries/Load_Libraries.xml index 4b9c2ae..ea430d1 100644 --- a/ElvUI/Libraries/Load_Libraries.xml +++ b/ElvUI/Libraries/Load_Libraries.xml @@ -17,6 +17,7 @@ + diff --git a/ElvUI/Libraries/oUF/elements/auras.lua b/ElvUI/Libraries/oUF/elements/auras.lua index e8f834b..1c2c991 100644 --- a/ElvUI/Libraries/oUF/elements/auras.lua +++ b/ElvUI/Libraries/oUF/elements/auras.lua @@ -16,7 +16,6 @@ At least one of the above widgets must be present for the element to work. ## Options .disableMouse - Disables mouse events (boolean) -.disableCooldown - Disables the cooldown spiral (boolean) .size - Aura icon size. Defaults to 16 (number) .spacing - Spacing between each icon. Defaults to 0 (number) .['spacing-x'] - Horizontal spacing between each icon. Takes priority over `spacing` (number) @@ -64,18 +63,26 @@ button.isDebuff - indicates if the button holds a debuff (boolean) local ns = oUF local oUF = ns.oUF -local tinsert = table.insert -local floor = math.floor +local tinsert, getn = table.insert, table.getn +local floor, min, mod = math.floor, math.min, math.mod local CreateFrame = CreateFrame local GetTime = GetTime local UnitAura = UnitAura +local GetPlayerBuff = GetPlayerBuff +local GetPlayerBuffTexture = GetPlayerBuffTexture +local GetPlayerBuffApplications = GetPlayerBuffApplications +local GetPlayerBuffDispelType = GetPlayerBuffDispelType +local GetPlayerBuffTimeLeft = GetPlayerBuffTimeLeft local VISIBLE = 1 local HIDDEN = 0 local function UpdateTooltip(self) - if self.filter == 'HELPFUL' then + if self:GetParent().__owner.unit == "player" then + local index = GetPlayerBuff(self:GetID() - 1, self.filter) + GameTooltip:SetPlayerBuff(index) + elseif self.filter == 'HELPFUL' then GameTooltip:SetUnitBuff(self:GetParent().__owner.unit, self:GetID(), self.filter) else GameTooltip:SetUnitDebuff(self:GetParent().__owner.unit, self:GetID(), self.filter) @@ -83,7 +90,7 @@ local function UpdateTooltip(self) end local function onEnter(self) - if(not self:IsVisible()) then return end + if not self:IsVisible() then return end GameTooltip:SetOwner(self, 'ANCHOR_BOTTOMRIGHT') self:UpdateTooltip() @@ -97,9 +104,6 @@ local function createAuraIcon(element, index) local button = CreateFrame('Button', '$parentButton' .. index, element) button:RegisterForClicks('RightButtonUp') - local cd = CreateFrame('Cooldown', '$parentCooldown', button, 'oUF_CooldownFrameTemplate') - cd:SetAllPoints() - local icon = button:CreateTexture(nil, 'BORDER') icon:SetAllPoints() @@ -113,12 +117,11 @@ local function createAuraIcon(element, index) button.overlay = overlay button.UpdateTooltip = UpdateTooltip - button:SetScript('OnEnter', onEnter) + button:SetScript('OnEnter', function() onEnter(this) end) button:SetScript('OnLeave', onLeave) button.icon = icon button.count = count - button.cd = cd --[[ Callback: Auras:PostCreateIcon(button) Called after a new aura button has been created. @@ -126,29 +129,39 @@ local function createAuraIcon(element, index) * self - the widget holding the aura buttons * button - the newly created aura button (Button) --]] - if(element.PostCreateIcon) then element:PostCreateIcon(button) end + if element.PostCreateIcon then element:PostCreateIcon(button) end return button end -local function customFilter(element, unit, button, name) - if(name) then - return true - end +local function customFilter(element, unit, button, texture) + if texture then return true end end local function updateIcon(element, unit, index, offset, filter, isDebuff, visible) - local name, rank, texture, count, dispelType, duration, expiration = UnitAura(unit, index, filter) + local texture, count, dispelType, duration, expiration - if element.forceShow then - name, rank, texture = GetSpellInfo(26993) - count, dispelType, duration, expiration = 5, 'Magic', 0, 60 + if unit == "player" then + local idx = GetPlayerBuff(index - 1, filter) + --if idx < 0 then return end + --index = idx + texture = GetPlayerBuffTexture(idx) + count = GetPlayerBuffApplications(idx) + dispelType = GetPlayerBuffDispelType(idx) + duration = GetPlayerBuffTimeLeft(idx) + else + texture, count, dispelType, duration, expiration = UnitAura(unit, index, filter) end - if(name) then + if element.forceShow then + texture = 'Interface\\Icons\\Spell_Holy_DivineSpirit' + count, dispelType = 5, 'Magic' + end + + if texture then local position = visible + offset + 1 local button = element[position] - if(not button) then + if not button then --[[ Override: Auras:CreateIcon(position) Used to create the aura button at a given position. @@ -182,24 +195,12 @@ local function updateIcon(element, unit, index, offset, filter, isDebuff, visibl --]] local show = true if not element.forceShow then - show = (element.CustomFilter or customFilter) (element, unit, button, name, rank, texture, count, dispelType, duration, expiration) + show = (element.CustomFilter or customFilter) (element, unit, button, texture, count, dispelType, duration, expiration) end - if(show) then - -- We might want to consider delaying the creation of an actual cooldown - -- object to this point, but I think that will just make things needlessly - -- complicated. - if(button.cd and not element.disableCooldown) then - if(duration and duration > 0) then - button.cd:SetCooldown(GetTime() - (duration - expiration), duration) - button.cd:Show() - else - button.cd:Hide() - end - end - - if(button.overlay) then - if((isDebuff and element.showDebuffType) or (not isDebuff and element.showBuffType) or element.showType) then + if show then + if button.overlay then + if (isDebuff and element.showDebuffType) or (not isDebuff and element.showBuffType) or element.showType then local color = DebuffTypeColor[dispelType] or DebuffTypeColor.none button.overlay:SetVertexColor(color.r, color.g, color.b) @@ -209,11 +210,12 @@ local function updateIcon(element, unit, index, offset, filter, isDebuff, visibl end end - if(button.icon) then button.icon:SetTexture(texture) end - if(button.count) then button.count:SetText(count > 1 and count) end + if button.icon then button.icon:SetTexture(texture) end + if button.count then button.count:SetText(count > 1 and count) end local size = element.size or 16 - button:SetSize(size, size) + button:SetWidth(size) + button:SetHeight(size) button:EnableMouse(not element.disableMouse) button:SetID(index) @@ -228,7 +230,7 @@ local function updateIcon(element, unit, index, offset, filter, isDebuff, visibl * index - the index of the aura (number) * position - the actual position of the aura button (number) --]] - if(element.PostUpdateIcon) then + if element.PostUpdateIcon then element:PostUpdateIcon(unit, button, index, position) end @@ -252,7 +254,7 @@ local function SetPosition(element, from, to) -- Bail out if the to range is out of scope. if(not button) then break end - local col = (i - 1) % cols + local col = mod((i - 1), cols) local row = floor((i - 1) / cols) button:ClearAllPoints() @@ -261,25 +263,25 @@ local function SetPosition(element, from, to) end local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontHide) - if(not offset) then offset = 0 end + if not offset then offset = 0 end local index = 1 local visible = 0 local hidden = 0 - while(visible < limit) do + while visible < limit do local result = updateIcon(element, unit, index, offset, filter, isDebuff, visible) - if(not result) then + if not result then break - elseif(result == VISIBLE) then + elseif result == VISIBLE then visible = visible + 1 - elseif(result == HIDDEN) then + elseif result == HIDDEN then hidden = hidden + 1 end index = index + 1 end - if(not dontHide) then - for i = visible + offset + 1, #element do + if not dontHide then + for i = visible + offset + 1, getn(element) do element[i]:Hide() end end @@ -288,42 +290,43 @@ local function filterIcons(element, unit, filter, limit, isDebuff, offset, dontH end local function UpdateAuras(self, event, unit) - if(self.unit ~= unit) then return end + if event == "PLAYER_AURAS_CHANGED" then unit = "player" end + + if self.unit ~= unit then return end local auras = self.Auras - if(auras) then + if auras then --[[ Callback: Auras:PreUpdate(unit) Called before the element has been updated. * self - the widget holding the aura buttons * unit - the unit for which the update has been triggered (string) --]] - if(auras.PreUpdate) then auras:PreUpdate(unit) end + if auras.PreUpdate then auras:PreUpdate(unit) end local numBuffs = auras.numBuffs or 32 local numDebuffs = auras.numDebuffs or 40 local max = auras.numTotal or numBuffs + numDebuffs - local visibleBuffs, hiddenBuffs = filterIcons(auras, unit, auras.buffFilter or auras.filter or 'HELPFUL', math.min(numBuffs, max), nil, 0, true) + local visibleBuffs, hiddenBuffs = filterIcons(auras, unit, auras.buffFilter or auras.filter or 'HELPFUL', min(numBuffs, max), nil, 0, true) local hasGap - if(visibleBuffs ~= 0 and auras.gap) then + if visibleBuffs ~= 0 and auras.gap then hasGap = true visibleBuffs = visibleBuffs + 1 local button = auras[visibleBuffs] - if(not button) then + if not button then button = (auras.CreateIcon or createAuraIcon) (auras, visibleBuffs) tinsert(auras, button) auras.createdIcons = auras.createdIcons + 1 end -- Prevent the button from displaying anything. - if(button.cd) then button.cd:Hide() end - if(button.icon) then button.icon:SetTexture() end - if(button.overlay) then button.overlay:Hide() end - if(button.stealable) then button.stealable:Hide() end - if(button.count) then button.count:SetText() end + if button.icon then button.icon:SetTexture() end + if button.overlay then button.overlay:Hide() end + if button.stealable then button.stealable:Hide() end + if button.count then button.count:SetText() end button:EnableMouse(false) button:Show() @@ -341,10 +344,10 @@ local function UpdateAuras(self, event, unit) end end - local visibleDebuffs, hiddenDebuffs = filterIcons(auras, unit, auras.debuffFilter or auras.filter or 'HARMFUL', math.min(numDebuffs, max - visibleBuffs), true, visibleBuffs) + local visibleDebuffs, hiddenDebuffs = filterIcons(auras, unit, auras.debuffFilter or auras.filter or 'HARMFUL', min(numDebuffs, max - visibleBuffs), true, visibleBuffs) auras.visibleDebuffs = visibleDebuffs - if(hasGap and visibleDebuffs == 0) then + if hasGap and visibleDebuffs == 0 then auras[visibleBuffs]:Hide() visibleBuffs = visibleBuffs - 1 end @@ -364,11 +367,11 @@ local function UpdateAuras(self, event, unit) * from - the offset of the first aura button to be (re-)anchored (number) * to - the offset of the last aura button to be (re-)anchored (number) --]] - if(auras.PreSetPosition) then + if auras.PreSetPosition then fromRange, toRange = auras:PreSetPosition(max) end - if(fromRange or auras.createdIcons > auras.anchoredIcons) then + if fromRange or auras.createdIcons > auras.anchoredIcons then --[[ Override: Auras:SetPosition(from, to) Used to (re-)anchor the aura buttons. Called when new aura buttons have been created or if :PreSetPosition is defined. @@ -387,72 +390,72 @@ local function UpdateAuras(self, event, unit) * self - the widget holding the aura buttons * unit - the unit for which the update has been triggered (string) --]] - if(auras.PostUpdate) then auras:PostUpdate(unit) 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 + if buffs then + if buffs.PreUpdate then buffs:PreUpdate(unit) end local numBuffs = buffs.num or 32 local visibleBuffs, hiddenBuffs = filterIcons(buffs, unit, buffs.filter or 'HELPFUL', numBuffs) buffs.visibleBuffs = visibleBuffs local fromRange, toRange - if(buffs.PreSetPosition) then + if buffs.PreSetPosition then fromRange, toRange = buffs:PreSetPosition(numBuffs) end - if(fromRange or buffs.createdIcons > buffs.anchoredIcons) then + 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 + if buffs.PostUpdate then buffs:PostUpdate(unit) end end local debuffs = self.Debuffs - if(debuffs) then - if(debuffs.PreUpdate) then debuffs:PreUpdate(unit) end + if debuffs then + if debuffs.PreUpdate then debuffs:PreUpdate(unit) end local numDebuffs = debuffs.num or 40 local visibleDebuffs, hiddenDebuffs = filterIcons(debuffs, unit, debuffs.filter or 'HARMFUL', numDebuffs, true) debuffs.visibleDebuffs = visibleDebuffs local fromRange, toRange - if(debuffs.PreSetPosition) then + if debuffs.PreSetPosition then fromRange, toRange = debuffs:PreSetPosition(numDebuffs) end - if(fromRange or debuffs.createdIcons > debuffs.anchoredIcons) then + 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 + if debuffs.PostUpdate then debuffs:PostUpdate(unit) end end end local function Update(self, event, unit) - if(self.unit ~= unit) then return end + 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 + if event == 'ForceUpdate' or not event then local buffs = self.Buffs - if(buffs) then + if buffs then (buffs.SetPosition or SetPosition) (buffs, 1, buffs.createdIcons) end local debuffs = self.Debuffs - if(debuffs) then + if debuffs then (debuffs.SetPosition or SetPosition) (debuffs, 1, debuffs.createdIcons) end local auras = self.Auras - if(auras) then + if auras then (auras.SetPosition or SetPosition) (auras, 1, auras.createdIcons) end end @@ -463,11 +466,12 @@ local function ForceUpdate(element) end local function Enable(self) - if(self.Buffs or self.Debuffs or self.Auras) then + if self.Buffs or self.Debuffs or self.Auras then + self:RegisterEvent('PLAYER_AURAS_CHANGED', UpdateAuras) self:RegisterEvent('UNIT_AURA', UpdateAuras) local buffs = self.Buffs - if(buffs) then + if buffs then buffs.__owner = self buffs.ForceUpdate = ForceUpdate @@ -478,7 +482,7 @@ local function Enable(self) end local debuffs = self.Debuffs - if(debuffs) then + if debuffs then debuffs.__owner = self debuffs.ForceUpdate = ForceUpdate @@ -489,7 +493,7 @@ local function Enable(self) end local auras = self.Auras - if(auras) then + if auras then auras.__owner = self auras.ForceUpdate = ForceUpdate @@ -504,13 +508,14 @@ local function Enable(self) end local function Disable(self) - if(self.Buffs or self.Debuffs or self.Auras) then + if self.Buffs or self.Debuffs or self.Auras then + self:UnregisterEvent('PLAYER_AURAS_CHANGED', UpdateAuras) self:UnregisterEvent('UNIT_AURA', UpdateAuras) - if(self.Buffs) then self.Buffs:Hide() end - if(self.Debuffs) then self.Debuffs:Hide() end - if(self.Auras) then self.Auras:Hide() end + if self.Buffs then self.Buffs:Hide() end + if self.Debuffs then self.Debuffs:Hide() end + if self.Auras then self.Auras:Hide() end end end -oUF:AddElement('Auras', Update, Enable, Disable) \ No newline at end of file +oUF:AddElement('Auras', Update, Enable, Disable) diff --git a/ElvUI/Libraries/oUF/elements/castbar.lua b/ElvUI/Libraries/oUF/elements/castbar.lua index 3e1af3e..297c377 100644 --- a/ElvUI/Libraries/oUF/elements/castbar.lua +++ b/ElvUI/Libraries/oUF/elements/castbar.lua @@ -11,9 +11,7 @@ Castbar - A `StatusBar` to represent spell cast/channel progress. ## Sub-Widgets .Text - A `FontString` to represent spell name. -.Icon - A `Texture` to represent spell icon. .Time - A `FontString` to represent spell duration. -.SafeZone - A `Texture` to represent latency. ## Notes @@ -52,138 +50,80 @@ A default texture will be applied to the StatusBar and Texture widgets if they d Text:SetPoint("LEFT", Castbar) -- Add spell icon - local Icon = Castbar:CreateTexture(nil, "OVERLAY") + local Icon = Castbar:CreateTexture(nil, 'OVERLAY') Icon:SetSize(20, 20) - Icon:SetPoint("TOPLEFT", Castbar, "TOPLEFT") - - -- Add safezone - local SafeZone = Castbar:CreateTexture(nil, "OVERLAY") + Icon:SetPoint('TOPLEFT', Castbar, 'TOPLEFT') -- Register it with oUF Castbar.bg = Background Castbar.Spark = Spark Castbar.Time = Time Castbar.Text = Text - Castbar.Icon = Icon - Castbar.SafeZone = SafeZone + Castbar.Icon = Icon self.Castbar = Castbar --]] local ns = oUF local oUF = ns.oUF -local match = string.match - -local GetNetStats = GetNetStats +local GetActionTexture = GetActionTexture +local GetContainerItemInfo = GetContainerItemInfo +local GetSpellTexture = GetSpellTexture local GetTime = GetTime -local UnitCastingInfo = UnitCastingInfo -local UnitChannelInfo = UnitChannelInfo -local UnitIsUnit = UnitIsUnit -local tradeskillCastTime, tradeskillCastDuration, tradeskillCurrent, tradeskillTotal, mergeTradeskill = 0, 0, 0, 0, false +local iconTexture +hooksecurefunc("UseAction", function(id) + iconTexture = GetActionTexture(id) +end) -local function updateSafeZone(self) - local safeZone = self.SafeZone - local width = self:GetWidth() - local _, _, ms = GetNetStats() +hooksecurefunc("CastSpell", function(id, bookType) + iconTexture = GetSpellTexture(id, bookType) +end) - -- Guard against GetNetStats returning latencies of 0. - if(ms ~= 0) then - local safeZoneRatio = (ms / 1e3) / self.max - if(safeZoneRatio > 1) then - safeZoneRatio = 1 - end - safeZone:SetWidth(width * safeZoneRatio) - safeZone:Show() - else - safeZone:Hide() - end -end +hooksecurefunc("UseContainerItem", function(id, index) + iconTexture = GetContainerItemInfo(id, index) +end) -local function UNIT_SPELLCAST_SENT(self, event, unit, spell, rank, target) +local function SPELLCAST_START(self, event, name, endTime) local element = self.Castbar - element.curTarget = (target and target ~= "") and target or nil - - if element.isTradeSkill then - element.tradeSkillCastName = spell - end -end - -local function UNIT_SPELLCAST_START(self, event, unit) - if(self.unit ~= unit and self.realUnit ~= unit) then return end - - local element = self.Castbar - local name, _, text, texture, startTime, endTime, isTradeSkill = UnitCastingInfo(unit) if(not name) then return element:Hide() end - endTime = endTime / 1e3 - startTime = startTime / 1e3 - local max = endTime - startTime - - element.castName = name - element.duration = GetTime() - startTime - element.max = max + endTime = endTime / 1000 + element.startTime = GetTime() + element.duration = element.startTime + element.max = endTime element.delay = 0 element.casting = true element.holdTime = 0 - element.isTradeSkill = isTradeSkill - if(mergeTradeskill and isTradeSkill and UnitIsUnit(unit, "player")) then - element.duration = element.duration + (element.max * tradeskillCurrent) - element.max = max * tradeskillTotal - - if(unit == "player") then - tradeskillCurrent = tradeskillCurrent + 1 - tradeskillCastDuration = element.duration - tradeskillCastTime = max - end - - element:SetValue(element.duration) - else - element:SetValue(0) - end element:SetMinMaxValues(0, element.max) + element:SetValue(0) - if(element.Text) then element.Text:SetText(text) end - if(element.Icon) then element.Icon:SetTexture(texture) end - if(element.Time) then element.Time:SetText() end - - local sf = element.SafeZone - if(sf) then - sf:ClearAllPoints() - sf:SetPoint("RIGHT") - sf:SetPoint("TOP") - sf:SetPoint("BOTTOM") - updateSafeZone(element) + if(element.Text) then element.Text:SetText(name) end + if(element.Icon) then + if(not iconTexture) then iconTexture = "Interface\\Icons\\Ability_Ambush" end + element.Icon:SetTexture(iconTexture) + iconTexture = nil end + if(element.Time) then element.Time:SetText() end --[[ Callback: Castbar:PostCastStart(unit, name) Called after the element has been updated upon a spell cast start. * self - the Castbar widget - * unit - unit for which the update has been triggered (string) * name - name of the spell being cast (string) --]] if(element.PostCastStart) then - element:PostCastStart(unit, name) + element:PostCastStart(name) end element:Show() end -local function UNIT_SPELLCAST_FAILED(self, event, unit, spellname) +local function SPELLCAST_FAILED(self, event) if(not self.casting) then return end - if(self.unit ~= unit and self.realUnit ~= unit) then return end local element = self.Castbar - if(spellname and (element.castName ~= spellname and element.tradeSkillCastName ~= spellname)) then - return - end - - if(mergeTradeskill and UnitIsUnit(unit, "player")) then - mergeTradeskill = false - element.tradeSkillCastName = nil - end local text = element.Text if(text) then @@ -197,40 +137,14 @@ local function UNIT_SPELLCAST_FAILED(self, event, unit, spellname) Called after the element has been updated upon a failed spell cast. * self - the Castbar widget - * unit - unit for which the update has been triggered (string) - * name - name of the failed spell (string) --]] if(element.PostCastFailed) then - return element:PostCastFailed(unit, spellname) + return element:PostCastFailed() end end -local function UNIT_SPELLCAST_FAILED_QUIET(self, event, unit, spellname) - if(not self.casting) then return end - if(self.unit ~= unit and self.realUnit ~= unit) then return end - +local function SPELLCAST_INTERRUPTED(self, event) local element = self.Castbar - if(spellname and (element.castName ~= spellname and element.tradeSkillCastName ~= spellname)) then - return - end - - if(mergeTradeskill and UnitIsUnit(unit, "player")) then - mergeTradeskill = false - element.tradeSkillCastName = nil - end - - element.casting = nil - element:SetValue(0) - element:Hide() -end - -local function UNIT_SPELLCAST_INTERRUPTED(self, event, unit, spellname) - if(self.unit ~= unit and self.realUnit ~= unit) then return end - - local element = self.Castbar - if(spellname and element.castName ~= spellname) then - return - end local text = element.Text if(text) then @@ -245,25 +159,22 @@ local function UNIT_SPELLCAST_INTERRUPTED(self, event, unit, spellname) Called after the element has been updated upon an interrupted spell cast. * self - the Castbar widget - * unit - unit for which the update has been triggered (string) - * name - name of the interrupted spell (string) --]] if(element.PostCastInterrupted) then - return element:PostCastInterrupted(unit, spellname) + return element:PostCastInterrupted() end end -local function UNIT_SPELLCAST_DELAYED(self, event, unit) - if(self.unit ~= unit and self.realUnit ~= unit) then return end - +local function SPELLCAST_DELAYED(self, event, delay) local element = self.Castbar - local name, _, _, _, startTime = UnitCastingInfo(unit) - if(not startTime or not element:IsShown()) then return end + if(not delay or not element:IsShown()) then return end - local duration = GetTime() - (startTime / 1000) + delay = delay / 1000 + local duration = GetTime() - (element.startTime / 1000) if(duration < 0) then duration = 0 end - element.delay = element.delay + element.duration - duration + element.startTime = element.startTime + delay + element.delay = delay element.duration = duration element:SetValue(duration) @@ -272,27 +183,20 @@ local function UNIT_SPELLCAST_DELAYED(self, event, unit) Called after the element has been updated when a spell cast has been delayed. * self - the Castbar widget - * unit - unit that the update has been triggered (string) - * name - name of the delayed spell (string) --]] if(element.PostCastDelayed) then - return element:PostCastDelayed(unit, name) + return element:PostCastDelayed() end end -local function UNIT_SPELLCAST_STOP(self, event, unit, spellname) - if(self.unit ~= unit and self.realUnit ~= unit) then return end - +local function SPELLCAST_STOP(self, event) local element = self.Castbar - if(spellname and (element.castName ~= spellname)) then - return + + if(element.casting or element.channeling) then + iconTexture = nil end - if(mergeTradeskill and UnitIsUnit(unit, "player")) then - if(tradeskillCurrent == tradeskillTotal) then - mergeTradeskill = false - end - else + if(element:IsShown()) then element.casting = nil end @@ -300,34 +204,23 @@ local function UNIT_SPELLCAST_STOP(self, event, unit, spellname) Called after the element has been updated when a spell cast has finished. * self - the Castbar widget - * unit - unit for which the update has been triggered (string) - * name - name of the spell (string) --]] if(element.PostCastStop) then - return element:PostCastStop(unit, spellname) + return element:PostCastStop() end end -local function UNIT_SPELLCAST_CHANNEL_START(self, event, unit) - if(self.unit ~= unit and self.realUnit ~= unit) then return end - +local function SPELLCAST_CHANNEL_START(self, event, endTime, name) local element = self.Castbar - local name, _, _, texture, startTime, endTime = UnitChannelInfo(unit) if(not name) then return end - endTime = endTime / 1e3 - startTime = startTime / 1e3 - local max = (endTime - startTime) - local duration = endTime - GetTime() - - element.duration = duration - element.max = max + endTime = endTime / 1000 + element.startTime = GetTime() + element.duration = element.startTime + endTime + element.max = endTime element.delay = 0 - element.startTime = startTime - element.endTime = endTime - element.extraTickRatio = 0 element.channeling = true element.holdTime = 0 @@ -335,71 +228,54 @@ local function UNIT_SPELLCAST_CHANNEL_START(self, event, unit) -- executed or be fully completed by the OnUpdate handler before CHANNEL_START -- is called. element.casting = nil - element.castName = nil - element:SetMinMaxValues(0, max) - element:SetValue(duration) + element:SetMinMaxValues(0, endTime) + element:SetValue(endTime) if(element.Text) then element.Text:SetText(name) end - if(element.Icon) then element.Icon:SetTexture(texture) end - if(element.Time) then element.Time:SetText() end - - local sf = element.SafeZone - if(sf) then - sf:ClearAllPoints() - sf:SetPoint("LEFT") - sf:SetPoint("TOP") - sf:SetPoint("BOTTOM") - updateSafeZone(element) + if(element.Icon) then + if(not iconTexture) then iconTexture = "Interface\\Icons\\Ability_Ambush" end + element.Icon:SetTexture(iconTexture) + iconTexture = nil end + if(element.Time) then element.Time:SetText() end --[[ Callback: Castbar:PostChannelStart(unit, name) Called after the element has been updated upon a spell channel start. * self - the Castbar widget - * unit - unit for which the update has been triggered (string) * name - name of the channeled spell (string) --]] if(element.PostChannelStart) then - element:PostChannelStart(unit, name) + element:PostChannelStart(name) end element:Show() end -local function UNIT_SPELLCAST_CHANNEL_UPDATE(self, event, unit) - if(self.unit ~= unit and self.realUnit ~= unit) then return end - +local function SPELLCAST_CHANNEL_UPDATE(self, event, delay) local element = self.Castbar - local name, _, _, _, startTime, endTime = UnitChannelInfo(unit) - if(not name or not element:IsShown()) then + if(not element:IsShown()) then return end - local duration = (endTime / 1000) - GetTime() - element.delay = element.delay + element.duration - duration + delay = delay / 1000 + local duration = element.startTime + (element.max - GetTime()) - delay + element.delay = element.delay - duration element.duration = duration - element.max = (endTime - startTime) / 1000 - element.startTime = startTime / 1000 - element.endTime = endTime / 1000 - - element:SetMinMaxValues(0, element.max) + element.startTime = element.startTime - duration element:SetValue(duration) --[[ Callback: Castbar:PostChannelUpdate(unit, name) Called after the element has been updated after a channeled spell has been delayed or interrupted. * self - the Castbar widget - * unit - unit for which the update has been triggered (string) - * name - name of the channeled spell (string) --]] if(element.PostChannelUpdate) then - return element:PostChannelUpdate(unit, name) + return element:PostChannelUpdate() end end -local function UNIT_SPELLCAST_CHANNEL_STOP(self, event, unit, spellname) - if(self.unit ~= unit and self.realUnit ~= unit) then return end - +local function SPELLCAST_CHANNEL_STOP(self, event) local element = self.Castbar if(element:IsShown()) then element.channeling = nil @@ -408,22 +284,20 @@ local function UNIT_SPELLCAST_CHANNEL_STOP(self, event, unit, spellname) Called after the element has been updated after a channeled spell has been completed. * self - the Castbar widget - * unit - unit for which the update has been triggered (string) - * name - name of the channeled spell (string) --]] if(element.PostChannelStop) then - return element:PostChannelStop(unit, spellname) + return element:PostChannelStop() end end end local function onUpdate(self, elapsed) if(self.casting) then - local duration = self.duration + elapsed - if(duration >= self.max or (tradeskillTotal > 1 and duration >= (tradeskillCastDuration + tradeskillCastTime * 1.25))) then + local duration = GetTime() - self.startTime + + if(duration >= self.max) then self.casting = nil self:Hide() - tradeskillTotal = 0 if(self.PostCastStop) then self:PostCastStop(self.__owner.unit) end return @@ -449,10 +323,10 @@ local function onUpdate(self, elapsed) self:SetValue(duration) if(self.Spark) then - self.Spark:SetPoint("CENTER", self, "LEFT", (duration / self.max) * self:GetWidth(), 0) + self.Spark:SetPoint("CENTER", self, "LEFT", (duration / ((self.startTime + self.max) - self.startTime)) * self:GetWidth(), 0) end elseif(self.channeling) then - local duration = self.duration - elapsed + local duration = self.startTime + (self.max - GetTime()) if(duration <= 0) then self.channeling = nil @@ -489,15 +363,14 @@ local function onUpdate(self, elapsed) self.casting = nil self.castName = nil self.channeling = nil - tradeskillTotal = 0 self:Hide() end end local function Update(self, ...) - UNIT_SPELLCAST_START(self, ...) - return UNIT_SPELLCAST_CHANNEL_START(self, ...) + SPELLCAST_START(self, unpack(arg)) + return SPELLCAST_CHANNEL_START(self, unpack(arg)) end local function ForceUpdate(element) @@ -510,30 +383,28 @@ local function Enable(self, unit) element.__owner = self element.ForceUpdate = ForceUpdate - if(not (unit and match(unit, "%wtarget$"))) then - self:RegisterEvent("UNIT_SPELLCAST_START", UNIT_SPELLCAST_START) - self:RegisterEvent("UNIT_SPELLCAST_FAILED", UNIT_SPELLCAST_FAILED) - self:RegisterEvent("UNIT_SPELLCAST_STOP", UNIT_SPELLCAST_STOP) - self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED", UNIT_SPELLCAST_INTERRUPTED) - self:RegisterEvent("UNIT_SPELLCAST_DELAYED", UNIT_SPELLCAST_DELAYED) - self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START", UNIT_SPELLCAST_CHANNEL_START) - self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", UNIT_SPELLCAST_CHANNEL_UPDATE) - self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", UNIT_SPELLCAST_CHANNEL_STOP) - self:RegisterEvent("UNIT_SPELLCAST_SENT", UNIT_SPELLCAST_SENT, true) - self:RegisterEvent("UNIT_SPELLCAST_FAILED_QUIET", UNIT_SPELLCAST_FAILED_QUIET) - end - element.holdTime = 0 - element:SetScript("OnUpdate", element.OnUpdate or onUpdate) + element:SetScript("OnUpdate", function() + if element.OnUpdate then + + else + onUpdate(this, arg1) + end + end) + + if(unit == "player") then + self:RegisterEvent("SPELLCAST_START", SPELLCAST_START) + self:RegisterEvent("SPELLCAST_STOP", SPELLCAST_STOP) + self:RegisterEvent("SPELLCAST_FAILED", SPELLCAST_FAILED) + self:RegisterEvent("SPELLCAST_INTERRUPTED", SPELLCAST_INTERRUPTED) + self:RegisterEvent("SPELLCAST_DELAYED", SPELLCAST_DELAYED) + self:RegisterEvent("SPELLCAST_CHANNEL_START", SPELLCAST_CHANNEL_START) + self:RegisterEvent("SPELLCAST_CHANNEL_UPDATE", SPELLCAST_CHANNEL_UPDATE) + self:RegisterEvent("SPELLCAST_CHANNEL_STOP", SPELLCAST_CHANNEL_STOP) - if(self.unit == "player") then CastingBarFrame:UnregisterAllEvents() CastingBarFrame.Show = CastingBarFrame.Hide CastingBarFrame:Hide() - - PetCastingBarFrame:UnregisterAllEvents() - PetCastingBarFrame.Show = PetCastingBarFrame.Hide - PetCastingBarFrame:Hide() end if(element:IsObjectType("StatusBar") and not element:GetStatusBarTexture()) then @@ -545,11 +416,6 @@ local function Enable(self, unit) spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]]) end - local safeZone = element.SafeZone - if(safeZone and safeZone:IsObjectType("Texture") and not safeZone:GetTexture()) then - safeZone:SetTexture(1, 0, 0) - end - element:Hide() return true @@ -561,27 +427,17 @@ local function Disable(self) if(element) then element:Hide() - self:UnregisterEvent("UNIT_SPELLCAST_START", UNIT_SPELLCAST_START) - self:UnregisterEvent("UNIT_SPELLCAST_FAILED", UNIT_SPELLCAST_FAILED) - self:UnregisterEvent("UNIT_SPELLCAST_STOP", UNIT_SPELLCAST_STOP) - self:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED", UNIT_SPELLCAST_INTERRUPTED) - self:UnregisterEvent("UNIT_SPELLCAST_DELAYED", UNIT_SPELLCAST_DELAYED) - self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START", UNIT_SPELLCAST_CHANNEL_START) - self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", UNIT_SPELLCAST_CHANNEL_UPDATE) - self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", UNIT_SPELLCAST_CHANNEL_STOP) - self:UnregisterEvent("UNIT_SPELLCAST_SENT", UNIT_SPELLCAST_SENT) - self:UnregisterEvent("UNIT_SPELLCAST_FAILED_QUIET", UNIT_SPELLCAST_FAILED_QUIET) + self:UnregisterEvent("SPELLCAST_START", SPELLCAST_START) + self:UnregisterEvent("SPELLCAST_FAILED", SPELLCAST_FAILED) + self:UnregisterEvent("SPELLCAST_STOP", SPELLCAST_STOP) + self:UnregisterEvent("SPELLCAST_INTERRUPTED", SPELLCAST_INTERRUPTED) + self:UnregisterEvent("SPELLCAST_DELAYED", SPELLCAST_DELAYED) + self:UnregisterEvent("SPELLCAST_CHANNEL_START", SPELLCAST_CHANNEL_START) + self:UnregisterEvent("SPELLCAST_CHANNEL_UPDATE", SPELLCAST_CHANNEL_UPDATE) + self:UnregisterEvent("SPELLCAST_CHANNEL_STOP", SPELLCAST_CHANNEL_STOP) element:SetScript("OnUpdate", nil) end end -hooksecurefunc("DoTradeSkill", function(_, num) - tradeskillCastTime = 0 - tradeskillCastDuration = 0 - tradeskillCurrent = 0 - tradeskillTotal = num or 1 - mergeTradeskill = true -end) - -oUF:AddElement("Castbar", Update, Enable, Disable) \ No newline at end of file +oUF:AddElement("Castbar", function() end, Enable, Disable) \ No newline at end of file diff --git a/ElvUI/Libraries/oUF/elements/elements.xml b/ElvUI/Libraries/oUF/elements/elements.xml index 91f969b..19b77f3 100644 --- a/ElvUI/Libraries/oUF/elements/elements.xml +++ b/ElvUI/Libraries/oUF/elements/elements.xml @@ -1,21 +1,20 @@