local addonname, shared = ... ---@cast shared HeimdallShared ---@cast addonname string local ModuleName = "Spotter" ---@diagnostic disable-next-line: missing-fields shared.Spotter = {} function shared.Spotter.Init() local function FormatHP(hp) if hp > 1e9 then return string.format("%.1fB", hp / 1e9) elseif hp > 1e6 then return string.format("%.1fM", hp / 1e6) elseif hp > 1e3 then return string.format("%.1fK", hp / 1e3) else return hp end end ---@type table local throttleTable = {} ---@param unit string ---@param name string ---@param faction string ---@param hostile boolean ---@return boolean ---@return string? error local function ShouldNotify(unit, name, faction, hostile) if Heimdall_Data.config.spotter.debug then print(string.format("%s: ShouldNotify", ModuleName)) shared.dumpTable(Heimdall_Data.config.spotter) end if Heimdall_Data.config.agents[name] then return false end if Heimdall_Data.config.spotter.stinky then if Heimdall_Data.config.stinkies[name] then if Heimdall_Data.config.spotter.debug then print(string.format("%s: Stinky found in config", ModuleName)) end return true end end if Heimdall_Data.config.spotter.alliance then if faction == "Alliance" then if Heimdall_Data.config.spotter.debug then print(string.format("%s: Alliance", ModuleName)) end return true end end if Heimdall_Data.config.spotter.hostile then if hostile then if Heimdall_Data.config.spotter.debug then print(string.format("%s: Hostile", ModuleName)) end return true end end return Heimdall_Data.config.spotter.everyone end ---@param unit string ---@return string? local function NotifySpotted(unit) if Heimdall_Data.config.spotter.debug then print(string.format("%s: NotifySpotted", ModuleName)) shared.dumpTable(Heimdall_Data.config.spotter) end if not unit then return string.format("Could not find unit %s", tostring(unit)) end if not UnitIsPlayer(unit) then return nil end if Heimdall_Data.config.spotter.debug then print(string.format("%s: UnitIsPlayer", ModuleName)) end local name = UnitName(unit) if not name then return string.format("Could not find name for unit %s", tostring(unit)) end local time = GetTime() if throttleTable[name] and time - throttleTable[name] < Heimdall_Data.config.spotter.throttleTime then if Heimdall_Data.config.spotter.debug then print(string.format("%s: Throttled %s", ModuleName, tostring(name))) end return string.format("Throttled %s", tostring(name)) end throttleTable[name] = time local race = UnitRace(unit) if not race then return string.format("Could not find race for unit %s", tostring(unit)) end local faction = shared.raceMap[race] if not faction then return string.format("Could not find faction for race %s", tostring(race)) end if Heimdall_Data.config.spotter.debug then print(string.format("%s: Faction %s", ModuleName, tostring(faction))) end local hostile = UnitCanAttack("player", unit) if Heimdall_Data.config.spotter.debug then print(string.format("%s: Hostile %s", ModuleName, tostring(hostile))) end local doNotify = ShouldNotify(unit, name, faction, hostile) if not doNotify then return string.format("Not notifying for %s", tostring(name)) end local hp = UnitHealth(unit) if not hp then return string.format("Could not find hp for unit %s", tostring(unit)) end if Heimdall_Data.config.spotter.debug then print(string.format("%s: HP %s", ModuleName, tostring(hp))) end local maxHp = UnitHealthMax(unit) if not maxHp then return string.format("Could not find maxHp for unit %s", tostring(unit)) end if Heimdall_Data.config.spotter.debug then print(string.format("%s: MaxHP %s", ModuleName, tostring(maxHp))) end local class = UnitClass(unit) if not class then return string.format("Could not find class for unit %s", tostring(unit)) end if Heimdall_Data.config.spotter.debug then print(string.format("%s: Class %s", ModuleName, tostring(class))) end local location = Heimdall_Data.config.spotter.zoneOverride if not location or location == "" then local zone = GetZoneText() if not zone then return string.format("Could not find zone for unit %s", tostring(unit)) end local subzone = GetSubZoneText() if not subzone then subzone = "" end if Heimdall_Data.config.spotter.debug then print(string.format("%s: Zone %s", ModuleName, tostring(zone))) print(string.format("%s: Subzone %s", ModuleName, tostring(subzone))) end location = string.format("%s (%s)", zone, subzone) end local x, y = GetPlayerMapPosition("player") if Heimdall_Data.config.spotter.debug then print(string.format("%s: X %s", ModuleName, tostring(x))) print(string.format("%s: Y %s", ModuleName, tostring(y))) end local stinky = Heimdall_Data.config.stinkies[name] or false local text = string.format("I see (%s) %s/%s %s of race %s (%s) with health %s/%s at %s (%2.2f, %2.2f)", hostile and "Hostile" or "Friendly", name, class, stinky and string.format("(%s)", "!!!!") or "", race, faction, FormatHP(hp), FormatHP(maxHp), location, x * 100, y * 100) if Heimdall_Data.config.spotter.debug then print(string.format("%s: Text %s", ModuleName, tostring(text))) end ---@type Message local msg = { channel = "CHANNEL", data = Heimdall_Data.config.spotter.notifyChannel, message = text } if Heimdall_Data.config.spotter.debug then print(string.format("%s: Inserting message into queue", ModuleName)) shared.dumpTable(msg) end table.insert(shared.messenger.queue, msg) end local frame = CreateFrame("Frame") frame:RegisterEvent("NAME_PLATE_UNIT_ADDED") frame:RegisterEvent("UNIT_TARGET") frame:SetScript("OnEvent", function(self, event, unit) if not Heimdall_Data.config.spotter.enabled then return end if event == "UNIT_TARGET" then unit = "target" end local err = NotifySpotted(unit) if err then print(string.format("Error notifying %s: %s", tostring(unit), tostring(err))) end end) print("Heimdall - Spotter loaded") end