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/!Compatibility/libs/libs.xml b/!Compatibility/libs/libs.xml
index b37fb2c..6c654fe 100644
--- a/!Compatibility/libs/libs.xml
+++ b/!Compatibility/libs/libs.xml
@@ -3,4 +3,7 @@
+
+
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua b/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua
index 0cfc19d..0b22af2 100644
--- a/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua
+++ b/ElvUI/Libraries/LibUIDropDownMenu/LibUIDropDownMenu.lua
@@ -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/oUF/oUF.xml b/ElvUI/Libraries/oUF/oUF.xml
index f954b51..2a3133a 100644
--- a/ElvUI/Libraries/oUF/oUF.xml
+++ b/ElvUI/Libraries/oUF/oUF.xml
@@ -1,7 +1,7 @@
-
+
@@ -16,7 +16,7 @@
-
+
\ No newline at end of file
diff --git a/ElvUI/Libraries/oUF/ouf.lua b/ElvUI/Libraries/oUF/ouf.lua
index f27efa1..25ec9cd 100644
--- a/ElvUI/Libraries/oUF/ouf.lua
+++ b/ElvUI/Libraries/oUF/ouf.lua
@@ -59,7 +59,7 @@ local function onAttributeChanged(self, name, value)
if(not self.onlyProcessChildren) then
updateActiveUnit(self, "OnAttributeChanged")
end
---[[
+
if(self.unit and self.unit == value) then
return
else
@@ -67,7 +67,7 @@ local function onAttributeChanged(self, name, value)
iterateChildren(self:GetChildren())
end
end
-]]
+
end
end
@@ -331,7 +331,7 @@ local function initObject(unit, style, styleFunc, header, ...)
styleFunc(object, objectUnit, not header)
- --object:SetScript("OnAttributeChanged", onAttributeChanged)
+ object:SetScript("OnAttributeChanged", onAttributeChanged)
object:SetScript("OnShow", function() onShow(this) end)
activeElements[object] = {}
@@ -359,7 +359,7 @@ local function walkObject(object, unit)
-- Check if we should leave the main frame blank.
if(object.onlyProcessChildren) then
object.hasChildren = true
- --object:SetScript("OnAttributeChanged", onAttributeChanged)
+ object:SetScript("OnAttributeChanged", onAttributeChanged)
return initObject(unit, style, styleFunc, header, object:GetChildren())
end
@@ -542,8 +542,8 @@ do
end
self.menu = togglemenu
- --self:SetAttribute("type1", "target")
- --self:SetAttribute("type2", "menu")
+ self:SetAttribute("type1", "target")
+ self:SetAttribute("type2", "menu")
self.guessUnit = unit
self.unit = "player"
-- self.onlyProcessChildren =true
@@ -552,18 +552,18 @@ do
styleProxy(nil, self:GetName())
end
- local setAttribute = function(self, name, value)
- if self.attributes[name] ~= value then
- self.attributes[name] = value
+ -- local setAttribute = function(self, name, value)
+ -- if self.attributes[name] ~= value then
+ -- self.attributes[name] = value
- if self:IsVisible() then
- SecureGroupHeader_Update(self)
- end
- end
- end
- local getAttribute = function(self, name)
- return self.attributes[name]
- end
+ -- if self:IsVisible() then
+ -- SecureGroupHeader_Update(self)
+ -- end
+ -- end
+ -- end
+ -- local getAttribute = function(self, name)
+ -- return self.attributes[name]
+ -- end
--[[ oUF:SpawnHeader(overrideName, template, visibility, ...)
Used to create a group header and apply the currently active style to it.
@@ -594,10 +594,10 @@ do
header:Hide()
header.attributes = {}
- header.SetAttribute = setAttribute
- header.GetAttribute = getAttribute
+ -- header.SetAttribute = SetAttribute
+ -- header.GetAttribute = GetAttribute
- --header:SetAttribute("template", "SecureUnitButtonTemplate")
+ header:SetAttribute("template", "SecureUnitButtonTemplate")
for i = 1, getn(arg), 2 do
local att, val = select(i, unpack(arg))
if(not att) then break end
@@ -620,7 +620,7 @@ do
end
- --[[if(visibility) then
+ if(visibility) then
local type, list = split(" ", visibility, 2)
if(list and type == "custom") then
RegisterStateDriver(header, "visibility", list)
@@ -630,7 +630,7 @@ do
RegisterStateDriver(header, "visibility", condition)
header.visibility = condition
end
- end]]
+ end
return header
end
diff --git a/ElvUI/Modules/UnitFrames/Config_Enviroment.lua b/ElvUI/Modules/UnitFrames/Config_Enviroment.lua
index 4d6070f..2b63471 100644
--- a/ElvUI/Modules/UnitFrames/Config_Enviroment.lua
+++ b/ElvUI/Modules/UnitFrames/Config_Enviroment.lua
@@ -1,27 +1,29 @@
-local E, L, V, P, G = unpack(ElvUI)
+local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local UF = E:GetModule("UnitFrames");
-local ns = oUF
-local ElvUF = ns.oUF
+local ns = oUF;
+local ElvUF = ns.oUF;
-local _G = _G;
-local setmetatable, getfenv, setfenv = setmetatable, getfenv, setfenv;
-local type, unpack, select, pairs = type, unpack, select, pairs;
-local min, random = math.min, math.random;
-local format = string.format;
-
-local UnitMana = UnitMana;
-local UnitManaMax = UnitManaMax;
-local UnitHealth = UnitHealth;
-local UnitHealthMax = UnitHealthMax;
-local UnitName = UnitName;
-local UnitClass = UnitClass;
-local InCombatLockdown = InCombatLockdown;
-local UnregisterUnitWatch = UnregisterUnitWatch;
-local RegisterUnitWatch = RegisterUnitWatch;
-local RegisterStateDriver = RegisterStateDriver;
-local LOCALIZED_CLASS_NAMES_MALE = LOCALIZED_CLASS_NAMES_MALE;
-local CLASS_SORT_ORDER = CLASS_SORT_ORDER;
-local MAX_RAID_MEMBERS = MAX_RAID_MEMBERS;
+--Cache global variables
+--Lua functions
+local _G = _G
+local setmetatable, getfenv, setfenv = setmetatable, getfenv, setfenv
+local type, unpack, select, pairs = type, unpack, select, pairs
+local min, random = math.min, math.random
+local format = string.format
+--WoW API / Variables
+local UnitMana = UnitMana
+local UnitManaMax = UnitManaMax
+local UnitHealth = UnitHealth
+local UnitHealthMax = UnitHealthMax
+local UnitName = UnitName
+local UnitClass = UnitClass
+local UnitAffectingCombat = UnitAffectingCombat
+local UnregisterUnitWatch = UnregisterUnitWatch
+local RegisterUnitWatch = RegisterUnitWatch
+local RegisterStateDriver = RegisterStateDriver
+local LOCALIZED_CLASS_NAMES_MALE = LOCALIZED_CLASS_NAMES_MALE
+local CLASS_SORT_ORDER = CLASS_SORT_ORDER
+local MAX_RAID_MEMBERS = MAX_RAID_MEMBERS
local attributeBlacklist = {["showRaid"] = true, ["showParty"] = true, ["showSolo"] = true}
local configEnv
@@ -29,45 +31,45 @@ local originalEnvs = {}
local overrideFuncs = {}
local function createConfigEnv()
- if( configEnv ) then return end
+ if configEnv then return end
configEnv = setmetatable({
UnitMana = function (unit, displayType)
- if(unit:find("target") or unit:find("focus")) then
- return UnitMana(unit, displayType);
+ if find(unit, "target") or find(unit, "focus") then
+ return UnitMana(unit, displayType)
end
- return random(1, UnitManaMax(unit, displayType) or 1);
+ return random(1, UnitManaMax(unit, displayType) or 1)
end,
UnitHealth = function(unit)
- if(unit:find("target") or unit:find("focus")) then
- return UnitHealth(unit);
+ if find(unit, "target") or find(unit, "focus") then
+ return UnitHealth(unit)
end
- return random(1, UnitHealthMax(unit));
+ return random(1, UnitHealthMax(unit))
end,
UnitName = function(unit)
- if(unit:find("target") or unit:find("focus")) then
- return UnitName(unit);
+ if find(unit, "target") or find(unit, "focus") then
+ return UnitName(unit)
end
- if(E.CreditsList) then
- local max = #E.CreditsList;
- return E.CreditsList[random(1, max)];
+ if E.CreditsList then
+ local max = getn(E.CreditsList)
+ return E.CreditsList[random(1, max)]
end
- return "Test Name";
+ return "Test Name"
end,
UnitClass = function(unit)
- if(unit:find("target") or unit:find("focus")) then
- return UnitClass(unit);
+ if find(unit, "target") or find(unit, "focus") then
+ return UnitClass(unit)
end
- local classToken = CLASS_SORT_ORDER[random(1, #(CLASS_SORT_ORDER))];
- return LOCALIZED_CLASS_NAMES_MALE[classToken], classToken;
+ local classToken = CLASS_SORT_ORDER[random(1, getn(CLASS_SORT_ORDER))]
+ return LOCALIZED_CLASS_NAMES_MALE[classToken], classToken
end,
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
+ 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 format("|cff%02x%02x%02x", r*255, g*255, b*255);
+ return format("|cff%02x%02x%02x", r*255, g*255, b*255)
end,
ColorGradient = ElvUF.ColorGradient,
}, {
@@ -101,11 +103,11 @@ local function createConfigEnv()
end
function UF:ForceShow(frame)
- if InCombatLockdown() then return; end
+ if UnitAffectingCombat("player") then return end
if not frame.isForced then
frame.oldUnit = frame.unit
frame.unit = "player"
- frame.isForced = true;
+ frame.isForced = true
frame.oldOnUpdate = frame:GetScript("OnUpdate")
end
@@ -119,17 +121,17 @@ function UF:ForceShow(frame)
frame:Update()
end
- if(_G[frame:GetName().."Target"]) then
- self:ForceShow(_G[frame:GetName().."Target"]);
+ if _G[frame:GetName().."Target"] then
+ self:ForceShow(_G[frame:GetName().."Target"])
end
- if(_G[frame:GetName().."Pet"]) then
- self:ForceShow(_G[frame:GetName().."Pet"]);
+ if _G[frame:GetName().."Pet"] then
+ self:ForceShow(_G[frame:GetName().."Pet"])
end
end
function UF:UnforceShow(frame)
- if InCombatLockdown() then return; end
+ if UnitAffectingCombat("player") then return end
if not frame.isForced then
return
end
@@ -152,11 +154,11 @@ function UF:UnforceShow(frame)
frame:Update()
end
- if(_G[frame:GetName().."Target"]) then
+ if _G[frame:GetName().."Target"] then
self:UnforceShow(_G[frame:GetName().."Target"])
end
- if(_G[frame:GetName().."Pet"]) then
+ if _G[frame:GetName().."Pet"] then
self:UnforceShow(_G[frame:GetName().."Pet"])
end
end
@@ -164,8 +166,8 @@ end
function UF:ShowChildUnits(header, ...)
header.isForced = true
- for i=1, select("#", ...) do
- local frame = select(i, ...)
+ for i = 1, getn(args) do
+ local frame = select(i, unpack(args))
frame:RegisterForClicks(nil)
frame:SetID(i)
frame.TargetGlow:SetAlpha(0)
@@ -176,8 +178,8 @@ end
function UF:UnshowChildUnits(header, ...)
header.isForced = nil
- for i=1, select("#", ...) do
- local frame = select(i, ...)
+ for i = 1, getn(args) do
+ local frame = select(i, unpack(args))
frame:RegisterForClicks(self.db.targetOnMouseDown and "AnyDown" or "AnyUp")
frame.TargetGlow:SetAlpha(1)
self:UnforceShow(frame)
@@ -185,7 +187,7 @@ function UF:UnshowChildUnits(header, ...)
end
local function OnAttributeChanged(self)
- if not self:GetParent().forceShow and not self.forceShow then return; end
+ if not self:GetParent().forceShow and not self.forceShow then return end
if not self:IsShown() then return end
local db = self.db or self:GetParent().db
@@ -199,7 +201,7 @@ local function OnAttributeChanged(self)
end
function UF:HeaderConfig(header, configMode)
- if InCombatLockdown() then return; end
+ if UnitAffectingCombat("player") then return end
createConfigEnv()
header.forceShow = configMode
@@ -225,18 +227,18 @@ function UF:HeaderConfig(header, configMode)
RegisterStateDriver(header, "visibility", header.db.visibility)
- if(header:GetScript("OnEvent")) then
- header:GetScript("OnEvent")(header, "PLAYER_ENTERING_WORLD");
+ if header:GetScript("OnEvent") then
+ header:GetScript("OnEvent")(header, "PLAYER_ENTERING_WORLD")
end
end
- for i=1, #header.groups do
+ for i = 1, getn(header.groups) do
local group = header.groups[i]
if group:IsShown() then
group.forceShow = header.forceShow
group.forceShowAuras = header.forceShowAuras
- group:HookScript("OnAttributeChanged", OnAttributeChanged)
+ HookScript(group, "OnAttributeChanged", OnAttributeChanged)
if configMode then
for key in pairs(attributeBlacklist) do
group:SetAttribute(key, nil)
@@ -258,7 +260,7 @@ function UF:HeaderConfig(header, configMode)
end
end
- UF["headerFunctions"][header.groupName]:AdjustVisibility(header);
+ UF["headerFunctions"][header.groupName]:AdjustVisibility(header)
end
function UF:PLAYER_REGEN_DISABLED()
@@ -275,19 +277,7 @@ function UF:PLAYER_REGEN_DISABLED()
end
end
- for i=1, 5 do
- if self["arena"..i] and self["arena"..i].isForced then
- self:UnforceShow(self["arena"..i])
- end
- end
-
- for i=1, 4 do
- if self["boss"..i] and self["boss"..i].isForced then
- self:UnforceShow(self["boss"..i])
- end
- end
-
- for i=1, 4 do
+ for i = 1, 4 do
if self["party"..i] and self["party"..i].isForced then
self:UnforceShow(self["party"..i])
end
diff --git a/ElvUI/Modules/UnitFrames/Load_UnitFrames.xml b/ElvUI/Modules/UnitFrames/Load_UnitFrames.xml
index ecbb659..6d72871 100644
--- a/ElvUI/Modules/UnitFrames/Load_UnitFrames.xml
+++ b/ElvUI/Modules/UnitFrames/Load_UnitFrames.xml
@@ -1,5 +1,6 @@
+
diff --git a/ElvUI/Modules/UnitFrames/UnitFrames.lua b/ElvUI/Modules/UnitFrames/UnitFrames.lua
index 6d65633..97f088e 100644
--- a/ElvUI/Modules/UnitFrames/UnitFrames.lua
+++ b/ElvUI/Modules/UnitFrames/UnitFrames.lua
@@ -679,7 +679,7 @@ function UF:CreateAndUpdateHeaderGroup(group, groupFilter, template, headerUpdat
if headerUpdate or not self[group].mover then
UF["headerFunctions"][group]:Configure_Groups(self[group])
if not self[group].isForced and not self[group].blockVisibilityChanges then
- -- RegisterStateDriver(self[group], "visibility", db.visibility)
+ RegisterStateDriver(self[group], "visibility", db.visibility)
end
else
UF["headerFunctions"][group]:Configure_Groups(self[group])
@@ -693,7 +693,7 @@ function UF:CreateAndUpdateHeaderGroup(group, groupFilter, template, headerUpdat
E:EnableMover(self[group].mover:GetName())
end
else
- -- UnregisterStateDriver(self[group], "visibility")
+ UnregisterStateDriver(self[group], "visibility")
self[group]:Hide()
if self[group].mover then
E:DisableMover(self[group].mover:GetName())
@@ -708,7 +708,7 @@ function UF:CreateAndUpdateHeaderGroup(group, groupFilter, template, headerUpdat
local db = UF.db["units"][group]
if db.enable ~= true then
UnregisterStateDriver(UF[group], "visibility")
- --UF[group]:Hide()
+ UF[group]:Hide()
if(UF[group].mover) then
E:DisableMover(UF[group].mover:GetName())
end