local addonname, shared = ... ---@cast shared HeimdallShared ---@cast addonname string local ModuleName = "MinimapTagger" local HeimdallRoot = "Interface\\AddOns\\Heimdall\\" local SoundRoot = HeimdallRoot .. "Sounds\\" local TextureRoot = HeimdallRoot .. "Texture\\" --/run local a=GetChannelName("Agent")local b,c=GetPlayerMapPosition("player")b,c=b*100,c*100;local d=string.format("I need help at %s (%s) [%s](%2.2f, %2.2f)",GetZoneText(),GetSubZoneText(),GetCurrentMapAreaID(),b,c)SendChatMessage(d,"CHANNEL",nil,a) ---@diagnostic disable-next-line: missing-fields shared.MinimapTagger = {} function shared.MinimapTagger.Init() ---@param x number ---@param y number ---@param frame Frame ---@param scale number? ---@param ttl number? local function PlantFrame(x, y, frame, scale, ttl) if not BattlefieldMinimap then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] BattlefieldMinimap not found", ModuleName)) end return end scale = scale or 1 ttl = ttl or 1 local w, h = BattlefieldMinimap:GetSize() w, h = w * BattlefieldMinimap:GetEffectiveScale(), h * BattlefieldMinimap:GetEffectiveScale() local maxSize = w > h and w or h if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Minimap size: %d", ModuleName, maxSize)) print(string.format("[%s] Scale: %d", ModuleName, scale)) print(string.format("[%s] TTL: %d", ModuleName, ttl)) end local iconSize = maxSize * 0.05 iconSize = iconSize * scale x, y = x / 100, y / 100 -- Could do with how... I have no idea, but this seems more accurate than without --x, y = x - 0.01, y - 0.01 local offsetx, offsety = w * x, h * y if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Alert position: %d, %d", ModuleName, x, y)) print(string.format("[%s] Alert offset: %d, %d", ModuleName, offsetx, offsety)) end frame:Hide() frame:SetSize(iconSize, iconSize) frame:SetFrameStrata("HIGH") frame:SetFrameLevel(100) frame:SetPoint("CENTER", BattlefieldMinimap, "TOPLEFT", offsetx, -offsety) if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Alert frame created, OnUpdate hooked", ModuleName)) end frame:SetScript("OnShow", function(self) self:SetAlpha(1) self.custom.busy = true self.custom.progress = 0 self:SetScript("OnUpdate", function(self, elapsed) self.custom.progress = self.custom.progress + elapsed local progress = self.custom.progress / ttl -- if Heimdall_Data.config.minimapTagger.debug then -- print(string.format("[%s] Alert progress%%: %f", ModuleName, progress)) -- print(string.format("[%s] Alert progress: %f", ModuleName, self.custom.progress)) -- print(string.format("[%s] Alert ttl: %d", ModuleName, Heimdall_Data.config.minimapTagger.ttl)) -- end self:SetAlpha(1 - progress) if progress >= 1 then self:Hide() self.custom.busy = false self:SetScript("OnUpdate", nil) end end) end) frame:Show() end --region Alert ---@type Frame[] local alertFramePool = {} local alertFramePoolMaxSize = 20 for i = 1, alertFramePoolMaxSize do local frame = CreateFrame("Frame") frame.custom = { busy = false } local texture = frame:CreateTexture(nil, "ARTWORK") texture:SetAllPoints(frame) texture:SetTexture(TextureRoot .. Heimdall_Data.config.minimapTagger.alertTextureFile) table.insert(alertFramePool, frame) end local muteAlertUntil = 0 ---@param x number ---@param y number ---@param scale number? local function PlantAlert(x, y, scale) local frame = nil for _, alertFrame in ipairs(alertFramePool) do if not alertFrame.custom.busy then frame = alertFrame break end end if not frame then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Alert frame pool is full and could not get frame", ModuleName)) end return end if Heimdall_Data.config.minimapTagger.alertSound then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Playing alert sound: %s", ModuleName, Heimdall_Data.config.minimapTagger.alertSoundFile)) end if muteAlertUntil > GetTime() then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Alert sound is muted until %d", ModuleName, muteAlertUntil)) end else muteAlertUntil = GetTime() + Heimdall_Data.config.minimapTagger.alertSoundThrottle local ok = PlaySoundFile(SoundRoot .. Heimdall_Data.config.minimapTagger.alertSoundFile, "Master") if not ok and Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Failed to play alert sound: %s", ModuleName, Heimdall_Data.config.minimapTagger.alertSoundFile)) end end end PlantFrame(x, y, frame, scale, Heimdall_Data.config.minimapTagger.alertTTL) end --endregion --region Tag ---@type Frame[] local tagFramePool = {} local tagFramePoolMaxSize = 20 for i = 1, tagFramePoolMaxSize do local frame = CreateFrame("Frame") frame.custom = { busy = false } local texture = frame:CreateTexture(nil, "ARTWORK") texture:SetAllPoints(frame) texture:SetTexture(TextureRoot .. Heimdall_Data.config.minimapTagger.tagTextureFile) table.insert(tagFramePool, frame) end local muteTagUntil = 0 ---@param x number ---@param y number ---@param scale number? local function PlantTag(x, y, scale) local frame = nil for _, tagFrame in ipairs(tagFramePool) do if not tagFrame.custom.busy then frame = tagFrame break end end if not frame then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Tag frame pool is full and could not get frame", ModuleName)) end return end if Heimdall_Data.config.minimapTagger.tagSound then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Playing tag sound: %s", ModuleName, Heimdall_Data.config.minimapTagger.tagSoundFile)) end if muteTagUntil > GetTime() then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Tag sound is muted until %d", ModuleName, muteTagUntil)) end else muteTagUntil = GetTime() + Heimdall_Data.config.minimapTagger.tagSoundThrottle local ok = PlaySoundFile(SoundRoot .. Heimdall_Data.config.minimapTagger.tagSoundFile, "Master") if not ok and Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Failed to play tag sound: %s", ModuleName, Heimdall_Data.config.minimapTagger.tagSoundFile)) end end end PlantFrame(x, y, frame, scale, Heimdall_Data.config.minimapTagger.tagTTL) end --endregion --region Combat ---@type Frame[] local combatFramePool = {} local combatFramePoolMaxSize = 20 for i = 1, combatFramePoolMaxSize do local frame = CreateFrame("Frame") frame.custom = { busy = false } local texture = frame:CreateTexture(nil, "ARTWORK") texture:SetAllPoints(frame) texture:SetTexture(TextureRoot .. Heimdall_Data.config.minimapTagger.combatTextureFile) table.insert(combatFramePool, frame) end local muteCombatUntil = 0 ---@param x number ---@param y number ---@param scale number? local function PlantCombat(x, y, scale) local frame = nil for _, combatFrame in ipairs(combatFramePool) do if not combatFrame.custom.busy then frame = combatFrame break end end if not frame then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Battle frame pool is full and could not get frame", ModuleName)) end return end if Heimdall_Data.config.minimapTagger.combatSound then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Playing combat sound: %s", ModuleName, Heimdall_Data.config.minimapTagger.combatSoundFile)) end if muteCombatUntil > GetTime() then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Combat sound is muted until %d", ModuleName, muteCombatUntil)) end else muteCombatUntil = GetTime() + Heimdall_Data.config.minimapTagger.combatSoundThrottle local ok = PlaySoundFile(SoundRoot .. Heimdall_Data.config.minimapTagger.combatSoundFile, "Master") if not ok and Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Failed to play combat sound: %s", ModuleName, Heimdall_Data.config.minimapTagger.combatSoundFile)) end end end PlantFrame(x, y, frame, scale, Heimdall_Data.config.minimapTagger.combatTTL) end --endregion --region Help ---@type Frame[] local helpFramePool = {} local helpFramePoolMaxSize = 20 for i = 1, helpFramePoolMaxSize do local frame = CreateFrame("Frame") frame.custom = { busy = false } local texture = frame:CreateTexture(nil, "ARTWORK") texture:SetAllPoints(frame) texture:SetTexture(TextureRoot .. Heimdall_Data.config.minimapTagger.helpTextureFile) table.insert(helpFramePool, frame) end local muteHelpUntil = 0 ---@param x number ---@param y number ---@param scale number? local function PlantHelp(x, y, scale) local frame = nil for _, helpFrame in ipairs(helpFramePool) do if not helpFrame.custom.busy then frame = helpFrame break end end if not frame then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Help frame pool is full and could not get frame", ModuleName)) end return end if Heimdall_Data.config.minimapTagger.helpSound then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Playing help sound: %s", ModuleName, Heimdall_Data.config.minimapTagger.helpSoundFile)) end if muteHelpUntil > GetTime() then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Help sound is muted until %d", ModuleName, muteHelpUntil)) end else muteHelpUntil = GetTime() + Heimdall_Data.config.minimapTagger.helpSoundThrottle local ok = PlaySoundFile(SoundRoot .. Heimdall_Data.config.minimapTagger.helpSoundFile, "Master") if not ok and Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Failed to play help sound: %s", ModuleName, Heimdall_Data.config.minimapTagger.helpSoundFile)) end end end PlantFrame(x, y, frame, scale, Heimdall_Data.config.minimapTagger.helpTTL) end --endregion local pauseUntil = 0 local frame = CreateFrame("Frame") frame:RegisterEvent("WORLD_MAP_UPDATE") frame:SetScript("OnEvent", function(self, event, addon) if pauseUntil > GetTime() then return end pauseUntil = GetTime() + 1 if not BattlefieldMinimap then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] BattlefieldMinimap not found", ModuleName)) end return end if not Heimdall_Data.config.minimapTagger.enabled then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] MinimapTagger is disabled", ModuleName)) end return end local scale = Heimdall_Data.config.minimapTagger.scale BattlefieldMinimap:SetScale(scale) BattlefieldMinimap:SetMovable(true) BattlefieldMinimap:EnableMouse(true) BattlefieldMinimap:RegisterForDrag("LeftButton") BattlefieldMinimap:SetScript("OnDragStart", function(self) self:StartMoving() end) BattlefieldMinimap:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end) BattlefieldMinimapBackground:Hide() BattlefieldMinimapCloseButton:Hide() BattlefieldMinimapCorner:Hide() BattlefieldMinimap:HookScript("OnHide", function(self) for _, alertFrame in ipairs(alertFramePool) do alertFrame:Hide() alertFrame.custom.busy = false end for _, tagFrame in ipairs(tagFramePool) do tagFrame:Hide() tagFrame.custom.busy = false end for _, battleFrame in ipairs(battleFramePool) do battleFrame:Hide() battleFrame.custom.busy = false end end) end) local chatFrame = CreateFrame("Frame") chatFrame:RegisterEvent("CHAT_MSG_CHANNEL") chatFrame:SetScript("OnEvent", function(self, event, msg, sender, ...) -- if Heimdall_Data.config.echoer.debug then -- print(string.format("[%s] Channel message received from: %s", ModuleName, sender)) -- end if not Heimdall_Data.config.minimapTagger.enabled then -- if Heimdall_Data.config.echoer.debug then -- print(string.format("[%s] Module disabled, ignoring message", ModuleName)) -- end return end local channelId = select(6, ...) local _, channelname = GetChannelName(channelId) -- if Heimdall_Data.config.echoer.debug then -- print(string.format("[%s] Processing message from channel: %s", ModuleName, channelname)) -- end if channelname ~= Heimdall_Data.config.minimapTagger.masterChannel then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Ignoring message from non-master channel: %s, need %s", ModuleName, channelname, Heimdall_Data.config.minimapTagger.masterChannel)) end return end if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Processing message from master channel: %s", ModuleName, sender)) shared.dumpTable(Heimdall_Data.config.minimapTagger) end --region Tag if string.find(msg, "^I see") then if Heimdall_Data.config.minimapTagger.tagTTL == 0 then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Tag TTL is 0, ignoring message: %s", ModuleName, msg)) end return end local x, y = string.match(msg, "%((%d+%.%d+)%s*,%s*(%d+%.%d+)%)") if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Found alert position: %s, %s", ModuleName, tostring(x), tostring(y))) end if x and y then PlantTag(tonumber(x), tonumber(y), 2) end end --endregion --region Combat if string.find(msg, "^I am in combat with") then if Heimdall_Data.config.minimapTagger.combatTTL == 0 then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Combat TTL is 0, ignoring message: %s", ModuleName, msg)) end return end if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Found combat alert in message: %s", ModuleName, msg)) end local x, y = string.match(msg, "%((%d+%.%d+)%s*,%s*(%d+%.%d+)%)") if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Found combat position: %s, %s", ModuleName, tostring(x), tostring(y))) end if x and y then PlantCombat(tonumber(x), tonumber(y), 2) end end --endregion --region Death if string.find(msg, " killed ") then if Heimdall_Data.config.minimapTagger.alertTTL == 0 then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Alert TTL is 0, ignoring message: %s", ModuleName, msg)) end return end if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Found death alert in message: %s", ModuleName, msg)) end local x, y = string.match(msg, "%((%d+%.%d+)%s*,%s*(%d+%.%d+)%)") if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Found death position: %s, %s", ModuleName, tostring(x), tostring(y))) end if x and y then PlantAlert(tonumber(x), tonumber(y), 2) end end --endregion --region Help if string.find(msg, "I need help") then if Heimdall_Data.config.minimapTagger.helpTTL == 0 then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Help TTL is 0, ignoring message: %s", ModuleName, msg)) end return end if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Found help alert in message: %s", ModuleName, msg)) end local x, y = string.match(msg, "%((%d+%.%d+)%s*,%s*(%d+%.%d+)%)") if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Found help position: %s, %s", ModuleName, tostring(x), tostring(y))) end if x and y then x, y = tonumber(x), tonumber(y) PlantHelp(x, y, 1) if TomTom then if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Adding help waypoint to TomTom", ModuleName)) end local areaId = string.match(msg, "%[(%d+)%]") or 0 if areaId then areaId = tonumber(areaId) end if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] Area ID: %s", ModuleName, tostring(areaId))) end TomTom:AddMFWaypoint(areaId, nil, x / 100, y / 100, { title = "Help " .. sender, world = true, from = "Heimdall", crazy = true, }) else if Heimdall_Data.config.minimapTagger.debug then print(string.format("[%s] No tomtom no waypoint", ModuleName)) end end end end --endregion end) print("[Heimdall] MinimapTagger loaded") end SlashCmdList["HEIMDALL_MINIMAPTAGGER"] = function(args) shared.MinimapTagger.Init() end SLASH_HEIMDALL_MINIMAPTAGGER1 = "/mf"