---@type Tinkr local Tinkr, ---@class Bastion Bastion = ... -- Create an EventManager class ---@class Bastion.EventManager ---@field frame Frame ---@field events table ---@field eventHandlers table ---@field wowEventHandlers table ---@field selfCombatEventHandlers table ---@field CombatEventHandlers table ---@field playerGUID string|boolean local EventManager = { events = {}, eventHandlers = {}, wowEventHandlers = {}, selfCombatEventHandlers = { ["*"] = {}, }, CombatEventHandlers = { ["*"] = {}, }, } EventManager.__index = EventManager -- Constructor ---@return Bastion.EventManager function EventManager:New() local self = setmetatable({}, EventManager) self.playerGUID = UnitGUID("player") or false -- Frame for wow events self.frame = CreateFrame("Frame") self.frame:SetScript("OnEvent", function(f, event, ...) if self.wowEventHandlers[event] then for _, eventHandler in ipairs(self.wowEventHandlers[event]) do if eventHandler.sendEvent then eventHandler.fun(event, ...) else eventHandler.fun(...) end end end end) self:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function() self:CLEUHandler(CombatLogGetCurrentEventInfo()) end) return self end -- Register an event ---@param event string ---@param handler fun(...) ---@return nil function EventManager:RegisterEvent(event, handler) if not self.events[event] then self.events[event] = {} end table.insert(self.events[event], handler) end -- Register a wow event ---@param events WowEvent | WowEvent[] ---@param handler fun(...) ---@param sendEvent? boolean function EventManager:RegisterWoWEvent(events, handler, sendEvent) if type(events) == "string" then events = { events } end for _, event in ipairs(events) do if not self.wowEventHandlers[event] then self.wowEventHandlers[event] = {} self.frame:RegisterEvent(event) end table.insert(self.wowEventHandlers[event], { fun = handler, sendEvent = sendEvent or false, }) end end -- Trigger an event ---@param event string ---@param ... any function EventManager:TriggerEvent(event, ...) if self.events[event] then for _, handler in pairs(self.events[event]) do handler(...) end end end ---@param subevents string | string[] ---@param handler fun(...) function EventManager:RegisterSelfCombatEvent(subevents, handler) if type(subevents) == "string" then subevents = { subevents } end for _, subevent in ipairs(subevents) do if not self.selfCombatEventHandlers[subevent] then self.selfCombatEventHandlers[subevent] = {} end table.insert(self.selfCombatEventHandlers[subevent], handler) end end ---@param subevents string | string[] ---@param handler fun(...) function EventManager:RegisterCombatEvent(subevents, handler) if type(subevents) == "string" then subevents = { subevents } end for _, subevent in ipairs(subevents) do if not self.CombatEventHandlers[subevent] then self.CombatEventHandlers[subevent] = {} end table.insert(self.CombatEventHandlers[subevent], handler) end end ---@param ... any function EventManager:CLEUHandler(...) ---@type number local timestamp = select(1, ...) ---@type string local subevent = select(2, ...) ---@type string local sourceGUID = select(4, ...) ---@type string local destGUID = select(8, ...) local keys = { subevent, "*" } local isSelf = self.playerGUID and sourceGUID == self.playerGUID for _, key in ipairs(keys) do if isSelf then if self.selfCombatEventHandlers[key] then for _, callback in ipairs(self.selfCombatEventHandlers[key]) do callback(...) end end end if self.CombatEventHandlers[key] then for _, callback in ipairs(self.CombatEventHandlers[key]) do callback(...) end end end end function EventManager:SetOnUpdate(func) self.frame:SetScript("OnUpdate", func) end Bastion.EventManager = EventManager --Bastion.Globals.EventManager = Bastion.EventManager:New()