diff --git a/logic/Hints.cpp b/logic/Hints.cpp index bcc98600..2d08f02c 100644 --- a/logic/Hints.cpp +++ b/logic/Hints.cpp @@ -519,8 +519,7 @@ static HintError generateItemHintLocations(World& world, std::vector& !location->hasKnownVanillaItem && // and does not have a known vanilla item... !location->hasExpectedItem && // and does not have an expected item... !location->hasBeenHinted && // and has not been hinted at yet... - !(settings.ho_ho_triforce_hints && location->currentItem.isTriforceShard()) && // and isn't a shard when ho ho will hint shards... - (location->hintPriority != "Always" || !world.getSettings().use_always_hints)) // and the hint priority is not "Always" when we're using always hints... + !(settings.ho_ho_triforce_hints && location->currentItem.isTriforceShard())) // and isn't a shard when ho ho will hint shards... { // Then the item is a possible item hint location @@ -589,51 +588,74 @@ static HintError generateLocationHintMessage(Location* location) return HintError::NONE; } -static HintError generateLocationHintLocations(World& world, std::vector& locationHintLocations, uint8_t numLocationHints) +static HintError generateAlwaysHints(World& world, std::vector& alwaysHintLocations) { + // 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) + { + return HintError::NONE; + } + // Gather all the always locations std::vector alwaysLocations = {}; - std::vector sometimesLocations = {}; - - // Put locations into the always or sometimes categories depending on what their hint priority is for (auto& [name, location] : world.locationTable) { - if (location->progression && !location->hasBeenHinted && !location->isRaceModeLocation) + if (location->progression && location->hintPriority == "Always") { - if (location->hintPriority == "Always") - { - alwaysLocations.push_back(location.get()); - } - else if (location->hintPriority == "Sometimes" && !(world.getSettings().ho_ho_triforce_hints && location->currentItem.isTriforceShard())) - { - sometimesLocations.push_back(location.get()); - } + alwaysLocations.push_back(location.get()); } } - // If use_always_hints is off, then add the always locations to the sometimes locations - if (!world.getSettings().use_always_hints) - { - addElementsToPool(sometimesLocations, alwaysLocations); - alwaysLocations.clear(); - } + // Shuffle the always locations so we don't hint them in the same order + shufflePool(alwaysLocations); - for (uint8_t i = 0; i < numLocationHints; i++) + for (uint8_t i = 0; i < world.getSettings().location_hints; ++i) { Location* hintLocation = nullptr; if (i < alwaysLocations.size()) { hintLocation = alwaysLocations[i]; } + // Break if we've hinted all the always locations else { - if (sometimesLocations.empty()) + break; + } + alwaysHintLocations.push_back(hintLocation); + LOG_AND_RETURN_IF_ERR(generateLocationHintMessage(hintLocation)); + LOG_TO_DEBUG("Chose \"" + hintLocation->getName() + "\" as always hint location"); + } + + return HintError::NONE; +} + +static HintError generateLocationHintLocations(World& world, std::vector& locationHintLocations, uint8_t numLocationHints) +{ + std::vector sometimesLocations = {}; + + // Gather all the sometimes locations + for (auto& [name, location] : world.locationTable) + { + if (location->progression && + !location->hasBeenHinted && + !location->isRaceModeLocation && + location->hintPriority == "Sometimes" && + !(world.getSettings().ho_ho_triforce_hints && location->currentItem.isTriforceShard())) { - LOG_TO_DEBUG("No more possible location hints."); - break; + sometimesLocations.push_back(location.get()); } - hintLocation = popRandomElement(sometimesLocations); + } + + // Choose them randomly + for (uint8_t i = 0; i < numLocationHints; ++i) + { + Location* hintLocation = nullptr; + if (sometimesLocations.empty()) + { + LOG_TO_DEBUG("No more possible location hints."); + break; } + hintLocation = popRandomElement(sometimesLocations); locationHintLocations.push_back(hintLocation); LOG_AND_RETURN_IF_ERR(generateLocationHintMessage(hintLocation)); LOG_TO_DEBUG("Chose \"" + hintLocation->getName() + "\" as location hint location"); @@ -769,7 +791,10 @@ HintError generateHints(WorldPool& worlds) { std::vector hintLocations = {}; - // First, select path hint locations so that we don't hint at them during item and location hints + // First, select always hints + LOG_AND_RETURN_IF_ERR(generateAlwaysHints(world, hintLocations)); + + // 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)); // Determine barren hint locations next so that we similarly don't hint at locations @@ -787,6 +812,11 @@ HintError generateHints(WorldPool& worlds) uint8_t totalMadeHints = hintLocations.size(); LOG_AND_RETURN_IF_ERR(generateLocationHintLocations(world, hintLocations, totalNumHints - totalMadeHints)); + // Sort hints by type + std::sort(hintLocations.begin(), hintLocations.end(), [](Location* l1, Location* l2){ + return l1->hint.type < l2->hint.type; + }); + // Assign Kreeb Bow Hints if the setting is enabled if (settings.kreeb_bow_hints) {