The gameflow in TR1X is fully configurable and contributes to removing several original hard-coded aspects of the game. This document describes each element available to edit.
Jump to:
The following properties are in the root of the gameflow document and control various pieces of global behaviour.
Show snippet
"main_menu_picture": "data/titleh.png",
"savegame_fmt_legacy": "saveati.%d",
"savegame_fmt_bson": "save_tr1_%02d.dat",
"force_game_modes": null,
"force_save_crystals": null,
"demo_delay": 16,
"water_color": [0.45, 1.0, 1.0],
"draw_distance_fade": 22.0,
"draw_distance_max": 30.0,
"injections": [
"data/global_injection1.bin",
"data/global_injection2.bin",
// etc
],
"convert_dropped_guns": false,
"levels": [
{
"title": "Caves",
// etc
}
],
"strings": {
"HEADING_INVENTORY": "INVENTORY",
"HEADING_GAME_OVER": "GAME OVER",
// etc
},
Property | Type | Required | Description |
---|---|---|---|
convert_dropped_guns
|
Boolean | No | Forces guns dropped by enemies to be converted to the equivalent ammo if Lara already has the gun. See Item drops for full details. |
demo_delay
|
Double | Yes | The number of seconds to pass in the main menu before playing the demo. |
draw_distance_fade
|
Double | Yes |
The distance (in tiles) at which objects and the world start to fade into
blackness.
|
draw_distance_max
|
Double | Yes |
The distance (in tiles) at which objects and the world are clipped away.
|
force_game_modes
|
Optional Boolean | No |
Forces game mode selection to be enabled if true or disabled
if false , so the user can't select NG+ modes until a
playthrough is completed. Overrides the config option
enable_game_modes . Has no action if null .
|
force_save_crystals
|
Optional Boolean | No |
Forces save crystals to be enabled if true or disabled if
false . Overrides the config option
enable_save_crystals . Has no action if null .
|
injections
|
String array | No |
Global data injection file paths. Individual levels will inherit these
unless inherit_injections is set to false on
those levels. See Injections for full details.
|
levels
|
Object array | Yes | This is where the individual level details are defined - see Level properties for full details. |
main_menu_picture
|
String | Yes | Path to the main menu background image. |
savegame_fmt_bson
|
String | Yes | Path to the savegame file. |
savegame_fmt_legacy
|
|||
strings
|
String-to-string map | Yes | All language used in the game is defined here. Edit the right-hand values only. |
water_color
|
Float array | No |
Water color (R, G, B). 1.0 means pass-through, 0.0 means no value at all.
|
The levels
section of the document defines how the game plays out. This is an
array of objects and can be defined in any order. The flow is controlled using
the correct sequencing within each level itself.
Following are each of the properties available within a level.
Show snippet
{
"title": "Example Level",
"file": "data/example.phd",
"type": "normal",
"music": 57,
"lara_type": 0,
"water_color": [0.7, 0.5, 0.85],
"draw_distance_fade": 34.0,
"draw_distance_max": 50.0,
"demo": true,
"unobtainable_pickups": 1,
"unobtainable_kills": 1,
"inherit_injections": false,
"injections": [
"data/level_injection1.bin",
"data/level_injection2.bin",
],
"item_drops": [
{"enemy_num": 17, "object_ids": [86]},
{"enemy_num": 50, "object_ids": [87]},
// etc
],
"sequence": [
{"type": "play_fmv", "fmv_path": "fmv/snow.avi"},
{"type": "start_game"},
// etc
],
"strings": {
"key1": "Silver Key",
"puzzle2": "Machine Cog",
// etc
},
},
Property | Type | Required | Description | |
---|---|---|---|---|
demo
|
Boolean | No | Flag to indicate that the level has available demo data to play out from the title screen. | |
draw_distance_fade
|
Double | No | Can be customized per level. See above for details. | |
draw_distance_max
|
Double | No | Can be customized per level. See above for details. | |
file
|
String | Yes | The path to the level's data file. | |
inherit_injections
|
Boolean | No | A flag to indicate whether or not the level should use the globally defined injections. See Injections for full details. | |
injections
|
String array | No | Injection file paths. See Injections for full details. | |
item_drops
|
Object array | No | Instructions to allocate items to enemies who will drop those items when killed. See Item drops for full details. | |
lara_type
|
Integer | No | Used only in cutscene levels to link the braid (if enabled) to the relevant cutscene actor object ID. | |
music
|
Integer | Yes | The ambient music track ID. | |
sequence
|
Object array | Yes | Instructions to define how a level plays out. See Sequences for full details. | |
strings
|
String-to-string map | Yes | Key and puzzle item names. The possible types are as follows. An empty map is permitted. | |
String ID | Description | |||
key1
|
Describes pickup object ID 129 in the inventory top-ring. | |||
key2
|
Describes pickup object ID 130 in the inventory top-ring. | |||
key3
|
Describes pickup object ID 131 in the inventory top-ring. | |||
key4
|
Describes pickup object ID 132 in the inventory top-ring. | |||
pickup1
|
Describes pickup object ID 141 in the inventory top-ring. | |||
pickup2
|
Describes pickup object ID 142 in the inventory top-ring. | |||
puzzle1
|
Describes pickup object ID 110 in the inventory top-ring. | |||
puzzle2
|
Describes pickup object ID 111 in the inventory top-ring. | |||
puzzle3
|
Describes pickup object ID 112 in the inventory top-ring. | |||
puzzle4
|
Describes pickup object ID 113 in the inventory top-ring. | |||
title
|
String | Yes | The title of the level. | |
type
|
String | Yes | The level type, which must be one of the following values. | |
Type | Description | |||
bonus
|
Only playable when all secrets are collected. See Bonus levels for full details. | |||
current
|
One level of this type is necessary to read TombATI's save files. OG has a
special level called LV_CURRENT to handle save/load logic.
TR1X does away with this hack. However, the existing save games expect the
level count to match, otherwise the game will crash.
|
|||
cutscene
|
A cutscene level. | |||
gym
|
At most one of these can be defined. Accessed from the photo option (object ID 73) on the title screen. If omitted, the photo option is not displayed. | |||
normal
|
A standard level. | |||
title
|
The main menu level. One - and only one - of these must be defined. | |||
unobtainable_kills
|
Integer | No | A count of enemies that will be excluded from kill statistics. | |
unobtainable_pickups
|
Integer | No | A count of items that will be excluded from pickup statistics. | |
water_color
|
Float array | No | Can be customized per level. See above for details. |
The following describes each available gameflow sequence type and the required parameters for each. Note that while this table is displayed in alphabetical order, care must be taken to define sequences in the correct order. Refer to the default gameflow for examples.
Sequence | Parameter | Type | Description |
---|---|---|---|
display_picture
|
picture_path
|
String | Displays the specified picture for the given number of seconds. |
display_time
|
Double | ||
exit_to_cine
|
level_id
|
Integer | Exits to the specified cinematic level. |
exit_to_level
|
level_id
|
Integer | Exits to the specified level. |
exit_to_title
|
N/A | Returns to the title level. | |
flip_map
|
N/A | Triggers the flip map. | |
give_item
|
object_id
|
Integer |
Adds the specified item and quantity to Lara's inventory. If used, this
must appear after the start_game sequence.
|
quantity
|
Integer | ||
level_stats
|
level_id
|
Integer | Displays the end of level statistics for the given level number. |
loop_cine
|
N/A | Plays the cinematic loop. | |
loop_game
|
N/A | Plays the main game loop. | |
mesh_swap
|
object1_id
|
Integer | Swaps the given mesh ID between the given objects. |
object2_id
|
Integer | ||
mesh_id
|
Integer | ||
play_fmv
|
fmv_path
|
String | Plays the specified FMV file. |
play_synced_audio
|
audio_id
|
Integer | Plays the given audio track. |
remove_ammo
|
N/A |
Any combination of these four sequences can be used to modify Lara's
inventory at the start of a level. There are a few simple points to note:
|
|
remove_guns
|
N/A | ||
remove_medipacks
|
N/A | ||
remove_scions
|
N/A | ||
set_cam_angle
|
value
|
Integer | Sets the camera's angle. |
set_cam_x
|
value
|
Integer | Sets the camera's X position. |
set_cam_y
|
value
|
Integer | Sets the camera's Y position. |
set_cam_z
|
value
|
Integer | Sets the camera's Z position. |
setup_bacon_lara
|
anchor_room
|
Integer | Sets the room number in which Bacon Lara will be anchored to enable correct mirroring behaviour with Lara. |
start_cine
|
N/A | Starts a new cinematic level. | |
start_game
|
N/A | Starts a new level. | |
stop_cine
|
N/A | Ends a cinematic level. | |
stop_game
|
N/A | Ends a level. | |
total_stats
|
picture_path
|
String | Displays the end of game statistics with the given picture file shown as a background. |
The gameflow supports bonus levels, which are unlocked only when the player collects all secrets in the game's normal levels. These bonus levels behave just like normal levels, so you can include FMVs, cutscenes in-between and so on.
Statistics are maintained separately, so normal end-game statistics are shown once, and then separate bonus level statistics are shown on completion of those levels.
Following is a sample level configuration with three normal levels and two bonus levels. After the end-game credits are played following level 3, if the player has collected all secrets, they will then be taken to level 4. Otherwise, the game will exit to title.
Show example setup
{
// gym level definition
},
{
"title": "Level 1",
"file": "data/level1.phd",
"type": "normal",
"music": 57,
"sequence": [
{"type": "start_game"},
{"type": "loop_game"},
{"type": "stop_game"},
{"type": "level_stats", "level_id": 1},
{"type": "exit_to_level", "level_id": 2},
],
"strings": {},
},
{
"title": "Level 2",
"file": "data/level2.phd",
"type": "normal",
"music": 57,
"sequence": [
{"type": "start_game"},
{"type": "loop_game"},
{"type": "stop_game"},
{"type": "level_stats", "level_id": 2},
{"type": "exit_to_level", "level_id": 3},
],
"strings": {},
},
{
"title": "Level 3",
"file": "data/level3.phd",
"type": "normal",
"music": 57,
"sequence": [
{"type": "start_game"},
{"type": "loop_game"},
{"type": "stop_game"},
{"type": "level_stats", "level_id": 3},
{"type": "play_synced_audio", "audio_id": 19},
{"type": "display_picture", "picture_path": "data/end.pcx", "display_time": 7.5},
{"type": "display_picture", "picture_path": "data/cred1.pcx", "display_time": 7.5},
{"type": "display_picture", "picture_path": "data/cred2.pcx", "display_time": 7.5},
{"type": "display_picture", "picture_path": "data/cred3.pcx", "display_time": 7.5},
{"type": "total_stats", "picture_path": "data/install.pcx"},
{"type": "exit_to_level", "level_id": 4},
],
"strings": {},
},
{
"title": "Level 4",
"file": "data/bonus1.phd",
"type": "bonus",
"music": 57,
"sequence": [
{"type": "play_fmv", "fmv_path": "fmv/snow.avi"},
{"type": "start_game"},
{"type": "loop_game"},
{"type": "stop_game"},
{"type": "exit_to_cine", "level_id": 6},
],
"strings": {},
},
{
"title": "Level 5",
"file": "data/bonus2.phd",
"type": "bonus",
"music": 57,
"sequence": [
{"type": "start_game"},
{"type": "loop_game"},
{"type": "stop_game"},
{"type": "level_stats", "level_id": 5},
{"type": "play_synced_audio", "audio_id": 14},
{"type": "total_stats", "picture_path": "data/install.pcx"},
{"type": "exit_to_title"},
],
"strings": {},
},
{
"title": "Bonus Cut Scene",
"file": "data/bonuscut1.phd",
"type": "cutscene",
"music": 0,
"sequence": [
{"type": "start_cine"},
{"type": "set_cam_x", "value": 36668},
{"type": "set_cam_z", "value": 63180},
{"type": "set_cam_angle", "value": -23312},
{"type": "play_synced_audio", "audio_id": 23},
{"type": "loop_cine"},
{"type": "stop_cine"},
{"type": "level_stats", "level_id": 4},
{"type": "exit_to_level", "level_id": 5},
],
"strings": {},
},
In the original game, items dropped by enemies were hardcoded such that only specific enemies could drop, and the items and quantities that they dropped were immutable. This is no longer the case, with the gameflow providing a mechanism to allow the majority of enemy types to carry and drop items. Note that this also means by default that the original enemies who did drop items will not do so unless the gameflow has been configured as such.
Item drops are defined in the item_drops
section of a level's definition by
creating objects with the following parameter structure. You can define at most
one entry per enemy, but that definition can have as many drop items as
necessary (within the engine's overall item limit).
Show example setup
{
"title": "Example Level",
"file": "data/example.phd",
"type": "normal",
"music": 57,
"item_drops": [
{"enemy_num": 17, "object_ids": [86]},
{"enemy_num": 50, "object_ids": [87]},
{"enemy_num": 12, "object_ids": [93, 93]},
{"enemy_num": 47, "object_ids": [111]},
],
"sequence": [
{"type": "start_game"},
{"type": "loop_game"},
{"type": "stop_game"},
{"type": "level_stats", "level_id": 1},
{"type": "exit_to_level", "level_id": 2},
],
"strings": {
"key1": "Silver Key",
"puzzle2": "Machine Cog",
},
},
This translates as follows.
- Enemy #17 will drop the magnums
- Enemy #50 will drop the uzis
- Enemy #12 will drop two small medipacks
- Enemy #47 will drop puzzle 2
Parameter | Type | Description |
---|---|---|
enemy_num
|
Integer | The index of the enemy in the level's item list. |
object_ids
|
Integer array | A list of item types to drop. These items will spawn dynamically and do not need to be added to the level file. Duplicate IDs are permitted in the same array. |
You can also toggle convert_dropped_guns
in
global properties. When true
, if an enemy drops a gun
that Lara already has, it will be converted to the equivalent ammo. When
false
, the gun will always be dropped.
All enemy types are permitted to carry and drop items. This includes regular enemies as well as Atlantean pods (objects 163, 181) and centaur statues (object 161). For pods, the items will be allocated to the creature within (obviously empty pods are excluded).
Items dropped by flying or swimming creatures will fall to the ground.
For clarity, following is a list of all TR1 enemy type IDs, which you can reference when building your gameflow. The gameflow will ignore drops for non-enemy type objects, and a suitable warning message will be produced in the log file.
Object ID | Name |
---|---|
7 | Wolf |
8 | Bear |
9 | Bat |
10 | Crocodile |
11 | Alligator |
12 | Lion |
13 | Lioness |
14 | Puma |
15 | Ape |
16 | Rat |
17 | Vole |
18 | T-rex |
19 | Raptor |
20 | Flying mutant |
21 | Grounded mutant (shooter) |
22 | Grounded mutant (non-shooter) |
23 | Centaur |
24 | Mummy (Tomb of Qualopec) |
27 | Larson |
28 | Pierre (not runaway) |
30 | Skate kid |
31 | Cowboy |
32 | Kold |
33 | Natla (items drop after second phase) |
34 | Torso |
The following object types are capable of being carried and dropped. The gameflow will ignore anything that is not in this list, and a suitable warning message will be produced in the log file.
Object ID | Name |
---|---|
84 | Pistols |
85 | Shotgun |
86 | Magnums |
87 | Uzis |
89 | Shotgun ammo |
90 | Magnum ammo |
91 | Uzi ammo |
93 | Small medipack |
94 | Large medipack |
110 | Puzzle1 |
111 | Puzzle2 |
112 | Puzzle3 |
113 | Puzzle4 |
126 | Lead bar |
129 | Key1 |
130 | Key2 |
131 | Key3 |
132 | Key4 |
141 | Pickup1 |
142 | Pickup2 |
144 | Scion (à la Pierre) |
Injections defined in the global gameflow will by default be applied to each level. Individual levels can also specify their own specific injections to include. In that case, the global injections are merged with the level's when the level loads.
Individual levels can set inherit_injections
to false
and as a result they
will not use the global injection files. If those levels have their own
injections defined, only those will be used. And of course, if they have none
defined, nothing will be injected.
Disclaimer: Custom levels should not use the injections mechanism and instead should provide data that is already correct and consistent. Reports of bugs about injection files not working for custom levels will not be considered. Note however that the injections that relate to Lara can work in custom levels that do not modify Lara's default mesh structure or animations. These injection files are based on the original Lara model.
The gameflow will ignore referenced injection files that do not exist, but it is best practice to remove the references to maintain a clean gameflow file.
Following is a summary of what each of the default injection files that are provided with the game achieves.
Injection file | Purpose |
---|---|
*_fd.bin
|
Injects fixes for floor data issues in the original levels. Refer to the README for a full list of fixes. |
*_itemrots.bin
|
Injects rotations on pickup items so they make more visual sense when using the 3D pickups option. |
*_textures.bin
|
Injects fixes for texture issues in the original levels, such as gaps in the walls or wrongly colored models. Refer to the README for a full list of fixes. |
backpack.bin
|
Injects mesh edits for Lara's backback, such that it becomes shallower. This is only applied when the braid is enabled, to avoid the braid merging with the backpack. The different files are needed to address mesh structure differences between cutscene and normal levels. |
backpack_cut.bin
|
|
braid.bin
|
Injects a braid when the option for it is enabled. This also edits Lara's head meshes (object 0 and object 4) to make the braid fit better. A golden braid is also provided for the Midas Touch animation. Again, different files are needed to cater for mesh differences between cutscene and normal levels. |
braid_cut1.bin
|
|
braid_cut2_cut4.bin
|
|
khamoon_mummy.bin
|
Injects the mummy in room 25 of City of Khamoon, which is present in the PS1 version but not the PC. |
lara_animations.bin
|
Injects several animations for Lara, such as the jump-twist, somersault, and underwater roll. |
lara_jumping.bin
|
Injects animation change/dispatch edits for Lara to cater for responsive jumping, if that option is enabled. |