Use ClassicAPI spell events for predictions

This commit is contained in:
Dusk-92
2026-09-03 11:18:41 +02:00
parent cee87b2433
commit 2e3ad8449d
+75 -20
View File
@@ -1,5 +1,6 @@
local _G = ShaguTweaks.GetGlobalEnv() local _G = ShaguTweaks.GetGlobalEnv()
local L = ShaguTweaks.L local L = ShaguTweaks.L
local API = ShaguTweaks.API
local GetExpansion = ShaguTweaks.GetExpansion local GetExpansion = ShaguTweaks.GetExpansion
local libtipscan = ShaguTweaks.libtipscan local libtipscan = ShaguTweaks.libtipscan
local libspell = ShaguTweaks.libspell local libspell = ShaguTweaks.libspell
@@ -334,7 +335,28 @@ end
local function TrackUseAction(slot, target, selfcast) local function TrackUseAction(slot, target, selfcast)
if not libpredict.sender.enabled then return end if not libpredict.sender.enabled then return end
-- Conditional macros are resolved by the later CastSpellByName hook. For a
-- direct spell action, ClassicAPI gives us the spellID without a tooltip.
if API and API.actioninfo and API.GetActionInfo then
local actionType, actionID = API.GetActionInfo(slot)
if actionType == "macro" or actionType == "item" then return end
if actionType == "spell" and actionID then
if not IsCurrentAction(slot) then return end
local effect, rank = API.GetSpellInfo(actionID)
if not effect then return end
spell_queue[1] = effect
spell_queue[2] = effect.. ( rank or "" )
spell_queue[3] = selfcast and UnitName("player") or UnitName("target") and UnitCanAssist("player", "target") and UnitName("target") or UnitName("player")
return
elseif actionType then
return
end
end
if GetActionText(slot) or not IsCurrentAction(slot) then return end if GetActionText(slot) or not IsCurrentAction(slot) then return end
scanner = scanner or libtipscan:GetScanner("prediction")
scanner:SetAction(slot) scanner:SetAction(slot)
local effect, rank = scanner:Line(1) local effect, rank = scanner:Line(1)
if not effect then return end if not effect then return end
@@ -345,7 +367,6 @@ end
local function InstallSenderHooks() local function InstallSenderHooks()
if hooksInstalled then return end if hooksInstalled then return end
scanner = scanner or libtipscan:GetScanner("prediction")
hooksecurefunc("CastSpell", TrackCastSpell) hooksecurefunc("CastSpell", TrackCastSpell)
hooksecurefunc("CastSpellByName", TrackCastSpellByName) hooksecurefunc("CastSpellByName", TrackCastSpellByName)
hooksecurefunc("UseAction", TrackUseAction) hooksecurefunc("UseAction", TrackUseAction)
@@ -395,17 +416,30 @@ libpredict.sender:SetScript("OnEvent", function()
elseif spell and heal then elseif spell and heal then
if spell == spell_queue[1] then UpdateCache(spell_queue[2], heal) end if spell == spell_queue[1] then UpdateCache(spell_queue[2], heal) end
end end
elseif event == "UNIT_SPELLCAST_SENT" and arg4 then -- fix tbc mouseover macros elseif event == "UNIT_SPELLCAST_SENT" then
senttarget = arg4 if arg1 ~= "player" then return end
-- ClassicAPI follows the modern event shape: unit, target, castGUID,
-- spellID, spellName, rank. TBC's legacy shape stores target in arg4.
senttarget = GetExpansion() == "vanilla" and arg2 or arg4
elseif strfind(event, "SPELLCAST_START", 1) then elseif strfind(event, "SPELLCAST_START", 1) then
local spell, time = arg1, arg2 local spell, time = arg1, arg2
if strfind(event, "UNIT_", 1) then -- tbc if strfind(event, "UNIT_", 1) then
if arg1 ~= "player" then return end if arg1 ~= "player" then return end
local spellname, _, _, _, starttime, endtime = UnitCastingInfo("player")
spell, time = spellname, endtime - starttime if GetExpansion() == "vanilla" and API and API.casts then
local spellname, _, _, _, starttime, endtime = API.GetCastInfo("player")
spell = spellname
time = starttime and endtime and endtime - starttime or nil
else
local spellname, _, _, _, starttime, endtime = UnitCastingInfo("player")
spell = spellname
time = starttime and endtime and endtime - starttime or nil
end
end end
if not spell or not time then return end
if spell_queue[1] == spell and cache[spell_queue[2]] then if spell_queue[1] == spell and cache[spell_queue[2]] then
local sender = player local sender = player
local target = senttarget or spell_queue[3] local target = senttarget or spell_queue[3]
@@ -487,21 +521,42 @@ function libpredict:Enable()
resetcache:RegisterEvent("SKILL_LINES_CHANGED") resetcache:RegisterEvent("SKILL_LINES_CHANGED")
resetcache:RegisterEvent("UNIT_INVENTORY_CHANGED") resetcache:RegisterEvent("UNIT_INVENTORY_CHANGED")
-- tbc if GetExpansion() == "vanilla" then
self.sender:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") -- ClassicAPI supplies structured player spellcast events on 1.12. Use
self.sender:RegisterEvent("UNIT_SPELLCAST_START") -- those instead of registering both event families and processing each cast
self.sender:RegisterEvent("UNIT_SPELLCAST_STOP") -- twice. Keep the native SPELLCAST_DELAYED event because it carries the
self.sender:RegisterEvent("UNIT_SPELLCAST_FAILED") -- exact delay delta consumed by HealDelay().
self.sender:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED") local useClassicCastEvents = API and API.eventutils and _G.C_EventUtils
self.sender:RegisterEvent("UNIT_SPELLCAST_SENT") and _G.C_EventUtils.IsEventValid("UNIT_SPELLCAST_START")
and _G.C_EventUtils.IsEventValid("UNIT_SPELLCAST_STOP")
and _G.C_EventUtils.IsEventValid("UNIT_SPELLCAST_FAILED")
and _G.C_EventUtils.IsEventValid("UNIT_SPELLCAST_INTERRUPTED")
and _G.C_EventUtils.IsEventValid("UNIT_SPELLCAST_SENT")
-- vanilla if useClassicCastEvents then
self.sender:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF") self.sender:RegisterEvent("UNIT_SPELLCAST_START")
self.sender:RegisterEvent("SPELLCAST_START") self.sender:RegisterEvent("UNIT_SPELLCAST_STOP")
self.sender:RegisterEvent("SPELLCAST_STOP") self.sender:RegisterEvent("UNIT_SPELLCAST_FAILED")
self.sender:RegisterEvent("SPELLCAST_FAILED") self.sender:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
self.sender:RegisterEvent("SPELLCAST_INTERRUPTED") self.sender:RegisterEvent("UNIT_SPELLCAST_SENT")
self.sender:RegisterEvent("SPELLCAST_DELAYED") else
self.sender:RegisterEvent("SPELLCAST_START")
self.sender:RegisterEvent("SPELLCAST_STOP")
self.sender:RegisterEvent("SPELLCAST_FAILED")
self.sender:RegisterEvent("SPELLCAST_INTERRUPTED")
end
self.sender:RegisterEvent("SPELLCAST_DELAYED")
self.sender:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF")
else
-- Native TBC event layout and combat log.
self.sender:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
self.sender:RegisterEvent("UNIT_SPELLCAST_START")
self.sender:RegisterEvent("UNIT_SPELLCAST_STOP")
self.sender:RegisterEvent("UNIT_SPELLCAST_FAILED")
self.sender:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
self.sender:RegisterEvent("UNIT_SPELLCAST_SENT")
end
-- force cache updates -- force cache updates
self.sender:RegisterEvent("UNIT_INVENTORY_CHANGED") self.sender:RegisterEvent("UNIT_INVENTORY_CHANGED")