local addonname, shared = ... ---@cast shared HeimdallShared ---@cast addonname string local VERSION = "3.11.0" shared.VERSION = VERSION local function init() ---@class Heimdall_Data ---@field config HeimdallConfig if not Heimdall_Data then Heimdall_Data = {} end ---@class InitTable ---@field Init fun(): nil ---@class HeimdallShared ---@field raceMap table ---@field classColors table ---@field messenger HeimdallMessengerData ---@field who HeimdallWhoData ---@field stinkyTracker StinkyTrackerData ---@field agentTracker AgentTrackerData ---@field networkNodes string[] ---@field network HeimdallNetworkData ---@field networkMessenger HeimdallNetworkMessengerData ---@field stinkyCache HeimdallStinkyCacheData ---@field _L fun(key: string, locale: string): string ---@field _Locale Localization ---@field VERSION string ---@field dumpTable fun(table: any, msg?: string, depth?: number): nil ---@field utf8len fun(input: string): number ---@field padString fun(input: string, targetLength: number, left?: boolean): string ---@field GetOrDefault fun(table: table, keys: string[], default: any): any ---@field Split fun(input: string, deliminer: string): string[] ---@field IsStinky fun(name: string): boolean ---@field Memoize fun(f: function): function ---@field GetLocaleForChannel fun(channel: string): string ---@field WhoQueryService WhoQueryService ---@field AchievementSniffer AchievementSniffer ---@field AgentTracker AgentTracker ---@field BonkDetector BonkDetector ---@field Bully Bully ---@field CombatAlerter CombatAlerter ---@field Commander Commander ---@field Config Config ---@field Configurator Configurator ---@field DeathReporter DeathReporter ---@field Dueler Dueler ---@field Echoer Echoer ---@field Emoter Emoter ---@field Inviter Inviter ---@field Macroer Macroer ---@field Messenger Messenger ---@field MinimapTagger MinimapTagger ---@field Network Network ---@field NetworkMessenger NetworkMessenger ---@field Noter Noter ---@field Sniffer Sniffer ---@field Spotter Spotter ---@field StinkyCache StinkyCache ---@field StinkyTracker StinkyTracker ---@field Whoer Whoer --- Config --- ---@class HeimdallConfig ---@field spotter HeimdallSpotterConfig ---@field who HeimdallWhoConfig ---@field messenger HeimdallMessengerConfig ---@field deathReporter HeimdallDeathReporterConfig ---@field inviter HeimdallInviterConfig ---@field dueler HeimdallDuelerConfig ---@field agentTracker HeimdallAgentTrackerConfig ---@field emoter HeimdallEmoterConfig ---@field echoer HeimdallEchoerConfig ---@field macroer HeimdallMacroerConfig ---@field commander HeimdallCommanderConfig ---@field stinkyTracker HeimdallStinkyTrackerConfig ---@field combatAlerter HeimdallCombatAlerterConfig ---@field sniffer HeimdallSnifferConfig ---@field noter HeimdallNoterConfig ---@field network HeimdallNetworkConfig ---@field networkMessenger HeimdallNetworkMessengerConfig ---@field configurator HeimdallConfiguratorConfig ---@field stinkyCache HeimdallStinkyCacheConfig ---@field achievementSniffer HeimdallAchievementSnifferConfig ---@field whisperNotify table ---@field addonPrefix string ---@field stinkies table ---@field agents table ---@field scale number ---@field notes table ---@field channelLocale table ---@field locale string ---@field debug boolean --- Data --- ---@class HeimdallMessengerData ---@field queue table ---@field ticker Timer? ---@class HeimdallNetworkMessengerData ---@field queue table ---@field ticker Timer? ---@class HeimdallWhoData ---@field updateTicker Timer? ---@field whoTicker Timer? ---@field ignored table ---@class HeimdallStinkyCacheData ---@field stinkies table shared.GetOrDefault = function(table, keys, default) local value = default if not table then return value end if not keys then return value end local traverse = table for i = 1, #keys do local key = keys[i] if traverse[key] ~= nil then traverse = traverse[key] else break end if i == #keys then value = traverse end end return value end shared.messenger = { queue = {}, } shared.who = { ignored = {}, } --/run Heimdall_Data.config.who.queries="g-\"БеспредеЛ\"|ally" Heimdall_Data.config = { debug = shared.GetOrDefault(Heimdall_Data, { "config", "debug" }, false), spotter = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "enabled" }, true), debug = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "debug" }, false), everyone = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "everyone" }, false), hostile = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "hostile" }, true), alliance = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "alliance" }, true), stinky = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "stinky" }, true), channels = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "channels" }, { "Agent" }), zoneOverride = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "zoneOverride" }, nil), throttleTime = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "throttleTime" }, 10), }, who = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "who", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "who", "debug" }, false), ignored = shared.GetOrDefault(Heimdall_Data, { "config", "who", "ignored" }, {}), channels = shared.GetOrDefault(Heimdall_Data, { "config", "who", "channels" }, { "Agent" }), ttl = shared.GetOrDefault(Heimdall_Data, { "config", "who", "ttl" }, 20), doWhisper = shared.GetOrDefault(Heimdall_Data, { "config", "who", "doWhisper" }, true), zoneNotifyFor = shared.GetOrDefault(Heimdall_Data, { "config", "who", "zoneNotifyFor" }, { ["Orgrimmar"] = true, ["Thunder Bluff"] = true, ["Undercity"] = true, ["Durotar"] = true, ["Echo Isles"] = true, ["Valley of Trials"] = true, }), queries = shared.GetOrDefault(Heimdall_Data, { "config", "who", "queries" }, ""), }, messenger = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "messenger", "enabled" }, true), debug = shared.GetOrDefault(Heimdall_Data, { "config", "messenger", "debug" }, false), interval = shared.GetOrDefault(Heimdall_Data, { "config", "messenger", "interval" }, 0.2), }, deathReporter = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "debug" }, false), throttle = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "throttle" }, 10), doWhisper = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "doWhisper" }, true), channels = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "channels" }, { "Agent" }), zoneOverride = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "zoneOverride" }, nil), duelThrottle = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "duelThrottle" }, 5), }, inviter = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "channels" }, { "Agent" }), keyword = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "keyword" }, "+"), allAssist = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "allAssist" }, false), agentsAssist = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "agentsAssist" }, false), throttle = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "throttle" }, 1), kickOffline = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "kickOffline" }, false), cleanupInterval = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "cleanupInterval" }, 10), afkThreshold = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "afkThreshold" }, 300), listeningChannel = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "listeningChannel" }, {}), }, dueler = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "dueler", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "dueler", "debug" }, false), declineOther = shared.GetOrDefault(Heimdall_Data, { "config", "dueler", "declineOther" }, false), }, bully = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "bully", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "bully", "debug" }, false), }, agentTracker = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "agentTracker", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "agentTracker", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "agentTracker", "channels" }, { "Agent" }), }, emoter = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "channels" }, { "Agent" }), prefix = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "prefix" }, ""), }, echoer = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "channels" }, { "Agent" }), prefix = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "prefix" }, ""), }, macroer = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "macroer", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "macroer", "debug" }, false), priority = shared.GetOrDefault(Heimdall_Data, { "config", "macroer", "priority" }, {}), }, agents = shared.GetOrDefault(Heimdall_Data, { "config", "agents" }, {}), commander = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "channels" }, { "Agent" }), commander = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "commander" }, "Heimdállr"), commands = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "commands" }, {}), }, stinkyTracker = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyTracker", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyTracker", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyTracker", "channels" }, { "Agent" }), ignoredTimeout = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyTracker", "ignoredTimeout" }, 600), }, combatAlerter = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "combatAlerter", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "combatAlerter", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "combatAlerter", "channels" }, { "Agent" }), }, messageDelegator = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "messageDelegator", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "messageDelegator", "debug" }, false), delegates = shared.GetOrDefault(Heimdall_Data, { "config", "messageDelegator", "delegates" }, {}), masterChannel = shared.GetOrDefault( Heimdall_Data, { "config", "messageDelegator", "masterChannel" }, "Agent" ), }, sniffer = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "channels" }, { "Agent" }), throttle = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "throttle" }, 10), zoneOverride = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "zoneOverride" }, nil), stinky = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "stinky" }, true), }, minimapTagger = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "channels" }, { "Agent" }), throttle = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "throttle" }, 10), scale = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "scale" }, 3), tagTTL = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "tagTTL" }, 1), tagSound = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "tagSound" }, false), tagSoundFile = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "tagSoundFile" }, "MGSSpot.ogg" ), tagSoundThrottle = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "tagSoundThrottle" }, 0), tagTextureFile = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "tagTextureFile" }, "Aura4.tga" ), --- alertTTL = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "alertTTL" }, 1), alertSound = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "alertSound" }, false), alertSoundFile = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "alertSoundFile" }, "OOF.ogg" ), alertSoundThrottle = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "alertSoundThrottle" }, 0 ), alertTextureFile = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "alertTextureFile" }, "Aura27.tga" ), --- combatTTL = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "combatTTL" }, 1), combatSound = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "combatSound" }, false), combatSoundFile = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "combatSoundFile" }, "StarScream.ogg" ), combatSoundThrottle = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "combatSoundThrottle" }, 2 ), combatTextureFile = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "combatTextureFile" }, "Aura58.tga" ), --- helpTTL = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "helpTTL" }, 1), helpSound = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "helpSound" }, false), helpSoundFile = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "helpSoundFile" }, "MedicGangsterParadise.ogg" ), helpSoundThrottle = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "helpSoundThrottle" }, 2 ), helpTextureFile = shared.GetOrDefault( Heimdall_Data, { "config", "minimapTagger", "helpTextureFile" }, "Aura68.tga" ), }, whisperNotify = shared.GetOrDefault(Heimdall_Data, { "config", "whisperNotify" }, {}), stinkies = shared.GetOrDefault(Heimdall_Data, { "config", "stinkies" }, {}), notes = shared.GetOrDefault(Heimdall_Data, { "config", "notes" }, {}), scale = shared.GetOrDefault(Heimdall_Data, { "config", "scale" }, 1), locale = shared.GetOrDefault(Heimdall_Data, { "config", "locale" }, "en"), bonkDetector = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "bonkDetector", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "bonkDetector", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "bonkDetector", "channels" }, { "Agent" }), throttle = shared.GetOrDefault(Heimdall_Data, { "config", "bonkDetector", "throttle" }, 5), }, noter = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "noter", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "noter", "debug" }, false), channels = shared.GetOrDefault(Heimdall_Data, { "config", "noter", "channels" }, { "Agent" }), lastNotes = shared.GetOrDefault(Heimdall_Data, { "config", "noter", "lastNotes" }, 5), }, network = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "network", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "network", "debug" }, false), members = shared.GetOrDefault(Heimdall_Data, { "config", "network", "members" }, {}), updateInterval = shared.GetOrDefault(Heimdall_Data, { "config", "network", "updateInterval" }, 10), }, networkMessenger = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "networkMessenger", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "networkMessenger", "debug" }, false), interval = shared.GetOrDefault(Heimdall_Data, { "config", "networkMessenger", "interval" }, 0.01), }, configurator = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "configurator", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "configurator", "debug" }, false), }, stinkyCache = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyCache", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyCache", "debug" }, false), commander = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyCache", "commander" }, "Heimdállr"), ttl = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyCache", "ttl" }, 10), }, achievementSniffer = { enabled = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "enabled" }, false), debug = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "debug" }, false), --texture = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "texture" }, "Aura53.tga"), --offsetX = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "offsetX" }, 0), --offsetY = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "offsetY" }, 0), rescan = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "rescan" }, false), scanInterval = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "scanInterval" }, 1), --iconScale = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "iconScale" }, 1), }, addonPrefix = shared.GetOrDefault(Heimdall_Data, { "config", "addonPrefix" }, "HEIMDALL"), channelLocale = shared.GetOrDefault(Heimdall_Data, { "config", "channelLocale" }, {}), } shared.raceMap = { ["Orc"] = "Horde", ["Undead"] = "Horde", ["Tauren"] = "Horde", ["Troll"] = "Horde", ["Blood Elf"] = "Horde", ["Goblin"] = "Horde", ["Human"] = "Alliance", ["Dwarf"] = "Alliance", ["Night Elf"] = "Alliance", ["Gnome"] = "Alliance", ["Draenei"] = "Alliance", ["Worgen"] = "Alliance", ["Vulpera"] = "Horde", ["Nightborne"] = "Horde", ["Zandalari Troll"] = "Horde", ["Kul Tiran"] = "Alliance", ["Dark Iron Dwarf"] = "Alliance", ["Void Elf"] = "Alliance", ["Lightforged Draenei"] = "Alliance", ["Mechagnome"] = "Alliance", ["Mag'har Orc"] = "Horde", } shared.classColors = { ["Warrior"] = "C69B6D", ["Paladin"] = "F48CBA", ["Hunter"] = "AAD372", ["Rogue"] = "FFF468", ["Priest"] = "FFFFFF", ["Death Knight"] = "C41E3A", ["Shaman"] = "0070DD", ["Mage"] = "3FC7EB", ["Warlock"] = "8788EE", ["Monk"] = "00FF98", ["Druid"] = "FF7C0A", ["Demon Hunter"] = "A330C9", } ---@param input string ---@return number shared.utf8len = function(input) if not input then return 0 end local len = 0 local i = 1 local n = #input while i <= n do local c = input:byte(i) if c >= 0 and c <= 127 then i = i + 1 elseif c >= 194 and c <= 223 then i = i + 2 elseif c >= 224 and c <= 239 then i = i + 3 elseif c >= 240 and c <= 244 then i = i + 4 else i = i + 1 end len = len + 1 end return len end ---@param input string ---@param targetLength number ---@param left boolean ---@return string shared.padString = function(input, targetLength, left) left = left or false local len = shared.utf8len(input) if len < targetLength then if left then input = input .. string.rep(" ", targetLength - len) else input = string.rep(" ", targetLength - len) .. input end end return input end ---@param input string ---@param deliminer string ---@return table shared.Split = function(input, deliminer) if deliminer == nil then deliminer = "%s" end local t = {} for str in string.gmatch(input, "([^" .. deliminer .. "]+)") do table.insert(t, str) end return t end ---@param name string ---@return boolean shared.IsStinky = function(name) return Heimdall_Data.config.stinkies[name] ~= nil or shared.StinkyCache[name] ~= nil end ---@param f function ---@return function shared.Memoize = function(f) local mem = {} -- memoizing table setmetatable(mem, { __mode = "kv" }) -- make it weak return function(x) -- new version of 'f', with memoizing if Heimdall_Data.config.debug then print(string.format("[Heimdall] Memoize %s", tostring(x))) end local r = mem[x] if r == nil then -- no previous result? if Heimdall_Data.config.debug then print(string.format("[Heimdall] Memoize %s is nil, calling original function", tostring(x))) end r = f(x) -- calls original function if Heimdall_Data.config.debug then print(string.format("[Heimdall] Memoized result for %s: %s", tostring(x), tostring(r))) end mem[x] = r -- store result for reuse end if Heimdall_Data.config.debug then print(string.format("[Heimdall] Memoize %s is %s", tostring(x), tostring(r))) end return r end end ---@param channel string ---@return string shared.GetLocaleForChannel = function(channel) return Heimdall_Data.config.channelLocale[channel] or "en" end ---@param key string ---@param locale string ---@return string shared._L = function(key, locale) local localeTable = shared._Locale[locale] if not localeTable then if Heimdall_Data.config.debug then print(string.format("[Heimdall] Locale %s not found", tostring(locale))) end return key end local value = localeTable[key] if not value then if Heimdall_Data.config.debug then print(string.format("[Heimdall] Key %s not found in locale %s", tostring(key), tostring(locale))) end return key end return value end shared.Messenger.Init() shared.StinkyTracker.Init() shared.AgentTracker.Init() shared.Whoer.Init() shared.Spotter.Init() shared.DeathReporter.Init() shared.Inviter.Init() shared.Dueler.Init() shared.Bully.Init() shared.Macroer.Init() shared.Commander.Init() shared.CombatAlerter.Init() shared.Config.Init() shared.MinimapTagger.Init() shared.BonkDetector.Init() shared.Sniffer.Init() shared.Noter.Init() shared.Network.Init() shared.NetworkMessenger.Init() shared.Configurator.Init() shared.StinkyCache.Init() shared.AchievementSniffer.Init() print("Heimdall loaded!") end local loadedFrame = CreateFrame("Frame") loadedFrame:RegisterEvent("ADDON_LOADED") loadedFrame:SetScript("OnEvent", function(self, event, addonName) if addonName == addonname then init() end end)