add config menu and hook it up into current config system

currently any options that requires additional settings, like "Hyrule Barrier Requirements", wont actually have any additional options yet until i figure out a clean way to handle that
This commit is contained in:
CraftyBoss
2026-05-10 23:13:02 -07:00
parent 83480110fd
commit 04d9640eff
13 changed files with 431 additions and 102 deletions
+2
View File
@@ -1508,6 +1508,8 @@ set(DUSK_FILES
src/dusk/ui/ui.hpp
src/dusk/ui/window.cpp
src/dusk/ui/window.hpp
src/dusk/ui/rando_config.cpp
src/dusk/ui/rando_config.hpp
src/dusk/achievements.cpp
src/dusk/iso_validate.cpp
src/dusk/livesplit.cpp
+3
View File
@@ -175,6 +175,9 @@ struct UserSettings {
ConfigVar<bool> speedrunMode;
ConfigVar<bool> liveSplitEnabled;
ConfigVar<bool> recordingMode;
// Misc
ConfigVar<bool> randomizerEnabled;
} game;
struct {
+7 -3
View File
@@ -60,10 +60,14 @@ namespace dusk {
std::list<std::string> hashes{};
for (const auto& entry : std::filesystem::directory_iterator(seedDirectory)) {
if (entry.is_directory()) {
hashes.push_back(entry.path().filename().string());
if (std::filesystem::exists(seedDirectory)) {
for (const auto& entry : std::filesystem::directory_iterator(seedDirectory)) {
if (entry.is_directory()) {
hashes.push_back(entry.path().filename().string());
}
}
}else {
std::filesystem::create_directories(seedDirectory);
}
if (hashes.empty()) {
@@ -304,6 +304,8 @@ int RandomizerContext::OptionToEnum(const std::string& optionName) {
RandomizerState g_randomizerState;
randomizer::Randomizer g_RandomizerGenerator;
int RandomizerState::_create() {
mInitialized = true;
mEventItemStatus = QUEUE_EMPTY;
@@ -1164,12 +1166,8 @@ static void DeleteFailedGenerationFiles(randomizer::Randomizer& rando) {
* Generates a seed and writes the necessary seed files to the players seed directory
*/
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& r = g_RandomizerGenerator;
auto generationResult = r.Generate();
if (generationResult.has_value()) {
generationStatusMsg = fmt::format("Seed Generation failed. Reason:\n{}", generationResult.value());
@@ -1199,3 +1197,12 @@ void GenerateAndWriteSeed(std::string& generationStatusMsg) {
generationStatusMsg = fmt::format("Seed generated! Hash: {}", randoData.mHash);
}
void LoadRandomizerConfig() {
const auto result = SDL_GetPrefPath(dusk::OrgName, dusk::AppName);
if (!result)
DuskLog.fatal("Unable to get PrefPath: {}", SDL_GetError());
g_RandomizerGenerator.SetBaseOutputPath(result);
g_RandomizerGenerator.LoadConfig();
}
@@ -12,6 +12,8 @@
#include <unordered_map>
#include <unordered_set>
#include "dusk/randomizer/generator/randomizer.hpp"
/*
* Class holding all the information necessary for playing
* the current randomizer seed
@@ -162,6 +164,8 @@ public:
u8 mFlowMessageItemId{0};
};
extern randomizer::Randomizer g_RandomizerGenerator;
extern RandomizerState g_randomizerState;
RandomizerContext& randomizer_GetContext();
@@ -215,4 +219,7 @@ class stage_actor_data_class;
u32 getStageObjCRC32(u8* data, size_t size);
void GenerateAndWriteSeed(std::string& generationStatusMsg);
void LoadRandomizerConfig();
#endif //DUSK_RANDOMIZER_CONTEXT_HPP
@@ -34,35 +34,35 @@
Tracker Important: True
Default Option: 1
Options:
- 1-3: description
- 1-3: No description available.
- Name: Hyrule Barrier Mirror Shards
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-4: description
- 1-4: No description available.
- Name: Hyrule Barrier Dungeons
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-8: description
- 1-8: No description available.
- Name: Hyrule Barrier Poe Souls
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-60: description
- 1-60: No description available.
- Name: Hyrule Barrier Hearts
Need In Game: True
Tracker Important: True
Default Option: 4
Options:
- 4-20: description # Hehe 420
- 4-20: No description available. # Hehe 420
- Name: Palace of Twilight Requirements
Need In Game: True
@@ -96,62 +96,62 @@
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Gifts From NPCs
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Shop Items
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Hidden Skills
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Hidden Rupees
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Freestanding Rupees
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Poe Souls
Tracker Important: True
Default Option: Vanilla
Options:
- Vanilla: description
- Overworld: description
- Dungeon: description
- All: description
- Vanilla: No description available.
- Overworld: No description available.
- Dungeon: No description available.
- All: No description available.
- Name: Ilia Memory Quest
Tracker Important: True
Default Option: Vanilla
Options:
- Vanilla: description
- Letter: description
- Invoice: description
- Statue: description
- Charm: description
- Vanilla: No description available.
- Letter: No description available.
- Invoice: No description available.
- Statue: No description available.
- Charm: No description available.
- Name: Item Scarcity
Default Option: Vanilla
@@ -218,47 +218,47 @@
Tracker Important: True
Default Option: 1
Options:
- 1-3: description
- 1-3: No description available.
- Name: Hyrule Castle Big Key Mirror Shards
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-4: description
- 1-4: No description available.
- Name: Hyrule Castle Big Key Dungeons
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-8: description
- 1-8: No description available.
- Name: Hyrule Castle Big Key Poe Souls
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-60: description
- 1-60: No description available.
- Name: Hyrule Castle Big Key Hearts
Need In Game: True
Tracker Important: True
Default Option: 4
Options:
- 4-20: description # Hehe 420
- 4-20: No description available. # Hehe 420
- Name: Dungeon Rewards Can Be Anywhere
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: No Small Keys on Bosses
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
# - Name: required_dungeons
# Default Option: 2
@@ -283,87 +283,87 @@
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Faron Twilight Cleared
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Eldin Twilight Cleared
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Lanayru Twilight Cleared
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Skip Midna's Desparate Hour
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Skip Minor Cutscenes
Need In Game: True
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Skip Major Cutscenes
Need In Game: True
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Unlock Map Regions
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Open Door of Time
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Active Goron Mines Magnets
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Lower Hyrule Castle Chandelier
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Skip Bridge Donation
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
######################
# Additional Settings#
@@ -380,22 +380,22 @@
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Shops Display The Replaced Item
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Bonks Do Damage
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Trap Item Frequency
Default Option: None
@@ -409,19 +409,19 @@
- Name: Damage Multiplier
Default Option: Vanilla
Options:
- Vanilla: description
- Double: description
- Triple: description
- Quadruple: description
- Vanilla: No description available.
- Double: No description available.
- Triple: No description available.
- Quadruple: No description available.
- OHKO: Any damage taken will kill link
- Name: Starting Time of Day
Default Option: Noon
Options:
- Morning: description
- Noon: description
- Evening: description
- Night: description
- Morning: No description available.
- Noon: No description available.
- Evening: No description available.
- Night: No description available.
#############################
# Dungeon Entrance Settings #
@@ -431,55 +431,55 @@
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Arbiters Does Not Require Bulblin Camp
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Snowpeak Does Not Require Reekfish Scent
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Sacred Grove Does Not Require Skull Kid
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: City Does Not Require Filled Skybook
Tracker Important: True
Default Option: "Off"
Options:
- "Off": description
- "On": description
- "Off": No description available.
- "On": No description available.
- Name: Goron Mines Entrance
Tracker Important: True
Default Option: Closed
Options:
- Closed: description
- No Wrestling: description
- Open: description
- Closed: No description available.
- No Wrestling: No description available.
- Open: No description available.
- Name: Temple of Time Sword Requirement
Need In Game: True
Tracker Important: True
Default Option: None
Options:
- None: description
- Wooden Sword: description
- Ordon Sword: description
- Master Sword: description
- Light Sword: description
- None: No description available.
- Wooden Sword: No description available.
- Ordon Sword: No description available.
- Master Sword: No description available.
- Light Sword: No description available.
# - Name: chest_type_matches_contents
# Default Option: "Off"
+9 -1
View File
@@ -31,11 +31,19 @@ namespace randomizer
return std::nullopt;
}
void Randomizer::LoadConfig() {
this->_config.LoadFromFile(GetConfigPath(), GetPrefPath());
}
void Randomizer::GenerateWorlds()
{
utility::time::ScopedTimer<"Seed generation took ", std::chrono::milliseconds> timer;
this->_worlds.clear();
this->_config.LoadFromFile(this->GetBaseOutputPath() + "settings.yaml", this->GetBaseOutputPath() + "preferences.yaml");
this->_eventIdCounter = 0;
this->_areaIdCounter = 0;
this->_locAccIdCounter = 0;
this->_playthroughSpheres.clear();
this->_entranceSpheres.clear();
utility::platform::Log(std::string("Seed: ") + this->_config.GetSeed());
@@ -32,6 +32,11 @@ namespace randomizer
std::string GetSeedOutputPath();
const std::string& GetBaseOutputPath() const { return this->_baseOutputPath; };
void SetBaseOutputPath(const std::string& path) { this->_baseOutputPath = path + "randomizer/"; };
void LoadConfig();
std::string GetConfigPath() const { return this->GetBaseOutputPath() + "settings.yaml"; }
std::string GetPrefPath() const { return this->GetBaseOutputPath() + "preferences.yaml"; }
private:
seedgen::config::Config _config{};
logic::world::WorldPool _worlds{};
+4 -1
View File
@@ -111,7 +111,8 @@ UserSettings g_userSettings = {
// Tools
.speedrunMode {"game.speedrunMode", false},
.liveSplitEnabled {"game.liveSplitEnabled", false},
.recordingMode {"game.recordingMode", false}
.recordingMode {"game.recordingMode", false},
.randomizerEnabled = {"game.randomizerEnabled", false}
},
.backend = {
@@ -222,6 +223,8 @@ void registerSettings() {
Register(g_userSettings.game.debugFlyCamLockEvents);
Register(g_userSettings.game.allowBackgroundInput);
Register(g_userSettings.game.randomizerEnabled);
Register(g_userSettings.backend.isoPath);
Register(g_userSettings.backend.isoVerification);
Register(g_userSettings.backend.graphicsBackend);
+5
View File
@@ -21,6 +21,8 @@
#include <chrono>
#include <cmath>
#include "rando_config.hpp"
namespace dusk::ui {
namespace {
@@ -58,6 +60,9 @@ MenuBar::MenuBar() : Document(kDocumentSource), mRoot(mDocument->GetElementById(
}
mTabBar->add_tab("Achievements", [this] { push(std::make_unique<AchievementsWindow>()); });
mTabBar->add_tab("Randomizer", [this] { push(std::make_unique<RandomizerWindow>()); });
mTabBar->add_tab("Reset", [this] {
mTabBar->set_active_tab(-1);
const auto dismiss = [](Modal& modal) { modal.pop(); };
+270
View File
@@ -0,0 +1,270 @@
#include "rando_config.hpp"
#include <mutex>
#include "bool_button.hpp"
#include "pane.hpp"
#include "dusk/config.hpp"
#include "dusk/logging.h"
namespace dusk::ui {
struct ConfigBoolProps {
Rml::String key;
Rml::String icon;
Rml::String helpText;
std::function<void(bool)> onChange;
std::function<bool()> isDisabled;
};
static bool generatingSeed = false;
static std::string generationStatusMsg{};
static std::mutex generationStatusMsgMutex{};
static void StartSeedGeneration() {
if (generatingSeed) {
return;
}
generatingSeed = true;
std::lock_guard lock(generationStatusMsgMutex);
GenerateAndWriteSeed(generationStatusMsg);
generatingSeed = false;
DuskLog.debug("{}", generationStatusMsg);
}
// ripped straight from settings window
SelectButton& config_bool_select(
Pane& leftPane, Pane& rightPane, ConfigVar<bool>& var, ConfigBoolProps props) {
auto& button = leftPane.add_child<BoolButton>(BoolButton::Props{
.key = std::move(props.key),
.icon = std::move(props.icon),
.getValue = [&var] { return var.getValue(); },
.setValue =
[&var, callback = std::move(props.onChange)](bool value) {
if (value == var.getValue()) {
return;
}
var.setValue(value);
config::Save();
if (callback) {
callback(value);
}
},
.isDisabled = std::move(props.isDisabled),
.isModified = [&var] { return var.getValue() != var.getDefaultValue(); },
});
leftPane.register_control(
button, rightPane, [helpText = std::move(props.helpText)](Pane& pane) {
pane.clear();
pane.add_rml(helpText);
});
return button;
}
auto& FindSetting(const std::string& key) {
// TODO: handle multi-world selection
auto& settings = g_RandomizerGenerator.GetConfig().GetSettingsList().front();
return settings.GetMap().at(key);
}
auto* FindSettingPtr(const std::string& key) {
// TODO: handle multi-world selection
auto& settings = g_RandomizerGenerator.GetConfig().GetSettingsList().front();
return &settings.GetMap().at(key);
}
void SaveConfig() {
g_RandomizerGenerator.GetConfig().WriteSettingsToFile(g_RandomizerGenerator.GetConfigPath());
}
void rando_config_group(Pane& leftPane, Pane& rightPane, std::string settingKey) {
auto randoSettings = randomizer::seedgen::settings::GetAllSettingsInfo();
auto& settingData = randoSettings->at(settingKey);
if (settingData == nullptr) {
return;
}
auto& curSetting = FindSetting(settingKey);
leftPane.register_control(
leftPane.add_select_button({
.key = settingKey,
.getValue =
[settingKey = std::move(settingKey)] { return Rml::String{FindSetting(settingKey).GetCurrentOption()}; },
}),
rightPane, [&curSetting, settingKey](Pane& pane) {
auto curSelIdx = curSetting.GetCurrentOptionIndex();
auto settingInfo = curSetting.GetInfo();
Rml::Element* text_elem = pane.add_rml(settingInfo->GetDescriptions().at(curSelIdx));
for (int i = 0; i < settingInfo->GetOptions().size(); ++i) {
pane.add_button(
{
.text = settingInfo->GetOptions()[i],
.isSelected = [settingKey = std::move(settingKey), i] { return FindSetting(settingKey).GetCurrentOptionIndex() == i; },
})
.on_pressed([i, text_elem, settingKey = std::move(settingKey)] {
auto& curSetting = FindSetting(settingKey);
auto settingInfo = curSetting.GetInfo();
mDoAud_seStartMenu(kSoundItemChange);
curSetting.SetCurrentOption(i);
text_elem->SetInnerRML(settingInfo->GetDescriptions().at(i));
SaveConfig();
});
}
});
}
SelectButton& rando_config_toggle(
Pane& leftPane, Pane& rightPane, std::string settingKey) {
auto& button = leftPane.add_child<BoolButton>(BoolButton::Props{
.key = settingKey,
.getValue = [settingKey] { return FindSetting(settingKey).GetCurrentOptionIndex() != 0; },
.setValue =
[settingKey](bool value) {
auto& setting = FindSetting(settingKey);
auto idx = setting.GetCurrentOptionIndex();
if (idx == value) {
return;
}
setting.SetCurrentOption(value);
SaveConfig();
},
});
auto& comp = leftPane.register_control(
button, rightPane, [settingKey](Pane& pane) {
pane.clear();
auto& setting = FindSetting(settingKey);
auto info = setting.GetInfo();
pane.add_rml(info->GetDescriptions()[setting.GetCurrentOptionIndex()]);
});
comp.listen(comp.root(), Rml::EventId::Click, [&rightPane, settingKey](Rml::Event&) {
rightPane.clear();
auto& setting = FindSetting(settingKey);
auto info = setting.GetInfo();
rightPane.add_rml(info->GetDescriptions()[setting.GetCurrentOptionIndex()]);
});
return button;
}
RandomizerWindow::RandomizerWindow() {
add_tab("Seed Management", [this](Rml::Element* content) {
auto& leftPane = add_child<Pane>(content, Pane::Type::Controlled);
auto& rightPane = add_child<Pane>(content, Pane::Type::Controlled);
config_bool_select(leftPane, rightPane, getSettings().game.randomizerEnabled, {
.key = "Randomizer Enabled",
.helpText = "Determines if a new Save will load as a regular save or randomized save. (Doesn't do anything currently)"
});
leftPane.add_button("Generate Seed").on_pressed([this] {
std::thread randoGenerationThread(StartSeedGeneration);
randoGenerationThread.detach();
m_showRandoGeneration = true;
});
});
add_tab("Seed Options", [this](Rml::Element* content) {
auto& leftPane = add_child<Pane>(content, Pane::Type::Controlled);
auto& rightPane = add_child<Pane>(content, Pane::Type::Uncontrolled);
leftPane.add_section("Logic Settings");
rando_config_group(leftPane, rightPane, "Logic Rules");
leftPane.add_section("Access Options");
rando_config_group(leftPane, rightPane, "Hyrule Barrier Requirements");
rando_config_group(leftPane, rightPane, "Palace of Twilight Requirements");
rando_config_group(leftPane, rightPane, "Faron Woods Logic");
leftPane.add_section("World (TODO)");
leftPane.add_section("Item Pool");
rando_config_toggle(leftPane, rightPane, "Golden Bugs");
rando_config_toggle(leftPane, rightPane, "Sky Characters");
rando_config_toggle(leftPane, rightPane, "Gifts From NPCs");
rando_config_toggle(leftPane, rightPane, "Shop Items");
rando_config_toggle(leftPane, rightPane, "Hidden Skills");
rando_config_toggle(leftPane, rightPane, "Hidden Rupees");
rando_config_toggle(leftPane, rightPane, "Freestanding Rupees");
rando_config_group(leftPane, rightPane, "Poe Souls");
rando_config_group(leftPane, rightPane, "Ilia Memory Quest");
rando_config_group(leftPane, rightPane, "Item Scarcity");
leftPane.add_section("Dungeon Items");
rando_config_group(leftPane, rightPane, "Small Keys");
rando_config_group(leftPane, rightPane, "Big Keys");
rando_config_group(leftPane, rightPane, "Maps and Compasses");
rando_config_group(leftPane, rightPane, "Hyrule Castle Big Key Requirements");
// TODO: figure out a way to add conditional options depending on selection above
rando_config_toggle(leftPane, rightPane, "Dungeon Rewards Can Be Anywhere");
rando_config_toggle(leftPane, rightPane, "No Small Keys on Bosses");
rando_config_toggle(leftPane, rightPane, "Unrequired Dungeons Are Barren");
leftPane.add_section("Timesavers");
rando_config_toggle(leftPane, rightPane, "Skip Prologue");
rando_config_toggle(leftPane, rightPane, "Faron Twilight Cleared");
rando_config_toggle(leftPane, rightPane, "Eldin Twilight Cleared");
rando_config_toggle(leftPane, rightPane, "Lanayru Twilight Cleared");
rando_config_toggle(leftPane, rightPane, "Skip Midna's Desparate Hour");
rando_config_toggle(leftPane, rightPane, "Skip Minor Cutscenes");
rando_config_toggle(leftPane, rightPane, "Skip Major Cutscenes");
rando_config_toggle(leftPane, rightPane, "Unlock Map Regions");
rando_config_toggle(leftPane, rightPane, "Open Door of Time");
rando_config_toggle(leftPane, rightPane, "Active Goron Mines Magnets");
rando_config_toggle(leftPane, rightPane, "Lower Hyrule Castle Chandelier");
rando_config_toggle(leftPane, rightPane, "Skip Bridge Donation");
leftPane.add_section("Additional Settings");
rando_config_group(leftPane, rightPane, "Starting Form");
rando_config_toggle(leftPane, rightPane, "Increase Wallet Capacity");
rando_config_toggle(leftPane, rightPane, "Shops Display The Replaced Item");
rando_config_toggle(leftPane, rightPane, "Bonks Do Damage");
rando_config_group(leftPane, rightPane, "Trap Item Frequency");
rando_config_toggle(leftPane, rightPane, "Starting Time of Day");
leftPane.add_section("Dungeon Entrance Settings");
rando_config_toggle(leftPane, rightPane, "Lakebed Does Not Require Water Bombs");
rando_config_toggle(leftPane, rightPane, "Arbiters Does Not Require Bulblin Camp");
rando_config_toggle(leftPane, rightPane, "Snowpeak Does Not Require Reekfish Scent");
rando_config_toggle(leftPane, rightPane, "Sacred Grove Does Not Require Skull Kid");
rando_config_toggle(leftPane, rightPane, "City Does Not Require Filled Skybook");
rando_config_group(leftPane, rightPane, "Goron Mines Entrance");
rando_config_group(leftPane, rightPane, "Temple of Time Sword Requirement");
rando_config_toggle(leftPane, rightPane, "Randomize Starting Spawn");
rando_config_group(leftPane, rightPane, "Randomize Dungeon Entrances");
rando_config_toggle(leftPane, rightPane, "Randomize Boss Entrances");
rando_config_toggle(leftPane, rightPane, "Randomize Grotto Entrances");
rando_config_toggle(leftPane, rightPane, "Randomize Cave Entrances");
rando_config_toggle(leftPane, rightPane, "Randomize Interior Entrances");
rando_config_toggle(leftPane, rightPane, "Randomize Overworld Entrances");
rando_config_toggle(leftPane, rightPane, "Decouple Double Door Entrances");
rando_config_toggle(leftPane, rightPane, "Decouple Entrances");
leftPane.add_section("Tricks");
rando_config_toggle(leftPane, rightPane, "Back Slice as Sword");
rando_config_toggle(leftPane, rightPane, "Ball and Chain Webs");
rando_config_toggle(leftPane, rightPane, "Logic Transform Anywhere");
});
}
}
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include "window.hpp"
namespace dusk::ui {
class RandomizerWindow : public Window {
public:
RandomizerWindow();
private:
bool m_showRandoGeneration = false;
};
}
+3
View File
@@ -757,6 +757,9 @@ int game_main(int argc, char* argv[]) {
dusk::audio::SetEnableReverb(dusk::getSettings().audio.enableReverb);
dusk::audio::EnableHrtf = dusk::getSettings().audio.enableHrtf;
// load rando generator configuration data
LoadRandomizerConfig();
// Run ImGui UI loop if Aurora couldn't initialize a backend
if (auroraInfo.backend == BACKEND_NULL) {
launchUILoop();