Kelsidavis-WoWee/include/pipeline/wowee_taxi.hpp
Kelsi 3b107459b2 feat(pipeline): add WTAX (Wowee Taxi catalog) format
Novel open replacement for Blizzard's TaxiNodes.dbc +
TaxiPath.dbc + TaxiPathNode.dbc. The 24th open format
added to the editor.

Defines the flight-master network: a set of named nodes
(positions on the world map) plus the paths between them
(sequences of waypoints with per-segment delay and a
per-path gold cost). The same file holds both node and
path lists — flat arrays keyed by id, with intra-format
references from path.fromNodeId / toNodeId to node.nodeId.

Cross-references:
  WCRT.entry (with FlightMaster npcFlag) ~= WTAX.nodeId
                                            (matched by world
                                             position; flight
                                             master NPCs stand
                                             at their nodes)
  WTAX.path.fromNodeId / toNodeId -> WTAX.entry.nodeId
                                     (intra-format graph)

Format:
  • magic "WTAX", version 1, little-endian
  • nodes (each): nodeId / mapId / name / iconPath /
    position / faction restrictions
  • paths (each): pathId / from+toNodeId / moneyCostCopper /
    waypoints[] each with position + per-waypoint delaySec

API: WoweeTaxiLoader::save / load / exists +
WoweeTaxi::findNode / findPath / findPathBetween.

Three preset emitters showcase different graph shapes:
  • makeStarter  — 2 nodes + 2 paths (round-trip)
  • makeRegion   — 4 nodes at a 500m square + 4-path
                    directed ring (NW->NE->SE->SW->NW)
  • makeContinent — 6 nodes hub-spoke + 3 perimeter
                     shortcuts; intermediate waypoints
                     climb to altitude 120m for visual
                     arc effect

CLI added (5 flags, 564 documented total now):
  --gen-taxi / --gen-taxi-region / --gen-taxi-continent
  --info-wtax / --validate-wtax

Validator catches: nodeId/pathId=0 + duplicates, empty node
name, non-finite positions, fromNodeId == toNodeId
(self-loop path), path references to non-existent nodes
(intra-format cross-reference resolution), negative
waypoint delays.
2026-05-09 16:26:27 -07:00

113 lines
3.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <glm/glm.hpp>
#include <cstdint>
#include <string>
#include <vector>
namespace wowee {
namespace pipeline {
// Wowee Open Taxi catalog (.wtax) — novel replacement for
// Blizzard's TaxiNodes.dbc + TaxiPath.dbc + TaxiPathNode.dbc.
// The 24th open format added to the editor.
//
// Defines the flight-master network: a set of named nodes
// (positions on the world map) plus the paths between them
// (sequences of waypoints with per-segment delay and a
// per-path gold cost). The same file holds both node and
// path lists — flat arrays keyed by id.
//
// Cross-references with previously-added formats:
// WCRT.entry (with FlightMaster npcFlag) ≈ WTAX.entry.nodeId
// (matched by world
// position, not by
// direct ID — the
// flight-master NPC
// stands at the node)
// WTAX.path.fromNodeId / toNodeId → WTAX.entry.nodeId
// (intra-format graph)
//
// Binary layout (little-endian):
// magic[4] = "WTAX"
// version (uint32) = current 1
// nameLen + name (catalog label)
// nodeCount (uint32)
// nodes (each):
// nodeId (uint32)
// mapId (uint32)
// nameLen + name
// iconLen + iconPath
// position (3 × float)
// factionAlliance (uint32) / factionHorde (uint32)
// pathCount (uint32)
// paths (each):
// pathId (uint32)
// fromNodeId (uint32) / toNodeId (uint32)
// moneyCostCopper (uint32)
// waypointCount (uint32)
// waypoints (waypointCount × {
// position (3 × float)
// delaySec (float)
// })
struct WoweeTaxi {
struct Node {
uint32_t nodeId = 0;
uint32_t mapId = 0;
std::string name;
std::string iconPath;
glm::vec3 position{0};
uint32_t factionAlliance = 0; // 0 = available to all
uint32_t factionHorde = 0;
};
struct Waypoint {
glm::vec3 position{0};
float delaySec = 0.0f; // pause at this waypoint
};
struct Path {
uint32_t pathId = 0;
uint32_t fromNodeId = 0;
uint32_t toNodeId = 0;
uint32_t moneyCostCopper = 0;
std::vector<Waypoint> waypoints;
};
std::string name;
std::vector<Node> nodes;
std::vector<Path> paths;
bool isValid() const { return !nodes.empty(); }
// Lookup helpers.
const Node* findNode(uint32_t nodeId) const;
const Path* findPath(uint32_t pathId) const;
// First path matching a from→to pair, or nullptr.
const Path* findPathBetween(uint32_t fromNodeId, uint32_t toNodeId) const;
};
class WoweeTaxiLoader {
public:
static bool save(const WoweeTaxi& cat,
const std::string& basePath);
static WoweeTaxi load(const std::string& basePath);
static bool exists(const std::string& basePath);
// Preset emitters used by --gen-taxi* variants.
//
// makeStarter — 2 nodes + 1 path (round-trip 2 cities,
// 3 waypoints, 50 silver each way).
// makeRegion — 4 nodes around a square (~500m apart) +
// 4 paths forming a connected ring
// (each path is 2 waypoints).
// makeContinent — 6 nodes + 8 paths covering a small
// continent's flight network with
// cross-route shortcuts.
static WoweeTaxi makeStarter(const std::string& catalogName);
static WoweeTaxi makeRegion(const std::string& catalogName);
static WoweeTaxi makeContinent(const std::string& catalogName);
};
} // namespace pipeline
} // namespace wowee