local addonname, shared = ... ---@cast shared HeimdallShared ---@cast addonname string local VERSION = "3.12.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 HeimdallStinkyTrackerData ---@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 dump fun(table: any, 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 Whoer InitTable|{ShouldNotifyForZone: fun(zone: string): boolean} ---@field Messenger InitTable ---@field Spotter InitTable ---@field DeathReporter InitTable ---@field Inviter InitTable ---@field Dueler InitTable ---@field Bully InitTable ---@field AgentTracker InitTable ---@field Emoter InitTable ---@field Echoer InitTable ---@field Macroer InitTable ---@field Commander InitTable ---@field StinkyTracker InitTable ---@field CombatAlerter InitTable ---@field Config InitTable ---@field Sniffer InitTable ---@field MinimapTagger InitTable ---@field BonkDetector InitTable ---@field Noter InitTable ---@field Network InitTable ---@field NetworkMessenger InitTable ---@field StinkyCache InitTable ---@field Configurator InitTable ---@field AchievementSniffer InitTable ---@field ChatSniffer InitTable --- Config --- ---@class HeimdallConfig ---@field spotter HeimdallSpotterConfig ---@field who HeimdallWhoConfig ---@field messenger HeimdallMessengerConfig ---@field deathReporter HeimdallDeathReporterConfig ---@field inviter HeimdallInviterConfig ---@field dueler HeimdallDuelerConfig ---@field bully HeimdallBullyConfig ---@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 bonkDetector HeimdallBonkDetectorConfig ---@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 ---@class HeimdallSpotterConfig ---@field enabled boolean ---@field debug boolean ---@field everyone boolean ---@field hostile boolean ---@field alliance boolean ---@field stinky boolean ---@field channels string[] ---@field zoneOverride string? ---@field throttleTime number ---@class HeimdallWhoConfig ---@field enabled boolean ---@field debug boolean ---@field ignored table ---@field channels string[] ---@field ttl number ---@field doWhisper boolean ---@field zoneNotifyFor table ---@field queries string ---@class HeimdallMessengerConfig ---@field enabled boolean ---@field debug boolean ---@field interval number ---@class HeimdallDeathReporterConfig ---@field enabled boolean ---@field debug boolean ---@field throttle number ---@field doWhisper boolean ---@field channels string[] ---@field zoneOverride string? ---@field duelThrottle number ---@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 ---@class HeimdallDuelerConfig ---@field enabled boolean ---@field debug boolean ---@field declineOther boolean ---@class HeimdallBullyConfig ---@field enabled boolean ---@field debug boolean ---@class HeimdallAgentTrackerConfig ---@field enabled boolean ---@field debug boolean ---@field channels string[] ---@class HeimdallEmoterConfig ---@field enabled boolean ---@field debug boolean ---@field channels string[] ---@field prefix string ---@class HeimdallEchoerConfig ---@field enabled boolean ---@field debug boolean ---@field channels string[] ---@field prefix string ---@class HeimdallMacroerConfig ---@field enabled boolean ---@field debug boolean ---@field priority string[] ---@class HeimdallCommanderConfig ---@field enabled boolean ---@field debug boolean ---@field channels string[] ---@field commander string ---@field commands table ---@class HeimdallStinkyTrackerConfig ---@field enabled boolean ---@field debug boolean ---@field channels string[] ---@class HeimdallCombatAlerterConfig ---@field enabled boolean ---@field debug boolean ---@field channels string[] ---@class HeimdallSnifferConfig ---@field enabled boolean ---@field debug boolean ---@field channels string[] ---@field throttle number ---@field zoneOverride string? ---@field stinky boolean ---@class HeimdallMinimapTaggerConfig ---@field enabled boolean ---@field debug boolean ---@field channels string[] ---@field throttle number ---@field scale number ---@field tagTTL number ---@field tagSound boolean ---@field tagSoundFile string ---@field tagSoundThrottle number ---@field tagTextureFile string ---@field alertTTL number ---@field alertSound boolean ---@field alertSoundFile string ---@field alertSoundThrottle number ---@field alertTextureFile string ---@field combatTTL number ---@field combatSound boolean ---@field combatSoundFile string ---@field combatSoundThrottle number ---@field combatTextureFile string ---@field helpTTL number ---@field helpSound boolean ---@field helpSoundFile string ---@field helpSoundThrottle number ---@field helpTextureFile string ---@class HeimdallBonkDetectorConfig ---@field enabled boolean ---@field debug boolean ---@field channels string[] ---@field throttle number ---@class HeimdallNoterConfig ---@field enabled boolean ---@field debug boolean ---@field channels string[] ---@field lastNotes number ---@class HeimdallNetworkConfig ---@field enabled boolean ---@field debug boolean ---@field members string[] ---@field updateInterval number ---@class HeimdallNetworkMessengerConfig ---@field enabled boolean ---@field debug boolean ---@field interval number ---@class HeimdallConfiguratorConfig ---@field enabled boolean ---@field debug boolean ---@class HeimdallStinkyCacheConfig ---@field enabled boolean ---@field debug boolean ---@field commander string ---@field ttl number ---@class HeimdallAchievementSnifferConfig ---@field enabled boolean ---@field debug boolean -----@field texture string -----@field offsetX number -----@field offsetY number ---@field rescan boolean ---@field scanInterval number -----@field iconScale number --- Data --- ---@class HeimdallMessengerData ---@field queue table ---@field ticker Timer? ---@class HeimdallNetworkMessengerData ---@field queue table ---@field ticker Timer? ---@class HeimdallWhoData ---@field updateTicker number? ---@field whoTicker number? ---@field ignored table ---@class HeimdallStinkyTrackerData ---@field stinkies ReactiveValue ---@class HeimdallNetworkData ---@field ticker number? ---@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" }), }, 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() shared.ChatSniffer.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) -- Create the import/export frame local ccpFrame = CreateFrame("Frame", "CCPFrame", UIParent) ccpFrame:SetSize(512 * 1.5, 512 * 1.5) ccpFrame:SetPoint("CENTER") ccpFrame:SetFrameStrata("HIGH") ccpFrame:EnableMouse(true) ccpFrame:SetMovable(true) ccpFrame:SetResizable(false) ccpFrame:SetBackdrop({ bgFile = "Interface/Tooltips/UI-Tooltip-Background", edgeFile = "Interface/Tooltips/UI-Tooltip-Border", tile = true, tileSize = 4, edgeSize = 4, insets = { left = 4, right = 4, top = 4, bottom = 4, }, }) ccpFrame:SetBackdropColor(0, 0, 0, 0.8) ccpFrame:SetBackdropBorderColor(0.5, 0.5, 0.5, 1) ccpFrame:SetMovable(true) ccpFrame:EnableMouse(true) ccpFrame:RegisterForDrag("LeftButton") ccpFrame:SetScript("OnDragStart", function(self) self:StartMoving() end) ccpFrame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end) ccpFrame:SetScript("OnShow", function(self) self:SetScale(1) end) ccpFrame:Hide() -- Create scroll frame local scrollFrame = CreateFrame("ScrollFrame", "CCPFrameScrollFrame", ccpFrame, "UIPanelScrollFrameTemplate") scrollFrame:SetPoint("TOPLEFT", ccpFrame, "TOPLEFT", 10, -10) scrollFrame:SetPoint("BOTTOMRIGHT", ccpFrame, "BOTTOMRIGHT", -30, 10) -- Create the text box local ccpFrameTextBox = CreateFrame("EditBox", "CCPFrameTextBox", scrollFrame) ccpFrameTextBox:SetSize(512 * 1.5 - 40, 512 * 1.5 - 20) ccpFrameTextBox:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0) ccpFrameTextBox:SetFont("Fonts\\FRIZQT__.ttf", 12) ccpFrameTextBox:SetTextColor(1, 1, 1, 1) ccpFrameTextBox:SetTextInsets(10, 10, 10, 10) ccpFrameTextBox:SetMultiLine(true) ccpFrameTextBox:SetAutoFocus(true) ccpFrameTextBox:SetMaxLetters(1000000) ccpFrameTextBox:SetScript("OnEscapePressed", function(self) ccpFrame:Hide() end) -- Set the scroll frame's scroll child scrollFrame:SetScrollChild(ccpFrameTextBox) CCP = function(window) window = window or 1 local charFrame = _G["ChatFrame" .. window] local maxLines = charFrame:GetNumMessages() or 0 local chat = {} for i = 1, maxLines do local currentMsg = charFrame:GetMessageInfo(i) chat[#chat + 1] = currentMsg end ccpFrameTextBox:SetText(table.concat(chat, "\n")) ccpFrame:Show() ccpFrameTextBox:SetFocus() end