Skip to content

Commit

Permalink
tr1/game-flow: move demos to own level sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
rr- committed Jan 25, 2025
1 parent dfef88b commit a550558
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 85 deletions.
45 changes: 43 additions & 2 deletions data/tr1/ship/cfg/TR1X_gameflow.json5
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@
{"type": "level_stats", "level_id": 2},
{"type": "exit_to_level", "level_id": 3},
],
"demo": true,
},

// Level 3: Lost Valley
Expand All @@ -108,7 +107,6 @@
{"type": "level_stats", "level_id": 3},
{"type": "exit_to_level", "level_id": 4},
],
"demo": true,
},

// Level 4: Tomb of Qualopec
Expand Down Expand Up @@ -506,6 +504,49 @@
},
],

"demos": [
// Demo 1: City of Vilcabamba
{
"path": "data/level2.phd",
"type": "normal",
"music_track": 57,
"injections": [
"data/injections/vilcabamba_itemrots.bin",
"data/injections/vilcabamba_textures.bin",
],
"sequence": [
{"type": "loading_screen", "path": "data/images/peru.webp"},
{"type": "load_level"},
{"type": "play_level"},
{"type": "level_stats", "level_id": 2},
{"type": "exit_to_level", "level_id": 3},
],
"demo": true,
},

// Demo 2: Lost Valley
{
"path": "data/level3a.phd",
"type": "normal",
"music_track": 57,
"injections": [
"data/injections/braid_valley.bin",
"data/injections/valley_itemrots.bin",
"data/injections/valley_skybox.bin",
"data/injections/valley_textures.bin",
],
"sequence": [
{"type": "loading_screen", "path": "data/images/peru.webp"},
{"type": "load_level"},
{"type": "play_level"},
{"type": "level_stats", "level_id": 3},
{"type": "exit_to_level", "level_id": 4},
],
"demo": true,
},

],

// FMVs
"fmvs": [
{"path": "fmv/core.avi"},
Expand Down
18 changes: 18 additions & 0 deletions data/tr1/ship/cfg/TR1X_strings.json5
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,24 @@
},
],

"demos": [
{
"title": "City of Vilcabamba",
"objects": {
"key_1": {"name": "Silver Key"},
"puzzle_1": {"name": "Gold Idol"},
},
},

{
"title": "Lost Valley",
"objects": {
"puzzle_1": {"name": "Machine Cog"},
},
},

],

"objects": {
"small_medipack": {"name": "Small Medi Pack"},
"large_medipack": {"name": "Large Medi Pack"},
Expand Down
6 changes: 3 additions & 3 deletions data/tr2/ship/cfg/TR2X_gameflow.json5
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@
],

"demos": [
// 0. Venice
// Demo 1: Venice
{
"path": "data/boat.tr2",
"music_track": -1,
Expand All @@ -326,7 +326,7 @@
],
},

// 1. Wreck of the Maria Doria
// Demo 2: Wreck of the Maria Doria
{
"path": "data/keel.tr2",
"music_track": 31,
Expand All @@ -342,7 +342,7 @@
],
},

// 2. Tibetan Foothills
// Demo 3: Tibetan Foothills
{
"path": "data/skidoo.tr2",
"music_track": 33,
Expand Down
24 changes: 12 additions & 12 deletions docs/tr1/GAMEFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ various pieces of global behaviour.
// etc
},
],
"demos": [
{
"path": "data/gym.phd",
// etc
},
],
"fmvs": [
{"path": "data/snow.rpl"},
// etc
Expand Down Expand Up @@ -228,7 +234,6 @@ Following are each of the properties available within a level.
"water_color": [0.7, 0.5, 0.85],
"draw_distance_fade": 34.0,
"draw_distance_max": 50.0,
"demo": true,
"unobtainable_pickups": 1,
"unobtainable_kills": 1,
"inherit_injections": false,
Expand Down Expand Up @@ -257,17 +262,6 @@ Following are each of the properties available within a level.
<th>Required</th>
<th colspan="2">Description</th>
</tr>
<tr valign="top">
<td>
<code>demo</code>
</td>
<td>Boolean</td>
<td>No</td>
<td colspan="2">
Flag to indicate that the level has available demo data to play out from
the title screen.
</td>
</tr>
<tr valign="top">
<td>
<code>draw_distance_fade</code>
Expand Down Expand Up @@ -756,6 +750,12 @@ default gameflow for examples.
</tr>
</table>

## Demos
The `demos` section shows all the levels that can play a demo when the player
leaves the main inventory screen idle for a while or by using the `/demo`
command. For the demos to work, these levels need to have demo data built-in.
Aside from this requirement, this section works just like the `levels` section.

## Bonus levels
The gameflow supports bonus levels, which are unlocked only when the player
collects all secrets in the game's normal levels. These bonus levels behave just
Expand Down
19 changes: 13 additions & 6 deletions src/libtrx/game/game_string_table/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,25 +91,32 @@ void GameStringTable_Apply(const GAME_FLOW_LEVEL *const level)
GF_SetLevelTitle(
GF_GetLevel(i, GFL_NORMAL), gs_file->levels.entries[i].title);
}

#if TR_VERSION == 2
// TODO: TR1 still has everything in a single linear sequence
for (int32_t i = 0; i < GF_GetLevelCount(GFL_DEMO); i++) {
GF_SetLevelTitle(
GF_GetLevel(i, GFL_DEMO), gs_file->demos.entries[i].title);
}

#if TR_VERSION == 2
// TODO: TR1 still has cutscene levels in a single linear sequence
for (int32_t i = 0; i < GF_GetLevelCount(GFL_CUTSCENE); i++) {
GF_SetLevelTitle(
GF_GetLevel(i, GFL_CUTSCENE), gs_file->cutscenes.entries[i].title);
}
#endif

if (level != NULL) {
const GS_LEVEL_TABLE *level_table = NULL;
#if TR_VERSION == 1
// TODO: TR1 still has everything in a single linear sequence
const GS_LEVEL_TABLE *const level_table = &gs_file->levels;
// TODO: TR1 still has most levels in a single linear sequence
switch (level->type) {
default:
level_table = &gs_file->levels;
break;
case GFL_DEMO:
level_table = &gs_file->demos;
break;
}
#elif TR_VERSION == 2
const GS_LEVEL_TABLE *level_table = NULL;
switch (level->type) {
case GFL_NORMAL:
case GFL_SAVED:
Expand Down
2 changes: 1 addition & 1 deletion src/libtrx/game/game_string_table/reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ void GameStringTable_LoadFromFile(const char *const path)
JSON_OBJECT *root_obj = JSON_ValueAsObject(root);
M_LoadTableFromJSON(root_obj, &gs_file->global);
M_LoadLevelsFromJSON(root_obj, "levels", GFL_NORMAL, &gs_file->levels);
M_LoadLevelsFromJSON(root_obj, "demos", GFL_DEMO, &gs_file->demos);
#if TR_VERSION == 2
// TODO: TR1 still has everything in a single linear sequence
M_LoadLevelsFromJSON(root_obj, "demos", GFL_DEMO, &gs_file->demos);
M_LoadLevelsFromJSON(
root_obj, "cutscenes", GFL_CUTSCENE, &gs_file->cutscenes);
#endif
Expand Down
5 changes: 1 addition & 4 deletions src/libtrx/include/libtrx/game/game_flow/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ typedef struct {
#if TR_VERSION == 1
GAME_FLOW_LEVEL_SETTINGS settings;

bool demo;

struct {
uint32_t pickups;
uint32_t kills;
Expand Down Expand Up @@ -110,13 +108,13 @@ typedef struct {
int32_t cutscene_count;
GAME_FLOW_LEVEL *cutscenes;
};
#endif

// demos
struct {
int32_t demo_count;
GAME_FLOW_LEVEL *demos;
};
#endif

// FMVs
struct {
Expand All @@ -134,7 +132,6 @@ typedef struct {
// global settings
struct {
float demo_delay;
bool has_demo;
char *main_menu_background_path;
bool enable_tr2_item_drops;
bool convert_dropped_guns;
Expand Down
49 changes: 16 additions & 33 deletions src/tr1/game/demo.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ typedef struct {
TEXTSTRING *text;
} M_PRIV;

static int32_t m_LastDemoNum = 0;
static M_PRIV m_Priv;

static void M_PrepareConfig(M_PRIV *const p);
Expand Down Expand Up @@ -70,8 +71,18 @@ static void M_PrepareResumeInfo(M_PRIV *const p)
RESUME_INFO *const resume_info = GF_GetResumeInfo(p->level);
p->old_resume_info = *resume_info;
resume_info->flags.available = 1;
resume_info->flags.costume = 0;
resume_info->num_medis = 0;
resume_info->num_big_medis = 0;
resume_info->num_scions = 0;
resume_info->flags.got_pistols = 1;
resume_info->flags.got_shotgun = 0;
resume_info->flags.got_magnums = 0;
resume_info->flags.got_uzis = 0;
resume_info->pistol_ammo = 1000;
resume_info->shotgun_ammo = 0;
resume_info->magnum_ammo = 0;
resume_info->uzi_ammo = 0;
resume_info->gun_status = LGS_ARMLESS;
resume_info->equipped_gun_type = LGT_PISTOLS;
resume_info->holsters_gun_type = LGT_PISTOLS;
Expand Down Expand Up @@ -235,41 +246,13 @@ void Demo_Unpause(void)
int32_t Demo_ChooseLevel(const int32_t demo_num)
{
M_PRIV *const p = &m_Priv;

bool any_demos = false;
for (int32_t i = g_GameFlow.first_level_num; i <= g_GameFlow.last_level_num;
i++) {
if (g_GameFlow.levels[i].demo) {
any_demos = true;
}
}
if (!any_demos) {
return -1;
}

if (demo_num >= 0) {
int32_t j = 0;
for (int32_t i = g_GameFlow.first_level_num;
i <= g_GameFlow.last_level_num; i++) {
if (g_GameFlow.levels[i].demo) {
if (j == demo_num) {
return i;
}
j++;
}
}
if (GF_GetDemoCount() <= 0) {
return -1;
} else if (demo_num < 0 || demo_num >= GF_GetDemoCount()) {
return (m_LastDemoNum++) % GF_GetDemoCount();
} else {
return demo_num;
}

// pick the next demo
int16_t level_num = p->level != NULL ? p->level->num : -1;
do {
level_num++;
if (level_num > g_GameFlow.last_level_num) {
level_num = g_GameFlow.first_level_num;
}
} while (!g_GameFlow.levels[level_num].demo);
return level_num;
}

GAME_FLOW_COMMAND Demo_Control(void)
Expand Down
18 changes: 10 additions & 8 deletions src/tr1/game/game_flow/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,16 @@ int32_t GF_GetLevelCount(const GAME_FLOW_LEVEL_TYPE level_type)
return 1;
case GFL_GYM:
return 1;
case GFL_DEMO:
return g_GameFlow.demo_count;
default:
return g_GameFlow.level_count;
}
}

int32_t GF_GetDemoCount(void)
{
int32_t demo_count = 0;
for (int32_t i = g_GameFlow.first_level_num; i <= g_GameFlow.last_level_num;
i++) {
if (g_GameFlow.levels[i].demo) {
demo_count++;
}
}
return demo_count;
return g_GameFlow.demo_count;
}

void GF_SetLevelTitle(GAME_FLOW_LEVEL *const level, const char *const title)
Expand All @@ -96,6 +91,13 @@ GAME_FLOW_LEVEL *GF_GetLevel(
case GFL_TITLE:
return &g_GameFlow.levels[g_GameFlow.title_level_num];

case GFL_DEMO:
if (num < 0 || num >= GF_GetDemoCount()) {
LOG_ERROR("Invalid demo number: %d", num);
return NULL;
}
return &g_GameFlow.demos[num];

default:
if (num < 0 || num >= GF_GetLevelCount(level_type)) {
LOG_ERROR("Invalid level number: %d", num);
Expand Down
Loading

0 comments on commit a550558

Please sign in to comment.