Files
ShaguTweaks-ClassicAPI/mods/superwow.lua
T

126 lines
4.2 KiB
Lua

-- SuperWoW compatibility
--
-- https://github.com/balakethelock/SuperWoW
--
-- This module adds GUID based cast and channel data to the
-- libcast library that is used to query enemy casting infos.
-- Skip module initialization if SuperWoW is not running.
if not GetPlayerBuffID or not CombatLogAdd or not SpellInfo then return end
local T = ShaguTweaks.T
local API = ShaguTweaks.API
local module = ShaguTweaks:register({
title = T["Super WoW Compatibility"],
description = T["Adds compatibility for the SuperWoW client mod."],
expansions = { ["vanilla"] = true },
category = T["General"],
enabled = true,
})
module.enable = function(self)
if self.listener then return end
local enemyTitle = T["Enemy Castbars"]
local enabled = ShaguTweaks_config[enemyTitle]
if enabled == nil then
local consumer = ShaguTweaks.mods[enemyTitle]
enabled = consumer and consumer.enabled and 1 or 0
end
if enabled ~= 1 then return end
local libcast = ShaguTweaks.libcast
local playerName = UnitName("player")
local lastPrune = -1
local function Changed(guid)
if libcast.OnRemoteChanged then libcast.OnRemoteChanged(guid) end
end
local unitcast = CreateFrame("Frame")
self.listener = unitcast
unitcast:RegisterEvent("UNIT_CASTEVENT")
unitcast:SetScript("OnEvent", function()
local guid = arg1
local event_type = arg3
local spellID = arg4
if type(guid) ~= "string" or type(spellID) ~= "number" then return end
-- Player timing belongs to ClassicAPI (or Hunter-only local emulation).
if guid == API.UnitGUID("player") then return end
local now = GetTime()
if now - lastPrune >= .5 then libcast:Prune(now); lastPrune = now end
if event_type == "START" or event_type == "CAST" or event_type == "CHANNEL" then
-- human readable argument list
local timer = arg5
if type(timer) ~= "number" or timer ~= timer or timer <= 0 or timer > 600000 then
local cast = libcast.db[guid]
if cast and cast.spellID == spellID then libcast.db[guid] = nil; Changed(guid) end
return
end
-- A complete native record needs no second Lua copy. Keep SuperWoW
-- timing only where the native unit-token query cannot provide it.
local token = API.UnitTokenFromGUID(guid)
if token then
local name, finish
if event_type == "CHANNEL" then
local a, b, c, d, e, f = API.GetChannelInfo(token)
name, finish = a, f
else
local a, b, c, d, e, f = API.GetCastInfo(token)
name, finish = a, f
end
if name and finish and finish > now * 1000 then libcast.db[guid] = nil; return end
end
-- get spell info from spell id
local spell, icon, _
spell, _, icon = SpellInfo(spellID)
-- set fallback values
spell = spell or UNKNOWN
icon = icon or "Interface\\Icons\\INV_Misc_QuestionMark"
-- add cast action to the database
local cast = libcast.db[guid]
if not cast then
-- Cache only a bounded number of live remote records, even in long
-- sessions with unique NPC GUIDs. No permanent cleanup OnUpdate.
local count, earliest, expiry = 0, nil, nil
for key, entry in pairs(libcast.db) do
if key ~= playerName then
count = count + 1
local ending = entry.start + entry.casttime/1000
if not expiry or ending < expiry then earliest, expiry = key, ending end
end
end
if count >= 128 and earliest then libcast.db[earliest] = nil end
cast = {}
libcast.db[guid] = cast
end
cast.cast = spell
cast.rank = nil
cast.start = now
cast.casttime = timer
cast.icon = icon
cast.channel = event_type == "CHANNEL" or false
cast.spellID = spellID
-- write state variable
ShaguTweaks.superwow_active = true
Changed(guid)
elseif event_type == "FAIL" then
local cast = libcast.db[guid]
-- Ignore a delayed FAIL for an older spell. Otherwise it can erase a
-- newer cast from the same GUID that already replaced it in the cache.
if cast and cast.spellID == spellID then
libcast.db[guid] = nil
Changed(guid)
end
end
end)
end