Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sr2echa/TF2-Source-Code/llms.txt

Use this file to discover all available pages before exploring further.

The navigation mesh (nav mesh) is a graph of CNavArea polygons that covers all walkable surfaces in a TF2 map. Bots use it to navigate from point to point using A* pathfinding. The base system lives in game/server/nav_mesh.cpp, and TF2 extends it with CTFNavMesh (game/server/tf/nav_mesh/) to tag areas with game-specific attributes like capture zone proximity and spawn room locations.

CNavArea

Each nav area is a convex quadrilateral (stored as four corner positions) with connections to adjacent areas. Areas encode travel costs, attributes, and ladder connections.
// game/server/nav_area.h
class CNavArea
{
public:
    NavAreaID       GetID() const;
    const Vector   &GetCenter() const;
    float           GetSizeX() const;
    float           GetSizeY() const;

    // Connections to adjacent areas
    const NavConnectVector *GetAdjacentAreas( NavDirType dir ) const;
    bool IsConnected( const CNavArea *area, NavDirType dir ) const;

    // Attribute flags
    NavAttributeType GetAttributes() const;
    bool HasAttributes( NavAttributeType bits ) const;
    void SetAttributes( NavAttributeType bits );

    // Cost for pathfinding
    float GetCostSoFar() const;
    float GetTotalCost() const;
};

CTFNavMesh and CTFNavArea

CTFNavMesh (game/server/tf/nav_mesh/tf_nav_mesh.h) extends CNavMesh with TF2-specific logic:
  • Tags areas adjacent to control points, capture zones, and spawn rooms
  • Tracks which areas are currently within a spawn room for each team
  • Updates area danger levels based on active sentry gun positions (m_sentryAreas)
  • Provides CollectAmbushAreas() for Spy/Sniper positioning
// game/server/tf/nav_mesh/tf_nav_mesh.h
class CTFNavMesh : public CNavMesh
{
public:
    virtual CTFNavArea *CreateArea() const;
    virtual void Update();
    virtual void OnRoundRestart();

    void CollectBuiltObjects( CUtlVector<CBaseObject *> *collection, int team );
    void CollectAmbushAreas( CUtlVector<CTFNavArea *> *ambushAreas,
                             CTFNavArea *startArea, int teamThatDominates,
                             float maxTravel ) const;
};
CTFNavArea adds TF2 attributes as a bitfield:
Attribute flagMeaning
TF_NAV_BLOCKEDBlocked by a map trigger or entity
TF_NAV_SPAWN_ROOM_RED / _BLUEInside a team spawn room
TF_NAV_SPAWN_ROOM_EXITAdjacent to a spawn room exit
TF_NAV_HAS_AMMOAmmo pack present nearby
TF_NAV_HAS_HEALTHHealth pack present nearby
TF_NAV_CONTROL_POINTAdjacent to a control point
TF_NAV_BLUE_SENTRY_DANGER / _RED_SENTRY_DANGERCovered by an enemy sentry

Pathfinding

Bots request paths through ILocomotion::IsAreaTraversable() and the CNavPathFollower system. The A* implementation in nav_pathfind.h uses CNavArea::GetCostSoFar() and a heuristic based on Euclidean distance to the goal.
// game/server/nav_pathfind.h
template< typename CostFunctor >
bool NavAreaBuildPath( CNavArea *startArea, CNavArea *goalArea,
                       const Vector *goalPos, CostFunctor &costFunc,
                       CNavArea **closestArea = NULL,
                       float maxPathLength = 0.0f,
                       int teamID = TEAM_ANY );
Nav meshes are generated by the nav_generate console command, which flood-fills the world from walkable seed points. The result is saved to a .nav file alongside the map BSP.
1

Generate

Run nav_generate in-server to auto-generate a nav mesh for the current map. The engine walks geometry and creates areas.
2

Edit

Use nav_edit 1 to enter nav edit mode. Select areas with +use, split/merge/connect with nav_split, nav_merge, nav_connect.
3

Mark TF attributes

Use nav_mark_attribute TF_NAV_SPAWN_ROOM_RED (etc.) while areas are selected to tag TF2-specific properties.
4

Save

nav_save writes the .nav file. It is loaded automatically when the map loads.
Shipped TF2 maps include hand-tuned .nav files distributed with the game. The auto-generated mesh is a starting point, not a final product — manual attribute tagging is required for correct bot behavior.

Build docs developers (and LLMs) love