Skip to content

Commit

Permalink
game-flow: move common bits to libtrx
Browse files Browse the repository at this point in the history
  • Loading branch information
rr- committed Jan 29, 2025
1 parent 4ec06bd commit 5caef30
Show file tree
Hide file tree
Showing 20 changed files with 333 additions and 381 deletions.
105 changes: 48 additions & 57 deletions src/libtrx/game/game_flow/sequencer.c
Original file line number Diff line number Diff line change
@@ -1,65 +1,56 @@
#include "game/game_flow/sequencer.h"

#include "config.h"
#include "game/inventory_ring/control.h"
#include "game/objects/vars.h"
#include "game/phase.h"
#include "debug.h"
#include "enum_map.h"
#include "game/game_flow/sequencer_priv.h"

GF_COMMAND GF_EnterPhotoMode(void)
GF_COMMAND GF_InterpretSequence(
const GF_LEVEL *const level, GF_SEQUENCE_CONTEXT seq_ctx,
void *const seq_ctx_arg)
{
PHASE *const subphase = Phase_PhotoMode_Create();
const GF_COMMAND gf_cmd = PhaseExecutor_Run(subphase);
Phase_PhotoMode_Destroy(subphase);
return gf_cmd;
}

GF_COMMAND GF_PauseGame(void)
{
PHASE *const subphase = Phase_Pause_Create();
const GF_COMMAND gf_cmd = PhaseExecutor_Run(subphase);
Phase_Pause_Destroy(subphase);
return gf_cmd;
}

GF_COMMAND GF_ShowInventory(const INVENTORY_MODE mode)
{
PHASE *const phase = Phase_Inventory_Create(mode);
const GF_COMMAND gf_cmd = PhaseExecutor_Run(phase);
Phase_Inventory_Destroy(phase);
return gf_cmd;
}

GF_COMMAND GF_ShowInventoryKeys(const GAME_OBJECT_ID receptacle_type_id)
{
if (g_Config.gameplay.enable_auto_item_selection) {
const GAME_OBJECT_ID object_id = Object_GetCognateInverse(
receptacle_type_id, g_KeyItemToReceptacleMap);
InvRing_SetRequestedObjectID(object_id);
ASSERT(level != nullptr);
LOG_DEBUG(
"running sequence for level=%d type=%d seq_ctx=%d", level->num,
level->type, seq_ctx);

GF_PreSequenceHook();

GF_COMMAND gf_cmd = { .action = GF_EXIT_TO_TITLE };

const GF_SEQUENCE *const sequence = &level->sequence;
for (int32_t i = 0; i < sequence->length; i++) {
const GF_SEQUENCE_EVENT *const event = &sequence->events[i];
LOG_DEBUG(
"event type=%s(%d) data=0x%x",
ENUM_MAP_TO_STRING(GF_SEQUENCE_EVENT_TYPE, event->type),
event->type, event->data);

if (GF_ShouldSkipSequenceEvent(level, event)) {
continue;
}

// Handle the event
if (event->type < GFS_NUMBER_OF
&& GF_GetSequenceEventHandler(event->type) != nullptr) {
gf_cmd = GF_GetSequenceEventHandler(event->type)(
level, event, seq_ctx, seq_ctx_arg);
LOG_DEBUG(
"event type=%s(%d) data=0x%x finished, result: action=%s, "
"param=%d",
ENUM_MAP_TO_STRING(GF_SEQUENCE_EVENT_TYPE, event->type),
event->type, event->data,
ENUM_MAP_TO_STRING(GF_ACTION, gf_cmd.action), gf_cmd.param);
if (gf_cmd.action != GF_NOOP) {
return gf_cmd;
}
}

// Update sequence context if necessary
seq_ctx = GF_SwitchSequenceContext(event, seq_ctx);
}
return GF_ShowInventory(INV_KEYS_MODE);
}

GF_COMMAND GF_RunDemo(const int32_t demo_num)
{
PHASE *const demo_phase = Phase_Demo_Create(demo_num);
const GF_COMMAND gf_cmd = PhaseExecutor_Run(demo_phase);
Phase_Demo_Destroy(demo_phase);
return gf_cmd;
}

GF_COMMAND GF_RunCutscene(const int32_t cutscene_num)
{
PHASE *const cutscene_phase = Phase_Cutscene_Create(cutscene_num);
const GF_COMMAND gf_cmd = PhaseExecutor_Run(cutscene_phase);
Phase_Cutscene_Destroy(cutscene_phase);
return gf_cmd;
}

GF_COMMAND GF_RunGame(
const GF_LEVEL *const level, const GF_SEQUENCE_CONTEXT seq_ctx)
{
PHASE *const phase = Phase_Game_Create(level, seq_ctx);
const GF_COMMAND gf_cmd = PhaseExecutor_Run(phase);
Phase_Game_Destroy(phase);
LOG_DEBUG(
"sequence finished: action=%s param=%d",
ENUM_MAP_TO_STRING(GF_ACTION, gf_cmd.action), gf_cmd.param);
return gf_cmd;
}
100 changes: 100 additions & 0 deletions src/libtrx/game/game_flow/sequencer_misc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include "config.h"
#include "game/demo.h"
#include "game/game_flow/common.h"
#include "game/game_flow/sequencer.h"
#include "game/game_flow/vars.h"
#include "game/inventory_ring/control.h"
#include "game/objects/vars.h"
#include "game/phase.h"
#include "log.h"

GF_COMMAND GF_EnterPhotoMode(void)
{
PHASE *const subphase = Phase_PhotoMode_Create();
const GF_COMMAND gf_cmd = PhaseExecutor_Run(subphase);
Phase_PhotoMode_Destroy(subphase);
return gf_cmd;
}

GF_COMMAND GF_PauseGame(void)
{
PHASE *const subphase = Phase_Pause_Create();
const GF_COMMAND gf_cmd = PhaseExecutor_Run(subphase);
Phase_Pause_Destroy(subphase);
return gf_cmd;
}

GF_COMMAND GF_ShowInventory(const INVENTORY_MODE mode)
{
PHASE *const phase = Phase_Inventory_Create(mode);
const GF_COMMAND gf_cmd = PhaseExecutor_Run(phase);
Phase_Inventory_Destroy(phase);
return gf_cmd;
}

GF_COMMAND GF_ShowInventoryKeys(const GAME_OBJECT_ID receptacle_type_id)
{
if (g_Config.gameplay.enable_auto_item_selection) {
const GAME_OBJECT_ID object_id = Object_GetCognateInverse(
receptacle_type_id, g_KeyItemToReceptacleMap);
InvRing_SetRequestedObjectID(object_id);
}
return GF_ShowInventory(INV_KEYS_MODE);
}

GF_COMMAND GF_RunDemo(const int32_t demo_num)
{
PHASE *const demo_phase = Phase_Demo_Create(demo_num);
const GF_COMMAND gf_cmd = PhaseExecutor_Run(demo_phase);
Phase_Demo_Destroy(demo_phase);
return gf_cmd;
}

GF_COMMAND GF_RunCutscene(const int32_t cutscene_num)
{
PHASE *const cutscene_phase = Phase_Cutscene_Create(cutscene_num);
const GF_COMMAND gf_cmd = PhaseExecutor_Run(cutscene_phase);
Phase_Cutscene_Destroy(cutscene_phase);
return gf_cmd;
}

GF_COMMAND GF_RunGame(
const GF_LEVEL *const level, const GF_SEQUENCE_CONTEXT seq_ctx)
{
PHASE *const phase = Phase_Game_Create(level, seq_ctx);
const GF_COMMAND gf_cmd = PhaseExecutor_Run(phase);
Phase_Game_Destroy(phase);
return gf_cmd;
}

GF_COMMAND GF_DoFrontendSequence(void)
{
if (g_GameFlow.title_level == nullptr) {
return (GF_COMMAND) { .action = GF_NOOP };
}
return GF_InterpretSequence(g_GameFlow.title_level, GFSC_NORMAL, nullptr);
}

GF_COMMAND GF_DoDemoSequence(int32_t demo_num)
{
demo_num = Demo_ChooseLevel(demo_num);
if (demo_num < 0) {
return (GF_COMMAND) { .action = GF_NOOP };
}
const GF_LEVEL *const level = GF_GetLevel(GFLT_DEMOS, demo_num);
if (level == nullptr) {
LOG_ERROR("Missing demo: %d", demo_num);
return (GF_COMMAND) { .action = GF_NOOP };
}
return GF_InterpretSequence(level, GFSC_NORMAL, nullptr);
}

GF_COMMAND GF_DoCutsceneSequence(const int32_t cutscene_num)
{
const GF_LEVEL *const level = GF_GetLevel(GFLT_CUTSCENES, cutscene_num);
if (level == nullptr) {
LOG_ERROR("Missing cutscene: %d", cutscene_num);
return (GF_COMMAND) { .action = GF_NOOP };
}
return GF_InterpretSequence(level, GFSC_NORMAL, nullptr);
}
10 changes: 10 additions & 0 deletions src/libtrx/game/game_flow/sequencer_priv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

extern void GF_PreSequenceHook(void);
extern GF_SEQUENCE_CONTEXT GF_SwitchSequenceContext(
const GF_SEQUENCE_EVENT *event, GF_SEQUENCE_CONTEXT seq_ctx);
extern bool GF_ShouldSkipSequenceEvent(
const GF_LEVEL *level, const GF_SEQUENCE_EVENT *event);
extern GF_COMMAND (
*GF_GetSequenceEventHandler(GF_SEQUENCE_EVENT_TYPE event_type))(
const GF_LEVEL *, const GF_SEQUENCE_EVENT *, GF_SEQUENCE_CONTEXT, void *);
60 changes: 60 additions & 0 deletions src/libtrx/include/libtrx/game/enum_map.def
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,63 @@ ENUM_MAP_DEFINE(UNDERWATER_MUSIC_MODE, UMM_QUIET, "quiet")
ENUM_MAP_DEFINE(UNDERWATER_MUSIC_MODE, UMM_FULL_NO_AMBIENT, "full_no_ambient")
ENUM_MAP_DEFINE(UNDERWATER_MUSIC_MODE, UMM_QUIET_NO_AMBIENT, "quiet_no_ambient")
ENUM_MAP_DEFINE(UNDERWATER_MUSIC_MODE, UMM_NONE, "none")

#if TR_VERSION == 1
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_LOAD_LEVEL, "load_level")
#endif
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_PLAY_LEVEL, "play_level")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_PLAY_FMV, "play_fmv")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_PLAY_CUTSCENE, "play_cutscene")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_PLAY_MUSIC, "play_music")
#if TR_VERSION == 1
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_LOADING_SCREEN, "loading_screen")
#endif
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_DISPLAY_PICTURE, "display_picture")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_LEVEL_STATS, "level_stats")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_TOTAL_STATS, "total_stats")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_EXIT_TO_TITLE, "exit_to_title")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_LEVEL_COMPLETE, "level_complete")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_SET_CAMERA_ANGLE, "set_cutscene_angle")
#if TR_VERSION == 1
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_FLIP_MAP, "flip_map")
#endif
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_ADD_ITEM, "give_item")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_REMOVE_WEAPONS, "remove_weapons")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_REMOVE_AMMO, "remove_ammo")
#if TR_VERSION == 1
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_REMOVE_SCIONS, "remove_scions")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_REMOVE_MEDIPACKS, "remove_medipacks")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_MESH_SWAP, "mesh_swap")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_SETUP_BACON_LARA, "setup_bacon_lara")
#elif TR_VERSION == 2
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_ENABLE_SUNSET, "enable_sunset")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_SET_NUM_SECRETS, "set_secret_count")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_SET_START_ANIM, "set_lara_start_anim")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_DISABLE_FLOOR, "disable_floor")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_ADD_SECRET_REWARD, "add_secret_reward")
#endif

ENUM_MAP_DEFINE(GF_LEVEL_TYPE, GFL_TITLE, "title")
ENUM_MAP_DEFINE(GF_LEVEL_TYPE, GFL_NORMAL, "normal")
ENUM_MAP_DEFINE(GF_LEVEL_TYPE, GFL_CUTSCENE, "cutscene")
ENUM_MAP_DEFINE(GF_LEVEL_TYPE, GFL_GYM, "gym")
#if TR_VERSION == 1
ENUM_MAP_DEFINE(GF_LEVEL_TYPE, GFL_BONUS, "bonus")
ENUM_MAP_DEFINE(GF_LEVEL_TYPE, GFL_DUMMY, "dummy")
ENUM_MAP_DEFINE(GF_LEVEL_TYPE, GFL_CURRENT, "current")
#endif

ENUM_MAP_DEFINE(GF_ACTION, GF_NOOP, "noop")
ENUM_MAP_DEFINE(GF_ACTION, GF_START_GAME, "play_level")
ENUM_MAP_DEFINE(GF_ACTION, GF_START_SAVED_GAME, "load_saved_game")
ENUM_MAP_DEFINE(GF_ACTION, GF_START_CINE, "play_cutscene")
ENUM_MAP_DEFINE(GF_ACTION, GF_START_DEMO, "play_demo")
ENUM_MAP_DEFINE(GF_ACTION, GF_START_FMV, "play_fmv")
ENUM_MAP_DEFINE(GF_ACTION, GF_EXIT_TO_TITLE, "exit_to_title")
ENUM_MAP_DEFINE(GF_ACTION, GF_LEVEL_COMPLETE, "level_complete")
ENUM_MAP_DEFINE(GF_ACTION, GF_EXIT_GAME, "exit_game")
ENUM_MAP_DEFINE(GF_ACTION, GF_SELECT_GAME, "select_level")
#if TR_VERSION == 1
ENUM_MAP_DEFINE(GF_ACTION, GF_RESTART_GAME, "restart_level")
ENUM_MAP_DEFINE(GF_ACTION, GF_STORY_SO_FAR, "story_so_far")
#endif
8 changes: 8 additions & 0 deletions src/libtrx/include/libtrx/game/game_flow/sequencer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,11 @@ GF_COMMAND GF_ShowInventoryKeys(GAME_OBJECT_ID receptacle_type_id);
GF_COMMAND GF_RunDemo(int32_t demo_num);
GF_COMMAND GF_RunCutscene(int32_t cutscene_num);
GF_COMMAND GF_RunGame(const GF_LEVEL *level, GF_SEQUENCE_CONTEXT seq_ctx);

GF_COMMAND GF_DoFrontendSequence(void);
GF_COMMAND GF_TitleSequence(void);
GF_COMMAND GF_DoDemoSequence(int32_t demo_num);
GF_COMMAND GF_DoCutsceneSequence(int32_t cutscene_num);

extern GF_COMMAND GF_InterpretSequence(
const GF_LEVEL *level, GF_SEQUENCE_CONTEXT seq_ctx, void *seq_ctx_arg);
1 change: 1 addition & 0 deletions src/libtrx/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ sources = [
'game/game_flow/common.c',
'game/game_flow/reader.c',
'game/game_flow/sequencer.c',
'game/game_flow/sequencer_misc.c',
'game/game_flow/vars.c',
'game/game_string.c',
'game/game_string_table/common.c',
Expand Down
Loading

0 comments on commit 5caef30

Please sign in to comment.