mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-21 14:53:30 -04:00
cleanup
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
#include "imgui.h"
|
||||
|
||||
#include "d/d_stage.h"
|
||||
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "ImGuiMenuRandomizer.hpp"
|
||||
|
||||
@@ -9,7 +7,6 @@
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/randomizer/game/randomizer_context.hpp"
|
||||
#include "dusk/randomizer/game/tools.h"
|
||||
#include "dusk/randomizer/generator/randomizer.hpp"
|
||||
|
||||
#include "SDL3/SDL_filesystem.h"
|
||||
|
||||
@@ -17,237 +14,20 @@
|
||||
#include <thread>
|
||||
#include <filesystem>
|
||||
|
||||
#include "dusk/randomizer/generator/utility/endian.hpp"
|
||||
#include "dusk/randomizer/generator/utility/string.hpp"
|
||||
|
||||
namespace dusk {
|
||||
|
||||
static bool generatingSeed = false;
|
||||
static std::string generationStatusMsg{};
|
||||
static std::mutex generationStatusMsgMutex{};
|
||||
|
||||
void GenerateSeed() {
|
||||
std::lock_guard lock(generationStatusMsgMutex);
|
||||
const auto result = SDL_GetPrefPath(dusk::OrgName, dusk::AppName);
|
||||
if (!result) {
|
||||
DuskLog.fatal("Unable to get PrefPath: {}", SDL_GetError());
|
||||
}
|
||||
randomizer::Randomizer r;
|
||||
r.SetBaseOutputPath(result);
|
||||
auto generationResult = r.Generate();
|
||||
if (generationResult.has_value()) {
|
||||
generationStatusMsg = fmt::format("Generation failed with the following error:\n{}", generationResult.value());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& world = r.GetWorlds()[0];
|
||||
|
||||
RandomizerContext randoData{};
|
||||
|
||||
// Settings we need to check ingame
|
||||
for (const auto& [setting, info] : *randomizer::seedgen::settings::GetAllSettingsInfo()) {
|
||||
if (info->NeedInGame()) {
|
||||
randoData.mSettings[setting] = world->Setting(setting).GetCurrentOption();
|
||||
}
|
||||
}
|
||||
|
||||
// Set data for all locations
|
||||
for (const auto& location : world->GetAllLocations()) {
|
||||
const auto& metaData = location->GetMetadata();
|
||||
|
||||
// Chest Overrides
|
||||
if (location->HasCategories("Chest")) {
|
||||
const auto& stage = metaData[0]["Stage"].as<std::string>();
|
||||
const auto& tboxId = metaData[0]["Tbox ID"].as<u8>();
|
||||
const auto& itemId = location->GetCurrentItem()->GetID();
|
||||
randoData.mTreasureChestOverrides[stage][tboxId] = itemId;
|
||||
}
|
||||
|
||||
// Freestanding Overrides
|
||||
if (location->HasCategories("Freestanding Item")) {
|
||||
u8 stage = metaData[0]["Stage"].as<u8>();
|
||||
u8 flag = metaData[0]["Flag"].as<u8>();
|
||||
u8 itemId = location->GetCurrentItem()->GetID();
|
||||
randoData.mFreestandingItemOverrides[stage][flag] = itemId;
|
||||
}
|
||||
|
||||
// Bug Rewards
|
||||
if (location->HasCategories("Bug Reward")) {
|
||||
u8 bugItemId = metaData[0]["Bug Item Id"].as<u8>();
|
||||
u8 itemId = location->GetCurrentItem()->GetID();
|
||||
randoData.mBugRewardOverrides[bugItemId] = itemId;
|
||||
}
|
||||
|
||||
// Items that we lookup just by calling their location name
|
||||
if (location->HasCategories("Location Name Lookup")) {
|
||||
const auto& locationName = metaData.as<std::string>();
|
||||
const int itemId = location->GetCurrentItem()->GetID();
|
||||
randoData.mItemLocations[locationName] = itemId;
|
||||
}
|
||||
}
|
||||
|
||||
// Set starting inventory
|
||||
for (const auto& item: world->GetStartingItemPool()) {
|
||||
randoData.mStartingInventory.push_back(item->GetID());
|
||||
}
|
||||
|
||||
// Set starting flags
|
||||
auto startFlags = LoadYAML(RANDO_DATA_PATH "startflags.yaml");
|
||||
// Event Flags
|
||||
for (const auto& flagNode : startFlags["EventFlags"]) {
|
||||
if (flagNode.IsScalar()) {
|
||||
const auto& flag = flagNode.as<u16>();
|
||||
randoData.mStartEventFlags.push_back(flag);
|
||||
} else if (flagNode.IsMap()) {
|
||||
const auto& condition = flagNode.begin()->first.as<std::string>();
|
||||
if (world->EvaluateSettingCondition(condition)) {
|
||||
DuskLog.debug("Setting flags for {}", condition);
|
||||
for (const auto& conditionalFlag : flagNode.begin()->second) {
|
||||
const auto& flag = conditionalFlag.as<u16>();
|
||||
randoData.mStartEventFlags.push_back(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Region Flags
|
||||
for (const auto& regionNode : startFlags["RegionFlags"]) {
|
||||
const auto& region = regionNode.first.as<std::string>();
|
||||
const auto& index = regionNode.second["Index"].as<int>();
|
||||
const auto& flags = regionNode.second["Flags"];
|
||||
DuskLog.debug("Setting region flags for {}", region);
|
||||
// This seems kinda scuffed so maybe we change it later
|
||||
for (const auto& flagNode : flags) {
|
||||
if (flagNode.IsScalar()) {
|
||||
const auto& flag = flagNode.as<int>();
|
||||
randoData.mStartRegionFlags[index].push_back(flag);
|
||||
} else if (flagNode.IsMap()) {
|
||||
const auto& condition = flagNode.begin()->first.as<std::string>();
|
||||
if (world->EvaluateSettingCondition(condition)) {
|
||||
for (const auto& conditionalFlag : flagNode.begin()->second) {
|
||||
const auto& flag = conditionalFlag.as<int>();
|
||||
randoData.mStartRegionFlags[index].push_back(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (world->Setting("Unlock Map Regions") == "On")
|
||||
{
|
||||
auto& bits = randoData.mMapBits;
|
||||
bits = 0x20;
|
||||
if (world->Setting("Snowpeak Does Not Require Reekfish Scent") == "On") {bits |= 0x40;}
|
||||
if (world->Setting("Lanayru Twilight Cleared") == "On") {bits |= 0x10;}
|
||||
if (world->Setting("Eldin Twilight Cleared") == "On") {bits |= 0x08;}
|
||||
if (world->Setting("Faron Twilight Cleared") == "On") {bits |= 0x04;}
|
||||
if (world->Setting("Skip Prologue") == "On") {bits |= 0x02;}
|
||||
}
|
||||
|
||||
// Set starting time of day
|
||||
const auto startTimeSetting = world->Setting("Starting Time of Day");
|
||||
if (startTimeSetting == "Morning")
|
||||
randoData.mStartHour = 6;
|
||||
else if (startTimeSetting == "Noon")
|
||||
randoData.mStartHour = 12;
|
||||
else if (startTimeSetting == "Evening")
|
||||
randoData.mStartHour = 18;
|
||||
else if (startTimeSetting == "Night")
|
||||
randoData.mStartHour = 24;
|
||||
|
||||
// Actor Patches
|
||||
auto actorPatches = LoadYAML(RANDO_DATA_PATH "actor_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;
|
||||
// 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>()));
|
||||
|
||||
// Create unique hash based off of actor data
|
||||
u32 actorCRC32 = getActorCRC32(&actor);
|
||||
|
||||
// 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>()));
|
||||
}
|
||||
}
|
||||
|
||||
// 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"]) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
randoData.mHash = r.GetConfig().GetHash();
|
||||
auto writeToFileResult = randoData.WriteToFile();
|
||||
if (writeToFileResult.has_value()) {
|
||||
generationStatusMsg =
|
||||
fmt::format("Failed to write seed data. Reason: {}", writeToFileResult.value());
|
||||
return;
|
||||
}
|
||||
|
||||
generationStatusMsg = fmt::format("Seed generated! Hash: {}", randoData.mHash);
|
||||
}
|
||||
|
||||
static void StartSeedGeneration() {
|
||||
if (generatingSeed) {
|
||||
return;
|
||||
}
|
||||
|
||||
generatingSeed = true;
|
||||
GenerateSeed();
|
||||
std::lock_guard lock(generationStatusMsgMutex);
|
||||
GenerateAndWriteSeed(generationStatusMsg);
|
||||
generatingSeed = false;
|
||||
DuskLog.debug("{}", generationStatusMsg);
|
||||
}
|
||||
@@ -259,6 +39,7 @@ namespace dusk {
|
||||
if (ImGui::BeginMenu("Generate")) {
|
||||
if (ImGui::MenuItem("Generate Seed", nullptr, false, !generatingSeed)) {
|
||||
|
||||
// Put seed generation on a separate thread so it doesn't freeze the game
|
||||
std::thread randoGenerationThread(StartSeedGeneration);
|
||||
randoGenerationThread.detach();
|
||||
m_showRandoGeneration = true;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include "randomizer_context.hpp"
|
||||
|
||||
#include "../generator/utility/yaml.hpp"
|
||||
|
||||
#include "dusk/app_info.hpp"
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/randomizer/game/tools.h"
|
||||
#include "dusk/randomizer/generator/utility/endian.hpp"
|
||||
#include "dusk/randomizer/generator/utility/yaml.hpp"
|
||||
#include "dusk/randomizer/generator/randomizer.hpp"
|
||||
|
||||
#include "SDL3/SDL_filesystem.h"
|
||||
#include <zlib-ng.h>
|
||||
@@ -15,15 +15,6 @@
|
||||
|
||||
#include "d/actor/d_a_alink.h"
|
||||
|
||||
RandomizerContext& randomizer_GetContext() {
|
||||
static RandomizerContext instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool randomizer_IsActive() {
|
||||
return dusk::IsGameLaunched && (!playerIsOnTitleScreen() || randomizer_GetContext().mCreatingSave) && !randomizer_GetContext().mHash.empty();
|
||||
}
|
||||
|
||||
std::optional<std::string> RandomizerContext::WriteToFile() {
|
||||
|
||||
std::ofstream seedData(this->GetSeedDataPath());
|
||||
@@ -179,6 +170,15 @@ std::string RandomizerContext::GetSeedDataPath() const {
|
||||
return std::string(SDL_GetPrefPath(dusk::OrgName, dusk::AppName)) + "randomizer/seeds/" + this->mHash + "/seed.dat";
|
||||
}
|
||||
|
||||
RandomizerContext& randomizer_GetContext() {
|
||||
static RandomizerContext instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool randomizer_IsActive() {
|
||||
return dusk::IsGameLaunched && (!playerIsOnTitleScreen() || randomizer_GetContext().mCreatingSave) && !randomizer_GetContext().mHash.empty();
|
||||
}
|
||||
|
||||
std::vector<u8> HexToBytes(std::string hex) {
|
||||
std::vector<u8> bytes;
|
||||
// Strip "0x" if present
|
||||
@@ -206,4 +206,219 @@ u32 getActorPatchesCurrentStageKey() {
|
||||
|
||||
u32 getActorCRC32(stage_actor_data_class* actor) {
|
||||
return zng_crc32(0, reinterpret_cast<u8*>(actor), RandomizerContext::ACTOR_CRC_SIZE);
|
||||
}
|
||||
|
||||
void GenerateAndWriteSeed(std::string& generationStatusMsg) {
|
||||
const auto result = SDL_GetPrefPath(dusk::OrgName, dusk::AppName);
|
||||
if (!result) {
|
||||
DuskLog.fatal("Unable to get PrefPath: {}", SDL_GetError());
|
||||
}
|
||||
randomizer::Randomizer r;
|
||||
r.SetBaseOutputPath(result);
|
||||
auto generationResult = r.Generate();
|
||||
if (generationResult.has_value()) {
|
||||
generationStatusMsg = fmt::format("Generation failed with the following error:\n{}", generationResult.value());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& world = r.GetWorlds()[0];
|
||||
|
||||
RandomizerContext randoData{};
|
||||
|
||||
// Settings we need to check ingame
|
||||
for (const auto& [setting, info] : *randomizer::seedgen::settings::GetAllSettingsInfo()) {
|
||||
if (info->NeedInGame()) {
|
||||
randoData.mSettings[setting] = world->Setting(setting).GetCurrentOption();
|
||||
}
|
||||
}
|
||||
|
||||
// Set data for all locations
|
||||
for (const auto& location : world->GetAllLocations()) {
|
||||
const auto& metaData = location->GetMetadata();
|
||||
|
||||
// Chest Overrides
|
||||
if (location->HasCategories("Chest")) {
|
||||
const auto& stage = metaData[0]["Stage"].as<std::string>();
|
||||
const auto& tboxId = metaData[0]["Tbox ID"].as<u8>();
|
||||
const auto& itemId = location->GetCurrentItem()->GetID();
|
||||
randoData.mTreasureChestOverrides[stage][tboxId] = itemId;
|
||||
}
|
||||
|
||||
// Freestanding Overrides
|
||||
if (location->HasCategories("Freestanding Item")) {
|
||||
u8 stage = metaData[0]["Stage"].as<u8>();
|
||||
u8 flag = metaData[0]["Flag"].as<u8>();
|
||||
u8 itemId = location->GetCurrentItem()->GetID();
|
||||
randoData.mFreestandingItemOverrides[stage][flag] = itemId;
|
||||
}
|
||||
|
||||
// Bug Rewards
|
||||
if (location->HasCategories("Bug Reward")) {
|
||||
u8 bugItemId = metaData[0]["Bug Item Id"].as<u8>();
|
||||
u8 itemId = location->GetCurrentItem()->GetID();
|
||||
randoData.mBugRewardOverrides[bugItemId] = itemId;
|
||||
}
|
||||
|
||||
// Items that we lookup just by calling their location name
|
||||
if (location->HasCategories("Location Name Lookup")) {
|
||||
const auto& locationName = metaData.as<std::string>();
|
||||
const int itemId = location->GetCurrentItem()->GetID();
|
||||
randoData.mItemLocations[locationName] = itemId;
|
||||
}
|
||||
}
|
||||
|
||||
// Set starting inventory
|
||||
for (const auto& item: world->GetStartingItemPool()) {
|
||||
randoData.mStartingInventory.push_back(item->GetID());
|
||||
}
|
||||
|
||||
// Set starting flags
|
||||
auto startFlags = LoadYAML(RANDO_DATA_PATH "startflags.yaml");
|
||||
// Event Flags
|
||||
for (const auto& flagNode : startFlags["EventFlags"]) {
|
||||
if (flagNode.IsScalar()) {
|
||||
const auto& flag = flagNode.as<u16>();
|
||||
randoData.mStartEventFlags.push_back(flag);
|
||||
} else if (flagNode.IsMap()) {
|
||||
const auto& condition = flagNode.begin()->first.as<std::string>();
|
||||
if (world->EvaluateSettingCondition(condition)) {
|
||||
DuskLog.debug("Setting flags for {}", condition);
|
||||
for (const auto& conditionalFlag : flagNode.begin()->second) {
|
||||
const auto& flag = conditionalFlag.as<u16>();
|
||||
randoData.mStartEventFlags.push_back(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Region Flags
|
||||
for (const auto& regionNode : startFlags["RegionFlags"]) {
|
||||
const auto& region = regionNode.first.as<std::string>();
|
||||
const auto& index = regionNode.second["Index"].as<int>();
|
||||
const auto& flags = regionNode.second["Flags"];
|
||||
DuskLog.debug("Setting region flags for {}", region);
|
||||
// This seems kinda scuffed so maybe we change it later
|
||||
for (const auto& flagNode : flags) {
|
||||
if (flagNode.IsScalar()) {
|
||||
const auto& flag = flagNode.as<int>();
|
||||
randoData.mStartRegionFlags[index].push_back(flag);
|
||||
} else if (flagNode.IsMap()) {
|
||||
const auto& condition = flagNode.begin()->first.as<std::string>();
|
||||
if (world->EvaluateSettingCondition(condition)) {
|
||||
for (const auto& conditionalFlag : flagNode.begin()->second) {
|
||||
const auto& flag = conditionalFlag.as<int>();
|
||||
randoData.mStartRegionFlags[index].push_back(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (world->Setting("Unlock Map Regions") == "On")
|
||||
{
|
||||
auto& bits = randoData.mMapBits;
|
||||
bits = 0x20;
|
||||
if (world->Setting("Snowpeak Does Not Require Reekfish Scent") == "On") {bits |= 0x40;}
|
||||
if (world->Setting("Lanayru Twilight Cleared") == "On") {bits |= 0x10;}
|
||||
if (world->Setting("Eldin Twilight Cleared") == "On") {bits |= 0x08;}
|
||||
if (world->Setting("Faron Twilight Cleared") == "On") {bits |= 0x04;}
|
||||
if (world->Setting("Skip Prologue") == "On") {bits |= 0x02;}
|
||||
}
|
||||
|
||||
// Set starting time of day
|
||||
const auto startTimeSetting = world->Setting("Starting Time of Day");
|
||||
if (startTimeSetting == "Morning")
|
||||
randoData.mStartHour = 6;
|
||||
else if (startTimeSetting == "Noon")
|
||||
randoData.mStartHour = 12;
|
||||
else if (startTimeSetting == "Evening")
|
||||
randoData.mStartHour = 18;
|
||||
else if (startTimeSetting == "Night")
|
||||
randoData.mStartHour = 24;
|
||||
|
||||
// Actor Patches
|
||||
auto actorPatches = LoadYAML(RANDO_DATA_PATH "actor_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;
|
||||
// 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>()));
|
||||
|
||||
// Create unique hash based off of actor data
|
||||
u32 actorCRC32 = getActorCRC32(&actor);
|
||||
|
||||
// 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>()));
|
||||
}
|
||||
}
|
||||
|
||||
// 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"]) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
randoData.mHash = r.GetConfig().GetHash();
|
||||
auto writeToFileResult = randoData.WriteToFile();
|
||||
if (writeToFileResult.has_value()) {
|
||||
generationStatusMsg =
|
||||
fmt::format("Failed to write seed data. Reason: {}", writeToFileResult.value());
|
||||
return;
|
||||
}
|
||||
|
||||
generationStatusMsg = fmt::format("Seed generated! Hash: {}", randoData.mHash);
|
||||
}
|
||||
@@ -88,4 +88,5 @@ class stage_actor_data_class;
|
||||
*/
|
||||
u32 getActorCRC32(stage_actor_data_class*);
|
||||
|
||||
void GenerateAndWriteSeed(std::string& generationStatusMsg);
|
||||
#endif //DUSK_RANDOMIZER_CONTEXT_HPP
|
||||
|
||||
Reference in New Issue
Block a user