You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
9.7 KiB

--========================================================--
-- Scorpio Secure Spell Handler --
-- --
-- Author : kurapica125@outlook.com --
-- Create Date : 2021/03/29 --
--========================================================--
--========================================================--
Scorpio "Scorpio.Secure.SpellHandler" "1.0.0"
--========================================================--
------------------------------------------------------
-- Action Handler
------------------------------------------------------
handler = ActionTypeHandler {
Name = "spell",
InitSnippet = [[
_StanceMap = newtable()
_MacroMap = newtable()
]],
UpdateSnippet = [[
local target = ...
if _StanceMap[target] then
self:SetAttribute("*type*", "macro")
self:SetAttribute("*macrotext*", "/click StanceButton".. _StanceMap[target])
elseif _MacroMap[target] then
self:SetAttribute("*type*", "macro")
self:SetAttribute("*macrotext*", "/cast ".. _MacroMap[target])
end
]],
ReceiveSnippet = [[
local value, detail, extra = ...
-- Spell id is stored in extra
return extra
]],
ClearSnippet = [[
self:SetAttribute("*type*", nil)
self:SetAttribute("*macrotext*", nil)
]],
}
------------------------------------------------------
-- Module Event Handler
------------------------------------------------------
_StanceMapTemplate = "_StanceMap[%d] = %d\n"
_MacroMapTemplate = "_MacroMap[%d] = %q\n"
_StanceMap = {}
_Profession = {}
_MacroMap = {}
function OnEnable()
OnEnable = nil
UpdateStanceMap()
UpdateMacroMap()
Wow.FromEvent("UNIT_AURA"):MatchUnit("player"):Next():Subscribe(function()
if not next(_StanceMap) then return end
for _, btn in handler:GetIterator() do
if _StanceMap[btn.ActionTarget] then
handler:RefreshActionButtons(btn)
end
end
end)
return handler:RefreshActionButtons()
end
------------------------------------------------------
-- System Event Handler
------------------------------------------------------
if Scorpio.IsRetail then
__SystemEvent__"LEARNED_SPELL_IN_TAB"
function LEARNED_SPELL_IN_TAB()
return UpdateProfession()
end
__SystemEvent__"SKILL_LINES_CHANGED" "PLAYER_GUILD_UPDATE" "PLAYER_SPECIALIZATION_CHANGED"
function SKILL_LINES_CHANGED(unit)
return (not unit or unit == "player") and UpdateProfession()
end
end
__SystemEvent__()
function SPELLS_CHANGED()
UpdateMacroMap()
UpdateStanceMap()
return Scorpio.IsRetail and UpdateProfession()
end
__SystemEvent__"UPDATE_SHAPESHIFT_FORM" "PLAYER_ENTERING_WORLD" "SPELL_FLYOUT_UPDATE"
function UPDATE_SHAPESHIFT_FORM()
return handler:RefreshActionButtons()
end
__SystemEvent__()
function UPDATE_SHAPESHIFT_FORMS()
UpdateStanceMap()
return handler:RefreshActionButtons()
end
__SystemEvent__()
function SPELL_UPDATE_COOLDOWN()
return handler:RefreshCooldown()
end
__SystemEvent__"SPELL_UPDATE_USABLE" "PLAYER_ALIVE" "PLAYER_DEAD"
function SPELL_UPDATE_USABLE()
return handler:RefreshUsable()
end
__SystemEvent__()
function CURRENT_SPELL_CAST_CHANGED()
return handler:RefreshButtonState()
end
__NoCombat__()
function UpdateStanceMap()
local str = ""
for i = 1, GetNumShapeshiftForms() do
local id = select(4, GetShapeshiftFormInfo(i))
if id then
str = str.._StanceMapTemplate:format(id, i)
_StanceMap[id] = i
end
end
if str ~= "" then
handler:RunSnippet(str)
for _, btn in handler:GetIterator() do
if _StanceMap[btn.ActionTarget] then
btn:SetAttribute("*type*", "macro")
btn:SetAttribute("*macrotext*", "/click StanceButton".._StanceMap[btn.ActionTarget])
end
end
end
end
__NoCombat__()
function UpdateMacroMap()
local str = {}
local cnt = 0
local index = 1
local _, id = GetSpellBookItemInfo(index, "spell")
while id do
local name = GetSpellInfo(id)
if name and _MacroMap[id] ~= name then
_MacroMap[id] = name
cnt = cnt + 1
str[cnt] = _MacroMapTemplate:format(id, name)
end
index = index + 1
_, id = GetSpellBookItemInfo(index, "spell")
end
if cnt > 0 then
handler:RunSnippet(tblconcat(str, "\n"))
for _, btn in handler:GetIterator() do
if _MacroMap[btn.ActionTarget] then
btn:SetAttribute("*type*", "macro")
btn:SetAttribute("*macrotext*", "/cast ".._MacroMap[btn.ActionTarget])
end
end
end
end
__NoCombat__()
function UpdateProfession()
local lst = { GetProfessions() }
local offset, spell, name
for i = 1, 6 do
if lst[i] then
offset = 1 + select(6, GetProfessionInfo(lst[i]))
spell = select(2, GetSpellBookItemInfo(offset, "spell"))
name = GetSpellBookItemName(offset, "spell")
if _Profession[name] ~= spell then
_Profession[name] = spell
for _, btn in handler:GetIterator() do
if GetSpellInfo(btn.ActionTarget) == name then
btn:SetAction("spell", spell)
end
end
end
end
end
end
------------------------------------------------------
-- Overwrite methods
------------------------------------------------------
function handler:Refresh()
local target = self.ActionTarget
if not target then return end
if not _StanceMap[target] and not _MacroMap[target] then
local name = GetSpellInfo(target)
if name and _MacroMap[target] ~= name then
_MacroMap[target] = name
NoCombat(function ()
handler:RunSnippet( _MacroMapTemplate:format(target, name) )
self:SetAttribute("*type*", "macro")
self:SetAttribute("*macrotext*", "/cast ".. name)
end)
end
end
end
function handler:PickupAction(target)
return PickupSpell(target)
end
function handler:GetActionTexture()
local target = self.ActionTarget
if _StanceMap[target] then
return (GetShapeshiftFormInfo(_StanceMap[target]))
elseif _MacroMap[target] then
return GetSpellTexture(_MacroMap[target])
else
return GetSpellTexture(target)
end
end
function handler:GetActionCharges()
local target = self.ActionTarget
if _MacroMap[target] then
return GetSpellCharges(_MacroMap[target])
else
return GetSpellCharges(target)
end
end
function handler:GetActionCount()
local target = self.ActionTarget
if _MacroMap[target] then
return GetSpellCount(_MacroMap[target])
end
end
function handler:GetActionCooldown()
local target = self.ActionTarget
if _StanceMap[target] then
if select(2, GetSpellCooldown(target)) > 2 then
return GetSpellCooldown(target)
else
return 0, 0
end
elseif _MacroMap[target] then
return GetSpellCooldown(_MacroMap[target])
else
return GetSpellCooldown(target)
end
end
function handler:IsAttackAction()
return IsAttackSpell(GetSpellInfo(self.ActionTarget))
end
function handler:IsActivedAction()
local target = self.ActionTarget
if _StanceMap[target] then
return select(2, GetShapeshiftFormInfo(_StanceMap[target]))
elseif _MacroMap[target] then
return IsCurrentSpell(_MacroMap[target])
end
end
function handler:IsAutoRepeatAction()
local target = _MacroMap[self.ActionTarget]
return target and IsAutoRepeatSpell(target)
end
function handler:IsUsableAction()
local target = self.ActionTarget
if _StanceMap[target] then
return select(3, GetShapeshiftFormInfo(_StanceMap[target]))
elseif _MacroMap[target] then
return IsUsableSpell(_MacroMap[target])
end
end
function handler:IsConsumableAction()
local target = _MacroMap[self.ActionTarget]
return target and IsConsumableSpell(_MacroMap[target])
end
function handler:IsInRange()
local target = self.ActionTarget
if not _StanceMap[target] and _MacroMap[target] then
return IsSpellInRange(_MacroMap[target], self:GetAttribute("unit"))
end
end
function handler:SetTooltip(tip)
return tip:SetSpellByID(self.ActionTarget)
end
function handler:GetSpellId()
return self.ActionTarget
end
function handler:IsRangeSpell()
return true
end
function handler:Map(target, detail)
-- Convert to spell id
if tonumber(target) then
target = tonumber(target)
else
target = GetSpellLink(target)
target = tonumber(target and target:match("spell:(%d+)"))
end
if target and _Profession[GetSpellInfo(target)] then
target = _Profession[GetSpellInfo(target)]
end
return target, detail
end