tr2/game-flow: fix /play keeping Lara's inventory

Resolves #2267.
This commit is contained in:
Marcin Kurczewski 2025-02-09 17:58:18 +01:00
parent 60eaf76aad
commit 1d10559202
8 changed files with 85 additions and 52 deletions

View file

@ -51,6 +51,7 @@
- fixed software renderer skybox occlusion issues (#2343, regression from 0.7)
- fixed gunflare from bandits in Tibetan levels spawning too far from their guns (#2365, regression from 0.8)
- fixed guns sometimes appearing in Lara's hands when entering the fly cheat while undrawing weapons (#2376, regression from 0.3)
- fixed the `/play` console command not resetting Lara's inventory (#2267, regression from 0.3)
- improved rendering to achieve a slight performance boost in big rooms (#2325)
- improved wireframe mode appearance around screen edges

View file

@ -30,8 +30,8 @@ typedef enum {
GFSC_SAVED,
#if TR_VERSION == 1
GFSC_RESTART,
GFSC_SELECT,
#endif
GFSC_SELECT,
GFSC_STORY,
} GF_SEQUENCE_CONTEXT;

View file

@ -200,21 +200,18 @@ void Shell_Main(void)
gf_cmd.param);
switch (gf_cmd.action) {
case GF_START_GAME: {
case GF_START_GAME:
case GF_SELECT_GAME: {
const int32_t level_num = gf_cmd.param;
const GF_LEVEL *const level = GF_GetLevel(GFLT_MAIN, level_num);
const GF_SEQUENCE_CONTEXT seq_ctx =
gf_cmd.action == GF_SELECT_GAME ? GFSC_SELECT : GFSC_NORMAL;
if (level != nullptr) {
gf_cmd = GF_DoLevelSequence(level, GFSC_NORMAL);
gf_cmd = GF_DoLevelSequence(level, seq_ctx);
}
break;
}
case GF_SELECT_GAME: {
const GF_LEVEL *const level = GF_GetLevel(GFLT_MAIN, gf_cmd.param);
gf_cmd = GF_DoLevelSequence(level, GFSC_SELECT);
break;
}
case GF_START_SAVED_GAME: {
const int16_t slot_num = gf_cmd.param;
const int16_t level_num = Savegame_GetLevelNumber(slot_num);

View file

@ -701,6 +701,17 @@ void Savegame_InitCurrentInfo(void)
g_SaveGame.bonus_flag = 0;
}
void Savegame_CarryCurrentInfoToNextLevel(
const GF_LEVEL *const src_level, const GF_LEVEL *const dst_level)
{
LOG_INFO(
"Copying resume info from level #%d to level #%d", src_level->num,
dst_level->num);
START_INFO *const src_resume = Savegame_GetCurrentInfo(src_level);
START_INFO *const dst_resume = Savegame_GetCurrentInfo(dst_level);
memcpy(dst_resume, src_resume, sizeof(START_INFO));
}
void Savegame_ApplyLogicToCurrentInfo(const GF_LEVEL *const level)
{
START_INFO *start = Savegame_GetCurrentInfo(level);
@ -780,6 +791,33 @@ void Savegame_ApplyLogicToCurrentInfo(const GF_LEVEL *const level)
start->flares = -1;
start->gun_type = LGT_GRENADE;
}
if (g_GF_RemoveWeapons) {
start->has_pistols = 0;
start->has_magnums = 0;
start->has_uzis = 0;
start->has_shotgun = 0;
start->has_m16 = 0;
start->has_grenade = 0;
start->has_harpoon = 0;
start->gun_type = LGT_UNARMED;
start->gun_status = LGS_ARMLESS;
g_GF_RemoveWeapons = false;
}
if (g_GF_RemoveAmmo) {
start->m16_ammo = 0;
start->grenade_ammo = 0;
start->harpoon_ammo = 0;
start->shotgun_ammo = 0;
start->uzi_ammo = 0;
start->magnum_ammo = 0;
start->pistol_ammo = 0;
start->flares = 0;
start->large_medipacks = 0;
start->small_medipacks = 0;
g_GF_RemoveAmmo = false;
}
}
void Savegame_PersistGameToCurrentInfo(const GF_LEVEL *const level)

View file

@ -14,6 +14,8 @@ void Savegame_InitCurrentInfo(void);
void Savegame_ResetCurrentInfo(const GF_LEVEL *level);
START_INFO *Savegame_GetCurrentInfo(const GF_LEVEL *level);
void Savegame_CarryCurrentInfoToNextLevel(
const GF_LEVEL *src_level, const GF_LEVEL *dst_level);
void Savegame_ApplyLogicToCurrentInfo(const GF_LEVEL *level);
void Savegame_PersistGameToCurrentInfo(const GF_LEVEL *level);
void CreateSaveGameInfo(void);

View file

@ -52,6 +52,25 @@ static DECLARE_GF_EVENT_HANDLER(M_HandlePlayLevel)
case GFSC_SAVED:
break;
case GFSC_SELECT: {
// console /play level feature
Savegame_InitCurrentInfo();
const GF_LEVEL *tmp_level = GF_GetFirstLevel();
while (tmp_level != nullptr && tmp_level <= level) {
Savegame_ApplyLogicToCurrentInfo(tmp_level);
if (tmp_level == level) {
break;
}
const GF_LEVEL *const next_level = GF_GetLevelAfter(tmp_level);
if (next_level != nullptr) {
Savegame_CarryCurrentInfoToNextLevel(tmp_level, next_level);
}
tmp_level = next_level;
}
InitialiseLevelFlags();
break;
}
default:
Savegame_ApplyLogicToCurrentInfo(level);
InitialiseLevelFlags();
@ -241,10 +260,16 @@ GF_SEQUENCE_CONTEXT GF_SwitchSequenceContext(
const GF_SEQUENCE_EVENT *const event, const GF_SEQUENCE_CONTEXT seq_ctx)
{
// Update sequence context if necessary
if (event->type == GFS_LOOP_GAME && seq_ctx == GFSC_SAVED) {
return GFSC_NORMAL;
if (event->type != GFS_LOOP_GAME) {
return seq_ctx;
}
switch (seq_ctx) {
case GFSC_SAVED:
case GFSC_SELECT:
return GFSC_NORMAL;
default:
return seq_ctx;
}
return seq_ctx;
}
bool GF_ShouldSkipSequenceEvent(

View file

@ -859,33 +859,6 @@ void Lara_InitialiseInventory(const GF_LEVEL *const level)
START_INFO *const start = Savegame_GetCurrentInfo(level);
if (start != nullptr) {
if (g_GF_RemoveWeapons) {
start->has_pistols = 0;
start->has_magnums = 0;
start->has_uzis = 0;
start->has_shotgun = 0;
start->has_m16 = 0;
start->has_grenade = 0;
start->has_harpoon = 0;
start->gun_type = LGT_UNARMED;
start->gun_status = LGS_ARMLESS;
g_GF_RemoveWeapons = false;
}
if (g_GF_RemoveAmmo) {
start->m16_ammo = 0;
start->grenade_ammo = 0;
start->harpoon_ammo = 0;
start->shotgun_ammo = 0;
start->uzi_ammo = 0;
start->magnum_ammo = 0;
start->pistol_ammo = 0;
start->flares = 0;
start->large_medipacks = 0;
start->small_medipacks = 0;
g_GF_RemoveAmmo = false;
}
g_Lara.pistol_ammo.ammo = 1000;
if (start->has_pistols) {
Inv_AddItem(O_PISTOL_ITEM);

View file

@ -370,21 +370,18 @@ void Shell_Main(void)
switch (gf_cmd.action) {
case GF_START_GAME:
case GF_SELECT_GAME:
if (g_GameFlow.single_level >= 0) {
const GF_LEVEL *const level =
GF_GetLevel(GFLT_MAIN, g_GameFlow.single_level);
if (level != nullptr) {
gf_cmd = GF_DoLevelSequence(level, GFSC_NORMAL);
}
} else {
const GF_LEVEL *const level =
GF_GetLevel(GFLT_MAIN, gf_cmd.param);
if (level != nullptr) {
gf_cmd = GF_DoLevelSequence(level, GFSC_NORMAL);
}
case GF_SELECT_GAME: {
const int32_t level_num = g_GameFlow.single_level >= 0
? g_GameFlow.single_level
: gf_cmd.param;
const GF_SEQUENCE_CONTEXT seq_ctx =
gf_cmd.action == GF_SELECT_GAME ? GFSC_SELECT : GFSC_NORMAL;
const GF_LEVEL *const level = GF_GetLevel(GFLT_MAIN, level_num);
if (level != nullptr) {
gf_cmd = GF_DoLevelSequence(level, seq_ctx);
}
break;
}
case GF_START_SAVED_GAME: {
S_LoadGame(gf_cmd.param);