console: add ability to /tp to specific items

This commit is contained in:
Marcin Kurczewski 2024-09-04 03:06:03 +02:00
parent 661d742c8d
commit 09353e32f4
No known key found for this signature in database
GPG Key ID: CC65E6FD28CAE42A
23 changed files with 1119 additions and 73 deletions

View File

@ -37,16 +37,28 @@
{},
// 11. Tibetan Foothills
{},
{
"object_strings": {
"O_TIGER": "Snow Leopard",
},
},
// 12. Barkhang Monastery
{},
// 13. Catacombs of the Talion
{},
{
"object_strings": {
"O_TIGER": "Snow Leopard",
},
},
// 14. Ice Palace
{},
{
"object_strings": {
"O_TIGER": "Snow Leopard",
},
},
// 15. Temple of Xian
{},
@ -70,6 +82,274 @@
{},
],
"object_strings": {
"O_LARA": "Lara",
"O_LARA_PISTOLS": "Pistols Animation",
"O_LARA_HAIR": "Braid",
"O_LARA_SHOTGUN": "Shotgun Animation",
"O_LARA_MAGNUMS": "Magnums Animation",
"O_LARA_UZIS": "Uzis Animation",
"O_LARA_M16": "M16 Animation",
"O_LARA_GRENADE": "Grenade Launcher Animation",
"O_LARA_HARPOON": "Harpoon Animation",
"O_LARA_FLARE": "Flare Animation",
"O_LARA_SKIDOO": "Snowmobile Animation",
"O_LARA_BOAT": "Boat Animation",
"O_LARA_EXTRA": "Lara's Extra Animation",
"O_SKIDOO_FAST": "Red Snowmobile",
"O_BOAT": "Boat",
"O_DOG": "Dog",
"O_CULT_1": "Masked Goon 1",
"O_CULT_1A": "Masked Goon 2",
"O_CULT_1B": "Masked Goon 3",
"O_CULT_2": "Knife Thrower",
"O_CULT_3": "Shotgun Goon",
"O_MOUSE": "Rat",
"O_DRAGON_FRONT": "Dragon Front",
"O_DRAGON_BACK": "Dragon Back",
"O_GONDOLA": "Gondola",
"O_SHARK": "Shark",
"O_EEL": "Eel",
"O_BIG_EEL": "Big Eel",
"O_BARRACUDA": "Barracuda",
"O_DIVER": "Scuba Diver",
"O_WORKER_1": "Gunman Goon 1",
"O_WORKER_2": "Gunman Goon 2",
"O_WORKER_3": "Stick Wielding Goon 1",
"O_WORKER_4": "Stick Wielding Goon 2",
"O_WORKER_5": "Flamethrower Goon",
"O_JELLY": "Jellyfish",
"O_SPIDER": "Spider",
"O_BIG_SPIDER": "Giant Spider",
"O_CROW": "Crow",
"O_TIGER": "Tiger",
"O_BARTOLI": "Marco Bartoli",
"O_XIAN_SPEARMAN": "Xian Spearman",
"O_XIAN_SPEARMAN_STATUE": "Xian Spearman Statue",
"O_XIAN_KNIGHT": "Xian Knight",
"O_XIAN_KNIGHT_STATUE": "Xian Knight",
"O_YETI": "Yeti",
"O_GIANT_YETI": "Bird Monster",
"O_EAGLE": "Eagle",
"O_BANDIT_1": "Mercenary 1",
"O_BANDIT_2": "Mercenary 2",
"O_BANDIT_2B": "Mercenary 3",
"O_SKIDOO_ARMED": "Black Snowmobile",
"O_SKIDMAN": "Black Snowmobile Driver",
"O_MONK_1": "Monk 1",
"O_MONK_2": "Monk 2",
"O_FALLING_BLOCK_1": "Falling Block 1",
"O_FALLING_BLOCK_2": "Falling Block 2",
"O_FALLING_BLOCK_3": "Loose Boards",
"O_PENDULUM_1": "Sandbag",
"O_SPIKES": "Spikes",
"O_ROLLING_BALL_1": "Boulder 1",
"O_DARTS": "Disc",
"O_DART_EMITTER": "Disc Emitter",
"O_DRAW_BRIDGE": "Drawbridge",
"O_TEETH_TRAP": "Teeth Trap",
"O_LIFT": "Lift",
"O_GENERAL": "Minisub",
"O_MOVABLE_BLOCK_1": "Push Block 1",
"O_MOVABLE_BLOCK_2": "Push Block 2",
"O_MOVABLE_BLOCK_3": "Push Block 3",
"O_MOVABLE_BLOCK_4": "Push Block 4",
"O_BIG_BOWL": "Lava Bowl",
"O_WINDOW_1": "Breakable Window 1",
"O_WINDOW_2": "Breakable Window 2",
"O_WINDOW_3": "Breakable Window 3",
"O_WINDOW_4": "Breakable Window 4",
"O_PROPELLER_1": "Airplane Propeller",
"O_POWER_SAW": "Power Saw",
"O_HOOK": "Hook",
"O_FALLING_CEILING": "Falling Ceiling",
"O_SPINNING_BLADE": "Spinning Blade",
"O_BLADE": "Wall-mounted Blade",
"O_KILLER_STATUE": "Statue with Sword",
"O_ROLLING_BALL_2": "Boulder 2",
"O_ICICLE": "Icicles",
"O_SPIKE_WALL": "Spike Wall",
"O_SPRING_BOARD": "Springboard",
"O_CEILING_SPIKES": "Spiky Ceiling",
"O_BELL": "Bell",
"O_WATER_SPRITE": "Boat Wake",
"O_SNOW_SPRITE": "Snowmobile Wale",
"O_SKIDOO_LARA": "Snowmobile Animation",
"O_SWITCH_TYPE_1": "Switch 1",
"O_SWITCH_TYPE_2": "Switch 2",
"O_PROPELLER_2": "Underwater Propeller",
"O_PROPELLER_3": "Air Fan",
"O_PENDULUM_2": "Swinging Box",
"O_MESH_SWAP_1": "Mesh Swap 1",
"O_MESH_SWAP_2": "Mesh Swap 2",
"O_LARA_SWAP": "Lara Mesh Swap",
"O_TEXT_BOX": "UI Frame",
"O_ROLLING_BALL_3": "Boulder 3",
"O_DEATH_SLIDE": "Zipline Handle",
"O_SWITCH_TYPE_3": "Switch 3",
"O_SWITCH_TYPE_4": "Switch 4",
"O_SWITCH_TYPE_5": "Switch 5",
"O_DOOR_TYPE_1": "Door 1",
"O_DOOR_TYPE_2": "Door 2",
"O_DOOR_TYPE_3": "Door 3",
"O_DOOR_TYPE_4": "Door 4",
"O_DOOR_TYPE_5": "Door 5",
"O_DOOR_TYPE_6": "Door 6",
"O_DOOR_TYPE_7": "Door 7",
"O_DOOR_TYPE_8": "Door 8",
"O_TRAPDOOR_TYPE_1": "Trapdoor 1",
"O_TRAPDOOR_TYPE_2": "Trapdoor 2",
"O_TRAPDOOR_TYPE_3": "Trapdoor 3",
"O_BRIDGE_FLAT": "Bridge Flat",
"O_BRIDGE_TILT_1": "Bridge Tilt 1",
"O_BRIDGE_TILT_2": "Bridge Tilt 2",
"O_PASSPORT_OPTION": "Passport Option",
"O_COMPASS_OPTION": "Compass Option",
"O_PHOTO_OPTION": "Photo Option",
"O_PLAYER_1": "Cutscene Actor 1",
"O_PLAYER_2": "Cutscene Actor 2",
"O_PLAYER_3": "Cutscene Actor 3",
"O_PLAYER_4": "Cutscene Actor 4",
"O_PLAYER_5": "Cutscene Actor 5",
"O_PLAYER_6": "Cutscene Actor 6",
"O_PLAYER_7": "Cutscene Actor 7",
"O_PLAYER_8": "Cutscene Actor 8",
"O_PLAYER_9": "Cutscene Actor 9",
"O_PLAYER_10": "Cutscene Actor 10",
"O_PASSPORT_CLOSED": "Passport Closed",
"O_COMPASS_ITEM": "Compass",
"O_PISTOL_ITEM": "Pistols",
"O_SHOTGUN_ITEM": "Shotgun",
"O_MAGNUM_ITEM": "Magnums",
"O_UZI_ITEM": "Uzis",
"O_HARPOON_ITEM": "Harpoon",
"O_M16_ITEM": "M16",
"O_GRENADE_ITEM": "Grenade Launcher",
"O_PISTOL_AMMO_ITEM": "Pistol Ammo",
"O_SHOTGUN_AMMO_ITEM": "Shotgun Ammo",
"O_MAGNUM_AMMO_ITEM": "Magnum Ammo",
"O_UZI_AMMO_ITEM": "Uzi Ammo",
"O_HARPOON_AMMO_ITEM": "Harpoon Ammo",
"O_M16_AMMO_ITEM": "M16 Ammo",
"O_GRENADE_AMMO_ITEM": "Grenade Launcher Ammo",
"O_SMALL_MEDIPACK_ITEM": "Small Medipack",
"O_LARGE_MEDIPACK_ITEM": "Large Medipack",
"O_FLARES_ITEM": "Flares Box",
"O_FLARE_ITEM": "Flare",
"O_DETAIL_OPTION": "Detail Option",
"O_SOUND_OPTION": "Sound Option",
"O_CONTROL_OPTION": "Control 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_HARPOON_OPTION": "Harpoon Option",
"O_M16_OPTION": "M16 Option",
"O_GRENADE_OPTION": "Grenade Launcher Option",
"O_PISTOL_AMMO_OPTION": "Pistol Ammo Option",
"O_SHOTGUN_AMMO_OPTION": "Shotgun Ammo Option",
"O_MAGNUM_AMMO_OPTION": "Magnum Ammo Option",
"O_UZI_AMMO_OPTION": "Uzi Ammo Option",
"O_HARPOON_AMMO_OPTION": "Harpoon Ammo Option",
"O_M16_AMMO_OPTION": "M16 Ammo Option",
"O_GRENADE_AMMO_OPTION": "Grenade Launcher Ammo Option",
"O_SMALL_MEDIPACK_OPTION": "Small Medipack Option",
"O_LARGE_MEDIPACK_OPTION": "Large Medipack Option",
"O_FLARES_OPTION": "Flare Option",
"O_PUZZLE_ITEM_1": "Puzzle Item 1",
"O_PUZZLE_ITEM_2": "Puzzle Item 2",
"O_PUZZLE_ITEM_3": "Puzzle Item 3",
"O_PUZZLE_ITEM_4": "Puzzle Item 4",
"O_PUZZLE_OPTION_1": "Puzzle Option 1",
"O_PUZZLE_OPTION_2": "Puzzle Option 2",
"O_PUZZLE_OPTION_3": "Puzzle Option 3",
"O_PUZZLE_OPTION_4": "Puzzle Option 4",
"O_PUZZLE_HOLE_1": "Puzzle Hole 1 (Empty)",
"O_PUZZLE_HOLE_2": "Puzzle Hole 2 (Empty)",
"O_PUZZLE_HOLE_3": "Puzzle Hole 3 (Empty)",
"O_PUZZLE_HOLE_4": "Puzzle Hole 4 (Empty)",
"O_PUZZLE_DONE_1": "Puzzle Hole 1 (Done)",
"O_PUZZLE_DONE_2": "Puzzle Hole 2 (Done)",
"O_PUZZLE_DONE_3": "Puzzle Hole 3 (Done)",
"O_PUZZLE_DONE_4": "Puzzle Hole 4 (Done)",
"O_SECRET_1": "Secret 1",
"O_SECRET_2": "Secret 2",
"O_SECRET_3": "Secret 3",
"O_KEY_ITEM_1": "Key 1",
"O_KEY_ITEM_2": "Key 2",
"O_KEY_ITEM_3": "Key 3",
"O_KEY_ITEM_4": "Key 4",
"O_KEY_OPTION_1": "Key Option 1",
"O_KEY_OPTION_2": "Key Option 2",
"O_KEY_OPTION_3": "Key Option 3",
"O_KEY_OPTION_4": "Key Option 4",
"O_KEY_HOLE_1": "Key Hole 1",
"O_KEY_HOLE_2": "Key Hole 2",
"O_KEY_HOLE_3": "Key Hole 3",
"O_KEY_HOLE_4": "Key Hole 4",
"O_PICKUP_ITEM_1": "Pickup Item 1",
"O_PICKUP_ITEM_2": "Pickup Item 2",
"O_PICKUP_OPTION_1": "Pickup Option 1",
"O_PICKUP_OPTION_2": "Pickup Option 2",
"O_SPHERE_OF_DOOM_1": "Dragon Explosion 1",
"O_SPHERE_OF_DOOM_2": "Dragon Explosion 2",
"O_SPHERE_OF_DOOM_3": "Dragon Explosion 3",
"O_ALARM_SOUND": "Alarm",
"O_BIRD_TWEETER_1": "Dripping Water",
"O_DINO": "T-Rex",
"O_BIRD_TWEETER_2": "Singing Birds",
"O_CLOCK_CHIMES": "Bartoli Hideout clock",
"O_DRAGON_BONES_1": "Placeholder",
"O_DRAGON_BONES_2": "Dragon Bones Front",
"O_DRAGON_BONES_3": "Dragon Bones Back",
"O_HOT_LIQUID": "Extra Fire",
"O_BOAT_BITS": "Boat Bits",
"O_MINE": "Aquatic Mine",
"O_INV_BACKGROUND": "Menu Background",
"O_FX_RESERVED": "Gray disk",
"O_GONG_BONGER": "Gong Stick",
"O_DETONATOR_1": "Gong",
"O_DETONATOR_2": "Detonator Box",
"O_COPTER": "Helicopter",
"O_EXPLOSION": "Explosion",
"O_SPLASH": "Water Ripples",
"O_BUBBLES": "Bubbles",
"O_BUBBLE_EMITTER": "Bubbles Emitter",
"O_BLOOD": "Blood",
"O_DART_EFFECT": "Dart Effect",
"O_FLARE_FIRE": "Flare sparks",
"O_GLOW": "Glow",
"O_GLOW_RESERVED": "Map Glow",
"O_RICOCHET": "Ricochet",
"O_TWINKLE": "Sparkles",
"O_GUN_FLASH": "Gun Flash",
"O_M16_FLASH": "M16 Flash",
"O_BODY_PART": "Body Part",
"O_CAMERA_TARGET": "Camera Target",
"O_WATERFALL": "Waterfall",
"O_MISSILE_HARPOON": "Missile Harpoon",
"O_MISSILE_FLAME": "Missile Flame",
"O_MISSILE_KNIFE": "Missile Knife",
"O_GRENADE": "Grenade",
"O_HARPOON_BOLT": "Harpoon Bolt",
"O_LAVA": "Lava",
"O_LAVA_EMITTER": "Lava Emitter",
"O_FLAME": "Flame",
"O_FLAME_EMITTER": "Flame Emitter",
"O_SKYBOX": "Skybox",
"O_ALPHABET": "Alphabet",
"O_DYING_MONK": "Dying monk",
"O_DING_DONG": "Doorbell",
"O_LARA_ALARM": "Alarm Bell",
"O_MINI_COPTER": "Helicopter 2",
"O_WINSTON": "Winston",
"O_ASSAULT_DIGITS": "Assault Digits",
"O_FINAL_LEVEL_COUNTER": "Final Level Counter",
"O_CUT_SHOTGUN": "Shotgun Shower Animation",
"O_EARTHQUAKE": "Earthquake",
},
"game_strings": {
"OSD_FLY_MODE_ON": "Fly mode enabled",
"OSD_FLY_MODE_OFF": "Fly mode disabled",

View File

@ -2061,15 +2061,15 @@ typedef enum {
O_WORKER_4 = 33,
O_WORKER_5 = 34,
O_JELLY = 35,
O_SPIDER_or_WOLF = 36,
O_BIG_SPIDER_or_BEAR = 37,
O_SPIDER = 36,
O_BIG_SPIDER = 37,
O_CROW = 38,
O_TIGER = 39,
O_BARTOLI = 40,
O_XIAN_LORD = 41,
O_CHINESE_2 = 42,
O_WARRIOR = 43,
O_CHINESE_4 = 44,
O_XIAN_SPEARMAN = 41,
O_XIAN_SPEARMAN_STATUE = 42,
O_XIAN_KNIGHT = 43,
O_XIAN_KNIGHT_STATUE = 44,
O_YETI = 45,
O_GIANT_YETI = 46,
O_EAGLE = 47,
@ -2102,7 +2102,7 @@ typedef enum {
O_WINDOW_3 = 74,
O_WINDOW_4 = 75,
O_PROPELLER_1 = 76,
O_PROPELLER_2 = 77,
O_POWER_SAW = 77,
O_HOOK = 78,
O_FALLING_CEILING = 79,
O_SPINNING_BLADE = 80,
@ -2119,8 +2119,8 @@ typedef enum {
O_SKIDOO_LARA = 91,
O_SWITCH_TYPE_1 = 92,
O_SWITCH_TYPE_2 = 93,
O_PROPELLER_3 = 94,
O_PROPELLER_4 = 95,
O_PROPELLER_2 = 94,
O_PROPELLER_3 = 95,
O_PENDULUM_2 = 96,
O_MESH_SWAP_1 = 97,
O_MESH_SWAP_2 = 98,

View File

@ -118,6 +118,7 @@ dll_sources = [
'src/game/objects/creatures/diver.c',
'src/game/objects/general/door.c',
'src/game/objects/general/final_level_counter.c',
'src/game/objects/names.c',
'src/game/objects/vars.c',
'src/game/objects/vehicles/boat.c',
'src/game/option/option.c',

View File

@ -4,6 +4,9 @@
#include "game/game_string.h"
#include "game/items.h"
#include "game/lara/lara_cheat.h"
#include "game/objects/common.h"
#include "game/objects/names.h"
#include "game/objects/vars.h"
#include "game/random.h"
#include "game/room.h"
#include "game/sound.h"
@ -70,7 +73,7 @@ static COMMAND_RESULT Console_Cmd_Teleport(const char *const args)
z += 0.5f;
}
if (Item_Teleport(g_LaraItem, x * WALL_L, y * WALL_L, z * WALL_L)) {
if (Lara_Cheat_Teleport(x * WALL_L, y * WALL_L, z * WALL_L)) {
Console_Log(GS(OSD_POS_SET_POS), x, y, z);
return CR_SUCCESS;
}
@ -104,7 +107,7 @@ static COMMAND_RESULT Console_Cmd_Teleport(const char *const args)
int32_t x = x1 + Random_GetControl() * (x2 - x1) / 0x7FFF;
int32_t y = y1;
int32_t z = z1 + Random_GetControl() * (z2 - z1) / 0x7FFF;
if (Item_Teleport(g_LaraItem, x, y, z)) {
if (Lara_Cheat_Teleport(x, y, z)) {
Console_Log(GS(OSD_POS_SET_ROOM), room_num);
return CR_SUCCESS;
}
@ -115,6 +118,65 @@ static COMMAND_RESULT Console_Cmd_Teleport(const char *const args)
}
}
// Nearest item of this name
if (!String_Equivalent(args, "")) {
int32_t match_count = 0;
GAME_OBJECT_ID *matching_objs = Object_IdsFromName(args, &match_count);
const ITEM_INFO *best_item = NULL;
int32_t best_distance = INT32_MAX;
for (int16_t item_num = 0; item_num < Item_GetTotalCount();
item_num++) {
const ITEM_INFO *const item = &g_Items[item_num];
const bool is_pickup =
Object_IsObjectType(item->object_num, g_PickupObjects);
if (is_pickup
&& (item->status == IS_INVISIBLE
|| item->status == IS_DEACTIVATED)) {
continue;
}
if (item->flags & IF_KILLED) {
continue;
}
bool is_matched = false;
for (int32_t i = 0; i < match_count; i++) {
if (matching_objs[i] == item->object_num) {
is_matched = true;
break;
}
}
if (!is_matched) {
continue;
}
const int32_t distance = Item_GetDistance(item, &g_LaraItem->pos);
if (distance < best_distance) {
best_distance = distance;
best_item = item;
}
}
if (best_item != NULL) {
if (Lara_Cheat_Teleport(
best_item->pos.x, best_item->pos.y, best_item->pos.z)) {
Console_Log(
GS(OSD_POS_SET_ITEM),
Object_GetName(best_item->object_num));
} else {
Console_Log(
GS(OSD_POS_SET_ITEM_FAIL),
Object_GetName(best_item->object_num));
}
return CR_SUCCESS;
} else {
Console_Log(GS(OSD_POS_SET_ITEM_FAIL), args);
return CR_FAILURE;
}
}
return CR_BAD_INVOCATION;
}

View File

@ -5,6 +5,7 @@
#include "game/demo.h"
#include "game/game.h"
#include "game/gun/gun.h"
#include "game/objects/names.h"
#include "game/overlay.h"
#include "gameflow/gameflow_new.h"
#include "global/funcs.h"

View File

@ -1,6 +1,7 @@
#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"
@ -8,9 +9,21 @@
GAMEFLOW_NEW g_GameflowNew;
static void GF_N_LoadObjectString(const char *key, const char *value);
static void GF_N_LoadGameString(const char *key, const char *value);
static void GF_N_LoadObjectStrings(const int32_t level_num);
static void GF_N_LoadGameStrings(const int32_t level_num);
static void GF_N_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);
}
}
static void GF_N_LoadGameString(const char *const key, const char *const value)
{
const GAME_STRING_ID game_string =
@ -20,6 +33,27 @@ static void GF_N_LoadGameString(const char *const key, const char *const value)
}
}
static void GF_N_LoadObjectStrings(const int32_t level_num)
{
const GAMEFLOW_NEW *const gf = &g_GameflowNew;
const GAMEFLOW_NEW_STRING_ENTRY *entry = gf->object_strings;
while (entry != NULL && entry->key != NULL) {
GF_N_LoadObjectString(entry->key, entry->value);
entry++;
}
if (level_num >= 0) {
assert(level_num < gf->level_count);
const GAMEFLOW_NEW_LEVEL *const level = &gf->levels[level_num];
entry = level->object_strings;
while (entry != NULL && entry->key != NULL) {
GF_N_LoadObjectString(entry->key, entry->value);
entry++;
}
}
}
static void GF_N_LoadGameStrings(const int32_t level_num)
{
const GAMEFLOW_NEW *const gf = &g_GameflowNew;
@ -43,5 +77,6 @@ static void GF_N_LoadGameStrings(const int32_t level_num)
void GF_N_LoadStrings(const int32_t level_num)
{
GF_N_LoadObjectStrings(level_num);
GF_N_LoadGameStrings(level_num);
}

View File

@ -105,6 +105,8 @@ static bool GF_N_LoadScriptLevels(
goto end;
}
result &= GF_N_LoadStringTable(
jlvl_obj, "object_strings", &level->object_strings);
result &= GF_N_LoadStringTable(
jlvl_obj, "game_strings", &level->game_strings);
}
@ -141,6 +143,8 @@ bool GF_N_Load(const char *const path)
GAMEFLOW_NEW *const gf = &g_GameflowNew;
struct json_object_s *root_obj = json_value_as_object(root);
result &=
GF_N_LoadStringTable(root_obj, "object_strings", &gf->object_strings);
result &= GF_N_LoadStringTable(root_obj, "game_strings", &gf->game_strings);
result &= GF_N_LoadScriptLevels(root_obj, gf);
@ -163,8 +167,10 @@ void GF_N_Shutdown(void)
GAMEFLOW_NEW *const gf = &g_GameflowNew;
for (int32_t i = 0; i < gf->level_count; i++) {
GF_N_StringTableShutdown(gf->levels[i].object_strings);
GF_N_StringTableShutdown(gf->levels[i].game_strings);
}
GF_N_StringTableShutdown(gf->object_strings);
GF_N_StringTableShutdown(gf->game_strings);
}

View File

@ -1,6 +1,5 @@
#include "game/items.h"
#include "game/camera.h"
#include "game/math.h"
#include "game/matrix.h"
#include "game/room.h"
@ -13,6 +12,7 @@
#include <assert.h>
static int16_t m_MaxUsedItemCount = 0;
static BOUNDS_16 m_InterpolatedBounds = { 0 };
static OBJECT_BOUNDS Item_ConvertBounds(const int16_t *bounds_in);
@ -55,6 +55,7 @@ void __cdecl Item_InitialiseArray(const int32_t num_items)
g_NextItemFree = g_LevelItemCount;
g_PrevItemActive = NO_ITEM;
g_NextItemActive = NO_ITEM;
m_MaxUsedItemCount = g_LevelItemCount;
for (int32_t i = g_NextItemFree; i < num_items - 1; i++) {
ITEM_INFO *const item = &g_Items[i];
item->active = 0;
@ -63,14 +64,20 @@ void __cdecl Item_InitialiseArray(const int32_t num_items)
g_Items[num_items - 1].next_item = NO_ITEM;
}
int32_t Item_GetTotalCount(void)
{
return m_MaxUsedItemCount;
}
int16_t __cdecl Item_Create(void)
{
const int16_t result = g_NextItemFree;
if (result != NO_ITEM) {
g_Items[result].flags = 0;
g_NextItemFree = g_Items[result].next_item;
const int16_t item_num = g_NextItemFree;
if (item_num != NO_ITEM) {
g_Items[item_num].flags = 0;
g_NextItemFree = g_Items[item_num].next_item;
}
return result;
m_MaxUsedItemCount = MAX(m_MaxUsedItemCount, item_num + 1);
return item_num;
}
void __cdecl Item_Kill(const int16_t item_num)
@ -89,6 +96,11 @@ void __cdecl Item_Kill(const int16_t item_num)
item->next_item = g_NextItemFree;
g_NextItemFree = item_num;
}
while (m_MaxUsedItemCount > 0
&& g_Items[m_MaxUsedItemCount - 1].flags & IF_KILLED) {
m_MaxUsedItemCount--;
}
}
void __cdecl Item_Initialise(const int16_t item_num)
@ -279,32 +291,6 @@ void __cdecl Item_ClearKilled(void)
g_PrevItemActive = NO_ITEM;
}
bool __cdecl Item_Teleport(ITEM_INFO *item, int32_t x, int32_t y, int32_t z)
{
int16_t room_num = Room_GetIndexFromPos(x, y, z);
if (room_num == NO_ROOM) {
return false;
}
SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
const int16_t height = Room_GetHeight(sector, x, y, z);
if (height != NO_HEIGHT) {
item->pos.x = x;
item->pos.y = y;
item->pos.z = z;
item->floor = height;
if (item->room_num != room_num) {
const int16_t item_num = item - g_Items;
Item_NewRoom(item_num, room_num);
}
if (item->object_num == O_LARA) {
Camera_ResetPosition();
}
return true;
}
return false;
}
bool Item_IsSmashable(const ITEM_INFO *item)
{
return (item->object_num == O_WINDOW_1 || item->object_num == O_BELL);
@ -751,3 +737,12 @@ void Item_TakeDamage(
item->hit_status = 1;
}
}
int32_t Item_GetDistance(
const ITEM_INFO *const item, const XYZ_32 *const target)
{
const int32_t x = (item->pos.x - target->x);
const int32_t y = (item->pos.y - target->y);
const int32_t z = (item->pos.z - target->z);
return Math_Sqrt(SQUARE(x) + SQUARE(y) + SQUARE(z));
}

View File

@ -3,6 +3,7 @@
#include "global/types.h"
void __cdecl Item_InitialiseArray(int32_t num_items);
int32_t Item_GetTotalCount(void);
int16_t __cdecl Item_Create(void);
void __cdecl Item_Kill(int16_t item_num);
void __cdecl Item_Initialise(int16_t item_num);
@ -13,7 +14,6 @@ void __cdecl Item_NewRoom(int16_t item_num, int16_t room_num);
int32_t __cdecl Item_GlobalReplace(
int32_t src_object_num, int32_t dst_object_num);
void __cdecl Item_ClearKilled(void);
bool Item_Teleport(ITEM_INFO *item, int32_t x, int32_t y, int32_t z);
void __cdecl Item_ShiftCol(ITEM_INFO *item, COLL_INFO *coll);
void __cdecl Item_UpdateRoom(ITEM_INFO *item, int32_t height);
int32_t __cdecl Item_TestBoundsCollide(
@ -36,3 +36,4 @@ bool __cdecl Item_IsNearItem(
bool Item_IsSmashable(const ITEM_INFO *item);
void Item_TakeDamage(ITEM_INFO *item, int16_t damage, bool hit_status);
int32_t Item_GetDistance(const ITEM_INFO *item, const XYZ_32 *target);

View File

@ -1,14 +1,21 @@
#include "game/lara/lara_cheat.h"
#include "game/camera.h"
#include "game/console.h"
#include "game/game_string.h"
#include "game/inventory.h"
#include "game/items.h"
#include "game/lara/lara_control.h"
#include "game/math.h"
#include "game/output.h"
#include "game/room.h"
#include "global/funcs.h"
#include "global/utils.h"
#include "global/vars.h"
#include <libtrx/utils.h>
#include <libtrx/vector.h>
void __cdecl Lara_Cheat_EndLevel(void)
{
g_LevelComplete = true;
@ -21,6 +28,8 @@ bool __cdecl Lara_Cheat_EnterFlyMode(void)
return false;
}
Lara_GetOffVehicle();
if (g_Lara.water_status != LWS_UNDERWATER || g_LaraItem->hit_points <= 0) {
g_LaraItem->pos.y -= STEP_L;
g_LaraItem->current_anim_state = LS_SWIM;
@ -37,13 +46,6 @@ bool __cdecl Lara_Cheat_EnterFlyMode(void)
g_Lara.torso_y_rot = 0;
}
if (g_Lara.skidoo != NO_ITEM) {
ITEM_INFO *const vehicle = &g_Items[g_Lara.skidoo];
vehicle->anim_num = g_Objects[vehicle->object_num].anim_idx;
vehicle->frame_num = g_Anims[vehicle->anim_num].frame_base;
g_Lara.skidoo = NO_ITEM;
}
g_Lara.water_status = LWS_CHEAT;
g_Lara.spaz_effect_count = 0;
g_Lara.spaz_effect = NULL;
@ -114,3 +116,89 @@ void __cdecl Lara_Cheat_GetStuff(void)
g_Lara.m16_ammo.ammo = 300;
g_Lara.grenade_ammo.ammo = 300;
}
bool Lara_Cheat_Teleport(int32_t x, int32_t y, int32_t z)
{
int16_t room_num = Room_GetIndexFromPos(x, y, z);
if (room_num == NO_ROOM) {
return false;
}
const SECTOR_INFO *sector = Room_GetSector(x, y, z, &room_num);
int16_t height = Room_GetHeight(sector, x, y, z);
if (height == NO_HEIGHT) {
// Sample a sphere of points around target x, y, z
// and teleport to the first available location.
VECTOR *const points = Vector_Create(sizeof(XYZ_32));
const int32_t radius = 10;
const int32_t unit = STEP_L;
for (int32_t dx = -radius; dx <= radius; dx++) {
for (int32_t dz = -radius; dz <= radius; dz++) {
if (SQUARE(dx) + SQUARE(dz) > SQUARE(radius)) {
continue;
}
const XYZ_32 point = {
.x = ROUND_TO_SECTOR(x + dx * unit) + WALL_L / 2,
.y = y,
.z = ROUND_TO_SECTOR(z + dz * unit) + WALL_L / 2,
};
room_num = Room_GetIndexFromPos(point.x, point.y, point.z);
if (room_num == NO_ROOM) {
continue;
}
sector = Room_GetSector(point.x, point.y, point.z, &room_num);
height = Room_GetHeight(sector, point.x, point.y, point.z);
if (height == NO_HEIGHT) {
continue;
}
Vector_Add(points, (void *)&point);
}
}
int32_t best_distance = INT32_MAX;
for (int32_t i = 0; i < points->count; i++) {
const XYZ_32 *const point = (const XYZ_32 *)Vector_Get(points, i);
const int32_t distance =
XYZ_32_GetDistance(point, &g_LaraItem->pos);
if (distance < best_distance) {
best_distance = distance;
x = point->x;
y = point->y;
z = point->z;
}
}
Vector_Free(points);
if (best_distance == INT32_MAX) {
return false;
}
}
room_num = Room_GetIndexFromPos(x, y, z);
if (room_num == NO_ROOM) {
return false;
}
sector = Room_GetSector(x, y, z, &room_num);
height = Room_GetHeight(sector, x, y, z);
if (height == NO_HEIGHT) {
return false;
}
g_LaraItem->pos.x = x;
g_LaraItem->pos.y = y;
g_LaraItem->pos.z = z;
g_LaraItem->floor = height;
Lara_GetOffVehicle();
if (g_LaraItem->room_num != room_num) {
const int16_t item_num = g_LaraItem - g_Items;
Item_NewRoom(item_num, room_num);
}
Camera_ResetPosition();
return true;
}

View File

@ -1,8 +1,10 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
void __cdecl Lara_Cheat_EndLevel(void);
bool __cdecl Lara_Cheat_EnterFlyMode(void);
bool __cdecl Lara_Cheat_ExitFlyMode(void);
void __cdecl Lara_Cheat_GetStuff(void);
bool Lara_Cheat_Teleport(int32_t x, int32_t y, int32_t z);

View File

@ -952,3 +952,18 @@ void Lara_SwapSingleMesh(const LARA_MESH mesh, const GAME_OBJECT_ID object_id)
{
g_Lara.mesh_ptrs[mesh] = g_Meshes[g_Objects[object_id].mesh_idx + mesh];
}
void Lara_GetOffVehicle(void)
{
if (g_Lara.skidoo != NO_ITEM) {
ITEM_INFO *const vehicle = &g_Items[g_Lara.skidoo];
vehicle->anim_num = g_Objects[vehicle->object_num].anim_idx;
vehicle->frame_num = g_Anims[vehicle->anim_num].frame_base;
g_Lara.skidoo = NO_ITEM;
g_LaraItem->current_anim_state = LS_STOP;
g_LaraItem->goal_anim_state = LS_STOP;
g_LaraItem->anim_num = LA_STAND_STILL;
g_LaraItem->frame_num = g_Anims[g_LaraItem->anim_num].frame_base;
}
}

View File

@ -23,4 +23,5 @@ void __cdecl Lara_InitialiseInventory(int32_t level_num);
void __cdecl Lara_InitialiseMeshes(int32_t level_num);
void Lara_GetOffVehicle(void);
void Lara_SwapSingleMesh(LARA_MESH mesh, GAME_OBJECT_ID);

View File

@ -641,7 +641,7 @@ static void __cdecl Level_LoadBoxes(VFILE *const file)
for (int32_t i = 0; i < 2; i++) {
for (int32_t j = 0; j < 4; j++) {
const bool skip = j == 2
|| (j == 1 && !g_Objects[O_SPIDER_or_WOLF].loaded
|| (j == 1 && !g_Objects[O_SPIDER].loaded
&& !g_Objects[O_SKIDOO_ARMED].loaded)
|| (j == 3 && !g_Objects[O_YETI].loaded
&& !g_Objects[O_WORKER_3].loaded);

View File

@ -149,7 +149,7 @@ void __cdecl LOT_InitialiseSlot(const int16_t item_num, const int32_t slot)
creature->lot.drop = -WALL_L;
break;
case O_SPIDER_or_WOLF:
case O_SPIDER:
case O_SKIDOO_ARMED:
creature->lot.step = WALL_L / 2;
creature->lot.drop = -WALL_L;

218
src/game/objects/names.c Normal file
View File

@ -0,0 +1,218 @@
#include "game/objects/names.h"
#include "game/inventory.h"
#include "game/objects/common.h"
#include "game/objects/vars.h"
#include "global/vars.h"
#include <libtrx/log.h>
#include <libtrx/memory.h>
#include <libtrx/strings.h>
#include <libtrx/utils.h>
#include <libtrx/vector.h>
#include <assert.h>
#include <string.h>
#define GOOD_MATCH_THRESHOLD 50
typedef struct {
int32_t score;
GAME_OBJECT_ID obj_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,
&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 }
};
static int32_t Object_NameMatch(const char *user_input, const char *name);
static void Object_TryMatch(
VECTOR *matches, const char *user_input, const char *name,
GAME_OBJECT_ID obj_id);
static int32_t Object_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(&regex);
return score;
}
static void Object_TryMatch(
VECTOR *const matches, const char *const user_input, const char *const name,
const GAME_OBJECT_ID obj_id)
{
const int32_t score = Object_NameMatch(user_input, name);
if (score > 0) {
MATCH match = {
.score = score,
.obj_id = obj_id,
};
Vector_Add(matches, &match);
}
}
const char *Object_GetName(const GAME_OBJECT_ID obj_id)
{
// TODO: remove this in favor of changing the INVENTORY_ITEM.text directly
// clang-format off
switch (obj_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[obj_id] != NULL ? (const char *)m_ObjectNames[obj_id]
: m_DefaultObjectNames[obj_id];
}
void Object_SetName(const GAME_OBJECT_ID obj_id, const char *const name)
{
assert(obj_id >= 0);
assert(obj_id < O_NUMBER_OF);
Memory_FreePointer(&m_ObjectNames[obj_id]);
m_ObjectNames[obj_id] = Memory_DupStr(name);
}
GAME_OBJECT_ID *Object_IdsFromName(
const char *user_input, int32_t *out_match_count)
{
// first, calculate the number of matches to allocate
VECTOR *matches = Vector_Create(sizeof(MATCH));
// Store matches from 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 obj_id =
Object_GetCognateInverse(item->obj_num, g_ItemToInvObjectMap);
Object_TryMatch(matches, user_input, item->string, obj_id);
}
// Store matches from hardcoded strings
for (GAME_OBJECT_ID obj_id = 0; obj_id < O_NUMBER_OF; obj_id++) {
Object_TryMatch(matches, user_input, Object_GetName(obj_id), obj_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->obj_id), match->score);
}
// Make sure the returned matching object ids are unique
GAME_OBJECT_ID *unique_ids =
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->obj_id == unique_ids[j]) {
is_unique = false;
break;
}
}
if (is_unique) {
unique_ids[unique_count++] = match->obj_id;
}
}
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;
}

265
src/game/objects/names.def Normal file
View File

@ -0,0 +1,265 @@
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_DRAW_BRIDGE, "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, "Magnums")
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_LAVA, "Lava")
OBJ_NAME_DEFINE(O_LAVA_EMITTER, "Lava 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")

19
src/game/objects/names.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include "global/types.h"
#include <libtrx/enum_str.h>
#include <stdint.h>
extern ENUM_STRING_MAP ENUM_STRING_MAP(GAME_OBJECT_ID)[];
void Object_SetupNames(void);
const char *Object_GetName(GAME_OBJECT_ID obj_id);
void Object_SetName(GAME_OBJECT_ID obj_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);

View File

@ -24,15 +24,15 @@ const GAME_OBJECT_ID g_EnemyObjects[] = {
O_WORKER_4,
O_WORKER_5,
O_JELLY,
O_SPIDER_or_WOLF,
O_BIG_SPIDER_or_BEAR,
O_SPIDER,
O_BIG_SPIDER,
O_CROW,
O_TIGER,
O_BARTOLI,
O_XIAN_LORD,
O_CHINESE_2,
O_WARRIOR,
O_CHINESE_4,
O_XIAN_SPEARMAN,
O_XIAN_SPEARMAN_STATUE,
O_XIAN_KNIGHT,
O_XIAN_KNIGHT_STATUE,
O_YETI,
O_GIANT_YETI,
O_EAGLE,
@ -55,6 +55,42 @@ const GAME_OBJECT_ID g_FriendObjects[] = {
// clang-format on
};
const GAME_OBJECT_ID g_PickupObjects[] = {
// clang-format off
O_PISTOL_ITEM,
O_SHOTGUN_ITEM,
O_MAGNUM_ITEM,
O_UZI_ITEM,
O_HARPOON_ITEM,
O_M16_ITEM,
O_GRENADE_ITEM,
O_PISTOL_AMMO_ITEM,
O_SHOTGUN_AMMO_ITEM,
O_MAGNUM_AMMO_ITEM,
O_UZI_AMMO_ITEM,
O_HARPOON_AMMO_ITEM,
O_M16_AMMO_ITEM,
O_GRENADE_AMMO_ITEM,
O_SMALL_MEDIPACK_ITEM,
O_LARGE_MEDIPACK_ITEM,
O_FLARES_ITEM,
O_PUZZLE_ITEM_1,
O_PUZZLE_ITEM_2,
O_PUZZLE_ITEM_3,
O_PUZZLE_ITEM_4,
O_KEY_ITEM_1,
O_KEY_ITEM_2,
O_KEY_ITEM_3,
O_KEY_ITEM_4,
O_PICKUP_ITEM_1,
O_PICKUP_ITEM_2,
O_SECRET_1,
O_SECRET_2,
O_SECRET_3,
NO_OBJECT,
// clang-format on
};
const GAME_OBJECT_ID g_InvObjects[] = {
// clang-format off
O_PISTOL_OPTION,

View File

@ -6,4 +6,5 @@
extern const GAME_OBJECT_ID g_EnemyObjects[];
extern const GAME_OBJECT_ID g_FriendObjects[];
extern const GAME_OBJECT_ID g_InvObjects[];
extern const GAME_OBJECT_ID g_PickupObjects[];
extern const GAME_OBJECT_PAIR g_ItemToInvObjectMap[];

View File

@ -2077,15 +2077,15 @@ typedef enum {
O_WORKER_4 = 33,
O_WORKER_5 = 34,
O_JELLY = 35,
O_SPIDER_or_WOLF = 36,
O_BIG_SPIDER_or_BEAR = 37,
O_SPIDER = 36,
O_BIG_SPIDER = 37,
O_CROW = 38,
O_TIGER = 39,
O_BARTOLI = 40,
O_XIAN_LORD = 41,
O_CHINESE_2 = 42,
O_WARRIOR = 43,
O_CHINESE_4 = 44,
O_XIAN_SPEARMAN = 41,
O_XIAN_SPEARMAN_STATUE = 42,
O_XIAN_KNIGHT = 43,
O_XIAN_KNIGHT_STATUE = 44,
O_YETI = 45,
O_GIANT_YETI = 46,
O_EAGLE = 47,
@ -2118,7 +2118,7 @@ typedef enum {
O_WINDOW_3 = 74,
O_WINDOW_4 = 75,
O_PROPELLER_1 = 76,
O_PROPELLER_2 = 77,
O_POWER_SAW = 77,
O_HOOK = 78,
O_FALLING_CEILING = 79,
O_SPINNING_BLADE = 80,
@ -2135,8 +2135,8 @@ typedef enum {
O_SKIDOO_LARA = 91,
O_SWITCH_TYPE_1 = 92,
O_SWITCH_TYPE_2 = 93,
O_PROPELLER_3 = 94,
O_PROPELLER_4 = 95,
O_PROPELLER_2 = 94,
O_PROPELLER_3 = 95,
O_PENDULUM_2 = 96,
O_MESH_SWAP_1 = 97,
O_MESH_SWAP_2 = 98,

6
src/global/utils.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include "global/const.h"
#define ROUND_TO_CLICK(V) ((V) & ~(STEP_L - 1))
#define ROUND_TO_SECTOR(V) ((V) & ~(WALL_L - 1))

View File

@ -18,7 +18,19 @@ def get_string_map(path: Path) -> dict[str, str]:
return result
def postprocess_gameflow(gameflow: str, game_strings_map: dict[str, str]) -> str:
def postprocess_gameflow(gameflow: str, object_strings_map: dict[str, str], game_strings_map: dict[str, str]) -> str:
gameflow = re.sub(
r'^( "object_strings": {)[^}]*(})',
' "object_strings": {\n'
+ "\n".join(
f" {json.dumps(key)}: {json.dumps(value)},"
for key, value in object_strings_map.items()
)
+ "\n }",
gameflow,
flags=re.M | re.DOTALL,
)
gameflow = re.sub(
r'^( "game_strings": {)[^}]*(})',
' "game_strings": {\n'
@ -34,12 +46,14 @@ def postprocess_gameflow(gameflow: str, game_strings_map: dict[str, str]) -> str
def main() -> None:
object_strings_map = get_string_map(OBJECT_STRINGS_DEF_PATH)
game_strings_map = get_string_map(GAME_STRINGS_DEF_PATH)
assert object_strings_map
assert game_strings_map
for gameflow_path in SHIP_DIR.rglob("*gameflow*.json*"):
old_gameflow = gameflow_path.read_text()
new_gameflow = postprocess_gameflow(old_gameflow, game_strings_map)
new_gameflow = postprocess_gameflow(old_gameflow, object_strings_map, game_strings_map)
if new_gameflow != old_gameflow:
gameflow_path.write_text(new_gameflow)