From 9ab51b24924d8879a2b3d96e127822f6f4967c7f Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Fri, 27 Sep 2024 15:33:47 +0200 Subject: [PATCH 1/3] libtrx: use new fuzzy matcher --- src/game/objects/names.c | 135 ++++++++------------------------------- subprojects/libtrx | 2 +- 2 files changed, 26 insertions(+), 111 deletions(-) diff --git a/src/game/objects/names.c b/src/game/objects/names.c index e2b54828..f140f7f6 100644 --- a/src/game/objects/names.c +++ b/src/game/objects/names.c @@ -16,11 +16,6 @@ #define GOOD_MATCH_THRESHOLD 50 -typedef struct { - int32_t score; - GAME_OBJECT_ID object_id; -} MATCH; - static const INVENTORY_ITEM *const m_InvItems[] = { &g_Inv_Item_Stopwatch, &g_Inv_Item_Pistols, &g_Inv_Item_Flare, &g_Inv_Item_Shotgun, @@ -60,50 +55,6 @@ ENUM_STRING_MAP ENUM_STRING_MAP(GAME_OBJECT_ID)[] = { { NULL, -1 } }; -static int32_t M_NameMatch(const char *user_input, const char *name); -static void M_TryMatch( - VECTOR *matches, const char *user_input, const char *name, - GAME_OBJECT_ID object_id); - -static int32_t M_NameMatch(const char *const user_input, const char *const name) -{ - int32_t score; - - char *regex = Memory_Alloc(strlen(user_input) + 5); - strcpy(regex, "\\b"); - strcat(regex, user_input); - strcat(regex, "\\b"); - if (String_Match(name, regex)) { - // Match by full word. - score = GOOD_MATCH_THRESHOLD + strlen(user_input) * 100 / strlen(name); - } else if (String_CaseSubstring(name, user_input)) { - // Match by substring. - score = strlen(user_input) * 100 / strlen(name); - } else { - // No match. - score = 0; - } - Memory_FreePointer(®ex); - return score; -} - -static void M_TryMatch( - VECTOR *const matches, const char *const user_input, const char *const name, - const GAME_OBJECT_ID object_id) -{ - int32_t score = M_NameMatch(user_input, name); - if (!g_Objects[object_id].loaded) { - score -= GOOD_MATCH_THRESHOLD; - } - if (score > 0) { - MATCH match = { - .score = score, - .object_id = object_id, - }; - Vector_Add(matches, &match); - } -} - const char *Object_GetName(const GAME_OBJECT_ID object_id) { // TODO: remove this in favor of changing the INVENTORY_ITEM.text directly @@ -140,89 +91,53 @@ GAME_OBJECT_ID *Object_IdsFromName( const char *user_input, int32_t *out_match_count, bool (*filter)(GAME_OBJECT_ID)) { - // first, calculate the number of matches to allocate - VECTOR *matches = Vector_Create(sizeof(MATCH)); + VECTOR *source = Vector_Create(sizeof(STRING_FUZZY_SOURCE)); - // Store matches from customizable inventory strings + // Check customizable inventory strings for (const INVENTORY_ITEM *const *item_ptr = m_InvItems; *item_ptr != NULL; item_ptr++) { const INVENTORY_ITEM *const item = *item_ptr; const GAME_OBJECT_ID object_id = Object_GetCognateInverse(item->object_id, g_ItemToInvObjectMap); + LOG_DEBUG("%d %s", object_id, item->string); if (filter != NULL && !filter(object_id)) { continue; } - M_TryMatch(matches, user_input, item->string, object_id); + STRING_FUZZY_SOURCE source_item = { + .key = item->string, + .value = (void *)(intptr_t)object_id, + .weight = 1, + }; + Vector_Add(source, &source_item); } - // Store matches from hardcoded strings + // Check hardcoded object names for (GAME_OBJECT_ID object_id = 0; object_id < O_NUMBER_OF; object_id++) { if (filter != NULL && !filter(object_id)) { continue; } - M_TryMatch(matches, user_input, Object_GetName(object_id), object_id); - } - - // If we got a perfect match, discard poor matches - bool good_matches = false; - for (int i = 0; i < matches->count; i++) { - const MATCH *const match = Vector_Get(matches, i); - if (match->score >= GOOD_MATCH_THRESHOLD) { - good_matches = true; - } - } - if (good_matches) { - for (int i = matches->count - 1; i >= 0; i--) { - const MATCH *const match = Vector_Get(matches, i); - if (match->score < GOOD_MATCH_THRESHOLD) { - Vector_RemoveAt(matches, i); - } - } - } - - // sort by match length so that best-matching results appear first - for (int i = 0; i < matches->count; i++) { - for (int j = i + 1; j < matches->count; j++) { - if (((const MATCH *)Vector_Get(matches, i))->score - < ((const MATCH *)Vector_Get(matches, j))->score) { - Vector_Swap(matches, i, j); - } - } - } - for (int i = 0; i < matches->count; i++) { - const MATCH *const match = Vector_Get(matches, i); - LOG_DEBUG( - "%d. %s (%d)", i, Object_GetName(match->object_id), match->score); + STRING_FUZZY_SOURCE source_item = { + .key = Object_GetName(object_id), + .value = (void *)(intptr_t)object_id, + .weight = 1, + }; + Vector_Add(source, &source_item); } - // Make sure the returned matching object ids are unique - GAME_OBJECT_ID *unique_ids = + VECTOR *matches = String_FuzzyMatch(user_input, source); + GAME_OBJECT_ID *results = Memory_Alloc(sizeof(GAME_OBJECT_ID) * (matches->count + 1)); - - int32_t unique_count = 0; for (int32_t i = 0; i < matches->count; i++) { - const MATCH *const match = Vector_Get(matches, i); - bool is_unique = true; - for (int32_t j = 0; j < unique_count; j++) { - if (match->object_id == unique_ids[j]) { - is_unique = false; - break; - } - } - if (is_unique) { - unique_ids[unique_count++] = match->object_id; - } + const STRING_FUZZY_MATCH *const match = Vector_Get(matches, i); + results[i] = (GAME_OBJECT_ID)(intptr_t)match->value; + } + results[matches->count] = NO_OBJECT; + if (out_match_count != NULL) { + *out_match_count = matches->count; } Vector_Free(matches); matches = NULL; - // Finalize results - unique_ids[unique_count] = NO_OBJECT; - if (out_match_count != NULL) { - *out_match_count = unique_count; - } - - Memory_FreePointer(&matches); - return unique_ids; + return results; } diff --git a/subprojects/libtrx b/subprojects/libtrx index e1d12599..fd2df506 160000 --- a/subprojects/libtrx +++ b/subprojects/libtrx @@ -1 +1 @@ -Subproject commit e1d12599cac2d06331d13f3758e763b8588904e1 +Subproject commit fd2df5065b738f57bc3cbcfafcfe5d2110ecdf95 From 1933238739fe92df64b46f67ce24cb37f5d553c9 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Fri, 27 Sep 2024 16:35:39 +0200 Subject: [PATCH 2/3] object/names: move name management to libtrx --- data/ship/cfg/TR2X_gameflow.json5 | 8 +- docs/progress.txt | 2 +- meson.build | 1 - src/game/gameflow.c | 46 +----- src/game/gameflow/gameflow_new.c | 132 ++++++++++++++- src/game/inventory/common.c | 49 +----- src/game/objects/names.c | 143 ---------------- src/game/objects/names.def | 265 ------------------------------ src/game/objects/names.h | 18 -- src/global/const.h | 1 - src/global/enum_str.def | 14 ++ subprojects/libtrx | 2 +- tools/update_gameflow | 2 +- 13 files changed, 157 insertions(+), 526 deletions(-) delete mode 100644 src/game/objects/names.c delete mode 100644 src/game/objects/names.def delete mode 100644 src/game/objects/names.h diff --git a/data/ship/cfg/TR2X_gameflow.json5 b/data/ship/cfg/TR2X_gameflow.json5 index fc412a68..e6699b1b 100644 --- a/data/ship/cfg/TR2X_gameflow.json5 +++ b/data/ship/cfg/TR2X_gameflow.json5 @@ -238,12 +238,12 @@ "O_FLARE_ITEM": "Flare", "O_DETAIL_OPTION": "Detail Option", "O_SOUND_OPTION": "Sound Option", - "O_CONTROL_OPTION": "Control Option", + "O_CONTROL_OPTION": "Controls Option", "O_GAMMA_OPTION": "Gamma Option", "O_PISTOL_OPTION": "Pistol Option", "O_SHOTGUN_OPTION": "Shotgun Option", - "O_MAGNUM_OPTION": "Magnum Option", - "O_UZI_OPTION": "Uzi Option", + "O_MAGNUM_OPTION": "Magnums Option", + "O_UZI_OPTION": "Uzis Option", "O_HARPOON_OPTION": "Harpoon Option", "O_M16_OPTION": "M16 Option", "O_GRENADE_OPTION": "Grenade Launcher Option", @@ -327,7 +327,7 @@ "O_M16_FLASH": "M16 Flash", "O_BODY_PART": "Body Part", "O_CAMERA_TARGET": "Camera Target", - "O_WATERFALL": "Waterfall", + "O_WATERFALL": "Waterfall Mist", "O_MISSILE_HARPOON": "Missile Harpoon", "O_MISSILE_FLAME": "Missile Flame", "O_MISSILE_KNIFE": "Missile Knife", diff --git a/docs/progress.txt b/docs/progress.txt index 04b82d47..eeca13b4 100644 --- a/docs/progress.txt +++ b/docs/progress.txt @@ -2042,7 +2042,7 @@ typedef enum { // decompiled } LARA_MESH; typedef enum { // decompiled - O_NONE = -1, + NO_OBJECT = -1, O_LARA = 0, O_LARA_PISTOLS = 1, O_LARA_HAIR = 2, diff --git a/meson.build b/meson.build index ec9be072..c87f17f3 100644 --- a/meson.build +++ b/meson.build @@ -141,7 +141,6 @@ dll_sources = [ 'src/game/objects/general/body_part.c', 'src/game/objects/general/door.c', 'src/game/objects/general/final_level_counter.c', - 'src/game/objects/names.c', 'src/game/objects/traps/ember_emitter.c', 'src/game/objects/traps/flame_emitter.c', 'src/game/objects/vars.c', diff --git a/src/game/gameflow.c b/src/game/gameflow.c index 23ba06b6..ba700062 100644 --- a/src/game/gameflow.c +++ b/src/game/gameflow.c @@ -6,7 +6,6 @@ #include "game/game.h" #include "game/gun/gun.h" #include "game/inventory/backpack.h" -#include "game/objects/names.h" #include "game/overlay.h" #include "game/requester.h" #include "gameflow/gameflow_new.h" @@ -14,6 +13,7 @@ #include "global/vars.h" #include +#include #include #include @@ -334,50 +334,6 @@ int32_t __cdecl GF_LoadScriptFile(const char *const fname) g_GameFlow.level_complete_track = MX_END_OF_LEVEL; - g_Inv_Item_Stopwatch.string = - g_GF_GameStrings[GF_S_GAME_INV_ITEM_STATISTICS]; - g_Inv_Item_Pistols.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_PISTOLS]; - g_Inv_Item_Flare.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_FLARE]; - g_Inv_Item_Shotgun.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_SHOTGUN]; - g_Inv_Item_Magnums.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_MAGNUMS]; - g_Inv_Item_Uzis.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_UZIS]; - g_Inv_Item_Harpoon.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_HARPOON]; - g_Inv_Item_M16.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_M16]; - g_Inv_Item_Grenade.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_GRENADE]; - g_Inv_Item_PistolAmmo.string = - g_GF_GameStrings[GF_S_GAME_INV_ITEM_PISTOL_AMMO]; - g_Inv_Item_ShotgunAmmo.string = - g_GF_GameStrings[GF_S_GAME_INV_ITEM_SHOTGUN_AMMO]; - g_Inv_Item_MagnumAmmo.string = - g_GF_GameStrings[GF_S_GAME_INV_ITEM_MAGNUM_AMMO]; - g_Inv_Item_UziAmmo.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_UZI_AMMO]; - g_Inv_Item_HarpoonAmmo.string = - g_GF_GameStrings[GF_S_GAME_INV_ITEM_HARPOON_AMMO]; - g_Inv_Item_M16Ammo.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_M16_AMMO]; - g_Inv_Item_GrenadeAmmo.string = - g_GF_GameStrings[GF_S_GAME_INV_ITEM_GRENADE_AMMO]; - g_Inv_Item_SmallMedi.string = - g_GF_GameStrings[GF_S_GAME_INV_ITEM_SMALL_MEDIPACK]; - g_Inv_Item_LargeMedi.string = - g_GF_GameStrings[GF_S_GAME_INV_ITEM_LARGE_MEDIPACK]; - g_Inv_Item_Pickup1.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_PICKUP]; - g_Inv_Item_Pickup2.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_PICKUP]; - g_Inv_Item_Puzzle1.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_PUZZLE]; - g_Inv_Item_Puzzle2.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_PUZZLE]; - g_Inv_Item_Puzzle3.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_PUZZLE]; - g_Inv_Item_Puzzle4.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_PUZZLE]; - g_Inv_Item_Key1.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_KEY]; - g_Inv_Item_Key2.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_KEY]; - g_Inv_Item_Key3.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_KEY]; - g_Inv_Item_Key4.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_KEY]; - - g_Inv_Item_Passport.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_GAME]; - g_Inv_Item_Graphics.string = g_GF_PCStrings[GF_S_PC_DETAIL_LEVELS]; - - g_Inv_Item_Sound.string = g_GF_PCStrings[GF_S_PC_SOUND]; - g_Inv_Item_Controls.string = g_GF_PCStrings[GF_S_PC_CONTROLS]; - g_Inv_Item_Photo.string = g_GF_GameStrings[GF_S_GAME_INV_ITEM_LARA_HOME]; - Requester_SetHeading( &g_LoadGameRequester, g_GF_GameStrings[GF_S_GAME_PASSPORT_SELECT_LEVEL], 0, 0, 0); diff --git a/src/game/gameflow/gameflow_new.c b/src/game/gameflow/gameflow_new.c index 2bd4de94..174bb997 100644 --- a/src/game/gameflow/gameflow_new.c +++ b/src/game/gameflow/gameflow_new.c @@ -1,12 +1,12 @@ #include "game/gameflow/gameflow_new.h" #include "game/game_string.h" -#include "game/objects/names.h" #include "global/enum_str.h" #include "global/types.h" #include "global/vars.h" #include +#include #include #include @@ -83,8 +83,138 @@ static void M_LoadGameStrings(const int32_t level_num) void GF_N_LoadStrings(const int32_t level_num) { + Object_ResetNames(); + M_LoadObjectStrings(level_num); M_LoadGameStrings(level_num); + + struct { + GAME_OBJECT_ID object_id; + GF_GAME_STRING game_string; + } game_string_defs[] = { + { O_COMPASS_OPTION, GF_S_GAME_INV_ITEM_STATISTICS }, + { O_COMPASS_ITEM, GF_S_GAME_INV_ITEM_STATISTICS }, + { O_PISTOL_ITEM, GF_S_GAME_INV_ITEM_PISTOLS }, + { O_PISTOL_OPTION, GF_S_GAME_INV_ITEM_PISTOLS }, + { O_FLARE_ITEM, GF_S_GAME_INV_ITEM_FLARE }, + { O_FLARES_OPTION, GF_S_GAME_INV_ITEM_FLARE }, + { O_SHOTGUN_ITEM, GF_S_GAME_INV_ITEM_SHOTGUN }, + { O_SHOTGUN_OPTION, GF_S_GAME_INV_ITEM_SHOTGUN }, + { O_MAGNUM_ITEM, GF_S_GAME_INV_ITEM_MAGNUMS }, + { O_MAGNUM_OPTION, GF_S_GAME_INV_ITEM_MAGNUMS }, + { O_UZI_ITEM, GF_S_GAME_INV_ITEM_UZIS }, + { O_UZI_OPTION, GF_S_GAME_INV_ITEM_UZIS }, + { O_HARPOON_ITEM, GF_S_GAME_INV_ITEM_HARPOON }, + { O_HARPOON_OPTION, GF_S_GAME_INV_ITEM_HARPOON }, + { O_M16_ITEM, GF_S_GAME_INV_ITEM_M16 }, + { O_M16_OPTION, GF_S_GAME_INV_ITEM_M16 }, + { O_GRENADE_ITEM, GF_S_GAME_INV_ITEM_GRENADE }, + { O_GRENADE_OPTION, GF_S_GAME_INV_ITEM_GRENADE }, + { O_PISTOL_AMMO_ITEM, GF_S_GAME_INV_ITEM_PISTOL_AMMO }, + { O_PISTOL_AMMO_OPTION, GF_S_GAME_INV_ITEM_PISTOL_AMMO }, + { O_SHOTGUN_AMMO_ITEM, GF_S_GAME_INV_ITEM_SHOTGUN_AMMO }, + { O_SHOTGUN_AMMO_OPTION, GF_S_GAME_INV_ITEM_SHOTGUN_AMMO }, + { O_MAGNUM_AMMO_ITEM, GF_S_GAME_INV_ITEM_MAGNUM_AMMO }, + { O_MAGNUM_AMMO_OPTION, GF_S_GAME_INV_ITEM_MAGNUM_AMMO }, + { O_UZI_AMMO_ITEM, GF_S_GAME_INV_ITEM_UZI_AMMO }, + { O_UZI_AMMO_OPTION, GF_S_GAME_INV_ITEM_UZI_AMMO }, + { O_HARPOON_AMMO_ITEM, GF_S_GAME_INV_ITEM_HARPOON_AMMO }, + { O_HARPOON_AMMO_OPTION, GF_S_GAME_INV_ITEM_HARPOON_AMMO }, + { O_M16_AMMO_ITEM, GF_S_GAME_INV_ITEM_M16_AMMO }, + { O_M16_AMMO_OPTION, GF_S_GAME_INV_ITEM_M16_AMMO }, + { O_GRENADE_AMMO_ITEM, GF_S_GAME_INV_ITEM_GRENADE_AMMO }, + { O_GRENADE_AMMO_OPTION, GF_S_GAME_INV_ITEM_GRENADE_AMMO }, + { O_SMALL_MEDIPACK_ITEM, GF_S_GAME_INV_ITEM_SMALL_MEDIPACK }, + { O_SMALL_MEDIPACK_OPTION, GF_S_GAME_INV_ITEM_SMALL_MEDIPACK }, + { O_LARGE_MEDIPACK_ITEM, GF_S_GAME_INV_ITEM_LARGE_MEDIPACK }, + { O_LARGE_MEDIPACK_OPTION, GF_S_GAME_INV_ITEM_LARGE_MEDIPACK }, + { O_PICKUP_ITEM_1, GF_S_GAME_INV_ITEM_PICKUP }, + { O_PICKUP_OPTION_1, GF_S_GAME_INV_ITEM_PICKUP }, + { O_PICKUP_ITEM_2, GF_S_GAME_INV_ITEM_PICKUP }, + { O_PICKUP_OPTION_2, GF_S_GAME_INV_ITEM_PICKUP }, + { O_PUZZLE_ITEM_1, GF_S_GAME_INV_ITEM_PUZZLE }, + { O_PUZZLE_OPTION_1, GF_S_GAME_INV_ITEM_PUZZLE }, + { O_PUZZLE_ITEM_2, GF_S_GAME_INV_ITEM_PUZZLE }, + { O_PUZZLE_OPTION_2, GF_S_GAME_INV_ITEM_PUZZLE }, + { O_PUZZLE_ITEM_3, GF_S_GAME_INV_ITEM_PUZZLE }, + { O_PUZZLE_OPTION_3, GF_S_GAME_INV_ITEM_PUZZLE }, + { O_PUZZLE_ITEM_4, GF_S_GAME_INV_ITEM_PUZZLE }, + { O_PUZZLE_OPTION_4, GF_S_GAME_INV_ITEM_PUZZLE }, + { O_KEY_ITEM_1, GF_S_GAME_INV_ITEM_KEY }, + { O_KEY_OPTION_1, GF_S_GAME_INV_ITEM_KEY }, + { O_KEY_ITEM_2, GF_S_GAME_INV_ITEM_KEY }, + { O_KEY_OPTION_2, GF_S_GAME_INV_ITEM_KEY }, + { O_KEY_ITEM_3, GF_S_GAME_INV_ITEM_KEY }, + { O_KEY_OPTION_3, GF_S_GAME_INV_ITEM_KEY }, + { O_KEY_ITEM_4, GF_S_GAME_INV_ITEM_KEY }, + { O_KEY_OPTION_4, GF_S_GAME_INV_ITEM_KEY }, + { O_PASSPORT_OPTION, GF_S_GAME_INV_ITEM_GAME }, + { O_PASSPORT_CLOSED, GF_S_GAME_INV_ITEM_GAME }, + { O_PHOTO_OPTION, GF_S_GAME_INV_ITEM_LARA_HOME }, + { NO_OBJECT, -1 }, + }; + + for (int32_t i = 0; game_string_defs[i].object_id != NO_OBJECT; i++) { + const char *const new_name = + g_GF_GameStrings[game_string_defs[i].game_string]; + if (new_name != NULL) { + Object_SetName(game_string_defs[i].object_id, new_name); + } + } + + struct { + GAME_OBJECT_ID object_id; + GF_PC_STRING pc_string; + } pc_string_defs[] = { + { O_DETAIL_OPTION, GF_S_PC_DETAIL_LEVELS }, + { O_SOUND_OPTION, GF_S_PC_SOUND }, + { O_CONTROL_OPTION, GF_S_PC_CONTROLS }, + { NO_OBJECT, -1 }, + }; + + for (int32_t i = 0; pc_string_defs[i].object_id != NO_OBJECT; i++) { + const char *const new_name = + g_GF_PCStrings[pc_string_defs[i].pc_string]; + if (new_name != NULL) { + Object_SetName(pc_string_defs[i].object_id, new_name); + } + } + + struct { + GAME_OBJECT_ID object_id; + char **strings; + } level_item_defs[] = { + { O_PUZZLE_ITEM_1, g_GF_Puzzle1Strings }, + { O_PUZZLE_ITEM_2, g_GF_Puzzle2Strings }, + { O_PUZZLE_ITEM_3, g_GF_Puzzle3Strings }, + { O_PUZZLE_ITEM_4, g_GF_Puzzle4Strings }, + { O_KEY_ITEM_1, g_GF_Key1Strings }, + { O_KEY_ITEM_2, g_GF_Key2Strings }, + { O_KEY_ITEM_3, g_GF_Key3Strings }, + { O_KEY_ITEM_4, g_GF_Key4Strings }, + { O_PICKUP_ITEM_1, g_GF_Pickup1Strings }, + { O_PICKUP_ITEM_2, g_GF_Pickup2Strings }, + { O_PUZZLE_OPTION_1, g_GF_Puzzle1Strings }, + { O_PUZZLE_OPTION_2, g_GF_Puzzle2Strings }, + { O_PUZZLE_OPTION_3, g_GF_Puzzle3Strings }, + { O_PUZZLE_OPTION_4, g_GF_Puzzle4Strings }, + { O_KEY_OPTION_1, g_GF_Key1Strings }, + { O_KEY_OPTION_2, g_GF_Key2Strings }, + { O_KEY_OPTION_3, g_GF_Key3Strings }, + { O_KEY_OPTION_4, g_GF_Key4Strings }, + { O_PICKUP_OPTION_1, g_GF_Pickup1Strings }, + { O_PICKUP_OPTION_2, g_GF_Pickup2Strings }, + { NO_OBJECT, NULL }, + }; + + if (level_num >= 0 && level_num < g_GameFlow.num_levels) { + for (int32_t i = 0; level_item_defs[i].object_id != NO_OBJECT; i++) { + const char *const new_name = level_item_defs[i].strings[level_num]; + if (new_name != NULL) { + Object_SetName(level_item_defs[i].object_id, new_name); + } + } + } } void Gameflow_OverrideCommand(const GAMEFLOW_COMMAND command) diff --git a/src/game/inventory/common.c b/src/game/inventory/common.c index 11faddf4..ec36b99d 100644 --- a/src/game/inventory/common.c +++ b/src/game/inventory/common.c @@ -21,6 +21,8 @@ #include "global/types.h" #include "global/vars.h" +#include + #include #define TITLE_RING_OBJECTS 3 @@ -1127,52 +1129,9 @@ void __cdecl Inv_RingIsNotOpen(RING_INFO *const ring) void __cdecl Inv_RingNotActive(const INVENTORY_ITEM *const inv_item) { if (g_Inv_ItemText[0] == NULL) { - switch (inv_item->object_id) { - case O_PASSPORT_OPTION: - break; - case O_PUZZLE_OPTION_1: - g_Inv_ItemText[0] = - Text_Create(0, -16, 0, g_GF_Puzzle1Strings[g_CurrentLevel]); - break; - case O_PUZZLE_OPTION_2: - g_Inv_ItemText[0] = - Text_Create(0, -16, 0, g_GF_Puzzle2Strings[g_CurrentLevel]); - break; - case O_PUZZLE_OPTION_3: - g_Inv_ItemText[0] = - Text_Create(0, -16, 0, g_GF_Puzzle3Strings[g_CurrentLevel]); - break; - case O_PUZZLE_OPTION_4: - g_Inv_ItemText[0] = - Text_Create(0, -16, 0, g_GF_Puzzle4Strings[g_CurrentLevel]); - break; - case O_KEY_OPTION_1: - g_Inv_ItemText[0] = - Text_Create(0, -16, 0, g_GF_Key1Strings[g_CurrentLevel]); - break; - case O_KEY_OPTION_2: - g_Inv_ItemText[0] = - Text_Create(0, -16, 0, g_GF_Key2Strings[g_CurrentLevel]); - break; - case O_KEY_OPTION_3: + if (inv_item->object_id != O_PASSPORT_OPTION) { g_Inv_ItemText[0] = - Text_Create(0, -16, 0, g_GF_Key3Strings[g_CurrentLevel]); - break; - case O_KEY_OPTION_4: - g_Inv_ItemText[0] = - Text_Create(0, -16, 0, g_GF_Key4Strings[g_CurrentLevel]); - break; - case O_PICKUP_OPTION_1: - g_Inv_ItemText[0] = - Text_Create(0, -16, 0, g_GF_Pickup1Strings[g_CurrentLevel]); - break; - case O_PICKUP_OPTION_2: - g_Inv_ItemText[0] = - Text_Create(0, -16, 0, g_GF_Pickup2Strings[g_CurrentLevel]); - break; - default: - g_Inv_ItemText[0] = Text_Create(0, -16, 0, inv_item->string); - break; + Text_Create(0, -16, 0, Object_GetName(inv_item->object_id)); } if (g_Inv_ItemText[0]) { diff --git a/src/game/objects/names.c b/src/game/objects/names.c deleted file mode 100644 index f140f7f6..00000000 --- a/src/game/objects/names.c +++ /dev/null @@ -1,143 +0,0 @@ -#include "game/objects/names.h" - -#include "game/inventory/common.h" -#include "game/objects/common.h" -#include "game/objects/vars.h" -#include "global/vars.h" - -#include -#include -#include -#include -#include - -#include -#include - -#define GOOD_MATCH_THRESHOLD 50 - -static const INVENTORY_ITEM *const m_InvItems[] = { - &g_Inv_Item_Stopwatch, &g_Inv_Item_Pistols, - &g_Inv_Item_Flare, &g_Inv_Item_Shotgun, - &g_Inv_Item_Magnums, &g_Inv_Item_Uzis, - &g_Inv_Item_Harpoon, &g_Inv_Item_M16, - &g_Inv_Item_Grenade, &g_Inv_Item_PistolAmmo, - &g_Inv_Item_ShotgunAmmo, &g_Inv_Item_MagnumAmmo, - &g_Inv_Item_UziAmmo, &g_Inv_Item_HarpoonAmmo, - &g_Inv_Item_M16Ammo, &g_Inv_Item_GrenadeAmmo, - &g_Inv_Item_SmallMedi, &g_Inv_Item_LargeMedi, - &g_Inv_Item_Pickup1, &g_Inv_Item_Pickup2, - &g_Inv_Item_Puzzle1, &g_Inv_Item_Puzzle2, - &g_Inv_Item_Puzzle3, &g_Inv_Item_Puzzle4, - &g_Inv_Item_Key1, &g_Inv_Item_Key2, - &g_Inv_Item_Key3, &g_Inv_Item_Key4, - &g_Inv_Item_Passport, &g_Inv_Item_Graphics, - &g_Inv_Item_Sound, &g_Inv_Item_Controls, - &g_Inv_Item_Photo, NULL, -}; - -static const char *m_ObjectNames[O_NUMBER_OF] = { NULL }; - -#undef OBJ_NAME_DEFINE -#define OBJ_NAME_DEFINE(id, str) str, -static const char *m_DefaultObjectNames[O_NUMBER_OF] = { -#include "game/objects/names.def" -}; - -#undef OBJ_NAME_DEFINE -#define OBJ_NAME_DEFINE(id, str) \ - { \ - QUOTE(id), \ - id, \ - }, -ENUM_STRING_MAP ENUM_STRING_MAP(GAME_OBJECT_ID)[] = { -#include "game/objects/names.def" - { NULL, -1 } -}; - -const char *Object_GetName(const GAME_OBJECT_ID object_id) -{ - // TODO: remove this in favor of changing the INVENTORY_ITEM.text directly - // clang-format off - switch (object_id) { - case O_PUZZLE_ITEM_1: return g_GF_Puzzle1Strings[g_CurrentLevel]; - case O_PUZZLE_ITEM_2: return g_GF_Puzzle2Strings[g_CurrentLevel]; - case O_PUZZLE_ITEM_3: return g_GF_Puzzle3Strings[g_CurrentLevel]; - case O_PUZZLE_ITEM_4: return g_GF_Puzzle4Strings[g_CurrentLevel]; - case O_KEY_ITEM_1: return g_GF_Key1Strings[g_CurrentLevel]; - case O_KEY_ITEM_2: return g_GF_Key2Strings[g_CurrentLevel]; - case O_KEY_ITEM_3: return g_GF_Key3Strings[g_CurrentLevel]; - case O_KEY_ITEM_4: return g_GF_Key4Strings[g_CurrentLevel]; - case O_PICKUP_ITEM_1: return g_GF_Pickup1Strings[g_CurrentLevel]; - case O_PICKUP_ITEM_2: return g_GF_Pickup2Strings[g_CurrentLevel]; - default: break; - } - // clang-format on - - return m_ObjectNames[object_id] != NULL - ? (const char *)m_ObjectNames[object_id] - : m_DefaultObjectNames[object_id]; -} - -void Object_SetName(const GAME_OBJECT_ID object_id, const char *const name) -{ - assert(object_id >= 0); - assert(object_id < O_NUMBER_OF); - Memory_FreePointer(&m_ObjectNames[object_id]); - m_ObjectNames[object_id] = Memory_DupStr(name); -} - -GAME_OBJECT_ID *Object_IdsFromName( - const char *user_input, int32_t *out_match_count, - bool (*filter)(GAME_OBJECT_ID)) -{ - VECTOR *source = Vector_Create(sizeof(STRING_FUZZY_SOURCE)); - - // Check customizable inventory strings - for (const INVENTORY_ITEM *const *item_ptr = m_InvItems; *item_ptr != NULL; - item_ptr++) { - const INVENTORY_ITEM *const item = *item_ptr; - const GAME_OBJECT_ID object_id = - Object_GetCognateInverse(item->object_id, g_ItemToInvObjectMap); - LOG_DEBUG("%d %s", object_id, item->string); - if (filter != NULL && !filter(object_id)) { - continue; - } - STRING_FUZZY_SOURCE source_item = { - .key = item->string, - .value = (void *)(intptr_t)object_id, - .weight = 1, - }; - Vector_Add(source, &source_item); - } - - // Check hardcoded object names - for (GAME_OBJECT_ID object_id = 0; object_id < O_NUMBER_OF; object_id++) { - if (filter != NULL && !filter(object_id)) { - continue; - } - STRING_FUZZY_SOURCE source_item = { - .key = Object_GetName(object_id), - .value = (void *)(intptr_t)object_id, - .weight = 1, - }; - Vector_Add(source, &source_item); - } - - VECTOR *matches = String_FuzzyMatch(user_input, source); - GAME_OBJECT_ID *results = - Memory_Alloc(sizeof(GAME_OBJECT_ID) * (matches->count + 1)); - for (int32_t i = 0; i < matches->count; i++) { - const STRING_FUZZY_MATCH *const match = Vector_Get(matches, i); - results[i] = (GAME_OBJECT_ID)(intptr_t)match->value; - } - results[matches->count] = NO_OBJECT; - if (out_match_count != NULL) { - *out_match_count = matches->count; - } - - Vector_Free(matches); - matches = NULL; - - return results; -} diff --git a/src/game/objects/names.def b/src/game/objects/names.def deleted file mode 100644 index d179d9ef..00000000 --- a/src/game/objects/names.def +++ /dev/null @@ -1,265 +0,0 @@ -OBJ_NAME_DEFINE(O_LARA, "Lara") -OBJ_NAME_DEFINE(O_LARA_PISTOLS, "Pistols Animation") -OBJ_NAME_DEFINE(O_LARA_HAIR, "Braid") -OBJ_NAME_DEFINE(O_LARA_SHOTGUN, "Shotgun Animation") -OBJ_NAME_DEFINE(O_LARA_MAGNUMS, "Magnums Animation") -OBJ_NAME_DEFINE(O_LARA_UZIS, "Uzis Animation") -OBJ_NAME_DEFINE(O_LARA_M16, "M16 Animation") -OBJ_NAME_DEFINE(O_LARA_GRENADE, "Grenade Launcher Animation") -OBJ_NAME_DEFINE(O_LARA_HARPOON, "Harpoon Animation") -OBJ_NAME_DEFINE(O_LARA_FLARE, "Flare Animation") -OBJ_NAME_DEFINE(O_LARA_SKIDOO, "Snowmobile Animation") -OBJ_NAME_DEFINE(O_LARA_BOAT, "Boat Animation") -OBJ_NAME_DEFINE(O_LARA_EXTRA, "Lara's Extra Animation") -OBJ_NAME_DEFINE(O_SKIDOO_FAST, "Red Snowmobile") -OBJ_NAME_DEFINE(O_BOAT, "Boat") -OBJ_NAME_DEFINE(O_DOG, "Dog") -OBJ_NAME_DEFINE(O_CULT_1, "Masked Goon 1") -OBJ_NAME_DEFINE(O_CULT_1A, "Masked Goon 2") -OBJ_NAME_DEFINE(O_CULT_1B, "Masked Goon 3") -OBJ_NAME_DEFINE(O_CULT_2, "Knife Thrower") -OBJ_NAME_DEFINE(O_CULT_3, "Shotgun Goon") -OBJ_NAME_DEFINE(O_MOUSE, "Rat") -OBJ_NAME_DEFINE(O_DRAGON_FRONT, "Dragon Front") -OBJ_NAME_DEFINE(O_DRAGON_BACK, "Dragon Back") -OBJ_NAME_DEFINE(O_GONDOLA, "Gondola") -OBJ_NAME_DEFINE(O_SHARK, "Shark") -OBJ_NAME_DEFINE(O_EEL, "Eel") -OBJ_NAME_DEFINE(O_BIG_EEL, "Big Eel") -OBJ_NAME_DEFINE(O_BARRACUDA, "Barracuda") -OBJ_NAME_DEFINE(O_DIVER, "Scuba Diver") -OBJ_NAME_DEFINE(O_WORKER_1, "Gunman Goon 1") -OBJ_NAME_DEFINE(O_WORKER_2, "Gunman Goon 2") -OBJ_NAME_DEFINE(O_WORKER_3, "Stick Wielding Goon 1") -OBJ_NAME_DEFINE(O_WORKER_4, "Stick Wielding Goon 2") -OBJ_NAME_DEFINE(O_WORKER_5, "Flamethrower Goon") -OBJ_NAME_DEFINE(O_JELLY, "Jellyfish") -OBJ_NAME_DEFINE(O_SPIDER, "Spider") -OBJ_NAME_DEFINE(O_BIG_SPIDER, "Giant Spider") -OBJ_NAME_DEFINE(O_CROW, "Crow") -OBJ_NAME_DEFINE(O_TIGER, "Tiger") -OBJ_NAME_DEFINE(O_BARTOLI, "Marco Bartoli") -OBJ_NAME_DEFINE(O_XIAN_SPEARMAN, "Xian Spearman") -OBJ_NAME_DEFINE(O_XIAN_SPEARMAN_STATUE, "Xian Spearman Statue") -OBJ_NAME_DEFINE(O_XIAN_KNIGHT, "Xian Knight") -OBJ_NAME_DEFINE(O_XIAN_KNIGHT_STATUE, "Xian Knight") -OBJ_NAME_DEFINE(O_YETI, "Yeti") -OBJ_NAME_DEFINE(O_GIANT_YETI, "Bird Monster") -OBJ_NAME_DEFINE(O_EAGLE, "Eagle") -OBJ_NAME_DEFINE(O_BANDIT_1, "Mercenary 1") -OBJ_NAME_DEFINE(O_BANDIT_2, "Mercenary 2") -OBJ_NAME_DEFINE(O_BANDIT_2B, "Mercenary 3") -OBJ_NAME_DEFINE(O_SKIDOO_ARMED, "Black Snowmobile") -OBJ_NAME_DEFINE(O_SKIDMAN, "Black Snowmobile Driver") -OBJ_NAME_DEFINE(O_MONK_1, "Monk 1") -OBJ_NAME_DEFINE(O_MONK_2, "Monk 2") -OBJ_NAME_DEFINE(O_FALLING_BLOCK_1, "Falling Block 1") -OBJ_NAME_DEFINE(O_FALLING_BLOCK_2, "Falling Block 2") -OBJ_NAME_DEFINE(O_FALLING_BLOCK_3, "Loose Boards") -OBJ_NAME_DEFINE(O_PENDULUM_1, "Sandbag") -OBJ_NAME_DEFINE(O_SPIKES, "Spikes") -OBJ_NAME_DEFINE(O_ROLLING_BALL_1, "Boulder 1") -OBJ_NAME_DEFINE(O_DARTS, "Disc") -OBJ_NAME_DEFINE(O_DART_EMITTER, "Disc Emitter") -OBJ_NAME_DEFINE(O_DRAWBRIDGE, "Drawbridge") -OBJ_NAME_DEFINE(O_TEETH_TRAP, "Teeth Trap") -OBJ_NAME_DEFINE(O_LIFT, "Lift") -OBJ_NAME_DEFINE(O_GENERAL, "Minisub") -OBJ_NAME_DEFINE(O_MOVABLE_BLOCK_1, "Push Block 1") -OBJ_NAME_DEFINE(O_MOVABLE_BLOCK_2, "Push Block 2") -OBJ_NAME_DEFINE(O_MOVABLE_BLOCK_3, "Push Block 3") -OBJ_NAME_DEFINE(O_MOVABLE_BLOCK_4, "Push Block 4") -OBJ_NAME_DEFINE(O_BIG_BOWL, "Lava Bowl") -OBJ_NAME_DEFINE(O_WINDOW_1, "Breakable Window 1") -OBJ_NAME_DEFINE(O_WINDOW_2, "Breakable Window 2") -OBJ_NAME_DEFINE(O_WINDOW_3, "Breakable Window 3") -OBJ_NAME_DEFINE(O_WINDOW_4, "Breakable Window 4") -OBJ_NAME_DEFINE(O_PROPELLER_1, "Airplane Propeller") -OBJ_NAME_DEFINE(O_POWER_SAW, "Power Saw") -OBJ_NAME_DEFINE(O_HOOK, "Hook") -OBJ_NAME_DEFINE(O_FALLING_CEILING, "Falling Ceiling") -OBJ_NAME_DEFINE(O_SPINNING_BLADE, "Spinning Blade") -OBJ_NAME_DEFINE(O_BLADE, "Wall-mounted Blade") -OBJ_NAME_DEFINE(O_KILLER_STATUE, "Statue with Sword") -OBJ_NAME_DEFINE(O_ROLLING_BALL_2, "Boulder 2") -OBJ_NAME_DEFINE(O_ICICLE, "Icicles") -OBJ_NAME_DEFINE(O_SPIKE_WALL, "Spike Wall") -OBJ_NAME_DEFINE(O_SPRING_BOARD, "Springboard") -OBJ_NAME_DEFINE(O_CEILING_SPIKES, "Spiky Ceiling") -OBJ_NAME_DEFINE(O_BELL, "Bell") -OBJ_NAME_DEFINE(O_WATER_SPRITE, "Boat Wake") -OBJ_NAME_DEFINE(O_SNOW_SPRITE, "Snowmobile Wale") -OBJ_NAME_DEFINE(O_SKIDOO_LARA, "Snowmobile Animation") -OBJ_NAME_DEFINE(O_SWITCH_TYPE_1, "Switch 1") -OBJ_NAME_DEFINE(O_SWITCH_TYPE_2, "Switch 2") -OBJ_NAME_DEFINE(O_PROPELLER_2, "Underwater Propeller") -OBJ_NAME_DEFINE(O_PROPELLER_3, "Air Fan") -OBJ_NAME_DEFINE(O_PENDULUM_2, "Swinging Box") -OBJ_NAME_DEFINE(O_MESH_SWAP_1, "Mesh Swap 1") -OBJ_NAME_DEFINE(O_MESH_SWAP_2, "Mesh Swap 2") -OBJ_NAME_DEFINE(O_LARA_SWAP, "Lara Mesh Swap") -OBJ_NAME_DEFINE(O_TEXT_BOX, "UI Frame") -OBJ_NAME_DEFINE(O_ROLLING_BALL_3, "Boulder 3") -OBJ_NAME_DEFINE(O_DEATH_SLIDE, "Zipline Handle") -OBJ_NAME_DEFINE(O_SWITCH_TYPE_3, "Switch 3") -OBJ_NAME_DEFINE(O_SWITCH_TYPE_4, "Switch 4") -OBJ_NAME_DEFINE(O_SWITCH_TYPE_5, "Switch 5") -OBJ_NAME_DEFINE(O_DOOR_TYPE_1, "Door 1") -OBJ_NAME_DEFINE(O_DOOR_TYPE_2, "Door 2") -OBJ_NAME_DEFINE(O_DOOR_TYPE_3, "Door 3") -OBJ_NAME_DEFINE(O_DOOR_TYPE_4, "Door 4") -OBJ_NAME_DEFINE(O_DOOR_TYPE_5, "Door 5") -OBJ_NAME_DEFINE(O_DOOR_TYPE_6, "Door 6") -OBJ_NAME_DEFINE(O_DOOR_TYPE_7, "Door 7") -OBJ_NAME_DEFINE(O_DOOR_TYPE_8, "Door 8") -OBJ_NAME_DEFINE(O_TRAPDOOR_TYPE_1, "Trapdoor 1") -OBJ_NAME_DEFINE(O_TRAPDOOR_TYPE_2, "Trapdoor 2") -OBJ_NAME_DEFINE(O_TRAPDOOR_TYPE_3, "Trapdoor 3") -OBJ_NAME_DEFINE(O_BRIDGE_FLAT, "Bridge Flat") -OBJ_NAME_DEFINE(O_BRIDGE_TILT_1, "Bridge Tilt 1") -OBJ_NAME_DEFINE(O_BRIDGE_TILT_2, "Bridge Tilt 2") -OBJ_NAME_DEFINE(O_PASSPORT_OPTION, "Passport Option") -OBJ_NAME_DEFINE(O_COMPASS_OPTION, "Compass Option") -OBJ_NAME_DEFINE(O_PHOTO_OPTION, "Photo Option") -OBJ_NAME_DEFINE(O_PLAYER_1, "Cutscene Actor 1") -OBJ_NAME_DEFINE(O_PLAYER_2, "Cutscene Actor 2") -OBJ_NAME_DEFINE(O_PLAYER_3, "Cutscene Actor 3") -OBJ_NAME_DEFINE(O_PLAYER_4, "Cutscene Actor 4") -OBJ_NAME_DEFINE(O_PLAYER_5, "Cutscene Actor 5") -OBJ_NAME_DEFINE(O_PLAYER_6, "Cutscene Actor 6") -OBJ_NAME_DEFINE(O_PLAYER_7, "Cutscene Actor 7") -OBJ_NAME_DEFINE(O_PLAYER_8, "Cutscene Actor 8") -OBJ_NAME_DEFINE(O_PLAYER_9, "Cutscene Actor 9") -OBJ_NAME_DEFINE(O_PLAYER_10, "Cutscene Actor 10") -OBJ_NAME_DEFINE(O_PASSPORT_CLOSED, "Passport Closed") -OBJ_NAME_DEFINE(O_COMPASS_ITEM, "Compass") -OBJ_NAME_DEFINE(O_PISTOL_ITEM, "Pistols") -OBJ_NAME_DEFINE(O_SHOTGUN_ITEM, "Shotgun") -OBJ_NAME_DEFINE(O_MAGNUM_ITEM, "Automatic Pistols") -OBJ_NAME_DEFINE(O_UZI_ITEM, "Uzis") -OBJ_NAME_DEFINE(O_HARPOON_ITEM, "Harpoon") -OBJ_NAME_DEFINE(O_M16_ITEM, "M16") -OBJ_NAME_DEFINE(O_GRENADE_ITEM, "Grenade Launcher") -OBJ_NAME_DEFINE(O_PISTOL_AMMO_ITEM, "Pistol Ammo") -OBJ_NAME_DEFINE(O_SHOTGUN_AMMO_ITEM, "Shotgun Ammo") -OBJ_NAME_DEFINE(O_MAGNUM_AMMO_ITEM, "Magnum Ammo") -OBJ_NAME_DEFINE(O_UZI_AMMO_ITEM, "Uzi Ammo") -OBJ_NAME_DEFINE(O_HARPOON_AMMO_ITEM, "Harpoon Ammo") -OBJ_NAME_DEFINE(O_M16_AMMO_ITEM, "M16 Ammo") -OBJ_NAME_DEFINE(O_GRENADE_AMMO_ITEM, "Grenade Launcher Ammo") -OBJ_NAME_DEFINE(O_SMALL_MEDIPACK_ITEM, "Small Medipack") -OBJ_NAME_DEFINE(O_LARGE_MEDIPACK_ITEM, "Large Medipack") -OBJ_NAME_DEFINE(O_FLARES_ITEM, "Flares Box") -OBJ_NAME_DEFINE(O_FLARE_ITEM, "Flare") -OBJ_NAME_DEFINE(O_DETAIL_OPTION, "Detail Option") -OBJ_NAME_DEFINE(O_SOUND_OPTION, "Sound Option") -OBJ_NAME_DEFINE(O_CONTROL_OPTION, "Control Option") -OBJ_NAME_DEFINE(O_GAMMA_OPTION, "Gamma Option") -OBJ_NAME_DEFINE(O_PISTOL_OPTION, "Pistol Option") -OBJ_NAME_DEFINE(O_SHOTGUN_OPTION, "Shotgun Option") -OBJ_NAME_DEFINE(O_MAGNUM_OPTION, "Magnum Option") -OBJ_NAME_DEFINE(O_UZI_OPTION, "Uzi Option") -OBJ_NAME_DEFINE(O_HARPOON_OPTION, "Harpoon Option") -OBJ_NAME_DEFINE(O_M16_OPTION, "M16 Option") -OBJ_NAME_DEFINE(O_GRENADE_OPTION, "Grenade Launcher Option") -OBJ_NAME_DEFINE(O_PISTOL_AMMO_OPTION, "Pistol Ammo Option") -OBJ_NAME_DEFINE(O_SHOTGUN_AMMO_OPTION, "Shotgun Ammo Option") -OBJ_NAME_DEFINE(O_MAGNUM_AMMO_OPTION, "Magnum Ammo Option") -OBJ_NAME_DEFINE(O_UZI_AMMO_OPTION, "Uzi Ammo Option") -OBJ_NAME_DEFINE(O_HARPOON_AMMO_OPTION, "Harpoon Ammo Option") -OBJ_NAME_DEFINE(O_M16_AMMO_OPTION, "M16 Ammo Option") -OBJ_NAME_DEFINE(O_GRENADE_AMMO_OPTION, "Grenade Launcher Ammo Option") -OBJ_NAME_DEFINE(O_SMALL_MEDIPACK_OPTION, "Small Medipack Option") -OBJ_NAME_DEFINE(O_LARGE_MEDIPACK_OPTION, "Large Medipack Option") -OBJ_NAME_DEFINE(O_FLARES_OPTION, "Flare Option") -OBJ_NAME_DEFINE(O_PUZZLE_ITEM_1, "Puzzle Item 1") -OBJ_NAME_DEFINE(O_PUZZLE_ITEM_2, "Puzzle Item 2") -OBJ_NAME_DEFINE(O_PUZZLE_ITEM_3, "Puzzle Item 3") -OBJ_NAME_DEFINE(O_PUZZLE_ITEM_4, "Puzzle Item 4") -OBJ_NAME_DEFINE(O_PUZZLE_OPTION_1, "Puzzle Option 1") -OBJ_NAME_DEFINE(O_PUZZLE_OPTION_2, "Puzzle Option 2") -OBJ_NAME_DEFINE(O_PUZZLE_OPTION_3, "Puzzle Option 3") -OBJ_NAME_DEFINE(O_PUZZLE_OPTION_4, "Puzzle Option 4") -OBJ_NAME_DEFINE(O_PUZZLE_HOLE_1, "Puzzle Hole 1 (Empty)") -OBJ_NAME_DEFINE(O_PUZZLE_HOLE_2, "Puzzle Hole 2 (Empty)") -OBJ_NAME_DEFINE(O_PUZZLE_HOLE_3, "Puzzle Hole 3 (Empty)") -OBJ_NAME_DEFINE(O_PUZZLE_HOLE_4, "Puzzle Hole 4 (Empty)") -OBJ_NAME_DEFINE(O_PUZZLE_DONE_1, "Puzzle Hole 1 (Done)") -OBJ_NAME_DEFINE(O_PUZZLE_DONE_2, "Puzzle Hole 2 (Done)") -OBJ_NAME_DEFINE(O_PUZZLE_DONE_3, "Puzzle Hole 3 (Done)") -OBJ_NAME_DEFINE(O_PUZZLE_DONE_4, "Puzzle Hole 4 (Done)") -OBJ_NAME_DEFINE(O_SECRET_1, "Secret 1") -OBJ_NAME_DEFINE(O_SECRET_2, "Secret 2") -OBJ_NAME_DEFINE(O_SECRET_3, "Secret 3") -OBJ_NAME_DEFINE(O_KEY_ITEM_1, "Key 1") -OBJ_NAME_DEFINE(O_KEY_ITEM_2, "Key 2") -OBJ_NAME_DEFINE(O_KEY_ITEM_3, "Key 3") -OBJ_NAME_DEFINE(O_KEY_ITEM_4, "Key 4") -OBJ_NAME_DEFINE(O_KEY_OPTION_1, "Key Option 1") -OBJ_NAME_DEFINE(O_KEY_OPTION_2, "Key Option 2") -OBJ_NAME_DEFINE(O_KEY_OPTION_3, "Key Option 3") -OBJ_NAME_DEFINE(O_KEY_OPTION_4, "Key Option 4") -OBJ_NAME_DEFINE(O_KEY_HOLE_1, "Key Hole 1") -OBJ_NAME_DEFINE(O_KEY_HOLE_2, "Key Hole 2") -OBJ_NAME_DEFINE(O_KEY_HOLE_3, "Key Hole 3") -OBJ_NAME_DEFINE(O_KEY_HOLE_4, "Key Hole 4") -OBJ_NAME_DEFINE(O_PICKUP_ITEM_1, "Pickup Item 1") -OBJ_NAME_DEFINE(O_PICKUP_ITEM_2, "Pickup Item 2") -OBJ_NAME_DEFINE(O_PICKUP_OPTION_1, "Pickup Option 1") -OBJ_NAME_DEFINE(O_PICKUP_OPTION_2, "Pickup Option 2") -OBJ_NAME_DEFINE(O_SPHERE_OF_DOOM_1, "Dragon Explosion 1") -OBJ_NAME_DEFINE(O_SPHERE_OF_DOOM_2, "Dragon Explosion 2") -OBJ_NAME_DEFINE(O_SPHERE_OF_DOOM_3, "Dragon Explosion 3") -OBJ_NAME_DEFINE(O_ALARM_SOUND, "Alarm") -OBJ_NAME_DEFINE(O_BIRD_TWEETER_1, "Dripping Water") -OBJ_NAME_DEFINE(O_DINO, "T-Rex") -OBJ_NAME_DEFINE(O_BIRD_TWEETER_2, "Singing Birds") -OBJ_NAME_DEFINE(O_CLOCK_CHIMES, "Bartoli Hideout clock") -OBJ_NAME_DEFINE(O_DRAGON_BONES_1, "Placeholder") -OBJ_NAME_DEFINE(O_DRAGON_BONES_2, "Dragon Bones Front") -OBJ_NAME_DEFINE(O_DRAGON_BONES_3, "Dragon Bones Back") -OBJ_NAME_DEFINE(O_HOT_LIQUID, "Extra Fire") -OBJ_NAME_DEFINE(O_BOAT_BITS, "Boat Bits") -OBJ_NAME_DEFINE(O_MINE, "Aquatic Mine") -OBJ_NAME_DEFINE(O_INV_BACKGROUND, "Menu Background") -OBJ_NAME_DEFINE(O_FX_RESERVED, "Gray disk") -OBJ_NAME_DEFINE(O_GONG_BONGER, "Gong Stick") -OBJ_NAME_DEFINE(O_DETONATOR_1, "Gong") -OBJ_NAME_DEFINE(O_DETONATOR_2, "Detonator Box") -OBJ_NAME_DEFINE(O_COPTER, "Helicopter") -OBJ_NAME_DEFINE(O_EXPLOSION, "Explosion") -OBJ_NAME_DEFINE(O_SPLASH, "Water Ripples") -OBJ_NAME_DEFINE(O_BUBBLES, "Bubbles") -OBJ_NAME_DEFINE(O_BUBBLE_EMITTER, "Bubbles Emitter") -OBJ_NAME_DEFINE(O_BLOOD, "Blood") -OBJ_NAME_DEFINE(O_DART_EFFECT, "Dart Effect") -OBJ_NAME_DEFINE(O_FLARE_FIRE, "Flare sparks") -OBJ_NAME_DEFINE(O_GLOW, "Glow") -OBJ_NAME_DEFINE(O_GLOW_RESERVED, "Map Glow") -OBJ_NAME_DEFINE(O_RICOCHET, "Ricochet") -OBJ_NAME_DEFINE(O_TWINKLE, "Sparkles") -OBJ_NAME_DEFINE(O_GUN_FLASH, "Gun Flash") -OBJ_NAME_DEFINE(O_M16_FLASH, "M16 Flash") -OBJ_NAME_DEFINE(O_BODY_PART, "Body Part") -OBJ_NAME_DEFINE(O_CAMERA_TARGET, "Camera Target") -OBJ_NAME_DEFINE(O_WATERFALL, "Waterfall") -OBJ_NAME_DEFINE(O_MISSILE_HARPOON, "Missile Harpoon") -OBJ_NAME_DEFINE(O_MISSILE_FLAME, "Missile Flame") -OBJ_NAME_DEFINE(O_MISSILE_KNIFE, "Missile Knife") -OBJ_NAME_DEFINE(O_GRENADE, "Grenade") -OBJ_NAME_DEFINE(O_HARPOON_BOLT, "Harpoon Bolt") -OBJ_NAME_DEFINE(O_EMBER, "Ember") -OBJ_NAME_DEFINE(O_EMBER_EMITTER, "Ember Emitter") -OBJ_NAME_DEFINE(O_FLAME, "Flame") -OBJ_NAME_DEFINE(O_FLAME_EMITTER, "Flame Emitter") -OBJ_NAME_DEFINE(O_SKYBOX, "Skybox") -OBJ_NAME_DEFINE(O_ALPHABET, "Alphabet") -OBJ_NAME_DEFINE(O_DYING_MONK, "Dying monk") -OBJ_NAME_DEFINE(O_DING_DONG, "Doorbell") -OBJ_NAME_DEFINE(O_LARA_ALARM, "Alarm Bell") -OBJ_NAME_DEFINE(O_MINI_COPTER, "Helicopter 2") -OBJ_NAME_DEFINE(O_WINSTON, "Winston") -OBJ_NAME_DEFINE(O_ASSAULT_DIGITS, "Assault Digits") -OBJ_NAME_DEFINE(O_FINAL_LEVEL_COUNTER, "Final Level Counter") -OBJ_NAME_DEFINE(O_CUT_SHOTGUN, "Shotgun Shower Animation") -OBJ_NAME_DEFINE(O_EARTHQUAKE, "Earthquake") diff --git a/src/game/objects/names.h b/src/game/objects/names.h deleted file mode 100644 index fcb600ad..00000000 --- a/src/game/objects/names.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "global/types.h" - -#include - -extern ENUM_STRING_MAP ENUM_STRING_MAP(GAME_OBJECT_ID)[]; - -void Object_SetupNames(void); - -const char *Object_GetName(GAME_OBJECT_ID object_id); -void Object_SetName(GAME_OBJECT_ID object_id, const char *name); - -// Return a list of object ids that match given string. -// out_match_count may be NULL. -// The result must be freed by the caller. -GAME_OBJECT_ID *Object_IdsFromName( - const char *name, int32_t *out_match_count, bool (*filter)(GAME_OBJECT_ID)); diff --git a/src/global/const.h b/src/global/const.h index fcdd4074..4ee20c9e 100644 --- a/src/global/const.h +++ b/src/global/const.h @@ -30,7 +30,6 @@ #define MIN_SQUARE SQUARE(WALL_L / 3) #define NO_BOX (-1) #define NO_ITEM (-1) -#define NO_OBJECT (-1) #define NO_ROOM 255 // TODO: merge this with NO_ROOM_NEG #define NO_ROOM_NEG (-1) #define NO_CAMERA (-1) diff --git a/src/global/enum_str.def b/src/global/enum_str.def index e69de29b..02c6835d 100644 --- a/src/global/enum_str.def +++ b/src/global/enum_str.def @@ -0,0 +1,14 @@ +// TODO: this is garbage +#ifdef ENUM_STR_IMPL +#define OBJ_NAME_DEFINE(id, str) \ + { \ + #id, \ + id, \ + }, +ENUM_STRING_MAP ENUM_STRING_MAP(GAME_OBJECT_ID)[] = { +#include + { NULL, -1 } +}; +#else +extern ENUM_STRING_MAP ENUM_STRING_MAP(GAME_OBJECT_ID)[]; +#endif diff --git a/subprojects/libtrx b/subprojects/libtrx index fd2df506..ba38d9e7 160000 --- a/subprojects/libtrx +++ b/subprojects/libtrx @@ -1 +1 @@ -Subproject commit fd2df5065b738f57bc3cbcfafcfe5d2110ecdf95 +Subproject commit ba38d9e762ea7320e896e4eb02a9e382ce55f40b diff --git a/tools/update_gameflow b/tools/update_gameflow index f7e9bb81..dff295a8 100755 --- a/tools/update_gameflow +++ b/tools/update_gameflow @@ -10,7 +10,7 @@ GAME_STRING_DEF_PATHS = [ TR2X_SRC_DIR / "game/game_string.def", LIBTRX_INCLUDE_DIR / "game/game_string.def", ] -OBJECT_STRINGS_DEF_PATH = TR2X_SRC_DIR / "game/objects/names.def" +OBJECT_STRINGS_DEF_PATH = LIBTRX_INCLUDE_DIR / "game/objects/names_tr2.def" def get_strings_map(paths: list[Path]) -> dict[str, str]: From 397a7bc363e23e5f1634bed65e4de99bd6b2120b Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Fri, 27 Sep 2024 23:49:34 +0200 Subject: [PATCH 3/3] libtrx: use new enum maps --- meson.build | 2 +- src/config_map.c | 1 - src/game/gameflow/gameflow_new.c | 10 +++++----- src/game/shell.c | 3 +++ src/global/enum_map.c | 12 ++++++++++++ src/global/enum_map.def | 0 src/global/enum_str.c | 3 --- src/global/enum_str.def | 14 -------------- src/global/enum_str.h | 11 ----------- subprojects/libtrx | 2 +- 10 files changed, 22 insertions(+), 36 deletions(-) create mode 100644 src/global/enum_map.c create mode 100644 src/global/enum_map.def delete mode 100644 src/global/enum_str.c delete mode 100644 src/global/enum_str.def delete mode 100644 src/global/enum_str.h diff --git a/meson.build b/meson.build index c87f17f3..28b6d8b5 100644 --- a/meson.build +++ b/meson.build @@ -169,7 +169,7 @@ dll_sources = [ 'src/game/ui/widgets/label.c', 'src/game/ui/widgets/prompt.c', 'src/game/ui/widgets/window.c', - 'src/global/enum_str.c', + 'src/global/enum_map.c', 'src/global/vars.c', 'src/inject_exec.c', 'src/inject_util.c', diff --git a/src/config_map.c b/src/config_map.c index a6e431fb..82a3299d 100644 --- a/src/config_map.c +++ b/src/config_map.c @@ -6,7 +6,6 @@ #include // import order guard -#include "global/enum_str.h" #include "global/types.h" const CONFIG_OPTION g_ConfigOptionMap[] = { diff --git a/src/game/gameflow/gameflow_new.c b/src/game/gameflow/gameflow_new.c index 174bb997..d8c39cf4 100644 --- a/src/game/gameflow/gameflow_new.c +++ b/src/game/gameflow/gameflow_new.c @@ -1,10 +1,10 @@ #include "game/gameflow/gameflow_new.h" #include "game/game_string.h" -#include "global/enum_str.h" #include "global/types.h" #include "global/vars.h" +#include #include #include #include @@ -21,10 +21,10 @@ static void M_LoadGameStrings(const int32_t level_num); static void M_LoadObjectString(const char *const key, const char *const value) { - const GAME_OBJECT_ID object = - ENUM_STRING_GET(GAME_OBJECT_ID, key, NO_OBJECT); - if (object != NO_OBJECT) { - Object_SetName(object, value); + const GAME_OBJECT_ID object_id = + ENUM_MAP_GET(GAME_OBJECT_ID, key, NO_OBJECT); + if (object_id != NO_OBJECT) { + Object_SetName(object_id, value); } } diff --git a/src/game/shell.c b/src/game/shell.c index 13ca488b..1f6eeee4 100644 --- a/src/game/shell.c +++ b/src/game/shell.c @@ -13,6 +13,7 @@ #include "global/funcs.h" #include "global/vars.h" +#include #include #include @@ -28,6 +29,7 @@ BOOL __cdecl Shell_Main(void) g_GameSizerCopy = 1.0; GameString_Init(); + EnumMap_Init(); Config_Init(); UI_Init(); @@ -161,6 +163,7 @@ BOOL __cdecl Shell_Main(void) S_SaveSettings(); GameBuf_Shutdown(); + EnumMap_Shutdown(); GameString_Shutdown(); return true; } diff --git a/src/global/enum_map.c b/src/global/enum_map.c new file mode 100644 index 00000000..1acba19e --- /dev/null +++ b/src/global/enum_map.c @@ -0,0 +1,12 @@ +#include +#include + +void EnumMap_Init(void) +{ +#include "global/enum_map.def" + +#undef OBJ_ID_DEFINE +#define OBJ_ID_DEFINE(object_id, value) \ + EnumMap_Define("GAME_OBJECT_ID", object_id, #object_id); +#include +} diff --git a/src/global/enum_map.def b/src/global/enum_map.def new file mode 100644 index 00000000..e69de29b diff --git a/src/global/enum_str.c b/src/global/enum_str.c deleted file mode 100644 index c516b12c..00000000 --- a/src/global/enum_str.c +++ /dev/null @@ -1,3 +0,0 @@ -#define ENUM_STR_IMPL - -#include "global/enum_str.h" diff --git a/src/global/enum_str.def b/src/global/enum_str.def deleted file mode 100644 index 02c6835d..00000000 --- a/src/global/enum_str.def +++ /dev/null @@ -1,14 +0,0 @@ -// TODO: this is garbage -#ifdef ENUM_STR_IMPL -#define OBJ_NAME_DEFINE(id, str) \ - { \ - #id, \ - id, \ - }, -ENUM_STRING_MAP ENUM_STRING_MAP(GAME_OBJECT_ID)[] = { -#include - { NULL, -1 } -}; -#else -extern ENUM_STRING_MAP ENUM_STRING_MAP(GAME_OBJECT_ID)[]; -#endif diff --git a/src/global/enum_str.h b/src/global/enum_str.h deleted file mode 100644 index 44793bf4..00000000 --- a/src/global/enum_str.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -// import order guard -#include -// import order guard - -// import order guard -#include "global/types.h" -// import order guard - -#include "global/enum_str.def" diff --git a/subprojects/libtrx b/subprojects/libtrx index ba38d9e7..3e514225 160000 --- a/subprojects/libtrx +++ b/subprojects/libtrx @@ -1 +1 @@ -Subproject commit ba38d9e762ea7320e896e4eb02a9e382ce55f40b +Subproject commit 3e51422534f81fcc3178bb9516567ed0b15b8618