From 480845f884d6323bf7419e8a2eecb33011d33c8f Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Tue, 29 Aug 2023 16:49:06 +0100 Subject: [PATCH] inject: restore City of Khamoon mummy (#951) Added an option to restore the PS mummy in City of Khamoon room 25. This required moving the stats room caching call to occur after injection, otherwise inserted triggers aren't detected and hence the kill count would be wrong. Resolves #886. --- CHANGELOG.md | 1 + README.md | 3 +- bin/cfg/Tomb1Main_gameflow.json5 | 1 + bin/data/khamoon_mummy.bin | Bin 0 -> 964 bytes src/config.c | 2 ++ src/config.h | 1 + src/game/inject.c | 34 ++++++++++++++++++ src/game/level.c | 4 ++- .../Resources/Lang/en.json | 4 +++ .../Resources/Lang/fr.json | 4 +++ .../Resources/specification.json | 5 +++ 11 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 bin/data/khamoon_mummy.bin diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a203c58a..095c7dcf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - added the current music track and timestamp to the savegame so they now persist on load (#419) - added the triggered music tracks to the savegame so one shot tracks don't replay on load (#371) - added forward/backward input detection in line with TR2+ for jump-twists (#931) +- added an option to restore the mummy in City of Khamoon room 25, similar to the PS1 version (#886) - changed the installer to always overwrite all essential files such as the gameflow and injections (#904) - changed the data injection system to warn when it detects invalid or missing files, rather than preventing levels from loading (#918) - changed the gameflow to detect and skip over legacy sequence types, rather than preventing the game from starting (#882) diff --git a/README.md b/README.md index 84991fce3..0e97663f0 100644 --- a/README.md +++ b/README.md @@ -256,6 +256,7 @@ Not all options are turned on by default. Refer to `Tomb1Main_ConfigTool.exe` fo - added ability to restart the adventure from any level when loading a game - added the "Story so far..." option in the select level menu to view cutscenes and FMVs - added graphics effects, lava emitters, flame emitters, and waterfalls to the savegame so they now persist on load +- added an option to restore the mummy in City of Khamoon room 25, similar to the PS version - fixed keys and items not working when drawing guns immediately after using them - fixed counting the secret in The Great Pyramid - fixed running out of ammo forcing Lara to equip pistols even if she doesn't carry them @@ -476,7 +477,7 @@ Note: this section may be subject to change. - [ ] Work on data injection and other features - [x] Add Lara's braid to each level - [x] Fix texture/face issues - - [ ] Fix floor data issues + - [x] Fix floor data issues - [ ] ... ## License diff --git a/bin/cfg/Tomb1Main_gameflow.json5 b/bin/cfg/Tomb1Main_gameflow.json5 index b73648b81..b4afbcd8c 100644 --- a/bin/cfg/Tomb1Main_gameflow.json5 +++ b/bin/cfg/Tomb1Main_gameflow.json5 @@ -319,6 +319,7 @@ "music": 59, "injections": [ "data/khamoon_fd.bin", + "data/khamoon_mummy.bin", "data/khamoon_textures.bin", ], "sequence": [ diff --git a/bin/data/khamoon_mummy.bin b/bin/data/khamoon_mummy.bin new file mode 100644 index 0000000000000000000000000000000000000000..87e71747b0b451bf196a4a31c5e71f6b081654c4 GIT binary patch literal 964 zcmWGB^z~w4U|`??Vrl_qph0ZZGHleG(GVC$As`9%3nP#O23Z{904x3rEdT%j literal 0 HcmV?d00001 diff --git a/src/config.c b/src/config.c index 42977f1a2..d1ed4de05 100644 --- a/src/config.c +++ b/src/config.c @@ -234,6 +234,7 @@ bool Config_ReadFromJSON(const char *cfg_data) READ_BOOL(load_current_music, true); READ_BOOL(load_music_triggers, true); READ_BOOL(fix_item_rots, true); + READ_BOOL(restore_ps1_enemies, false); CLAMP(g_Config.start_lara_hitpoints, 1, LARA_HITPOINTS); CLAMP(g_Config.fov_value, 30, 255); @@ -421,6 +422,7 @@ bool Config_Write(void) WRITE_BOOL(load_current_music); WRITE_BOOL(load_music_triggers); WRITE_BOOL(fix_item_rots); + WRITE_BOOL(restore_ps1_enemies); // User settings WRITE_BOOL(rendering.enable_bilinear_filter); diff --git a/src/config.h b/src/config.h index 92b2ea60c..8224bf2f5 100644 --- a/src/config.h +++ b/src/config.h @@ -114,6 +114,7 @@ typedef struct { bool load_current_music; bool load_music_triggers; bool fix_item_rots; + bool restore_ps1_enemies; struct { int32_t layout; diff --git a/src/game/inject.c b/src/game/inject.c index 6baf1cd7d..304a3be9d 100644 --- a/src/game/inject.c +++ b/src/game/inject.c @@ -34,6 +34,7 @@ typedef enum INJECTION_TYPE { INJ_LARA_ANIMS = 5, INJ_LARA_JUMPS = 6, INJ_ITEM_ROTATION = 7, + INJ_PS1_ENEMY = 8, } INJECTION_TYPE; typedef struct INJECTION { @@ -81,6 +82,7 @@ typedef enum FLOOR_EDIT_TYPE { FET_MUSIC_ONESHOT = 1, FET_FD_INSERT = 2, FET_ROOM_SHIFT = 3, + FET_TRIGGER_ITEM = 4, } FLOOR_EDIT_TYPE; typedef enum ROOM_MESH_EDIT_TYPE { @@ -129,6 +131,7 @@ static void Inject_SetMusicOneShot(FLOOR_INFO *floor); static void Inject_InsertFloorData( INJECTION *injection, FLOOR_INFO *floor, LEVEL_INFO *level_info); static void Inject_RoomShift(INJECTION *injection, int16_t room_num); +static void Inject_TriggeredItem(INJECTION *injection, LEVEL_INFO *level_info); static void Inject_RoomMeshEdits(INJECTION *injection); static void Inject_TextureRoomFace(INJECTION *injection); @@ -215,6 +218,9 @@ static void Inject_LoadFromFile(INJECTION *injection, const char *filename) case INJ_ITEM_ROTATION: injection->relevant = g_Config.fix_item_rots; break; + case INJ_PS1_ENEMY: + injection->relevant = g_Config.restore_ps1_enemies; + break; default: LOG_WARNING("%s is of unknown type %d", filename, injection->type); break; @@ -1009,6 +1015,9 @@ static void Inject_FloorDataEdits(INJECTION *injection, LEVEL_INFO *level_info) case FET_ROOM_SHIFT: Inject_RoomShift(injection, room); break; + case FET_TRIGGER_ITEM: + Inject_TriggeredItem(injection, level_info); + break; default: LOG_WARNING("Unknown floor data edit type: %d", edit_type); break; @@ -1227,6 +1236,31 @@ static void Inject_RoomShift(INJECTION *injection, int16_t room_num) } } +static void Inject_TriggeredItem(INJECTION *injection, LEVEL_INFO *level_info) +{ + MYFILE *fp = injection->fp; + + if (g_LevelItemCount == MAX_ITEMS) { + File_Skip( + fp, sizeof(int16_t) * 4 + sizeof(int32_t) * 3 + sizeof(uint16_t)); + LOG_WARNING("Cannot add more than %d items", MAX_ITEMS); + return; + } + + ITEM_INFO *item = &g_Items[g_LevelItemCount]; + File_Read(&item->object_number, sizeof(int16_t), 1, fp); + File_Read(&item->room_number, sizeof(int16_t), 1, fp); + File_Read(&item->pos.x, sizeof(int32_t), 1, fp); + File_Read(&item->pos.y, sizeof(int32_t), 1, fp); + File_Read(&item->pos.z, sizeof(int32_t), 1, fp); + File_Read(&item->pos.y_rot, sizeof(int16_t), 1, fp); + File_Read(&item->shade, sizeof(int16_t), 1, fp); + File_Read(&item->flags, sizeof(uint16_t), 1, fp); + + level_info->item_count++; + g_LevelItemCount++; +} + uint32_t Inject_GetExtraRoomMeshSize(int32_t room_index) { uint32_t size = 0; diff --git a/src/game/level.c b/src/game/level.c index 9307310c0..e4003760c 100644 --- a/src/game/level.c +++ b/src/game/level.c @@ -83,7 +83,6 @@ static bool Level_LoadFromFile(const char *filename, int32_t level_num) if (!Level_LoadRooms(fp)) { return false; } - Stats_ObserveRoomsLoad(); if (!Level_LoadObjects(fp)) { return false; @@ -664,6 +663,9 @@ static void Level_CompleteSetup(void) { Inject_AllInjections(&m_LevelInfo); + // Must be called post-injection to allow for floor data changes. + Stats_ObserveRoomsLoad(); + // Must be called after all g_Anims, g_Meshes etc initialised. Setup_AllObjects(); diff --git a/tools/config/Tomb1Main_ConfigTool/Resources/Lang/en.json b/tools/config/Tomb1Main_ConfigTool/Resources/Lang/en.json index 19730e548..289b23fbf 100644 --- a/tools/config/Tomb1Main_ConfigTool/Resources/Lang/en.json +++ b/tools/config/Tomb1Main_ConfigTool/Resources/Lang/en.json @@ -239,6 +239,10 @@ "Title": "Change Pierre spawn behavior", "Description": "Makes a freshly triggered (runaway) Pierre replace an already existing (runaway) Pierre." }, + "restore_ps1_enemies": { + "Title": "Restore PS1 enemies", + "Description": "Adds the mummy that appears in the PlayStation version of City of Khamoon, room 25.\nChanging this option will require restarting the level." + }, "enable_timer_in_inventory": { "Title": "Timer counts in inventory", "Description": "Makes the in-game timer work even while the game is showing the inventory." diff --git a/tools/config/Tomb1Main_ConfigTool/Resources/Lang/fr.json b/tools/config/Tomb1Main_ConfigTool/Resources/Lang/fr.json index 59ed28c6f..e0d63b5b1 100644 --- a/tools/config/Tomb1Main_ConfigTool/Resources/Lang/fr.json +++ b/tools/config/Tomb1Main_ConfigTool/Resources/Lang/fr.json @@ -239,6 +239,10 @@ "Title": "Modifier le comportement d'apparition de Pierre", "Description": "Fait en sorte que Pierre (en fuite) remplace bien un autre Pierre (en fuite) déjà existant." }, + "restore_ps1_enemies": { + "Title": "Restaure les ennemis PlayStation", + "Description": "Remet la momie absente sur la version PC mais présente dans la version PlayStation (room 25).\nAttention, changer cette option sur une partie en cours nécessite de redémarrer le niveau, pour être prise en charge." + }, "enable_timer_in_inventory": { "Title": "Compteur de temps de jeu dans l'inventaire", "Description": "Fait fonctionner le conteur du jeu même en étant dans les menus de l'inventaire." diff --git a/tools/config/Tomb1Main_ConfigTool/Resources/specification.json b/tools/config/Tomb1Main_ConfigTool/Resources/specification.json index 6b693572b..30297e103 100644 --- a/tools/config/Tomb1Main_ConfigTool/Resources/specification.json +++ b/tools/config/Tomb1Main_ConfigTool/Resources/specification.json @@ -266,6 +266,11 @@ "DataType": "Bool", "DefaultValue": true }, + { + "Field": "restore_ps1_enemies", + "DataType": "Bool", + "DefaultValue": false + }, { "Field": "enable_timer_in_inventory", "DataType": "Bool",