Skip to content

Commit

Permalink
inject: restore City of Khamoon mummy (#951)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lahm86 authored Aug 29, 2023
1 parent d958807 commit 480845f
Show file tree
Hide file tree
Showing 11 changed files with 57 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions bin/cfg/Tomb1Main_gameflow.json5
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@
"music": 59,
"injections": [
"data/khamoon_fd.bin",
"data/khamoon_mummy.bin",
"data/khamoon_textures.bin",
],
"sequence": [
Expand Down
Binary file added bin/data/khamoon_mummy.bin
Binary file not shown.
2 changes: 2 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
34 changes: 34 additions & 0 deletions src/game/inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion src/game/level.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();

Expand Down
4 changes: 4 additions & 0 deletions tools/config/Tomb1Main_ConfigTool/Resources/Lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand Down
4 changes: 4 additions & 0 deletions tools/config/Tomb1Main_ConfigTool/Resources/Lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@
"DataType": "Bool",
"DefaultValue": true
},
{
"Field": "restore_ps1_enemies",
"DataType": "Bool",
"DefaultValue": false
},
{
"Field": "enable_timer_in_inventory",
"DataType": "Bool",
Expand Down

0 comments on commit 480845f

Please sign in to comment.