diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index 051f9825..48bf9d9c 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -1298,6 +1298,17 @@ public: const Character* ch = getActiveCharacter(); return ch ? static_cast(ch->race) : 0; } + // Horde races: Orc, Undead, Tauren, Troll, Goblin, Blood Elf. Everything + // else (including an unknown/zero race) defaults to Alliance. + bool isPlayerAlliance() const { + switch (static_cast(getPlayerRace())) { + case Race::ORC: case Race::UNDEAD: case Race::TAUREN: + case Race::TROLL: case Race::GOBLIN: case Race::BLOOD_ELF: + return false; + default: + return true; + } + } void setPlayerGuid(uint64_t guid) { playerGuid = guid; } // Player death state diff --git a/src/rendering/world_map/layers/taxi_node_layer.cpp b/src/rendering/world_map/layers/taxi_node_layer.cpp index 0c7caff8..4fc985a4 100644 --- a/src/rendering/world_map/layers/taxi_node_layer.cpp +++ b/src/rendering/world_map/layers/taxi_node_layer.cpp @@ -119,7 +119,6 @@ void TaxiNodeLayer::renderWorldMapMarkers(const LayerContext& ctx, bool isContinent) { ImVec2 mp = ImGui::GetMousePos(); for (const auto& node : *nodes_) { - if (!node.known) continue; glm::vec3 rPos(0.0f); if (!projectNodeToDisplayedMap(node, ctx, rPos)) continue; glm::vec2 uv = renderPosToMapUV(rPos, bounds, isContinent); @@ -128,13 +127,26 @@ void TaxiNodeLayer::renderWorldMapMarkers(const LayerContext& ctx, float px = ctx.imgMin.x + uv.x * ctx.displayW; float py = ctx.imgMin.y + uv.y * ctx.displayH; - drawDiamond(ctx.drawList, px, py, 5.0f, - IM_COL32(255, 215, 0, 230), IM_COL32(80, 50, 0, 200), 1.2f); + // Discovered nodes are gold; undiscovered flight masters are drawn in + // green so the player can see where flight paths exist before visiting + // them (matches the green flight-point icon from the game). + if (node.known) { + drawDiamond(ctx.drawList, px, py, 5.0f, + IM_COL32(255, 215, 0, 230), IM_COL32(80, 50, 0, 200), 1.2f); + } else { + drawDiamond(ctx.drawList, px, py, 4.5f, + IM_COL32(70, 200, 90, 210), IM_COL32(15, 60, 25, 200), 1.2f); + } if (!node.name.empty()) { float mdx = mp.x - px, mdy = mp.y - py; if (mdx * mdx + mdy * mdy < 49.0f) { - ImGui::SetTooltip("%s\n(Flight Master)", node.name.c_str()); + if (node.known) { + ImGui::SetTooltip("%s\n(Flight Master)", node.name.c_str()); + } else { + ImGui::SetTooltip("%s\n(Flight Master — not yet discovered)", + node.name.c_str()); + } } } } diff --git a/src/ui/game_screen_hud.cpp b/src/ui/game_screen_hud.cpp index 565928d6..86bac24c 100644 --- a/src/ui/game_screen_hud.cpp +++ b/src/ui/game_screen_hud.cpp @@ -461,8 +461,23 @@ void GameScreen::renderWorldMap(game::GameHandler& gameHandler) { std::vector taxiNodes; const auto& nodes = gameHandler.getTaxiNodes(); uint32_t currentTaxiNode = gameHandler.getTaxiCurrentNode(); + const bool playerAlliance = gameHandler.isPlayerAlliance(); taxiNodes.reserve(nodes.size()); for (const auto& [id, node] : nodes) { + const bool known = gameHandler.isKnownTaxiNode(id); + // Undiscovered nodes are shown so the player can see where flight + // paths exist, but only ones their faction can actually use. A node's + // faction is inferred from which taxi mount TaxiNodes.dbc lists: + // own-faction mount → show; both mounts → neutral flight point, show; + // opposite-faction-only OR no mount at all (boat/zeppelin/script + // nodes) → hide. Known nodes are always shown. + if (!known) { + const bool hasAlliance = node.mountDisplayIdAlliance != 0; + const bool hasHorde = node.mountDisplayIdHorde != 0; + const bool bothFactions = hasAlliance && hasHorde; // neutral hub + const bool ownFaction = playerAlliance ? hasAlliance : hasHorde; + if (!bothFactions && !ownFaction) continue; + } rendering::WorldMapTaxiNode wtn; wtn.id = node.id; wtn.mapId = node.mapId; @@ -475,7 +490,7 @@ void GameScreen::renderWorldMap(game::GameHandler& gameHandler) { wtn.wowY = canonical.y; wtn.wowZ = canonical.z; wtn.name = node.name; - wtn.known = gameHandler.isKnownTaxiNode(id); + wtn.known = known; wtn.costCopper = gameHandler.getTaxiCostTo(id); wtn.current = (id == currentTaxiNode); wtn.reachable = gameHandler.hasTaxiRouteTo(id);