Jump to content

GHB files


RobExplorien
 Share

Recommended Posts

RobExplorien

LEGO Racers: The structure and values of ghost path files

 

NOTE: The following information was generally obtained by testing with the .GHB file located in the RACEC0R1 (Imperial Grand Prix) folder of the .JAM archive. Though I'm not completely sure, the information about to follow will apply to other .GHB files in the LEGO.JAM too. Values in code tags apply to the ghost racer on Imperial Grand Prix. This topic is not (yet) a full documentation of the regarding files. Tools used to gather the following information are JMMB's JAMExtractor and origamiguy's Binary File Editor.

 

I know that it is confirmed that .GHB files are the path files for the time trial ghost (AKA Veronica Voltage), but I have not found a good documentation of these files yet. I've been tinkering with these files lately, and would be glad to share the information I gained from working with these files. I will discuss the main values/structure of an .GHB file, and explain what value does what wherever I can. Some information that follows may already be known by some or many, but I felt that I should include most, if not all, information of these files here. If I missed out information, or if you know more that adds to the understanding of these files, I'd be glad to hear from you then.

 

To start off with, where can these files be found?

Each track folder (RACEC*R*) in the LEGO.JAM contains a single .GHB files by default, with the exception of RACEC3R0 (Rocket Racer Run) and TEST (Test Track), because time trial races are/were not meant to be held on those tracks.

How are these files named?

All .GHB files are named 'GHOST', indubitably referring to the semi-transparent racer which you race against on the time trials, Veronica Voltage. The file extension could mean something like 'Ghost Binary'.

 

What happens when I delete or replace a .GHB file from a track folder?

Deleting a .GHB file from a track folder hardly affects the game at all. It's like running on an unmodified LEGO.JAM, the ghost still follows the path from the designated track and no error messages show up during the game. Replacing a .GHB file with those of another track simply makes the AI follow this replaced path. For example, replacing the ghost's Knightmare-Athon path with the one from Magma Moon Marathon makes the boss follow the latter path on Knightmare-Athon. This path obviously isn't aligned with the Knightmare-Athon track, so you would see the red dot on the Knightmare-Athon map 'floating' around the actual track.

 

How is a .GHB file structured?

Elements of an .RRB file can be found in a .GHB file as well, but there are differences in both structure and definitions of values. Below is part of a .GHB file. All .GHB files share this structure. The code is 'divided' in five groups being: k_2A, k_28, k_29, k_2B and k_27. All in a single .GHB file applies to the path of a ghost racer on one track. This time, the path isn't named as 'nodes' in a comment, but we'll call it nodes anyway now. I left out the other 488 nodes for an obvious reason. You can already see a difference with the .RRB file nodes; (f16) and (f8) is structured different and (byte) is nowhere to be found.

k_2C
{
 k_2A
 42204
 38936
 40953
 k_28
 (float)455.1043
 (float)-239.2298
 (float)-76.33071
 k_29
 (float)0
 (float)0
 (float)0.970296
 (float)0.241923
 k_2B
 0
 k_27
 [489]
 {
  (f16)56.88672
  (f16)-29.90234
  (f16)-9.539063
  (f8)0
  (f8)0
  (f8)7.6875
  (f8)1.875
  ...
}

What are the values for in an .GHB file?

The values in a .GHB file vary from defining the startposition of the ghost racer, to the waypoints it has to follow in a race. These values are either set in integer or decimal numbers.

 

How is a startposition set in a .GHB file?

The floats under k_28 are used for defining the startposition of the ghost racer. They are relatively simple to understand. These floats define the startposition of an AI, and work the same as for the player (which are defined in an .SPB file) and opponents (in an .RRB file).

  • The first float under k_28 is for x-positioning. This means that the horizontal position (left/right) of an AI's vehicle is set with this float.
  • The second float under k_28 is for y-positioning. This means that the horizontal position (up/down) of an AI's vehicle is set with this float.
  • The third and last float under k_28 is for z-positioning. This means that the vertical position of an AI's vehicle is set with this float.

If you still like to know more about (editing) the startpositions, >this tutorial explains most of it.

 

How is rotation set in an .RRB file?

This is a double-sided question, because the rotation can refer to the startposition or the path. I'll discuss the former.

The floats under k_29 are for the rotation of the AI vehicle IN its startposition. This rotation is not for setting the direction of the path it has to follow, there is no connection between startposition rotation and path direction. That means, setting the rotation for the AI vehicle under k_28 to a different value may change the direction his/her vehicle faces, but at the moment the race starts, the AI will directly face its path direction. This can be clearly observed when setting the AI vehicle in reversed position (i.e. having its facing direction 180 degrees switched). At the moment the race starts, its vehicle will switch back 180 degrees to align instantly with the direction of its path again.

All floats under k_29 range from -1 to 1. This rotation is not based on quaternions, so that means rotation of an AI vehicle works different than that of a player.

  • The first two floats under k_29 are for a 3D rotation of an AI vehicle in startposition, to just call it that way. This also explains why the value of this float is always (close to) absolute zero, because in all tracks, the startposition is on a leveled surface. If this float is bigger or smaller than 0, the AI vehicle will align with the surface in an angled (see image) and somewhat twisted way, but not perpendicular at absolute 1 or -1 I believe. The float is represented as 'z'.
  • The last two floats under k_29 are for horizontal rotation of an AI vehicle in startposition.

gallery_6631_326_8778.png

 

(NOTE: In a .GHB file, the floats under k_28 define the startposition and under k_29 the rotation of this position. In an .RRB file, the floats under k_29 define the startposition and under k_28 the rotation of this position.)

 

What do the k_2C, k_2A and k_2B groups stand for?

I have this issue too with the .RRB files; I don't know what these stand for. I tried changing the values, and removing them, but nothing extraordinary happened when I ran a time trial against the ghost racer having these modified groups. The k_2C probably defines as to what we're talking about in this file, like a tag does in XHTML. The k_2A holds unsigned 16-bit integers in which ghost times are saved. Each line under k_2A contains an integer which is the lap time in milliseconds of laps 1, 2 and 3 respectively. Lastly, k_2B, don't know what it is for. They only appear 'naturally' as positive integers, but the game doesn't complain about signed integers.

 

What are the nodes (the k_27 group)?

Just like in an .RRB file, the nodes are set under k_27. Nodes are waypoints for a ghost to follow during a race. Going through all nodes in a single .GHB file means that the ghost racer completed three laps (thus one race). The nodes are the ones that really add up to the amount of code lines in the .GHB file, because one node only represents a small distance to race on the racetrack. Therefore a lot of nodes are used to fill a complete AI path. The average amount of nodes for a ghost's path is 450, but I've seen .GHB files with up to 603 nodes found in the RACEC2R2 folder (Adventure Temple Trail, the longest track in the game).

Below follows the structure of the nodes again. Each node consists of 7 code lines. I also put additional comments next to the nodes. These comments (subnode may not be the correct term) refer to the explanation given in the text below the code.

 k_27
 [489]
 {
  (f16)56.88672         //subnode 1
  (f16)-29.90234        //subnode 2
  (f16)-9.539063        //subnode 3
  (f8)0                 //subnode 4
  (f8)0                 //subnode 5
  (f8)7.6875            //subnode 6
  (f8)1.875             //subnode 7
  ...
}

 

What are the floats at (f16) for?

These three nodes are for the position of the path. Subnode 1 is for the x-position, subnode 2 is for the y-position and subnode 3 is for the z-position. So the ghost racer travels via positions, unlike the bytes in an .RRB file that define the 'speed' an AI has to pass a node. It seems that each node is passed in the same amount of time (probably in the range of 25-40 milliseconds?) and the difference in the position from the former node and next node have an effect on the speed of the ghost racer. For example, if the distance in position between node 4 and 5 is equal to 7ft and the distance in position between node 5 and 6 is 9.5ft, the ghost racer will travel faster from node 5 to 6 than from node 4 to 5 (same time limit).

The three nodes represent the coördinates of each node divided by 8 (due to limited storing space).

 

What are the floats at (f8) for?

These nodes concern the rotation of the ghost racer in its path. The rotation of the racer (object) is saved as unsigned 8-bit fixed points, representing quaternions.

  • Subnode 4 is for vertical rotation, thus the vertical alignment with the track. It works the same as the first two floats under k_29 (rotation of startposition).
  • Subnode 5 is also for vertical rotation, but then sideways. I guess I can explain it best with the image below (the float for subnode 5 is represented as 'z'):

gallery_6631_326_2696.png

  • Subnode 6 is for the horizontal rotation of the ghost racer during the path, meaning which direction the vehicle faces. Note that the faced direction does not define the direction of motion.
  • Subnode 7 also does something to the horizontal rotation, like subnode 6, but I also managed to flip the ghost racer upside down by setting the node to a specific value.

 

What happens if I remove (sub)nodes?

Unlike the .RRB files, tinkering with the subnodes in a .GHB file is prone to errors. If the node structure is messed up (e.g. only having two lines of (f16) instead of three) will result in a syntax error upon loading the track with the 'wrongly' modified .GHB file. Removing whole nodes from the .GHB will work fine if the amount specified between square brackets is the same as the amount of nodes under k_27. If certain nodes are removed from the .GHB, the ghost racer will skip the relevant nodes (positions) and immediately proceed to the path position of the next node, as if the ghost teleports. Thus the ghost racer keeps aligned with the track and won't go 'out of bounds'.

 

.GHB file compatible with .RRB file?

The idea has been floating around of replacing AI paths (in circuit races and single races) with ghost paths, like having your prerecorded path used by an AI. A great idea that would boost LR modding if possible. If you read through this documentation, you've seen the different structure of the waypoints compared to an .RRB file. A ghost racer moves via positions, a normal AI via bytes and relative coördinates; a ghost racer has three (f16) floats, a normal AI two; a ghost racer has a significant less amount of waypoints than a normal AI.

First of all, messing up the structure of waypoints is prone to errors in a .GHB file. Thus replacing those with the waypoints of an .RRB file won't simply work just like that, you get a syntax error. And second, replacing the waypoints of an .RRB file with those from a .GHB file will result in an 'invalid value' error. However, I did manage to have an AI use a ghost path, but I don't recall anymore how I pulled this off (I'll see if I can manage to get it to work again). When the AI uses the ghost path, it will float around doing weird rotations (remember, bytes were missing from the nodes in .GHB waypoints), not really making any progression forward or backwards.

Also, I haven't found a file storing the player's prerecorded path (appearing as a ghost in time trial races) anywhere in the .JAM archive (hopefully I didn't look for it well enough). I extracted the .JAM after I had raced a full race in time trial mode, so in the next try a second ghost racer (using your previously raced path) shows up (marked with a blue dot in the HUD map). I was hoping that I could expose this prerecorded path this way somewhere in the .JAM archive, but without success.

 

Extra facts:

  • Despite playing on time trial mode, all AI paths in the corresponding track folder are being loaded at the start of a time trial.
  • Veronica Voltage keeps shaking her head (animation sequence when losing a race) during time trial races.
  • Like 4
Link to comment
Share on other sites

  • 1 month later...
RobExplorien

I did manage to have an AI use a ghost path, but I don't recall anymore how I pulled this off (I'll see if I can manage to get it to work again). When the AI uses the ghost path, it will float around doing weird rotations (remember, bytes were missing from the nodes in .GHB waypoints), not really making any progression forward or backwards.

I mentioned it in the documentation, but I had no video proof of it. This is what happens when you use the 'GHB path' for the 'RRB path'. Copying the nodes straight from GHB to RRB would result in a syntax error, so I worked my way around it and used a different method to simulate the 'path switching'.

http://www.youtube.com/watch?v=DZIr95C2MAU&feature=youtu.be

  • Like 3
Link to comment
Share on other sites

RobExplorien

Why they're doing all these rotations?

Because an .RRB file consists of lines saying (apparently) that the vehicle has to progress forward. These lines are the bytes, an unsigned integer (like (byte)198). I think that each node represents the same distance of a path, and that the byte tells how quickly a node is to be passed. A .GHB file on the other hand has no lines with (byte)*, for these path files work with moving from coördinate to coördinate  where each node is likely to cover a specific amount of time (equal for all nodes I think).

So if we 'black out' all bytes from an .RRB file, the only thing that lasts are the subnodes like (f16)* and (f8)*, meant for the rotation of the vehicle in order to align with the track. But why their rotation is being so weird (e.g. flipping over) questions me a bit. Maybe because of the node structure I messed up. One node used to be 10 lines, I made 9 lines of it by removing the bytes. Maybe the game might read the nodes as if they're still 10 lines long, despite the fact that an actual node is now 9 lines long, causing it to read the data on a way we did not mean to.

Link to comment
Share on other sites

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.