local addonname, shared = ... ---@cast shared HeimdallShared ---@cast addonname string ---@diagnostic disable-next-line: missing-fields shared.Macroer = {} function shared.Macroer.Init() ---@class stinky ---@field name string ---@field class string ---@field seenAt number ---@field hostile boolean ---@type table local recentStinkies = {} local function FindOrCreateMacro(macroName) local idx = GetMacroIndexByName(macroName) if idx == 0 then CreateMacro(macroName, "INV_Misc_QuestionMark", "") end idx = GetMacroIndexByName(macroName) return idx end ---@param stinkies table local function FixMacro(stinkies) local priorityMap = {} for priority, className in ipairs(Heimdall_Data.config.macroer.priority) do priorityMap[className] = priority end local minPriority = #Heimdall_Data.config.macroer.priority + 1 local sortedStinkies = {} for _, stinky in pairs(stinkies) do table.insert(sortedStinkies, stinky) end table.sort(sortedStinkies, function(a, b) local aPriority = priorityMap[a.class] or minPriority local bPriority = priorityMap[b.class] or minPriority return aPriority > bPriority end) local lines = {"/targetenemy"} for _, stinky in pairs(sortedStinkies) do if stinky.seenAt > GetTime() - 600 then print(string.format("Macroing %s", stinky.name)) lines[#lines + 1] = string.format("/tar %s", stinky.name) end end local idx = FindOrCreateMacro("HeimdallTarget") local body = strjoin("\n", unpack(lines)) EditMacro(idx, "HeimdallTarget", "INV_Misc_QuestionMark", body) end local whoRegex = "([^ -/]+)-?%w*/(%w+)" ---@param msg string ---@return table local function ParseWho(msg) local stinkies = {} for name, class in string.gmatch(msg, whoRegex) do stinkies[name] = { name = name, class = class, seenAt = GetTime(), hostile = true } end return stinkies end local seeRegex = "I see %((%w+)%) ([^ -/]+)-?%w*/(%w+)" ---@param msg string ---@return table local function ParseSee(msg) local stinkies = {} local aggression, name, class = string.match(msg, seeRegex) if not name or not class then return stinkies end local stinky = { name = name, class = class, seenAt = GetTime(), hostile = aggression == "Hostile" } stinkies[name] = stinky return stinkies end local arrivedRegex = "([^ -/]+)-?%w* of class (%w+)" local arrivedRegexAlt = "([^ -/]+)-?%w* %(!!!!%) of class (%w+)" ---@param msg string ---@return table local function ParseArrived(msg) local stinkies = {} local name, class = string.match(msg, arrivedRegex) if not name or not class then name, class = string.match(msg, arrivedRegexAlt) end if not name or not class then return stinkies end local stinky = { name = name, class = class, seenAt = GetTime(), hostile = true } return stinkies end local frame = CreateFrame("Frame") frame:RegisterEvent("CHAT_MSG_CHANNEL") frame:SetScript("OnEvent", function(self, event, msg, sender, ...) if not Heimdall_Data.config.macroer.enabled then return end local doUpdate = false if string.find(msg, "^who:") then local whoStinkies = ParseWho(msg) for name, stinky in pairs(whoStinkies) do if stinky.hostile then recentStinkies[name] = stinky doUpdate = true end end end if string.find(msg, "^I see") then local seeStinkies = ParseSee(msg) for name, stinky in pairs(seeStinkies) do if stinky.hostile then recentStinkies[name] = stinky doUpdate = true end if not stinky.hostile then recentStinkies[name] = nil doUpdate = true end end end if string.find(msg, " and guild ") then local arrivedStinkies = ParseArrived(msg) for name, stinky in pairs(arrivedStinkies) do recentStinkies[name] = stinky doUpdate = true end end if doUpdate then FixMacro(recentStinkies) end end) print("Heimdall - Macroer loaded") end