4 bytes: size of the level file header
2 bytes: (with 3 bytes of padding) that describes the version number of the header
4 bytes: Unknown/Unused
4 bytes: A 32 bit integer that refers to the position in the file where some now obsolete data is.
4 bytes: Unknown/Unused
4 bytes: A 32 bit integer that refers to the position in the file where the navigation data is.
1 byte: size of the file header
4 bytes: An 8 bit integer (with 3 bytes of padding) that describes the version number of the header
8 bytes: A 64 bit integer that describes how many Unique IDs for things that have been used.
4 bytes: width (32 bit integer)
4 bytes: height (32 bit integer)
1 byte: A Boolean which is always true
33792 bytes: A “palette” of themes that can be on the height field
4 bytes: Ambient Sound Version. 3 = Global, 0 = Use Heightmap Sound
4 bytes: The number of sound themes that are available.
33792 bytes: A “palette” of sound atmosphere themes that can be on the height field.
4 bytes: A checksum. this exists only if the map header pad byte 2 is 9
loop of number of sound themes - 1
uint string length char[string length] string
endloop
Then, the real meat of the file: the heightfield data. (Width+1)*(Height+1) (read in above) cells are written out. A cell consists of the following data:
4 bytes: A 32 bit integer that's the size of the cell being written (should always be the same for every cell).
1 bytes: An 8 bit integerthat describes the version number of the cell
4 bytes: A 32 bit floating point number that's the height of the ground at that point divided by 2048.
1 byte: Should be 0.
3 bytes: These are actually an array of 3 single bytes. Each byte refers to a ground theme in the palette defined in the header.
2 bytes: A 2 element array that contains the strength of the ground themes in the previous array. The 2 numbers should add up to 255 (less if 3 themes are used).
1 byte: A Boolean that specifies whether the hero can walk on the ground at this point.
1 byte: A Boolean that specifies whether the camera is allowed to pass over the ground at this point.
1 byte: Sound Theme
1 byte: Should be 0.
1 byte: Boolean that specifies whether this cell is a shore point
1 byte: Unknown/Unused
There then follows a Width*Height amount of cells. These cells have the following format:
4 bytes: A 32 bit integer that's the size of the cell being written.
1 byte: An 8 bit integer that describes the version number of the cell
3 bytes: A 3 element array with each byte referring to a sound atmosphere theme in the palette defined in the header.
2 bytes: A 2 element array that contains the strength of the sound atmosphere themes in the previous array. The 2 numbers should add up to 255 (less if 3 themes are used)
1 byte: A sound theme palette index.
4 bytes - Start of Navigation Data
4 bytes - Number of Navigation Sections
[Section Names]
4 bytes - String Length [String Length] String 4 bytes - Start of Section's Navigation Data
[/Section Names]
4 bytes - Size
4 bytes - Version
4 bytes - Level Width
4 bytes - Level Height
4 bytes - Unknown Number of levels, see navigation nodes
4 bytes - Number Interactive Nodes
[Interactive Nodes] Location of Interactive Items
4 bytes - Number of SubSets
4 bytes - Number of Level Nodes
[Level Nodes] Walkable Area layered by accuracy
4 bytes - X coord
4 bytes - Y coord
4 bytes - SubSet
A Subset has 7 Layers (0-6), each defining blocks of walkable area.
Layer 0 = 32 X 32
Layer 1 = 16 X 16
Layer 2 = 8 X 8
Layer 3 = 4 X 4
Layer 4 = 2 X 2
Layer 5 = 1 X 1
Layer 6 = 0.5 X 0.5
00 00 00 00
00 01 00 00
struct NAV_STANDARD_NODE { BYTE unknown BYTE ROOT BYTE unknown BYTE END BYTE Layer; //0-6 BYTE SubSet; FLOAT X Coord; FLOAT Y Coord; DWORD NodeID; DWORD ChildNode; //Top Right DWORD ChildNode; //Top Left DWORD ChildNode; //Bottom Right DWORD ChildNode; //Bottom Left };
00 00 00 01
00 01 00 01
struct NAV_NODE { BYTE unknown BYTE ROOT BYTE unknown BYTE END BYTE Layer; //0-6 BYTE SubSet; FLOAT X Coord; FLOAT Y Coord; DWORD NodeID; DWORD Level; //Represents some sort of z level attribute BYTE Unknown; //So far, Subset 0 = 0 or 128, SubSet 1+ = 64 DWORD NumberNodes; DWORD AdjacentNode[NumberNodes]; //Adjanent navigation or exit nodes };
01 00 00 01
01 00 01 01
struct EXIT_NODE { BYTE unknown BYTE ROOT BYTE unknown BYTE END BYTE Layer; //0-6 BYTE SubSet; FLOAT X Coord; FLOAT Y Coord; DWORD NodeID; DWORD Level; //Represents some sort of z level attribute BYTE Unknown; //So far, Subset 0 = 0 or 128, SubSet 1+ = 64 DWORD NumberNodes; DWORD AdjacentNode[NumberNodes]; //Adjanent navigation or exit nodes DWORD NumberUIDs; QWORD TNG_UID[NumberUIDs]; // Stripped UID to create the real uid add 18446741874686296064 to this value };
00 01 01
struct BLANK_NODE { BYTE unknown; BYTE ROOT; BYTE unknown; };