mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 20:58:07 +03:00
passport: add the story so far option to view cutscenes and FMVs
Resolves #201
This commit is contained in:
parent
e2015b9003
commit
d8b4fbecf6
14 changed files with 180 additions and 19 deletions
|
@ -1,6 +1,7 @@
|
|||
## [Unreleased](https://github.com/rr-/Tomb1Main/compare/stable...develop)
|
||||
- added the option to make Lara revert to pistols on new level start (#557)
|
||||
- added the PS1 style UI (#517)
|
||||
- added the "Story so far..." option in the select level menu to view cutscenes and FMVs (#201)
|
||||
|
||||
## [2.9.1](https://github.com/rr-/Tomb1Main/compare/2.9...2.9.1) - 2022-06-03
|
||||
- fixed crash on centaur hatch (#579, regression from 2.9)
|
||||
|
|
|
@ -270,6 +270,7 @@ Not all options are turned on by default. Refer to `Tomb1Main.json5` for details
|
|||
- added level selection to the load game menu
|
||||
- added the ability to make freshly triggered (runaway) Pierre replace an already existing (runaway) Pierre
|
||||
- added the PS1 style UI
|
||||
- added the "Story so far..." option in the select level menu to view cutscenes and FMVs
|
||||
- changed internal game memory limit from 3.5 MB to 16 MB
|
||||
- changed moveable limit from 256 to 10240
|
||||
- changed maximum textures from 2048 to 8192
|
||||
|
|
|
@ -496,7 +496,7 @@
|
|||
"HEADING_ITEMS": "ITEMS",
|
||||
"PASSPORT_SELECT_LEVEL": "Select Level",
|
||||
"PASSPORT_RESTART_LEVEL": "Restart Level",
|
||||
"PASSPORT_LOCKED_LEVEL": "Level Locked",
|
||||
"PASSPORT_STORY_SO_FAR": "Story so far...",
|
||||
"PASSPORT_LEGACY_SELECT_LEVEL_1": "Legacy saves do not",
|
||||
"PASSPORT_LEGACY_SELECT_LEVEL_2": "support this feature.",
|
||||
"PASSPORT_SELECT_MODE": "Select Mode",
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
"HEADING_ITEMS": "ITEMS",
|
||||
"PASSPORT_SELECT_LEVEL": "Select Level",
|
||||
"PASSPORT_RESTART_LEVEL": "Restart Level",
|
||||
"PASSPORT_LOCKED_LEVEL": "Level Locked",
|
||||
"PASSPORT_STORY_SO_FAR": "Story so far...",
|
||||
"PASSPORT_LEGACY_SELECT_LEVEL_1": "Legacy saves do not",
|
||||
"PASSPORT_LEGACY_SELECT_LEVEL_2": "support this feature.",
|
||||
"PASSPORT_SELECT_MODE": "Select Mode",
|
||||
|
|
|
@ -246,6 +246,11 @@ int32_t Game_Stop(void)
|
|||
g_GameInfo.passport_page == PASSPORT_PAGE_1
|
||||
&& g_GameInfo.passport_mode == PASSPORT_MODE_SELECT_LEVEL) {
|
||||
return GF_SELECT_GAME | g_GameInfo.select_level_num;
|
||||
} else if (
|
||||
g_GameInfo.passport_page == PASSPORT_PAGE_1
|
||||
&& g_GameInfo.passport_mode == PASSPORT_MODE_STORY_SO_FAR) {
|
||||
// page 1: story so far
|
||||
return GF_STORY_SO_FAR | g_GameInfo.current_save_slot;
|
||||
} else if (g_GameInfo.passport_page == PASSPORT_PAGE_2) {
|
||||
return GF_START_GAME
|
||||
| (g_InvMode == INV_DEATH_MODE ? g_CurrentLevel
|
||||
|
|
|
@ -54,7 +54,7 @@ static GAME_STRING_ID GameFlow_StringToGameStringID(const char *str)
|
|||
{ "HEADING_ITEMS", GS_HEADING_ITEMS },
|
||||
{ "PASSPORT_SELECT_LEVEL", GS_PASSPORT_SELECT_LEVEL },
|
||||
{ "PASSPORT_RESTART_LEVEL", GS_PASSPORT_RESTART_LEVEL },
|
||||
{ "PASSPORT_LOCKED_LEVEL", GS_PASSPORT_LOCKED_LEVEL },
|
||||
{ "PASSPORT_STORY_SO_FAR", GS_PASSPORT_STORY_SO_FAR },
|
||||
{ "PASSPORT_LEGACY_SELECT_LEVEL_1", GS_PASSPORT_LEGACY_SELECT_LEVEL_1 },
|
||||
{ "PASSPORT_LEGACY_SELECT_LEVEL_2", GS_PASSPORT_LEGACY_SELECT_LEVEL_2 },
|
||||
{ "PASSPORT_SELECT_MODE", GS_PASSPORT_SELECT_MODE },
|
||||
|
@ -1299,3 +1299,101 @@ GameFlow_InterpretSequence(int32_t level_num, GAMEFLOW_LEVEL_TYPE level_type)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GAMEFLOW_OPTION
|
||||
GameFlow_StorySoFar(int32_t level_num, int32_t savegame_level)
|
||||
{
|
||||
LOG_INFO("%d", level_num);
|
||||
|
||||
GAMEFLOW_SEQUENCE *seq = g_GameFlow.levels[level_num].sequence;
|
||||
GAMEFLOW_OPTION ret = GF_EXIT_TO_TITLE;
|
||||
while (seq->type != GFS_END) {
|
||||
LOG_INFO("seq %d %d", seq->type, seq->data);
|
||||
|
||||
switch (seq->type) {
|
||||
case GFS_LOOP_GAME:
|
||||
case GFS_STOP_GAME:
|
||||
case GFS_LEVEL_STATS:
|
||||
case GFS_TOTAL_STATS:
|
||||
case GFS_DISPLAY_PICTURE:
|
||||
case GFS_GIVE_ITEM:
|
||||
case GFS_REMOVE_GUNS:
|
||||
case GFS_REMOVE_SCIONS:
|
||||
case GFS_FIX_PYRAMID_SECRET_TRIGGER:
|
||||
break;
|
||||
|
||||
case GFS_START_GAME:
|
||||
if (level_num == savegame_level) {
|
||||
return GF_EXIT_TO_TITLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GFS_START_CINE:
|
||||
ret = Game_Cutscene_Start((int32_t)seq->data);
|
||||
break;
|
||||
|
||||
case GFS_LOOP_CINE:
|
||||
ret = Game_Cutscene_Loop();
|
||||
break;
|
||||
|
||||
case GFS_STOP_CINE:
|
||||
ret = Game_Cutscene_Stop((int32_t)seq->data);
|
||||
break;
|
||||
|
||||
case GFS_PLAY_FMV:
|
||||
FMV_Play((char *)seq->data);
|
||||
break;
|
||||
|
||||
case GFS_EXIT_TO_TITLE:
|
||||
return GF_EXIT_TO_TITLE;
|
||||
|
||||
case GFS_EXIT_TO_LEVEL:
|
||||
return GF_START_GAME | ((int32_t)seq->data & ((1 << 6) - 1));
|
||||
|
||||
case GFS_EXIT_TO_CINE:
|
||||
return GF_START_CINE | ((int32_t)seq->data & ((1 << 6) - 1));
|
||||
|
||||
case GFS_SET_CAM_X:
|
||||
g_Camera.pos.x = (int32_t)seq->data;
|
||||
break;
|
||||
case GFS_SET_CAM_Y:
|
||||
g_Camera.pos.y = (int32_t)seq->data;
|
||||
break;
|
||||
case GFS_SET_CAM_Z:
|
||||
g_Camera.pos.z = (int32_t)seq->data;
|
||||
break;
|
||||
case GFS_SET_CAM_ANGLE:
|
||||
g_Camera.target_angle = (int32_t)seq->data;
|
||||
break;
|
||||
case GFS_FLIP_MAP:
|
||||
Room_FlipMap();
|
||||
break;
|
||||
case GFS_PLAY_SYNCED_AUDIO:
|
||||
Music_Play((int32_t)seq->data);
|
||||
break;
|
||||
|
||||
case GFS_MESH_SWAP: {
|
||||
GAMEFLOW_MESH_SWAP_DATA *swap_data = seq->data;
|
||||
int16_t *temp = g_Meshes
|
||||
[g_Objects[swap_data->object1_num].mesh_index
|
||||
+ swap_data->mesh_num];
|
||||
g_Meshes
|
||||
[g_Objects[swap_data->object1_num].mesh_index
|
||||
+ swap_data->mesh_num] = g_Meshes
|
||||
[g_Objects[swap_data->object2_num].mesh_index
|
||||
+ swap_data->mesh_num];
|
||||
g_Meshes
|
||||
[g_Objects[swap_data->object2_num].mesh_index
|
||||
+ swap_data->mesh_num] = temp;
|
||||
break;
|
||||
}
|
||||
|
||||
case GFS_END:
|
||||
return ret;
|
||||
}
|
||||
|
||||
seq++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -75,5 +75,7 @@ extern GAMEFLOW_DEFAULT_STRING g_GameFlowDefaultStrings[];
|
|||
|
||||
GAMEFLOW_OPTION
|
||||
GameFlow_InterpretSequence(int32_t level_num, GAMEFLOW_LEVEL_TYPE level_type);
|
||||
GAMEFLOW_OPTION
|
||||
GameFlow_StorySoFar(int32_t level_num, int32_t savegame_level);
|
||||
bool GameFlow_LoadFromFile(const char *file_name);
|
||||
void GameFlow_Shutdown(void);
|
||||
|
|
|
@ -900,6 +900,11 @@ int32_t Inv_Display(int inv_mode)
|
|||
&& g_GameInfo.passport_mode == PASSPORT_MODE_SELECT_LEVEL) {
|
||||
// page 1: select level
|
||||
return GF_SELECT_GAME | g_GameInfo.select_level_num;
|
||||
} else if (
|
||||
g_GameInfo.passport_page == PASSPORT_PAGE_1
|
||||
&& g_GameInfo.passport_mode == PASSPORT_MODE_STORY_SO_FAR) {
|
||||
// page 1: story so far
|
||||
return GF_STORY_SO_FAR | g_GameInfo.current_save_slot;
|
||||
} else if (g_GameInfo.passport_page == PASSPORT_PAGE_2) {
|
||||
// page 2: new game
|
||||
Savegame_InitCurrentInfo();
|
||||
|
@ -918,6 +923,11 @@ int32_t Inv_Display(int inv_mode)
|
|||
&& g_GameInfo.passport_mode == PASSPORT_MODE_SELECT_LEVEL) {
|
||||
// page 1: select level
|
||||
return GF_SELECT_GAME | g_GameInfo.select_level_num;
|
||||
} else if (
|
||||
g_GameInfo.passport_page == PASSPORT_PAGE_1
|
||||
&& g_GameInfo.passport_mode == PASSPORT_MODE_STORY_SO_FAR) {
|
||||
// page 1: story so far
|
||||
return GF_STORY_SO_FAR | g_GameInfo.current_save_slot;
|
||||
} else if (g_GameInfo.passport_page == PASSPORT_PAGE_2) {
|
||||
// page 2: restart level
|
||||
return GF_RESTART_GAME | g_CurrentLevel;
|
||||
|
@ -935,6 +945,11 @@ int32_t Inv_Display(int inv_mode)
|
|||
&& g_GameInfo.passport_mode == PASSPORT_MODE_SELECT_LEVEL) {
|
||||
// page 1: select level
|
||||
return GF_SELECT_GAME | g_GameInfo.select_level_num;
|
||||
} else if (
|
||||
g_GameInfo.passport_page == PASSPORT_PAGE_1
|
||||
&& g_GameInfo.passport_mode == PASSPORT_MODE_STORY_SO_FAR) {
|
||||
// page 1: story so far
|
||||
return GF_STORY_SO_FAR | g_GameInfo.current_save_slot;
|
||||
} else if (g_GameInfo.passport_page == PASSPORT_PAGE_2) {
|
||||
if (g_CurrentLevel == g_GameFlow.gym_level_num) {
|
||||
// page 2: new game in gym
|
||||
|
|
|
@ -98,7 +98,7 @@ void Option_PassportInit(void)
|
|||
g_SavegameRequester.item_texts = Memory_Alloc(
|
||||
g_Config.maximum_save_slots * g_SavegameRequester.item_text_len);
|
||||
m_SelectLevelRequester.item_texts = Memory_Alloc(
|
||||
g_GameFlow.level_count * m_SelectLevelRequester.item_text_len);
|
||||
(g_GameFlow.level_count + 1) * m_SelectLevelRequester.item_text_len);
|
||||
}
|
||||
|
||||
void Option_PassportShutdown(void)
|
||||
|
@ -181,7 +181,10 @@ static void Option_PassportShowLevelSelect(void)
|
|||
{
|
||||
int32_t select = Requester_Display(&m_SelectLevelRequester);
|
||||
if (select) {
|
||||
if (select > 0) {
|
||||
if (select - 1 + g_GameFlow.first_level_num
|
||||
== Savegame_GetLevelNumber(g_GameInfo.current_save_slot) + 1) {
|
||||
g_GameInfo.passport_mode = PASSPORT_MODE_STORY_SO_FAR;
|
||||
} else if (select > 0) {
|
||||
g_GameInfo.select_level_num =
|
||||
select - 1 + g_GameFlow.first_level_num;
|
||||
g_GameInfo.passport_mode = PASSPORT_MODE_SELECT_LEVEL;
|
||||
|
|
|
@ -53,6 +53,7 @@ bool Savegame_LoadOnlyResumeInfo(int32_t slot_num, GAME_INFO *game_info);
|
|||
|
||||
void Savegame_ScanSavedGames(void);
|
||||
void Savegame_ScanAvailableLevels(REQUEST_INFO *req);
|
||||
GAMEFLOW_OPTION Savegame_PlayAvailableStory(int32_t slot_num);
|
||||
bool Savegame_RestartAvailable(int32_t slot_num);
|
||||
|
||||
void Savegame_ApplyLogicToCurrentInfo(int level_num);
|
||||
|
|
|
@ -586,21 +586,23 @@ void Savegame_ScanAvailableLevels(REQUEST_INFO *req)
|
|||
return;
|
||||
}
|
||||
|
||||
for (int i = g_GameFlow.first_level_num; i <= g_GameFlow.last_level_num;
|
||||
for (int i = g_GameFlow.first_level_num; i <= savegame_info->level_num;
|
||||
i++) {
|
||||
if (i <= savegame_info->level_num) {
|
||||
req->item_flags[req->items] &= ~RIF_BLOCKED;
|
||||
sprintf(
|
||||
&req->item_texts[req->items * req->item_text_len], "%s",
|
||||
g_GameFlow.levels[i].level_title);
|
||||
} else {
|
||||
req->item_flags[req->items] |= RIF_BLOCKED;
|
||||
sprintf(
|
||||
&req->item_texts[req->items * req->item_text_len],
|
||||
g_GameFlow.strings[GS_PASSPORT_LOCKED_LEVEL]);
|
||||
}
|
||||
req->item_flags[req->items] &= ~RIF_BLOCKED;
|
||||
sprintf(
|
||||
&req->item_texts[req->items * req->item_text_len], "%s",
|
||||
g_GameFlow.levels[i].level_title);
|
||||
req->items++;
|
||||
}
|
||||
|
||||
if (g_InvMode == INV_TITLE_MODE) {
|
||||
req->item_flags[req->items] &= ~RIF_BLOCKED;
|
||||
sprintf(
|
||||
&req->item_texts[req->items * req->item_text_len], "%s",
|
||||
g_GameFlow.strings[GS_PASSPORT_STORY_SO_FAR]);
|
||||
req->items++;
|
||||
}
|
||||
|
||||
req->requested = 0;
|
||||
req->line_offset = 0;
|
||||
}
|
||||
|
@ -614,3 +616,29 @@ bool Savegame_RestartAvailable(int32_t slot_num)
|
|||
SAVEGAME_INFO *savegame_info = &m_SavegameInfo[slot_num];
|
||||
return savegame_info->features.restart;
|
||||
}
|
||||
|
||||
GAMEFLOW_OPTION Savegame_PlayAvailableStory(int32_t slot_num)
|
||||
{
|
||||
SAVEGAME_INFO *savegame_info = &m_SavegameInfo[slot_num];
|
||||
|
||||
int32_t gf_option = GF_START_GAME | g_GameFlow.first_level_num;
|
||||
|
||||
bool loop_continue = true;
|
||||
while (loop_continue) {
|
||||
int32_t gf_direction = gf_option & ~((1 << 6) - 1);
|
||||
int32_t gf_param = gf_option & ((1 << 6) - 1);
|
||||
|
||||
gf_option = GameFlow_StorySoFar(gf_param, savegame_info->level_num);
|
||||
|
||||
if (gf_param >= savegame_info->level_num
|
||||
&& gf_param <= g_GameFlow.last_level_num) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (gf_direction == GF_EXIT_GAME) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return GF_EXIT_TO_TITLE;
|
||||
}
|
||||
|
|
|
@ -213,6 +213,11 @@ void Shell_Main(void)
|
|||
break;
|
||||
}
|
||||
|
||||
case GF_STORY_SO_FAR: {
|
||||
gf_option = Savegame_PlayAvailableStory(gf_param);
|
||||
break;
|
||||
}
|
||||
|
||||
case GF_START_CINE:
|
||||
gf_option = GameFlow_InterpretSequence(gf_param, GFL_CUTSCENE);
|
||||
break;
|
||||
|
|
|
@ -994,6 +994,7 @@ typedef enum GAMEFLOW_OPTION {
|
|||
GF_RESTART_GAME = 8 << 6,
|
||||
GF_SELECT_GAME = 9 << 6,
|
||||
GF_START_GYM = 10 << 6,
|
||||
GF_STORY_SO_FAR = 11 << 6,
|
||||
} GAMEFLOW_OPTION;
|
||||
|
||||
typedef enum GAMEFLOW_SEQUENCE_TYPE {
|
||||
|
@ -1031,7 +1032,7 @@ typedef enum GAME_STRING_ID {
|
|||
GS_HEADING_ITEMS,
|
||||
|
||||
GS_PASSPORT_SELECT_LEVEL,
|
||||
GS_PASSPORT_LOCKED_LEVEL,
|
||||
GS_PASSPORT_STORY_SO_FAR,
|
||||
GS_PASSPORT_LEGACY_SELECT_LEVEL_1,
|
||||
GS_PASSPORT_LEGACY_SELECT_LEVEL_2,
|
||||
GS_PASSPORT_RESTART_LEVEL,
|
||||
|
@ -1181,6 +1182,7 @@ typedef enum PASSPORT_MODE {
|
|||
PASSPORT_MODE_SHOW_SAVES = 1,
|
||||
PASSPORT_MODE_NEW_GAME = 2,
|
||||
PASSPORT_MODE_SELECT_LEVEL = 3,
|
||||
PASSPORT_MODE_STORY_SO_FAR = 4,
|
||||
} PASSPORT_MODE;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
|
|
@ -19,7 +19,7 @@ GAMEFLOW_DEFAULT_STRING g_GameFlowDefaultStrings[] = {
|
|||
{ GS_HEADING_ITEMS, "ITEMS" },
|
||||
{ GS_PASSPORT_SELECT_LEVEL, "Select Level" },
|
||||
{ GS_PASSPORT_RESTART_LEVEL, "Restart Level" },
|
||||
{ GS_PASSPORT_LOCKED_LEVEL, "Level Locked" },
|
||||
{ GS_PASSPORT_STORY_SO_FAR, "Story so far..." },
|
||||
{ GS_PASSPORT_LEGACY_SELECT_LEVEL_1, "Legacy saves do not" },
|
||||
{ GS_PASSPORT_LEGACY_SELECT_LEVEL_2, "support this feature." },
|
||||
{ GS_PASSPORT_SELECT_MODE, "Select Mode" },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue