Refactor CombatAlerter, Commander, Inviter, Macroer, Sniffer modules for improved structure and clarity

This commit is contained in:
2025-05-18 12:12:57 +02:00
parent 0edf0561d8
commit 0057ac3a5c
5 changed files with 840 additions and 795 deletions

View File

@@ -7,134 +7,135 @@ local ModuleName = "CombatAlerter"
---@field debug boolean ---@field debug boolean
---@field channels string[] ---@field channels string[]
---@diagnostic disable-next-line: missing-fields ---@class CombatAlerter
shared.CombatAlerter = {} shared.CombatAlerter = {
function shared.CombatAlerter.Init() Init = function()
local alerted = {} local alerted = {}
local combatAlerterFrame = CreateFrame("Frame") local combatAlerterFrame = CreateFrame("Frame")
combatAlerterFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") combatAlerterFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
combatAlerterFrame:SetScript("OnEvent", function(self, event, ...) combatAlerterFrame:SetScript("OnEvent", function(self, event, ...)
if Heimdall_Data.config.combatAlerter.debug then
print(string.format("[%s] Combat log event received", ModuleName))
end
if not Heimdall_Data.config.combatAlerter.enabled then
if Heimdall_Data.config.combatAlerter.debug then if Heimdall_Data.config.combatAlerter.debug then
print(string.format("[%s] Module disabled, ignoring combat event", ModuleName)) print(string.format("[%s] Combat log event received", ModuleName))
end end
return if not Heimdall_Data.config.combatAlerter.enabled then
end if Heimdall_Data.config.combatAlerter.debug then
print(string.format("[%s] Module disabled, ignoring combat event", ModuleName))
---@type string|nil, string, string end
local err, source, destination return
destination, err = CLEUParser.GetDestName(...)
if err then
if Heimdall_Data.config.combatAlerter.debug then
print(string.format("[%s] Error getting destination: %s", ModuleName, err))
end end
return
end
if Heimdall_Data.config.combatAlerter.debug then ---@type string|nil, string, string
print(string.format("[%s] Combat event destination: %s", ModuleName, destination)) local err, source, destination
end
if destination ~= UnitName("player") then destination, err = CLEUParser.GetDestName(...)
if Heimdall_Data.config.combatAlerter.debug then if err then
print(string.format("[%s] Ignoring event - not targeted at player", ModuleName)) if Heimdall_Data.config.combatAlerter.debug then
print(string.format("[%s] Error getting destination: %s", ModuleName, err))
end
return
end end
return
end
source, err = CLEUParser.GetSourceName(...)
if err then
if Heimdall_Data.config.combatAlerter.debug then if Heimdall_Data.config.combatAlerter.debug then
print(string.format("[%s] Error getting source, using 'unknown': %s", ModuleName, err)) print(string.format("[%s] Combat event destination: %s", ModuleName, destination))
end end
source = "unknown"
end
if Heimdall_Data.config.combatAlerter.debug then if destination ~= UnitName("player") then
print(string.format("[%s] Combat event source: %s", ModuleName, source)) if Heimdall_Data.config.combatAlerter.debug then
end print(string.format("[%s] Ignoring event - not targeted at player", ModuleName))
end
return
end
source, err = CLEUParser.GetSourceName(...)
if err then
if Heimdall_Data.config.combatAlerter.debug then
print(string.format("[%s] Error getting source, using 'unknown': %s", ModuleName, err))
end
source = "unknown"
end
if shared.StinkyTracker.IsStinky(source) then
if Heimdall_Data.config.combatAlerter.debug then if Heimdall_Data.config.combatAlerter.debug then
print( print(string.format("[%s] Combat event source: %s", ModuleName, source))
string.format( end
"[%s] Source is tracked stinky: %s (Already alerted: %s)",
ModuleName, if shared.StinkyTracker.IsStinky(source) then
source, if Heimdall_Data.config.combatAlerter.debug then
tostring(alerted[source] or false) print(
string.format(
"[%s] Source is tracked stinky: %s (Already alerted: %s)",
ModuleName,
source,
tostring(alerted[source] or false)
)
) )
) end
end if alerted[source] then return end
if alerted[source] then return end
alerted[source] = true alerted[source] = true
local x, y = GetPlayerMapPosition("player") local x, y = GetPlayerMapPosition("player")
local zone, subZone = GetZoneText(), GetSubZoneText() local zone, subZone = GetZoneText(), GetSubZoneText()
if Heimdall_Data.config.combatAlerter.debug then if Heimdall_Data.config.combatAlerter.debug then
print( print(
string.format( string.format(
"[%s] Player location: %s/%s at %.2f,%.2f", "[%s] Player location: %s/%s at %.2f,%.2f",
ModuleName, ModuleName,
zone, zone,
subZone, subZone,
x * 100,
y * 100
)
)
end
SetMapToCurrentZone()
SetMapByID(GetCurrentMapAreaID())
local areaId = GetCurrentMapAreaID()
for _, channel in pairs(Heimdall_Data.config.combatAlerter.channels) do
local locale = shared.GetLocaleForChannel(channel)
local text = string.format(
shared._L("combatAlerterInCombat", locale),
source,
shared._L("zone", locale),
shared._L("subZone", locale),
tostring(areaId),
x * 100, x * 100,
y * 100 y * 100
) )
) ---@type Message
end local msg = {
channel = "C",
SetMapToCurrentZone() data = channel,
SetMapByID(GetCurrentMapAreaID()) message = text,
local areaId = GetCurrentMapAreaID() }
if Heimdall_Data.config.combatAlerter.debug then
for _, channel in pairs(Heimdall_Data.config.combatAlerter.channels) do print(string.format("[%s] Queuing alert message", ModuleName))
local locale = shared.GetLocaleForChannel(channel) shared.dumpTable(msg)
local text = string.format( end
shared._L("combatAlerterInCombat", locale), table.insert(shared.messenger.queue, msg)
source,
shared._L("zone", locale),
shared._L("subZone", locale),
tostring(areaId),
x * 100,
y * 100
)
---@type Message
local msg = {
channel = "C",
data = channel,
message = text,
}
if Heimdall_Data.config.combatAlerter.debug then
print(string.format("[%s] Queuing alert message", ModuleName))
shared.dumpTable(msg)
end end
table.insert(shared.messenger.queue, msg) elseif Heimdall_Data.config.combatAlerter.debug then
print(string.format("[%s] Source not in stinky list, ignoring: %s", ModuleName, source))
end end
elseif Heimdall_Data.config.combatAlerter.debug then end)
print(string.format("[%s] Source not in stinky list, ignoring: %s", ModuleName, source))
end
end)
local combatTriggerFrame = CreateFrame("Frame") local combatTriggerFrame = CreateFrame("Frame")
combatTriggerFrame:RegisterEvent("PLAYER_REGEN_DISABLED") combatTriggerFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
combatTriggerFrame:RegisterEvent("PLAYER_REGEN_ENABLED") combatTriggerFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
combatTriggerFrame:SetScript("OnEvent", function(self, event, ...) combatTriggerFrame:SetScript("OnEvent", function(self, event, ...)
if Heimdall_Data.config.combatAlerter.debug then if Heimdall_Data.config.combatAlerter.debug then
print(string.format("[%s] Combat state changed: %s", ModuleName, event)) print(string.format("[%s] Combat state changed: %s", ModuleName, event))
if event == "PLAYER_REGEN_DISABLED" then if event == "PLAYER_REGEN_DISABLED" then
print(string.format("[%s] Entered combat - Resetting alerts", ModuleName)) print(string.format("[%s] Entered combat - Resetting alerts", ModuleName))
else else
print(string.format("[%s] Left combat - Resetting alerts", ModuleName)) print(string.format("[%s] Left combat - Resetting alerts", ModuleName))
end
end end
end alerted = {}
alerted = {} end)
end)
if Heimdall_Data.config.combatAlerter.debug then print(string.format("[%s] Module initialized", ModuleName)) end if Heimdall_Data.config.combatAlerter.debug then print(string.format("[%s] Module initialized", ModuleName)) end
print("[Heimdall] CombatAlerter loaded") print("[Heimdall] CombatAlerter loaded")
end end,
}

View File

@@ -39,344 +39,356 @@ local helpMessages = {
}, },
} }
---@diagnostic disable-next-line: missing-fields ---@class Commander
shared.Commander = {} shared.Commander = {
function shared.Commander.Init() Init = function()
---@param text string ---@param text string
---@param size number ---@param size number
---@return string[] ---@return string[]
local function Partition(text, size) local function Partition(text, size)
local words = {} local words = {}
for word in text:gmatch("[^,]+") do for word in text:gmatch("[^,]+") do
words[#words + 1] = word 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
end
if #currentChunk > 0 then ret[#ret + 1] = currentChunk end local ret = {}
local currentChunk = ""
return ret for _, word in ipairs(words) do
end if #currentChunk + #word + 1 <= size then
---@param arr table<string, Player> currentChunk = currentChunk .. (currentChunk == "" and word or " " .. word)
---@return string[] else
local function Count(arr) if #currentChunk > 0 then ret[#ret + 1] = currentChunk end
local ret = {} currentChunk = word
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<string, Player>
---@return string[]
local function CountPartitioned(arr)
local count = Count(arr)
local text = {}
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
for _, line in pairs(Partition(strjoin(", ", unpack(count)), 200)) do
text[#text + 1] = line
end
return text
end
---@param arr table<string, Player>
---@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<string, Player>
---@return string[]
local function WhoPartitioned(arr)
local who = Who(arr)
local text = {}
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
for _, line in pairs(Partition(strjoin(", ", unpack(who)), 200)) do
text[#text + 1] = "who: " .. line
end
return text
end
---@param arr table<string, Player>
---@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<string, Player>
---@return string[]
local function CountClassPartitioned(arr)
local countClass = CountClass(arr)
local text = {}
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
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
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
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 end
return {}
end end
end
table.remove(args, 1)
for i = 1, #args do if #currentChunk > 0 then ret[#ret + 1] = currentChunk end
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.Track({
name = name,
class = class or "unknown",
seenAt = GetTime(),
hostile = true,
})
if Heimdall_Data.config.commander.debug then
print(string.format("[%s] Added stinky: %s/%s", ModuleName, name, tostring(class)))
end
end
return {}
end
---@param args string[] return ret
local function IgnoreMacroTarget(args) end
if Heimdall_Data.config.commander.debug then ---@param arr table<string, Player>
---@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<string, Player>
---@return string[]
local function CountPartitioned(arr)
local count = Count(arr)
local text = {}
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack ---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
print(string.format("[%s] Macroing: %s", ModuleName, strjoin(" ", unpack(args)))) for _, line in pairs(Partition(strjoin(", ", unpack(count)), 200)) do
text[#text + 1] = line
end
return text
end end
if #args < 1 then ---@param arr table<string, Player>
---@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 if Heimdall_Data.config.commander.debug then
print(string.format("[%s] Invalid number of arguments for IgnoreMacroTarget", ModuleName)) print(string.format("[%s] Command result: %s", ModuleName, strjoin(", ", unpack(ret))))
end
return ret
end
---@param arr table<string, Player>
---@return string[]
local function WhoPartitioned(arr)
local who = Who(arr)
local text = {}
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
for _, line in pairs(Partition(strjoin(", ", unpack(who)), 200)) do
text[#text + 1] = "who: " .. line
end
return text
end
---@param arr table<string, Player>
---@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<string, Player>
---@return string[]
local function CountClassPartitioned(arr)
local countClass = CountClass(arr)
local text = {}
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
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
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
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.Track({
name = name,
class = class or "unknown",
seenAt = GetTime(),
hostile = true,
})
if Heimdall_Data.config.commander.debug then
print(string.format("[%s] Added stinky: %s/%s", ModuleName, name, tostring(class)))
end
end end
return {} return {}
end end
table.remove(args, 1)
for i = 1, #args do ---@param args string[]
local stinky = strtrim(args[i]) local function IgnoreMacroTarget(args)
local name = stinky:match("([^/]+)")
if Heimdall_Data.config.commander.debug then if Heimdall_Data.config.commander.debug then
print(string.format("[%s] Ignoring stinky: %s", ModuleName, name)) ---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
print(string.format("[%s] Macroing: %s", ModuleName, strjoin(" ", unpack(args))))
end end
shared.StinkyTracker.Ignore(name) if #args < 1 then
if Heimdall_Data.config.commander.debug then
print(string.format("[%s] Invalid number of arguments for IgnoreMacroTarget", ModuleName))
end
return {}
end
table.remove(args, 1)
for i = 1, #args do
local stinky = strtrim(args[i])
local name = stinky:match("([^/]+)")
if Heimdall_Data.config.commander.debug then
print(string.format("[%s] Ignoring stinky: %s", ModuleName, name))
end
shared.StinkyTracker.Ignore(name)
end
return {}
end end
return {}
end
---@class Command ---@class Command
---@field keywordRe string ---@field keywordRe string
---@field commanderOnly boolean ---@field commanderOnly boolean
---@field callback fun(...: any): string[] ---@field callback fun(...: any): string[]
local commands = { local commands = {
{ keywordRe = "^who$", commanderOnly = false, callback = WhoPartitionedStinkies }, { keywordRe = "^who$", commanderOnly = false, callback = WhoPartitionedStinkies },
{ keywordRe = "^howmany$", commanderOnly = false, callback = CountPartitionedStinkies }, { keywordRe = "^howmany$", commanderOnly = false, callback = CountPartitionedStinkies },
{ keywordRe = "^classes$", commanderOnly = false, callback = CountClassPartitionedStinkies }, { keywordRe = "^classes$", commanderOnly = false, callback = CountClassPartitionedStinkies },
{ keywordRe = "^help$", commanderOnly = false, callback = HelpRu }, { keywordRe = "^help$", commanderOnly = false, callback = HelpRu },
{ keywordRe = "^helpen$", commanderOnly = false, callback = HelpEn }, { keywordRe = "^helpen$", commanderOnly = false, callback = HelpEn },
{ keywordRe = "^joingroup$", commanderOnly = false, callback = JoinGroup }, { keywordRe = "^joingroup$", commanderOnly = false, callback = JoinGroup },
{ keywordRe = "^leavegroup$", commanderOnly = false, callback = LeaveGroup }, { keywordRe = "^leavegroup$", commanderOnly = false, callback = LeaveGroup },
{ keywordRe = "^follow$", commanderOnly = false, callback = FollowTarget }, { keywordRe = "^follow$", commanderOnly = false, callback = FollowTarget },
{ keywordRe = "^macro", commanderOnly = false, callback = MacroTarget }, { keywordRe = "^macro", commanderOnly = false, callback = MacroTarget },
{ keywordRe = "^ignore", commanderOnly = false, callback = IgnoreMacroTarget }, { keywordRe = "^ignore", commanderOnly = false, callback = IgnoreMacroTarget },
} }
local commanderChannelFrame = CreateFrame("Frame") local commanderChannelFrame = CreateFrame("Frame")
commanderChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL") commanderChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
commanderChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...) 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 --if Heimdall_Data.config.commander.debug then
-- print(string.format("[%s] Module disabled, ignoring event", ModuleName)) -- print(string.format("[%s] Event received", ModuleName))
-- shared.dumpTable(Heimdall_Data.config.commander)
--end --end
return if not Heimdall_Data.config.commander.enabled then
end --if Heimdall_Data.config.commander.debug then
local channelId = select(6, ...) -- print(string.format("[%s] Module disabled, ignoring event", ModuleName))
local _, channelname = GetChannelName(channelId) --end
local ok = false return
for _, channel in pairs(Heimdall_Data.config.commander.channels) do
if channel == channelname then
ok = true
break
end end
end local channelId = select(6, ...)
if not ok then local _, channelname = GetChannelName(channelId)
if Heimdall_Data.config.commander.debug then local ok = false
print( for _, channel in pairs(Heimdall_Data.config.commander.channels) do
string.format( if channel == channelname then
"[%s] Channel name '%s' does not match any of the channels '%s'", ok = true
ModuleName, break
channelname, end
table.concat(Heimdall_Data.config.commander.channels, ", ") 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 end
return
end
sender = string.match(sender, "^[^-]+") 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 if Heimdall_Data.config.commander.debug then
print(string.format("[%s] Command match: %s = %s", ModuleName, command.keywordRe, tostring(enabled))) print(string.format("[%s] Message from: %s", ModuleName, sender))
shared.dumpTable(Heimdall_Data.config.commander)
end end
if
enabled for _, command in ipairs(commands) do
and ( local enabled = Heimdall_Data.config.commander.commands[command.keywordRe] == true or false
not command.commanderOnly if Heimdall_Data.config.commander.debug then
or (command.commanderOnly and sender == Heimdall_Data.config.commander.commander) print(
) string.format("[%s] Command match: %s = %s", ModuleName, command.keywordRe, tostring(enabled))
then )
if msg:match(command.keywordRe) then end
---@diagnostic disable-next-line: redundant-parameter Currently luals does not support variadic functions as a @field if
local messages = command.callback({ strsplit(",", msg) }) enabled
if Heimdall_Data.config.commander.debug then and (
---@diagnostic disable-next-line: param-type-mismatch not command.commanderOnly
print(string.format("[%s] Messages to send: %s", ModuleName, strjoin(", ", unpack(messages)))) -- if Heimdall_Data.config.commander.debug then print(string.format("[%s] Ignoring command, sender %s not commander %s", ModuleName, sender, Heimdall_Data.config.commander.commander)) end
end
for _, message in ipairs(messages) do
---@type Message
local returnmsg = {
channel = "C", or (command.commanderOnly and sender == Heimdall_Data.config.commander.commander)
data = channelname, )
message = message, then
} if msg:match(command.keywordRe) then
---@diagnostic disable-next-line: redundant-parameter Currently luals does not support variadic functions as a @field
local messages = command.callback({ strsplit(",", msg) })
if Heimdall_Data.config.commander.debug then if Heimdall_Data.config.commander.debug then
print(string.format("[%s] Queuing message", ModuleName)) ---@diagnostic disable-next-line: param-type-mismatch
shared.dumpTable(msg) print(
string.format("[%s] Messages to send: %s", ModuleName, strjoin(", ", unpack(messages)))
)
end
for _, message in ipairs(messages) do
---@type Message
local returnmsg = {
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, returnmsg)
end end
--table.insert(shared.messenger.queue, msg)
table.insert(shared.networkMessenger.queue, returnmsg)
end end
end end
end end
end end)
end)
print("[Heimdall] Commander module loaded") print("[Heimdall] Commander module loaded")
end end,
}

View File

@@ -1,259 +1,276 @@
local _, shared = ... local _, shared = ...
---@cast shared HeimdallShared ---@cast shared HeimdallShared
---@class HeimdallInviterConfig
---@field enabled boolean
---@field debug boolean
---@field channels string[]
---@field keyword string
---@field allAssist boolean
---@field agentsAssist boolean
---@field throttle number
---@field kickOffline boolean
---@field cleanupInterval number
---@field afkThreshold number
---@field listeningChannel table<string, boolean>
local ModuleName = "Inviter" local ModuleName = "Inviter"
---@diagnostic disable-next-line: missing-fields ---@class Inviter
shared.Inviter = {} shared.Inviter = {
function shared.Inviter.Init() Init = function()
-- Fallback for old config -- Fallback for old config
if type(Heimdall_Data.config.inviter.listeningChannel) == "string" then if type(Heimdall_Data.config.inviter.listeningChannel) == "string" then
Heimdall_Data.config.inviter.listeningChannel = { Heimdall_Data.config.inviter.listeningChannel = {
[Heimdall_Data.config.inviter.listeningChannel] = true, [Heimdall_Data.config.inviter.listeningChannel] = true,
} }
end
---@type Timer
local updateTimer = nil
local function FixGroup()
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Checking and fixing group configuration", ModuleName))
end end
---@type Timer
local updateTimer = nil
if not IsInRaid() then local function FixGroup()
if Heimdall_Data.config.inviter.debug then if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Converting party to raid", ModuleName)) print(string.format("[%s] Checking and fixing group configuration", ModuleName))
end
ConvertToRaid()
end
if Heimdall_Data.config.inviter.allAssist then
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Setting all members to assistant", ModuleName))
end
SetEveryoneIsAssistant()
end
if Heimdall_Data.config.inviter.agentsAssist then
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Processing agents for assistant promotion", ModuleName))
end end
shared.AgentTracker.ForEach(function(agent) if not IsInRaid() then
if UnitInParty(agent) and not UnitIsGroupLeader(agent) and not UnitIsRaidOfficer(agent) then
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Promoting agent to assistant: %s", ModuleName, agent))
end
PromoteToAssistant(agent, true)
elseif Heimdall_Data.config.inviter.debug then
if not UnitInParty(agent) then
print(string.format("[%s] Agent not in party: %s", ModuleName, agent))
elseif UnitIsGroupLeader(agent) then
print(string.format("[%s] Agent is already leader: %s", ModuleName, agent))
elseif UnitIsRaidOfficer(agent) then
print(string.format("[%s] Agent is already assistant: %s", ModuleName, agent))
end
end
end)
end
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Group configuration update complete", ModuleName))
end
end
---@param name string
---@return Frame?
local function FindPlayerRaidFrame(name)
for group = 1, 8 do
for player = 1, 5 do
local button = _G[string.format("ElvUF_RaidGroup%dUnitButton%d", group, player)]
if Heimdall_Data.config.inviter.debug then if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] button = %s", ModuleName, tostring(button))) print(string.format("[%s] Converting party to raid", ModuleName))
end
local unitName = button and button.unit and UnitName(button.unit)
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] unitName = %s", ModuleName, tostring(unitName)))
end
if unitName == name then
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] unitName == name", ModuleName))
end
return button
end end
ConvertToRaid()
end end
end
return nil
end
local framePool = {} if Heimdall_Data.config.inviter.allAssist then
local playerButtons = {} if Heimdall_Data.config.inviter.debug then
setmetatable(playerButtons, { __mode = "kv" }) print(string.format("[%s] Setting all members to assistant", ModuleName))
---@param players string[] end
local function OverlayKickButtons(players) SetEveryoneIsAssistant()
for _, frame in pairs(framePool) do end
frame:Hide()
end
for _, name in pairs(players) do
local frame = FindPlayerRaidFrame(name)
if frame then
playerButtons[name] = frame
-- All of these are ELVUI specific so they won't be in our meta...
---@diagnostic disable-next-line: undefined-field
local button = framePool[frame.unit]
or CreateFrame(
"Button",
---@diagnostic disable-next-line: undefined-field
string.format("HeimdallKickButton%s", frame.unit, frame, "SecureActionButtonTemplate")
)
---@diagnostic disable-next-line: undefined-field
framePool[frame.unit] = button
---@diagnostic disable-next-line: undefined-field if Heimdall_Data.config.inviter.agentsAssist then
button:SetSize(frame.UNIT_WIDTH / 2, frame.UNIT_HEIGHT / 2) if Heimdall_Data.config.inviter.debug then
button:SetPoint("CENTER", frame, "CENTER", 0, 0) print(string.format("[%s] Processing agents for assistant promotion", ModuleName))
button:SetNormalTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon") end
button:SetHighlightTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
button:SetPushedTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon") shared.AgentTracker.ForEach(function(agent)
button:SetDisabledTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon") if UnitInParty(agent) and not UnitIsGroupLeader(agent) and not UnitIsRaidOfficer(agent) then
button:SetAlpha(0.5) if Heimdall_Data.config.inviter.debug then
button:Show() print(string.format("[%s] Promoting agent to assistant: %s", ModuleName, agent))
button:SetScript("OnClick", function() end
UninviteUnit(name) PromoteToAssistant(agent, true)
button:Hide() elseif Heimdall_Data.config.inviter.debug then
if not UnitInParty(agent) then
print(string.format("[%s] Agent not in party: %s", ModuleName, agent))
elseif UnitIsGroupLeader(agent) then
print(string.format("[%s] Agent is already leader: %s", ModuleName, agent))
elseif UnitIsRaidOfficer(agent) then
print(string.format("[%s] Agent is already assistant: %s", ModuleName, agent))
end
end
end) end)
else end
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Frame for player %s not found", ModuleName, name)) if Heimdall_Data.config.inviter.debug then
end print(string.format("[%s] Group configuration update complete", ModuleName))
end end
end end
end
---@type table<string, number> ---@param name string
local groupMembers = {} ---@return Frame?
local function CleanGroups() local function FindPlayerRaidFrame(name)
if not Heimdall_Data.config.inviter.kickOffline then return end for group = 1, 8 do
print("Cleaning groups") for player = 1, 5 do
local now = GetTime() local button = _G[string.format("ElvUF_RaidGroup%dUnitButton%d", group, player)]
for i = 1, 40 do if Heimdall_Data.config.inviter.debug then
local unit = "raid" .. i print(string.format("[%s] button = %s", ModuleName, tostring(button)))
if UnitExists(unit) then end
local name = UnitName(unit)
if name then local unitName = button and button.unit and UnitName(button.unit)
-- When we load (into game) we want to consider everyone "online" if Heimdall_Data.config.inviter.debug then
-- In other words everyone we haven't seen before is "online" the first time we see them print(string.format("[%s] unitName = %s", ModuleName, tostring(unitName)))
-- This is to avoid kicking people who might not be offline which we don't know because we just logged in end
if not groupMembers[name] then if unitName == name then
groupMembers[name] = now if Heimdall_Data.config.inviter.debug then
else print(string.format("[%s] unitName == name", ModuleName))
local online = UnitIsConnected(unit) end
if online then groupMembers[name] = now end return button
end
end
end
return nil
end
local framePool = {}
local playerButtons = {}
setmetatable(playerButtons, { __mode = "kv" })
---@param players string[]
local function OverlayKickButtons(players)
for _, frame in pairs(framePool) do
frame:Hide()
end
for _, name in pairs(players) do
local frame = FindPlayerRaidFrame(name)
if frame then
playerButtons[name] = frame
-- All of these are ELVUI specific so they won't be in our meta...
---@diagnostic disable-next-line: undefined-field
local button = framePool[frame.unit]
or CreateFrame(
"Button",
---@diagnostic disable-next-line: undefined-field
string.format("HeimdallKickButton%s", frame.unit, frame, "SecureActionButtonTemplate")
)
---@diagnostic disable-next-line: undefined-field
framePool[frame.unit] = button
---@diagnostic disable-next-line: undefined-field
button:SetSize(frame.UNIT_WIDTH / 2, frame.UNIT_HEIGHT / 2)
button:SetPoint("CENTER", frame, "CENTER", 0, 0)
button:SetNormalTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
button:SetHighlightTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
button:SetPushedTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
button:SetDisabledTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
button:SetAlpha(0.5)
button:Show()
button:SetScript("OnClick", function()
UninviteUnit(name)
button:Hide()
end)
else
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Frame for player %s not found", ModuleName, name))
end end
end end
end end
end end
local afkPlayers = {}
for name, time in pairs(groupMembers) do ---@type table<string, number>
if not UnitInParty(name) then local groupMembers = {}
print(string.format("%s no longer in party", name)) local function CleanGroups()
groupMembers[name] = nil if not Heimdall_Data.config.inviter.kickOffline then return end
else print("Cleaning groups")
if time < now - Heimdall_Data.config.inviter.afkThreshold then local now = GetTime()
print(string.format("Kicking %s for being offline", name)) for i = 1, 40 do
afkPlayers[#afkPlayers + 1] = name local unit = "raid" .. i
-- Blyat this is protected... if UnitExists(unit) then
-- UninviteUnit(name) local name = UnitName(unit)
if name then
-- When we load (into game) we want to consider everyone "online"
-- In other words everyone we haven't seen before is "online" the first time we see them
-- This is to avoid kicking people who might not be offline which we don't know because we just logged in
if not groupMembers[name] then
groupMembers[name] = now
else
local online = UnitIsConnected(unit)
if online then groupMembers[name] = now end
end
end
end end
end end
end local afkPlayers = {}
OverlayKickButtons(afkPlayers) for name, time in pairs(groupMembers) do
end if not UnitInParty(name) then
local function Tick() print(string.format("%s no longer in party", name))
CleanGroups() groupMembers[name] = nil
C_Timer.NewTimer(Heimdall_Data.config.inviter.cleanupInterval, Tick, 1) else
end if time < now - Heimdall_Data.config.inviter.afkThreshold then
Tick() print(string.format("Kicking %s for being offline", name))
afkPlayers[#afkPlayers + 1] = name
local groupRosterUpdateFrame = CreateFrame("Frame") -- Blyat this is protected...
groupRosterUpdateFrame:RegisterEvent("GROUP_ROSTER_UPDATE") -- UninviteUnit(name)
groupRosterUpdateFrame:SetScript("OnEvent", function(self, event, ...) end
if Heimdall_Data.config.inviter.debug then end
print(string.format("[%s] Event received: %s", ModuleName, event))
end
if not Heimdall_Data.config.inviter.enabled then
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Module disabled, ignoring event", ModuleName))
end end
return OverlayKickButtons(afkPlayers)
end end
local function Tick()
CleanGroups()
C_Timer.NewTimer(Heimdall_Data.config.inviter.cleanupInterval, Tick, 1)
end
Tick()
local groupRosterUpdateFrame = CreateFrame("Frame")
groupRosterUpdateFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
groupRosterUpdateFrame:SetScript("OnEvent", function(self, event, ...)
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Event received: %s", ModuleName, event))
end
if not Heimdall_Data.config.inviter.enabled then
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Module disabled, ignoring event", ModuleName))
end
return
end
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Group roster changed - Checking configuration", ModuleName))
end
if updateTimer then updateTimer:Cancel() end
updateTimer = C_Timer.NewTimer(Heimdall_Data.config.inviter.throttle, FixGroup)
end)
local inviterChannelFrame = CreateFrame("Frame")
inviterChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
inviterChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
--if Heimdall_Data.config.inviter.debug then
-- print(string.format("[%s] Chat message received: %s", ModuleName, msg))
-- shared.dumpTable(Heimdall_Data.config.inviter)
--end
if not Heimdall_Data.config.inviter.enabled then return end
local channelId = select(6, ...)
local _, channelname = GetChannelName(channelId)
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Channel name: %s", ModuleName, channelname))
end
local ok = false
for _, channel in pairs(Heimdall_Data.config.inviter.channels) do
if channel == channelname then
ok = true
break
end
end
if not ok then
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Channel name does not match any of the channels", ModuleName))
end
return
end
if msg == Heimdall_Data.config.inviter.keyword then
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Inviting %s", ModuleName, sender))
end
InviteUnit(sender)
else
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Message does not match keyword", ModuleName))
end
end
end)
if Heimdall_Data.config.inviter.debug then if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Group roster changed - Checking configuration", ModuleName)) print(
end string.format(
if updateTimer then updateTimer:Cancel() end "[%s] Module initialized - All assist: %s, Agents assist: %s",
updateTimer = C_Timer.NewTimer(Heimdall_Data.config.inviter.throttle, FixGroup) ModuleName,
end) tostring(Heimdall_Data.config.inviter.allAssist),
tostring(Heimdall_Data.config.inviter.agentsAssist)
local inviterChannelFrame = CreateFrame("Frame") )
inviterChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
inviterChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
--if Heimdall_Data.config.inviter.debug then
-- print(string.format("[%s] Chat message received: %s", ModuleName, msg))
-- shared.dumpTable(Heimdall_Data.config.inviter)
--end
if not Heimdall_Data.config.inviter.enabled then return end
local channelId = select(6, ...)
local _, channelname = GetChannelName(channelId)
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Channel name: %s", ModuleName, channelname))
end
local ok = false
for _, channel in pairs(Heimdall_Data.config.inviter.channels) do
if channel == channelname then
ok = true
break
end
end
if not ok then
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Channel name does not match any of the channels", ModuleName))
end
return
end
if msg == Heimdall_Data.config.inviter.keyword then
if Heimdall_Data.config.inviter.debug then print(string.format("[%s] Inviting %s", ModuleName, sender)) end
InviteUnit(sender)
else
if Heimdall_Data.config.inviter.debug then
print(string.format("[%s] Message does not match keyword", ModuleName))
end
end
end)
if Heimdall_Data.config.inviter.debug then
print(
string.format(
"[%s] Module initialized - All assist: %s, Agents assist: %s",
ModuleName,
tostring(Heimdall_Data.config.inviter.allAssist),
tostring(Heimdall_Data.config.inviter.agentsAssist)
) )
) end
end
if Heimdall_Data.config.inviter.debug then if Heimdall_Data.config.inviter.debug then
print( print(
string.format( string.format(
"[%s] Module initialized - All assist: %s, Agents assist: %s", "[%s] Module initialized - All assist: %s, Agents assist: %s",
ModuleName, ModuleName,
tostring(Heimdall_Data.config.inviter.allAssist), tostring(Heimdall_Data.config.inviter.allAssist),
tostring(Heimdall_Data.config.inviter.agentsAssist) tostring(Heimdall_Data.config.inviter.agentsAssist)
)
) )
) end
end print("[Heimdall] Inviter loaded")
print("[Heimdall] Inviter loaded") end,
end }

View File

@@ -1,96 +1,102 @@
local _, shared = ... local _, shared = ...
---@cast shared HeimdallShared ---@cast shared HeimdallShared
---@class HeimdallMacroerConfig
---@field enabled boolean
---@field debug boolean
---@field priority string[]
local ModuleName = "Macroer" local ModuleName = "Macroer"
---@diagnostic disable-next-line: missing-fields ---@class Macroer
shared.Macroer = {} shared.Macroer = {
function shared.Macroer.Init() Init = function()
local function FindOrCreateMacro(macroName) local function FindOrCreateMacro(macroName)
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Finding or creating macro: %s", ModuleName, macroName))
end
local idx = GetMacroIndexByName(macroName)
if idx == 0 then
if Heimdall_Data.config.macroer.debug then if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Creating new macro: %s", ModuleName, macroName)) print(string.format("[%s] Finding or creating macro: %s", ModuleName, macroName))
end end
CreateMacro(macroName, "INV_Misc_QuestionMark", "") local idx = GetMacroIndexByName(macroName)
end if idx == 0 then
idx = GetMacroIndexByName(macroName)
if Heimdall_Data.config.macroer.debug then print(string.format("[%s] Macro index: %d", ModuleName, idx)) end
return idx
end
---@param stinkies table<string, Stinky>
local function FixMacro(stinkies)
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Fixing macro with %d stinkies", ModuleName, #stinkies))
end
if not Heimdall_Data.config.macroer.enabled then
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Module disabled, skipping macro update", ModuleName))
end
return
end
if InCombatLockdown() then
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] In combat, skipping macro update", ModuleName))
end
return
end
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
if not shared.AgentTracker.IsAgent(stinky.name) then sortedStinkies[#sortedStinkies + 1] = stinky end
end
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Processing %d non-agent stinkies", ModuleName, #sortedStinkies))
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)
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Sorted stinkies: %d", ModuleName, #sortedStinkies))
shared.dumpTable(sortedStinkies)
end
local lines = { "/targetenemy" }
for _, stinky in pairs(sortedStinkies) do
if stinky.seenAt > GetTime() - 600 then
if Heimdall_Data.config.macroer.debug then if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Adding target macro for: %s", ModuleName, stinky.name)) print(string.format("[%s] Creating new macro: %s", ModuleName, macroName))
end end
lines[#lines + 1] = string.format("/tar %s", stinky.name) CreateMacro(macroName, "INV_Misc_QuestionMark", "")
end end
idx = GetMacroIndexByName(macroName)
if Heimdall_Data.config.macroer.debug then print(string.format("[%s] Macro index: %d", ModuleName, idx)) end
return idx
end end
local idx = FindOrCreateMacro("HeimdallTarget") ---@param stinkies table<string, Stinky>
---@diagnostic disable-next-line: param-type-mismatch local function FixMacro(stinkies)
local body = strjoin("\n", unpack(lines)) if Heimdall_Data.config.macroer.debug then
if Heimdall_Data.config.macroer.debug then print(string.format("[%s] Fixing macro with %d stinkies", ModuleName, #stinkies))
print(string.format("[%s] Updating macro with %d lines", ModuleName, #lines)) end
end if not Heimdall_Data.config.macroer.enabled then
EditMacro(idx, "HeimdallTarget", "INV_Misc_QuestionMark", body) if Heimdall_Data.config.macroer.debug then
end print(string.format("[%s] Module disabled, skipping macro update", ModuleName))
end
return
end
if InCombatLockdown() then
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] In combat, skipping macro update", ModuleName))
end
return
end
shared.StinkyTracker.OnChange(function(stinkies) local priorityMap = {}
if Heimdall_Data.config.macroer.debug then for priority, className in ipairs(Heimdall_Data.config.macroer.priority) do
print(string.format("[%s] Stinkies changed, updating macro", ModuleName)) priorityMap[className] = priority
shared.dumpTable(stinkies) end
end local minPriority = #Heimdall_Data.config.macroer.priority + 1
FixMacro(stinkies)
end)
if Heimdall_Data.config.macroer.debug then print(string.format("[%s] Module initialized", ModuleName)) end local sortedStinkies = {}
print("[Heimdall] Macroer loaded") for _, stinky in pairs(stinkies) do
end if not shared.AgentTracker.IsAgent(stinky.name) then sortedStinkies[#sortedStinkies + 1] = stinky end
end
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Processing %d non-agent stinkies", ModuleName, #sortedStinkies))
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)
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Sorted stinkies: %d", ModuleName, #sortedStinkies))
shared.dumpTable(sortedStinkies)
end
local lines = { "/targetenemy" }
for _, stinky in pairs(sortedStinkies) do
if stinky.seenAt > GetTime() - 600 then
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Adding target macro for: %s", ModuleName, stinky.name))
end
lines[#lines + 1] = string.format("/tar %s", stinky.name)
end
end
local idx = FindOrCreateMacro("HeimdallTarget")
---@diagnostic disable-next-line: param-type-mismatch
local body = strjoin("\n", unpack(lines))
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Updating macro with %d lines", ModuleName, #lines))
end
EditMacro(idx, "HeimdallTarget", "INV_Misc_QuestionMark", body)
end
shared.StinkyTracker.OnChange(function(stinkies)
if Heimdall_Data.config.macroer.debug then
print(string.format("[%s] Stinkies changed, updating macro", ModuleName))
shared.dumpTable(stinkies)
end
FixMacro(stinkies)
end)
if Heimdall_Data.config.macroer.debug then print(string.format("[%s] Module initialized", ModuleName)) end
print("[Heimdall] Macroer loaded")
end,
}

View File

@@ -2,82 +2,91 @@ local _, shared = ...
---@cast shared HeimdallShared ---@cast shared HeimdallShared
local ModuleName = "Sniffer" local ModuleName = "Sniffer"
---@diagnostic disable-next-line: missing-fields ---@class HeimdallSnifferConfig
shared.Sniffer = {} ---@field enabled boolean
function shared.Sniffer.Init() ---@field debug boolean
if Heimdall_Data.config.sniffer.debug then print(string.format("[%s] Module initializing", ModuleName)) end ---@field channels string[]
local smellThrottle = {} ---@field throttle number -- throttleTime in the original code, matching config name now
local SmellStinky = function(stinky) ---@field zoneOverride string?
if Heimdall_Data.config.sniffer.debug then ---@field stinky boolean
print(string.format("%s: SmellStinky", ModuleName))
shared.dumpTable(Heimdall_Data.config.sniffer)
end
if not Heimdall_Data.config.sniffer.enabled then return end
if Heimdall_Data.config.sniffer.stinky and not shared.IsStinky(stinky) then
if Heimdall_Data.config.sniffer.debug then
print(string.format("%s: Stinky not found in config", ModuleName))
end
return
end
if smellThrottle[stinky] and GetTime() - smellThrottle[stinky] < Heimdall_Data.config.sniffer.throttleTime then
if Heimdall_Data.config.sniffer.debug then print(string.format("%s: Throttled", ModuleName)) end
return
end
smellThrottle[stinky] = GetTime()
for _, channel in pairs(Heimdall_Data.config.sniffer.channels) do ---@class Sniffer
local locale = shared.GetLocaleForChannel(channel) shared.Sniffer = {
local text = string.format(shared._L("snifferStinky", locale), stinky) Init = function()
---@type Message if Heimdall_Data.config.sniffer.debug then print(string.format("[%s] Module initializing", ModuleName)) end
local msg = { local smellThrottle = {}
channel = "C", local SmellStinky = function(stinky)
data = channel,
message = text,
}
if Heimdall_Data.config.sniffer.debug then if Heimdall_Data.config.sniffer.debug then
print(string.format("[%s] Queuing sniffer message", ModuleName)) print(string.format("%s: SmellStinky", ModuleName))
shared.dumpTable(msg) shared.dumpTable(Heimdall_Data.config.sniffer)
end end
table.insert(shared.messenger.queue, msg) if not Heimdall_Data.config.sniffer.enabled then return end
end if Heimdall_Data.config.sniffer.stinky and not shared.IsStinky(stinky) then
end if Heimdall_Data.config.sniffer.debug then
print(string.format("%s: Stinky not found in config", ModuleName))
end
return
end
if smellThrottle[stinky] and GetTime() - smellThrottle[stinky] < Heimdall_Data.config.sniffer.throttle then
if Heimdall_Data.config.sniffer.debug then print(string.format("%s: Throttled", ModuleName)) end
return
end
smellThrottle[stinky] = GetTime()
local cleuFrame = CreateFrame("Frame") for _, channel in pairs(Heimdall_Data.config.sniffer.channels) do
cleuFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") local locale = shared.GetLocaleForChannel(channel)
cleuFrame:SetScript("OnEvent", function(self, event, ...) local text = string.format(shared._L("snifferStinky", locale), stinky)
if Heimdall_Data.config.sniffer.debug then ---@type Message
print(string.format("[%s] Received event: %s", ModuleName, event)) local msg = {
end channel = "C",
if not Heimdall_Data.config.sniffer.enabled then data = channel,
if Heimdall_Data.config.sniffer.debug then message = text,
print(string.format("[%s] Module disabled, ignoring event", ModuleName)) }
if Heimdall_Data.config.sniffer.debug then
print(string.format("[%s] Queuing sniffer message", ModuleName))
shared.dumpTable(msg)
end
table.insert(shared.messenger.queue, msg)
end end
return
end end
local source, destination, err
source, err = CLEUParser.GetSourceName(...) local cleuFrame = CreateFrame("Frame")
if Heimdall_Data.config.sniffer.debug then cleuFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
print(string.format("[%s] Processing source: %s", ModuleName, source)) cleuFrame:SetScript("OnEvent", function(self, event, ...)
end
if err then
if Heimdall_Data.config.sniffer.debug then if Heimdall_Data.config.sniffer.debug then
print(string.format("[%s] Error parsing source: %s", ModuleName, err)) print(string.format("[%s] Received event: %s", ModuleName, event))
end end
return if not Heimdall_Data.config.sniffer.enabled then
end if Heimdall_Data.config.sniffer.debug then
SmellStinky(source) print(string.format("[%s] Module disabled, ignoring event", ModuleName))
destination, err = CLEUParser.GetDestName(...) end
if Heimdall_Data.config.sniffer.debug then return
print(string.format("[%s] Processing destination: %s", ModuleName, destination)) end
end local source, destination, err
if err then source, err = CLEUParser.GetSourceName(...)
if Heimdall_Data.config.sniffer.debug then if Heimdall_Data.config.sniffer.debug then
print(string.format("[%s] Error parsing destination: %s", ModuleName, err)) print(string.format("[%s] Processing source: %s", ModuleName, source))
end end
return if err then
end if Heimdall_Data.config.sniffer.debug then
SmellStinky(destination) print(string.format("[%s] Error parsing source: %s", ModuleName, err))
end) end
if Heimdall_Data.config.sniffer.debug then print(string.format("[%s] Module initialized", ModuleName)) end return
print("[Heimdall] Sniffer loaded") end
end SmellStinky(source)
destination, err = CLEUParser.GetDestName(...)
if Heimdall_Data.config.sniffer.debug then
print(string.format("[%s] Processing destination: %s", ModuleName, destination))
end
if err then
if Heimdall_Data.config.sniffer.debug then
print(string.format("[%s] Error parsing destination: %s", ModuleName, err))
end
return
end
SmellStinky(destination)
end)
if Heimdall_Data.config.sniffer.debug then print(string.format("[%s] Module initialized", ModuleName)) end
print("[Heimdall] Sniffer loaded")
end,
}