From 75d86ab29618b7455b7362376d472a5cddd4dff9 Mon Sep 17 00:00:00 2001 From: gymnast86 Date: Sat, 23 May 2026 11:44:05 -0700 Subject: [PATCH] fix ilia quest logic setting logic --- .../data/world/overworld/Eldin Province.yaml | 2 +- .../world/overworld/Lanayru Province.yaml | 2 +- .../randomizer/generator/logic/item_pool.cpp | 28 ++++++++---- src/dusk/randomizer/generator/logic/world.cpp | 43 ++++++++++++++++--- src/dusk/randomizer/generator/logic/world.hpp | 9 ++++ .../randomizer/generator/seedgen/settings.cpp | 22 ++++++++++ .../randomizer/generator/seedgen/settings.hpp | 2 + 7 files changed, 92 insertions(+), 16 deletions(-) diff --git a/src/dusk/randomizer/generator/data/world/overworld/Eldin Province.yaml b/src/dusk/randomizer/generator/data/world/overworld/Eldin Province.yaml index 69fb939acb..236d923f38 100644 --- a/src/dusk/randomizer/generator/data/world/overworld/Eldin Province.yaml +++ b/src/dusk/randomizer/generator/data/world/overworld/Eldin Province.yaml @@ -576,7 +576,7 @@ North Eldin Field Hint Sign: Nothing Exits: Eldin Field Grotto Platform: Spinner - Eldin Field Outside Hidden Village: "'Can_Show_Ilia_Wooden_Statue'" + Eldin Field Outside Hidden Village: Ilia_Memory_Quest >= Charm or 'Can_Show_Ilia_Wooden_Statue' Lanayru Field: Nothing Eldin Field North of Bridge: Nothing diff --git a/src/dusk/randomizer/generator/data/world/overworld/Lanayru Province.yaml b/src/dusk/randomizer/generator/data/world/overworld/Lanayru Province.yaml index 1d0c0c206a..69e1a355e9 100644 --- a/src/dusk/randomizer/generator/data/world/overworld/Lanayru Province.yaml +++ b/src/dusk/randomizer/generator/data/world/overworld/Lanayru Province.yaml @@ -281,7 +281,7 @@ - Name: Castle Town Doctors Office Entrance Can Transform: If Transform Anywhere Exits: - Castle Town Doctors Office Lower: Invoice and Can_Talk_to_Humans + Castle Town Doctors Office Lower: Ilia_Memory_Quest >= Statue or (Invoice and Can_Talk_to_Humans) Castle Town Doctors Office West Door Interior: Nothing Castle Town Doctors Office East Door Interior: Nothing diff --git a/src/dusk/randomizer/generator/logic/item_pool.cpp b/src/dusk/randomizer/generator/logic/item_pool.cpp index aa0243113d..664ddcf4da 100644 --- a/src/dusk/randomizer/generator/logic/item_pool.cpp +++ b/src/dusk/randomizer/generator/logic/item_pool.cpp @@ -264,33 +264,45 @@ namespace randomizer::logic::item_pool // Remove the Tears for Twilight sections if they're cleared if (world->Setting("Faron Twilight Cleared") == "On") { - itemPool.at("Faron Twilight Tear") = 0; + itemPool.erase("Faron Twilight Tear"); } if (world->Setting("Eldin Twilight Cleared") == "On") { - itemPool.at("Eldin Twilight Tear") = 0; + itemPool.erase("Eldin Twilight Tear"); } if (world->Setting("Lanayru Twilight Cleared") == "On") { - itemPool.at("Lanayru Twilight Tear") = 0; + itemPool.erase("Lanayru Twilight Tear"); + } + + // Remove items depending on Ilia Memory Quest setting + const auto& iliaQuest = world->Setting("Ilia Memory Quest"); + if (iliaQuest > "Letter") { + itemPool.erase("Renados Letter"); + } + if (iliaQuest > "Invoice") { + itemPool.erase("Invoice"); + } + if (iliaQuest > "Statue") { + itemPool.erase("Wooden Statue"); } // Remove the North Faron Woods Gate Key if we're skipping prologue if (world->Setting("Skip Prologue") == "On") { - itemPool.at("North Faron Woods Gate Key") = 0; + itemPool.erase("North Faron Woods Gate Key"); } // Remove the bulblin camp key if we're skipping bulblin camp if (world->Setting("Arbiters Does Not Require Bulblin Camp") == "On") { - itemPool.at("Gerudo Desert Bulblin Camp Key") = 0; + itemPool.erase("Gerudo Desert Bulblin Camp Key"); } // Remove sky book characters if we're starting with the sky canon open if (world->Setting("City Does Not Require Filled Skybook") == "On") { - itemPool.at("Progressive Sky Book") = 0; + itemPool.erase("Progressive Sky Book"); } // Remove Small Keys if we're playing without them @@ -312,7 +324,7 @@ namespace randomizer::logic::item_pool }; for (const auto& key : smallKeys) { - itemPool.at(key) = 0; + itemPool.erase(key); } } @@ -337,7 +349,7 @@ namespace randomizer::logic::item_pool for (const auto& key : bigKeys) { - itemPool.at(key) = 0; + itemPool.erase(key); } } diff --git a/src/dusk/randomizer/generator/logic/world.cpp b/src/dusk/randomizer/generator/logic/world.cpp index 6fe1aa574e..9c578c617d 100644 --- a/src/dusk/randomizer/generator/logic/world.cpp +++ b/src/dusk/randomizer/generator/logic/world.cpp @@ -172,13 +172,9 @@ namespace randomizer::logic::world // Optional Fields auto originalItemName = locationNode["Original Item"].as("Nothing"); - // If the original item is a twilight tear for a twilight section that's been cleared, then don't include the - // location - if ((originalItemName == "Faron Twilight Tear" && this->Setting("Faron Twilight Cleared") == "On") || - (originalItemName == "Eldin Twilight Tear" && this->Setting("Eldin Twilight Cleared") == "On") || - (originalItemName == "Lanayru Twilight Tear" && this->Setting("Lanayru Twilight Cleared") == "On")) + // If this location should be removed based on settings, don't insert it into the location table + if (ShouldRemoveLocation(name, originalItemName)) { - LOG_TO_DEBUG("Removing " + name + " because it's corresponding twilight is already cleared"); this->_intentionallyRemovedLocations.insert(name); continue; } @@ -506,6 +502,41 @@ namespace randomizer::logic::world } } + bool World::ShouldRemoveLocation(const std::string& locationName, const std::string& originalItemName) + { + // Twilight Tears + if (originalItemName == "Faron Twilight Tear" && this->Setting("Faron Twilight Cleared") == "On") + { + LOG_TO_DEBUG("Removing " + locationName + " because Faron Twilight is cleared."); + return true; + } + + if (originalItemName == "Eldin Twilight Tear" && this->Setting("Eldin Twilight Cleared") == "On") + { + LOG_TO_DEBUG("Removing " + locationName + " because Eldin Twilight is cleared."); + return true; + } + + if (originalItemName == "Lanayru Twilight Tear" && this->Setting("Lanayru Twilight Cleared") == "On") + { + LOG_TO_DEBUG("Removing " + locationName + " because Lanayru Twilight is cleared."); + return true; + } + + // Ilia Memory Quest + const auto& iliaQuest = this->Setting("Ilia Memory Quest"); + if ((iliaQuest >= "Letter" && locationName == "Renados Letter") || + (iliaQuest >= "Invoice" && locationName == "Telma Invoice") || + (iliaQuest >= "Statue" && locationName == "Wooden Statue") || + (iliaQuest >= "Charm" && locationName == "Ilia Charm")) + { + LOG_TO_DEBUG("Removing " + locationName + " because Ilia Memory Quest is " + iliaQuest.GetCurrentOption() + "."); + return true; + } + + return false; + } + void World::PerformPreEntranceShuffleTasks() { this->PlaceVanillaItems(); diff --git a/src/dusk/randomizer/generator/logic/world.hpp b/src/dusk/randomizer/generator/logic/world.hpp index ab43211e10..e3a61d4e3f 100644 --- a/src/dusk/randomizer/generator/logic/world.hpp +++ b/src/dusk/randomizer/generator/logic/world.hpp @@ -64,6 +64,15 @@ namespace randomizer::logic::world */ void GenerateItemPools(); + /** + * @brief Decides if a location should be removed depending on settings. + * @param locationName The name of the location + * @param originalItemName The name of the original item at the location + * + * @return true if the location should be removed. False otherwise + */ + bool ShouldRemoveLocation(const std::string& locationName, const std::string& originalItemName); + /** * @brief Perform all tasks which must be complete before shuffling entrances. */ diff --git a/src/dusk/randomizer/generator/seedgen/settings.cpp b/src/dusk/randomizer/generator/seedgen/settings.cpp index ba2414277d..13c282caf7 100644 --- a/src/dusk/randomizer/generator/seedgen/settings.cpp +++ b/src/dusk/randomizer/generator/seedgen/settings.cpp @@ -179,6 +179,28 @@ namespace randomizer::seedgen::settings return this->_currentOptionIndex <= optionNameIndex; } + bool Setting::operator>(const char* optionName) const + { + int optionNameIndex = this->GetInfo()->GetIndexOfOption(optionName); + if (optionNameIndex == -1) + { + throw std::runtime_error(std::string("\"") + optionName + "\" is not a valid option for setting \"" + + this->GetInfo()->GetName() + "\""); + } + return this->_currentOptionIndex > optionNameIndex; + } + + bool Setting::operator<(const char* optionName) const + { + int optionNameIndex = this->GetInfo()->GetIndexOfOption(optionName); + if (optionNameIndex == -1) + { + throw std::runtime_error(std::string("\"") + optionName + "\" is not a valid option for setting \"" + + this->GetInfo()->GetName() + "\""); + } + return this->_currentOptionIndex < optionNameIndex; + } + void Settings::InsertSetting(const std::string& settingName, Setting setting) { this->_map.emplace(settingName, setting); diff --git a/src/dusk/randomizer/generator/seedgen/settings.hpp b/src/dusk/randomizer/generator/seedgen/settings.hpp index 555d54edc8..c1f6cc4ef2 100644 --- a/src/dusk/randomizer/generator/seedgen/settings.hpp +++ b/src/dusk/randomizer/generator/seedgen/settings.hpp @@ -149,6 +149,8 @@ namespace randomizer::seedgen::settings bool operator!=(const char* optionName) const; bool operator>=(const char* optionName) const; bool operator<=(const char* optionName) const; + bool operator>(const char* optionName) const; + bool operator<(const char* optionName) const; template bool IsAnyOf(Types... optionNames)