add master sword actor to grove layer 2

This commit is contained in:
gymnast86
2026-04-25 21:43:32 -07:00
parent 8ea4b7747d
commit 8e3306f87f
5 changed files with 118 additions and 1 deletions
+25
View File
@@ -1991,6 +1991,31 @@ static int dStage_actorCommonLayerInit(dStage_dt_c* i_stage, void* i_data, int e
actor_data++;
}
#if TARGET_PC
// For randomizer, add in our custom actors
if (randomizer_IsActive()) {
u32 type = static_cast<dStage_nodeHeader*>(i_data)->m_tag;
u32 stageRoomLayer = getActorPatchesCurrentStageKey(i_stage->getRoomNo());
const auto& actorAdditions = randomizer_GetContext().mActorAdditions;
if (actorAdditions.contains(type) && actorAdditions.at(type).contains(stageRoomLayer)) {
auto& newActors = actorAdditions.at(type).at(stageRoomLayer);
for (const auto& actorData : newActors) {
stage_actor_data_class actor{};
std::memcpy(&actor, actorData.data(), actorData.size());
actor.base.setID = 0xFFFF;
// Code copied from base game for loop above
fopAcM_prm_class* appen = fopAcM_CreateAppend();
if (appen != NULL) {
appen->base = actor.base;
appen->room_no = (int)i_stage->getRoomNo();
dStage_actorCreate(&actor, appen);
}
}
}
}
#endif
return 1;
}
@@ -78,6 +78,14 @@ std::optional<std::string> RandomizerContext::WriteToFile() {
}
}
for (const auto& [actorType, stages] : this->mActorAdditions) {
for (const auto& [stageRoomLayer, newActors] : stages) {
for (const auto& actor : newActors) {
out["mActorAdditions"][actorType][stageRoomLayer].push_back(ContainerToHexString(actor));
}
}
}
seedData << YAML::Dump(out);
seedData.close();
@@ -187,6 +195,19 @@ std::optional<std::string> RandomizerContext::LoadFromHash(const std::string& ha
}
}
// Actor Additions
for (const auto& typeNode: in["mActorAdditions"]) {
u32 type = typeNode.first.as<u32>();
for (const auto& stageNode : typeNode.second) {
u32 stageRoomLayer = stageNode.first.as<u32>();
for (const auto& actorNode : stageNode.second) {
auto actorBytes = HexToBytes(actorNode.as<std::string>());
auto& patchedActor = this->mActorAdditions[type][stageRoomLayer].emplace_back();
std::copy_n(actorBytes.begin(), actorBytes.size(), patchedActor.begin());
}
}
}
DuskLog.debug("Loaded Randomizer Seed {}", this->mHash);
return std::nullopt;
@@ -753,6 +774,53 @@ void GenerateAndWriteSeed(std::string& generationStatusMsg) {
}
}
// Actor Additions
auto actorAdditions = LoadYAML(RANDO_DATA_PATH "actor_additions.yaml");
for (const auto& typeNode : actorAdditions) {
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 new actors
for (const auto& actorNode : roomNode.second) {
using namespace Utility::Endian;
// Get all the data for the actor (with endian shenanigans)
stage_actor_data_class actor{};
const auto& actorName = actorNode["name"].as<std::string>();
strncpy(actor.name, actorName.c_str(), 8);
actor.base.parameters = toPlatform(target, actorNode["parameters"].as<u32>());
actor.base.position.x = toPlatform(target, actorNode["position"]["x"].as<f32>());
actor.base.position.y = toPlatform(target, actorNode["position"]["y"].as<f32>());
actor.base.position.z = 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
actor.base.angle.x = toPlatform(target, static_cast<s16>(actorNode["angle"]["x"].as<u16>()));
actor.base.angle.y = toPlatform(target, static_cast<s16>(actorNode["angle"]["y"].as<u16>()));
actor.base.angle.z = toPlatform(target, static_cast<s16>(actorNode["angle"]["z"].as<u16>()));
// Insert the actor into the context keyed by type and the stage/layer/room combo
std::array<u8, RandomizerContext::ACTOR_CRC_SIZE> newActorData{};
std::memcpy(newActorData.data(), &actor, RandomizerContext::ACTOR_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.mActorAdditions[actorType][stageRoomLayerKey].push_back(newActorData);
}
}
}
}
}
randoData.mHash = r.GetConfig().GetHash();
auto writeToFileResult = randoData.WriteToFile();
if (writeToFileResult.has_value()) {
@@ -38,6 +38,7 @@ public:
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::optional<std::string> WriteToFile();
std::optional<std::string> LoadFromHash(const std::string& hash);
@@ -0,0 +1,23 @@
# New actors to spawn in
# NOTE: All data is expressed in little endian format
# Objects which have the ACTR dzx type
ACTR:
# Sacred Grove
F_SP117:
# Pedestal of Time
1:
# Spawn in the Master Sword actor
- name: mstrsrd
parameters: 0x00020110
position:
x: 0.0
y: 1700.0
z: -5435.0
angle:
x: 0x0147
y: 0x0000
z: 0x0000
layers:
- 2
@@ -1,4 +1,4 @@
# Patches for actors that already exist on a given map
# Patches for actors that already exist
# NOTE: Data is expressed in little endian format