{{indexmenu_n>10}}
====== Scripting in TR2/TR3 for PC/PSX ======
===== Overview =====
The internal gameflow, which levels come in what order, what item(s) Lara has at the beginning of each level, the filenames of the level and cut-scene files, all the visible text (e.g. “Save Game,” “Rusty Key,” etc.), and various other options are controlled by a script file called ''%%TOMBPC.DAT%%''/''%%TOMBPSX.DAT%%''. The scripts were compiled using a utility known as ''%%GAMEFLOW.EXE%%'' which was distributed by Eidos in the German release of Tomb Raider II Gold. Both TR2 and TR3 use these script files. From both games the format remained unchanged. TR1’s gameflow is hardcoded thus there is no external file controlling this resulting in loss of flexibility.
uint32_t Version; // The Script Version (Always 3 for TR2/3)
uint8_t Description[256]; // Null-terminated string describing the script copyright info etc. Not encrypted.
uint16_t GameflowSize; // Size in bytes of the game flow data, always 128 bytes
int32_t FirstOption; // What to do when the game starts
int32_t TitleReplace; // What to do when ExitToTitle is requested and "TitleDisabled" flag is set
int32_t OnDeathDemoMode; // What to do when Lara dies during the demo mode
int32_t OnDeathInGame; // What to do when Lara dies during the game
uint32_t DemoTime; // Time in game ticks (1/30th of a second) to wait before starting a demo
int32_t OnDemoInterrupt; // What to do when the demo mode is interrupted
int32_t OnDemoEnd; // What to do when the demo mode ends
uint8_t Unknown1[36]; // Filler
uint16_t NumLevels; // Number of levels in the game, including the training level, not including the title level.
uint16_t NumChapterScreens; // Chapter screens (Present in TR2, first used in TR3)
uint16_t NumTitles; // Number of title elements (TITLE.TR2 level + the legal/title pictures in *.PCX format)
uint16_t NumFMVs; // Number of FMV cutscenes PC - (*.RPL), PSX - (*.STR)
uint16_t NumCutscenes; // Number of in-game (engine-rendered) cutscenes (CUT*.TR2)
uint16_t NumDemoLevels; // Number of demo levels
uint16_t TitleSoundID; // ID of title soundtrack (see below)
uint16_t SingleLevel; // If doing only a single level, the level ID (starting at 1). -1 means disabled.
uint8_t Unknown2[32]; // Filler
uint16_t Flags; // Various flags, see below
uint8_t Unknown3[6]; // Filler
uint8_t XORKey; // Key used to encrypt/decrypt strings
uint8_t LanguageID; // Script Language ID, see below
uint16_t SecretSoundID; // ID of soundtrack to play when a secret is found (see below)
uint8_t Unknown4[4]; // Filler
// If Flags & UseXor true each character (except null-terminator) must be ^ XORKey to decrypt the string.
TPCStringArray[NumLevels] LevelStrings; // level name strings
TPCStringArray[NumChapterScreens] ChapterScreenStrings; // chapter screen strings
TPCStringArray[NumTitles] TitleStrings; // title strings
TPCStringArray[NumFMVs] FMVStrings; // FMV path strings
TPCStringArray[NumLevels] LevelPathStrings; // level path strings
TPCStringArray[NumCutscenes] CutscenePathStrings; // cutscene path strings
uint16_t SequenceOffsets[NumLevels + 1]; // Relative offset to sequence info (the +1 is because the first one is the FrontEnd sequence, for when the game starts)
uint16_t SequenceNumBytes; // Size of SequenceOffsets in bytes
uint16_t[] Sequences[NumLevels + 1]; // Sequence info see explanation below (SIZE is dependant on first opcode)
uint16_t DemoLevelIDs[NumDemoLevels];
#if PSX
PSXFMVInfo[NumFMVs];
#endif
uint16_t NumGameStrings;
TPCStringArray[NumGameStrings] GameStrings;
#if PSX
TPCStringArray[size] PSXStrings; // size is 79 for the TR2 beta, 80 for all other versions
#else
TPCStringArray[41] PCStrings;
#endif
TPCStringArray[NumLevels] PuzzleStrings[4];
#if PSX && TR2_BETA
TPCStringArray[NumLevels] SecretsStrings[4];
TPCStringArray[NumLevels] SpecialStrings[2];
#endif
TPCStringArray[NumLevels] PickupStrings[2];
TPCStringArray[NumLevels] KeyStrings[4];
==== String arrays ====
struct TPCStringArray // (variable length)
{
uint16_t Offsets[Count]; // List containing for each string an offset in the Data block (Count * 2 bytes)
uint16_t TotalSize; // Total size, in bytes (2 bytes)
uint8_t Data[TotalSize]; // Strings block, usually encrypted (XOR-ed with XORKey, see above)
}
{{anchor:accents}}
In non-English versions of TR2-3, accented characters are written using "escape" characters so that everything can be written in standard ASCII, here are the 4 escape characters:
^ Accent ^ Code ^ becomes ^
| Acute | '')e'' | ''é'' |
| Circumflex | ''(e'' | ''ê'' |
| Grave | ''$e'' | ''è'' |
| Diaeresis | ''~e'' | ''ë'' |
The following non-ASCII characters are also replaced:
^ Character ^^ becomes ^
| Eszett (German) | ''ß'' | ''='' |
There are also some exceptions (strings that were badly encoded by Core):
^ String ^ becomes ^
| Red)marrer un niveau \\ ("e" missing after parenthesis, '')e'' implied) | Redémarrer un niveau |
===== PSX FMV Info =====
struct PSXFMVInfo // 8 bytes
{
uint32_t Start; // Start frame
uint32_t End; // End frame
};
This specific info is exclusive to ''%%TOMBPSX.DAT%%''.
===== Script Flags =====
^ Bit ^ Hex ^ Name ^ Description ^
| 0 | ''%%0x01%%'' | DemoVersion | Indicates that the game is a demo distribution. |
| 1 | ''%%0x02%%'' | TitleDisabled | Indicates that the game has no Title Screen. |
| 2 | ''%%0x04%%'' | CheatModeCheckDisabled | Indicates that the game does not look for the cheat sequence keystrokes and events. |
| 3 | ''%%0x08%%'' | NoInputTimeout | Indicates that the game waits forever if there is no input (won’t enter demo mode). |
| 4 | ''%%0x10%%'' | LoadSaveDisabled | Indicates that the game does not allow save games. |
| 5 | ''%%0x20%%'' | ScreenSizingDisabled | Indicates that the game does not allow screen resizing (with the function keys). |
| 6 | ''%%0x40%%'' | LockoutOptionRing | Indicates that the user has no access to the Option Ring while playing the game. |
| 7 | ''%%0x80%%'' | DozyCheatEnabled | Indicates that the game has the DOZY cheat enabled (flag only set in the final build of TR2 on PSX, but has no effect in-game). |
| 8 | ''%%0x100%%'' | UseXor | Indicates that a cypher byte was used to encrypt the strings in the script file, and is stored in the XorKey field. |
| 9 | ''%%0x200%%'' | GymEnabled | Is Gym available on title screen. |
| 10 | ''%%0x400%%'' | SelectAnyLevel | Enables level select when New Game is selected. |
| 11 | ''%%0x800%%'' | EnableCheatCode | It apparently has no effect on the PC game. |
===== Script Language =====
* **0** — English
* **1** — French
* **2** — German
* **3** — American
* **4** — Japanese
{{:icons:tr3.png?nolink&}} TR3 only:
* **5** — Italian
* **6** — Spanish
===== Script Sequencing & Opcodes/Operands =====
Each script has “sequence information”, Opcodes and Operands are all stored as ''%%uint16_t%%''. Sequences contain a set of commands to execute where an additional value (operand) is usually passed as a parameter to the function the command needs to call.
If a level is a demo level, its level ID will be 1024 higher than a //normal// level ID.
==== Script Opcodes ====
^ ID ^ Name ^ Description ^ Operand |
| 0 | ''Picture'' | Unused. On PC, crashes if used and file missing. Otherwise, no action. Crashes under TR3 (PC). | Picture ID |
| 1 | ''ListStart'' | Define the start and the end of a list of commands which will be cut short if the user presses a key/button. | |
| 2 | ''ListEnd'' | ::: | ::: |
| 3 | ''FMV'' | Display Full Motion Video. | [[#tr2_ids|FMV ID]] |
| 4 | ''Level'' | Start a playable level. | Level ID |
| 5 | ''Cine'' | Display cut scene sequence. | [[#tr2_ids|Cutscene ID]] |
| 6 | ''Complete'' | Display level-completion statistics panel. | |
| 7 | ''Demo'' | Display demo sequence. | Demo level ID |
| 8 | ''JumpToSequence'' | Jump to another sequence. | Sequence ID |
| 9 | ''End'' | Close script sequence. | |
| 10 | ''Track'' | Play Soundtrack (it precedes opcodes of associated levels). | [[#tr2_ids|Track ID]] |
| 11 | ''Sunset'' | Gradually dim all lights in rooms with ''LightMode'' set to ''sunset'' (3). Used in Bartoli's Hideout. | |
| 12 | ''LoadPic'' | {{:icons:tr2.png?nolink&|TR2 only}}{{:icons:tr3.png?nolink&|TR3 only}}Show chapter screen on TR2 (**PSX only** ) and TR3. On TR2 PC, it's hardcoded to do nothing. | Picture ID |
| 13 | ''DeadlyWater'' | Not used anywhere in the game code. Used in Temple of Xian. Maybe not-implemented ancestor of TR3 ''Death_by_Drowning'' ? | |
| 14 | ''RemoveWeapons'' | Lara starts the level with no weapons. | |
| 15 | ''GameComplete'' | End of game, show the final statistics and start the credits sequence. | |
| 16 | ''CutAngle'' | Match the North-South orientation of the Room Editor and the North-South orientation of the 3D animated characters from a CAD application. | Horizontal rotation ($\text{angle in degrees} \cdot 65536 / 360$) |
| 17 | ''NoFloor'' | Lara dies when her feet reach the given depth. If falling, 4 to 5 extra blocks are added to Depth. | Depth ($\text{blocks} \times 1024$), relative to where Lara starts the level |
| 18 | ''StartInv'' / ''Bonus'' | Give item to lara at level-start (''StartInv'' ) or at all-secrets-found (''Bonus''). | [[#item_ids|Item ID]] |
| 19 | ''StartAnim'' | Lara starts the level with the given animation. | Animation ID |
| 20 | ''Secrets'' | If zero, the level does not account for secrets. Non-zero value means the level must be accounted for secrets. ||
| 21 | ''KillToComplete'' | Kill all enemies to finish the level. | |
| 22 | ''RemoveAmmo'' | Lara starts the level without ammunition or medi packs. | |
The correct way to parse a sequence is to first read a ''uint16_t'' opcode specifying what this command within the sequence does. In reference to the list above, certain commands MUST have an additional ''uint16_t'' read from the sequence data directly after the opcode that’s the pairing operand to this opcode. Not all opcodes have an operand so this must be done correctly. The original games execute each sequence command 1 by 1 until it reaches ''End'' (9), where it then runs the next sequence.
{{anchor:item_ids}}
==== Opcode-18 StartInv and Bonus ====
(repeat means give another)
By default, the item is given at level start (''%%StartInv%%''). Adding 1000 to the item ID means it will be given when all secrets are found (''%%Bonus%%'').
^ ID ^ Tomb Raider 2 ^ Tomb Raider 3 ^
| 0 | Pistols ||
| 1 | Shotgun ||
| 2 | Automatic pistols | Desert Eagle |
| 3 | Uzis ||
| 4 | Harpoon gun ||
| 5 | M-16 | MP5 |
| 6 | Grenade launcher | Rocket launcher |
| 7 | Pistol clip (no effect, infinite by default) | Grenade launcher |
| 8 | Shotgun-shell box (adds 2 shells) | Pistol clip (no effect, infinite by default) |
| 9 | Automatic-pistol clip (adds 2 shells) | Shotgun-shell box (adds 2 shells) |
| 10 | Uzi clip (adds 2 shells) | Desert eagle clip (adds 5 shells) |
| 11 | Harpoon bundle (adds 2 harpoons) | Uzi clip (adds 2 shells) |
| 12 | M-16 clip (add 2 shells) | Harpoon bundle (adds 2 harpoons) |
| 13 | Grenade pack (adds 1 grenade) | MP5 clip (add 2 shells) |
| 14 | Flare box (adds 1 flare) | Rocket pack (adds 1 rocket) |
| 15 | Small medipack (adds 1 pack) | Grenade pack (adds 1 grenade) |
| 16 | Big medipack (adds 1 pack) | Flare box (adds 1 flare) |
| 17 | Pickup 1 | Small medipack (adds 1 pack) |
| 18 | Pickup 2 | Big medipack (adds 1 pack) |
| 19 | Puzzle 1 | Pickup 1 |
| 20 | Puzzle 2 | Pickup 2 |
| 21 | Puzzle 3 | Puzzle 1 |
| 22 | Puzzle 4 | Puzzle 2 |
| 23 | Key 1 | Puzzle 3 |
| 24 | Key 2 | Puzzle 4 |
| 25 | Key 3 | Key 1 |
| 26 | Key 4 | Key 2 |
| 27 | / | Key 3 |
| 28 | / | Key 4 |
| 29 | / | Save crystal |
{{anchor:tr2_ids}}
==== Tomb Raider 2 Identifications ====
TR2 only information here. These lists are virtually colored blue.
=== FMV IDs ===
* 0 — LOGO (everybody’s corporate logos)
* 1 — ANCIENT (monks vs. dragon)
* 2 — MODERN (Lara drops in from helicopter)
* 3 — LANDING (Seaplane lands at rig)
* 4 — MS (Lara hitchhikes on a minisub)
* 5 — CRASH (Lara goes to Tibet and has a rough landing there)
* 6 — JEEP (Lara steals it and outruns Bartoli’s goons)
* 7 — END (Lara escaping the collapsing lair)
=== Cutscene IDs ===
* 0 — CUT1 (At the end of the Great Wall)
* 1 — CUT2 (Lara the stowaway)
* 2 — CUT3 (Bartoli vs. goon)
* 3 — CUT4 (Bartoli stabs himself)
=== Soundtrack IDs ===
* 002 -- Cutscene Gates
* 003 -- Cutscene Gates
* 004 -- Cutscene Plane
* 005 -- Cutscene Monk
* 006 -- Home block begin
* 007
* 008
* 009
* 010
* 011
* 012
* 013
* 014
* 015
* 016
* 017
* 018
* 019
* 020
* 021
* 022
* 023
* 024
* 025
* 026 -- Lara shower (Endgame)
* 027 -- Lara shower (Endgame)
* 028 -- Dragon death
* 029 -- Home - addon
* 030 -- Cutscene Bartoli stab
* 031 -- Caves ambience
* 032 -- Water ambience
* 033 -- Wind ambience
* 034 -- Pulse ambience
* 035 -- Danger 1
* 036 -- Danger 2
* 037 -- Danger 3
* 038 -- Sacred
* 039 -- Awe
* 040 -- Venice Violins
* 041 -- End level
* 042 -- Mystical
* 043 -- Revelation
* 044 -- Careful
* 045 -- Guitar TR
* 046 -- Drama
* 047 -- Secret theme
* 048 -- It's coming!
* 049 -- It's coming 2!
* 050 -- Warning!
* 051 -- Warning 2!
* 052 -- Techno TR
* 053 -- Percussion
* 054 -- Pads
* 055 -- Super-revelation
* 056 -- Hmm...
* 057 -- Long way up
* 058 -- Industrial ambience
* 059 -- Spooky ambience
* 060 -- Barkhang theme
* 061 -- Super-revelation short
* 062 -- Monk beaten
* 063 -- Home sweet home
* 064 -- Main theme
* 065 -- Dummy track
==== Tomb Raider 3 Identifications ====
=== Level IDs ===
* 0 – Lara's House (''house.TR2'')
* 1 — Jungle (''jungle.TR2'')
* 2 — Temple Ruins (''temple.TR2'')
* 3 — The River Ganges (''quadchas.TR2'')
* 4 — Caves Of Kaliya (''tonyboss.TR2'')
* 5 — Coastal Village (''shore.TR2'')
* 6 — Crash Site (''crash.TR2'')
* 7 — Madubu Gorge (''rapids.TR2'')
* 8 — Temple Of Puna (''triboss.TR2'')
* 9 — Thames Wharf (''roofs.TR2'')
* 10 — Aldwych (''sewer.TR2'')
* 11 — Lud's Gate (''tower.TR2'')
* 12 — City (''office.TR2'')
* 13 — Nevada Desert (''nevada.TR2'')
* 14 — High Security Compound (''compound.TR2'')
* 15 — Area 51 (''area51.TR2'')
* 16 — Antarctica (''antarc.TR2'')
* 17 — RX-Tech Mines (''mines.TR2'')
* 18 — Lost City Of Tinnos (''city.TR2'')
* 19 — Meteorite Cavern (''chamber.TR2'')
* 20 — All Hallows (''stpaul.TR2'')
=== FMV IDs ===
* 0 — LOGO (everybody’s corporate logos)
* 1 — INTR (“The Meteorite”)
* 2 — SAIL (Lara meets Willard, after the India levels)
* 3 — CRSH (Plane crash, before the Antartica levels)
* 4 — ENDGAME
=== Cutscene IDs ===
* 0 — CUT6 (Lara at Tony's camp)
* 1 — CUT9 (Lara meets Tony again)
* 2 — CUT1 (Lara Meets Amputated Mercenary)
* 3 — CUT4 (Lara confronts tribesman about artifact)
* 4 — CUT2 (Saved by the Bell)
* 5 — CUT5 (Lara meets the leader of the Damned)
* 6 — CUT11 (Lara meets Sophia Leigh)
* 7 — CUT7 (Lara Drives Over Fence)
* 8 — CUT8 (Lara the stowaway in a delivery truck)
* 9 — CUT3 (Lara gets the artifacts to Willard)
* 10 — CUT12 (Lara watches Willard transform)
===== Other Script Commands =====
''FirstOption'', ''TitleReplace'', ''OnDeathDemoMode'', ''OnDeathInGame'', ''OnDemoInterrupt'' and ''OnDemoEnd'' can also be setup to perform specific actions. For example, ''OnDeathInGame'' will be set to "0x500" which loads the title screen when Lara dies in-game.
^Name^Code^Operand^Description|
|**Level** |''0x00000000'' |Level|Load specified level (0 means Lara's Home (or do nothing, if in a demo), 1 means first level (//Great Wall// or //Jungle//), 2 means second level)|
|**SavedGame**|''0x00000100'' |Number between in [0, 15]|Load specified savegame file (load file ''savegame.N'' where N is the operand)|
|**Cutscene**|''0x00000200'' |Cutscene ID|Play specified cutscene|
|**FMV**|''0x00000300'' |FMV ID|Play specified FMV|
|**Demo** |''0x00000400'' |None|Load a **random** demo level|
|**ExitToTitle** |''0x00000500'' |:::|Exit to Title Screen (or do action specified in ''TitleReplace'' if ''TitleDisabled'' flag is set)|
|**ExitGame** |''0x00000700'' |:::|Exit the game|
| (anything else) |||Exit the game|
Commands with operand are used like this: if you want to load the 2nd level, then you are going to do ''0x000'' (//Level//) + 2 which gives ''0x003''.
In the original TOMBPC.DAT/TOMBPSX.DAT files, the value ''0xFFFFFFFF'' is often used by Core in fields to denotate that //it should not happen//. For example, in the //standard// (not demo)
games' scripts, the ''TitleReplace'' field contains the value ''0xFFFFFFFF'' (which, as mentioned before, will crash-exit the game quietly) because this field should never be used, as the ''TitleDisabled'' flag should never be set in standard games.