diff --git a/data/tr1/ship/cfg/TR1X_gameflow.json5 b/data/tr1/ship/cfg/TR1X_gameflow.json5
index 566134982..f853cae49 100644
--- a/data/tr1/ship/cfg/TR1X_gameflow.json5
+++ b/data/tr1/ship/cfg/TR1X_gameflow.json5
@@ -338,7 +338,7 @@
{"type": "play_fmv", "fmv_id": 8},
{"type": "loading_screen", "path": "data/images/atlantis.webp"},
{"type": "load_level"},
- {"type": "give_item", "object_id": 84, "quantity": 1},
+ {"type": "give_item", "object_id": "pistols", "quantity": 1},
{"type": "setup_bacon_lara", "anchor_room": 10},
{"type": "play_level"},
{"type": "play_fmv", "fmv_id": 9},
@@ -378,7 +378,7 @@
"path": "data/cut1.phd",
"type": "cutscene",
"music_track": 0,
- "lara_type": 77,
+ "lara_type": "player_1",
"inherit_injections": false,
"injections": [
"data/injections/backpack_cut.bin",
@@ -401,7 +401,7 @@
"path": "data/cut2.phd",
"type": "cutscene",
"music_track": 0,
- "lara_type": 77,
+ "lara_type": "player_1",
"inherit_injections": false,
"injections": [
"data/injections/backpack_cut.bin",
@@ -413,8 +413,8 @@
{"type": "load_level"},
{"type": "set_cutscene_angle", "value": 16380},
{"type": "play_synced_audio", "audio_id": 25},
- {"type": "mesh_swap", "object1_id": 77, "object2_id": 1, "mesh_id": 1},
- {"type": "mesh_swap", "object1_id": 77, "object2_id": 1, "mesh_id": 4},
+ {"type": "mesh_swap", "object1_id": "player_1", "object2_id": "pistol_anim", "mesh_id": 1},
+ {"type": "mesh_swap", "object1_id": "player_1", "object2_id": "pistol_anim", "mesh_id": 4},
{"type": "play_level"},
{"type": "level_stats", "level_id": 9},
{"type": "exit_to_level", "level_id": 10},
@@ -449,7 +449,7 @@
"music_track": 0,
"draw_distance_fade": 12.0,
"draw_distance_max": 18.0,
- "lara_type": 77,
+ "lara_type": "player_1",
"inherit_injections": false,
"injections": [
"data/injections/backpack_cut.bin",
@@ -462,8 +462,8 @@
{"type": "load_level"},
{"type": "set_cutscene_angle", "value": 16384},
{"type": "play_synced_audio", "audio_id": 22},
- {"type": "mesh_swap", "object1_id": 77, "object2_id": 1, "mesh_id": 1},
- {"type": "mesh_swap", "object1_id": 77, "object2_id": 1, "mesh_id": 4},
+ {"type": "mesh_swap", "object1_id": "player_1", "object2_id": "pistol_anim", "mesh_id": 1},
+ {"type": "mesh_swap", "object1_id": "player_1", "object2_id": "pistol_anim", "mesh_id": 4},
{"type": "play_level"},
{"type": "level_stats", "level_id": 14},
{"type": "exit_to_level", "level_id": 15},
diff --git a/data/tr2/ship/cfg/TR2X_gameflow.json5 b/data/tr2/ship/cfg/TR2X_gameflow.json5
index afce2c21f..e2db05a2b 100644
--- a/data/tr2/ship/cfg/TR2X_gameflow.json5
+++ b/data/tr2/ship/cfg/TR2X_gameflow.json5
@@ -49,9 +49,9 @@
"music_track": 33,
"sequence": [
{"type": "play_fmv", "fmv_id": 2},
- {"type": "add_secret_reward", "item": "grenade_launcher"},
- {"type": "add_secret_reward", "item": "grenade_launcher_ammo", "qty": 2},
- {"type": "add_secret_reward", "item": "small_medipack"},
+ {"type": "add_secret_reward", "object_id": "grenade_launcher"},
+ {"type": "add_secret_reward", "object_id": "grenade_launcher_ammo", "quantity": 2},
+ {"type": "add_secret_reward", "object_id": "small_medipack"},
{"type": "play_level"},
{"type": "play_cutscene", "cutscene_id": 0},
{"type": "level_complete"},
@@ -66,7 +66,7 @@
"path": "data/boat.tr2",
"music_track": -1,
"sequence": [
- {"type": "add_secret_reward", "item": "magnums_ammo", "qty": 4},
+ {"type": "add_secret_reward", "object_id": "magnums_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -78,7 +78,7 @@
"music_track": -1,
"sequence": [
{"type": "enable_sunset"},
- {"type": "add_secret_reward", "item": "shotgun_ammo", "qty": 4},
+ {"type": "add_secret_reward", "object_id": "shotgun_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -89,8 +89,8 @@
"path": "data/opera.tr2",
"music_track": 31,
"sequence": [
- {"type": "add_secret_reward", "item": "uzis"},
- {"type": "add_secret_reward", "item": "uzis_ammo", "qty": 4},
+ {"type": "add_secret_reward", "object_id": "uzis"},
+ {"type": "add_secret_reward", "object_id": "uzis_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "play_cutscene", "cutscene_id": 1},
{"type": "level_complete"},
@@ -109,8 +109,8 @@
{"type": "play_fmv", "fmv_id": 3},
{"type": "set_lara_start_anim", "anim": 8},
{"type": "remove_weapons"},
- {"type": "add_secret_reward", "item": "uzis"},
- {"type": "add_secret_reward", "item": "uzis_ammo", "qty": 2},
+ {"type": "add_secret_reward", "object_id": "uzis"},
+ {"type": "add_secret_reward", "object_id": "uzis_ammo", "quantity": 2},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -124,7 +124,7 @@
"path": "data/platform.tr2",
"music_track": 58,
"sequence": [
- {"type": "add_secret_reward", "item": "uzis_ammo", "qty": 4},
+ {"type": "add_secret_reward", "object_id": "uzis_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "play_cutscene", "cutscene_id": 2},
{"type": "level_complete"},
@@ -140,7 +140,7 @@
"music_track": 34,
"sequence": [
{"type": "play_fmv", "fmv_id": 4},
- {"type": "add_secret_reward", "item": "harpoon_gun_ammo", "qty": 4},
+ {"type": "add_secret_reward", "object_id": "harpoon_gun_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -151,8 +151,8 @@
"path": "data/keel.tr2",
"music_track": 31,
"sequence": [
- {"type": "add_secret_reward", "item": "grenade_launcher"},
- {"type": "add_secret_reward", "item": "grenade_launcher_ammo", "qty": 2},
+ {"type": "add_secret_reward", "object_id": "grenade_launcher"},
+ {"type": "add_secret_reward", "object_id": "grenade_launcher_ammo", "quantity": 2},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -167,7 +167,7 @@
"path": "data/living.tr2",
"music_track": 34,
"sequence": [
- {"type": "add_secret_reward", "item": "m16_ammo", "qty": 4},
+ {"type": "add_secret_reward", "object_id": "m16_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -178,7 +178,7 @@
"path": "data/deck.tr2",
"music_track": 31,
"sequence": [
- {"type": "add_secret_reward", "item": "grenade_launcher_ammo", "qty": 4},
+ {"type": "add_secret_reward", "object_id": "grenade_launcher_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -193,8 +193,8 @@
"music_track": 33,
"sequence": [
{"type": "play_fmv", "fmv_id": 5},
- {"type": "give_item", "item": "puzzle_4"},
- {"type": "add_secret_reward", "item": "uzis_ammo", "qty": 4},
+ {"type": "give_item", "object_id": "puzzle_4"},
+ {"type": "add_secret_reward", "object_id": "uzis_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -209,8 +209,8 @@
"path": "data/monastry.tr2",
"music_track": -1,
"sequence": [
- {"type": "give_item", "item": "puzzle_4"},
- {"type": "add_secret_reward", "item": "m16_ammo", "qty": 4},
+ {"type": "give_item", "object_id": "puzzle_4"},
+ {"type": "add_secret_reward", "object_id": "m16_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -224,8 +224,8 @@
"path": "data/catacomb.tr2",
"music_track": 31,
"sequence": [
- {"type": "add_secret_reward", "item": "grenade_launcher_ammo", "qty": 2},
- {"type": "add_secret_reward", "item": "m16_ammo", "qty": 2},
+ {"type": "add_secret_reward", "object_id": "grenade_launcher_ammo", "quantity": 2},
+ {"type": "add_secret_reward", "object_id": "m16_ammo", "quantity": 2},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -240,7 +240,7 @@
"path": "data/icecave.tr2",
"music_track": 31,
"sequence": [
- {"type": "add_secret_reward", "item": "grenade_launcher_ammo", "qty": 4},
+ {"type": "add_secret_reward", "object_id": "grenade_launcher_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -256,7 +256,7 @@
"music_track": 59,
"sequence": [
{"type": "play_fmv", "fmv_id": 6},
- {"type": "add_secret_reward", "item": "uzis_ammo", "qty": 8},
+ {"type": "add_secret_reward", "object_id": "uzis_ammo", "quantity": 8},
{"type": "play_level"},
{"type": "play_cutscene", "cutscene_id": 3},
{"type": "level_complete"},
@@ -273,7 +273,7 @@
"music_track": 59,
"sequence": [
{"type": "disable_floor", "height": 9728},
- {"type": "add_secret_reward", "item": "grenade_launcher_ammo", "qty": 8},
+ {"type": "add_secret_reward", "object_id": "grenade_launcher_ammo", "quantity": 8},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -301,7 +301,7 @@
"music_track": -1,
"sequence": [
{"type": "set_secret_count", "count": 0},
- {"type": "give_item", "item": "key_1"},
+ {"type": "give_item", "object_id": "key_1"},
{"type": "set_lara_start_anim", "anim": 9},
{"type": "remove_weapons"},
{"type": "remove_ammo"},
@@ -320,7 +320,7 @@
"path": "data/boat.tr2",
"music_track": -1,
"sequence": [
- {"type": "add_secret_reward", "item": "magnums_ammo", "qty": 4},
+ {"type": "add_secret_reward", "object_id": "magnums_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -331,8 +331,8 @@
"path": "data/keel.tr2",
"music_track": 31,
"sequence": [
- {"type": "add_secret_reward", "item": "grenade_launcher"},
- {"type": "add_secret_reward", "item": "grenade_launcher_ammo", "qty": 2},
+ {"type": "add_secret_reward", "object_id": "grenade_launcher"},
+ {"type": "add_secret_reward", "object_id": "grenade_launcher_ammo", "quantity": 2},
{"type": "play_level"},
{"type": "level_complete"},
],
@@ -347,8 +347,8 @@
"path": "data/skidoo.tr2",
"music_track": 33,
"sequence": [
- {"type": "give_item", "item": "puzzle_4"},
- {"type": "add_secret_reward", "item": "uzis_ammo", "qty": 4},
+ {"type": "give_item", "object_id": "puzzle_4"},
+ {"type": "add_secret_reward", "object_id": "uzis_ammo", "quantity": 4},
{"type": "play_level"},
{"type": "level_complete"},
],
diff --git a/docs/tr1/GAMEFLOW.md b/docs/tr1/GAMEFLOW.md
index 15567fc57..34f619fb3 100644
--- a/docs/tr1/GAMEFLOW.md
+++ b/docs/tr1/GAMEFLOW.md
@@ -336,7 +336,7 @@ Following are each of the properties available within a level.
lara_type
|
- Integer |
+ Integer / string |
No |
Used only in cutscene levels to link the braid (if enabled) to the
@@ -562,7 +562,7 @@ default gameflow for examples.
|
object_id
|
- Integer |
+ Integer / String |
Adds the specified item and quantity to Lara's inventory. If used, this
must appear after the load_level sequence.
@@ -929,7 +929,7 @@ This translates as follows.
|
object_ids
|
- Integer array |
+ Integer / string array |
A list of item types to drop. These items will spawn dynamically
and do not need to be added to the level file. Duplicate IDs are permitted
diff --git a/src/tr1/game/game_flow/reader.c b/src/tr1/game/game_flow/reader.c
index 107884d03..1b6f99985 100644
--- a/src/tr1/game/game_flow/reader.c
+++ b/src/tr1/game/game_flow/reader.c
@@ -9,6 +9,7 @@
#include
#include
+#include
#include
#include
#include
@@ -31,9 +32,10 @@ typedef void (*M_LOAD_ARRAY_FUNC)(
static void M_LoadArray(
JSON_OBJECT *obj, const char *key, size_t element_size,
- M_LOAD_ARRAY_FUNC load_func, GAME_FLOW *const gf, int32_t *const count,
- void **const elements, void *user_arg);
+ M_LOAD_ARRAY_FUNC load_func, GAME_FLOW *gf, int32_t *count, void **elements,
+ void *user_arg);
+static GAME_OBJECT_ID M_GetObjectFromJSONValue(const JSON_VALUE *value);
static bool M_IsLegacySequence(const char *type_str);
static int32_t M_HandleIntEvent(
JSON_OBJECT *event_obj, GAME_FLOW_SEQUENCE_EVENT *event, void *extra_data,
@@ -102,6 +104,24 @@ static M_SEQUENCE_EVENT_HANDLER m_SequenceEventHandlers[] = {
// clang-format on
};
+static GAME_OBJECT_ID M_GetObjectFromJSONValue(const JSON_VALUE *const value)
+{
+ int32_t object_id = JSON_ValueGetInt(value, JSON_INVALID_NUMBER);
+ if (object_id == JSON_INVALID_NUMBER) {
+ const char *const object_key =
+ JSON_ValueGetString(value, JSON_INVALID_STRING);
+ if (object_key == JSON_INVALID_STRING) {
+ return NO_OBJECT;
+ }
+ object_id = Object_IdFromKey(object_key);
+ LOG_DEBUG("Chuj %s: %d", object_key, object_id);
+ }
+ if (object_id < 0 || object_id >= O_NUMBER_OF) {
+ return NO_OBJECT;
+ }
+ return object_id;
+}
+
static void M_LoadArray(
JSON_OBJECT *const obj, const char *const key, const size_t element_size,
M_LOAD_ARRAY_FUNC load_func, GAME_FLOW *const gf, int32_t *const count,
@@ -135,8 +155,8 @@ static bool M_IsLegacySequence(const char *const type_str)
}
static int32_t M_HandleIntEvent(
- JSON_OBJECT *event_obj, GAME_FLOW_SEQUENCE_EVENT *event, void *extra_data,
- void *user_arg)
+ JSON_OBJECT *const event_obj, GAME_FLOW_SEQUENCE_EVENT *const event,
+ void *const extra_data, void *const user_arg)
{
if (event != NULL) {
event->data =
@@ -146,12 +166,12 @@ static int32_t M_HandleIntEvent(
}
static int32_t M_HandlePictureEvent(
- JSON_OBJECT *event_obj, GAME_FLOW_SEQUENCE_EVENT *event, void *extra_data,
- void *user_arg)
+ JSON_OBJECT *const event_obj, GAME_FLOW_SEQUENCE_EVENT *const event,
+ void *const extra_data, void *const user_arg)
{
const char *const path = JSON_ObjectGetString(event_obj, "path", NULL);
if (path == NULL) {
- LOG_ERROR("Missing picture path");
+ Shell_ExitSystem("Missing picture path");
return -1;
}
if (event != NULL) {
@@ -167,13 +187,13 @@ static int32_t M_HandlePictureEvent(
}
static int32_t M_HandleTotalStatsEvent(
- JSON_OBJECT *event_obj, GAME_FLOW_SEQUENCE_EVENT *event, void *extra_data,
- void *user_arg)
+ JSON_OBJECT *const event_obj, GAME_FLOW_SEQUENCE_EVENT *const event,
+ void *const extra_data, void *const user_arg)
{
const char *const path =
JSON_ObjectGetString(event_obj, "background_path", NULL);
if (path == NULL) {
- LOG_ERROR("Missing picture path");
+ Shell_ExitSystem("Missing picture path");
return -1;
}
if (event != NULL) {
@@ -185,13 +205,13 @@ static int32_t M_HandleTotalStatsEvent(
}
static int32_t M_HandleAddItemEvent(
- JSON_OBJECT *event_obj, GAME_FLOW_SEQUENCE_EVENT *event, void *extra_data,
- void *user_arg)
+ JSON_OBJECT *const event_obj, GAME_FLOW_SEQUENCE_EVENT *const event,
+ void *const extra_data, void *const user_arg)
{
const GAME_OBJECT_ID object_id =
- JSON_ObjectGetInt(event_obj, "object_id", JSON_INVALID_NUMBER);
- if (object_id == JSON_INVALID_NUMBER) {
- LOG_ERROR("Invalid item: %s", object_id);
+ M_GetObjectFromJSONValue(JSON_ObjectGetValue(event_obj, "object_id"));
+ if (object_id == NO_OBJECT) {
+ Shell_ExitSystem("Invalid item");
return -1;
}
if (event != NULL) {
@@ -204,19 +224,19 @@ static int32_t M_HandleAddItemEvent(
}
static int32_t M_HandleMeshSwapEvent(
- JSON_OBJECT *event_obj, GAME_FLOW_SEQUENCE_EVENT *event, void *extra_data,
- void *user_arg)
+ JSON_OBJECT *const event_obj, GAME_FLOW_SEQUENCE_EVENT *const event,
+ void *const extra_data, void *const user_arg)
{
const GAME_OBJECT_ID object1_id =
- JSON_ObjectGetInt(event_obj, "object1_id", JSON_INVALID_NUMBER);
- if (object1_id == JSON_INVALID_NUMBER) {
- Shell_ExitSystem("'object1_id' must be a number");
+ M_GetObjectFromJSONValue(JSON_ObjectGetValue(event_obj, "object1_id"));
+ if (object1_id == NO_OBJECT) {
+ Shell_ExitSystem("'object1_id' is invalid");
}
const GAME_OBJECT_ID object2_id =
- JSON_ObjectGetInt(event_obj, "object2_id", JSON_INVALID_NUMBER);
- if (object2_id == JSON_INVALID_NUMBER) {
- Shell_ExitSystem("'object2_id' must be a number");
+ M_GetObjectFromJSONValue(JSON_ObjectGetValue(event_obj, "object2_id"));
+ if (object2_id == NO_OBJECT) {
+ Shell_ExitSystem("'object2_id' is invalid");
}
const int32_t mesh_num =
@@ -286,8 +306,8 @@ static size_t M_LoadSequenceEvent(
handler++;
}
if (handler->event_type != type) {
- LOG_ERROR("Unknown game flow sequence event type: '%s'", type);
- return -1;
+ Shell_ExitSystemFmt(
+ "Unknown game flow sequence event type: '%s'", type);
}
int32_t extra_data_size = 0;
@@ -371,7 +391,7 @@ static void M_LoadLevels(JSON_OBJECT *const obj, GAME_FLOW *const gf)
g_GameInfo.current = Memory_Alloc(sizeof(RESUME_INFO) * level_count);
JSON_ARRAY_ELEMENT *jlvl_elem = jlvl_arr->start;
- int level_num = 0;
+ int32_t level_num = 0;
gf->has_demo = 0;
gf->gym_level_num = -1;
@@ -477,9 +497,9 @@ static void M_LoadLevels(JSON_OBJECT *const obj, GAME_FLOW *const gf)
level->injections.data_paths =
Memory_Alloc(sizeof(char *) * level->injections.count);
- int inj_base_index = 0;
+ int32_t inj_base_index = 0;
if (tmp_i) {
- for (int i = 0; i < gf->injections.count; i++) {
+ for (int32_t i = 0; i < gf->injections.count; i++) {
level->injections.data_paths[i] =
Memory_DupStr(gf->injections.data_paths[i]);
}
@@ -495,7 +515,7 @@ static void M_LoadLevels(JSON_OBJECT *const obj, GAME_FLOW *const gf)
level->injections.count = gf->injections.count;
level->injections.data_paths =
Memory_Alloc(sizeof(char *) * level->injections.count);
- for (int i = 0; i < gf->injections.count; i++) {
+ for (int32_t i = 0; i < gf->injections.count; i++) {
level->injections.data_paths[i] =
Memory_DupStr(gf->injections.data_paths[i]);
}
@@ -503,13 +523,20 @@ static void M_LoadLevels(JSON_OBJECT *const obj, GAME_FLOW *const gf)
level->injections.count = 0;
}
- tmp_i = JSON_ObjectGetInt(jlvl_obj, "lara_type", (int32_t)O_LARA);
- if (tmp_i < 0 || tmp_i >= O_NUMBER_OF) {
- Shell_ExitSystemFmt(
- "level %d: 'lara_type' must be a valid game object id",
- level_num);
+ {
+ JSON_VALUE *const tmp_v =
+ JSON_ObjectGetValue(jlvl_obj, "lara_type");
+ if (tmp_v == NULL) {
+ level->lara_type = O_LARA;
+ } else {
+ level->lara_type = M_GetObjectFromJSONValue(tmp_v);
+ }
+ if (level->lara_type == NO_OBJECT) {
+ Shell_ExitSystemFmt(
+ "level %d: 'lara_type' must be a valid game object id",
+ level_num);
+ }
}
- level->lara_type = (GAME_OBJECT_ID)tmp_i;
tmp_arr = JSON_ObjectGetArray(jlvl_obj, "item_drops");
level->item_drops.count = 0;
@@ -523,7 +550,7 @@ static void M_LoadLevels(JSON_OBJECT *const obj, GAME_FLOW *const gf)
level->item_drops.data = Memory_Alloc(
sizeof(GAME_FLOW_DROP_ITEM_DATA) * (signed)tmp_arr->length);
- for (int i = 0; i < level->item_drops.count; i++) {
+ for (int32_t i = 0; i < level->item_drops.count; i++) {
GAME_FLOW_DROP_ITEM_DATA *data = &level->item_drops.data[i];
JSON_OBJECT *jlvl_data = JSON_ArrayGetObject(tmp_arr, i);
@@ -545,9 +572,10 @@ static void M_LoadLevels(JSON_OBJECT *const obj, GAME_FLOW *const gf)
data->count = (signed)object_arr->length;
data->object_ids = Memory_Alloc(sizeof(int16_t) * data->count);
- for (int j = 0; j < data->count; j++) {
- int id = JSON_ArrayGetInt(object_arr, j, -1);
- if (id < 0 || id >= O_NUMBER_OF) {
+ for (int32_t j = 0; j < data->count; j++) {
+ const GAME_OBJECT_ID id = M_GetObjectFromJSONValue(
+ JSON_ArrayGetValue(object_arr, j));
+ if (id == NO_OBJECT) {
Shell_ExitSystemFmt(
"level %d, item drop %d, index %d: 'object_id' "
"must be a valid object id",
@@ -594,7 +622,7 @@ static void M_LoadFMVs(JSON_OBJECT *const obj, GAME_FLOW *const gf)
static void M_LoadRoot(JSON_OBJECT *const obj, GAME_FLOW *const gf)
{
const char *tmp_s;
- int tmp_i;
+ int32_t tmp_i;
double tmp_d;
JSON_ARRAY *tmp_arr;
diff --git a/src/tr2/game/game_flow/reader.c b/src/tr2/game/game_flow/reader.c
index f80a5b6b4..120898383 100644
--- a/src/tr2/game/game_flow/reader.c
+++ b/src/tr2/game/game_flow/reader.c
@@ -28,9 +28,15 @@ typedef void (*M_LOAD_ARRAY_FUNC)(
JSON_OBJECT *source_elem, GAME_FLOW *gf, void *target_elem,
size_t target_elem_idx, void *user_arg);
+static GAME_OBJECT_ID M_GetObjectFromJSONValue(const JSON_VALUE *value);
static GAME_FLOW_COMMAND M_LoadCommand(
JSON_OBJECT *jcmd, GAME_FLOW_COMMAND fallback);
+static void M_LoadArray(
+ JSON_OBJECT *obj, const char *key, size_t element_size,
+ M_LOAD_ARRAY_FUNC load_func, GAME_FLOW *gf, int32_t *count, void **elements,
+ void *user_arg);
+
static int32_t M_HandleIntEvent(
JSON_OBJECT *event_obj, GAME_FLOW_SEQUENCE_EVENT *event, void *extra_data,
void *user_arg);
@@ -47,11 +53,6 @@ static void M_LoadSequence(JSON_ARRAY *jarr, GAME_FLOW_SEQUENCE *sequence);
static void M_LoadGlobalInjections(JSON_OBJECT *obj, GAME_FLOW *gf);
static void M_LoadRoot(JSON_OBJECT *obj, GAME_FLOW *gf);
-static void M_LoadArray(
- JSON_OBJECT *obj, const char *key, size_t element_size,
- M_LOAD_ARRAY_FUNC load_func, GAME_FLOW *const gf, int32_t *const count,
- void **const elements, void *user_arg);
-
static void M_LoadLevel(
JSON_OBJECT *obj, const GAME_FLOW *gf, GAME_FLOW_LEVEL *level, size_t idx,
void *user_arg);
@@ -95,6 +96,23 @@ static M_SEQUENCE_EVENT_HANDLER m_SequenceEventHandlers[] = {
// clang-format on
};
+static GAME_OBJECT_ID M_GetObjectFromJSONValue(const JSON_VALUE *const value)
+{
+ int32_t object_id = JSON_ValueGetInt(value, JSON_INVALID_NUMBER);
+ if (object_id == JSON_INVALID_NUMBER) {
+ const char *const object_key =
+ JSON_ValueGetString(value, JSON_INVALID_STRING);
+ if (object_key == JSON_INVALID_STRING) {
+ return NO_OBJECT;
+ }
+ object_id = Object_IdFromKey(object_key);
+ }
+ if (object_id < 0 || object_id >= O_NUMBER_OF) {
+ return NO_OBJECT;
+ }
+ return object_id;
+}
+
static GAME_FLOW_COMMAND M_LoadCommand(
JSON_OBJECT *const jcmd, const GAME_FLOW_COMMAND fallback)
{
@@ -106,14 +124,14 @@ static GAME_FLOW_COMMAND M_LoadCommand(
JSON_ObjectGetString(jcmd, "action", JSON_INVALID_STRING);
const int32_t param = JSON_ObjectGetInt(jcmd, "param", -1);
if (action_str == JSON_INVALID_STRING) {
- LOG_ERROR("Unknown game flow action: %s", action_str);
+ Shell_ExitSystemFmt("Unknown game flow action: %s", action_str);
return fallback;
}
const GAME_FLOW_ACTION action =
ENUM_MAP_GET(GAME_FLOW_ACTION, action_str, (GAME_FLOW_ACTION)-1234);
if (action == (GAME_FLOW_ACTION)-1234) {
- LOG_ERROR("Unknown game flow action: %s", action_str);
+ Shell_ExitSystemFmt("Unknown game flow action: %s", action_str);
return fallback;
}
@@ -121,8 +139,8 @@ static GAME_FLOW_COMMAND M_LoadCommand(
}
static int32_t M_HandleIntEvent(
- JSON_OBJECT *event_obj, GAME_FLOW_SEQUENCE_EVENT *event, void *extra_data,
- void *user_arg)
+ JSON_OBJECT *const event_obj, GAME_FLOW_SEQUENCE_EVENT *const event,
+ void *const extra_data, void *const user_arg)
{
if (event != NULL) {
event->data =
@@ -132,12 +150,12 @@ static int32_t M_HandleIntEvent(
}
static int32_t M_HandlePictureEvent(
- JSON_OBJECT *event_obj, GAME_FLOW_SEQUENCE_EVENT *event, void *extra_data,
- void *user_arg)
+ JSON_OBJECT *const event_obj, GAME_FLOW_SEQUENCE_EVENT *const event,
+ void *const extra_data, void *const user_arg)
{
const char *const path = JSON_ObjectGetString(event_obj, "path", NULL);
if (path == NULL) {
- LOG_ERROR("Missing picture path");
+ Shell_ExitSystem("Missing picture path");
return -1;
}
if (event != NULL) {
@@ -153,21 +171,21 @@ static int32_t M_HandlePictureEvent(
}
static int32_t M_HandleAddItemEvent(
- JSON_OBJECT *event_obj, GAME_FLOW_SEQUENCE_EVENT *event, void *extra_data,
- void *user_arg)
+ JSON_OBJECT *const event_obj, GAME_FLOW_SEQUENCE_EVENT *const event,
+ void *const extra_data, void *const user_arg)
{
+ const GAME_OBJECT_ID object_id =
+ M_GetObjectFromJSONValue(JSON_ObjectGetValue(event_obj, "object_id"));
+ if (object_id == NO_OBJECT) {
+ Shell_ExitSystem("Invalid item");
+ return -1;
+ }
if (event != NULL) {
- const char *const object_key =
- JSON_ObjectGetString(event_obj, "item", JSON_INVALID_STRING);
- const GAME_OBJECT_ID object_id = Object_IdFromKey(object_key);
- if (object_id == NO_OBJECT) {
- LOG_ERROR("Invalid item: %s", object_key);
- }
GAME_FLOW_ADD_ITEM_DATA *const event_data = extra_data;
event_data->object_id = object_id;
+ event_data->qty = JSON_ObjectGetInt(event_obj, "quantity", 1);
event_data->inv_type =
event->type == GFS_ADD_ITEM ? GF_INV_REGULAR : GF_INV_SECRET;
- event_data->qty = JSON_ObjectGetInt(event_obj, "qty", 1);
event->data = event_data;
}
return sizeof(GAME_FLOW_ADD_ITEM_DATA);
@@ -188,7 +206,8 @@ static size_t M_LoadSequenceEvent(
}
if (handler->event_type != type) {
- LOG_ERROR("Unknown game flow sequence event type: '%s'", type);
+ Shell_ExitSystemFmt(
+ "Unknown game flow sequence event type: '%s'", type);
return -1;
}
|