local addonname, shared = ... ---@cast shared HeimdallShared ---@cast addonname string local ModuleName = "Commander" local helpMessages = { ru = { "1) who - пишет вам никнеймы текущих врагов и локу.", "2) classes - покажет классы врагов и число.", "3) howmany - общее число врагов (дурик 4 . огри 2 ) ", "4) + - атоинвайт в сбор пати и сброса кд.", "5) ++ -автоинвайт в пати аликов (если нужен рефрак)", "6 ) note Никнейм текст - добавление заметки.", "7) note Никнейм - посмотреть последние заметки.", "8) note Никнейм 5 - посмотреть конкретную заметку.", "9) note Никнейм 1..5 - посмотреть заметки от 1 до 5", "10) note Никнейм delete 1 - удалить заметку номер 1", "11) note Никнейм delete 1..5 - удалить заметки 1 до 5", }, en = { "1) who - reports currently tracked stinkies in orgrimmar and durotar", "2) classes - reports stinkies grouped by class", "3) howmany - reports stinkies grouped by zone", "4) + - automatically invites to group with duel rogue for cd reset", "5) ++ - automatically invites to alliance group", "6) note - adds a note for the specified character.", "7) note - lists the last N notes for the character.", "8) note i - lists the i-th note for the character.", "9) note i..j - lists notes from i to j for the character.", "10) note delete i - deletes the i-th note for the character.", "11) note delete i..j - deletes notes from i to j for the character.", }, } ---@diagnostic disable-next-line: missing-fields shared.Commander = {} function shared.Commander.Init() ---@param text string ---@param size number ---@return string[] local function Partition(text, size) local words = {} for word in text:gmatch("[^,]+") do words[#words + 1] = word end local ret = {} local currentChunk = "" for _, word in ipairs(words) do if #currentChunk + #word + 1 <= size then currentChunk = currentChunk .. (currentChunk == "" and word or " " .. word) else if #currentChunk > 0 then ret[#ret + 1] = currentChunk end currentChunk = word end end if #currentChunk > 0 then ret[#ret + 1] = currentChunk end return ret end ---@param arr table ---@return string[] local function Count(arr) local ret = {} for _, player in pairs(arr) do if shared.Whoer.ShouldNotifyForZone(player.zone) then ret[player.zone] = (ret[player.zone] or 0) + 1 end end local text = {} for zone, count in pairs(ret) do text[#text + 1] = string.format("%s: %d", zone, count) end return text end ---@param arr table ---@return string[] local function CountPartitioned(arr) local count = Count(arr) local text = {} for _, line in pairs(Partition(strjoin(", ", unpack(count)), 200)) do text[#text + 1] = line end return text end ---@param arr table ---@return string[] local function Who(arr) local ret = {} for _, player in pairs(arr) do if shared.Whoer.ShouldNotifyForZone(player.zone) then ret[#ret + 1] = string.format( "%s/%s (%s) %s", player.name, player.class, player.zone, player.stinky and "(!!!!)" or "" ) end end if Heimdall_Data.config.commander.debug then print(string.format("[%s] Command result: %s", ModuleName, strjoin(", ", unpack(ret)))) end return ret end ---@param arr table ---@return string[] local function WhoPartitioned(arr) local who = Who(arr) local text = {} for _, line in pairs(Partition(strjoin(", ", unpack(who)), 200)) do text[#text + 1] = "who: " .. line end return text end ---@param arr table ---@return string[] local function CountClass(arr) local ret = {} for _, player in pairs(arr) do if shared.Whoer.ShouldNotifyForZone(player.zone) then ret[player.class] = (ret[player.class] or 0) + 1 end end local text = {} for class, count in pairs(ret) do text[#text + 1] = string.format("%s: %d", class, count) end if Heimdall_Data.config.commander.debug then print(string.format("[%s] Message text: %s", ModuleName, strjoin(", ", unpack(text)))) end return text end ---@param arr table ---@return string[] local function CountClassPartitioned(arr) local countClass = CountClass(arr) local text = {} for _, line in pairs(Partition(strjoin(", ", unpack(countClass)), 200)) do text[#text + 1] = line end return text end local function CountClassPartitionedStinkies() if Heimdall_Data.config.commander.debug then print(string.format("[%s] Executing: CountClassPartitionedStinkies", ModuleName)) end local res = CountClassPartitioned(HeimdallStinkies) if #res == 0 then return { "No stinkies found" } end return res end local function WhoPartitionedStinkies() if Heimdall_Data.config.commander.debug then print(string.format("[%s] Executing: WhoPartitionedStinkies", ModuleName)) shared.dumpTable(HeimdallStinkies) end local res = WhoPartitioned(HeimdallStinkies) if #res == 0 then return { "No stinkies found" } end return res end local function CountPartitionedStinkies() if Heimdall_Data.config.commander.debug then print(string.format("[%s] Executing: CountPartitionedStinkies", ModuleName)) end local res = CountPartitioned(HeimdallStinkies) if #res == 0 then return { "No stinkies found" } end return res end local function HelpRu() if Heimdall_Data.config.commander.debug then print(string.format("[%s] Executing: HelpRu", ModuleName)) end return helpMessages.ru end local function HelpEn() if Heimdall_Data.config.commander.debug then print(string.format("[%s] Executing: HelpEn", ModuleName)) end return helpMessages.en end local groupInviteFrame = CreateFrame("Frame") groupInviteFrame:SetScript("OnEvent", function(self, event, ...) if Heimdall_Data.config.commander.debug then print(string.format("[%s] Event received", ModuleName)) end AcceptGroup() groupInviteFrame:UnregisterEvent("PARTY_INVITE_REQUEST") C_Timer.NewTimer(0.1, function() if Heimdall_Data.config.commander.debug then print(string.format("[%s] Click event triggered", ModuleName)) end _G["StaticPopup1Button1"]:Click() end, 1) end) local function JoinGroup() if Heimdall_Data.config.commander.debug then print(string.format("[%s] JoinGroup command received", ModuleName)) end groupInviteFrame:RegisterEvent("PARTY_INVITE_REQUEST") C_Timer.NewTimer(10, function() groupInviteFrame:UnregisterEvent("PARTY_INVITE_REQUEST") end, 1) return { "+" } end local function LeaveGroup() if Heimdall_Data.config.commander.debug then print(string.format("[%s] LeaveGroup command received", ModuleName)) end LeaveParty() return {} end ---@param target string local function FollowTarget(target) if Heimdall_Data.config.commander.debug then print(string.format("[%s] Following target: %s", ModuleName, target)) end if not target then return end FollowUnit(target) return {} end ---@param args string[] local function MacroTarget(args) if Heimdall_Data.config.commander.debug then print(string.format("[%s] Macroing: %s", ModuleName, strjoin(" ", unpack(args)))) end if #args < 2 or #args % 2 ~= 0 then if #args < 2 or #args % 2 ~= 0 then if Heimdall_Data.config.commander.debug then print(string.format("[%s] Invalid number of arguments for MacroTarget", ModuleName)) end return {} end end table.remove(args, 1) for i = 1, #args do local stinky = strtrim(args[i]) local name = stinky:match("([^/]+)") local class = stinky:match("/([^ $]+)") if Heimdall_Data.config.commander.debug then print(string.format("[%s] Adding stinky: %s/%s", ModuleName, name, tostring(class))) end shared.stinkyTracker.stinkies[name] = { name = name, class = class or "unknown", seenAt = GetTime(), hostile = true, } end return {} end ---@class Command ---@field keywordRe string ---@field commanderOnly boolean ---@field callback fun(...: any): string[] local commands = { { keywordRe = "^who$", commanderOnly = false, callback = WhoPartitionedStinkies }, { keywordRe = "^howmany$", commanderOnly = false, callback = CountPartitionedStinkies }, { keywordRe = "^classes$", commanderOnly = false, callback = CountClassPartitionedStinkies }, { keywordRe = "^help$", commanderOnly = false, callback = HelpRu }, { keywordRe = "^helpen$", commanderOnly = false, callback = HelpEn }, { keywordRe = "^joingroup$", commanderOnly = false, callback = JoinGroup }, { keywordRe = "^leavegroup$", commanderOnly = false, callback = LeaveGroup }, { keywordRe = "^follow$", commanderOnly = false, callback = FollowTarget }, { keywordRe = "^macro", commanderOnly = false, callback = MacroTarget }, } local commanderChannelFrame = CreateFrame("Frame") commanderChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL") commanderChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...) --if Heimdall_Data.config.commander.debug then -- print(string.format("[%s] Event received", ModuleName)) -- shared.dumpTable(Heimdall_Data.config.commander) --end if not Heimdall_Data.config.commander.enabled then --if Heimdall_Data.config.commander.debug then -- print(string.format("[%s] Module disabled, ignoring event", ModuleName)) --end return end local channelId = select(6, ...) local _, channelname = GetChannelName(channelId) local ok = false for _, channel in pairs(Heimdall_Data.config.commander.channels) do if channel == channelname then ok = true break end end if not ok then if Heimdall_Data.config.commander.debug then print( string.format( "[%s] Channel name '%s' does not match any of the channels '%s'", ModuleName, channelname, table.concat(Heimdall_Data.config.commander.channels, ", ") ) ) end return end sender = string.match(sender, "^[^-]+") if Heimdall_Data.config.commander.debug then print(string.format("[%s] Message from: %s", ModuleName, sender)) shared.dumpTable(Heimdall_Data.config.commander) end for _, command in ipairs(commands) do local enabled = Heimdall_Data.config.commander.commands[command.keywordRe] == true or false if Heimdall_Data.config.commander.debug then print(string.format("[%s] Command match: %s = %s", ModuleName, command.keywordRe, tostring(enabled))) end if enabled and ( not command.commanderOnly or (command.commanderOnly and sender == Heimdall_Data.config.commander.commander) ) then if msg:match(command.keywordRe) then local messages = command.callback({ strsplit(",", msg) }) if Heimdall_Data.config.commander.debug then print(string.format("[%s] Messages to send: %s", ModuleName, strjoin(", ", unpack(messages)))) end for _, message in ipairs(messages) do ---@type Message local msg = { channel = "C", data = channelname, message = message, } if Heimdall_Data.config.commander.debug then print(string.format("[%s] Queuing message", ModuleName)) shared.dumpTable(msg) end --table.insert(shared.messenger.queue, msg) table.insert(shared.networkMessenger.queue, msg) end end end end end) print("[Heimdall] Commander module loaded") end