NAV (file format): Difference between revisions
No edit summary |
CHILLMODEA (talk | contribs) m (fix merge notice) |
||
(69 intermediate revisions by 26 users not shown) | |||
Line 1: | Line 1: | ||
{{ | {{back|Nav Mesh}} | ||
A NAV file is a | {{distinguish|AIN}} | ||
{{merge|[[Nav Mesh]]}} | |||
A '''NAV''' file is a map specific [[Nav Mesh|'''<u>Nav</u>'''igation Mesh]] file that defines the walkable space in a level for [[bot]]s in {{gldsrc|1}} ({{cscz|1|nt=1}}) and {{src|1}} games. They usually reside in <code><game folder>/maps</code> and can be integrated into [[BSP|BSPs]] in some [[Source]] games.{{clarify}} | |||
{{Todo|Document GoldSrc version. Format is identical - {{cscz|1}} uses version 5.}} | |||
= | == Games == | ||
In {{css|4}} and {{csgo|4}}, the file is generated automatically when bots are played or being added into a map for the first time on a specific map that doesn't have one. | |||
[[ | Nav Mesh file write is open source in Source SDK 2013: https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/game/server/nav_file.cpp#L1071 | ||
Nav Mesh generation is also open source in Source SDK 2013: https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/game/server/nav_generate.cpp#L3399 | |||
{{l4d|4}} games have extra data per nav-area, as well as in after the nav place directory (null term string + short?), both of which have unknown format. | |||
== File format == | |||
{{todo|The information listed on the NAV file structure is too vague.}} | |||
{{confirm|At least two versions of .nav files.}} | |||
{{todo|Add approach spot data.}} | |||
{{note|This is reverse engineered data.}} | |||
{{ExpandBox|<source lang="cpp"> | |||
unsigned int magicNumber; // Magic number to check if the file is a .nav file (little endian 0xFEEDFACE) | |||
unsigned int version; // Version of the .nav file, for example GMod and TF2 has 16 | |||
if ( version >= 10 ) { | |||
unsigned int subVersion; // Sub version of the .nav file, for example GMod has 0, TF2 has 2. This is usedt | |||
} | |||
if ( version >= 4 ) { | |||
unsigned int saveBspSize; // Size of source bsp file to verify that the bsp hasn't changed | |||
} | |||
if ( version >= 14 ) { | |||
unsigned char isAnalyzed; | |||
} | |||
if ( version >= 5 ) { | |||
// Callouts. Places data. This is the "Mid", "Banana", etc stuff that is used in this nav mesh | |||
unsigned short count; | |||
for( int i = 0; i < count; ++i ) { | |||
unsigned short len; // length of the name | |||
char name[len]; // The name. Maximum len is 256 | |||
} | |||
if ( version > 11 ) { | |||
unsigned char m_hasUnnamedAreas; | |||
} | |||
} | |||
{ | |||
// PreLoadAreas( count ) | |||
// This is by default is completely unused, it is left for mods to store custom data | |||
// Assuming that the data is per nav area | |||
//for( int i = 0; i < count; ++i ) { | |||
//} | |||
} | |||
unsigned int areaCount; // number of CNavAreas | |||
area_t area[areaCount]; // Area Data | |||
if ( version >= 6 ) { | |||
unsigned int ladderCount; // number of CNavLadders | |||
ladder_t ladders[ladderCount]; // Ladder Data | |||
} | |||
{ | |||
// Load Custom Data | |||
// Again, by default this is unused | |||
} | |||
</source>}} | |||
===Area=== | |||
A navigation area is a bounding square in which bots can move. | |||
<source lang="cpp"> | |||
struct nav_area_t { | |||
unsigned int ID; // Identifier of the navigation area. | |||
union AttributeBitField { | |||
unsigned char; // In NAV versions ≤ 8 | |||
unsigned short; // In NAV versions ≤ 12 | |||
unsigned int; // In NAV Versions ≥ 13 | |||
}; | |||
float nwCorner[3]; // North-West corner vector. | |||
float seCorner[3]; // South-East corner vector. | |||
float NorthEastZ; // Z coordinate of North-East corner. | |||
float SouthWestZ; // Z coordinate of South-West corner. | |||
connectionData_t connectionData[4]; // Connection data in NESW (North, East, South, West) order. | |||
unsigned char hidingSpotCount; // Amount of hiding spots. | |||
hidingSpot_t hidingSpots[hidingSpotCount]; // Hiding spot data. | |||
/* Approach spots were removed in NAV version 15. | |||
unsigned char approachSpotCount; // Amount of approach spots | |||
approachSpot_t approachSpotData[approachSpotCount]; // Approach spot data. | |||
*/ | |||
unsigned int encounterPathCount; // Amount of encounter paths. | |||
encounterPath_t encounterPaths[encounterPathCount]; // Encounter path data. | |||
unsigned short PlaceID; // ID of place. | |||
// Ladder data stored in order of vertical direction (up then down). | |||
struct ladderIDSequence_t { | |||
unsigned int ladderCount; // Amount of ladder Ids. | |||
unsigned int ladderIDs[ladderCount]; // Ladder IDs | |||
} ladderIDSequence[2]; | |||
float EarliestOccupyTimes[2]; // Earliest occupy times for teams. | |||
float LightIntensity[4]; // Light Intensities for each corner. | |||
unsigned int areaBindCount; // Amount of area-binds stored. | |||
nav_area_bind_t areaBindSequence[areaBindCount]; // Sequence of area-binds stored. | |||
unsigned int InheritVisibilityFromAreaID; // Inherit visibility from area. | |||
void* customData; // Game-specific data. | |||
} | |||
</source> | |||
===Approach Spot=== | |||
{{todo|Describe variables.}} | |||
<source lang="cpp"> | |||
struct approachSpot_t { | |||
uint approachHereId; | |||
uint approachPrevId; | |||
byte approachType; | |||
uint approachNextId; | |||
byte approachHow; | |||
} | |||
</source> | |||
===Area-bind=== | |||
Area-binds are a structure type used in nav areas to determine the visibility between the parent area and another navigation area, based on area ID. | |||
<source lang="cpp">struct nav_area_bind_t { | |||
unsigned int target_area_id; // Area ID of area. | |||
unsigned char AttributeBitField; // Attribute flag field that determines the visibility type. | |||
};</source> | |||
Area-binds were added in NAV version 16. | |||
===Connection=== | |||
<source lang="cpp"> | |||
struct connectionData_t { | |||
unsigned int count; // Amount of connections. | |||
unsigned int AreaIDs[count]; // List of area IDs that each connection points to. | |||
}; | |||
</source> | |||
===Hiding Spot=== | |||
Hiding spots are data structures used to determine points in a nav mesh that bots can hide at. | |||
<source lang="cpp"> | |||
enum Attribute : unsigned char // Hiding Spot attribute values. | |||
{ | |||
IN_COVER = 0x01, // In a corner with good hard cover nearby | |||
GOOD_SNIPER_SPOT = 0x02, // Had at least one decent sniping corridor | |||
IDEAL_SNIPER_SPOT = 0x04, // Can see either very far, or a large area, or both | |||
EXPOSED = 0x08 // Spot in the open, usually on a ledge or cliff | |||
}; | |||
struct hidingSpot_t { | |||
unsigned int ID; // Identifier of hide spot. Added in NAV version 2. | |||
float position[3]; // Position of the hiding spot. Added in NAV version 1. | |||
unsigned char Attributes; // Attribute field. Added in NAV version 2. Defaults to IN_COVER for version 1 | |||
}; | |||
</source> | |||
{| | |||
! Game !! Used For | |||
|- | |||
| {{tf2|4}} || Determines where Spy bots can lurk for targets. | |||
|- | |||
| {{css|4}} || Determines where bots can take cover and shoot at. | |||
|- | |||
| {{csgo|4}} || Determines where bots can take cover and shoot at. | |||
|} | |||
===Encounter Path=== | |||
Encounter paths are structures used to determine routes to take to get to certain areas. | |||
<source lang="cpp"> | |||
struct encounterPath_t { | |||
unsigned int EntryAreaID; // ID of the Area entered from. | |||
unsigned byte EntryDirection; // Direction of entry. | |||
unsigned int DestAreaID; // ID of the Area destination. | |||
unsigned byte DestDirection; // Direction towards the destination area. | |||
unsigned char encounterSpotCount; // Amount of encounter spots. | |||
encounterSpot_t encounterSpots[encounterSpotCount]; // Encounter spots. | |||
}; | |||
</source> | |||
{{warning|Encounter paths are only used in {{css|4}} and {{csgo|4}}.}} | |||
===Encounter Spot=== | |||
Encounter Spots (better termed waypoints) are data structures used in encounter paths to determine the order of area IDs in a route. | |||
<source lang="cpp"> | |||
struct encounterSpot_t { | |||
unsigned int AreaID; // The Area ID to go to. | |||
unsigned char ParametricDistance; // Parametric distance in bytes. | |||
}; | |||
</source> | |||
{{warning|Encounter spots are only used in {{css|4}} and {{csgo|4}}.}} | |||
===Ladder=== | |||
A navigation mesh ladder. | |||
<source lang="cpp"> | |||
struct nav_ladder_t { | |||
unsigned int ID; // Identifier of the navigation ladder. | |||
float width; // extent of ladder | |||
float top[3]; // top endpoint of ladder | |||
float bottom[3]; // bottom endpoint of ladder | |||
float length; // ladder length | |||
unsigned int direction; // Direction of the ladder (NavDirType) | |||
unsigned char bDangling; // if version 6, dangling status | |||
unsigned int topForwardArea; // area ID | |||
unsigned int topLeftArea; // area ID | |||
unsigned int topRightArea; // area ID | |||
unsigned int topBehindArea; // area ID | |||
unsigned int bottomArea; // area ID | |||
} | |||
</source> | |||
===Custom Data=== | |||
Some games store custom data in areas. | |||
{| class="wikitable" | |||
|+ Custom Area Data | |||
! Subversion !! Data !! Label | |||
|- | |||
| 2 || unsigned int || {{tf2|4}} specific attributes. | |||
|- | |||
| 1 || char[14] || {{csgo|4}} unknown data. | |||
|} | |||
==Versions Used By Games== | |||
{| class="wikitable" | |||
! Game | |||
! Version | |||
! Subversion | |||
|- | |||
| {{tf2|4}} | |||
| 16 | |||
| 2 | |||
|- | |||
| {{gmod|4}} | |||
| 16 | |||
| 0 | |||
|- | |||
| {{l4d2|4}} | |||
| 16 | |||
| 14 | |||
|- | |||
| {{l4d|4}} | |||
| 15 | |||
| 13 | |||
|- | |||
| {{css|4}} | |||
| 9 | |||
| n/a | |||
|- | |||
| {{cscz|4}} | |||
| 5 | |||
| n/a | |||
|} | |||
==See also== | |||
* [[Nav Mesh Editing]] | |||
===NAV processors=== | |||
* [https://github.com/Blackfire62/TF2_NavFile_Reader Nav file parser in C++.] | |||
* [https://codeberg.org/WhyIsEveryYearAlwaysBad/libSourceNav libSourceNav] — a NAV parser in Common Lisp. | |||
* [https://github.com/WhyIsEvery4thYearAlwaysBad/kaitai_struct_formats/blob/master/game/source_engine_nav.ksy Base NAV file format in Kaitai Struct.] | |||
* [https://github.com/mrazza/gonav Nav file parser in Go.] (Outdated) | |||
[[Category:Level Design]] | |||
[[Category:AI]] | |||
[[Category:File formats|nav]] | |||
[[Category:Counter-Strike: Source|nav]] | |||
[[Category:Team Fortress 2|nav]] | |||
[[Category:Counter-Strike: Global Offensive|nav]] |
Latest revision as of 18:41, 8 June 2025
A NAV file is a map specific Navigation Mesh file that defines the walkable space in a level for bots in GoldSrc (CS:CZ) and Source games. They usually reside in <game folder>/maps
and can be integrated into BSPs in some Source games.[Clarify]
Games
In Counter-Strike: Source and
Counter-Strike: Global Offensive, the file is generated automatically when bots are played or being added into a map for the first time on a specific map that doesn't have one.
Nav Mesh file write is open source in Source SDK 2013: https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/game/server/nav_file.cpp#L1071
Nav Mesh generation is also open source in Source SDK 2013: https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/game/server/nav_generate.cpp#L3399
Left 4 Dead games have extra data per nav-area, as well as in after the nav place directory (null term string + short?), both of which have unknown format.
File format


unsigned int magicNumber; // Magic number to check if the file is a .nav file (little endian 0xFEEDFACE)
unsigned int version; // Version of the .nav file, for example GMod and TF2 has 16
if ( version >= 10 ) {
unsigned int subVersion; // Sub version of the .nav file, for example GMod has 0, TF2 has 2. This is usedt
}
if ( version >= 4 ) {
unsigned int saveBspSize; // Size of source bsp file to verify that the bsp hasn't changed
}
if ( version >= 14 ) {
unsigned char isAnalyzed;
}
if ( version >= 5 ) {
// Callouts. Places data. This is the "Mid", "Banana", etc stuff that is used in this nav mesh
unsigned short count;
for( int i = 0; i < count; ++i ) {
unsigned short len; // length of the name
char name[len]; // The name. Maximum len is 256
}
if ( version > 11 ) {
unsigned char m_hasUnnamedAreas;
}
}
{
// PreLoadAreas( count )
// This is by default is completely unused, it is left for mods to store custom data
// Assuming that the data is per nav area
//for( int i = 0; i < count; ++i ) {
//}
}
unsigned int areaCount; // number of CNavAreas
area_t area[areaCount]; // Area Data
if ( version >= 6 ) {
unsigned int ladderCount; // number of CNavLadders
ladder_t ladders[ladderCount]; // Ladder Data
}
{
// Load Custom Data
// Again, by default this is unused
}
Area
A navigation area is a bounding square in which bots can move.
struct nav_area_t {
unsigned int ID; // Identifier of the navigation area.
union AttributeBitField {
unsigned char; // In NAV versions ≤ 8
unsigned short; // In NAV versions ≤ 12
unsigned int; // In NAV Versions ≥ 13
};
float nwCorner[3]; // North-West corner vector.
float seCorner[3]; // South-East corner vector.
float NorthEastZ; // Z coordinate of North-East corner.
float SouthWestZ; // Z coordinate of South-West corner.
connectionData_t connectionData[4]; // Connection data in NESW (North, East, South, West) order.
unsigned char hidingSpotCount; // Amount of hiding spots.
hidingSpot_t hidingSpots[hidingSpotCount]; // Hiding spot data.
/* Approach spots were removed in NAV version 15.
unsigned char approachSpotCount; // Amount of approach spots
approachSpot_t approachSpotData[approachSpotCount]; // Approach spot data.
*/
unsigned int encounterPathCount; // Amount of encounter paths.
encounterPath_t encounterPaths[encounterPathCount]; // Encounter path data.
unsigned short PlaceID; // ID of place.
// Ladder data stored in order of vertical direction (up then down).
struct ladderIDSequence_t {
unsigned int ladderCount; // Amount of ladder Ids.
unsigned int ladderIDs[ladderCount]; // Ladder IDs
} ladderIDSequence[2];
float EarliestOccupyTimes[2]; // Earliest occupy times for teams.
float LightIntensity[4]; // Light Intensities for each corner.
unsigned int areaBindCount; // Amount of area-binds stored.
nav_area_bind_t areaBindSequence[areaBindCount]; // Sequence of area-binds stored.
unsigned int InheritVisibilityFromAreaID; // Inherit visibility from area.
void* customData; // Game-specific data.
}
Approach Spot
struct approachSpot_t {
uint approachHereId;
uint approachPrevId;
byte approachType;
uint approachNextId;
byte approachHow;
}
Area-bind
Area-binds are a structure type used in nav areas to determine the visibility between the parent area and another navigation area, based on area ID.
struct nav_area_bind_t {
unsigned int target_area_id; // Area ID of area.
unsigned char AttributeBitField; // Attribute flag field that determines the visibility type.
};
Area-binds were added in NAV version 16.
Connection
struct connectionData_t {
unsigned int count; // Amount of connections.
unsigned int AreaIDs[count]; // List of area IDs that each connection points to.
};
Hiding Spot
Hiding spots are data structures used to determine points in a nav mesh that bots can hide at.
enum Attribute : unsigned char // Hiding Spot attribute values.
{
IN_COVER = 0x01, // In a corner with good hard cover nearby
GOOD_SNIPER_SPOT = 0x02, // Had at least one decent sniping corridor
IDEAL_SNIPER_SPOT = 0x04, // Can see either very far, or a large area, or both
EXPOSED = 0x08 // Spot in the open, usually on a ledge or cliff
};
struct hidingSpot_t {
unsigned int ID; // Identifier of hide spot. Added in NAV version 2.
float position[3]; // Position of the hiding spot. Added in NAV version 1.
unsigned char Attributes; // Attribute field. Added in NAV version 2. Defaults to IN_COVER for version 1
};
Game | Used For |
---|---|
![]() |
Determines where Spy bots can lurk for targets. |
![]() |
Determines where bots can take cover and shoot at. |
![]() |
Determines where bots can take cover and shoot at. |
Encounter Path
Encounter paths are structures used to determine routes to take to get to certain areas.
struct encounterPath_t {
unsigned int EntryAreaID; // ID of the Area entered from.
unsigned byte EntryDirection; // Direction of entry.
unsigned int DestAreaID; // ID of the Area destination.
unsigned byte DestDirection; // Direction towards the destination area.
unsigned char encounterSpotCount; // Amount of encounter spots.
encounterSpot_t encounterSpots[encounterSpotCount]; // Encounter spots.
};



Encounter Spot
Encounter Spots (better termed waypoints) are data structures used in encounter paths to determine the order of area IDs in a route.
struct encounterSpot_t {
unsigned int AreaID; // The Area ID to go to.
unsigned char ParametricDistance; // Parametric distance in bytes.
};



Ladder
A navigation mesh ladder.
struct nav_ladder_t {
unsigned int ID; // Identifier of the navigation ladder.
float width; // extent of ladder
float top[3]; // top endpoint of ladder
float bottom[3]; // bottom endpoint of ladder
float length; // ladder length
unsigned int direction; // Direction of the ladder (NavDirType)
unsigned char bDangling; // if version 6, dangling status
unsigned int topForwardArea; // area ID
unsigned int topLeftArea; // area ID
unsigned int topRightArea; // area ID
unsigned int topBehindArea; // area ID
unsigned int bottomArea; // area ID
}
Custom Data
Some games store custom data in areas.
Subversion | Data | Label |
---|---|---|
2 | unsigned int | ![]() |
1 | char[14] | ![]() |
Versions Used By Games
Game | Version | Subversion |
---|---|---|
![]() |
16 | 2 |
![]() |
16 | 0 |
![]() |
16 | 14 |
![]() |
15 | 13 |
![]() |
9 | n/a |
![]() |
5 | n/a |
See also
NAV processors
- Nav file parser in C++.
- libSourceNav — a NAV parser in Common Lisp.
- Base NAV file format in Kaitai Struct.
- Nav file parser in Go. (Outdated)