From c5096e49fbaf8475899920b43290eb83f67665e2 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Thu, 19 Sep 2024 16:25:05 +0200 Subject: [PATCH 1/3] console/cmd: move /give to libtrx --- data/ship/cfg/TR2X_gameflow.json5 | 2 +- meson.build | 1 + src/game/backpack.c | 8 ++++ src/game/console.c | 15 ++++--- src/game/console_cmd.c | 70 +------------------------------ src/game/game_string.def | 2 - subprojects/libtrx | 2 +- 7 files changed, 22 insertions(+), 78 deletions(-) create mode 100644 src/game/backpack.c diff --git a/data/ship/cfg/TR2X_gameflow.json5 b/data/ship/cfg/TR2X_gameflow.json5 index c3a14de4..02ebe1fa 100644 --- a/data/ship/cfg/TR2X_gameflow.json5 +++ b/data/ship/cfg/TR2X_gameflow.json5 @@ -376,7 +376,7 @@ "OSD_GIVE_ITEM_CHEAT": "Lara's backpack just got way heavier!", "OSD_HEAL_ALREADY_FULL_HP": "Lara's already at full health", "OSD_HEAL_SUCCESS": "Healed Lara back to full health", - "OSD_INVALID_ITEM": "Invalid item: %s", + "OSD_INVALID_ITEM": "Unknown item: %s", "OSD_INVALID_LEVEL": "Invalid level", "OSD_INVALID_OBJECT": "Invalid object", "OSD_INVALID_ROOM": "Invalid room: %d. Valid rooms are 0-%d", diff --git a/meson.build b/meson.build index 38fa8fa7..54bcf2cb 100644 --- a/meson.build +++ b/meson.build @@ -85,6 +85,7 @@ dll_sources = [ 'src/decomp/effects.c', 'src/decomp/stats.c', 'src/game/background.c', + 'src/game/backpack.c', 'src/game/box.c', 'src/game/camera.c', 'src/game/clock.c', diff --git a/src/game/backpack.c b/src/game/backpack.c new file mode 100644 index 00000000..e2d0ac63 --- /dev/null +++ b/src/game/backpack.c @@ -0,0 +1,8 @@ +#include "game/inventory/backpack.h" + +#include + +bool Backpack_AddItem(const GAME_OBJECT_ID object_id) +{ + return Inv_AddItem(object_id); +} diff --git a/src/game/console.c b/src/game/console.c index e9e79211..b19e6fe9 100644 --- a/src/game/console.c +++ b/src/game/console.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -97,16 +98,18 @@ static COMMAND_RESULT M_Eval(const char *const cmdline) if (cur_cmd == NULL) { break; } - if (strstr(cmdline, cur_cmd->prefix) != cmdline) { + + char regex[strlen(cur_cmd->prefix) + 13]; + sprintf(regex, "^(%s)(\\s+.*)?$", cur_cmd->prefix); + if (!String_Match(cmdline, regex)) { continue; } - if (cmdline[strlen(cur_cmd->prefix)] == ' ') { - args = cmdline + strlen(cur_cmd->prefix) + 1; - } else if (cmdline[strlen(cur_cmd->prefix)] == '\0') { - args = ""; + args = strstr(cmdline, " "); + if (args != NULL) { + args++; } else { - continue; + args = ""; } matching_cmd = cur_cmd; diff --git a/src/game/console_cmd.c b/src/game/console_cmd.c index 76610f84..40108451 100644 --- a/src/game/console_cmd.c +++ b/src/game/console_cmd.c @@ -19,6 +19,7 @@ #include "lara/lara_misc.h" #include +#include #include #include #include @@ -31,12 +32,10 @@ static bool M_CanTargetObject(GAME_OBJECT_ID object_id); static bool M_CanTargetObjectCreature(GAME_OBJECT_ID object_id); -static bool M_CanTargetObjectPickup(GAME_OBJECT_ID object_id); static bool M_IsFloatRound(float num); static COMMAND_RESULT Console_Cmd_Teleport(const char *args); static COMMAND_RESULT Console_Cmd_Fly(const char *const args); static COMMAND_RESULT Console_Cmd_FlipMap(const char *args); -static COMMAND_RESULT Console_Cmd_GiveItem(const char *args); static COMMAND_RESULT Console_Cmd_Kill(const char *args); static COMMAND_RESULT Console_Cmd_EndLevel(const char *args); static COMMAND_RESULT Console_Cmd_StartLevel(const char *args); @@ -60,11 +59,6 @@ static bool M_CanTargetObjectCreature(const GAME_OBJECT_ID object_id) || Object_IsObjectType(object_id, g_FriendObjects); } -static bool M_CanTargetObjectPickup(const GAME_OBJECT_ID object_id) -{ - return Object_IsObjectType(object_id, g_PickupObjects); -} - static inline bool M_IsFloatRound(const float num) { return (fabsf(num) - roundf(num)) < 0.0001f; @@ -337,65 +331,6 @@ static COMMAND_RESULT Console_Cmd_Kill(const char *args) } } -static COMMAND_RESULT Console_Cmd_GiveItem(const char *args) -{ - if (g_GameInfo.current_level.type == GFL_TITLE - || g_GameInfo.current_level.type == GFL_DEMO - || g_GameInfo.current_level.type == GFL_CUTSCENE) { - return CR_UNAVAILABLE; - } - - if (g_LaraItem == NULL) { - return CR_UNAVAILABLE; - } - - if (String_Equivalent(args, "keys")) { - return Lara_Cheat_GiveAllKeys() ? CR_SUCCESS : CR_FAILURE; - } - - if (String_Equivalent(args, "guns")) { - return Lara_Cheat_GiveAllGuns() ? CR_SUCCESS : CR_FAILURE; - } - - if (String_Equivalent(args, "all")) { - return Lara_Cheat_GiveAllItems() ? CR_SUCCESS : CR_FAILURE; - } - - int32_t num = 1; - if (sscanf(args, "%d ", &num) == 1) { - args = strstr(args, " "); - if (!args) { - return CR_BAD_INVOCATION; - } - args++; - } - - if (String_Equivalent(args, "")) { - return CR_BAD_INVOCATION; - } - - bool found = false; - int32_t match_count = 0; - GAME_OBJECT_ID *matching_objs = - Object_IdsFromName(args, &match_count, M_CanTargetObjectPickup); - for (int32_t i = 0; i < match_count; i++) { - const GAME_OBJECT_ID object_id = matching_objs[i]; - if (g_Objects[object_id].loaded) { - Inv_AddItemNTimes(object_id, num); - Console_Log(GS(OSD_GIVE_ITEM), Object_GetName(object_id)); - found = true; - } - } - Memory_FreePointer(&matching_objs); - - if (!found) { - Console_Log(GS(OSD_INVALID_ITEM), args); - return CR_FAILURE; - } - - return CR_SUCCESS; -} - static COMMAND_RESULT Console_Cmd_EndLevel(const char *const args) { if (strcmp(args, "") == 0) { @@ -540,8 +475,6 @@ static COMMAND_RESULT Console_Cmd_Abortion(const char *const args) CONSOLE_COMMAND *g_ConsoleCommands[] = { &(CONSOLE_COMMAND) { .prefix = "tp", .proc = Console_Cmd_Teleport }, &(CONSOLE_COMMAND) { .prefix = "fly", .proc = Console_Cmd_Fly }, - &(CONSOLE_COMMAND) { .prefix = "give", .proc = Console_Cmd_GiveItem }, - &(CONSOLE_COMMAND) { .prefix = "gimme", .proc = Console_Cmd_GiveItem }, &(CONSOLE_COMMAND) { .prefix = "flip", .proc = Console_Cmd_FlipMap }, &(CONSOLE_COMMAND) { .prefix = "flipmap", .proc = Console_Cmd_FlipMap }, &(CONSOLE_COMMAND) { .prefix = "kill", .proc = Console_Cmd_Kill }, @@ -560,5 +493,6 @@ CONSOLE_COMMAND *g_ConsoleCommands[] = { &g_Console_Cmd_Pos, &g_Console_Cmd_Heal, &g_Console_Cmd_SetHealth, + &g_Console_Cmd_GiveItem, NULL, }; diff --git a/src/game/game_string.def b/src/game/game_string.def index 6200cebd..70f7ddc6 100644 --- a/src/game/game_string.def +++ b/src/game/game_string.def @@ -6,7 +6,6 @@ GS_DEFINE(OSD_POS_SET_ROOM, "Teleported to room: %d") GS_DEFINE(OSD_POS_SET_ROOM_FAIL, "Failed to teleport to room: %d") GS_DEFINE(OSD_POS_SET_ITEM, "Teleported to object: %s") GS_DEFINE(OSD_POS_SET_ITEM_FAIL, "Failed to teleport to object: %s") -GS_DEFINE(OSD_GIVE_ITEM, "Added %s to Lara's inventory") GS_DEFINE(OSD_GIVE_ITEM_ALL_KEYS, "Surprise! Every key item Lara needs is now in her backpack.") GS_DEFINE(OSD_GIVE_ITEM_ALL_GUNS, "Lock'n'load - Lara's armed to the teeth!") GS_DEFINE(OSD_GIVE_ITEM_CHEAT, "Lara's backpack just got way heavier!") @@ -20,7 +19,6 @@ GS_DEFINE(OSD_KILL, "Bye-bye!") GS_DEFINE(OSD_KILL_FAIL, "No enemy nearby...") GS_DEFINE(OSD_COMPLETE_LEVEL, "Level complete!") GS_DEFINE(OSD_PLAY_LEVEL, "Loading %s") -GS_DEFINE(OSD_INVALID_ITEM, "Invalid item: %s") GS_DEFINE(OSD_INVALID_ROOM, "Invalid room: %d. Valid rooms are 0-%d") GS_DEFINE(OSD_INVALID_OBJECT, "Invalid object") GS_DEFINE(OSD_OBJECT_NOT_FOUND, "Object not found") diff --git a/subprojects/libtrx b/subprojects/libtrx index 712366cf..43678a60 160000 --- a/subprojects/libtrx +++ b/subprojects/libtrx @@ -1 +1 @@ -Subproject commit 712366cf915288e14b2a4cd8743572489ae12cc2 +Subproject commit 43678a60e92dc7d9ac8d9259c1e632949a19a5dd From dbdb6f66b6b23e6a45a8c567d1d8d7a74ce64e30 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sat, 21 Sep 2024 00:48:17 +0200 Subject: [PATCH 2/3] console/cmd: follow libtrx folder structure --- meson.build | 16 +- src/decomp/decomp.c | 2 +- src/game/console/cmd/die.c | 30 ++ src/game/console/cmd/die.h | 5 + src/game/console/cmd/end_level.c | 21 + src/game/console/cmd/end_level.h | 5 + src/game/console/cmd/exit_game.c | 16 + src/game/console/cmd/exit_game.h | 5 + src/game/console/cmd/exit_to_title.c | 16 + src/game/console/cmd/exit_to_title.h | 5 + src/game/console/cmd/flipmap.c | 42 ++ src/game/console/cmd/flipmap.h | 5 + src/game/console/cmd/fly.c | 21 + src/game/console/cmd/fly.h | 5 + src/game/console/cmd/kill.c | 124 ++++++ src/game/console/cmd/kill.h | 5 + src/game/console/cmd/load_game.c | 39 ++ src/game/console/cmd/load_game.h | 5 + src/game/console/cmd/play_demo.c | 16 + src/game/console/cmd/play_demo.h | 5 + src/game/console/cmd/play_level.c | 53 +++ src/game/console/cmd/play_level.h | 5 + src/game/console/cmd/save_game.c | 48 +++ src/game/console/cmd/save_game.h | 5 + src/game/console/cmd/teleport.c | 168 ++++++++ src/game/console/cmd/teleport.h | 5 + src/game/{console.c => console/common.c} | 2 +- src/game/{console.h => console/common.h} | 0 src/game/console/setup.c | 34 ++ src/game/console/setup.h | 5 + src/game/console_cmd.c | 498 ----------------------- src/game/game.c | 2 +- src/game/input.c | 2 +- src/game/lara/lara_cheat.c | 2 +- src/game/shell.c | 2 +- src/game/text.c | 2 +- src/specific/s_input.c | 2 +- subprojects/libtrx | 2 +- 38 files changed, 716 insertions(+), 509 deletions(-) create mode 100644 src/game/console/cmd/die.c create mode 100644 src/game/console/cmd/die.h create mode 100644 src/game/console/cmd/end_level.c create mode 100644 src/game/console/cmd/end_level.h create mode 100644 src/game/console/cmd/exit_game.c create mode 100644 src/game/console/cmd/exit_game.h create mode 100644 src/game/console/cmd/exit_to_title.c create mode 100644 src/game/console/cmd/exit_to_title.h create mode 100644 src/game/console/cmd/flipmap.c create mode 100644 src/game/console/cmd/flipmap.h create mode 100644 src/game/console/cmd/fly.c create mode 100644 src/game/console/cmd/fly.h create mode 100644 src/game/console/cmd/kill.c create mode 100644 src/game/console/cmd/kill.h create mode 100644 src/game/console/cmd/load_game.c create mode 100644 src/game/console/cmd/load_game.h create mode 100644 src/game/console/cmd/play_demo.c create mode 100644 src/game/console/cmd/play_demo.h create mode 100644 src/game/console/cmd/play_level.c create mode 100644 src/game/console/cmd/play_level.h create mode 100644 src/game/console/cmd/save_game.c create mode 100644 src/game/console/cmd/save_game.h create mode 100644 src/game/console/cmd/teleport.c create mode 100644 src/game/console/cmd/teleport.h rename src/game/{console.c => console/common.c} (99%) rename src/game/{console.h => console/common.h} (100%) create mode 100644 src/game/console/setup.c create mode 100644 src/game/console/setup.h delete mode 100644 src/game/console_cmd.c diff --git a/meson.build b/meson.build index 54bcf2cb..f1c21428 100644 --- a/meson.build +++ b/meson.build @@ -90,8 +90,20 @@ dll_sources = [ 'src/game/camera.c', 'src/game/clock.c', 'src/game/collide.c', - 'src/game/console.c', - 'src/game/console_cmd.c', + 'src/game/console/cmd/die.c', + 'src/game/console/cmd/end_level.c', + 'src/game/console/cmd/exit_game.c', + 'src/game/console/cmd/exit_to_title.c', + 'src/game/console/cmd/flipmap.c', + 'src/game/console/cmd/fly.c', + 'src/game/console/cmd/kill.c', + 'src/game/console/cmd/load_game.c', + 'src/game/console/cmd/play_demo.c', + 'src/game/console/cmd/play_level.c', + 'src/game/console/cmd/save_game.c', + 'src/game/console/cmd/teleport.c', + 'src/game/console/common.c', + 'src/game/console/setup.c', 'src/game/creature.c', 'src/game/demo.c', 'src/game/effects.c', diff --git a/src/decomp/decomp.c b/src/decomp/decomp.c index e1467b89..1b2279fe 100644 --- a/src/decomp/decomp.c +++ b/src/decomp/decomp.c @@ -2,7 +2,7 @@ #include "game/background.h" #include "game/camera.h" -#include "game/console.h" +#include "game/console/common.h" #include "game/effects.h" #include "game/game.h" #include "game/gameflow.h" diff --git a/src/game/console/cmd/die.c b/src/game/console/cmd/die.c new file mode 100644 index 00000000..20c121b6 --- /dev/null +++ b/src/game/console/cmd/die.c @@ -0,0 +1,30 @@ +#include "game/console/cmd/die.h" + +#include "decomp/effects.h" +#include "game/sound.h" +#include "global/vars.h" + +static COMMAND_RESULT M_Entrypoint(const char *args); + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + if (!g_Objects[O_LARA].loaded) { + return CR_UNAVAILABLE; + } + + if (g_LaraItem->hit_points <= 0) { + return CR_UNAVAILABLE; + } + + Sound_Effect(SFX_LARA_FALL, &g_LaraItem->pos, SPM_NORMAL); + Effect_ExplodingDeath(g_Lara.item_num, -1, 1); + + g_LaraItem->hit_points = 0; + g_LaraItem->flags |= IF_INVISIBLE; + return CR_SUCCESS; +} + +CONSOLE_COMMAND g_Console_Cmd_Die = { + .prefix = "abortion|natlastinks", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/die.h b/src/game/console/cmd/die.h new file mode 100644 index 00000000..bf50d44b --- /dev/null +++ b/src/game/console/cmd/die.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_Die; diff --git a/src/game/console/cmd/end_level.c b/src/game/console/cmd/end_level.c new file mode 100644 index 00000000..94db367a --- /dev/null +++ b/src/game/console/cmd/end_level.c @@ -0,0 +1,21 @@ +#include "game/console/cmd/end_level.h" + +#include "game/lara/lara_cheat.h" + +#include + +static COMMAND_RESULT M_Entrypoint(const char *args); + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + if (strcmp(args, "") == 0) { + Lara_Cheat_EndLevel(); + return CR_SUCCESS; + } + return CR_FAILURE; +} + +CONSOLE_COMMAND g_Console_Cmd_EndLevel = { + .prefix = "endlevel", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/end_level.h b/src/game/console/cmd/end_level.h new file mode 100644 index 00000000..818a1a08 --- /dev/null +++ b/src/game/console/cmd/end_level.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_EndLevel; diff --git a/src/game/console/cmd/exit_game.c b/src/game/console/cmd/exit_game.c new file mode 100644 index 00000000..d3e9e940 --- /dev/null +++ b/src/game/console/cmd/exit_game.c @@ -0,0 +1,16 @@ +#include "game/console/cmd/exit_game.h" + +#include "global/vars.h" + +static COMMAND_RESULT M_Entrypoint(const char *args); + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + g_GF_OverrideDir = GFD_EXIT_GAME; + return CR_SUCCESS; +} + +CONSOLE_COMMAND g_Console_Cmd_ExitGame = { + .prefix = "exit", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/exit_game.h b/src/game/console/cmd/exit_game.h new file mode 100644 index 00000000..a6f367cd --- /dev/null +++ b/src/game/console/cmd/exit_game.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_ExitGame; diff --git a/src/game/console/cmd/exit_to_title.c b/src/game/console/cmd/exit_to_title.c new file mode 100644 index 00000000..73512077 --- /dev/null +++ b/src/game/console/cmd/exit_to_title.c @@ -0,0 +1,16 @@ +#include "game/console/cmd/exit_to_title.h" + +#include "global/vars.h" + +static COMMAND_RESULT M_Entrypoint(const char *args); + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + g_GF_OverrideDir = GFD_EXIT_TO_TITLE; + return CR_SUCCESS; +} + +CONSOLE_COMMAND g_Console_Cmd_ExitToTitle = { + .prefix = "title", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/exit_to_title.h b/src/game/console/cmd/exit_to_title.h new file mode 100644 index 00000000..ee8064dd --- /dev/null +++ b/src/game/console/cmd/exit_to_title.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_ExitToTitle; diff --git a/src/game/console/cmd/flipmap.c b/src/game/console/cmd/flipmap.c new file mode 100644 index 00000000..d4d05065 --- /dev/null +++ b/src/game/console/cmd/flipmap.c @@ -0,0 +1,42 @@ +#include "game/console/cmd/flipmap.h" + +#include "game/game_string.h" +#include "game/gameflow/gameflow_new.h" +#include "game/room.h" +#include "global/vars.h" + +#include + +static COMMAND_RESULT M_Entrypoint(const char *args); + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + if (g_GameInfo.current_level.type == GFL_TITLE + || g_GameInfo.current_level.type == GFL_DEMO + || g_GameInfo.current_level.type == GFL_CUTSCENE) { + return CR_UNAVAILABLE; + } + + bool new_state; + if (String_Equivalent(args, "")) { + new_state = !g_FlipStatus; + } else if (!String_ParseBool(args, &new_state)) { + return CR_BAD_INVOCATION; + } + + if (g_FlipStatus == new_state) { + Console_Log( + new_state ? GS(OSD_FLIPMAP_FAIL_ALREADY_ON) + : GS(OSD_FLIPMAP_FAIL_ALREADY_OFF)); + return CR_SUCCESS; + } + + Room_FlipMap(); + Console_Log(new_state ? GS(OSD_FLIPMAP_ON) : GS(OSD_FLIPMAP_OFF)); + return CR_SUCCESS; +} + +CONSOLE_COMMAND g_Console_Cmd_FlipMap = { + .prefix = "flip|flipmap", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/flipmap.h b/src/game/console/cmd/flipmap.h new file mode 100644 index 00000000..1f9786dd --- /dev/null +++ b/src/game/console/cmd/flipmap.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_FlipMap; diff --git a/src/game/console/cmd/fly.c b/src/game/console/cmd/fly.c new file mode 100644 index 00000000..4fe91a84 --- /dev/null +++ b/src/game/console/cmd/fly.c @@ -0,0 +1,21 @@ +#include "game/console/cmd/fly.h" + +#include "game/game.h" +#include "game/lara/lara_cheat.h" +#include "global/vars.h" + +static COMMAND_RESULT M_Entrypoint(const char *args); + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + if (!Game_IsPlayable()) { + return CR_UNAVAILABLE; + } + Lara_Cheat_EnterFlyMode(); + return CR_SUCCESS; +} + +CONSOLE_COMMAND g_Console_Cmd_Fly = { + .prefix = "fly", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/fly.h b/src/game/console/cmd/fly.h new file mode 100644 index 00000000..24e195a5 --- /dev/null +++ b/src/game/console/cmd/fly.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_Fly; diff --git a/src/game/console/cmd/kill.c b/src/game/console/cmd/kill.c new file mode 100644 index 00000000..a80a8425 --- /dev/null +++ b/src/game/console/cmd/kill.c @@ -0,0 +1,124 @@ +#include "game/console/cmd/kill.h" + +#include "game/creature.h" +#include "game/game_string.h" +#include "game/items.h" +#include "game/lara/lara_cheat.h" +#include "game/lara/lara_control.h" +#include "game/objects/names.h" +#include "game/objects/vars.h" +#include "global/vars.h" + +#include +#include +#include +#include + +static bool M_CanTargetObjectCreature(GAME_OBJECT_ID object_id); +static COMMAND_RESULT M_Entrypoint(const char *args); + +static bool M_CanTargetObjectCreature(const GAME_OBJECT_ID object_id) +{ + return Object_IsObjectType(object_id, g_EnemyObjects) + || Object_IsObjectType(object_id, g_FriendObjects); +} + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + // kill all the enemies in the level + if (String_Equivalent(args, "all")) { + int32_t num_killed = 0; + for (int16_t item_num = 0; item_num < Item_GetTotalCount(); + item_num++) { + const ITEM_INFO *const item = &g_Items[item_num]; + if (!Creature_IsEnemy(item)) { + continue; + } + if (Lara_Cheat_KillEnemy(item_num)) { + num_killed++; + } + } + + if (num_killed == 0) { + Console_Log(GS(OSD_KILL_ALL_FAIL)); + return CR_FAILURE; + } + + Console_Log(GS(OSD_KILL_ALL), num_killed); + return CR_SUCCESS; + } + + // kill all the enemies around Lara within one tile, or a single nearest + // enemy + if (String_Equivalent(args, "")) { + bool found = false; + while (true) { + const int16_t best_item_num = Lara_GetNearestEnemy(); + if (best_item_num == NO_ITEM) { + break; + } + + const ITEM_INFO *const item = &g_Items[best_item_num]; + const int32_t distance = Item_GetDistance(item, &g_LaraItem->pos); + found |= Lara_Cheat_KillEnemy(best_item_num); + if (distance >= WALL_L) { + break; + } + } + + if (!found) { + Console_Log(GS(OSD_KILL_FAIL)); + return CR_FAILURE; + } + + Console_Log(GS(OSD_KILL)); + return CR_SUCCESS; + } + + // kill a single enemy type + { + bool matches_found = false; + int32_t num_killed = 0; + int32_t match_count = 0; + GAME_OBJECT_ID *matching_objs = + Object_IdsFromName(args, &match_count, M_CanTargetObjectCreature); + + for (int16_t item_num = 0; item_num < Item_GetTotalCount(); + item_num++) { + const ITEM_INFO *const item = &g_Items[item_num]; + + bool is_matched = false; + for (int32_t i = 0; i < match_count; i++) { + if (matching_objs[i] == item->object_id) { + is_matched = true; + break; + } + } + if (!is_matched) { + continue; + } + matches_found = true; + + if (Lara_Cheat_KillEnemy(item_num)) { + num_killed++; + } + } + Memory_FreePointer(&matching_objs); + + if (!matches_found) { + Console_Log(GS(OSD_INVALID_OBJECT), args); + return CR_FAILURE; + } + if (num_killed == 0) { + Console_Log(GS(OSD_OBJECT_NOT_FOUND), args); + return CR_FAILURE; + } + Console_Log(GS(OSD_KILL_ALL), num_killed); + return CR_SUCCESS; + } +} + +CONSOLE_COMMAND g_Console_Cmd_Kill = { + .prefix = "kill", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/kill.h b/src/game/console/cmd/kill.h new file mode 100644 index 00000000..3766fe1f --- /dev/null +++ b/src/game/console/cmd/kill.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_Kill; diff --git a/src/game/console/cmd/load_game.c b/src/game/console/cmd/load_game.c new file mode 100644 index 00000000..b24ff927 --- /dev/null +++ b/src/game/console/cmd/load_game.c @@ -0,0 +1,39 @@ +#include "game/console/cmd/load_game.h" + +#include "game/game_string.h" +#include "global/vars.h" + +#include + +static COMMAND_RESULT M_Entrypoint(const char *args); + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + int32_t slot_num; + if (!String_ParseInteger(args, &slot_num)) { + return CR_BAD_INVOCATION; + } + + // convert 1-indexing to 0-indexing + const int32_t slot_idx = slot_num - 1; + + if (slot_idx < 0 || slot_idx >= MAX_SAVE_SLOTS) { + Console_Log(GS(OSD_INVALID_SAVE_SLOT), slot_num); + return CR_FAILURE; + } + + // TODO: replace this with a proper status check + if (g_SavedLevels[slot_idx] <= 0) { + Console_Log(GS(OSD_LOAD_GAME_FAIL_UNAVAILABLE_SLOT), slot_num); + return CR_FAILURE; + } + + g_GF_OverrideDir = GFD_START_SAVED_GAME | slot_idx; + Console_Log(GS(OSD_LOAD_GAME), slot_num); + return CR_SUCCESS; +} + +CONSOLE_COMMAND g_Console_Cmd_LoadGame = { + .prefix = "load", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/load_game.h b/src/game/console/cmd/load_game.h new file mode 100644 index 00000000..6bf43395 --- /dev/null +++ b/src/game/console/cmd/load_game.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_LoadGame; diff --git a/src/game/console/cmd/play_demo.c b/src/game/console/cmd/play_demo.c new file mode 100644 index 00000000..459602c2 --- /dev/null +++ b/src/game/console/cmd/play_demo.c @@ -0,0 +1,16 @@ +#include "game/console/cmd/play_demo.h" + +#include "global/vars.h" + +static COMMAND_RESULT M_Entrypoint(const char *args); + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + g_GF_OverrideDir = GFD_START_DEMO; + return CR_SUCCESS; +} + +CONSOLE_COMMAND g_Console_Cmd_PlayDemo = { + .prefix = "demo", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/play_demo.h b/src/game/console/cmd/play_demo.h new file mode 100644 index 00000000..51c80a8e --- /dev/null +++ b/src/game/console/cmd/play_demo.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_PlayDemo; diff --git a/src/game/console/cmd/play_level.c b/src/game/console/cmd/play_level.c new file mode 100644 index 00000000..b7a67fa6 --- /dev/null +++ b/src/game/console/cmd/play_level.c @@ -0,0 +1,53 @@ +#include "game/console/cmd/play_level.h" + +#include "game/game_string.h" +#include "global/vars.h" + +#include + +#include + +static COMMAND_RESULT M_Entrypoint(const char *args); + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + int32_t level_to_load = -1; + + if (level_to_load == -1) { + int32_t num = 0; + if (sscanf(args, "%d", &num) == 1) { + level_to_load = num; + } + } + + if (level_to_load == -1 && strlen(args) >= 2) { + for (int i = 0; i < g_GameFlow.num_levels; i++) { + if (String_CaseSubstring(g_GF_LevelNames[i], args) != NULL) { + level_to_load = i; + break; + } + } + } + + if (level_to_load == -1 && String_Equivalent(args, "gym")) { + level_to_load = LV_GYM; + } + + if (level_to_load >= g_GameFlow.num_levels) { + Console_Log(GS(OSD_INVALID_LEVEL)); + return CR_FAILURE; + } + + if (level_to_load != -1) { + g_GF_OverrideDir = GFD_START_GAME | level_to_load; + Console_Log(GS(OSD_PLAY_LEVEL), g_GF_LevelNames[level_to_load]); + return CR_SUCCESS; + } + + return CR_BAD_INVOCATION; +} + +CONSOLE_COMMAND g_Console_Cmd_PlayLevel = { + .prefix = "play|level", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/play_level.h b/src/game/console/cmd/play_level.h new file mode 100644 index 00000000..200cc8c7 --- /dev/null +++ b/src/game/console/cmd/play_level.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_PlayLevel; diff --git a/src/game/console/cmd/save_game.c b/src/game/console/cmd/save_game.c new file mode 100644 index 00000000..869e5d13 --- /dev/null +++ b/src/game/console/cmd/save_game.c @@ -0,0 +1,48 @@ +#include "game/console/cmd/save_game.h" + +#include "decomp/decomp.h" +#include "game/game_string.h" +#include "game/gameflow/gameflow_new.h" +#include "global/funcs.h" +#include "global/vars.h" + +#include + +static COMMAND_RESULT M_Entrypoint(const char *args); + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + int32_t slot_num; + if (!String_ParseInteger(args, &slot_num)) { + return CR_BAD_INVOCATION; + } + + // convert 1-indexing to 0-indexing + const int32_t slot_idx = slot_num - 1; + + if (slot_idx < 0 || slot_idx >= MAX_SAVE_SLOTS) { + Console_Log(GS(OSD_INVALID_SAVE_SLOT), slot_num); + return CR_BAD_INVOCATION; + } + + if (g_GameInfo.current_level.type == GFL_TITLE + || g_GameInfo.current_level.type == GFL_DEMO + || g_GameInfo.current_level.type == GFL_CUTSCENE) { + return CR_UNAVAILABLE; + } + + if (g_LaraItem == NULL || g_LaraItem->hit_points <= 0) { + return CR_UNAVAILABLE; + } + + CreateSaveGameInfo(); + S_SaveGame(&g_SaveGame, sizeof(SAVEGAME_INFO), slot_idx); + GetSavedGamesList(&g_LoadGameRequester); + Console_Log(GS(OSD_SAVE_GAME), slot_num); + return CR_SUCCESS; +} + +CONSOLE_COMMAND g_Console_Cmd_SaveGame = { + .prefix = "save", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/save_game.h b/src/game/console/cmd/save_game.h new file mode 100644 index 00000000..26cab28f --- /dev/null +++ b/src/game/console/cmd/save_game.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_SaveGame; diff --git a/src/game/console/cmd/teleport.c b/src/game/console/cmd/teleport.c new file mode 100644 index 00000000..907574f2 --- /dev/null +++ b/src/game/console/cmd/teleport.c @@ -0,0 +1,168 @@ +#include "game/console/cmd/teleport.h" + +#include "game/game_string.h" +#include "game/gameflow/gameflow_new.h" +#include "game/items.h" +#include "game/lara/lara_cheat.h" +#include "game/objects/names.h" +#include "game/objects/vars.h" +#include "game/random.h" +#include "global/const.h" +#include "global/vars.h" + +#include +#include + +#include +#include + +static bool M_CanTargetObject(GAME_OBJECT_ID object_id); +static bool M_IsFloatRound(float num); +static COMMAND_RESULT M_Entrypoint(const char *args); + +static bool M_CanTargetObject(const GAME_OBJECT_ID object_id) +{ + return !Object_IsObjectType(object_id, g_NullObjects) + && !Object_IsObjectType(object_id, g_AnimObjects) + && !Object_IsObjectType(object_id, g_InvObjects); +} + +static inline bool M_IsFloatRound(const float num) +{ + return (fabsf(num) - roundf(num)) < 0.0001f; +} + +static COMMAND_RESULT M_Entrypoint(const char *const args) +{ + if (g_GameInfo.current_level.type == GFL_TITLE + || g_GameInfo.current_level.type == GFL_DEMO + || g_GameInfo.current_level.type == GFL_CUTSCENE) { + return CR_UNAVAILABLE; + } + + if (!g_Objects[O_LARA].loaded || !g_LaraItem->hit_points) { + return CR_UNAVAILABLE; + } + + // X Y Z + { + float x, y, z; + if (sscanf(args, "%f %f %f", &x, &y, &z) == 3) { + if (M_IsFloatRound(x)) { + x += 0.5f; + } + if (M_IsFloatRound(z)) { + z += 0.5f; + } + + 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; + } + + Console_Log(GS(OSD_POS_SET_POS_FAIL), x, y, z); + return CR_FAILURE; + } + } + + // Room number + { + int16_t room_num = NO_ROOM_NEG; + if (sscanf(args, "%hd", &room_num) == 1) { + if (room_num < 0 || room_num >= g_RoomCount) { + Console_Log(GS(OSD_INVALID_ROOM), room_num, g_RoomCount - 1); + return CR_FAILURE; + } + + const ROOM_INFO *const room = &g_Rooms[room_num]; + + const int32_t x1 = room->pos.x + WALL_L; + const int32_t x2 = + (room->x_size << WALL_SHIFT) + room->pos.x - WALL_L; + const int32_t y1 = room->min_floor; + const int32_t y2 = room->max_ceiling; + const int32_t z1 = room->pos.z + WALL_L; + const int32_t z2 = + (room->z_size << WALL_SHIFT) + room->pos.z - WALL_L; + + for (int32_t i = 0; i < 100; i++) { + int32_t x = x1 + Random_GetControl() * (x2 - x1) / 0x7FFF; + int32_t y = y1; + int32_t z = z1 + Random_GetControl() * (z2 - z1) / 0x7FFF; + if (Lara_Cheat_Teleport(x, y, z)) { + Console_Log(GS(OSD_POS_SET_ROOM), room_num); + return CR_SUCCESS; + } + } + + Console_Log(GS(OSD_POS_SET_ROOM_FAIL), room_num); + return CR_FAILURE; + } + } + + // Nearest item of this name + if (!String_Equivalent(args, "")) { + int32_t match_count = 0; + GAME_OBJECT_ID *matching_objs = + Object_IdsFromName(args, &match_count, M_CanTargetObject); + + 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]; + if (Object_IsObjectType(item->object_id, g_PickupObjects) + && (item->status == IS_INVISIBLE + || item->status == IS_DEACTIVATED + || item->room_num == NO_ROOM)) { + 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_id) { + 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 - STEP_L, + best_item->pos.z)) { + Console_Log( + GS(OSD_POS_SET_ITEM), Object_GetName(best_item->object_id)); + } else { + Console_Log( + GS(OSD_POS_SET_ITEM_FAIL), + Object_GetName(best_item->object_id)); + } + return CR_SUCCESS; + } else { + Console_Log(GS(OSD_POS_SET_ITEM_FAIL), args); + return CR_FAILURE; + } + } + + return CR_BAD_INVOCATION; +} + +CONSOLE_COMMAND g_Console_Cmd_Teleport = { + .prefix = "tp", + .proc = M_Entrypoint, +}; diff --git a/src/game/console/cmd/teleport.h b/src/game/console/cmd/teleport.h new file mode 100644 index 00000000..be17673b --- /dev/null +++ b/src/game/console/cmd/teleport.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND g_Console_Cmd_Teleport; diff --git a/src/game/console.c b/src/game/console/common.c similarity index 99% rename from src/game/console.c rename to src/game/console/common.c index b19e6fe9..bbd8f320 100644 --- a/src/game/console.c +++ b/src/game/console/common.c @@ -1,4 +1,4 @@ -#include "game/console.h" +#include "game/console/common.h" #include "game/clock.h" #include "game/game_string.h" diff --git a/src/game/console.h b/src/game/console/common.h similarity index 100% rename from src/game/console.h rename to src/game/console/common.h diff --git a/src/game/console/setup.c b/src/game/console/setup.c new file mode 100644 index 00000000..edc0fbdb --- /dev/null +++ b/src/game/console/setup.c @@ -0,0 +1,34 @@ +#include "game/console/setup.h" + +#include "game/console/cmd/die.h" +#include "game/console/cmd/end_level.h" +#include "game/console/cmd/exit_game.h" +#include "game/console/cmd/exit_to_title.h" +#include "game/console/cmd/flipmap.h" +#include "game/console/cmd/fly.h" +#include "game/console/cmd/kill.h" +#include "game/console/cmd/load_game.h" +#include "game/console/cmd/play_demo.h" +#include "game/console/cmd/play_level.h" +#include "game/console/cmd/save_game.h" +#include "game/console/cmd/teleport.h" + +#include +#include +#include +#include +#include + +#include + +CONSOLE_COMMAND *g_ConsoleCommands[] = { + &g_Console_Cmd_Teleport, &g_Console_Cmd_Fly, + &g_Console_Cmd_FlipMap, &g_Console_Cmd_Kill, + &g_Console_Cmd_EndLevel, &g_Console_Cmd_PlayLevel, + &g_Console_Cmd_LoadGame, &g_Console_Cmd_SaveGame, + &g_Console_Cmd_PlayDemo, &g_Console_Cmd_ExitToTitle, + &g_Console_Cmd_ExitGame, &g_Console_Cmd_Die, + &g_Console_Cmd_Config, &g_Console_Cmd_Pos, + &g_Console_Cmd_Heal, &g_Console_Cmd_SetHealth, + &g_Console_Cmd_GiveItem, NULL, +}; diff --git a/src/game/console/setup.h b/src/game/console/setup.h new file mode 100644 index 00000000..11f2f967 --- /dev/null +++ b/src/game/console/setup.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern CONSOLE_COMMAND *g_ConsoleCommands[]; diff --git a/src/game/console_cmd.c b/src/game/console_cmd.c deleted file mode 100644 index 40108451..00000000 --- a/src/game/console_cmd.c +++ /dev/null @@ -1,498 +0,0 @@ -#include "decomp/effects.h" -#include "game/console.h" -#include "game/creature.h" -#include "game/game_string.h" -#include "game/gameflow/gameflow_new.h" -#include "game/inventory/backpack.h" -#include "game/items.h" -#include "game/lara/lara_cheat.h" -#include "game/lara/lara_control.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" -#include "global/const.h" -#include "global/funcs.h" -#include "global/vars.h" -#include "lara/lara_misc.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static bool M_CanTargetObject(GAME_OBJECT_ID object_id); -static bool M_CanTargetObjectCreature(GAME_OBJECT_ID object_id); -static bool M_IsFloatRound(float num); -static COMMAND_RESULT Console_Cmd_Teleport(const char *args); -static COMMAND_RESULT Console_Cmd_Fly(const char *const args); -static COMMAND_RESULT Console_Cmd_FlipMap(const char *args); -static COMMAND_RESULT Console_Cmd_Kill(const char *args); -static COMMAND_RESULT Console_Cmd_EndLevel(const char *args); -static COMMAND_RESULT Console_Cmd_StartLevel(const char *args); -static COMMAND_RESULT Console_Cmd_LoadGame(const char *args); -static COMMAND_RESULT Console_Cmd_SaveGame(const char *args); -static COMMAND_RESULT Console_Cmd_StartDemo(const char *args); -static COMMAND_RESULT Console_Cmd_ExitToTitle(const char *args); -static COMMAND_RESULT Console_Cmd_ExitGame(const char *args); -static COMMAND_RESULT Console_Cmd_Abortion(const char *args); - -static bool M_CanTargetObject(const GAME_OBJECT_ID object_id) -{ - return !Object_IsObjectType(object_id, g_NullObjects) - && !Object_IsObjectType(object_id, g_AnimObjects) - && !Object_IsObjectType(object_id, g_InvObjects); -} - -static bool M_CanTargetObjectCreature(const GAME_OBJECT_ID object_id) -{ - return Object_IsObjectType(object_id, g_EnemyObjects) - || Object_IsObjectType(object_id, g_FriendObjects); -} - -static inline bool M_IsFloatRound(const float num) -{ - return (fabsf(num) - roundf(num)) < 0.0001f; -} - -static COMMAND_RESULT Console_Cmd_Teleport(const char *const args) -{ - if (g_GameInfo.current_level.type == GFL_TITLE - || g_GameInfo.current_level.type == GFL_DEMO - || g_GameInfo.current_level.type == GFL_CUTSCENE) { - return CR_UNAVAILABLE; - } - - if (!g_Objects[O_LARA].loaded || !g_LaraItem->hit_points) { - return CR_UNAVAILABLE; - } - - // X Y Z - { - float x, y, z; - if (sscanf(args, "%f %f %f", &x, &y, &z) == 3) { - if (M_IsFloatRound(x)) { - x += 0.5f; - } - if (M_IsFloatRound(z)) { - z += 0.5f; - } - - 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; - } - - Console_Log(GS(OSD_POS_SET_POS_FAIL), x, y, z); - return CR_FAILURE; - } - } - - // Room number - { - int16_t room_num = NO_ROOM_NEG; - if (sscanf(args, "%hd", &room_num) == 1) { - if (room_num < 0 || room_num >= g_RoomCount) { - Console_Log(GS(OSD_INVALID_ROOM), room_num, g_RoomCount - 1); - return CR_FAILURE; - } - - const ROOM_INFO *const room = &g_Rooms[room_num]; - - const int32_t x1 = room->pos.x + WALL_L; - const int32_t x2 = - (room->x_size << WALL_SHIFT) + room->pos.x - WALL_L; - const int32_t y1 = room->min_floor; - const int32_t y2 = room->max_ceiling; - const int32_t z1 = room->pos.z + WALL_L; - const int32_t z2 = - (room->z_size << WALL_SHIFT) + room->pos.z - WALL_L; - - for (int32_t i = 0; i < 100; i++) { - int32_t x = x1 + Random_GetControl() * (x2 - x1) / 0x7FFF; - int32_t y = y1; - int32_t z = z1 + Random_GetControl() * (z2 - z1) / 0x7FFF; - if (Lara_Cheat_Teleport(x, y, z)) { - Console_Log(GS(OSD_POS_SET_ROOM), room_num); - return CR_SUCCESS; - } - } - - Console_Log(GS(OSD_POS_SET_ROOM_FAIL), room_num); - return CR_FAILURE; - } - } - - // Nearest item of this name - if (!String_Equivalent(args, "")) { - int32_t match_count = 0; - GAME_OBJECT_ID *matching_objs = - Object_IdsFromName(args, &match_count, M_CanTargetObject); - - 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]; - if (Object_IsObjectType(item->object_id, g_PickupObjects) - && (item->status == IS_INVISIBLE - || item->status == IS_DEACTIVATED - || item->room_num == NO_ROOM)) { - 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_id) { - 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 - STEP_L, - best_item->pos.z)) { - Console_Log( - GS(OSD_POS_SET_ITEM), Object_GetName(best_item->object_id)); - } else { - Console_Log( - GS(OSD_POS_SET_ITEM_FAIL), - Object_GetName(best_item->object_id)); - } - return CR_SUCCESS; - } else { - Console_Log(GS(OSD_POS_SET_ITEM_FAIL), args); - return CR_FAILURE; - } - } - - return CR_BAD_INVOCATION; -} - -static COMMAND_RESULT Console_Cmd_Fly(const char *const args) -{ - if (g_GameInfo.current_level.type == GFL_TITLE - || g_GameInfo.current_level.type == GFL_DEMO - || g_GameInfo.current_level.type == GFL_CUTSCENE) { - return CR_UNAVAILABLE; - } - - if (!g_Objects[O_LARA].loaded) { - return CR_UNAVAILABLE; - } - Lara_Cheat_EnterFlyMode(); - return CR_SUCCESS; -} - -static COMMAND_RESULT Console_Cmd_FlipMap(const char *const args) -{ - if (g_GameInfo.current_level.type == GFL_TITLE - || g_GameInfo.current_level.type == GFL_DEMO - || g_GameInfo.current_level.type == GFL_CUTSCENE) { - return CR_UNAVAILABLE; - } - - bool new_state; - if (String_Equivalent(args, "")) { - new_state = !g_FlipStatus; - } else if (!String_ParseBool(args, &new_state)) { - return CR_BAD_INVOCATION; - } - - if (g_FlipStatus == new_state) { - Console_Log( - new_state ? GS(OSD_FLIPMAP_FAIL_ALREADY_ON) - : GS(OSD_FLIPMAP_FAIL_ALREADY_OFF)); - return CR_SUCCESS; - } - - Room_FlipMap(); - Console_Log(new_state ? GS(OSD_FLIPMAP_ON) : GS(OSD_FLIPMAP_OFF)); - return CR_SUCCESS; -} - -static COMMAND_RESULT Console_Cmd_Kill(const char *args) -{ - // kill all the enemies in the level - if (String_Equivalent(args, "all")) { - int32_t num_killed = 0; - for (int16_t item_num = 0; item_num < Item_GetTotalCount(); - item_num++) { - const ITEM_INFO *const item = &g_Items[item_num]; - if (!Creature_IsEnemy(item)) { - continue; - } - if (Lara_Cheat_KillEnemy(item_num)) { - num_killed++; - } - } - - if (num_killed == 0) { - Console_Log(GS(OSD_KILL_ALL_FAIL)); - return CR_FAILURE; - } - - Console_Log(GS(OSD_KILL_ALL), num_killed); - return CR_SUCCESS; - } - - // kill all the enemies around Lara within one tile, or a single nearest - // enemy - if (String_Equivalent(args, "")) { - bool found = false; - while (true) { - const int16_t best_item_num = Lara_GetNearestEnemy(); - if (best_item_num == NO_ITEM) { - break; - } - - const ITEM_INFO *const item = &g_Items[best_item_num]; - const int32_t distance = Item_GetDistance(item, &g_LaraItem->pos); - found |= Lara_Cheat_KillEnemy(best_item_num); - if (distance >= WALL_L) { - break; - } - } - - if (!found) { - Console_Log(GS(OSD_KILL_FAIL)); - return CR_FAILURE; - } - - Console_Log(GS(OSD_KILL)); - return CR_SUCCESS; - } - - // kill a single enemy type - { - bool matches_found = false; - int32_t num_killed = 0; - int32_t match_count = 0; - GAME_OBJECT_ID *matching_objs = - Object_IdsFromName(args, &match_count, M_CanTargetObjectCreature); - - for (int16_t item_num = 0; item_num < Item_GetTotalCount(); - item_num++) { - const ITEM_INFO *const item = &g_Items[item_num]; - - bool is_matched = false; - for (int32_t i = 0; i < match_count; i++) { - if (matching_objs[i] == item->object_id) { - is_matched = true; - break; - } - } - if (!is_matched) { - continue; - } - matches_found = true; - - if (Lara_Cheat_KillEnemy(item_num)) { - num_killed++; - } - } - Memory_FreePointer(&matching_objs); - - if (!matches_found) { - Console_Log(GS(OSD_INVALID_OBJECT), args); - return CR_FAILURE; - } - if (num_killed == 0) { - Console_Log(GS(OSD_OBJECT_NOT_FOUND), args); - return CR_FAILURE; - } - Console_Log(GS(OSD_KILL_ALL), num_killed); - return CR_SUCCESS; - } -} - -static COMMAND_RESULT Console_Cmd_EndLevel(const char *const args) -{ - if (strcmp(args, "") == 0) { - Lara_Cheat_EndLevel(); - return CR_SUCCESS; - } - return CR_FAILURE; -} - -static COMMAND_RESULT Console_Cmd_StartLevel(const char *const args) -{ - int32_t level_to_load = -1; - - if (level_to_load == -1) { - int32_t num = 0; - if (sscanf(args, "%d", &num) == 1) { - level_to_load = num; - } - } - - if (level_to_load == -1 && strlen(args) >= 2) { - for (int i = 0; i < g_GameFlow.num_levels; i++) { - if (String_CaseSubstring(g_GF_LevelNames[i], args) != NULL) { - level_to_load = i; - break; - } - } - } - - if (level_to_load == -1 && String_Equivalent(args, "gym")) { - level_to_load = LV_GYM; - } - - if (level_to_load >= g_GameFlow.num_levels) { - Console_Log(GS(OSD_INVALID_LEVEL)); - return CR_FAILURE; - } - - if (level_to_load != -1) { - g_GF_OverrideDir = GFD_START_GAME | level_to_load; - Console_Log(GS(OSD_PLAY_LEVEL), g_GF_LevelNames[level_to_load]); - return CR_SUCCESS; - } - - return CR_BAD_INVOCATION; -} - -static COMMAND_RESULT Console_Cmd_LoadGame(const char *const args) -{ - int32_t slot_num; - if (!String_ParseInteger(args, &slot_num)) { - return CR_BAD_INVOCATION; - } - - // convert 1-indexing to 0-indexing - const int32_t slot_idx = slot_num - 1; - - if (slot_idx < 0 || slot_idx >= MAX_SAVE_SLOTS) { - Console_Log(GS(OSD_INVALID_SAVE_SLOT), slot_num); - return CR_FAILURE; - } - - // TODO: replace this with a proper status check - if (g_SavedLevels[slot_idx] <= 0) { - Console_Log(GS(OSD_LOAD_GAME_FAIL_UNAVAILABLE_SLOT), slot_num); - return CR_FAILURE; - } - - g_GF_OverrideDir = GFD_START_SAVED_GAME | slot_idx; - Console_Log(GS(OSD_LOAD_GAME), slot_num); - return CR_SUCCESS; -} - -static COMMAND_RESULT Console_Cmd_SaveGame(const char *const args) -{ - int32_t slot_num; - if (!String_ParseInteger(args, &slot_num)) { - return CR_BAD_INVOCATION; - } - - // convert 1-indexing to 0-indexing - const int32_t slot_idx = slot_num - 1; - - if (slot_idx < 0 || slot_idx >= MAX_SAVE_SLOTS) { - Console_Log(GS(OSD_INVALID_SAVE_SLOT), slot_num); - return CR_BAD_INVOCATION; - } - - if (g_GameInfo.current_level.type == GFL_TITLE - || g_GameInfo.current_level.type == GFL_DEMO - || g_GameInfo.current_level.type == GFL_CUTSCENE) { - return CR_UNAVAILABLE; - } - - if (g_LaraItem == NULL || g_LaraItem->hit_points <= 0) { - return CR_UNAVAILABLE; - } - - CreateSaveGameInfo(); - S_SaveGame(&g_SaveGame, sizeof(SAVEGAME_INFO), slot_idx); - GetSavedGamesList(&g_LoadGameRequester); - Console_Log(GS(OSD_SAVE_GAME), slot_num); - return CR_SUCCESS; -} - -static COMMAND_RESULT Console_Cmd_StartDemo(const char *const args) -{ - g_GF_OverrideDir = GFD_START_DEMO; - return CR_SUCCESS; -} - -static COMMAND_RESULT Console_Cmd_ExitToTitle(const char *const args) -{ - g_GF_OverrideDir = GFD_EXIT_TO_TITLE; - return CR_SUCCESS; -} - -static COMMAND_RESULT Console_Cmd_ExitGame(const char *const args) -{ - g_GF_OverrideDir = GFD_EXIT_GAME; - return CR_SUCCESS; -} - -static COMMAND_RESULT Console_Cmd_Abortion(const char *const args) -{ - if (!g_Objects[O_LARA].loaded) { - return CR_UNAVAILABLE; - } - - if (g_LaraItem->hit_points <= 0) { - return CR_UNAVAILABLE; - } - - Sound_Effect(SFX_LARA_FALL, &g_LaraItem->pos, SPM_NORMAL); - Effect_ExplodingDeath(g_Lara.item_num, -1, 1); - - g_LaraItem->hit_points = 0; - g_LaraItem->flags |= IF_INVISIBLE; - return CR_SUCCESS; -} - -CONSOLE_COMMAND *g_ConsoleCommands[] = { - &(CONSOLE_COMMAND) { .prefix = "tp", .proc = Console_Cmd_Teleport }, - &(CONSOLE_COMMAND) { .prefix = "fly", .proc = Console_Cmd_Fly }, - &(CONSOLE_COMMAND) { .prefix = "flip", .proc = Console_Cmd_FlipMap }, - &(CONSOLE_COMMAND) { .prefix = "flipmap", .proc = Console_Cmd_FlipMap }, - &(CONSOLE_COMMAND) { .prefix = "kill", .proc = Console_Cmd_Kill }, - &(CONSOLE_COMMAND) { .prefix = "endlevel", .proc = Console_Cmd_EndLevel }, - &(CONSOLE_COMMAND) { .prefix = "play", .proc = Console_Cmd_StartLevel }, - &(CONSOLE_COMMAND) { .prefix = "level", .proc = Console_Cmd_StartLevel }, - &(CONSOLE_COMMAND) { .prefix = "load", .proc = Console_Cmd_LoadGame }, - &(CONSOLE_COMMAND) { .prefix = "save", .proc = Console_Cmd_SaveGame }, - &(CONSOLE_COMMAND) { .prefix = "demo", .proc = Console_Cmd_StartDemo }, - &(CONSOLE_COMMAND) { .prefix = "title", .proc = Console_Cmd_ExitToTitle }, - &(CONSOLE_COMMAND) { .prefix = "exit", .proc = Console_Cmd_ExitGame }, - &(CONSOLE_COMMAND) { .prefix = "abortion", .proc = Console_Cmd_Abortion }, - &(CONSOLE_COMMAND) { .prefix = "natlastinks", - .proc = Console_Cmd_Abortion }, - &g_Console_Cmd_Config, - &g_Console_Cmd_Pos, - &g_Console_Cmd_Heal, - &g_Console_Cmd_SetHealth, - &g_Console_Cmd_GiveItem, - NULL, -}; diff --git a/src/game/game.c b/src/game/game.c index 903243e0..ed92b9bf 100644 --- a/src/game/game.c +++ b/src/game/game.c @@ -306,7 +306,7 @@ bool Game_IsPlayable(void) return false; } - if (!g_Objects[O_LARA].loaded) { + if (!g_Objects[O_LARA].loaded || g_LaraItem == NULL) { return false; } diff --git a/src/game/input.c b/src/game/input.c index 2bd6b30f..bf3d7a13 100644 --- a/src/game/input.c +++ b/src/game/input.c @@ -1,6 +1,6 @@ #include "game/input.h" -#include "game/console.h" +#include "game/console/common.h" #include "global/funcs.h" #include "global/vars.h" #include "specific/s_input.h" diff --git a/src/game/lara/lara_cheat.c b/src/game/lara/lara_cheat.c index d3620312..9317d5af 100644 --- a/src/game/lara/lara_cheat.c +++ b/src/game/lara/lara_cheat.c @@ -2,7 +2,7 @@ #include "decomp/effects.h" #include "game/camera.h" -#include "game/console.h" +#include "game/console/common.h" #include "game/creature.h" #include "game/game_string.h" #include "game/gun/gun.h" diff --git a/src/game/shell.c b/src/game/shell.c index e3ab1871..70791fe1 100644 --- a/src/game/shell.c +++ b/src/game/shell.c @@ -2,7 +2,7 @@ #include "config.h" #include "decomp/decomp.h" -#include "game/console.h" +#include "game/console/common.h" #include "game/demo.h" #include "game/game_string.h" #include "game/gameflow.h" diff --git a/src/game/text.c b/src/game/text.c index 7b73f868..687dcc42 100644 --- a/src/game/text.c +++ b/src/game/text.c @@ -1,6 +1,6 @@ #include "game/text.h" -#include "game/console.h" +#include "game/console/common.h" #include "game/output.h" #include "game/overlay.h" #include "global/const.h" diff --git a/src/specific/s_input.c b/src/specific/s_input.c index 012fa155..97936260 100644 --- a/src/specific/s_input.c +++ b/src/specific/s_input.c @@ -1,7 +1,7 @@ #include "specific/s_input.h" #include "decomp/decomp.h" -#include "game/console.h" +#include "game/console/common.h" #include "game/gameflow/gameflow_new.h" #include "game/input.h" #include "game/inventory/backpack.h" diff --git a/subprojects/libtrx b/subprojects/libtrx index 43678a60..e3765893 160000 --- a/subprojects/libtrx +++ b/subprojects/libtrx @@ -1 +1 @@ -Subproject commit 43678a60e92dc7d9ac8d9259c1e632949a19a5dd +Subproject commit e376589305ba378c34fafcdf143d07d2f14a8b77 From db2e2cbd690dd46df983e929efabad90e7212ee7 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sat, 21 Sep 2024 01:17:55 +0200 Subject: [PATCH 3/3] console/cmd: move /kill to libtrx --- meson.build | 1 - src/game/console/cmd/kill.c | 124 ------------------------------------ src/game/console/cmd/kill.h | 5 -- src/game/console/setup.c | 2 +- src/game/creature.c | 2 +- src/game/game_string.def | 6 -- src/game/items.c | 5 ++ src/game/objects/vars.c | 2 +- src/game/objects/vars.h | 2 +- subprojects/libtrx | 2 +- 10 files changed, 10 insertions(+), 141 deletions(-) delete mode 100644 src/game/console/cmd/kill.c delete mode 100644 src/game/console/cmd/kill.h diff --git a/meson.build b/meson.build index f1c21428..25e950e0 100644 --- a/meson.build +++ b/meson.build @@ -96,7 +96,6 @@ dll_sources = [ 'src/game/console/cmd/exit_to_title.c', 'src/game/console/cmd/flipmap.c', 'src/game/console/cmd/fly.c', - 'src/game/console/cmd/kill.c', 'src/game/console/cmd/load_game.c', 'src/game/console/cmd/play_demo.c', 'src/game/console/cmd/play_level.c', diff --git a/src/game/console/cmd/kill.c b/src/game/console/cmd/kill.c deleted file mode 100644 index a80a8425..00000000 --- a/src/game/console/cmd/kill.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "game/console/cmd/kill.h" - -#include "game/creature.h" -#include "game/game_string.h" -#include "game/items.h" -#include "game/lara/lara_cheat.h" -#include "game/lara/lara_control.h" -#include "game/objects/names.h" -#include "game/objects/vars.h" -#include "global/vars.h" - -#include -#include -#include -#include - -static bool M_CanTargetObjectCreature(GAME_OBJECT_ID object_id); -static COMMAND_RESULT M_Entrypoint(const char *args); - -static bool M_CanTargetObjectCreature(const GAME_OBJECT_ID object_id) -{ - return Object_IsObjectType(object_id, g_EnemyObjects) - || Object_IsObjectType(object_id, g_FriendObjects); -} - -static COMMAND_RESULT M_Entrypoint(const char *const args) -{ - // kill all the enemies in the level - if (String_Equivalent(args, "all")) { - int32_t num_killed = 0; - for (int16_t item_num = 0; item_num < Item_GetTotalCount(); - item_num++) { - const ITEM_INFO *const item = &g_Items[item_num]; - if (!Creature_IsEnemy(item)) { - continue; - } - if (Lara_Cheat_KillEnemy(item_num)) { - num_killed++; - } - } - - if (num_killed == 0) { - Console_Log(GS(OSD_KILL_ALL_FAIL)); - return CR_FAILURE; - } - - Console_Log(GS(OSD_KILL_ALL), num_killed); - return CR_SUCCESS; - } - - // kill all the enemies around Lara within one tile, or a single nearest - // enemy - if (String_Equivalent(args, "")) { - bool found = false; - while (true) { - const int16_t best_item_num = Lara_GetNearestEnemy(); - if (best_item_num == NO_ITEM) { - break; - } - - const ITEM_INFO *const item = &g_Items[best_item_num]; - const int32_t distance = Item_GetDistance(item, &g_LaraItem->pos); - found |= Lara_Cheat_KillEnemy(best_item_num); - if (distance >= WALL_L) { - break; - } - } - - if (!found) { - Console_Log(GS(OSD_KILL_FAIL)); - return CR_FAILURE; - } - - Console_Log(GS(OSD_KILL)); - return CR_SUCCESS; - } - - // kill a single enemy type - { - bool matches_found = false; - int32_t num_killed = 0; - int32_t match_count = 0; - GAME_OBJECT_ID *matching_objs = - Object_IdsFromName(args, &match_count, M_CanTargetObjectCreature); - - for (int16_t item_num = 0; item_num < Item_GetTotalCount(); - item_num++) { - const ITEM_INFO *const item = &g_Items[item_num]; - - bool is_matched = false; - for (int32_t i = 0; i < match_count; i++) { - if (matching_objs[i] == item->object_id) { - is_matched = true; - break; - } - } - if (!is_matched) { - continue; - } - matches_found = true; - - if (Lara_Cheat_KillEnemy(item_num)) { - num_killed++; - } - } - Memory_FreePointer(&matching_objs); - - if (!matches_found) { - Console_Log(GS(OSD_INVALID_OBJECT), args); - return CR_FAILURE; - } - if (num_killed == 0) { - Console_Log(GS(OSD_OBJECT_NOT_FOUND), args); - return CR_FAILURE; - } - Console_Log(GS(OSD_KILL_ALL), num_killed); - return CR_SUCCESS; - } -} - -CONSOLE_COMMAND g_Console_Cmd_Kill = { - .prefix = "kill", - .proc = M_Entrypoint, -}; diff --git a/src/game/console/cmd/kill.h b/src/game/console/cmd/kill.h deleted file mode 100644 index 3766fe1f..00000000 --- a/src/game/console/cmd/kill.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -extern CONSOLE_COMMAND g_Console_Cmd_Kill; diff --git a/src/game/console/setup.c b/src/game/console/setup.c index edc0fbdb..9c962381 100644 --- a/src/game/console/setup.c +++ b/src/game/console/setup.c @@ -6,7 +6,6 @@ #include "game/console/cmd/exit_to_title.h" #include "game/console/cmd/flipmap.h" #include "game/console/cmd/fly.h" -#include "game/console/cmd/kill.h" #include "game/console/cmd/load_game.h" #include "game/console/cmd/play_demo.h" #include "game/console/cmd/play_level.h" @@ -16,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/src/game/creature.c b/src/game/creature.c index fb1b273b..390b33aa 100644 --- a/src/game/creature.c +++ b/src/game/creature.c @@ -952,5 +952,5 @@ bool Creature_IsEnemy(const ITEM_INFO *const item) bool Creature_IsAlly(const ITEM_INFO *const item) { - return Object_IsObjectType(item->object_id, g_FriendObjects); + return Object_IsObjectType(item->object_id, g_AllyObjects); } diff --git a/src/game/game_string.def b/src/game/game_string.def index 70f7ddc6..894f82be 100644 --- a/src/game/game_string.def +++ b/src/game/game_string.def @@ -13,15 +13,9 @@ GS_DEFINE(OSD_FLIPMAP_ON, "Flipmap set to ON") GS_DEFINE(OSD_FLIPMAP_OFF, "Flipmap set to OFF") GS_DEFINE(OSD_FLIPMAP_FAIL_ALREADY_ON, "Flipmap is already ON") GS_DEFINE(OSD_FLIPMAP_FAIL_ALREADY_OFF, "Flipmap is already OFF") -GS_DEFINE(OSD_KILL_ALL, "Poof! %d enemies gone!") -GS_DEFINE(OSD_KILL_ALL_FAIL, "Uh-oh, there are no enemies left to kill...") -GS_DEFINE(OSD_KILL, "Bye-bye!") -GS_DEFINE(OSD_KILL_FAIL, "No enemy nearby...") GS_DEFINE(OSD_COMPLETE_LEVEL, "Level complete!") GS_DEFINE(OSD_PLAY_LEVEL, "Loading %s") GS_DEFINE(OSD_INVALID_ROOM, "Invalid room: %d. Valid rooms are 0-%d") -GS_DEFINE(OSD_INVALID_OBJECT, "Invalid object") -GS_DEFINE(OSD_OBJECT_NOT_FOUND, "Object not found") GS_DEFINE(OSD_INVALID_LEVEL, "Invalid level") GS_DEFINE(OSD_INVALID_SAVE_SLOT, "Invalid save slot %d") GS_DEFINE(OSD_UNKNOWN_COMMAND, "Unknown command: %s") diff --git a/src/game/items.c b/src/game/items.c index a3653b81..c5119df6 100644 --- a/src/game/items.c +++ b/src/game/items.c @@ -732,3 +732,8 @@ int32_t Item_GetDistance( { return XYZ_32_GetDistance(&item->pos, target); } + +ITEM_INFO *Item_Get(const int16_t item_num) +{ + return &g_Items[item_num]; +} diff --git a/src/game/objects/vars.c b/src/game/objects/vars.c index b63e1fc4..b9391414 100644 --- a/src/game/objects/vars.c +++ b/src/game/objects/vars.c @@ -44,7 +44,7 @@ const GAME_OBJECT_ID g_EnemyObjects[] = { // clang-format on }; -const GAME_OBJECT_ID g_FriendObjects[] = { +const GAME_OBJECT_ID g_AllyObjects[] = { // clang-format off O_LARA, O_WINSTON, diff --git a/src/game/objects/vars.h b/src/game/objects/vars.h index 832e2059..563ed664 100644 --- a/src/game/objects/vars.h +++ b/src/game/objects/vars.h @@ -4,7 +4,7 @@ #include "global/types.h" extern const GAME_OBJECT_ID g_EnemyObjects[]; -extern const GAME_OBJECT_ID g_FriendObjects[]; +extern const GAME_OBJECT_ID g_AllyObjects[]; extern const GAME_OBJECT_ID g_PickupObjects[]; extern const GAME_OBJECT_ID g_DoorObjects[]; extern const GAME_OBJECT_ID g_TrapdoorObjects[]; diff --git a/subprojects/libtrx b/subprojects/libtrx index e3765893..41cd1a09 160000 --- a/subprojects/libtrx +++ b/subprojects/libtrx @@ -1 +1 @@ -Subproject commit e376589305ba378c34fafcdf143d07d2f14a8b77 +Subproject commit 41cd1a09e3ea1c445df702cd9fa0d7682761459f