diff --git a/custom_levels/jak1/test-zone/test-zone.jsonc b/custom_levels/jak1/test-zone/test-zone.jsonc index eedcdfa8f7..342edc56dc 100644 --- a/custom_levels/jak1/test-zone/test-zone.jsonc +++ b/custom_levels/jak1/test-zone/test-zone.jsonc @@ -20,16 +20,30 @@ // this makes collision 2x slower and bigger, so only use if really needed "double_sided_collide": false, - // available res-lump tag data types: - // int32, float, meters, vector, vector4m (meters) + // available res-lump tag types: + // value types: int32, uint32, enum-int32, enum-uint32, float, meters (1 meter = 4096.0 units), degrees (65536.0 = 360°) + // vector types: vector (normal floats), vector4m (meters), vector3m (meters with w set to 1.0), vector-vol (normal floats with w in meters), movie-pos (meters with w in degrees) + // special types: eco-info, water-height // // examples: // // adds a float tag 'spring-height' with value of 200 meters (1 meter = 4096.0 units): // "spring-height": ["meters", 200.0] // - // adds a vector tag 'movie-pos': - // "movie-pos": ["vector", [4096000.0, -176128.0, 1353973.76, 1.0]] + // adds a degrees tag 'rotoffset': + // "rotoffset": ["degrees", -45.0] + // + // adds a movie-pos tag: + // "movie-pos": ["movie-pos", [100.22, -25.3, 99.5, 180.0]] + // + // adds an enum tag 'options': + // "options": ["enum-int32", "(fact-options large)"] + // + // adds a water-height tag: + // "water-height": ["water-height", 25.0, 0.5, 2.0, "(water-flags wt08 wt03 wt01)"] + // + // adds an eco-info tag: + // "eco-info": ["eco-info", "(pickup-type health)", 2] // The base actor id for your custom level. If you have multiple levels this should be unique! "base_id": 100, @@ -65,7 +79,7 @@ "lump": { "name": "test-ambient", "type": "'hint", - "text-id": ["int32", 557], // text id for the "POWER CELL" text + "text-id": ["enum-uint32", "(text-id fuel-cell)"], // text id for the "POWER CELL" text "play-mode": "'notice" } } @@ -75,7 +89,7 @@ { "trans": [-21.6238, 20.0496, 17.1191], // translation "etype": "fuel-cell", // actor type - "game_task": 0, // associated game task (for powercells, etc) + "game_task": "(game-task none)", // associated game task (for powercells, etc) "quat": [0, 0, 0, 1], // quaternion "bsphere": [-21.6238, 19.3496, 17.1191, 10], // bounding sphere "lump": { @@ -86,20 +100,20 @@ { "trans": [-15.2818, 15.2461, 17.1360], // translation "etype": "crate", // actor type - "game_task": 0, // associated game task (for powercells, etc) + "game_task": "(game-task none)", // associated game task (for powercells, etc) "quat": [0, 0, 0, 1], // quaternion "bsphere": [-15.2818, 15.2461, 17.1360, 10], // bounding sphere "lump": { "name": "test-crate", "crate-type": "'steel", - "eco-info": ["int32", 5, 10] + "eco-info": ["eco-info", "(pickup-type money)", 10] } }, { "trans": [-5.4630, 17.4553, 1.6169], // translation "etype": "eco-yellow", // actor type - "game_task": 0, // associated game task (for powercells, etc) + "game_task": "(game-task none)", // associated game task (for powercells, etc) "quat": [0, 0, 0, 1], // quaternion "bsphere": [-5.4630, 17.4553, 1.6169, 10], // bounding sphere "lump": { @@ -109,7 +123,7 @@ // { // "trans": [-7.41, 3.5, 28.42], // translation // "etype": "plat", // actor type - // "game_task": 0, // associated game task (for powercells, etc) + // "game_task": "(game-task none)", // associated game task (for powercells, etc) // "quat": [0, 0, 0, 1], // quaternion // "bsphere": [-7.41, 3.5, 28.42, 10], // bounding sphere // "lump": { diff --git a/custom_levels/jak2/test-zone/test-zone.jsonc b/custom_levels/jak2/test-zone/test-zone.jsonc index 87ba939e81..92573d5267 100644 --- a/custom_levels/jak2/test-zone/test-zone.jsonc +++ b/custom_levels/jak2/test-zone/test-zone.jsonc @@ -20,24 +20,37 @@ // this makes collision 2x slower and bigger, so only use if really needed "double_sided_collide": false, - // available res-lump tag data types: - // int32, float, meters, vector, vector4m (meters) + // available res-lump tag types: + // value types: int32, uint32, enum-int32, enum-uint32, float, meters (1 meter = 4096.0 units), degrees (65536.0 = 360°) + // vector types: vector (normal floats), vector4m (meters), vector3m (meters with w set to 1.0), vector-vol (normal floats with w in meters), movie-pos (meters with w in degrees) + // special types: eco-info, water-height // // examples: // // adds a float tag 'spring-height' with value of 200 meters (1 meter = 4096.0 units): // "spring-height": ["meters", 200.0] // - // adds a vector tag 'movie-pos': - // "movie-pos": ["vector", [4096000.0, -176128.0, 1353973.76, 1.0]] + // adds a degrees tag 'rotoffset': + // "rotoffset": ["degrees", -45.0] + // + // adds a movie-pos tag: + // "movie-pos": ["movie-pos", [100.22, -25.3, 99.5, 180.0]] + // + // adds an enum tag 'options': + // "options": ["enum-int32", "(fact-options large)"] + // + // adds a water-height tag: + // "water-height": ["water-height", 25.0, 0.5, 2.0, "(water-flags can-swim can-wade)"] + // + // adds an eco-info tag: + // "eco-info": ["eco-info", "(pickup-type health)", 2] // The base actor id for your custom level. If you have multiple levels, this should be unique! "base_id": 100, // All art groups you want to use in your custom level. Will add their models and corresponding textures to the FR3 file. // Removed so that the release builds don't have to double-decompile the game - //"art_groups": ["prsn-torture-ag"], - "art_groups": [], + // "art_groups": ["prsn-torture-ag"], // Any textures you want to include in your custom level. // This is mainly useful for textures which are not in the common level files and have no art group associated with them. @@ -55,14 +68,14 @@ "bsphere": [-15.2818, 15.2461, 17.1360, 10], // bounding sphere "lump": { "name": "test-crate", - "eco-info": ["int32", 18, 2] + "eco-info": ["eco-info", "(pickup-type health)", 2] } }, { "trans": [-5.4630, 17.4553, 1.6169], // translation "etype": "eco-yellow", // actor type - "game_task": 0, // associated game task (for powercells, etc) + "game_task": "(game-task none)", // associated game task (for powercells, etc) "kill_mask": 0, "quat": [0, 0, 0, 1], // quaternion "bsphere": [-5.4630, 17.4553, 1.6169, 10], // bounding sphere @@ -74,7 +87,7 @@ { "trans": [-7.41, 13.5, 28.42], // translation "etype": "prsn-torture", // actor type - "game_task": 0, // associated game task (for powercells, etc) + "game_task": "(game-task none)", // associated game task (for powercells, etc) "quat": [0, 0, 0, 1], // quaternion "bsphere": [-7.41, 13.5, 28.42, 10], // bounding sphere "lump": { diff --git a/decompiler/util/DecompilerTypeSystem.cpp b/decompiler/util/DecompilerTypeSystem.cpp index 7272ef21f6..d006ab704d 100644 --- a/decompiler/util/DecompilerTypeSystem.cpp +++ b/decompiler/util/DecompilerTypeSystem.cpp @@ -115,6 +115,29 @@ void DecompilerTypeSystem::parse_type_defs(const std::vector& file_ }); } +void DecompilerTypeSystem::parse_enum_defs(const std::vector& file_path) { + auto read = m_reader.read_from_file(file_path); + auto& data = cdr(read); + + for_each_in_list(data, [&](goos::Object& o) { + try { + if (car(o).as_symbol() == "defenum") { + auto symbol_metadata = DefinitionMetadata(); + parse_defenum(cdr(o), &ts, &symbol_metadata); + symbol_metadata.definition_info = m_reader.db.get_short_info_for(o); + auto* rest = &cdr(o); + const auto& enum_name = car(*rest).as_symbol(); + symbol_metadata_map[enum_name.name_ptr] = symbol_metadata; + // so far, enums are never runtime types so there's no symbol for them. + } + } catch (std::exception& e) { + auto info = m_reader.db.get_info_for(o); + lg::error("{} when parsing decompiler type file:{}", e.what(), info); + throw; + } + }); +} + TypeSpec DecompilerTypeSystem::parse_type_spec(const std::string& str) const { auto read = m_reader.read_from_string(str); auto data = cdr(read); diff --git a/decompiler/util/DecompilerTypeSystem.h b/decompiler/util/DecompilerTypeSystem.h index b6569168f6..dcff54bb1c 100644 --- a/decompiler/util/DecompilerTypeSystem.h +++ b/decompiler/util/DecompilerTypeSystem.h @@ -56,6 +56,7 @@ class DecompilerTypeSystem { const TypeSpec& type_spec, const DefinitionMetadata& symbol_metadata); void parse_type_defs(const std::vector& file_path); + void parse_enum_defs(const std::vector& file_path); TypeSpec parse_type_spec(const std::string& str) const; void add_type_flags(const std::string& name, u64 flags); void add_type_parent(const std::string& child, const std::string& parent); diff --git a/goalc/build_level/common/Entity.cpp b/goalc/build_level/common/Entity.cpp index 4f3ed66c77..e1c51135f1 100644 --- a/goalc/build_level/common/Entity.cpp +++ b/goalc/build_level/common/Entity.cpp @@ -38,58 +38,233 @@ math::Vector4f vector_from_json(const nlohmann::json& json) { return result; } +math::Vector4f vector_vol_from_json(const nlohmann::json& json) { + ASSERT(json.size() == 4); + math::Vector4f result; + for (int i = 0; i < 3; i++) { + result[i] = json[i].get(); + } + result[3] = json[3].get() * METER_LENGTH; + return result; +} + +u64 parse_enum(EnumType* e, goos::Object& rest) { + if (e->is_bitfield()) { + u64 value = 0; + for_each_in_list(rest, [&](const goos::Object& o) { + auto kv = e->entries().find(o.as_symbol().name_ptr); + ASSERT_MSG(kv != e->entries().end(), + fmt::format("The value {} was not found in enum.", o.print())); + value |= ((u64)1 << (u64)kv->second); + }); + return value; + } else { + u64 value = 0; + bool got = false; + for_each_in_list(rest, [&](const goos::Object& o) { + ASSERT_MSG(!got, "Invalid enum lookup."); + auto kv = e->entries().find(o.as_symbol().name_ptr); + ASSERT_MSG(kv != e->entries().end(), + fmt::format("The value {} was not found in enum.", o.print())); + value = kv->second; + got = true; + }); + ASSERT_MSG(got, "Invalid enum lookup."); + return value; + } +} + +u64 get_enum_val(const std::string& val, decompiler::DecompilerTypeSystem& dts) { + auto& reader = pretty_print::get_pretty_printer_reader(); + auto value = reader.read_from_string(val).as_pair()->cdr.as_pair()->car; + auto type = value.as_pair()->car.as_symbol().name_ptr; + auto rest = value.as_pair()->cdr; + auto enum_def = dts.ts.try_enum_lookup(type); + ASSERT_MSG(enum_def, fmt::format("Enum {} was not found.", type)); + return parse_enum(enum_def, rest); +} + +template +std::vector enum_from_json(const nlohmann::json& json, decompiler::DecompilerTypeSystem& dts) { + std::vector result; + for (const auto& entry : json) { + result.push_back(static_cast(get_enum_val(entry.get(), dts))); + } + return result; +} + +static std::unordered_map(const std::string&, + const nlohmann::json&, + decompiler::DecompilerTypeSystem&)>> + lump_map = { + {"int32", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(json[i].get()); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"uint32", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(json[i].get()); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"enum-int32", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data = enum_from_json(json[i], dts); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"enum-uint32", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data = enum_from_json(json[i], dts); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"eco-info", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + std::vector data; + // pickup-type + data.push_back(static_cast(get_enum_val(json[1].get(), dts))); + // amount + data.push_back(json[2].get()); + return std::make_unique(name, data, -1000000000.0000); + }}, + {"water-height", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + std::vector data; + // water-height + data.push_back(json[1].get() * METER_LENGTH); + // wade-height + data.push_back(json[2].get() * METER_LENGTH); + // swim-height + data.push_back(json[3].get() * METER_LENGTH); + // water-flags + data.push_back(static_cast(get_enum_val(json[4].get(), dts))); + // bottom-height + if (json.size() >= 6) { + data.push_back(json[5].get() * METER_LENGTH); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"vector", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(vector_from_json(json[i])); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"vector4m", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(vectorm4_from_json(json[i])); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"vector3m", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(vectorm3_from_json(json[i])); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"movie-pos", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(movie_pos_from_json(json[i])); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"vector-vol", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(vector_vol_from_json(json[i])); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"float", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(json[i].get()); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"meters", + [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(json[i].get() * METER_LENGTH); + } + return std::make_unique(name, data, -1000000000.0000); + }}, + {"degrees", [](const std::string& name, + const nlohmann::json& json, + decompiler::DecompilerTypeSystem& dts) { + (void)dts; + std::vector data; + for (size_t i = 1; i < json.size(); i++) { + data.push_back(json[i].get() * DEGREES_LENGTH); + } + return std::make_unique(name, data, -1000000000.0000); + }}}; + std::unique_ptr res_from_json_array(const std::string& name, - const nlohmann::json& json_array) { - ASSERT(json_array.size() > 0); + const nlohmann::json& json_array, + decompiler::DecompilerTypeSystem& dts) { + ASSERT(!json_array.empty()); std::string array_type = json_array[0].get(); - if (array_type == "int32") { - std::vector data; - for (size_t i = 1; i < json_array.size(); i++) { - data.push_back(json_array[i].get()); - } - return std::make_unique(name, data, -1000000000.0000); - } else if (array_type == "uint32") { - std::vector data; - for (size_t i = 1; i < json_array.size(); i++) { - data.push_back(json_array[i].get()); - } - return std::make_unique(name, data, -1000000000.0000); - } else if (array_type == "vector") { - std::vector data; - for (size_t i = 1; i < json_array.size(); i++) { - data.push_back(vector_from_json(json_array[i])); - } - return std::make_unique(name, data, -1000000000.0000); - } else if (array_type == "vector4m") { - std::vector data; - for (size_t i = 1; i < json_array.size(); i++) { - data.push_back(vectorm4_from_json(json_array[i])); - } - return std::make_unique(name, data, -1000000000.0000); - } else if (array_type == "movie-pos") { - std::vector data; - for (size_t i = 1; i < json_array.size(); i++) { - data.push_back(movie_pos_from_json(json_array[i])); - } - return std::make_unique(name, data, -1000000000.0000); - } else if (array_type == "float") { - std::vector data; - for (size_t i = 1; i < json_array.size(); i++) { - data.push_back(json_array[i].get()); - } - return std::make_unique(name, data, -1000000000.0000); - } else if (array_type == "meters") { - std::vector data; - for (size_t i = 1; i < json_array.size(); i++) { - data.push_back(json_array[i].get() * METER_LENGTH); - } - return std::make_unique(name, data, -1000000000.0000); - } else if (array_type == "degrees") { - std::vector data; - for (size_t i = 1; i < json_array.size(); i++) { - data.push_back(json_array[i].get() * DEGREES_LENGTH); - } - return std::make_unique(name, data, -1000000000.0000); + if (lump_map.find(array_type) != lump_map.end()) { + return lump_map[array_type](name, json_array, dts); } else { ASSERT_MSG(false, fmt::format("unsupported array type: {}\n", array_type)); } diff --git a/goalc/build_level/common/Entity.h b/goalc/build_level/common/Entity.h index 3b22503375..f97335747d 100644 --- a/goalc/build_level/common/Entity.h +++ b/goalc/build_level/common/Entity.h @@ -1,8 +1,11 @@ #pragma once #include "common/goal_constants.h" +#include "common/goos/ParseHelpers.h" +#include "common/goos/Printer.h" #include "common/util/Assert.h" +#include "decompiler/util/DecompilerTypeSystem.h" #include "goalc/build_level/common/ResLump.h" #include "goalc/data_compiler/DataObjectGenerator.h" @@ -11,4 +14,7 @@ math::Vector4f vectorm3_from_json(const nlohmann::json& json); math::Vector4f vectorm4_from_json(const nlohmann::json& json); math::Vector4f vector_from_json(const nlohmann::json& json); -std::unique_ptr res_from_json_array(const std::string& name, const nlohmann::json& json_array); \ No newline at end of file +u64 get_enum_val(const std::string& val, decompiler::DecompilerTypeSystem& dts); +std::unique_ptr res_from_json_array(const std::string& name, + const nlohmann::json& json_array, + decompiler::DecompilerTypeSystem& dts); \ No newline at end of file diff --git a/goalc/build_level/jak1/Entity.cpp b/goalc/build_level/jak1/Entity.cpp index 857ae9c4f3..0998154349 100644 --- a/goalc/build_level/jak1/Entity.cpp +++ b/goalc/build_level/jak1/Entity.cpp @@ -69,13 +69,18 @@ size_t generate_inline_array_actors(DataObjectGenerator& gen, void add_actors_from_json(const nlohmann::json& json, std::vector& actor_list, - u32 base_aid) { + u32 base_aid, + decompiler::DecompilerTypeSystem& dts) { for (const auto& actor_json : json) { auto& actor = actor_list.emplace_back(); actor.aid = actor_json.value("aid", base_aid + actor_list.size()); actor.trans = vectorm3_from_json(actor_json.at("trans")); actor.etype = actor_json.at("etype").get(); - actor.game_task = actor_json.value("game_task", 0); + if (actor_json.contains("game_task") && actor_json.at("game_task").is_string()) { + actor.game_task = get_enum_val(actor_json.at("game_task").get(), dts); + } else { + actor.game_task = actor_json.value("game_task", 0); + } actor.vis_id = actor_json.value("vis_id", 0); actor.quat = math::Vector4f(0, 0, 0, 1); if (actor_json.find("quat") != actor_json.end()) { @@ -98,7 +103,7 @@ void add_actors_from_json(const nlohmann::json& json, } if (value.is_array()) { - actor.res_lump.add_res(res_from_json_array(key, value)); + actor.res_lump.add_res(res_from_json_array(key, value, dts)); } } } @@ -159,7 +164,8 @@ size_t generate_inline_array_ambients(DataObjectGenerator& gen, void add_ambients_from_json(const nlohmann::json& json, std::vector& ambient_list, - u32 base_aid) { + u32 base_aid, + decompiler::DecompilerTypeSystem& dts) { for (const auto& ambient_json : json) { auto& ambient = ambient_list.emplace_back(); ambient.aid = ambient_json.value("aid", base_aid + ambient_list.size()); @@ -180,7 +186,7 @@ void add_ambients_from_json(const nlohmann::json& json, continue; } if (value.is_array()) { - ambient.res_lump.add_res(res_from_json_array(key, value)); + ambient.res_lump.add_res(res_from_json_array(key, value, dts)); } } } diff --git a/goalc/build_level/jak1/Entity.h b/goalc/build_level/jak1/Entity.h index 1cb2aafd6f..d7b3f5c734 100644 --- a/goalc/build_level/jak1/Entity.h +++ b/goalc/build_level/jak1/Entity.h @@ -32,7 +32,8 @@ size_t generate_inline_array_actors(DataObjectGenerator& gen, void add_actors_from_json(const nlohmann::json& json, std::vector& actor_list, - u32 base_aid); + u32 base_aid, + decompiler::DecompilerTypeSystem& dts); struct EntityAmbient { ResLump res_lump; @@ -47,5 +48,6 @@ size_t generate_inline_array_ambients(DataObjectGenerator& gen, const std::vector& ambients); void add_ambients_from_json(const nlohmann::json& json, std::vector& ambient_list, - u32 base_aid); + u32 base_aid, + decompiler::DecompilerTypeSystem& dts); } // namespace jak1 \ No newline at end of file diff --git a/goalc/build_level/jak1/build_level.cpp b/goalc/build_level/jak1/build_level.cpp index 70683b4df5..1c79972879 100644 --- a/goalc/build_level/jak1/build_level.cpp +++ b/goalc/build_level/jak1/build_level.cpp @@ -45,12 +45,14 @@ bool run_build_level(const std::string& input_file, // vis infos // actors std::vector actors; - add_actors_from_json(level_json.at("actors"), actors, level_json.value("base_id", 1234)); + auto dts = decompiler::DecompilerTypeSystem(GameVersion::Jak1); + dts.parse_enum_defs({"decompiler", "config", "jak1", "all-types.gc"}); + add_actors_from_json(level_json.at("actors"), actors, level_json.value("base_id", 1234), dts); file.actors = std::move(actors); // ambients std::vector ambients; jak1::add_ambients_from_json(level_json.at("ambients"), ambients, - level_json.value("base_id", 12345)); + level_json.value("base_id", 12345), dts); file.ambients = std::move(ambients); auto& ambient_drawable_tree = file.drawable_trees.ambients.emplace_back(); (void)ambient_drawable_tree; diff --git a/goalc/build_level/jak2/Entity.cpp b/goalc/build_level/jak2/Entity.cpp index c8ab118ba3..3eb1739002 100644 --- a/goalc/build_level/jak2/Entity.cpp +++ b/goalc/build_level/jak2/Entity.cpp @@ -69,14 +69,23 @@ size_t generate_inline_array_actors(DataObjectGenerator& gen, void add_actors_from_json(const nlohmann::json& json, std::vector& actor_list, - u32 base_aid) { + u32 base_aid, + decompiler::DecompilerTypeSystem& dts) { for (const auto& actor_json : json) { auto& actor = actor_list.emplace_back(); actor.aid = actor_json.value("aid", base_aid + actor_list.size()); actor.trans = vectorm3_from_json(actor_json.at("trans")); actor.etype = actor_json.at("etype").get(); - actor.kill_mask = actor_json.value("kill_mask", 0); - actor.game_task = actor_json.value("game_task", 0); + if (actor_json.contains("kill_mask") && actor_json.at("kill_mask").is_string()) { + actor.kill_mask = get_enum_val(actor_json.at("kill_mask").get(), dts); + } else { + actor.kill_mask = actor_json.value("kill_mask", 0); + } + if (actor_json.contains("game_task") && actor_json.at("game_task").is_string()) { + actor.game_task = get_enum_val(actor_json.at("game_task").get(), dts); + } else { + actor.game_task = actor_json.value("game_task", 0); + } actor.vis_id = actor_json.value("vis_id", 0); actor.quat = math::Vector4f(0, 0, 0, 1); if (actor_json.find("quat") != actor_json.end()) { @@ -99,7 +108,7 @@ void add_actors_from_json(const nlohmann::json& json, } if (value.is_array()) { - actor.res_lump.add_res(res_from_json_array(key, value)); + actor.res_lump.add_res(res_from_json_array(key, value, dts)); } } } diff --git a/goalc/build_level/jak2/Entity.h b/goalc/build_level/jak2/Entity.h index 72e181d454..d26678c143 100644 --- a/goalc/build_level/jak2/Entity.h +++ b/goalc/build_level/jak2/Entity.h @@ -32,7 +32,6 @@ size_t generate_inline_array_actors(DataObjectGenerator& gen, void add_actors_from_json(const nlohmann::json& json, std::vector& actor_list, - u32 base_aid); - -struct Region {}; + u32 base_aid, + decompiler::DecompilerTypeSystem& dts); } // namespace jak2 \ No newline at end of file diff --git a/goalc/build_level/jak2/build_level.cpp b/goalc/build_level/jak2/build_level.cpp index 9f6210dd96..44bb3e05d6 100644 --- a/goalc/build_level/jak2/build_level.cpp +++ b/goalc/build_level/jak2/build_level.cpp @@ -43,8 +43,10 @@ bool run_build_level(const std::string& input_file, file.nickname = level_json.at("nickname").get(); // vis infos // actors + auto dts = decompiler::DecompilerTypeSystem(GameVersion::Jak2); + dts.parse_enum_defs({"decompiler", "config", "jak2", "all-types.gc"}); std::vector actors; - add_actors_from_json(level_json.at("actors"), actors, level_json.value("base_id", 1234)); + add_actors_from_json(level_json.at("actors"), actors, level_json.value("base_id", 1234), dts); file.actors = std::move(actors); // cameras // nodes