This commit is contained in:
Bunny67
2018-07-07 19:29:52 +03:00
parent d4ca4e6268
commit 48c18db70b
3 changed files with 0 additions and 807 deletions
-26
View File
@@ -1,26 +0,0 @@
--[[
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
-268
View File
@@ -1,268 +0,0 @@
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()
-513
View File
@@ -1,513 +0,0 @@
--[[
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