Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save WhyIsEvery4thYearAlwaysBad/39d286ccf03f1e06954b942c65362912 to your computer and use it in GitHub Desktop.

Select an option

Save WhyIsEvery4thYearAlwaysBad/39d286ccf03f1e06954b942c65362912 to your computer and use it in GitHub Desktop.
TF2 Nav mesh file format in Kaitai Struct.
# Base NAV file format in kaitai struct.
meta:
id: tf2_nav_mesh
title: TF2 Navigation Mesh (NAV)
file-extension: nav
tags:
- valve
- source_engine
- nav_mesh
- tf2
endian: le
# Docs
doc: |
File format used by the TF2 branch of the Source Engine to store nav mesh data for maps.
doc-ref:
- https://github.com/KitRifty/sourcepawn-navmesh
- https://developer.valvesoftware.com/wiki/NAV
- https://github.com/ValveSoftware/source-sdk-2013
# NAV Format
seq:
- id: magic_number
contents: [0xce, 0xfa, 0xed, 0xfe] # 0xFEEDFACE is outputed in reverse.
doc: Magic Number of the NAV file. NAV files are always generated with 0xFEEDFACE in little-endian.
- id: version
type: u4
doc: |
Version of the base NAV file format. It is present in all NAV files.
Changelog:
* 1 = hiding spots as plain vector array
* 2 = hiding spots as HidingSpot objects
* 3 = Encounter spots use HidingSpot ID's instead of storing vector again
* 4 = Includes size of source bsp file to verify nav data correlation
* ---- Beta Release at V4 -----
* 5 = Added Place info
* ---- Conversion to Source Engine ------
* 6 = Added Ladder info
* 7 = Areas store ladder ID's so ladders can have one-way connections
* 8 = Added earliest occupy times (2 floats) to each area
* 9 = Promoted CNavArea's attribute flags to a short
* 10 - Added sub-version number to allow derived classes to have custom area data
* 11 - Added light intensity to each area
* 12 - Storing presence of unnamed areas in the PlaceDirectory
* 13 - Widened NavArea attribute bits from unsigned short to int
* 14 - Added a bool for if the nav needs analysis
* 15 - removed approach areas
* 16 - Added visibility data to the base mesh
# NAV Subversion
- id: subversion
type: u4
if: 'version >= 10'
doc: |
Version of the NAV file for specialized implementations of the NAV file format. Added in NAV version 10.
Subversions used by Source Games:
* Base SDK and Garry's Mod | 0
* Counter-Strike: Source and Global Offensive | 1
* Team Fortress 2 | 2
* Left 4 Dead | 13
* Left 4 Dead 2 | 14
- id: bsp_size
type: u4
if: 'version >= 4'
doc: BSP Size of the map the NAV file was generated for. Added in NAV version 4.
- id: analyzed
type: u1 # The value is interpreted as a boolean, but it is actually stored as a full byte.
if: 'version >= 14'
doc: |
Value that stores if the nav mesh has been analyzed (usually through `nav_analyze`).
True: NAV file has been analyzed (usually through `nav_analyze`).
False: It has not been analyzed.
# Place Data
- id: place_count
type: u2
if: 'version >= 5'
doc: Amount of place names stored. Added in NAV version 5.
- id: place_name_array
type: place_name
repeat: expr
repeat-expr: place_count
if: 'version >= 5'
doc: Container for $place_count place names. Added in NAV version 5.
# Unnamed areas boolean.
- id: has_unnamed_areas
type: u1 # The value is interpreted as a boolean in the Source-Engine C++ code, but it is actually stored as a byte.
if: 'version >= 12'
doc: Determines if NAV file has unnamed areas. Added in NAV version 12.
# Area data.
- id: area_count
type: u4
doc: Amount of areas stored in the nav mesh.
- id: area_array
type: nav_area
repeat: expr
repeat-expr: area_count
doc: Container for stored navigation areas.
# Ladders
- id: ladder_count
type: u4
if: '_root.version >= 6'
doc: Amount of ladders stored in the nav mesh. Added in NAV version 6.
- id: ladder_array
type: nav_ladder
repeat: expr
repeat-expr: ladder_count
if: '_root.version >= 6'
doc: Container for ladder areas stored in the nav mesh. Added in NAV version 6.
- id: custom_data
size-eos: true
if: '_root.version >= 10 and _root.subversion != 0'
doc: Custom data appended by a specialized implementation of the NAV format. Should only be parsed if NAV file has a subversion.
types:
place_name:
seq:
- id: length
type: u2
doc: Length of the place name.
- id: name
type: str
size: length
encoding: ASCII
doc: The place name.
doc: Length-String pair that stores a place name.
# Connection Pair
area_id_array:
seq:
- id: count
type: u4
- id: area_ids
type: u4
repeat: expr
repeat-expr: count
# NavApproachSpot
approach_spot:
seq:
- id: target_area_id
type: u4
doc: ID of area to approach to.
- id: approach_prev
type: u4
- id: type
type: u1
- id: next
type: u4
- id: method
type: u1
doc: Datum point that determines the type of movement between areas. Removed in NAV version 15.
# NavHidingSpot
hiding_spot:
seq:
- id: hide_spot_id
type: u4
if: '_root.version >= 2'
doc: ID of the hide spot. Added in NAV version 2.
- id: hide_spot_position
type: f4
repeat: expr
repeat-expr: 3
if: '_root.version >= 1'
doc: Hide spot position (vector). Added in NAV version 1.
- id: attribute_flag
type: u1
doc: Hide spot attribute flags. Added in NAV version 2.
if: '_root.version >= 2'
enums:
# Attributes.
hide_spot_attribute:
1: in_cover
2: good_sniper_spot
4: ideal_sniper_spot
8: exposed
# Class: AreaBindInfo
area_bind:
seq:
- id: bound_area_id
type: u4
doc: Identifier of the targeted area.
- id: vis_attribute_flag
type: u1
enum: visibility_type
doc: "@brief Determines type of visibility to the bound area.
* Added in NAV version 16.
* Class"
doc: |
Holds relationship data to an area. Added in NAV version 16.
Reference Class: AreaBindInfo
enums:
# VisibilityType enum.
visibility_type:
0: not_visible
1: potentially_visible
2: completely_visible
# NavEncounterSpot
encounter_spot:
seq:
- id: order_id
type: u4
doc: The ID of the area to go to.
- id: parametric_distance
type: u1
doc: Parametric distance as byte.
doc: Spots of the encounter path that determine the path for the NextBot to take.
# NavEncounterPath
encounter_path:
seq:
- id: entry_area_id
type: u4
doc: The area ID to come from.
- id: entry_direction
type: u1
enum: nav_direction
- id: destination_area_id
type: u4
- id: destination_direction
type: u1
enum: nav_direction
# Encounter spots
- id: encounter_spot_count
type: u1
doc: Amount of encounter spots.
- id: encounter_spot_data
type: encounter_spot
repeat: expr
repeat-expr: encounter_spot_count
doc: Encounter spot container.
doc: |
A sequence of encounter spots which are used by NextBots to determine how to traverse an area.
# NavArea
nav_area:
enums:
# NavAttributeType
nav_attribute_type:
0: nav_mesh_id
0x00000001: nav_mesh_crouch # Must crouch to use this node/area.
0x00000002: nav_mesh_jump # Must jump to traverse this area (only used during generation).
0x00000004: nav_mesh_precise # Do not adjust for obstacles, just move along area.
0x00000008: nav_mesh_no_jump # Inhibit discontinuity jumping.
0x00000010: nav_mesh_stop # Must stop when entering this area.
0x00000020: nav_mesh_run # Must run to traverse this area.
0x00000040: nav_mesh_walk # Must walk to traverse this area.
0x00000080: nav_mesh_avoid # Avoid this area unless alternatives are too dangerous.
0x00000100: nav_mesh_transient # Area may become blocked, and should be periodically checked.
0x00000200: nav_mesh_dont_hide # Area should not be considered for hiding spot generation.
0x00000400: nav_mesh_stand # Bots hiding in this area should stand.
0x00000800: nav_mesh_no_hostages # Hostages shouldn't use this area.
0x00001000: nav_mesh_stairs # This area represents stairs, do not attempt to climb or jump them - just walk up.
0x00002000: nav_mesh_no_merge # Don't merge this area with adjacent areas.
0x00004000: nav_mesh_obstacle_top # This nav area is the climb point on the tip of an obstacle.
0x00008000: nav_mesh_cliff # This nav area is adjacent to a drop of at least CliffHeight.
0x00010000: nav_mesh_first_custom # Apps may define custom app-specific bits starting with this value.
0x04000000: nav_mesh_last_custom # Apps must not define custom app-specific bits higher than with this value.
0x20000000: nav_mesh_func_cost
0x40000000: nav_mesh_has_elevator # Area is in an elevator's path.
0x80000000: nav_mesh_nav_blocker # Area is blocked by nav blocker ( Alas, needed to hijack a bit in the attributes to get within a cache line [7/24/2008 tom]).
tf2_attribute_type:
0x00000000: tf_nav_invalid # also look for nav_mesh_nav_blocker (w/ nav_debug_blocked convar).
0x00000001: tf_nav_blocked # blocks nav area (for some tf-specific reason).
0x00000002: tf_nav_spawn_room_red # marks a nav area as if it was in a spawn room for red team.
0x00000004: tf_nav_spawn_room_blue # marks a nav area as if it was in a spawn room for blu team.
0x00000008: tf_nav_spawn_room_exit # marks an exit from a spawn room.
0x00000010: tf_nav_has_ammo # attribute that is applied when an ammo pack is on a nav area.
0x00000020: tf_nav_has_health # attribute that is applied when a health pack is on a nav area.
0x00000040: tf_nav_control_point # attribute that is applied when a control point is on a nav area.
0x00000080: tf_nav_blue_sentry_danger # marks that a red sentry is visible to the nav area.
0x00000100: tf_nav_red_sentry_danger # marks that a red sentry is visible to the nav area.
0x00000800: tf_nav_blue_setup_gate # blocks nav area to red team until the setup period is over.
0x00001000: tf_nav_red_setup_gate # blocks nav area to blue team until the setup period is over.
0x00002000: tf_nav_blocked_after_point_capture # area becomes blocked after a capture point is capped. (the capture point is specified through the `tf_nav_with_x_point` attributes.)
0x00004000: tf_nav_blocked_until_point_capture # area is blocked until a capture point is capped, then is unblocked. (the capture point is specified through the `tf_nav_with_x_point` attributes.)
0x00008000: tf_nav_blue_one_way_door # blocks nav area for red team.
0x00010000: tf_nav_red_one_way_door # blocks nav area for blu team.
0x00020000: tf_nav_with_second_point # selects the second capture point.
0x00040000: tf_nav_with_third_point # attribute modifier that selects the nth capture point (to be utilized by other attributes).
0x00080000: tf_nav_with_fourth_point # attribute modifier that selects the nth capture point (to be utilized by other attributes).
0x00100000: tf_nav_with_fifth_point # attribute modifier that selects the nth capture point (to be utilized by other attributes).
0x00200000: tf_nav_sniper_spot # indicates a good place for a sniper to lurk. (currently unused!)
0x00400000: tf_nav_sentry_spot # indicates a good place to build a sentry (currently unused!)
0x00800000: tf_nav_escape_route # for raid mode. (currently unused!)
0x01000000: tf_nav_escape_route_visible # all areas that have visibility to the escape route. (currently unused!)
0x02000000: tf_nav_no_spawning # don't spawn bots in this area
0x04000000: tf_nav_rescue_closet # for respawning friends in raid mode. (currently unused!)
0x08000000: tf_nav_bomb_can_drop_here # the bomb can be dropped here and reached by the invaders in mvm
0x10000000: tf_nav_door_never_blocks # prevents the nav area from being blocked if an overlapping door closes.
0x20000000: tf_nav_door_always_blocks # always blocks the nav area if an overlapping door closes.
0x40000000: tf_nav_unblockable # prevents an area from being unlocked.
seq:
# Custom data can be prepended here.
# Area Data.
- id: id
type: u4
doc: Identifier of an area.
- id: attribute_flag
type:
switch-on: _root.version
cases: {
0: u1,
1: u1,
2: u1,
3: u1,
4: u1,
5: u1,
6: u1,
7: u1,
8: u2,
9: u2,
10: u2,
11: u2,
12: u2,
13: u2,
_: u4
}
doc: Area attribute flag. Size varies across NAV versions.
- id: north_west_corner
type: f4
repeat: expr
repeat-expr: 3
doc: The north-west corner position of an area.
- id: south_east_corner
type: f4
repeat: expr
repeat-expr: 3
doc: The south-east corner position of an area.
- id: north_east_corner_height
type: f4
doc: The height (Z coordinate) of the area's north-east corner.
- id: south_west_corner_height
type: f4
doc: The height (Z coordinate) of the area's south-west corner.
# Connection data.
- id: connection_data
type: area_id_array
repeat: expr
repeat-expr: 4
doc: Container for connections.
# Hide spots
- id: hiding_spot_count
type: u1
doc: Amount of hiding spots.
- id: hiding_spot_data
type: hiding_spot
repeat: expr
repeat-expr: hiding_spot_count
# Approach Spots
- id: approach_spot_count
type: u1
if: '_root.version < 15'
doc: Approach spot count. Removed in NAV version 15 and above.
- id: approach_spot_data
type: approach_spot
repeat: expr
repeat-expr: approach_spot_count
if: '_root.version < 15'
# Encounter Path
- id: encounter_path_count
type: u4
doc: Amount of encounter paths.
- id: encounter_path_data
type: encounter_path
repeat: expr
repeat-expr: encounter_path_count
# Place ID
- id: place_id
type: u2
doc: Reference place index.
# Ladders
- id: ladder_data
type: area_id_array
repeat: expr
repeat-expr: 2
# Occupy times
- id: earliest_occupation_time
type: f4
repeat: expr
repeat-expr: 2
if: '_root.version >= 8'
doc: Earliest occupation times possible for each team. Added in NAV version 8.
# Light Intensity
- id: light_intensity
type: f4
repeat: expr
repeat-expr: 4
if: '_root.version >= 11'
doc: Light Intensities for each corner. Added in NAV version 11.
# Vis areas
- id: area_bind_count
type: u4
if: '_root.version >= 16'
doc: Amount of area-binds stored in area data. Added in NAV version 16.
- id: area_bind_array
type: area_bind
repeat: expr
repeat-expr: area_bind_count
if: '_root.version >= 16'
# Inheritance
- id: area_id_vis_inherit
type: u4
if: '_root.version >= 16'
doc: ID of area to inherit visibility bind information from. Only exists in NAV version 16 and later.
# TF2-specific attribute-flag
- id: tf2_attribute_flag
type: u4
enum: tf2_attribute_type
doc: Attribute bit flag for TF2-specific attributes.
# NavLadder
nav_ladder:
seq:
- id: ladder_id
type: u4
doc: Area ID of the ladder.
- id: width
type: f4
doc: Width of the ladder area.
- id: top_corner
type: f4
repeat: expr
repeat-expr: 3
doc: Top corner (vector) of the ladder.
- id: bottom_corner
type: f4
repeat: expr
repeat-expr: 3
doc: Bottom corner (vector) of the ladder.
- id: length
type: f4
doc: Length of the ladder area.
- id: direction
type: u4
enum: nav_ladder_direction
doc: Direction of the navigation area.
- id: top_forward_area_id
type: u4
doc: Connects area ID to the front of the top rung.
- id: top_left_area_id
type: u4
- id: top_right_area_id
type: u4
- id: top_behind_area_id
type: u4
- id: bottom_area_id
type: u4
enums:
nav_ladder_direction:
0: up
1: down
2: count
doc: A subtype of a navigation area that allows NextBots to walk up it. Added in NAV version 6.
enums:
# Directions defined by the Source Engine.
nav_direction:
0: north
1: east
2: south
3: west
# Amount of directions
4: count
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment