remove invisible wall blocking north palace

This commit is contained in:
gymnast86
2026-05-09 01:52:27 -07:00
parent bfb715e11a
commit ced018794f
4 changed files with 127 additions and 8 deletions
+15 -2
View File
@@ -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<u8*>(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<u8*>(&tgscData), RandomizerContext::TGSC_CRC_SIZE);
if (deletions.contains(actorKey)) {
return;
}
}
}
#endif
@@ -92,6 +92,12 @@ std::optional<std::string> 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<std::string> RandomizerContext::LoadFromHash(const std::string& ha
}
}
// Actor Deletions
for (const auto& stageRoomLayerNode: in["mTgscDeletions"]) {
u32 stageRoomLayer = stageRoomLayerNode.first.as<u32>();
for (const auto& actorPatchNode : stageRoomLayerNode.second) {
u32 actorCRC = actorPatchNode.as<u32>();
this->mTgscDeletions[stageRoomLayer].insert(actorCRC);
}
}
// Flow Patches
for (const auto& flowNode: in["mFlowPatches"]) {
auto key = flowNode.first.as<u32>();
@@ -726,8 +741,8 @@ u32 getActorPatchesCurrentStageKey(u8 roomNo) {
return actorPatchesStageKey;
}
u32 getActorCRC32(stage_actor_data_class* actor) {
return zng_crc32(0, reinterpret_cast<u8*>(actor), RandomizerContext::ACTOR_CRC_SIZE);
u32 getStageObjCRC32(u8* data, size_t size) {
return zng_crc32(0, (data), size);
}
RandomizerContext WriteSeedData(const std::unique_ptr<randomizer::logic::world::World>& world) {
@@ -950,7 +965,7 @@ RandomizerContext WriteSeedData(const std::unique_ptr<randomizer::logic::world::
actor.base.angle.z = toPlatform(target, static_cast<s16>(actorNode["angle"]["z"].as<u16>()));
// Create unique hash based off of actor data
u32 actorCRC32 = getActorCRC32(&actor);
u32 actorCRC32 = getStageObjCRC32(reinterpret_cast<u8*>(&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<randomizer::logic::world::
}
}
// Actor Deletions
auto actorDeletions = LoadYAML(RANDO_DATA_PATH "actor_deletions.yaml");
for (const auto& typeNode : actorDeletions) {
const auto& actorTypeStr = typeNode.first.as<std::string>();
// Get the integer interpretation of the multi-char type literal
u32 actorType = *(reinterpret_cast<const u32*>(actorTypeStr.c_str()));
// For each stage
for (const auto& stageNode : typeNode.second) {
const auto& stageName = stageNode.first.as<std::string>();
// For each room
for (const auto& roomNode : stageNode.second) {
u8 roomNo = roomNode.first.as<u8>();
// 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<std::string>();
auto parameters = toPlatform(target, actorNode["parameters"].as<u32>());
auto posX = toPlatform(target, actorNode["position"]["x"].as<f32>());
auto posY = toPlatform(target, actorNode["position"]["y"].as<f32>());
auto posZ = toPlatform(target, actorNode["position"]["z"].as<f32>());
// 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<s16>(actorNode["angle"]["x"].as<u16>()));
auto angY = toPlatform(target, static_cast<s16>(actorNode["angle"]["y"].as<u16>()));
auto angZ = toPlatform(target, static_cast<s16>(actorNode["angle"]["z"].as<u16>()));
u8 scaleX, scaleY, scaleZ;
if (actorNode["scale"]) {
scaleX = actorNode["scale"]["x"].as<u8>();
scaleY = actorNode["scale"]["y"].as<u8>();
scaleZ = actorNode["scale"]["z"].as<u8>();
}
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<u8*>(&actor), RandomizerContext::TGSC_CRC_SIZE);
// Insert the actor into the context keyed by type and the stage/layer/room combo
std::array<u8, RandomizerContext::TGSC_CRC_SIZE> actorData{};
std::memcpy(actorData.data(), &actor, RandomizerContext::TGSC_CRC_SIZE);
for (const auto& layerNode : actorNode["layers"]) {
u8 layerNo = layerNode.as<u8>();
// 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) {
@@ -10,6 +10,7 @@
#include <string>
#include <sstream>
#include <unordered_map>
#include <unordered_set>
/*
* 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<u32, std::unordered_map<u32, std::array<u8, 30>>> mActorPatches{};
std::unordered_map<u32, std::unordered_map<u32, std::list<std::array<u8, 30>>>> mActorAdditions{};
std::unordered_map<u32, std::unordered_map<u32, std::array<u8, ACTOR_CRC_SIZE>>> mActorPatches{};
std::unordered_map<u32, std::unordered_map<u32, std::list<std::array<u8, ACTOR_CRC_SIZE>>>> mActorAdditions{};
std::unordered_map<u32, std::unordered_set<u32>> mTgscDeletions{};
std::unordered_map<u32, u64> 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
@@ -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