CustomWaypoints: Rethinking Navigation in WoW Through Graph-Based Routing

An exploration of building a smarter routing engine for World of Warcraft

Table of Contents

Introduction

While working on a custom addon for WoW (Warmane, WotLK 3.3.5a), I ran into something that felt fundamentally off. Navigation addons like Carbonite are incredibly useful. They provide map overlays, waypoint systems, and routing with a directional arrow that guides you through the world. For most players, this is more than enough. But when I started pushing the system harder β€” long routes, intercontinental travel, optimization β€” I realized something: πŸ‘‰ the routing model itself is flawed. Not visually. Not UX-wise. But architecturally.

The Problem: Euclidean Thinking in a Non-Euclidean World

Most waypoint systems (including Carbonite) implicitly assume something simple: the shortest path between two points is a straight line. And while this works for short distances, it breaks down quickly in a game like WoW. Because WoW is not a continuous space. It is a constrained graph. Zones connect only through specific gates, continents are disconnected without transports, movement is governed by portals, boats, zeppelins, trams, and flight paths depend on discovery state. Yet the routing logic still behaves like "just walk there". You've probably seen it: walking toward unreachable terrain, ignoring portals entirely, bypassing optimal travel methods, failing to use flight masters correctly. At that point, the arrow is no longer guidance. It's just a suggestion.

Why CustomWaypoints Exists

CustomWaypoints started from a simple frustration: I don't want a direction. I want a valid path. So instead of trying to tweak Carbonite's behavior, I built a layer on top of it. The idea was to keep Carbonite as a visualization engine and replace the routing logic with something explicit and controllable.

System Design: From Waypoints to Graphs

At its core, CustomWaypoints introduces a different abstraction. Instead of points in space connected by distance, we define nodes (zones, gates, portals, flight masters, transport hubs), edges (walk, taxi, portal, etc.), and cost functions (time, distance, penalties). This turns navigation into a classic graph problem. Suddenly, things become much clearer: pathfinding becomes deterministic, transitions are explicit, optimization is tunable. Instead of asking "where is the target?" we ask "what is the cheapest valid path to the target?"

Deep vs Minimal Routing

One of the most interesting design choices was introducing two routing modes. The minimal mode keeps the path simple, relies partially on Carbonite expansion, and only uses essential transport nodes, making it suitable for quick routes and short distances. In contrast, the deep mode expands the full path explicitly, inserts intermediate nodes like zone transitions and gates, and produces a fully deterministic route, ideal for long routes and complex navigation. This distinction exists because sometimes you want control, and sometimes you want speed. And these are not the same problem.

Transport Awareness

A major limitation in default routing is the lack of transport modeling. CustomWaypoints treats transports as first-class edges: portals, zeppelins, boats, trams, and flight masters. Each has entry constraints, cost, and availability (e.g., discovered vs. not). This allows the system to do something very simple but very powerful: compare fundamentally different travel methods in the same graph. For example, it can weigh a short walk against a long portal chain, taxi versus manual traversal, or multi-hop intercontinental routes.

Heuristics vs Reality

At some point, I experimented with A* heuristics. And that's where things got interesting. Because in a world like WoW, Euclidean distance is not a good heuristic, and connectivity matters more than proximity. In some cases, a node that is "closer" is actually worse because it lacks a valid transition or leads to longer constrained paths. This led to experimenting with reduced heuristics or even pure Dijkstra in some cases. πŸ‘‰ Trading theoretical optimality for practical correctness.

The Hard Part: Not Breaking Everything

The biggest challenge wasn't building the routing. It was integrating it safely. Carbonite still renders paths, expands routes, and controls UI behavior. So CustomWaypoints has to inject logic without breaking existing flows, control when expansion happens, and override behavior selectively. This turned into a system problem: not just pathfinding, but state synchronization between two engines.

What This Became

At some point, this stopped being "an addon". It became πŸ‘‰ a routing engine inside a game. With graph modeling, cost tuning, transport abstraction, and multi-layer system integration.

What I Learned

Most systems fail not because of UI, but because of wrong abstractions. Real-world navigation is almost always graph-based, not geometric. Heuristics can hurt more than help if the model is wrong. Small UX bugs often point to deeper architectural flaws.

Final Thought

I didn't build CustomWaypoints to add features. I built it because the existing system was making the wrong assumptions. And once you see that… you can't unsee it. From that point on, you're no longer fixing waypoints. You're fixing the model.


This post is part of my exploration into game development and optimization. Stay tuned for more!

GitHub: CustomWaypoints source