Skip to content

Commit

Permalink
tr2/game-string: split from gameflow
Browse files Browse the repository at this point in the history
  • Loading branch information
rr- committed Jan 16, 2025
1 parent 972d786 commit 6502ac8
Show file tree
Hide file tree
Showing 19 changed files with 1,072 additions and 772 deletions.
526 changes: 8 additions & 518 deletions data/tr2/ship/cfg/TR2X_gameflow.json5

Large diffs are not rendered by default.

598 changes: 598 additions & 0 deletions data/tr2/ship/cfg/TR2X_strings.json5

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/tr2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
| Toggle photo mode | --- | F1 |
| Toggle photo mode UI | --- | H |
- changed the `/kill` command with no arguments to look for enemies within 5 tiles (#2297)
- changed the game data to use a separate strings file for text information, removing it from the game flow file
- fixed showing inventory ring up/down arrows when uncalled for (#2225)
- fixed Lara never stepping backwards off a step using her right foot (#1602)
- fixed blood spawning on Lara from gunshots using incorrect positioning data (#2253)
Expand Down
5 changes: 5 additions & 0 deletions src/libtrx/game/game_string_table/aliases.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#if TR_VERSION == 1
#include "aliases_tr1.def"
#elif TR_VERSION == 2
#include "aliases_tr2.def"
#endif
56 changes: 56 additions & 0 deletions src/libtrx/game/game_string_table/aliases_tr1.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
OBJ_ALIAS_DEFINE(O_PISTOL_ITEM, GS_ID(INV_ITEM_PISTOLS))
OBJ_ALIAS_DEFINE(O_PISTOL_OPTION, GS_ID(INV_ITEM_PISTOLS))
OBJ_ALIAS_DEFINE(O_SHOTGUN_ITEM, GS_ID(INV_ITEM_SHOTGUN))
OBJ_ALIAS_DEFINE(O_SHOTGUN_OPTION, GS_ID(INV_ITEM_SHOTGUN))
OBJ_ALIAS_DEFINE(O_MAGNUM_ITEM, GS_ID(INV_ITEM_MAGNUM))
OBJ_ALIAS_DEFINE(O_MAGNUM_OPTION, GS_ID(INV_ITEM_MAGNUM))
OBJ_ALIAS_DEFINE(O_UZI_ITEM, GS_ID(INV_ITEM_UZI))
OBJ_ALIAS_DEFINE(O_UZI_OPTION, GS_ID(INV_ITEM_UZI))
OBJ_ALIAS_DEFINE(O_PISTOL_AMMO_ITEM, GS_ID(INV_ITEM_PISTOL_AMMO))
OBJ_ALIAS_DEFINE(O_PISTOL_AMMO_OPTION, GS_ID(INV_ITEM_PISTOL_AMMO))
OBJ_ALIAS_DEFINE(O_SG_AMMO_ITEM, GS_ID(INV_ITEM_SHOTGUN_AMMO))
OBJ_ALIAS_DEFINE(O_SG_AMMO_OPTION, GS_ID(INV_ITEM_SHOTGUN_AMMO))
OBJ_ALIAS_DEFINE(O_MAG_AMMO_ITEM, GS_ID(INV_ITEM_MAGNUM_AMMO))
OBJ_ALIAS_DEFINE(O_MAG_AMMO_OPTION, GS_ID(INV_ITEM_MAGNUM_AMMO))
OBJ_ALIAS_DEFINE(O_UZI_AMMO_ITEM, GS_ID(INV_ITEM_UZI_AMMO))
OBJ_ALIAS_DEFINE(O_UZI_AMMO_OPTION, GS_ID(INV_ITEM_UZI_AMMO))
OBJ_ALIAS_DEFINE(O_EXPLOSIVE_ITEM, GS_ID(INV_ITEM_GRENADE))
OBJ_ALIAS_DEFINE(O_EXPLOSIVE_OPTION, GS_ID(INV_ITEM_GRENADE))
OBJ_ALIAS_DEFINE(O_MEDI_ITEM, GS_ID(INV_ITEM_SMALL_MEDIPACK))
OBJ_ALIAS_DEFINE(O_MEDI_OPTION, GS_ID(INV_ITEM_SMALL_MEDIPACK))
OBJ_ALIAS_DEFINE(O_BIGMEDI_ITEM, GS_ID(INV_ITEM_LARGE_MEDIPACK))
OBJ_ALIAS_DEFINE(O_BIGMEDI_OPTION, GS_ID(INV_ITEM_LARGE_MEDIPACK))
OBJ_ALIAS_DEFINE(O_PUZZLE_ITEM_1, GS_ID(INV_ITEM_PUZZLE_1))
OBJ_ALIAS_DEFINE(O_PUZZLE_OPTION_1, GS_ID(INV_ITEM_PUZZLE_1))
OBJ_ALIAS_DEFINE(O_PUZZLE_ITEM_2, GS_ID(INV_ITEM_PUZZLE_2))
OBJ_ALIAS_DEFINE(O_PUZZLE_OPTION_2, GS_ID(INV_ITEM_PUZZLE_2))
OBJ_ALIAS_DEFINE(O_PUZZLE_ITEM_3, GS_ID(INV_ITEM_PUZZLE_3))
OBJ_ALIAS_DEFINE(O_PUZZLE_OPTION_3, GS_ID(INV_ITEM_PUZZLE_3))
OBJ_ALIAS_DEFINE(O_PUZZLE_ITEM_4, GS_ID(INV_ITEM_PUZZLE_4))
OBJ_ALIAS_DEFINE(O_PUZZLE_OPTION_4, GS_ID(INV_ITEM_PUZZLE_4))
OBJ_ALIAS_DEFINE(O_KEY_ITEM_1, GS_ID(INV_ITEM_KEY_1))
OBJ_ALIAS_DEFINE(O_KEY_OPTION_1, GS_ID(INV_ITEM_KEY_1))
OBJ_ALIAS_DEFINE(O_KEY_ITEM_2, GS_ID(INV_ITEM_KEY_2))
OBJ_ALIAS_DEFINE(O_KEY_OPTION_2, GS_ID(INV_ITEM_KEY_2))
OBJ_ALIAS_DEFINE(O_KEY_ITEM_3, GS_ID(INV_ITEM_KEY_3))
OBJ_ALIAS_DEFINE(O_KEY_OPTION_3, GS_ID(INV_ITEM_KEY_3))
OBJ_ALIAS_DEFINE(O_KEY_ITEM_4, GS_ID(INV_ITEM_KEY_4))
OBJ_ALIAS_DEFINE(O_KEY_OPTION_4, GS_ID(INV_ITEM_KEY_4))
OBJ_ALIAS_DEFINE(O_PICKUP_ITEM_1, GS_ID(INV_ITEM_PICKUP_1))
OBJ_ALIAS_DEFINE(O_PICKUP_OPTION_1, GS_ID(INV_ITEM_PICKUP_1))
OBJ_ALIAS_DEFINE(O_PICKUP_ITEM_2, GS_ID(INV_ITEM_PICKUP_2))
OBJ_ALIAS_DEFINE(O_PICKUP_OPTION_2, GS_ID(INV_ITEM_PICKUP_2))
OBJ_ALIAS_DEFINE(O_LEADBAR_ITEM, GS_ID(INV_ITEM_LEADBAR))
OBJ_ALIAS_DEFINE(O_LEADBAR_OPTION, GS_ID(INV_ITEM_LEADBAR))
OBJ_ALIAS_DEFINE(O_SCION_ITEM_1, GS_ID(INV_ITEM_SCION))
OBJ_ALIAS_DEFINE(O_SCION_ITEM_2, GS_ID(INV_ITEM_SCION))
OBJ_ALIAS_DEFINE(O_SCION_ITEM_3, GS_ID(INV_ITEM_SCION))
OBJ_ALIAS_DEFINE(O_SCION_ITEM_4, GS_ID(INV_ITEM_SCION))
OBJ_ALIAS_DEFINE(O_SCION_OPTION, GS_ID(INV_ITEM_SCION))
OBJ_ALIAS_DEFINE(O_COMPASS_OPTION, GS_ID(INV_ITEM_COMPASS))
OBJ_ALIAS_DEFINE(O_PASSPORT_OPTION, GS_ID(INV_ITEM_GAME))
OBJ_ALIAS_DEFINE(O_PASSPORT_CLOSED, GS_ID(INV_ITEM_GAME))
OBJ_ALIAS_DEFINE(O_DETAIL_OPTION, GS_ID(INV_ITEM_DETAILS))
OBJ_ALIAS_DEFINE(O_SOUND_OPTION, GS_ID(INV_ITEM_SOUND))
OBJ_ALIAS_DEFINE(O_CONTROL_OPTION, GS_ID(INV_ITEM_CONTROLS))
OBJ_ALIAS_DEFINE(O_PHOTO_OPTION, GS_ID(INV_ITEM_LARAS_HOME))
62 changes: 62 additions & 0 deletions src/libtrx/game/game_string_table/aliases_tr2.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
OBJ_ALIAS_DEFINE(O_COMPASS_OPTION, GS_ID(INV_ITEM_STOPWATCH))
OBJ_ALIAS_DEFINE(O_COMPASS_ITEM, GS_ID(INV_ITEM_STOPWATCH))
OBJ_ALIAS_DEFINE(O_PISTOL_ITEM, GS_ID(INV_ITEM_PISTOLS))
OBJ_ALIAS_DEFINE(O_PISTOL_OPTION, GS_ID(INV_ITEM_PISTOLS))
OBJ_ALIAS_DEFINE(O_FLARE_ITEM, GS_ID(INV_ITEM_FLARE))
OBJ_ALIAS_DEFINE(O_FLARES_OPTION, GS_ID(INV_ITEM_FLARE))
OBJ_ALIAS_DEFINE(O_SHOTGUN_ITEM, GS_ID(INV_ITEM_SHOTGUN))
OBJ_ALIAS_DEFINE(O_SHOTGUN_OPTION, GS_ID(INV_ITEM_SHOTGUN))
OBJ_ALIAS_DEFINE(O_MAGNUM_ITEM, GS_ID(INV_ITEM_MAGNUMS))
OBJ_ALIAS_DEFINE(O_MAGNUM_OPTION, GS_ID(INV_ITEM_MAGNUMS))
OBJ_ALIAS_DEFINE(O_UZI_ITEM, GS_ID(INV_ITEM_UZIS))
OBJ_ALIAS_DEFINE(O_UZI_OPTION, GS_ID(INV_ITEM_UZIS))
OBJ_ALIAS_DEFINE(O_HARPOON_ITEM, GS_ID(INV_ITEM_HARPOON))
OBJ_ALIAS_DEFINE(O_HARPOON_OPTION, GS_ID(INV_ITEM_HARPOON))
OBJ_ALIAS_DEFINE(O_M16_ITEM, GS_ID(INV_ITEM_M16))
OBJ_ALIAS_DEFINE(O_M16_OPTION, GS_ID(INV_ITEM_M16))
OBJ_ALIAS_DEFINE(O_GRENADE_ITEM, GS_ID(INV_ITEM_GRENADE))
OBJ_ALIAS_DEFINE(O_GRENADE_OPTION, GS_ID(INV_ITEM_GRENADE))
OBJ_ALIAS_DEFINE(O_PISTOL_AMMO_ITEM, GS_ID(INV_ITEM_PISTOL_AMMO))
OBJ_ALIAS_DEFINE(O_PISTOL_AMMO_OPTION, GS_ID(INV_ITEM_PISTOL_AMMO))
OBJ_ALIAS_DEFINE(O_SHOTGUN_AMMO_ITEM, GS_ID(INV_ITEM_SHOTGUN_AMMO))
OBJ_ALIAS_DEFINE(O_SHOTGUN_AMMO_OPTION, GS_ID(INV_ITEM_SHOTGUN_AMMO))
OBJ_ALIAS_DEFINE(O_MAGNUM_AMMO_ITEM, GS_ID(INV_ITEM_MAGNUM_AMMO))
OBJ_ALIAS_DEFINE(O_MAGNUM_AMMO_OPTION, GS_ID(INV_ITEM_MAGNUM_AMMO))
OBJ_ALIAS_DEFINE(O_UZI_AMMO_ITEM, GS_ID(INV_ITEM_UZI_AMMO))
OBJ_ALIAS_DEFINE(O_UZI_AMMO_OPTION, GS_ID(INV_ITEM_UZI_AMMO))
OBJ_ALIAS_DEFINE(O_HARPOON_AMMO_ITEM, GS_ID(INV_ITEM_HARPOON_AMMO))
OBJ_ALIAS_DEFINE(O_HARPOON_AMMO_OPTION, GS_ID(INV_ITEM_HARPOON_AMMO))
OBJ_ALIAS_DEFINE(O_M16_AMMO_ITEM, GS_ID(INV_ITEM_M16_AMMO))
OBJ_ALIAS_DEFINE(O_M16_AMMO_OPTION, GS_ID(INV_ITEM_M16_AMMO))
OBJ_ALIAS_DEFINE(O_GRENADE_AMMO_ITEM, GS_ID(INV_ITEM_GRENADE_AMMO))
OBJ_ALIAS_DEFINE(O_GRENADE_AMMO_OPTION, GS_ID(INV_ITEM_GRENADE_AMMO))
OBJ_ALIAS_DEFINE(O_SMALL_MEDIPACK_ITEM, GS_ID(INV_ITEM_SMALL_MEDIPACK))
OBJ_ALIAS_DEFINE(O_SMALL_MEDIPACK_OPTION, GS_ID(INV_ITEM_SMALL_MEDIPACK))
OBJ_ALIAS_DEFINE(O_LARGE_MEDIPACK_ITEM, GS_ID(INV_ITEM_LARGE_MEDIPACK))
OBJ_ALIAS_DEFINE(O_LARGE_MEDIPACK_OPTION, GS_ID(INV_ITEM_LARGE_MEDIPACK))
OBJ_ALIAS_DEFINE(O_PICKUP_ITEM_1, GS_ID(INV_ITEM_PICKUP_1))
OBJ_ALIAS_DEFINE(O_PICKUP_OPTION_1, GS_ID(INV_ITEM_PICKUP_1))
OBJ_ALIAS_DEFINE(O_PICKUP_ITEM_2, GS_ID(INV_ITEM_PICKUP_2))
OBJ_ALIAS_DEFINE(O_PICKUP_OPTION_2, GS_ID(INV_ITEM_PICKUP_2))
OBJ_ALIAS_DEFINE(O_PUZZLE_ITEM_1, GS_ID(INV_ITEM_PUZZLE_1))
OBJ_ALIAS_DEFINE(O_PUZZLE_OPTION_1, GS_ID(INV_ITEM_PUZZLE_1))
OBJ_ALIAS_DEFINE(O_PUZZLE_ITEM_2, GS_ID(INV_ITEM_PUZZLE_2))
OBJ_ALIAS_DEFINE(O_PUZZLE_OPTION_2, GS_ID(INV_ITEM_PUZZLE_2))
OBJ_ALIAS_DEFINE(O_PUZZLE_ITEM_3, GS_ID(INV_ITEM_PUZZLE_3))
OBJ_ALIAS_DEFINE(O_PUZZLE_OPTION_3, GS_ID(INV_ITEM_PUZZLE_3))
OBJ_ALIAS_DEFINE(O_PUZZLE_ITEM_4, GS_ID(INV_ITEM_PUZZLE_4))
OBJ_ALIAS_DEFINE(O_PUZZLE_OPTION_4, GS_ID(INV_ITEM_PUZZLE_4))
OBJ_ALIAS_DEFINE(O_KEY_ITEM_1, GS_ID(INV_ITEM_KEY_1))
OBJ_ALIAS_DEFINE(O_KEY_OPTION_1, GS_ID(INV_ITEM_KEY_1))
OBJ_ALIAS_DEFINE(O_KEY_ITEM_2, GS_ID(INV_ITEM_KEY_2))
OBJ_ALIAS_DEFINE(O_KEY_OPTION_2, GS_ID(INV_ITEM_KEY_2))
OBJ_ALIAS_DEFINE(O_KEY_ITEM_3, GS_ID(INV_ITEM_KEY_3))
OBJ_ALIAS_DEFINE(O_KEY_OPTION_3, GS_ID(INV_ITEM_KEY_3))
OBJ_ALIAS_DEFINE(O_KEY_ITEM_4, GS_ID(INV_ITEM_KEY_4))
OBJ_ALIAS_DEFINE(O_KEY_OPTION_4, GS_ID(INV_ITEM_KEY_4))
OBJ_ALIAS_DEFINE(O_PASSPORT_OPTION, GS_ID(INV_ITEM_GAME))
OBJ_ALIAS_DEFINE(O_PASSPORT_CLOSED, GS_ID(INV_ITEM_GAME))
OBJ_ALIAS_DEFINE(O_DETAIL_OPTION, GS_ID(INV_ITEM_DETAILS))
OBJ_ALIAS_DEFINE(O_SOUND_OPTION, GS_ID(INV_ITEM_SOUND))
OBJ_ALIAS_DEFINE(O_CONTROL_OPTION, GS_ID(INV_ITEM_CONTROLS))
OBJ_ALIAS_DEFINE(O_PHOTO_OPTION, GS_ID(INV_ITEM_LARAS_HOME))
154 changes: 154 additions & 0 deletions src/libtrx/game/game_string_table/common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#include "debug.h"
#include "enum_map.h"
#include "game/game_string.h"
#include "game/game_string_table.h"
#include "game/game_string_table/priv.h"
#include "game/objects/names.h"
#include "log.h"
#include "memory.h"

#include <stddef.h>

typedef void (*M_LOAD_STRING_FUNC)(const char *, const char *);

GS_FILE g_GST_File = {};

static struct {
GAME_OBJECT_ID object_id;
GAME_STRING_ID game_string_id;
} m_ObjectAliases[] = {
#define OBJ_ALIAS_DEFINE(object_id_, game_string_id_) \
{ .object_id = object_id_, .game_string_id = game_string_id_ },
#include "./aliases.def"
#undef OBJ_ALIAS_DEFINE
{ .object_id = NO_OBJECT },
};

static void M_GameStringTableEntry_Free(GS_TABLE_ENTRY *entry);
static void M_GameStringTable_Free(GS_TABLE *gs_table);
static void M_GameStringFile_Free(GS_FILE *gs_file);
static void M_ApplyGameString(const char *key, const char *value);
static void M_ApplyObjectString(const char *key, const char *value);
static void M_ApplyEntries(
const GS_TABLE_ENTRY *const entries, M_LOAD_STRING_FUNC load_func);
static void M_ApplyStrings(
const GS_TABLE_ENTRY *global_entries, const GS_TABLE_ENTRY *level_entries,
M_LOAD_STRING_FUNC load_func);
static void M_ApplyGameStrings(const GS_FILE *gs_table, int32_t level_num);
static void M_ApplyObjectStrings(const GS_FILE *gs_table, int32_t level_num);

static void M_GameStringTableEntry_Free(GS_TABLE_ENTRY *const entry)
{
if (entry == NULL) {
return;
}
GS_TABLE_ENTRY *cur = entry;
while (cur->key != NULL) {
Memory_FreePointer(&cur->key);
Memory_FreePointer(&cur->value);
cur++;
}
Memory_Free(entry);
}

static void M_GameStringTable_Free(GS_TABLE *const gs_table)
{
M_GameStringTableEntry_Free(gs_table->object_strings);
gs_table->object_strings = NULL;
M_GameStringTableEntry_Free(gs_table->game_strings);
gs_table->game_strings = NULL;
}

static void M_GameStringFile_Free(GS_FILE *const gs_file)
{
M_GameStringTable_Free(&gs_file->global);
for (int32_t i = 0; i < gs_file->level_count; i++) {
M_GameStringTable_Free(&gs_file->levels[i]);
}
Memory_FreePointer(&gs_file->levels);
gs_file->level_count = 0;
}

static void M_ApplyGameString(const char *const key, const char *const value)
{
if (!GameString_IsKnown(key)) {
LOG_ERROR("Invalid game string key: %s", key);
} else if (value == NULL) {
LOG_ERROR("Invalid game string value: %s", key);
} else {
GameString_Define(key, value);
}
}

static void M_ApplyObjectString(const char *const key, const char *const value)
{
const GAME_OBJECT_ID object_id =
ENUM_MAP_GET(GAME_OBJECT_ID, key, NO_OBJECT);
if (object_id == NO_OBJECT) {
LOG_ERROR("Invalid object id: %s", key);
} else {
Object_SetName(object_id, value);
}
}

static void M_ApplyEntries(
const GS_TABLE_ENTRY *entries, const M_LOAD_STRING_FUNC load_func)
{
while (entries != NULL && entries->key != NULL) {
load_func(entries->key, entries->value);
entries++;
}
}

static void M_ApplyStrings(
const GS_TABLE_ENTRY *const global_entries,
const GS_TABLE_ENTRY *const level_entries,
const M_LOAD_STRING_FUNC load_func)
{
M_ApplyEntries(global_entries, load_func);
if (level_entries != NULL) {
M_ApplyEntries(level_entries, load_func);
}
}

static void M_ApplyGameStrings(
const GS_FILE *const gs_file, const int32_t level_num)
{
ASSERT(level_num >= -1 && level_num < gs_file->level_count);
M_ApplyStrings(
gs_file->global.game_strings,
level_num != -1 ? gs_file->levels[level_num].game_strings : NULL,
M_ApplyGameString);
}

static void M_ApplyObjectStrings(
const GS_FILE *const gs_file, const int32_t level_num)
{
ASSERT(level_num >= -1 && level_num < gs_file->level_count);
M_ApplyStrings(
gs_file->global.object_strings,
level_num != -1 ? gs_file->levels[level_num].object_strings : NULL,
M_ApplyObjectString);
}

void GameStringTable_Apply(const int32_t level_num)
{
Object_ResetNames();

const GS_FILE *const gs_file = &g_GST_File;
M_ApplyObjectStrings(gs_file, level_num);
M_ApplyGameStrings(gs_file, level_num);

for (int32_t i = 0; m_ObjectAliases[i].object_id != NO_OBJECT; i++) {
const char *const new_name =
GameString_Get(m_ObjectAliases[i].game_string_id);
if (new_name != NULL) {
Object_SetName(m_ObjectAliases[i].object_id, new_name);
}
}
}

void GameStringTable_Shutdown(void)
{
M_GameStringFile_Free(&g_GST_File);
}
21 changes: 21 additions & 0 deletions src/libtrx/game/game_string_table/priv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include <stdint.h>

typedef struct {
const char *key;
const char *value;
} GS_TABLE_ENTRY;

typedef struct {
GS_TABLE_ENTRY *object_strings;
GS_TABLE_ENTRY *game_strings;
} GS_TABLE;

typedef struct {
int32_t level_count;
GS_TABLE global;
GS_TABLE *levels;
} GS_FILE;

extern GS_FILE g_GST_File;
Loading

0 comments on commit 6502ac8

Please sign in to comment.