From b8e7fee9e7ceb839b4323f298d592406a94cc6fd Mon Sep 17 00:00:00 2001 From: Kelsi Date: Thu, 12 Mar 2026 07:04:45 -0700 Subject: [PATCH] feat: add quest kill objective markers on minimap Live NPCs that match active tracked quest kill objectives are now shown on the minimap as gold circles with an 'x' mark, making it easier to spot remaining quest targets at a glance without needing to open the map. Only shows targets for incomplete objectives in tracked quests. --- src/ui/game_screen.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index 2b219faf..bfbbd245 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -12878,6 +12878,46 @@ void GameScreen::renderMinimapMarkers(game::GameHandler& gameHandler) { IM_COL32(0, 0, 0, 255), marker); } + // Quest kill objective markers — highlight live NPCs matching active quest kill objectives + { + // Collect NPC entry IDs needed for incomplete kill objectives in tracked quests + std::unordered_set killTargetEntries; + const auto& trackedIds = gameHandler.getTrackedQuestIds(); + for (const auto& quest : gameHandler.getQuestLog()) { + if (quest.complete) continue; + if (!trackedIds.empty() && !trackedIds.count(quest.questId)) continue; + for (const auto& obj : quest.killObjectives) { + if (obj.npcOrGoId <= 0 || obj.required == 0) continue; + uint32_t npcEntry = static_cast(obj.npcOrGoId); + auto it = quest.killCounts.find(npcEntry); + uint32_t current = (it != quest.killCounts.end()) ? it->second.first : 0; + if (current < obj.required) killTargetEntries.insert(npcEntry); + } + } + + if (!killTargetEntries.empty()) { + for (const auto& [guid, entity] : gameHandler.getEntityManager().getEntities()) { + if (!entity || entity->getType() != game::ObjectType::UNIT) continue; + auto unit = std::static_pointer_cast(entity); + if (!unit || unit->getHealth() == 0) continue; + if (!killTargetEntries.count(unit->getEntry())) continue; + + glm::vec3 unitRender = core::coords::canonicalToRender( + glm::vec3(entity->getX(), entity->getY(), entity->getZ())); + float sx = 0.0f, sy = 0.0f; + if (!projectToMinimap(unitRender, sx, sy)) continue; + + // Gold circle with a dark "x" mark — indicates a quest kill target + drawList->AddCircleFilled(ImVec2(sx, sy), 5.0f, IM_COL32(255, 185, 0, 240)); + drawList->AddCircle(ImVec2(sx, sy), 5.5f, IM_COL32(0, 0, 0, 180), 12, 1.0f); + drawList->AddLine(ImVec2(sx - 2.5f, sy - 2.5f), ImVec2(sx + 2.5f, sy + 2.5f), + IM_COL32(20, 20, 20, 230), 1.2f); + drawList->AddLine(ImVec2(sx + 2.5f, sy - 2.5f), ImVec2(sx - 2.5f, sy + 2.5f), + IM_COL32(20, 20, 20, 230), 1.2f); + } + } + } + // Gossip POI markers (quest / NPC navigation targets) for (const auto& poi : gameHandler.getGossipPois()) { // Convert WoW canonical coords to render coords for minimap projection