mirror of
https://github.com/open-goal/jak-project
synced 2026-05-23 06:54:31 -04:00
[jak2/3] Support yakows in custom levels (#3951)
I discovered that `yakow`s are kinda broken if you try to use them in custom levels in jak 2/3. It's due to the missing `yakow-lod0` texture and associated fix, replacing it with `yak-medfur-end`. This solution works fine for the decompiler on vanilla levels. But for building custom levels, the requested art-groups were being handled before the textures were, and so it was impossible to have `yak-medfur-end` on hand to do the replacement. You'd hit an exception here because `idx_in_level_texture` would still be `INT32_MAX`: https://github.com/open-goal/jak-project/blob/c08118509b84feba002bd9e208f49162b4218556/decompiler/level_extractor/extract_merc.cpp#L806 My fix was just to swap the order when building custom levels, and handle the textures first. I only made the changes for jak2/3, because I see @Hat-Kid has a slightly different implementation for jak1. There's one other small change relating to the `combo_id` / `pc_combo_tex_id` short-circtuiting - I think `pc_combo_tex_id` is always 0 for vanilla textures? So initially `yakow-lod0` actually ended up matching the `combo_id` of the checkerboard texture from the test-zone GLB. I just added another sanity check here that the texture names match too. (I also added yakows in the test-zone.jsonc files 🐄)
This commit is contained in:
@@ -246,6 +246,17 @@
|
||||
"jak2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "default",
|
||||
"project": "CMakeLists.txt",
|
||||
"projectTarget": "goalc.exe (bin\\goalc.exe)",
|
||||
"name": "REPL - Jak 3",
|
||||
"args": [
|
||||
"--user-auto",
|
||||
"--game",
|
||||
"jak3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "default",
|
||||
"project": "CMakeLists.txt",
|
||||
|
||||
@@ -53,8 +53,8 @@
|
||||
"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"],
|
||||
// Commented out so that the release builds don't have to double-decompile the game
|
||||
// "art_groups": ["yakow-ag"],
|
||||
|
||||
// If you have any custom models in the "custom_assets/jak2/models/custom_levels" folder that you want to use in your level, add them to this list.
|
||||
// Note: Like with art groups, these should also be added to your level's .gd file.
|
||||
@@ -66,7 +66,7 @@
|
||||
// by setting "save_texture_pngs" to true in the decompiler config.
|
||||
// The format is ["tpage-name", "texture-name1", "texture-name2", ...].
|
||||
// If you want all textures from a tpage, you can just do ["tpage-name"].
|
||||
"textures": [],
|
||||
"textures": ["yak-medfur-end"], // for yakow texture fix
|
||||
|
||||
"actors": [
|
||||
{
|
||||
@@ -95,13 +95,13 @@
|
||||
},
|
||||
|
||||
{
|
||||
"trans": [-7.41, 13.5, 28.42], // translation
|
||||
"etype": "prsn-torture", // actor type
|
||||
"trans": [-7.41, 1.04, 28.42], // translation
|
||||
"etype": "yakow", // actor type
|
||||
"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
|
||||
"bsphere": [-7.41, 1.04, 28.42, 10], // bounding sphere
|
||||
"lump": {
|
||||
"name": "test-torture"
|
||||
"name": "test-yakow"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
;; the actual file name still needs to be 8.3
|
||||
("TSZ.DGO"
|
||||
(
|
||||
"prison-obs.o"
|
||||
;; "yakow.o" ;; leave this out, so it will spawn dummy viewer process (otherwise yakow needs navmesh)
|
||||
"yakow-ag.go"
|
||||
"test-zone-obs.o"
|
||||
"test-actor-ag.go"
|
||||
"test-zone.go"
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
"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.
|
||||
// "art_groups": [],
|
||||
// Commented out so that the release builds don't have to double-decompile the game
|
||||
// "art_groups": ["yakow-ag"],
|
||||
|
||||
// If you have any custom models in the "custom_assets/jak3/models/custom_levels" folder that you want to use in your level, add them to this list.
|
||||
// Note: Like with art groups, these should also be added to your level's .gd file.
|
||||
@@ -65,7 +66,7 @@
|
||||
// by setting "save_texture_pngs" to true in the decompiler config.
|
||||
// The format is ["tpage-name", "texture-name1", "texture-name2", ...].
|
||||
// If you want all textures from a tpage, you can just do ["tpage-name"].
|
||||
"textures": [],
|
||||
"textures": ["yak-medfur-end"], // for yakow texture fix
|
||||
|
||||
"actors": [
|
||||
{
|
||||
@@ -93,6 +94,18 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"trans": [-7.75, 1.04, 27.136], // translation
|
||||
"etype": "yakow", // actor type
|
||||
"game_task": "(game-task none)", // associated game task (for powercells, etc)
|
||||
"kill_mask": 0,
|
||||
"quat": [0, 0, 0, 1], // quaternion
|
||||
"bsphere": [-7.75, 1.04, 27.136, 10], // bounding sphere
|
||||
"lump": {
|
||||
"name": "test-yakow"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"trans": [5.41, 3.5, 28.42], // translation
|
||||
"etype": "test-actor", // actor type
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
;; the actual file name still needs to be 8.3
|
||||
("TSZ.DGO"
|
||||
(
|
||||
"yakow-ag.go" ;; no code page for this in jak3, so it will spawn dummy viewer process
|
||||
"test-zone-obs.o"
|
||||
"test-actor-ag.go"
|
||||
"test-zone.go"
|
||||
|
||||
@@ -729,7 +729,7 @@ s32 find_or_add_texture_to_level(tfrag3::Level& out,
|
||||
GameVersion version) {
|
||||
s32 idx_in_level_texture = INT32_MAX;
|
||||
for (s32 i = 0; i < (int)out.textures.size(); i++) {
|
||||
if (out.textures[i].combo_id == pc_combo_tex_id) {
|
||||
if (out.textures[i].combo_id == pc_combo_tex_id && out.textures[i].debug_name == debug_name) {
|
||||
idx_in_level_texture = i;
|
||||
break;
|
||||
}
|
||||
@@ -746,6 +746,7 @@ s32 find_or_add_texture_to_level(tfrag3::Level& out,
|
||||
for (size_t i = 0; i < out.textures.size(); i++) {
|
||||
auto& existing = out.textures[i];
|
||||
if (existing.debug_name == "yak-medfur-end") {
|
||||
lg::info("found yak-medfur-end to replace missing yakow-lod0");
|
||||
idx_in_level_texture = i;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -148,29 +148,6 @@ bool run_build_level(const std::string& input_file,
|
||||
tex_db.replace_textures(replacements_path);
|
||||
}
|
||||
|
||||
// find all art groups used by the custom level in other dgos
|
||||
if (gen_fr3 && level_json.contains("art_groups") && !level_json.at("art_groups").empty()) {
|
||||
for (auto& dgo : config.dgo_names) {
|
||||
std::vector<std::string> processed_art_groups;
|
||||
// remove "DGO/" prefix
|
||||
const auto& dgo_name = dgo.substr(4);
|
||||
const auto& files = db.obj_files_by_dgo.at(dgo_name);
|
||||
auto art_groups =
|
||||
find_art_groups(processed_art_groups,
|
||||
level_json.at("art_groups").get<std::vector<std::string>>(), files);
|
||||
auto tex_remap = decompiler::extract_tex_remap(db, dgo_name);
|
||||
for (const auto& ag : art_groups) {
|
||||
if (ag.name.length() > 3 && !ag.name.compare(ag.name.length() - 3, 3, "-ag")) {
|
||||
const auto& ag_file = db.lookup_record(ag);
|
||||
lg::print("custom level: extracting art group {}\n", ag_file.name_in_dgo);
|
||||
decompiler::MercSwapInfo info;
|
||||
decompiler::extract_merc(ag_file, tex_db, db.dts, tex_remap, pc_level, false,
|
||||
db.version(), info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add textures
|
||||
if (level_json.contains("textures") && !level_json.at("textures").empty()) {
|
||||
std::vector<std::string> processed_textures;
|
||||
@@ -201,6 +178,29 @@ bool run_build_level(const std::string& input_file,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find all art groups used by the custom level in other dgos
|
||||
if (gen_fr3 && level_json.contains("art_groups") && !level_json.at("art_groups").empty()) {
|
||||
for (auto& dgo : config.dgo_names) {
|
||||
std::vector<std::string> processed_art_groups;
|
||||
// remove "DGO/" prefix
|
||||
const auto& dgo_name = dgo.substr(4);
|
||||
const auto& files = db.obj_files_by_dgo.at(dgo_name);
|
||||
auto art_groups =
|
||||
find_art_groups(processed_art_groups,
|
||||
level_json.at("art_groups").get<std::vector<std::string>>(), files);
|
||||
auto tex_remap = decompiler::extract_tex_remap(db, dgo_name);
|
||||
for (const auto& ag : art_groups) {
|
||||
if (ag.name.length() > 3 && !ag.name.compare(ag.name.length() - 3, 3, "-ag")) {
|
||||
const auto& ag_file = db.lookup_record(ag);
|
||||
lg::print("custom level: extracting art group {}\n", ag_file.name_in_dgo);
|
||||
decompiler::MercSwapInfo info;
|
||||
decompiler::extract_merc(ag_file, tex_db, db.dts, tex_remap, pc_level, false,
|
||||
db.version(), info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add custom models to fr3
|
||||
|
||||
@@ -146,29 +146,6 @@ bool run_build_level(const std::string& input_file,
|
||||
tex_db.replace_textures(replacements_path);
|
||||
}
|
||||
|
||||
// find all art groups used by the custom level in other dgos
|
||||
if (gen_fr3 && level_json.contains("art_groups") && !level_json.at("art_groups").empty()) {
|
||||
for (auto& dgo : config.dgo_names) {
|
||||
std::vector<std::string> processed_art_groups;
|
||||
// remove "DGO/" prefix
|
||||
const auto& dgo_name = dgo.substr(4);
|
||||
const auto& files = db.obj_files_by_dgo.at(dgo_name);
|
||||
auto art_groups =
|
||||
find_art_groups(processed_art_groups,
|
||||
level_json.at("art_groups").get<std::vector<std::string>>(), files);
|
||||
auto tex_remap = decompiler::extract_tex_remap(db, dgo_name);
|
||||
for (const auto& ag : art_groups) {
|
||||
if (ag.name.length() > 3 && !ag.name.compare(ag.name.length() - 3, 3, "-ag")) {
|
||||
const auto& ag_file = db.lookup_record(ag);
|
||||
lg::print("custom level: extracting art group {}\n", ag_file.name_in_dgo);
|
||||
decompiler::MercSwapInfo info;
|
||||
decompiler::extract_merc(ag_file, tex_db, db.dts, tex_remap, pc_level, false,
|
||||
db.version(), info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add textures
|
||||
if (level_json.contains("textures") && !level_json.at("textures").empty()) {
|
||||
std::vector<std::string> processed_textures;
|
||||
@@ -199,6 +176,29 @@ bool run_build_level(const std::string& input_file,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find all art groups used by the custom level in other dgos
|
||||
if (gen_fr3 && level_json.contains("art_groups") && !level_json.at("art_groups").empty()) {
|
||||
for (auto& dgo : config.dgo_names) {
|
||||
std::vector<std::string> processed_art_groups;
|
||||
// remove "DGO/" prefix
|
||||
const auto& dgo_name = dgo.substr(4);
|
||||
const auto& files = db.obj_files_by_dgo.at(dgo_name);
|
||||
auto art_groups =
|
||||
find_art_groups(processed_art_groups,
|
||||
level_json.at("art_groups").get<std::vector<std::string>>(), files);
|
||||
auto tex_remap = decompiler::extract_tex_remap(db, dgo_name);
|
||||
for (const auto& ag : art_groups) {
|
||||
if (ag.name.length() > 3 && !ag.name.compare(ag.name.length() - 3, 3, "-ag")) {
|
||||
const auto& ag_file = db.lookup_record(ag);
|
||||
lg::print("custom level: extracting art group {}\n", ag_file.name_in_dgo);
|
||||
decompiler::MercSwapInfo info;
|
||||
decompiler::extract_merc(ag_file, tex_db, db.dts, tex_remap, pc_level, false,
|
||||
db.version(), info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add custom models to fr3
|
||||
|
||||
Reference in New Issue
Block a user