diff --git a/src/dusk/randomizer/generator/data/text/languages/english.yaml b/src/dusk/randomizer/generator/data/text/languages/english.yaml index 0524cf00a9..5b79f1ef99 100644 --- a/src/dusk/randomizer/generator/data/text/languages/english.yaml +++ b/src/dusk/randomizer/generator/data/text/languages/english.yaml @@ -2200,4 +2200,14 @@ Return to Spawn Dungeon No Choice Text: Standard: Text: |- <2 way choice 1>Nevermind - <2 way choice 2>Spawn \ No newline at end of file + <2 way choice 2>Spawn + +Midna Hints Required Dungeons Intro Zero Dungeons: + Standard: + Text: |- + There are 0 required dungeons. + +Midna Hints Required Dungeons Intro At Least One Dungeon: + Standard: + Text: |- + There are required dungeons: \ No newline at end of file diff --git a/src/dusk/randomizer/generator/data/text/languages/french.yaml b/src/dusk/randomizer/generator/data/text/languages/french.yaml index c1c908e484..ab2ec6357a 100644 --- a/src/dusk/randomizer/generator/data/text/languages/french.yaml +++ b/src/dusk/randomizer/generator/data/text/languages/french.yaml @@ -2200,4 +2200,14 @@ Return to Spawn Dungeon No Choice Text: Standard: Text: |- <2 way choice 1>Nevermind - <2 way choice 2>Spawn \ No newline at end of file + <2 way choice 2>Spawn + +Midna Hints Required Dungeons Intro Zero Dungeons: + Standard: + Text: |- + There are 0 required dungeons. + +Midna Hints Required Dungeons Intro At Least One Dungeon: + Standard: + Text: |- + There are required dungeons: \ No newline at end of file diff --git a/src/dusk/randomizer/generator/data/text/languages/german.yaml b/src/dusk/randomizer/generator/data/text/languages/german.yaml index 579ee74d1f..fdfc270eee 100644 --- a/src/dusk/randomizer/generator/data/text/languages/german.yaml +++ b/src/dusk/randomizer/generator/data/text/languages/german.yaml @@ -2200,4 +2200,14 @@ Return to Spawn Dungeon No Choice Text: Standard: Text: |- <2 way choice 1>Nevermind - <2 way choice 2>Spawn \ No newline at end of file + <2 way choice 2>Spawn + +Midna Hints Required Dungeons Intro Zero Dungeons: + Standard: + Text: |- + There are 0 required dungeons. + +Midna Hints Required Dungeons Intro At Least One Dungeon: + Standard: + Text: |- + There are required dungeons: \ No newline at end of file diff --git a/src/dusk/randomizer/generator/data/text/languages/italian.yaml b/src/dusk/randomizer/generator/data/text/languages/italian.yaml index 8fbe283883..5b247a1011 100644 --- a/src/dusk/randomizer/generator/data/text/languages/italian.yaml +++ b/src/dusk/randomizer/generator/data/text/languages/italian.yaml @@ -2200,4 +2200,14 @@ Return to Spawn Dungeon No Choice Text: Standard: Text: |- <2 way choice 1>Nevermind - <2 way choice 2>Spawn \ No newline at end of file + <2 way choice 2>Spawn + +Midna Hints Required Dungeons Intro Zero Dungeons: + Standard: + Text: |- + There are 0 required dungeons. + +Midna Hints Required Dungeons Intro At Least One Dungeon: + Standard: + Text: |- + There are required dungeons: \ No newline at end of file diff --git a/src/dusk/randomizer/generator/data/text/languages/spanish.yaml b/src/dusk/randomizer/generator/data/text/languages/spanish.yaml index 9629f70a08..c8384efc72 100644 --- a/src/dusk/randomizer/generator/data/text/languages/spanish.yaml +++ b/src/dusk/randomizer/generator/data/text/languages/spanish.yaml @@ -2200,4 +2200,14 @@ Return to Spawn Dungeon No Choice Text: Standard: Text: |- <2 way choice 1>Nevermind - <2 way choice 2>Spawn \ No newline at end of file + <2 way choice 2>Spawn + +Midna Hints Required Dungeons Intro Zero Dungeons: + Standard: + Text: |- + There are 0 required dungeons. + +Midna Hints Required Dungeons Intro At Least One Dungeon: + Standard: + Text: |- + There are required dungeons: \ No newline at end of file diff --git a/src/dusk/randomizer/generator/logic/hints.cpp b/src/dusk/randomizer/generator/logic/hints.cpp index 1b6c011a9a..ca75657cb2 100644 --- a/src/dusk/randomizer/generator/logic/hints.cpp +++ b/src/dusk/randomizer/generator/logic/hints.cpp @@ -3,27 +3,31 @@ #include "dusk/randomizer/generator/utility/text.hpp" #include "world.hpp" +#include + namespace randomizer::logic::hints { + static const std::list> dungeonColors = { + {"Forest Temple", ""}, + {"Goron Mines", ""}, + {"Lakebed Temple", ""}, + {"Arbiters Grounds", ""}, + {"Snowpeak Ruins", ""}, + {"Temple of Time", ""}, + {"City in the Sky", ""}, + {"Palace of Twilight", ""}, + // {"Hyrule Castle", ""} + }; + // Tell the player which dungeons are required on the sign in front of Link's House static void GenerateRequiredDungeonsHint(world::WorldPool& worlds) { - static const std::unordered_map dungeonColors = { - {"Forest Temple", ""}, - {"Goron Mines", ""}, - {"Lakebed Temple", ""}, - {"Arbiters Grounds", ""}, - {"Snowpeak Ruins", ""}, - {"Temple of Time", ""}, - {"City in the Sky", ""}, - {"Palace of Twilight", ""}, - // {"Hyrule Castle", ""} - }; - for (const auto& world : worlds) { auto& requiredDungeonText = world->AddNewText("Links House Sign"); - for (const auto& [dungeonName, dungeon] : world->GetDungeonTable()) { + // Use dungeonColors to loop through in base game dungeon order + for (const auto& [dungeonName, color] : dungeonColors) { + auto dungeon = world->GetDungeon(dungeonName); if (dungeon->IsRequired()) { - requiredDungeonText += dungeonColors.at(dungeonName) + getTextObject(dungeonName) + "\n"; + requiredDungeonText += color + getTextObject(dungeonName) + "\n"; } } @@ -82,8 +86,51 @@ namespace randomizer::logic::hints { } } + void GenerateMidnaHintsText(world::WorldPool& worlds) { + for (const auto& world : worlds) { + auto& midnaHintText = world->AddNewText("Custom Midna Call Hints Text"); + + // Put required dungeons on Midna. + // First loop through to get required number + int numRequiredDungeons = 0; + for (const auto& dungeon : world->GetDungeonTable() | std::views::values) { + if (dungeon->IsRequired()) { + ++numRequiredDungeons; + } + } + + // Set the text for the number of required dungeons + if (numRequiredDungeons > 0) { + midnaHintText += getTextObject("Midna Hints Required Dungeons Intro At Least One Dungeon"); + midnaHintText.Replace("", std::to_string(numRequiredDungeons)); + // Add newlines to begin listing dungeons on the next textbox + midnaHintText += "\n\n\n\n"; + + // Then loop through again to add the dungeon names. + // Use dungeonColors to loop through in base game dungeon order + int displayedRequiredDungeons = 0; + for (const auto& [dungeonName, color] : dungeonColors) { + auto dungeon = world->GetDungeon(dungeonName); + if (dungeon->IsRequired()) { + ++displayedRequiredDungeons; + midnaHintText += color + getTextObject(dungeonName) + ""; + // Add newline after every dungeon except the last one + if (displayedRequiredDungeons < numRequiredDungeons) { + midnaHintText += "\n"; + } + } + } + } else { + midnaHintText += getTextObject("Midna Hints Required Dungeons Intro Zero Dungeons"); + } + + midnaHintText.BreakLines(Text::MAX_LINE_WIDTH_NORMAL_TEXTBOX); + } + } + void GenerateAllHints(world::WorldPool& worlds) { GenerateRequiredDungeonsHint(worlds); GenerateItemTextReplacements(worlds); + GenerateMidnaHintsText(worlds); } } diff --git a/src/dusk/randomizer/generator/logic/world.cpp b/src/dusk/randomizer/generator/logic/world.cpp index 73a795085c..9b97a4d3b3 100644 --- a/src/dusk/randomizer/generator/logic/world.cpp +++ b/src/dusk/randomizer/generator/logic/world.cpp @@ -872,8 +872,17 @@ namespace randomizer::logic::world // For no logic, we're purely going to base whether the dungeon is required on the Hyrule Castle // Barrier requirements and Hyrule Castle Big Key chest requirements bool World::IsNoLogicRequiredDungeon(const std::unique_ptr& dungeon) { - auto barrierRequirements = this->Setting("Hyrule Barrier Requirements"); - auto bigKeyRequirements = this->Setting("Hyrule Castle Big Key Requirements"); + auto& barrierRequirements = this->Setting("Hyrule Barrier Requirements"); + auto& bigKeyRequirements = this->Setting("Hyrule Castle Big Key Requirements"); + auto barrierDungeonCount = this->Setting("Hyrule Barrier Dungeons").GetCurrentOptionAsNumber(); + auto bigkeyDungeonCount = this->Setting("Hyrule Castle Big Key Dungeons").GetCurrentOptionAsNumber(); + + // If all dungeons are required, then always return true + if ((barrierRequirements == "Dungeons" && barrierDungeonCount == 8) || + (bigKeyRequirements == "Dungeons" && bigkeyDungeonCount == 8)) + { + return true; + } bool dungeonHasFusedShadow = std::ranges::any_of(dungeon->GetLocations(), [](const auto& location) { return location->GetCurrentItem()->GetName() == "Progressive Fused Shadow"; diff --git a/src/dusk/randomizer/generator/utility/text.cpp b/src/dusk/randomizer/generator/utility/text.cpp index cc89856758..ced4d2d09f 100644 --- a/src/dusk/randomizer/generator/utility/text.cpp +++ b/src/dusk/randomizer/generator/utility/text.cpp @@ -63,7 +63,7 @@ namespace randomizer { } } - void Text::BreakLines(int maxLineWidth /*= MAX_LINE_WIDTH*/) { + void Text::BreakLines(int maxLineWidth /*= MAX_LINE_WIDTH_ITEM_TEXTBOX*/) { for (auto& text : mText) { breakLines(text, maxLineWidth); } diff --git a/src/dusk/randomizer/generator/utility/text.hpp b/src/dusk/randomizer/generator/utility/text.hpp index 3bc386e5d4..72774e10c6 100644 --- a/src/dusk/randomizer/generator/utility/text.hpp +++ b/src/dusk/randomizer/generator/utility/text.hpp @@ -57,7 +57,8 @@ namespace randomizer { PLURALITY_MAX, }; - static constexpr size_t MAX_LINE_WIDTH = 441; + static constexpr size_t MAX_LINE_WIDTH_ITEM_TEXTBOX = 441; + static constexpr size_t MAX_LINE_WIDTH_NORMAL_TEXTBOX = 750; Text() = default; explicit Text(const std::string& str); @@ -74,7 +75,7 @@ namespace randomizer { */ void Replace(const std::string& oldStr, const Text& replacementText, int count = 1); void Replace(const std::string& oldStr, const std::string& replacementText, int count = 1); - void BreakLines(int maxLineWidth = MAX_LINE_WIDTH); + void BreakLines(int maxLineWidth = MAX_LINE_WIDTH_ITEM_TEXTBOX); void Capitalize(); bool Empty() const; Text& operator+=(const Text& rhs);