From af78352b99c6a22d9bf6f6d3be4d1268338defdf Mon Sep 17 00:00:00 2001 From: gymnast86 Date: Sun, 25 Jan 2026 21:16:40 -0800 Subject: [PATCH] fix hint messages getting overwritten --- logic/Hints.cpp | 163 +++++++++++++++++++++++------------------- logic/Hints.hpp | 2 + logic/SpoilerLog.cpp | 36 +++++----- logic/World.hpp | 11 +-- text_replacements.cpp | 10 +-- tweaks.cpp | 60 ++++++++-------- 6 files changed, 151 insertions(+), 131 deletions(-) diff --git a/logic/Hints.cpp b/logic/Hints.cpp index 2d08f02c..861d735a 100644 --- a/logic/Hints.cpp +++ b/logic/Hints.cpp @@ -249,7 +249,7 @@ static HintError calculatePossibleBarrenRegions(WorldPool& worlds) return HintError::NONE; } -static HintError generatePathHintMessage(Location* location, Location* goalLocation) +static HintError generatePathHintMessage(Location* location, Location* goalLocation, std::list& hints) { std::u16string englishRegionText = u""; std::u16string spanishRegionText = u""; @@ -294,14 +294,17 @@ static HintError generatePathHintMessage(Location* location, Location* goalLocat std::u16string spanishPlurality = (totalRegions == 1 && spanishRegionText.find(u"Ilas") == std::string::npos) ? u" dirige"s : u" dirigen"s; std::u16string frenchPlurality = (totalRegions == 1 && englishRegionText.find(u"Angular Isles") == std::string::npos && englishRegionText.find(u"Forbidden Woods") == std::string::npos) ? u" est"s : u" sont"s; - location->hint.text["English"] = HINT_PREFIX_ENGLISH + englishRegionText + englishPlurality + u" on the path to "s + TEXT_COLOR_RED + Utility::Str::toUTF16(goalLocation->goalNames["English"]) + TEXT_COLOR_DEFAULT + u"."s; - location->hint.text["Spanish"] = HINT_PREFIX_SPANISH + spanishRegionText + spanishPlurality + u" hacia el camino de "s + TEXT_COLOR_RED + Utility::Str::toUTF16(goalLocation->goalNames["Spanish"]) + TEXT_COLOR_DEFAULT + u"."s; - location->hint.text["French"] = HINT_PREFIX_FRENCH + frenchRegionText + frenchPlurality + u" sur le chemin de "s + TEXT_COLOR_RED + Utility::Str::toUTF16(goalLocation->goalNames["French"]) + TEXT_COLOR_DEFAULT + u"."s; - location->hint.type = HintType::PATH; + Hint hint{}; + hint.text["English"] = HINT_PREFIX_ENGLISH + englishRegionText + englishPlurality + u" on the path to "s + TEXT_COLOR_RED + Utility::Str::toUTF16(goalLocation->goalNames["English"]) + TEXT_COLOR_DEFAULT + u"."s; + hint.text["Spanish"] = HINT_PREFIX_SPANISH + spanishRegionText + spanishPlurality + u" hacia el camino de "s + TEXT_COLOR_RED + Utility::Str::toUTF16(goalLocation->goalNames["Spanish"]) + TEXT_COLOR_DEFAULT + u"."s; + hint.text["French"] = HINT_PREFIX_FRENCH + frenchRegionText + frenchPlurality + u" sur le chemin de "s + TEXT_COLOR_RED + Utility::Str::toUTF16(goalLocation->goalNames["French"]) + TEXT_COLOR_DEFAULT + u"."s; + hint.type = HintType::PATH; + hint.location = location; + hints.emplace_back(std::move(hint)); return HintError::NONE; } -static HintError generatePathHintLocations(World& world, std::vector& pathHintLocations) +static HintError generatePathHintLocations(World& world, std::list& hints) { // Shuffle each pool of path locations so that their orders are random std::vector goalLocations = {}; @@ -359,26 +362,26 @@ static HintError generatePathHintLocations(World& world, std::vector& i--; continue; } + LOG_AND_RETURN_IF_ERR(generatePathHintMessage(hintLocation, goalLocation, hints)); hintLocation->hasBeenHinted = true; - pathHintLocations.push_back(hintLocation); LOG_TO_DEBUG("Chose \"" + hintLocation->getName() + "\" as path hint for " + goalLocation->getName()); - LOG_AND_RETURN_IF_ERR(generatePathHintMessage(hintLocation, goalLocation)); } return HintError::NONE; } -static HintError generateBarrenHintMessage(Location* location, const std::string& barrenRegion) +static HintError generateBarrenHintMessage(const std::string& barrenRegion, std::list& hints, World& world) { - auto world = location->world; - location->hint.text["English"] = HINT_PREFIX_ENGLISH u"visiting " + world->getUTF16HintRegion(barrenRegion, "English", Text::Type::PRETTY, Text::Color::BLUE) + u" is a foolish choice."s; - location->hint.text["Spanish"] = HINT_PREFIX_SPANISH u"visitar " + world->getUTF16HintRegion(barrenRegion, "Spanish", Text::Type::PRETTY, Text::Color::BLUE) + u" es una idea imprudente."s; - location->hint.text["French"] = HINT_PREFIX_FRENCH u"visiter " + world->getUTF16HintRegion(barrenRegion, "French", Text::Type::PRETTY, Text::Color::BLUE) + u" est un choix imprudent."s; - location->hint.type = HintType::BARREN; + Hint hint{}; + hint.text["English"] = HINT_PREFIX_ENGLISH u"visiting " + world.getUTF16HintRegion(barrenRegion, "English", Text::Type::PRETTY, Text::Color::BLUE) + u" is a foolish choice."s; + hint.text["Spanish"] = HINT_PREFIX_SPANISH u"visitar " + world.getUTF16HintRegion(barrenRegion, "Spanish", Text::Type::PRETTY, Text::Color::BLUE) + u" es una idea imprudente."s; + hint.text["French"] = HINT_PREFIX_FRENCH u"visiter " + world.getUTF16HintRegion(barrenRegion, "French", Text::Type::PRETTY, Text::Color::BLUE) + u" est un choix imprudent."s; + hint.type = HintType::BARREN; + hints.emplace_back(std::move(hint)); return HintError::NONE; } -static HintError generateBarrenHintLocations(World& world, std::vector& barrenHintLocations) +static HintError generateBarrenHintLocations(World& world, std::list& hints) { std::vector barrenPool = {}; std::vector barrenDistributions = {}; @@ -406,9 +409,9 @@ static HintError generateBarrenHintLocations(World& world, std::vectorhasBeenHinted = true; - LOG_AND_RETURN_IF_ERR(generateBarrenHintMessage(location, barrenRegion)); } - barrenHintLocations.push_back(*world.barrenRegions[barrenRegion].begin()); + LOG_AND_RETURN_IF_ERR(generateBarrenHintMessage(barrenRegion, hints, world)); + hints.back().location = *world.barrenRegions[barrenRegion].begin(); LOG_TO_DEBUG("Chose \"" + barrenRegion + "\" as a hinted barren region"); // Erase any potential barren regions if any of their locations have already @@ -435,7 +438,7 @@ static HintError generateBarrenHintLocations(World& world, std::vector& hints) { std::u16string englishRegionText = u""; std::u16string spanishRegionText = u""; @@ -500,14 +503,17 @@ static HintError generateItemHintMessage(Location* location) // Angular Isles and Forbidden Woods should use the plural tense in French even if they're a single area being referred to std::u16string frenchPlurality = (totalRegions == 1 && englishRegionText.find(u"Angular Isles") == std::string::npos && englishRegionText.find(u"Forbidden Woods") == std::string::npos) ? u" détiendrait "s : u" détiendraient "s; - location->hint.text["English"] = HINT_PREFIX_ENGLISH + englishHintedItem + englishItemImportance + u" can be found at "s + englishRegionText + u"."s; - location->hint.text["Spanish"] = HINT_PREFIX_SPANISH + spanishHintedItem + spanishItemImportance + u" se encuentra en "s + spanishRegionText + u"."s; - location->hint.text["French"] = HINT_PREFIX_FRENCH + frenchRegionText + frenchPlurality + frenchHintedItem + frenchItemImportance + u"."s; - location->hint.type = HintType::ITEM; + Hint hint{}; + hint.text["English"] = HINT_PREFIX_ENGLISH + englishHintedItem + englishItemImportance + u" can be found at "s + englishRegionText + u"."s; + hint.text["Spanish"] = HINT_PREFIX_SPANISH + spanishHintedItem + spanishItemImportance + u" se encuentra en "s + spanishRegionText + u"."s; + hint.text["French"] = HINT_PREFIX_FRENCH + frenchRegionText + frenchPlurality + frenchHintedItem + frenchItemImportance + u"."s; + hint.type = HintType::ITEM; + hint.location = location; + hints.emplace_back(std::move(hint)); return HintError::NONE; } -static HintError generateItemHintLocations(World& world, std::vector& itemHintLocations) +static HintError generateItemHintLocations(World& world, std::list& hints) { auto& settings = world.getSettings(); // First, make a vector of possible item hint locations @@ -536,34 +542,37 @@ static HintError generateItemHintLocations(World& world, std::vector& break; } auto hintLocation = popRandomElement(possibleItemHintLocations); + LOG_AND_RETURN_IF_ERR(generateItemHintMessage(hintLocation, hints)); hintLocation->hasBeenHinted = true; - itemHintLocations.push_back(hintLocation); - LOG_AND_RETURN_IF_ERR(generateItemHintMessage(hintLocation)); LOG_TO_DEBUG("Chose \"" + hintLocation->getName() + "\" as item hint location"); } // Choose one more potential item hint to give to the big octo great fairy. // This hint will always be chosen regardless of settings // Don't let the great fairy hint at itself + Location* octoFairyHintLocation = nullptr; filterAndEraseFromPool(possibleItemHintLocations, [](const Location* location){ return location->hintRegions.size() != 1 || location->getName() == "Two Eye Reef - Big Octo Great Fairy"; }); if (!possibleItemHintLocations.empty()) { - world.bigOctoFairyHintLocation = popRandomElement(possibleItemHintLocations); - LOG_AND_RETURN_IF_ERR(generateItemHintMessage(world.bigOctoFairyHintLocation)); - LOG_TO_DEBUG("Chose \"" + world.bigOctoFairyHintLocation->getName() + "\" as item hint location for big octo fairy") + octoFairyHintLocation = popRandomElement(possibleItemHintLocations); + LOG_TO_DEBUG("Chose \"" + octoFairyHintLocation->getName() + "\" as item hint location for big octo fairy") } else { // This item may not be helpful but we need something to fill the text // And it mirrors her vanilla hint at the Fairy Queen in M&C - world.bigOctoFairyHintLocation = world.locationTable["Mother & Child Isles - Inside Mother Isle"].get(); + octoFairyHintLocation = world.locationTable["Mother & Child Isles - Inside Mother Isle"].get(); LOG_TO_DEBUG("No possible item hints for big octo fairy. Falling back to Mother & Child Isles - Inside Mother Isle") } + std::list bigOctoFairyHints{}; + LOG_AND_RETURN_IF_ERR(generateItemHintMessage(octoFairyHintLocation, bigOctoFairyHints)); + world.bigOctoFairyHint = bigOctoFairyHints.back(); + return HintError::NONE; } -static HintError generateLocationHintMessage(Location* location) +static HintError generateLocationHintMessage(Location* location, std::list& hints) { auto& item = location->currentItem; @@ -581,14 +590,17 @@ static HintError generateLocationHintMessage(Location* location) auto spanishItemImportance = location->generateImportanceText("Spanish"); auto frenchItemImportance = location->generateImportanceText("French"); - location->hint.text["English"] = HINT_PREFIX_ENGLISH + TEXT_COLOR_RED + englishLocation + TEXT_COLOR_DEFAULT + u" rewards " + englishHintedItem + englishItemImportance + u"."s; - location->hint.text["Spanish"] = HINT_PREFIX_SPANISH + TEXT_COLOR_RED + spanishLocation + TEXT_COLOR_DEFAULT + u" otorgará " + spanishHintedItem + spanishItemImportance + u"."s; - location->hint.text["French"] = HINT_PREFIX_FRENCH + TEXT_COLOR_RED + frenchLocation + TEXT_COLOR_DEFAULT + u" aurait pour récompense " + frenchHintedItem + frenchItemImportance + u"."s; - location->hint.type = HintType::LOCATION; + Hint hint{}; + hint.text["English"] = HINT_PREFIX_ENGLISH + TEXT_COLOR_RED + englishLocation + TEXT_COLOR_DEFAULT + u" rewards " + englishHintedItem + englishItemImportance + u"."s; + hint.text["Spanish"] = HINT_PREFIX_SPANISH + TEXT_COLOR_RED + spanishLocation + TEXT_COLOR_DEFAULT + u" otorgará " + spanishHintedItem + spanishItemImportance + u"."s; + hint.text["French"] = HINT_PREFIX_FRENCH + TEXT_COLOR_RED + frenchLocation + TEXT_COLOR_DEFAULT + u" aurait pour récompense " + frenchHintedItem + frenchItemImportance + u"."s; + hint.type = HintType::LOCATION; + hint.location = location; + hints.emplace_back(std::move(hint)); return HintError::NONE; } -static HintError generateAlwaysHints(World& world, std::vector& alwaysHintLocations) +static HintError generateAlwaysHints(World& world, std::list& hints) { // Return early if we're not specifically generating always hints, or if we don't have any location hints if (!world.getSettings().use_always_hints || world.getSettings().location_hints == 0) @@ -621,15 +633,15 @@ static HintError generateAlwaysHints(World& world, std::vector& alway { break; } - alwaysHintLocations.push_back(hintLocation); - LOG_AND_RETURN_IF_ERR(generateLocationHintMessage(hintLocation)); + LOG_AND_RETURN_IF_ERR(generateLocationHintMessage(hintLocation, hints)); + hintLocation->hasBeenHinted = true; LOG_TO_DEBUG("Chose \"" + hintLocation->getName() + "\" as always hint location"); } return HintError::NONE; } -static HintError generateLocationHintLocations(World& world, std::vector& locationHintLocations, uint8_t numLocationHints) +static HintError generateLocationHintLocations(World& world, std::list& hints, uint8_t numLocationHints) { std::vector sometimesLocations = {}; @@ -656,15 +668,15 @@ static HintError generateLocationHintLocations(World& world, std::vectorhasBeenHinted = true; LOG_TO_DEBUG("Chose \"" + hintLocation->getName() + "\" as location hint location"); } return HintError::NONE; } -static HintError assignHoHoHints(World& world, WorldPool& worlds, std::list& locations) +static HintError assignHoHoHints(World& world, WorldPool& worlds, std::list& hints) { // If ho ho is hinting triforces, make those hints now if (world.getSettings().ho_ho_triforce_hints) @@ -673,25 +685,24 @@ static HintError assignHoHoHints(World& world, WorldPool& worlds, std::listcurrentItem.isTriforceShard() && !location->isRaceModeLocation) { - locations.push_back(location); - LOG_AND_RETURN_IF_ERR(generateItemHintMessage(location)); + LOG_AND_RETURN_IF_ERR(generateItemHintMessage(location, hints)); } } } // Shuffle the hints - std::vector locationsVector (locations.begin(), locations.end()); - shufflePool(locationsVector); + std::vector hintsVector (hints.begin(), hints.end()); + shufflePool(hintsVector); // Duplicate hints until we have a multiple of 10 so that each Ho Ho gets the same // number of hints size_t counter = 0; - while (locationsVector.size() % 10 != 0) + while (hintsVector.size() % 10 != 0) { - locationsVector.push_back(locationsVector[counter++]); + hintsVector.push_back(hintsVector[counter++]); } - locations.assign(locationsVector.begin(), locationsVector.end()); - size_t hintsPerHoHo = locations.size() / 10; + hints.assign(hintsVector.begin(), hintsVector.end()); + size_t hintsPerHoHo = hints.size() / 10; auto hohoLocations = world.getLocations(); filterAndEraseFromPool(hohoLocations, [](const Location* location){ return !location->categories.contains(LocationCategory::HoHoHint); }); @@ -704,8 +715,9 @@ static HintError assignHoHoHints(World& world, WorldPool& worlds, std::listcurrentItem; @@ -719,7 +731,9 @@ static HintError assignHoHoHints(World& world, WorldPool& worlds, std::listcurrentItem = itemAtLocation; // Erase Ho Ho locations which already have the desired number of hints - filterAndEraseFromPool(accessibleHoHoLocations, [&](Location* hoho){return world.hohoHints[hoho].size() >= hintsPerHoHo || world.hohoHints[hoho].contains(location);}); + filterAndEraseFromPool(accessibleHoHoLocations, [&](Location* hoho){ + return world.hohoHints[hoho].size() >= hintsPerHoHo || std::ranges::any_of(world.hohoHints[hoho], [&](const Hint& h){return h.location == location;}); + }); if (accessibleHoHoLocations.empty()) { @@ -727,15 +741,15 @@ static HintError assignHoHoHints(World& world, WorldPool& worlds, std::listgetName() + "\" now hints to \"" + location->getName() + "\""); } // If we went through and couldn't place all the hints, flag a failure and // try again - for (auto& [hohoLocation, hintedLocations] : world.hohoHints) + for (auto& [hohoLocation, locationHints] : world.hohoHints) { - if (hintedLocations.size() != hintsPerHoHo) + if (locationHints.size() != hintsPerHoHo) { successfullyPlacedHoHoHints = false; break; @@ -757,8 +771,7 @@ static HintError assignKreebHints(World& world, WorldPool& worlds) { if (location->currentItem.getGameItemId() == GameItem::ProgressiveBow) { - world.kreebHints.push_back(location); - LOG_AND_RETURN_IF_ERR(generateItemHintMessage(location)); + LOG_AND_RETURN_IF_ERR(generateItemHintMessage(location, world.kreebHints)); } } return HintError::NONE; @@ -775,8 +788,7 @@ static HintError assignKorlSwordHints(World& world, WorldPool& worlds) { if (location->currentItem.getGameItemId() == GameItem::ProgressiveSword) { - world.korlHyruleHints.push_back(location); - LOG_AND_RETURN_IF_ERR(generateItemHintMessage(location)); + LOG_AND_RETURN_IF_ERR(generateItemHintMessage(location, world.korlHyruleHints)); } } return HintError::NONE; @@ -789,33 +801,36 @@ HintError generateHints(WorldPool& worlds) for (auto& world : worlds) { - std::vector hintLocations = {}; + std::list hints = {}; // First, select always hints - LOG_AND_RETURN_IF_ERR(generateAlwaysHints(world, hintLocations)); + LOG_AND_RETURN_IF_ERR(generateAlwaysHints(world, hints)); // Then select path hint locations so that we don't hint at them during item and location hints - LOG_AND_RETURN_IF_ERR(generatePathHintLocations(world, hintLocations)); + LOG_AND_RETURN_IF_ERR(generatePathHintLocations(world, hints)); // Determine barren hint locations next so that we similarly don't hint at locations // in barren regions when generating item and location hints - LOG_AND_RETURN_IF_ERR(generateBarrenHintLocations(world, hintLocations)); + LOG_AND_RETURN_IF_ERR(generateBarrenHintLocations(world, hints)); // Next, select item hint locations - LOG_AND_RETURN_IF_ERR(generateItemHintLocations(world, hintLocations)); + LOG_AND_RETURN_IF_ERR(generateItemHintLocations(world, hints)); // Finally, select locations for location hints // If we weren't able to select as many hints as the player wanted for previous // types, then select more location hints to fill in the total number the player wanted auto& settings = world.getSettings(); uint8_t totalNumHints = settings.path_hints + settings.barren_hints + settings.item_hints + settings.location_hints; - uint8_t totalMadeHints = hintLocations.size(); - LOG_AND_RETURN_IF_ERR(generateLocationHintLocations(world, hintLocations, totalNumHints - totalMadeHints)); + uint8_t totalMadeHints = hints.size(); + LOG_AND_RETURN_IF_ERR(generateLocationHintLocations(world, hints, totalNumHints - totalMadeHints)); // Sort hints by type - std::sort(hintLocations.begin(), hintLocations.end(), [](Location* l1, Location* l2){ - return l1->hint.type < l2->hint.type; + // Need a vector to sort + std::vector hintsVector (hints.begin(), hints.end()); + std::ranges::sort(hintsVector, [](const Hint& h1, const Hint& h2){ + return h1.type < h2.type; }); + hints.assign(hintsVector.begin(), hintsVector.end()); // Assign Kreeb Bow Hints if the setting is enabled if (settings.kreeb_bow_hints) @@ -831,7 +846,7 @@ HintError generateHints(WorldPool& worlds) // Distribute hints evenly among the possible hint placement options std::vector hintPlacementOptions = {}; - std::unordered_map> hintsForCategory = {}; + std::unordered_map> hintsForCategory = {}; // Only include ho ho if he's not hinting triforces if (settings.ho_ho_hints && !settings.ho_ho_triforce_hints) { @@ -848,20 +863,22 @@ HintError generateHints(WorldPool& worlds) return HintError::NONE; } - for (size_t i = 0; i < hintLocations.size(); i++) + size_t i = 0; + for (auto& hint : hints) { // iterate to the next placement option on each index of the hint locations std::string placementOption = hintPlacementOptions[i % hintPlacementOptions.size()]; // add the hint location to that placement option - hintsForCategory[placementOption].push_back(hintLocations[i]); - LOG_TO_DEBUG("Hint for \"" + hintLocations[i]->getName() + "\" will be given to " + placementOption); + hintsForCategory[placementOption].push_back(hint); + LOG_TO_DEBUG("Hint \"" + hint.text["English"] + "\" will be given to " + placementOption); + ++i; } LOG_AND_RETURN_IF_ERR(assignHoHoHints(world, worlds, hintsForCategory["ho ho"])); - for (auto location : hintsForCategory["korl"]) + for (auto& hint : hintsForCategory["korl"]) { - world.korlHints.push_back(location); + world.korlHints.push_back(hint); } } diff --git a/logic/Hints.hpp b/logic/Hints.hpp index 05162f4f..8a92acb1 100644 --- a/logic/Hints.hpp +++ b/logic/Hints.hpp @@ -23,10 +23,12 @@ enum struct HintType LOCATION, }; +class Location; struct Hint { // Message for this location (one for each language) std::unordered_map text = {}; + Location* location; HintType type = HintType::NONE; }; diff --git a/logic/SpoilerLog.cpp b/logic/SpoilerLog.cpp index 5855b136..9d91e6b7 100644 --- a/logic/SpoilerLog.cpp +++ b/logic/SpoilerLog.cpp @@ -51,10 +51,10 @@ static std::string getSpoilerFormatLocation(Location* location, const size_t& lo return location->getName() + locWorldNumber + ":" + spaces + itemName; } -static std::string getSpoilerFormatHint(Location* location) +static std::string getSpoilerFormatHint(const Hint& hint) { // Get rid of commands in the hint text and then convert to UTF-8 - std::u16string hintText = location->hint.text["English"]; + std::u16string hintText = hint.text.at("English"); for (const std::u16string& eraseText : {TEXT_COLOR_RED, TEXT_COLOR_BLUE, TEXT_COLOR_CYAN, TEXT_COLOR_DEFAULT, TEXT_COLOR_GREEN, TEXT_COLOR_GRAY, TEXT_COLOR_YELLOW}) { auto pos = std::string::npos; @@ -238,7 +238,7 @@ void generateSpoilerLog(WorldPool& worlds) for (auto& world : worlds) { // Don't print "Hints" if there are none - if (world.hohoHints.empty() && world.korlHints.empty() && world.bigOctoFairyHintLocation == nullptr && world.kreebHints.empty() && world.korlHyruleHints.empty()) + if (world.hohoHints.empty() && world.korlHints.empty() && world.bigOctoFairyHint.location == nullptr && world.kreebHints.empty() && world.korlHyruleHints.empty()) { continue; } @@ -246,16 +246,16 @@ void generateSpoilerLog(WorldPool& worlds) spoilerLog << std::endl << (worlds.size() == 1 ? "Hints:" : "Hints for world " + std::to_string(world.getWorldId()) + ":") << std::endl; if (!world.hohoHints.empty()) { - for (auto& [hohoLocation, hintLocations] : world.hohoHints) + for (auto& [hohoLocation, hints] : world.hohoHints) { spoilerLog << " " << hohoLocation->getName() << ":" << std::endl; - for (auto location : hintLocations) + for (auto& hint : hints) { - spoilerLog << " " << getSpoilerFormatHint(location); + spoilerLog << " " << getSpoilerFormatHint(hint); // Show what item/location was being referred to with each path hint - if (location->hint.type == HintType::PATH) + if (hint.type == HintType::PATH) { - spoilerLog << " (" << location->currentItem.getName() << " at " << location->getName() << ")"; + spoilerLog << " (" << hint.location->currentItem.getName() << " at " << hint.location->getName() << ")"; } spoilerLog << std::endl; } @@ -265,13 +265,13 @@ void generateSpoilerLog(WorldPool& worlds) if (!world.korlHints.empty()) { spoilerLog << " KoRL Hints:" << std::endl; - for (auto location : world.korlHints) + for (auto& hint : world.korlHints) { - spoilerLog << " " << getSpoilerFormatHint(location); + spoilerLog << " " << getSpoilerFormatHint(hint); // Show what item/location was being referred to with each path hint - if (location->hint.type == HintType::PATH) + if (hint.type == HintType::PATH && hint.location) { - spoilerLog << " (" << location->currentItem.getName() << " at " << location->getName() << ")"; + spoilerLog << " (" << hint.location->currentItem.getName() << " at " << hint.location->getName() << ")"; } spoilerLog << std::endl; } @@ -280,17 +280,17 @@ void generateSpoilerLog(WorldPool& worlds) if (!world.korlHyruleHints.empty()) { spoilerLog << " KoRL Hyrule Hints:" << std::endl; - for (auto location : world.korlHyruleHints) + for (auto& hint : world.korlHyruleHints) { - spoilerLog << " " << getSpoilerFormatHint(location); + spoilerLog << " " << getSpoilerFormatHint(hint); spoilerLog << std::endl; } } - if (world.bigOctoFairyHintLocation != nullptr) + if (world.bigOctoFairyHint.location != nullptr) { spoilerLog << " Big Octo Great Fairy:" << std::endl; - std::u16string hintText = world.bigOctoFairyHintLocation->hint.text["English"]; + std::u16string hintText = world.bigOctoFairyHint.text["English"]; for (const std::u16string& eraseText : {TEXT_COLOR_RED, TEXT_COLOR_BLUE, TEXT_COLOR_CYAN, TEXT_COLOR_DEFAULT, TEXT_COLOR_GREEN, TEXT_COLOR_GRAY, TEXT_COLOR_YELLOW}) { auto pos = std::string::npos; @@ -305,9 +305,9 @@ void generateSpoilerLog(WorldPool& worlds) if (!world.kreebHints.empty()) { spoilerLog << " Kreeb Hints:" << std::endl; - for (auto location : world.kreebHints) + for (auto& hint : world.kreebHints) { - spoilerLog << " " << getSpoilerFormatHint(location); + spoilerLog << " " << getSpoilerFormatHint(hint); spoilerLog << std::endl; } } diff --git a/logic/World.hpp b/logic/World.hpp index 8e19f88c..52e45814 100644 --- a/logic/World.hpp +++ b/logic/World.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -127,11 +128,11 @@ class World LocationPool raceModeLocations = {}; std::list goalLocations = {}; std::map> barrenRegions = {}; - std::list korlHints = {}; - std::list korlHyruleHints = {}; - std::list kreebHints = {}; - std::map, PointerLess> hohoHints = {}; // map of Ho Ho Hint Location to hinted locations - Location* bigOctoFairyHintLocation = nullptr; + std::list korlHints = {}; + std::list korlHyruleHints = {}; + std::list kreebHints = {}; + std::map> hohoHints = {}; // map of Ho Ho Hint Location to hints + Hint bigOctoFairyHint{}; std::list> playthroughSpheres = {}; std::list> entranceSpheres = {}; std::map chartMappings = {}; diff --git a/text_replacements.cpp b/text_replacements.cpp index 475d2a98..76a75c6f 100644 --- a/text_replacements.cpp +++ b/text_replacements.cpp @@ -61,8 +61,8 @@ TextReplacements generate_text_replacements(World& world) auto& beedle500 = world.locationTable["Rock Spire Isle - Beedle 500 Rupee Item"]->currentItem; auto& beedle950 = world.locationTable["Rock Spire Isle - Beedle 950 Rupee Item"]->currentItem; auto& beedle900 = world.locationTable["Rock Spire Isle - Beedle 900 Rupee Item"]->currentItem; - auto& octoFairyItem = world.bigOctoFairyHintLocation->currentItem; - auto& octoFairyRegion = world.bigOctoFairyHintLocation->hintRegions.front(); + auto& octoFairyItem = world.bigOctoFairyHint.location->currentItem; + auto& octoFairyRegion = world.bigOctoFairyHint.location->hintRegions.front(); LOG_TO_DEBUG("Calculating text replacement articles/pronouns"); // Calculate articles for some replacements @@ -133,9 +133,9 @@ TextReplacements generate_text_replacements(World& world) auto savageFloor50SpanishImportance = savageFloor50Loc->generateImportanceText("Spanish"); auto savageFloor50FrenchImportance = savageFloor50Loc->generateImportanceText("French"); - auto bigOctoFairyEnglishImportance = world.bigOctoFairyHintLocation->generateImportanceText("English"); - auto bigOctoFairySpanishImportance = world.bigOctoFairyHintLocation->generateImportanceText("Spanish"); - auto bigOctoFairyFrenchImportance = world.bigOctoFairyHintLocation->generateImportanceText("French"); + auto bigOctoFairyEnglishImportance = world.bigOctoFairyHint.location->generateImportanceText("English"); + auto bigOctoFairySpanishImportance = world.bigOctoFairyHint.location->generateImportanceText("Spanish"); + auto bigOctoFairyFrenchImportance = world.bigOctoFairyHint.location->generateImportanceText("French"); // Format for text replacements: // Message Label, diff --git a/tweaks.cpp b/tweaks.cpp index d97ffa5e..b0717037 100644 --- a/tweaks.cpp +++ b/tweaks.cpp @@ -1194,11 +1194,11 @@ TweakError update_korl_dialog(World& world) { std::vector hintMessages = {u""}; size_t curLine = 0; - for (auto location : world.korlHints) { - std::u16string hint = location->hint.text[language]; - hint = Text::word_wrap_string(hint, 42); // wrap shorter lines, some edge cases are still too wide with 43 - hint = Text::pad_str_4_lines(hint); - const size_t numLines = std::count(hint.begin(), hint.end(), u'\n'); // 4 for most hints, 8+ for long hints with multiple textboxes + for (auto& hint : world.korlHints) { + std::u16string hintText = hint.text[language]; + hintText = Text::word_wrap_string(hintText, 42); // wrap shorter lines, some edge cases are still too wide with 43 + hintText = Text::pad_str_4_lines(hintText); + const size_t numLines = std::count(hintText.begin(), hintText.end(), u'\n'); // 4 for most hints, 8+ for long hints with multiple textboxes // if we would have >10 textboxes if(curLine + numLines > 40) { @@ -1207,7 +1207,7 @@ TweakError update_korl_dialog(World& world) { curLine = 0; // restart line counter } - hintMessages.back() += hint; // add hint to back of current message + hintMessages.back() += hintText; // add hint to back of current message curLine += numLines; // add hint lines to count } @@ -1253,13 +1253,13 @@ TweakError update_korl_dialog(World& world) { for (const auto& language : Text::supported_languages) { std::u16string hintLines = u""; size_t i = 0; // counter to know when to add null terminator - for (auto location : world.korlHyruleHints) { - std::u16string hint = Text::word_wrap_string(location->hint.text[language], 43); + for (auto& hint : world.korlHyruleHints) { + std::u16string hintText = Text::word_wrap_string(hint.text[language], 43); ++i; if (i == world.korlHyruleHints.size()) { - hint += u'\0'; // add null terminator on last hint before padding + hintText += u'\0'; // add null terminator on last hint before padding } - hintLines += Text::pad_str_4_lines(hint); + hintLines += Text::pad_str_4_lines(hintText); } RandoSession::CacheEntry& entry = g_session.openGameFile("content/Common/Pack/permanent_2d_Us" + language + ".pack@SARC@message2_msbt.szs@YAZ0@SARC@message2.msbt@MSBT"); @@ -1288,22 +1288,22 @@ TweakError update_ho_ho_dialog(World& world) { RandoSession::CacheEntry& entry = g_session.openGameFile("content/Common/Pack/permanent_2d_Us" + language + ".pack@SARC@message4_msbt.szs@YAZ0@SARC@message4.msbt@MSBT"); entry.addAction([=, &world](RandoSession* session, FileType* data) -> int { - for (auto& [hohoLocation, hintLocations] : world.hohoHints) { + for (auto& [hohoLocation, hints] : world.hohoHints) { std::u16string hintLines = u""; size_t i = 0; // counter to know when to add null terminator - for (auto location : hintLocations) { - std::u16string hint = u""; + for (auto& hint : hints) { + std::u16string hintText = u""; if (i == 0) { - hint += SOUND(0x0103) u"Ho ho! "s; + hintText += SOUND(0x0103) u"Ho ho! "s; } i++; - hint += location->hint.text[language]; - hint = Text::word_wrap_string(hint, 43); - if (i == hintLocations.size()) { - hint += u'\0'; // add null terminator on last hint before padding + hintText += hint.text[language]; + hintText = Text::word_wrap_string(hintText, 43); + if (i == hints.size()) { + hintText += u'\0'; // add null terminator on last hint before padding } - hint = Text::pad_str_4_lines(hint); - hintLines += hint; + hintText = Text::pad_str_4_lines(hintText); + hintLines += hintText; } CAST_ENTRY_TO_FILETYPE(msbt, FileTypes::MSBTFile, data) @@ -1327,16 +1327,16 @@ TweakError update_kreeb_dialog(World& world) { entry.addAction([=, &world](RandoSession* session, FileType* data) -> int { std::u16string hintLines = u""; size_t i = 0; // counter to know when to add null terminator - for (auto location : world.kreebHints) { - std::u16string hint = u""; - hint += location->hint.text[language]; - hint = Text::word_wrap_string(hint, 43); + for (auto& hint : world.kreebHints) { + std::u16string hintText = u""; + hintText += hint.text[language]; + hintText = Text::word_wrap_string(hintText, 43); ++i; if (i == world.kreebHints.size()) { - hint += u'\0'; // add null terminator on last hint before padding + hintText += u'\0'; // add null terminator on last hint before padding } - hint = Text::pad_str_4_lines(hint); - hintLines += hint; + hintText = Text::pad_str_4_lines(hintText); + hintLines += hintText; } CAST_ENTRY_TO_FILETYPE(msbt, FileTypes::MSBTFile, data) @@ -1354,10 +1354,10 @@ TweakError rotate_ho_ho_to_face_hints(World& world) { return TweakError::NONE; } - for (auto& [hohoLocation, hintLocations] : world.hohoHints) { + for (auto& [hohoLocation, hints] : world.hohoHints) { std::string island = ""; - for (auto location : hintLocations) { - for (auto region : location->hintRegions) { + for (auto& hint : hints) { + for (auto region : hint.location->hintRegions) { // If this region is a dungeon, use the dungeon's island instead if (world.dungeons.contains(region)) { region = world.dungeons[region].islands.front();