From 39fc6a645ef68f2afe1fee7ad7805e0f5a6a830a Mon Sep 17 00:00:00 2001 From: Kelsi Date: Thu, 12 Mar 2026 15:19:08 -0700 Subject: [PATCH] feat: show party member dots on minimap with class colors and name tooltip Small colored squares appear on the minimap for each online party member at their server-reported position. Dots use WoW class colors when the entity is loaded, gold for the party leader, and light blue otherwise; dead members show as gray. Hovering a dot shows the member's name. --- src/ui/game_screen.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index e4c6202c..76b45dbb 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -14961,6 +14961,59 @@ void GameScreen::renderMinimapMarkers(game::GameHandler& gameHandler) { } } + // Party member dots on minimap — small colored squares with name tooltip on hover + if (gameHandler.isInGroup()) { + const auto& partyData = gameHandler.getPartyData(); + ImVec2 mouse = ImGui::GetMousePos(); + for (const auto& member : partyData.members) { + if (!member.hasPartyStats) continue; + bool isOnline = (member.onlineStatus & 0x0001) != 0; + bool isDead = (member.onlineStatus & 0x0020) != 0; + bool isGhost = (member.onlineStatus & 0x0010) != 0; + if (!isOnline) continue; + if (member.posX == 0 && member.posY == 0) continue; + + // Party stat positions: posY = canonical X (north), posX = canonical Y (west) + glm::vec3 memberRender = core::coords::canonicalToRender( + glm::vec3(static_cast(member.posY), + static_cast(member.posX), 0.0f)); + float sx = 0.0f, sy = 0.0f; + if (!projectToMinimap(memberRender, sx, sy)) continue; + + // Determine dot color: class color > leader gold > light blue + ImU32 dotCol; + if (isDead || isGhost) { + dotCol = IM_COL32(140, 140, 140, 200); // gray for dead + } else { + auto mEnt = gameHandler.getEntityManager().getEntity(member.guid); + uint8_t cid = entityClassId(mEnt.get()); + if (cid != 0) { + ImVec4 cv = classColorVec4(cid); + dotCol = IM_COL32( + static_cast(cv.x * 255), + static_cast(cv.y * 255), + static_cast(cv.z * 255), 230); + } else if (member.guid == partyData.leaderGuid) { + dotCol = IM_COL32(255, 210, 0, 230); // gold for leader + } else { + dotCol = IM_COL32(100, 180, 255, 230); // blue for others + } + } + + // Draw a small square (WoW-style party member dot) + const float hs = 3.5f; + drawList->AddRectFilled(ImVec2(sx - hs, sy - hs), ImVec2(sx + hs, sy + hs), dotCol, 1.0f); + drawList->AddRect(ImVec2(sx - hs, sy - hs), ImVec2(sx + hs, sy + hs), + IM_COL32(0, 0, 0, 180), 1.0f, 0, 1.0f); + + // Name tooltip on hover + float mdx = mouse.x - sx, mdy = mouse.y - sy; + if (mdx * mdx + mdy * mdy < 64.0f && !member.name.empty()) { + ImGui::SetTooltip("%s", member.name.c_str()); + } + } + } + for (const auto& [guid, status] : statuses) { ImU32 dotColor; const char* marker = nullptr;