feat: show undiscovered flight points on the world map

Draw undiscovered flight masters as green diamonds so players can see
where flight paths exist before visiting them, keeping discovered nodes
gold. Filter to the player's own faction (own-faction or neutral both-
faction nodes only) so the opposite faction's flight masters and
non-flight boat/zeppelin nodes are not shown. Adds GameHandler::
isPlayerAlliance() helper.
This commit is contained in:
Kelsi
2026-07-21 04:58:24 -07:00
parent 37e8767ae9
commit 2300ca3653
3 changed files with 43 additions and 5 deletions

View File

@@ -1298,6 +1298,17 @@ public:
const Character* ch = getActiveCharacter();
return ch ? static_cast<uint8_t>(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<Race>(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

View File

@@ -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());
}
}
}
}

View File

@@ -461,8 +461,23 @@ void GameScreen::renderWorldMap(game::GameHandler& gameHandler) {
std::vector<rendering::WorldMapTaxiNode> 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);