local addonname, shared = ... ---@cast shared HeimdallShared ---@cast addonname string local ModuleName = "AchievementSniffer" local HeimdallRoot = "Interface\\AddOns\\Heimdall\\" local TextureRoot = HeimdallRoot .. "Texture\\" local Achievements = { 15, 958, 1266, 2078, 2141, 2200, 4958, 5456, 5749, 6460, 6753, 7382, 7383, 7384, 8929, 8982, 9017, 9038, 9493, 10059, 10079, 10278, 10657, 10672, 10684, 10688, 10689, 10692, 10693, 10698, 10790, 10875, 11124, 11126, 11127, 11128, 11153, 11157, 11164, 11188, 11189, 11190, 11446, 11473, 11610, 11657, 11658, 11659, 11660, 11674, 11992, 11993, 11994, 11995, 11996, 11997, 11998, 11999, 12000, 12001, 12020, 12026, 12074, 12445, 12447, 12448, } ---@diagnostic disable-next-line: missing-fields shared.AchievementSniffer = {} function shared.AchievementSniffer.Init() if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Module initialized", ModuleName)) end local guidMap = {} ---@class AchievementData ---@field id number ---@field date string ---@field completed boolean ---@class Heimdall_Achievements ---@field players table> ---@field alreadySeen table ---@field rescan boolean if not Heimdall_Achievements then Heimdall_Achievements = {} end if not Heimdall_Achievements.players then Heimdall_Achievements.players = {} end if not Heimdall_Achievements.alreadySeen then Heimdall_Achievements.alreadySeen = {} end --local framePool = {} --for i = 1, 40 do -- local frame = CreateFrame("Frame", "HeimdallAchievementSnifferNameplate" .. i, UIParent) -- local texture = frame:CreateTexture(nil, "ARTWORK") -- texture:SetAllPoints(frame) -- texture:SetTexture(TextureRoot .. Heimdall_Data.config.achievementSniffer.texture) -- frame.texture = texture -- frame:Hide() -- table.insert(framePool, frame) --end ---@param name string ---@return boolean local function ShouldInspect(name) local should = false if not Heimdall_Achievements.players[name] then if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Player %s does not have prior achievement data", ModuleName, name)) end should = true end if Heimdall_Achievements.alreadySeen[name] then if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Player %s has already been seen", ModuleName, name)) end -- Save some memory Heimdall_Achievements.players[name] = nil should = false end if Heimdall_Data.config.achievementSniffer.rescan then if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Rescan is enabled", ModuleName)) end should = true end return should end -- It's not working well AT ALL -- I don't know how to do it better -- It simply just does not work... --local function UpdateFrames() -- for i, frame in ipairs(framePool) do -- local unit = "nameplate" .. i -- if not UnitExists(unit) then -- --if Heimdall_Data.config.achievementSniffer.debug then -- -- print(string.format("[%s] Unit %s does not exist, hiding frame", ModuleName, unit)) -- --end -- frame:Hide() -- else -- --local unitFrame = _G[string.format("ElvUI_NamePlate%dHealthBar", i)] -- local unitFrame = _G[string.format("NamePlate%d", i)] -- if unitFrame == nil then -- if Heimdall_Data.config.achievementSniffer.debug then -- print(string.format("[%s] Unit frame for %s not found", ModuleName, unit)) -- end -- frame:Hide() -- else -- local unitName = UnitName(unit) -- if Heimdall_Data.config.achievementSniffer.debug then -- print(string.format("[%s] Unit frame found for %s (%s)", ModuleName, unit, unitName)) -- end -- frame:Show() -- frame:SetSize(32, 32) -- frame:SetFrameStrata("HIGH") -- frame:SetFrameLevel(100) -- frame:SetScale(Heimdall_Data.config.achievementSniffer.iconScale) -- frame.texture:SetTexture(TextureRoot .. Heimdall_Data.config.achievementSniffer.texture) -- frame:SetPoint("CENTER", unitFrame, "CENTER", -- Heimdall_Data.config.achievementSniffer.offsetX, -- Heimdall_Data.config.achievementSniffer.offsetY) -- frame:SetParent(unitFrame) -- frame:SetAlpha(1) -- local exists = ShouldInspect(unitName) -- if exists then -- frame.texture:SetVertexColor(1, 0, 0, 1) -- else -- frame.texture:SetVertexColor(0, 1, 0, 1) -- end -- if Heimdall_Data.config.achievementSniffer.debug then -- print(string.format("[%s] Frame updated for %s", ModuleName, unitName)) -- end -- end -- end -- end --end ---@param unit string local function TryInspect(unit) local targetPlayer = UnitIsPlayer(unit) if not targetPlayer then return end local targetName = UnitName(unit) local targetGuid = UnitGUID(unit) guidMap[targetGuid] = targetName if not ShouldInspect(targetName) then if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Not inspecting player: %s", ModuleName, targetName)) end return end local canInspect = CheckInteractDistance(unit, 1) if canInspect then if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Inspecting player: %s", ModuleName, targetName)) end SetAchievementComparisonUnit(unit) else if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Cannot inspect player (too far?): %s", ModuleName, targetName)) end end end ---@param name string local function Scan(name) if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Scanning achievements for %s", ModuleName, name)) end Heimdall_Achievements.players[name] = {} for i, aid in ipairs(Achievements) do local completed, month, day, year = GetAchievementComparisonInfo(aid) if completed then ---@type string local yearstr = "" .. year if year < 100 then yearstr = "20" .. year end local date = string.format("%04d-%02d-%02d", yearstr, month, day) local data = { id = aid, date = date, completed = completed, } if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Achievement %d completed on %s", ModuleName, aid, date)) end Heimdall_Achievements.players[name][aid] = data end end --UpdateFrames() end local nameplateFrame = CreateFrame("Frame") nameplateFrame:RegisterEvent("NAME_PLATE_UNIT_ADDED") nameplateFrame:RegisterEvent("NAME_PLATE_UNIT_REMOVED") nameplateFrame:SetScript("OnEvent", function(self, event, unit) if not Heimdall_Data.config.achievementSniffer.enabled then return end if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Event triggered: %s for unit: %s", ModuleName, event, unit)) end if event == "NAME_PLATE_UNIT_ADDED" then TryInspect(unit) end --UpdateFrames() end) local inspectFrame = CreateFrame("Frame") inspectFrame:RegisterEvent("INSPECT_ACHIEVEMENT_READY") inspectFrame:SetScript("OnEvent", function(self, event, guid) if not Heimdall_Data.config.achievementSniffer.enabled then return end local name = guidMap[guid] if not name then if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] No name found for guid: %s", ModuleName, guid)) end return end if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Event triggered: %s for player: %s", ModuleName, event, name)) end Scan(name) end) local function Tick() C_Timer.NewTimer(Heimdall_Data.config.achievementSniffer.scanInterval, Tick) if not Heimdall_Data.config.achievementSniffer.enabled then return end if Heimdall_Data.config.achievementSniffer.debug then print(string.format("[%s] Scanning achievements for everyone on screen", ModuleName)) end for i = 1, 40 do local unit = "nameplate" .. i if UnitExists(unit) then TryInspect(unit) --else -- if Heimdall_Data.config.achievementSniffer.debug then -- print(string.format("[%s] Unit %s does not exist, nothing to inspect", ModuleName, unit)) -- end end end --UpdateFrames() end Tick() print("[Heimdall] AchievementSniffer loaded") end