mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-09 12:37:18 -04:00
refactor object overrides
This commit is contained in:
+41
-36
@@ -1596,30 +1596,36 @@ 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,
|
||||
// In rando, potentially override this object's data
|
||||
if (randomizer_IsActive()) {
|
||||
// override the data for this actor if it's in the actorPatches
|
||||
// Get the current stage/room/layer key
|
||||
auto currentStageKey = getActorPatchesCurrentStageKey(i_actorPrm->room_no);
|
||||
if (randomizer_GetContext().mActorPatches.contains(currentStageKey)) {
|
||||
const auto& patches = randomizer_GetContext().mActorPatches.at(currentStageKey);
|
||||
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);
|
||||
// If we have patches for this stage/room/layer
|
||||
if (randomizer_GetContext().mObjectPatches.contains(currentStageKey)) {
|
||||
auto& patches = randomizer_GetContext().mObjectPatches.at(currentStageKey);
|
||||
|
||||
auto actrKey = getStageObjCRC32(reinterpret_cast<u8*>(i_actorData), RandomizerContext::ACTR_CRC_SIZE);
|
||||
auto tgscKey = getStageObjCRC32(reinterpret_cast<u8*>(i_actorData), RandomizerContext::TGSC_CRC_SIZE);
|
||||
std::vector<u8>* bytes = NULL;
|
||||
// See if the patches contain either key and the correct size for the key
|
||||
if (patches.contains(actrKey) &&
|
||||
(patches[actrKey].size() == RandomizerContext::ACTR_CRC_SIZE || patches[actrKey].size() == RandomizerContext::OBJ_DELETE_SIZE)) {
|
||||
bytes = &patches.at(actrKey);
|
||||
} else if (patches.contains(tgscKey) &&
|
||||
(patches[tgscKey].size() == RandomizerContext::TGSC_CRC_SIZE || patches[tgscKey].size() == RandomizerContext::OBJ_DELETE_SIZE)) {
|
||||
bytes = &patches.at(tgscKey);
|
||||
}
|
||||
}
|
||||
// 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)) {
|
||||
|
||||
// If we found a match with a size of OBJ_DELETE_SIZE, this is a signal to delete the actor.
|
||||
// Return early so we just don't spawn it
|
||||
if (bytes != NULL && bytes->size() == RandomizerContext::OBJ_DELETE_SIZE) {
|
||||
return;
|
||||
}
|
||||
// If we found a match, override the actor data
|
||||
if (bytes != NULL) {
|
||||
std::memcpy(i_actorPrm, bytes->data() + 8, bytes->size() - 8);
|
||||
std::memcpy(i_actorData, bytes->data(), bytes->size());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1645,25 +1651,24 @@ static void dStage_actorCreate(stage_actor_data_class* i_actorData, fopAcM_prm_c
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
// Custom function to spawn additional actors in randomizer
|
||||
static void dStage_createActorAdditions(dStage_dt_c* i_stage) {
|
||||
// Custom function to spawn additional objects in randomizer
|
||||
static void dStage_createObjectAdditions(dStage_dt_c* i_stage) {
|
||||
if (randomizer_IsActive()) {
|
||||
u32 stageRoomLayer = getActorPatchesCurrentStageKey(i_stage->getRoomNo());
|
||||
const auto& actorAdditions = randomizer_GetContext().mActorAdditions;
|
||||
for (const auto& [type, newActors] : actorAdditions) {
|
||||
if (newActors.contains(stageRoomLayer)) {
|
||||
for (const auto& actorData : newActors.at(stageRoomLayer)) {
|
||||
stage_actor_data_class actor{};
|
||||
std::memcpy(&actor, actorData.data(), actorData.size());
|
||||
actor.base.setID = 0xFFFF;
|
||||
// Code below copied from base game
|
||||
fopAcM_prm_class* appen = fopAcM_CreateAppend();
|
||||
const auto& objectAdditions = randomizer_GetContext().mObjectAdditions;
|
||||
if (objectAdditions.contains(stageRoomLayer)) {
|
||||
for (const auto& actorData : objectAdditions.at(stageRoomLayer)) {
|
||||
stage_tgsc_data_class object{};
|
||||
object.scale = fopAcM_prmScale_class{0, 0, 0};
|
||||
std::memcpy(&object, actorData.data(), actorData.size());
|
||||
// Code below copied from base game
|
||||
fopAcM_prm_class* appen = fopAcM_CreateAppend();
|
||||
|
||||
if (appen != NULL) {
|
||||
appen->base = actor.base;
|
||||
appen->room_no = (int)i_stage->getRoomNo();
|
||||
dStage_actorCreate(&actor, appen);
|
||||
}
|
||||
if (appen != NULL) {
|
||||
appen->base = object.base;
|
||||
appen->room_no = (int)i_stage->getRoomNo();
|
||||
appen->scale = object.scale;
|
||||
dStage_actorCreate(reinterpret_cast<stage_actor_data_class*>(&object), appen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2768,7 +2773,7 @@ void dStage_dt_c_roomReLoader(void* i_data, dStage_dt_c* i_stage, int param_2) {
|
||||
#if TARGET_PC
|
||||
// Spawn our custom actors in randomizer
|
||||
if (randomizer_IsActive()) {
|
||||
dStage_createActorAdditions(i_stage);
|
||||
dStage_createObjectAdditions(i_stage);
|
||||
}
|
||||
#endif
|
||||
layerActorLoader(i_data, i_stage, param_2);
|
||||
|
||||
@@ -78,25 +78,18 @@ std::optional<std::string> RandomizerContext::WriteToFile() {
|
||||
out["mStartHour"] = static_cast<u16>(this->mStartHour);
|
||||
out["mMapBits"] = static_cast<u16>(this->mMapBits);
|
||||
|
||||
for (const auto& [stageRoomLayer, actorPatches] : this->mActorPatches) {
|
||||
for (const auto& [stageRoomLayer, actorPatches] : this->mObjectPatches) {
|
||||
for (const auto& [actorCRC, actorPatch] : actorPatches) {
|
||||
out["mActorPatches"][stageRoomLayer][actorCRC] = ContainerToHexString(actorPatch);
|
||||
out["mObjectPatches"][stageRoomLayer][actorCRC] = ContainerToHexString(actorPatch);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
for (const auto& [stageRoomLayer, newActors] : this->mObjectAdditions) {
|
||||
for (const auto& actor : newActors) {
|
||||
out["mObjectAdditions"][stageRoomLayer].push_back(ContainerToHexString(actor));
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& [stageRoomLayer, actorPatches] : this->mTgscDeletions) {
|
||||
for (const auto& actorCRC : actorPatches) {
|
||||
out["mTgscDeletions"][stageRoomLayer].push_back(actorCRC);
|
||||
}
|
||||
}
|
||||
|
||||
out["mFlowPatches"] = this->mFlowPatches;
|
||||
|
||||
@@ -216,36 +209,20 @@ std::optional<std::string> RandomizerContext::LoadFromHash(const std::string& ha
|
||||
// Starting map bits
|
||||
this->mMapBits = in["mMapBits"].as<u8>();
|
||||
|
||||
// Actor Patches
|
||||
for (const auto& stageRoomLayerNode: in["mActorPatches"]) {
|
||||
// Object Patches
|
||||
for (const auto& stageRoomLayerNode: in["mObjectPatches"]) {
|
||||
u32 stageRoomLayer = stageRoomLayerNode.first.as<u32>();
|
||||
for (const auto& actorPatchNode : stageRoomLayerNode.second) {
|
||||
u32 actorCRC = actorPatchNode.first.as<u32>();
|
||||
auto actorBytes = HexToBytes(actorPatchNode.second.as<std::string>());
|
||||
auto& patchedActor = this->mActorPatches[stageRoomLayer][actorCRC];
|
||||
std::copy_n(actorBytes.begin(), actorBytes.size(), patchedActor.begin());
|
||||
this->mObjectPatches[stageRoomLayer][actorCRC] = HexToBytes(actorPatchNode.second.as<std::string>());
|
||||
}
|
||||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
// Object Additions
|
||||
for (const auto& stageNode: in["mObjectAdditions"]) {
|
||||
u32 stageRoomLayer = stageNode.first.as<u32>();
|
||||
for (const auto& objectData : stageNode.second) {
|
||||
this->mObjectAdditions[stageRoomLayer].emplace_back(HexToBytes(objectData.as<std::string>()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,6 +722,82 @@ u32 getStageObjCRC32(u8* data, size_t size) {
|
||||
return zng_crc32(0, (data), size);
|
||||
}
|
||||
|
||||
stage_tgsc_data_class parseObjData(const YAML::Node& objectNode) {
|
||||
using namespace Utility::Endian;
|
||||
// Get all the data for the actor (with endian shenanigans)
|
||||
stage_tgsc_data_class object{};
|
||||
const auto& actorName = objectNode["name"].as<std::string>();
|
||||
strncpy(object.name, actorName.c_str(), 8);
|
||||
object.base.parameters = toPlatform(target, objectNode["parameters"].as<u32>());
|
||||
object.base.position.x = toPlatform(target, objectNode["position"]["x"].as<f32>());
|
||||
object.base.position.y = toPlatform(target, objectNode["position"]["y"].as<f32>());
|
||||
object.base.position.z = toPlatform(target, objectNode["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
|
||||
object.base.angle.x = toPlatform(target, static_cast<s16>(objectNode["angle"]["x"].as<u16>()));
|
||||
object.base.angle.y = toPlatform(target, static_cast<s16>(objectNode["angle"]["y"].as<u16>()));
|
||||
object.base.angle.z = toPlatform(target, static_cast<s16>(objectNode["angle"]["z"].as<u16>()));
|
||||
object.base.setID = toPlatform(target, static_cast<s16>(objectNode["set id"].as<u16>()));
|
||||
|
||||
if (objectNode["scale"]) {
|
||||
object.scale.x = objectNode["scale"]["x"].as<u8>();
|
||||
object.scale.y = objectNode["scale"]["y"].as<u8>();
|
||||
object.scale.z = objectNode["scale"]["z"].as<u8>();
|
||||
} else {
|
||||
object.scale = fopAcM_prmScale_class{0, 0, 0};
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void parseObjPatchData(stage_tgsc_data_class& object, const YAML::Node& patchNode) {
|
||||
using namespace Utility::Endian;
|
||||
if (patchNode["name"]) {
|
||||
const auto& newName = patchNode["name"].as<std::string>();
|
||||
strncpy(object.name, newName.c_str(), 8);
|
||||
}
|
||||
if (patchNode["parameters"]) {
|
||||
object.base.parameters = toPlatform(target, patchNode["parameters"].as<u32>());
|
||||
}
|
||||
if (auto patchPosition = patchNode["position"]) {
|
||||
if (patchPosition["x"]) {
|
||||
object.base.position.x = toPlatform(target, patchPosition["x"].as<f32>());
|
||||
}
|
||||
if (patchPosition["y"]) {
|
||||
object.base.position.y = toPlatform(target, patchPosition["y"].as<f32>());
|
||||
}
|
||||
if (patchPosition["z"]) {
|
||||
object.base.position.z = toPlatform(target, patchPosition["z"].as<f32>());
|
||||
}
|
||||
}
|
||||
if (auto patchAngle = patchNode["angle"]) {
|
||||
// Have to retrieve as u16 and then cast as s16 because otherwise yaml-cpp
|
||||
// complains about values over 32767 not fitting in s16
|
||||
if (patchAngle["x"]) {
|
||||
object.base.angle.x = toPlatform(target, static_cast<s16>(patchAngle["x"].as<u16>()));
|
||||
}
|
||||
if (patchAngle["y"]) {
|
||||
object.base.angle.y = toPlatform(target, static_cast<s16>(patchAngle["y"].as<u16>()));
|
||||
}
|
||||
if (patchAngle["z"]) {
|
||||
object.base.angle.z = toPlatform(target, static_cast<s16>(patchAngle["z"].as<u16>()));
|
||||
}
|
||||
}
|
||||
if (auto patchScale = patchNode["scale"]) {
|
||||
// Have to retrieve as u16 and then cast as s16 because otherwise yaml-cpp
|
||||
// complains about values over 32767 not fitting in s16
|
||||
if (patchScale["x"]) {
|
||||
object.scale.x = toPlatform(target, static_cast<s16>(patchScale["x"].as<u16>()));
|
||||
}
|
||||
if (patchScale["y"]) {
|
||||
object.scale.y = toPlatform(target, static_cast<s16>(patchScale["y"].as<u16>()));
|
||||
}
|
||||
if (patchScale["z"]) {
|
||||
object.scale.z = toPlatform(target, static_cast<s16>(patchScale["z"].as<u16>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RandomizerContext WriteSeedData(const std::unique_ptr<randomizer::logic::world::World>& world) {
|
||||
RandomizerContext randoData{};
|
||||
|
||||
@@ -943,183 +996,56 @@ RandomizerContext WriteSeedData(const std::unique_ptr<randomizer::logic::world::
|
||||
randoData.mStartHour = 24;
|
||||
|
||||
// Actor Patches
|
||||
auto actorPatches = LoadYAML(RANDO_DATA_PATH "actor_patches.yaml");
|
||||
auto actorPatches = LoadYAML(RANDO_DATA_PATH "object_patches.yaml");
|
||||
for (const auto& stageNode : actorPatches) {
|
||||
const auto& stageName = stageNode.first.as<std::string>();
|
||||
for (const auto& roomNode : stageNode.second) {
|
||||
u8 roomNo = roomNode.first.as<u8>();
|
||||
for (const auto& actorNode : roomNode.second) {
|
||||
using namespace Utility::Endian;
|
||||
for (const auto& objectNode : roomNode.second) {
|
||||
const auto& action = objectNode["action"].as<std::string>();
|
||||
|
||||
// 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>()));
|
||||
auto object = parseObjData(objectNode);
|
||||
|
||||
size_t objDataSize = RandomizerContext::TGSC_CRC_SIZE;
|
||||
// If the scale of this object is all zeros, it's an ACTR
|
||||
if (object.scale.x == 0 && object.scale.y == 0 && object.scale.z == 0) {
|
||||
objDataSize = RandomizerContext::ACTR_CRC_SIZE;
|
||||
}
|
||||
|
||||
// Create unique hash based off of actor data
|
||||
u32 actorCRC32 = getStageObjCRC32(reinterpret_cast<u8*>(&actor), RandomizerContext::ACTOR_CRC_SIZE);
|
||||
u32 objectCRC32 = getStageObjCRC32(reinterpret_cast<u8*>(&object), objDataSize);
|
||||
|
||||
// Then override the actor with whatever parts are being patched
|
||||
const auto& patchNode = actorNode["patch"];
|
||||
if (patchNode["name"]) {
|
||||
const auto& newName = patchNode["name"].as<std::string>();
|
||||
strncpy(actor.name, newName.c_str(), 8);
|
||||
}
|
||||
if (patchNode["parameters"]) {
|
||||
actor.base.parameters = toPlatform(target, patchNode["parameters"].as<u32>());
|
||||
}
|
||||
if (auto patchPosition = patchNode["position"]) {
|
||||
if (patchPosition["x"]) {
|
||||
actor.base.position.x = toPlatform(target, patchPosition["x"].as<f32>());
|
||||
}
|
||||
if (patchPosition["y"]) {
|
||||
actor.base.position.y = toPlatform(target, patchPosition["y"].as<f32>());
|
||||
}
|
||||
if (patchPosition["z"]) {
|
||||
actor.base.position.z = toPlatform(target, patchPosition["z"].as<f32>());
|
||||
}
|
||||
}
|
||||
if (auto patchAngle = patchNode["angle"]) {
|
||||
// Have to retrieve as u16 and then cast as s16 because otherwise yaml-cpp
|
||||
// complains about values over 32767 not fitting in s16
|
||||
if (patchAngle["x"]) {
|
||||
actor.base.angle.x = toPlatform(target, static_cast<s16>(patchAngle["x"].as<u16>()));
|
||||
}
|
||||
if (patchAngle["y"]) {
|
||||
actor.base.angle.y = toPlatform(target, static_cast<s16>(patchAngle["y"].as<u16>()));
|
||||
}
|
||||
if (patchAngle["z"]) {
|
||||
actor.base.angle.z = toPlatform(target, static_cast<s16>(patchAngle["z"].as<u16>()));
|
||||
}
|
||||
// Depending on the action, store data on this actor
|
||||
std::vector<u8> actorData(0);
|
||||
// If we're patching this object, Then override the object with whatever parts are being patched
|
||||
// and add that patch data to our actorData
|
||||
if (action == "patch") {
|
||||
parseObjPatchData(object, objectNode["patch"]);
|
||||
actorData.resize(objDataSize);
|
||||
std::memcpy(actorData.data(), &object, objDataSize);
|
||||
} else if (action == "add") {
|
||||
// If we're adding the object, add it's regular data to the actorData
|
||||
actorData.resize(objDataSize);
|
||||
std::memcpy(actorData.data(), &object, objDataSize);
|
||||
} else if (action == "delete") {
|
||||
// If we're deleting this actor, give it a specific size to indicate we're deleting it
|
||||
actorData.resize(RandomizerContext::OBJ_DELETE_SIZE);
|
||||
}
|
||||
|
||||
// Insert the actor patch into the context with our crc32 as the key and the
|
||||
// raw actor patch data as the value
|
||||
std::array<u8, RandomizerContext::ACTOR_CRC_SIZE> patchedActorData{};
|
||||
std::memcpy(patchedActorData.data(), &actor, RandomizerContext::ACTOR_CRC_SIZE);
|
||||
for (const auto& layerNode : actorNode["layers"]) {
|
||||
// Loop through all of our layers to apply this action to
|
||||
for (const auto& layerNode : objectNode["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.mActorPatches[stageRoomLayerKey][actorCRC32] = patchedActorData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (action == "add") {
|
||||
randoData.mObjectAdditions[stageRoomLayerKey].push_back(actorData);
|
||||
} else { // patch or delete
|
||||
randoData.mObjectPatches[stageRoomLayerKey][objectCRC32] = actorData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
*/
|
||||
class RandomizerContext {
|
||||
public:
|
||||
static constexpr size_t ACTOR_CRC_SIZE = 30;
|
||||
static constexpr size_t TGSC_CRC_SIZE = 35;
|
||||
static constexpr size_t ACTR_CRC_SIZE = 32;
|
||||
static constexpr size_t TGSC_CRC_SIZE = 35; // 3 extra bytes for scale x, y, z
|
||||
static constexpr size_t OBJ_DELETE_SIZE = 1;
|
||||
|
||||
RandomizerContext() = default;
|
||||
|
||||
@@ -45,9 +46,9 @@ public:
|
||||
u8 mStartHour{0};
|
||||
u8 mMapBits{};
|
||||
|
||||
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, std::unordered_map<u32, std::vector<u8>>> mObjectPatches{};
|
||||
std::unordered_map<u32, std::list<std::vector<u8>>> mObjectAdditions{};
|
||||
// std::unordered_map<u32, std::unordered_set<u32>> mTgscDeletions{};
|
||||
std::unordered_map<u32, u64> mFlowPatches{};
|
||||
|
||||
// struct TextOverride {
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
# New actors to spawn in
|
||||
|
||||
# NOTE: All data is expressed in little endian format
|
||||
|
||||
# Objects which have the ACTR dzx type
|
||||
ACTR:
|
||||
# Faron Woods
|
||||
F_SP108:
|
||||
# Room 6 - North Faron Woods
|
||||
6:
|
||||
# Spawn Item for Golden Wolf in North Faron Woods layer 3
|
||||
- name: htPiece
|
||||
parameters: 0xFFFFFFE1
|
||||
position:
|
||||
x: -36699.4375
|
||||
y: 428.600311279297
|
||||
z: -23663.64453125
|
||||
angle:
|
||||
x: 0x0000
|
||||
y: 0x0000
|
||||
z: 0x00FF
|
||||
layers:
|
||||
- 3
|
||||
|
||||
# Lake Hylia
|
||||
F_SP115:
|
||||
# Room 0 - Main Lake
|
||||
0:
|
||||
# Spawn Auru on layers 1 & 3
|
||||
- name: Rafrel
|
||||
parameters: 0x00001D01
|
||||
position:
|
||||
x: -116486.945
|
||||
y: -13860.0
|
||||
z: 58533.0078
|
||||
angle:
|
||||
x: 0x0000
|
||||
y: 0xCCCD
|
||||
z: 0x0000
|
||||
layers:
|
||||
- 1
|
||||
- 3
|
||||
|
||||
# Spawn red rupee behind canon so players always have
|
||||
# enough money for the canon
|
||||
- name: item
|
||||
parameters: 0xF3FFFF04
|
||||
position:
|
||||
x: -108290.086
|
||||
y: -18654.748
|
||||
z: 45935.2969
|
||||
angle:
|
||||
x: 0x0000
|
||||
y: 0x0001
|
||||
z: 0x003F
|
||||
layers:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
# Sacred Grove
|
||||
F_SP117:
|
||||
# Room 1 - 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
|
||||
|
||||
# Outside Arbiters Grounds
|
||||
F_SP118:
|
||||
# Room 1 - Bulblin Camp
|
||||
1:
|
||||
# Spawn in the item for the Bulblin Guard Key on
|
||||
# the layer where the camp is already beaten
|
||||
- name: htPiece
|
||||
parameters: 0x00FF9AD7
|
||||
position:
|
||||
x: 4000
|
||||
y: 300
|
||||
z: -3500
|
||||
angle:
|
||||
x: 0x0000
|
||||
y: 0x0000
|
||||
z: 0x0000
|
||||
layers:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
# Kakariko Interiors
|
||||
R_SP109:
|
||||
# Kak Malo Mart
|
||||
3:
|
||||
# Spawn in a middle item Sold Out Sign
|
||||
- name: TGSPITM
|
||||
parameters: 0x02FFFFFF
|
||||
position:
|
||||
x: -650.0
|
||||
y: 450.0
|
||||
z: -500.0
|
||||
angle:
|
||||
x: 0x0147
|
||||
y: 0x8000
|
||||
z: 0x05FF
|
||||
layers:
|
||||
- 2
|
||||
- 3
|
||||
|
||||
# Castle Town Shops
|
||||
R_SP160:
|
||||
# Jovani's House
|
||||
5:
|
||||
# Spawn the poe in Jovani's House
|
||||
- name: E_hp
|
||||
parameters: 0xFF031E00
|
||||
position:
|
||||
x: 4531.19
|
||||
y: -30.0
|
||||
z: 2631.961
|
||||
angle:
|
||||
x: 0x0000
|
||||
y: 0x0000
|
||||
z: 0x0000
|
||||
layers:
|
||||
- 0
|
||||
- 1
|
||||
@@ -1,26 +0,0 @@
|
||||
# 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
|
||||
+643
-165
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user