Skip to content

Latest commit

 

History

History
1549 lines (1497 loc) · 37.5 KB

GAMEFLOW.md

File metadata and controls

1549 lines (1497 loc) · 37.5 KB

Game flow specification

The game flow 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:

Global properties

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",
"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,
"enforced_config": {
    "enable_save_crystals": 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.
  • The default hardcoded value in TR1 is 12.
  • The default (disabled) value in TombATI is 72.
draw_distance_max Double Yes The distance (in tiles) at which objects and the world are clipped away.
  • The default hardcoded value in TR1 is 20.
  • The default (disabled) value in TombATI is 80.
enable_killer_pushblocks Boolean No If enabled, when a pushblock falls from the air and lands on Lara, it will kill her outright. Otherwise, Lara will clip on top of the block and survive.
enable_tr2_item_drops Boolean No Forces enemies who are placed in the same position as pickup items to carry those items and drop them when killed, similar to TR2+. See Item drops for full details.
enforced_config String-to-object map No This allows any regular game config setting to be overriden. See User configuration for full details.
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.
  • [0.6, 0.7, 1.0] is the original DOS version filter.
  • [0.45, 1.0, 1.0] is the default TombATI filter.

Level properties

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
    },
    "examine": {
        "key1": "This shows when the player examines key1 in the inventory.",
        "puzzle2": "You can use \n to make new lines and \f to make new pages.",
        // 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.
examine String-to-string map No Allows longer text descriptions to be defined for key and puzzle items, over and above the names defined in strings (see below). Players can examine items in the inventory when this text has been defined. Use \n in the text to create new lines; you can also use \f to force a page break. Long text will be automatically wrapped and paginated as necessary. If an empty string is defined, the UI will not be shown and the inventory item simply focussed instead.
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 No Key and puzzle item names. The possible types are as follows. If this map is missing, or is missing an item's name, the game will use a suitable default value.
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.
unobtainable_secrets Integer No A count of secrets that will be excluded from secret statistics. Useful for level demos.
water_color Float array No Can be customized per level. See above for details.

Sequences

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
loading_screen picture_path String Displays the specified picture for the given number of seconds. Functions identically to display_picture except these pictures can be enabled/disabled by the user with the loading screen option in the config tool.
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:
  • If they are specified, they must appear before the start_game sequence.
  • remove_guns does not remove the ammo for those guns, and equally remove_ammo does not remove the guns. Each works independently of the other.
  • These sequences can also work together with give_item - so, item removal is performed first, followed by addition.
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_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.

Bonus levels

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": "level_stats", "level_id": 4},
        {"type": "exit_to_level", "level_id": 5},
    ],
    "strings": {},
},

Item drops

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 can be defined in two ways. If enable_tr2_item_drops is true, then custom level builders can add items directly to the level file, setting their position to be the same as the enemies who should drop them.

For the original levels, enable_tr2_item_drops is false. Item drops are instead 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.

Enemy validity

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

Item validity

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

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.
*_skybox.bin Injects a predefined skybox model into specific levels.
*_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. The Lost Valley file comprises a head mesh edit for object 5 only.
braid_cut1.bin
braid_cut2_cut4.bin
braid_valley.bin
cistern_plants.bin This disables the animation on sprite ID 193 in The Cistern and Tomb of Tihocan.
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, state changes and commands for Lara, such as responsive jumping, jump-twist, somersault, underwater roll, and wading.
explosion.bin Injects explosion sprites for certain console commands.
mines_pushblocks.bin Injects animation command data for pushblock types 2, 3 and 4 to restore the missing scraping SFX when pulling these blocks.
pickup_aid.bin Injects a sprite sequence similar to the Midas twinkle effect, which is used when the option for pickup aids is enabled. Custom levels should define a suitable sprite sequence in slot 185.
photo.bin Injects camera shutter sound effect for the photo mode, needed only for the cutscene levels.
purple_crystal.bin Injects a replacement savegame crystal model to match the PS1 style.
scion_collision.bin Increases the collision radius on the (targetable) Scion such that it can be shot with the shotgun.

User Configuration

TRX ships with a configuration tool to allow users to adjust game settings to their taste. This tool writes to cfg\TR1X.json5. As a level builder, you may however wish to enforce some settings to match how your level is designed.

As an example, let's say you do not wish to add save crystals to your level, and as a result you wish to prevent the player from enabling that option in the config tool. To achieve this, open cfg\TR1X_gameflow.json5 in a suitable text editor and add the following.

"enforced_config" : {
  "enable_save_crystals" : false,
}

This means that the game will enforce your chosen value for this particular config setting. If the player launches the config tool, the option to toggle save crystals will be greyed out.

You can add as many settings within the enforced_config section as needed. Refer to the key names within cfg\TR1X.json5 for reference.

Note that you do not need to ship a full cfg\TR1X.json5 with your level, and indeed it is not recommended to do so if you have, for example, your own custom keyboard or controller layouts defined.

If you do not have any requirement to enforce settings, you can omit the enforced_config section from your gameflow.