From ced018794f63f9cd832b70becd7fe53ecd1aa860 Mon Sep 17 00:00:00 2001 From: gymnast86 Date: Sat, 9 May 2026 01:52:27 -0700 Subject: [PATCH] remove invisible wall blocking north palace --- src/d/d_stage.cpp | 17 +++- .../randomizer/game/randomizer_context.cpp | 83 ++++++++++++++++++- .../randomizer/game/randomizer_context.hpp | 9 +- .../generator/data/actor_deletions.yaml | 26 ++++++ 4 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 src/dusk/randomizer/generator/data/actor_deletions.yaml diff --git a/src/d/d_stage.cpp b/src/d/d_stage.cpp index 946e0e0a5c..4574be9e86 100644 --- a/src/d/d_stage.cpp +++ b/src/d/d_stage.cpp @@ -1596,18 +1596,31 @@ u8 dStage_roomControl_c::mNoArcBank; static void dStage_actorCreate(stage_actor_data_class* i_actorData, fopAcM_prm_class* i_actorPrm) { #if TARGET_PC - // If randomizer is active, override the data for this actor if it's in the actorPatches + // If randomizer is active, if (randomizer_IsActive()) { + // override the data for this actor if it's in the actorPatches auto currentStageKey = getActorPatchesCurrentStageKey(i_actorPrm->room_no); if (randomizer_GetContext().mActorPatches.contains(currentStageKey)) { const auto& patches = randomizer_GetContext().mActorPatches.at(currentStageKey); - auto actorKey = getActorCRC32(i_actorData); + auto actorKey = getStageObjCRC32(reinterpret_cast(i_actorData), RandomizerContext::ACTOR_CRC_SIZE); if (patches.contains(actorKey)) { const auto& patchedActorData = patches.at(actorKey); std::memcpy(i_actorPrm, patchedActorData.data() + 8, RandomizerContext::ACTOR_CRC_SIZE - 8); std::memcpy(i_actorData, patchedActorData.data(), RandomizerContext::ACTOR_CRC_SIZE); } } + // Return early if this actor is in objectDeletions so it never spawns + if (randomizer_GetContext().mTgscDeletions.contains(currentStageKey)) { + const auto& deletions = randomizer_GetContext().mTgscDeletions.at(currentStageKey); + stage_tgsc_data_class tgscData{}; + strncpy(tgscData.name, i_actorData->name, 8); + tgscData.base = i_actorPrm->base; + tgscData.scale = i_actorPrm->scale; + auto actorKey = getStageObjCRC32(reinterpret_cast(&tgscData), RandomizerContext::TGSC_CRC_SIZE); + if (deletions.contains(actorKey)) { + return; + } + } } #endif diff --git a/src/dusk/randomizer/game/randomizer_context.cpp b/src/dusk/randomizer/game/randomizer_context.cpp index 43543d9846..ec33ba6a5d 100644 --- a/src/dusk/randomizer/game/randomizer_context.cpp +++ b/src/dusk/randomizer/game/randomizer_context.cpp @@ -92,6 +92,12 @@ std::optional RandomizerContext::WriteToFile() { } } + for (const auto& [stageRoomLayer, actorPatches] : this->mTgscDeletions) { + for (const auto& actorCRC : actorPatches) { + out["mTgscDeletions"][stageRoomLayer].push_back(actorCRC); + } + } + out["mFlowPatches"] = this->mFlowPatches; // Dump text overrides as binary to avoid losing intentional null characters @@ -234,6 +240,15 @@ std::optional RandomizerContext::LoadFromHash(const std::string& ha } } + // Actor Deletions + for (const auto& stageRoomLayerNode: in["mTgscDeletions"]) { + u32 stageRoomLayer = stageRoomLayerNode.first.as(); + for (const auto& actorPatchNode : stageRoomLayerNode.second) { + u32 actorCRC = actorPatchNode.as(); + this->mTgscDeletions[stageRoomLayer].insert(actorCRC); + } + } + // Flow Patches for (const auto& flowNode: in["mFlowPatches"]) { auto key = flowNode.first.as(); @@ -726,8 +741,8 @@ u32 getActorPatchesCurrentStageKey(u8 roomNo) { return actorPatchesStageKey; } -u32 getActorCRC32(stage_actor_data_class* actor) { - return zng_crc32(0, reinterpret_cast(actor), RandomizerContext::ACTOR_CRC_SIZE); +u32 getStageObjCRC32(u8* data, size_t size) { + return zng_crc32(0, (data), size); } RandomizerContext WriteSeedData(const std::unique_ptr& world) { @@ -950,7 +965,7 @@ RandomizerContext WriteSeedData(const std::unique_ptr(actorNode["angle"]["z"].as())); // Create unique hash based off of actor data - u32 actorCRC32 = getActorCRC32(&actor); + u32 actorCRC32 = getStageObjCRC32(reinterpret_cast(&actor), RandomizerContext::ACTOR_CRC_SIZE); // Then override the actor with whatever parts are being patched const auto& patchNode = actorNode["patch"]; @@ -1049,6 +1064,68 @@ RandomizerContext WriteSeedData(const std::unique_ptr(); + // Get the integer interpretation of the multi-char type literal + u32 actorType = *(reinterpret_cast(actorTypeStr.c_str())); + // For each stage + for (const auto& stageNode : typeNode.second) { + const auto& stageName = stageNode.first.as(); + // For each room + for (const auto& roomNode : stageNode.second) { + u8 roomNo = roomNode.first.as(); + // Get data on actors to delete + for (const auto& actorNode : roomNode.second) { + using namespace Utility::Endian; + // Get all the data for the actor (with endian shenanigans) + stage_tgsc_data_class actor{}; + const auto& actorName = actorNode["name"].as(); + + auto parameters = toPlatform(target, actorNode["parameters"].as()); + auto posX = toPlatform(target, actorNode["position"]["x"].as()); + auto posY = toPlatform(target, actorNode["position"]["y"].as()); + auto posZ = toPlatform(target, actorNode["position"]["z"].as()); + // Have to retrieve as u16 and then cast as s16 because otherwise yaml-cpp + // complains about values over 32767 not fitting in s16 + auto angX = toPlatform(target, static_cast(actorNode["angle"]["x"].as())); + auto angY = toPlatform(target, static_cast(actorNode["angle"]["y"].as())); + auto angZ = toPlatform(target, static_cast(actorNode["angle"]["z"].as())); + + u8 scaleX, scaleY, scaleZ; + if (actorNode["scale"]) { + scaleX = actorNode["scale"]["x"].as(); + scaleY = actorNode["scale"]["y"].as(); + scaleZ = actorNode["scale"]["z"].as(); + } + + strncpy(actor.name, actorName.c_str(), 8); + actor.base.parameters = parameters; + actor.base.position = cXyz{posX, posY, posZ}; + actor.base.angle = csXyz{angX, angY, angZ}; + actor.base.setID = 0xFFFF; // Always seems to be 0xFFFF + actor.scale = fopAcM_prmScale_class{scaleX, scaleY, scaleZ}; + + u32 objCRC32 = getStageObjCRC32(reinterpret_cast(&actor), RandomizerContext::TGSC_CRC_SIZE); + + // Insert the actor into the context keyed by type and the stage/layer/room combo + std::array actorData{}; + std::memcpy(actorData.data(), &actor, RandomizerContext::TGSC_CRC_SIZE); + for (const auto& layerNode : actorNode["layers"]) { + u8 layerNo = layerNode.as(); + // Create key based off of stage index, room, and layer + u32 stageRoomLayerKey{}; + stageRoomLayerKey |= getStageID(stageName.c_str()) << 16; + stageRoomLayerKey |= roomNo << 8; + stageRoomLayerKey |= layerNo; + randoData.mTgscDeletions[stageRoomLayerKey].insert(objCRC32); + } + } + } + } + } + // Flow Patches auto flowPatches = LoadYAML(RANDO_DATA_PATH "flow_patches.yaml"); for (const auto& groupNode : flowPatches) { diff --git a/src/dusk/randomizer/game/randomizer_context.hpp b/src/dusk/randomizer/game/randomizer_context.hpp index 526e48b63f..a9279e71ef 100644 --- a/src/dusk/randomizer/game/randomizer_context.hpp +++ b/src/dusk/randomizer/game/randomizer_context.hpp @@ -10,6 +10,7 @@ #include #include #include +#include /* * Class holding all the information necessary for playing @@ -18,6 +19,7 @@ class RandomizerContext { public: static constexpr size_t ACTOR_CRC_SIZE = 30; + static constexpr size_t TGSC_CRC_SIZE = 35; RandomizerContext() = default; @@ -43,8 +45,9 @@ public: u8 mStartHour{0}; u8 mMapBits{}; - std::unordered_map>> mActorPatches{}; - std::unordered_map>>> mActorAdditions{}; + std::unordered_map>> mActorPatches{}; + std::unordered_map>>> mActorAdditions{}; + std::unordered_map> mTgscDeletions{}; std::unordered_map mFlowPatches{}; // struct TextOverride { @@ -201,7 +204,7 @@ class stage_actor_data_class; /* * Gets the CRC32 hash of an actors name, parameters, position, and angle */ -u32 getActorCRC32(stage_actor_data_class*); +u32 getStageObjCRC32(u8* data, size_t size); void GenerateAndWriteSeed(std::string& generationStatusMsg); #endif //DUSK_RANDOMIZER_CONTEXT_HPP diff --git a/src/dusk/randomizer/generator/data/actor_deletions.yaml b/src/dusk/randomizer/generator/data/actor_deletions.yaml new file mode 100644 index 0000000000..77b155f94c --- /dev/null +++ b/src/dusk/randomizer/generator/data/actor_deletions.yaml @@ -0,0 +1,26 @@ +# Stage Objects to not spawn in + +# Actors which have the SCOB dzx type +SCOB: + # Palace of Twilight + D_MN08: + # Room 0 - Main Entrance + 0: + # Delete invisible wall that blocks north access + # in Palace of Twilight unless both Sols are placed + - name: ClearB + parameters: 0x00003F81 + position: + x: 255.0 + y: 1600.0 + z: 2560.0 + angle: + x: 0x4000 + y: 0x0000 + z: 0x0000 + scale: + x: 20 + y: 10 + z: 20 + layers: + - 14