custom levels: enum lump support (#3305)

This adds support for using enums in lumps using the new lump types
`enum-int32` and `enum-uint32`. Also adds these other new lump types:

- `water-height` (takes 3 meter floats, an enum and another optional
meter float)
- `eco-info` (takes an enum and an int)
- `vector3m` (3 meter floats + `w` set to 1.0)
This commit is contained in:
Hat Kid
2024-01-15 12:46:42 +01:00
committed by GitHub
parent 2071c98b55
commit 619f39d3b7
12 changed files with 339 additions and 87 deletions
+24 -10
View File
@@ -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": {
+22 -9
View File
@@ -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": {
+23
View File
@@ -115,6 +115,29 @@ void DecompilerTypeSystem::parse_type_defs(const std::vector<std::string>& file_
});
}
void DecompilerTypeSystem::parse_enum_defs(const std::vector<std::string>& 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);
+1
View File
@@ -56,6 +56,7 @@ class DecompilerTypeSystem {
const TypeSpec& type_spec,
const DefinitionMetadata& symbol_metadata);
void parse_type_defs(const std::vector<std::string>& file_path);
void parse_enum_defs(const std::vector<std::string>& 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);
+225 -50
View File
@@ -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<float>();
}
result[3] = json[3].get<float>() * 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 <typename T>
std::vector<T> enum_from_json(const nlohmann::json& json, decompiler::DecompilerTypeSystem& dts) {
std::vector<T> result;
for (const auto& entry : json) {
result.push_back(static_cast<T>(get_enum_val(entry.get<std::string>(), dts)));
}
return result;
}
static std::unordered_map<std::string,
std::function<std::unique_ptr<Res>(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<s32> data;
for (size_t i = 1; i < json.size(); i++) {
data.push_back(json[i].get<int>());
}
return std::make_unique<ResInt32>(name, data, -1000000000.0000);
}},
{"uint32",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
(void)dts;
std::vector<u32> data;
for (size_t i = 1; i < json.size(); i++) {
data.push_back(json[i].get<u32>());
}
return std::make_unique<ResUint32>(name, data, -1000000000.0000);
}},
{"enum-int32",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
std::vector<s32> data;
for (size_t i = 1; i < json.size(); i++) {
data = enum_from_json<s32>(json[i], dts);
}
return std::make_unique<ResInt32>(name, data, -1000000000.0000);
}},
{"enum-uint32",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
std::vector<u32> data;
for (size_t i = 1; i < json.size(); i++) {
data = enum_from_json<u32>(json[i], dts);
}
return std::make_unique<ResUint32>(name, data, -1000000000.0000);
}},
{"eco-info",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
std::vector<s32> data;
// pickup-type
data.push_back(static_cast<s32>(get_enum_val(json[1].get<std::string>(), dts)));
// amount
data.push_back(json[2].get<int>());
return std::make_unique<ResInt32>(name, data, -1000000000.0000);
}},
{"water-height",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
std::vector<float> data;
// water-height
data.push_back(json[1].get<float>() * METER_LENGTH);
// wade-height
data.push_back(json[2].get<float>() * METER_LENGTH);
// swim-height
data.push_back(json[3].get<float>() * METER_LENGTH);
// water-flags
data.push_back(static_cast<float>(get_enum_val(json[4].get<std::string>(), dts)));
// bottom-height
if (json.size() >= 6) {
data.push_back(json[5].get<float>() * METER_LENGTH);
}
return std::make_unique<ResFloat>(name, data, -1000000000.0000);
}},
{"vector",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
(void)dts;
std::vector<math::Vector4f> data;
for (size_t i = 1; i < json.size(); i++) {
data.push_back(vector_from_json(json[i]));
}
return std::make_unique<ResVector>(name, data, -1000000000.0000);
}},
{"vector4m",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
(void)dts;
std::vector<math::Vector4f> data;
for (size_t i = 1; i < json.size(); i++) {
data.push_back(vectorm4_from_json(json[i]));
}
return std::make_unique<ResVector>(name, data, -1000000000.0000);
}},
{"vector3m",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
(void)dts;
std::vector<math::Vector4f> data;
for (size_t i = 1; i < json.size(); i++) {
data.push_back(vectorm3_from_json(json[i]));
}
return std::make_unique<ResVector>(name, data, -1000000000.0000);
}},
{"movie-pos",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
(void)dts;
std::vector<math::Vector4f> data;
for (size_t i = 1; i < json.size(); i++) {
data.push_back(movie_pos_from_json(json[i]));
}
return std::make_unique<ResVector>(name, data, -1000000000.0000);
}},
{"vector-vol",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
(void)dts;
std::vector<math::Vector4f> data;
for (size_t i = 1; i < json.size(); i++) {
data.push_back(vector_vol_from_json(json[i]));
}
return std::make_unique<ResVector>(name, data, -1000000000.0000);
}},
{"float",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
(void)dts;
std::vector<float> data;
for (size_t i = 1; i < json.size(); i++) {
data.push_back(json[i].get<float>());
}
return std::make_unique<ResFloat>(name, data, -1000000000.0000);
}},
{"meters",
[](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
(void)dts;
std::vector<float> data;
for (size_t i = 1; i < json.size(); i++) {
data.push_back(json[i].get<float>() * METER_LENGTH);
}
return std::make_unique<ResFloat>(name, data, -1000000000.0000);
}},
{"degrees", [](const std::string& name,
const nlohmann::json& json,
decompiler::DecompilerTypeSystem& dts) {
(void)dts;
std::vector<float> data;
for (size_t i = 1; i < json.size(); i++) {
data.push_back(json[i].get<float>() * DEGREES_LENGTH);
}
return std::make_unique<ResFloat>(name, data, -1000000000.0000);
}}};
std::unique_ptr<Res> 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<std::string>();
if (array_type == "int32") {
std::vector<s32> data;
for (size_t i = 1; i < json_array.size(); i++) {
data.push_back(json_array[i].get<int>());
}
return std::make_unique<ResInt32>(name, data, -1000000000.0000);
} else if (array_type == "uint32") {
std::vector<u32> data;
for (size_t i = 1; i < json_array.size(); i++) {
data.push_back(json_array[i].get<u32>());
}
return std::make_unique<ResUint32>(name, data, -1000000000.0000);
} else if (array_type == "vector") {
std::vector<math::Vector4f> data;
for (size_t i = 1; i < json_array.size(); i++) {
data.push_back(vector_from_json(json_array[i]));
}
return std::make_unique<ResVector>(name, data, -1000000000.0000);
} else if (array_type == "vector4m") {
std::vector<math::Vector4f> data;
for (size_t i = 1; i < json_array.size(); i++) {
data.push_back(vectorm4_from_json(json_array[i]));
}
return std::make_unique<ResVector>(name, data, -1000000000.0000);
} else if (array_type == "movie-pos") {
std::vector<math::Vector4f> 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<ResVector>(name, data, -1000000000.0000);
} else if (array_type == "float") {
std::vector<float> data;
for (size_t i = 1; i < json_array.size(); i++) {
data.push_back(json_array[i].get<float>());
}
return std::make_unique<ResFloat>(name, data, -1000000000.0000);
} else if (array_type == "meters") {
std::vector<float> data;
for (size_t i = 1; i < json_array.size(); i++) {
data.push_back(json_array[i].get<float>() * METER_LENGTH);
}
return std::make_unique<ResFloat>(name, data, -1000000000.0000);
} else if (array_type == "degrees") {
std::vector<float> data;
for (size_t i = 1; i < json_array.size(); i++) {
data.push_back(json_array[i].get<float>() * DEGREES_LENGTH);
}
return std::make_unique<ResFloat>(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));
}
+7 -1
View File
@@ -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> res_from_json_array(const std::string& name, const nlohmann::json& json_array);
u64 get_enum_val(const std::string& val, decompiler::DecompilerTypeSystem& dts);
std::unique_ptr<Res> res_from_json_array(const std::string& name,
const nlohmann::json& json_array,
decompiler::DecompilerTypeSystem& dts);
+11 -5
View File
@@ -69,13 +69,18 @@ size_t generate_inline_array_actors(DataObjectGenerator& gen,
void add_actors_from_json(const nlohmann::json& json,
std::vector<EntityActor>& 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<std::string>();
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<std::string>(), 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<EntityAmbient>& 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));
}
}
}
+4 -2
View File
@@ -32,7 +32,8 @@ size_t generate_inline_array_actors(DataObjectGenerator& gen,
void add_actors_from_json(const nlohmann::json& json,
std::vector<EntityActor>& 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<EntityAmbient>& ambients);
void add_ambients_from_json(const nlohmann::json& json,
std::vector<EntityAmbient>& ambient_list,
u32 base_aid);
u32 base_aid,
decompiler::DecompilerTypeSystem& dts);
} // namespace jak1
+4 -2
View File
@@ -45,12 +45,14 @@ bool run_build_level(const std::string& input_file,
// vis infos
// actors
std::vector<EntityActor> 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<EntityAmbient> 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;
+13 -4
View File
@@ -69,14 +69,23 @@ size_t generate_inline_array_actors(DataObjectGenerator& gen,
void add_actors_from_json(const nlohmann::json& json,
std::vector<EntityActor>& 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<std::string>();
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<std::string>(), 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<std::string>(), 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));
}
}
}
+2 -3
View File
@@ -32,7 +32,6 @@ size_t generate_inline_array_actors(DataObjectGenerator& gen,
void add_actors_from_json(const nlohmann::json& json,
std::vector<EntityActor>& actor_list,
u32 base_aid);
struct Region {};
u32 base_aid,
decompiler::DecompilerTypeSystem& dts);
} // namespace jak2
+3 -1
View File
@@ -43,8 +43,10 @@ bool run_build_level(const std::string& input_file,
file.nickname = level_json.at("nickname").get<std::string>();
// vis infos
// actors
auto dts = decompiler::DecompilerTypeSystem(GameVersion::Jak2);
dts.parse_enum_defs({"decompiler", "config", "jak2", "all-types.gc"});
std::vector<EntityActor> 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