diff --git a/gui/desktop/mainwindow.cpp b/gui/desktop/mainwindow.cpp index 08561f5c..8ad4a147 100644 --- a/gui/desktop/mainwindow.cpp +++ b/gui/desktop/mainwindow.cpp @@ -545,7 +545,7 @@ void MainWindow::apply_config_settings() APPLY_SPINBOX_SETTING(config, ui, damage_multiplier, float(2.0f), float(MAXIMUM_DAMAGE_MULTIPLIER)); auto& num_required_dungeons = config.settings.num_required_dungeons; - // Race mode dungeons must be between 1 and 6 if race mode is enabled + // Required dungeons must be between 1 and 6 if race mode is enabled if (config.settings.progression_dungeons == ProgressionDungeons::RaceMode) { num_required_dungeons = std::clamp(num_required_dungeons, uint8_t(1), uint8_t(MAXIMUM_NUM_DUNGEONS)); @@ -771,7 +771,7 @@ DEFINE_STATE_CHANGE_FUNCTION(progression_combat_secret_caves) void MainWindow::on_progression_dungeons_currentTextChanged(const QString &arg1) { config.settings.progression_dungeons = nameToProgressionDungeons(arg1.toStdString()); - // Grey out the race mode dungeons combobox if race mode/standard is not selected + // Grey out the required dungeons combobox if dungeons are disabled if (config.settings.progression_dungeons == ProgressionDungeons::RaceMode) { ui->num_required_dungeons->setEnabled(true); diff --git a/logic/Dungeon.hpp b/logic/Dungeon.hpp index 6022ef67..ee68a1df 100644 --- a/logic/Dungeon.hpp +++ b/logic/Dungeon.hpp @@ -16,13 +16,13 @@ struct Dungeon { Item map = Item(); Item compass = Item(); std::list locations = {}; - Location* raceModeLocation = nullptr; + Location* bossLocation = nullptr; Area* startingArea = nullptr; Entrance* startingEntrance = nullptr; std::list islands = {}; std::string name = ""; bool isRequiredDungeon = false; - bool hasNaturalRaceModeLocation = false; + bool hasNaturalBossLocation = false; std::string windWarpExitStage = ""; uint8_t windWarpExitRoom = 0; uint8_t windWarpExitSpawn = 0; diff --git a/logic/EntranceShuffle.cpp b/logic/EntranceShuffle.cpp index 29d04fd9..70dedd80 100644 --- a/logic/EntranceShuffle.cpp +++ b/logic/EntranceShuffle.cpp @@ -306,25 +306,24 @@ static EntranceShuffleError validateWorld(WorldPool& worlds, const Entrance* ent for (auto& world : worlds) { - // Ensure that all race mode bosses are assigned to a single island + // Ensure that all required bosses are assigned to a single island auto& settings = world.getSettings(); if (settings.progression_dungeons != ProgressionDungeons::Disabled && settings.num_required_dungeons > 0) { - std::unordered_set raceModeIslands = {}; - for (auto loc : world.raceModeLocations) + for (auto loc : world.bossLocations) { - auto bossIslands = loc->accessPoints.front()->area->findIslands(); + const auto& bossIslands = loc->accessPoints.front()->area->findIslands(); if (bossIslands.size() > 1) { #ifdef ENABLE_DEBUG - LOG_TO_DEBUG("Error: More than 1 island leading to race mode boss room " + loc->accessPoints.front()->area->name); + LOG_TO_DEBUG("Error: More than 1 island leading to required boss room " + loc->accessPoints.front()->area->name); for (auto& island : bossIslands) { LOG_TO_DEBUG("\t" + island); } #endif - return EntranceShuffleError::AMBIGUOUS_RACE_MODE_ISLAND; + return EntranceShuffleError::AMBIGUOUS_BOSS_ISLAND; } } } @@ -952,7 +951,7 @@ EntranceShuffleError randomizeEntrances(WorldPool& worlds) } } - // Now set the islands the race mode dungeons are in + // Now set the islands the dungeons are in for (auto& [name, dungeon] : world.dungeons) { dungeon.islands = dungeon.startingArea->findIslands(); @@ -982,12 +981,8 @@ const std::string errorToName(EntranceShuffleError err) return "NO_MORE_VALID_ENTRANCES"; case EntranceShuffleError::ALL_LOCATIONS_NOT_REACHABLE: return "ALL_LOCATIONS_NOT_REACHABLE"; - case EntranceShuffleError::AMBIGUOUS_RACE_MODE_ISLAND: - return "AMBIGUOUS_RACE_MODE_ISLAND"; - case EntranceShuffleError::AMBIGUOUS_RACE_MODE_DUNGEON: - return "AMBIGUOUS_RACE_MODE_DUNGEON"; - case EntranceShuffleError::NO_RACE_MODE_ISLAND: - return "NO_RACE_MODE_ISLAND"; + case EntranceShuffleError::AMBIGUOUS_BOSS_ISLAND: + return "AMBIGUOUS_BOSS_ISLAND"; case EntranceShuffleError::NOT_ENOUGH_SPHERE_ZERO_LOCATIONS: return "NOT_ENOUGH_SPHERE_ZERO_LOCATIONS"; case EntranceShuffleError::ATTEMPTED_SELF_CONNECTION: diff --git a/logic/EntranceShuffle.hpp b/logic/EntranceShuffle.hpp index 3641eedc..10a97047 100644 --- a/logic/EntranceShuffle.hpp +++ b/logic/EntranceShuffle.hpp @@ -12,9 +12,7 @@ enum struct EntranceShuffleError RAN_OUT_OF_RETRIES, NO_MORE_VALID_ENTRANCES, ALL_LOCATIONS_NOT_REACHABLE, - AMBIGUOUS_RACE_MODE_ISLAND, - AMBIGUOUS_RACE_MODE_DUNGEON, - NO_RACE_MODE_ISLAND, + AMBIGUOUS_BOSS_ISLAND, NOT_ENOUGH_SPHERE_ZERO_LOCATIONS, ATTEMPTED_SELF_CONNECTION, FAILED_TO_DISCONNECT_TARGET, diff --git a/logic/Fill.cpp b/logic/Fill.cpp index 0acb3cc1..be34c49e 100644 --- a/logic/Fill.cpp +++ b/logic/Fill.cpp @@ -323,8 +323,7 @@ void placeVanillaItems(WorldPool& worlds) // Determine which items are major items. A major item is any item required // for access to any progression location and/or game beatability. This function // is called multiple times during the fill algorithm as the items required for -// beatability may change depending on which items are placed in race mode locations -// and/or plandomized +// beatability may change depending on which items are placed in boss locations and/or plandomized void determineMajorItems(WorldPool& worlds, ItemPool& itemPool, LocationPool& allLocations) { LOG_TO_DEBUG("Determining Major Items"); @@ -405,7 +404,7 @@ static FillError randomizeOwnDungeon(WorldPool& worlds, ItemPool& itemPool) { // Filter to only the dungeons locations which are progression locations // If dungeons are not progression locations, or if race mode is on - // and this isn't a race mode dungeon, then take all locations in + // and this isn't a required dungeon, then take all locations in // the dungeon since none of them are progression anyway auto worldLocations = world.getLocations(); auto dungeonLocations = filterFromPool(worldLocations, [&dungeon = dungeon, &settings = settings](const Location* loc){ @@ -586,12 +585,12 @@ static FillError handleDungeonItems(WorldPool& worlds, ItemPool& itemPool) return FillError::NONE; } -static void generateRaceModeItems(const LocationPool& raceModeLocations, ItemPool& raceModeItems, ItemPool& itemsToChooseFrom, ItemPool& mainItemPool) +static void generateBossItems(const LocationPool& bossLocations, ItemPool& chosenItems, ItemPool& itemsToChooseFrom, ItemPool& mainItemPool) { shufflePool(itemsToChooseFrom); - while (!itemsToChooseFrom.empty() && raceModeItems.size() < raceModeLocations.size()) + while (!itemsToChooseFrom.empty() && chosenItems.size() < bossLocations.size()) { - raceModeItems.push_back(popRandomElement(itemsToChooseFrom)); + chosenItems.push_back(popRandomElement(itemsToChooseFrom)); } // Add back any unused elements addElementsToPool(mainItemPool, itemsToChooseFrom); @@ -599,10 +598,10 @@ static void generateRaceModeItems(const LocationPool& raceModeLocations, ItemPoo // Place progression items in specific locations at the end of dungeons to require the player // to beat those dungeons. -static FillError placeRaceModeItems(WorldPool& worlds, ItemPool& itemPool, LocationPool& allLocations) +static FillError placeBossItems(WorldPool& worlds, ItemPool& itemPool, LocationPool& allLocations) { - LocationPool raceModeLocations; - ItemPool raceModeItems; + LocationPool bossLocations; + ItemPool bossItems; for (auto& world : worlds) { if(world.getSettings().required_boss_items) { @@ -610,13 +609,13 @@ static FillError placeRaceModeItems(WorldPool& worlds, ItemPool& itemPool, Locat { if (dungeon.isRequiredDungeon) { - auto raceModeLocation = dungeon.raceModeLocation; + auto bossLocation = dungeon.bossLocation; // If this location already has an item placed at it, then skip it - if (raceModeLocation->currentItem.getGameItemId() != GameItem::INVALID) + if (bossLocation->currentItem.getGameItemId() != GameItem::INVALID) { continue; } - raceModeLocations.push_back(raceModeLocation); + bossLocations.push_back(bossLocation); } } } @@ -624,28 +623,29 @@ static FillError placeRaceModeItems(WorldPool& worlds, ItemPool& itemPool, Locat // Build up the list of boss items with major items. auto majorItems = filterAndEraseFromPool(itemPool, [](const Item& item){return item.isMajorItem();}); - generateRaceModeItems(raceModeLocations, raceModeItems, majorItems, itemPool); + generateBossItems(bossLocations, bossItems, majorItems, itemPool); - // logItemPool("raceModeItems", raceModeItems); + logItemPool("Boss Items", bossItems); - if (raceModeItems.size() < raceModeLocations.size()) + if (bossItems.size() < bossLocations.size()) { - Utility::platformLog("WARNING: Not enough major items to place at race mode locations."); + Utility::platformLog("WARNING: Not enough major items to place at boss locations."); } - // Then place the items in the race mode locations + // Then place the items in the boss locations FillError err; - FILL_ERROR_CHECK(assumedFill(worlds, raceModeItems, itemPool, raceModeLocations)); + FILL_ERROR_CHECK(assumedFill(worlds, bossItems, itemPool, bossLocations)); - // Set race mode locations which had items placed at them as having expected items - for (auto raceModeLoc : raceModeLocations) + // Set boss locations which had items placed at them as having expected items + for (auto loc : bossLocations) { - raceModeLoc->hasExpectedItem = true; + loc->hasExpectedItem = true; } // Recalculate major items since new items may now be required depending on - // what items were placed at race mode locations + // what items were placed at boss locations determineMajorItems(worlds, itemPool, allLocations); + return FillError::NONE; } @@ -734,10 +734,10 @@ FillError fill(WorldPool& worlds) determineMajorItems(worlds, itemPool, allLocations); FILL_ERROR_CHECK(placeNonProgressLocationPlandomizerItems(worlds, itemPool)); - // Handle dungeon items and race mode dungeons first if necessary. Generally + // Handle dungeon and/or boss items first if necessary. Generally // we need to place items that go into more restrictive location pools first before // we can place other items. - FILL_ERROR_CHECK(placeRaceModeItems(worlds, itemPool, allLocations)); + FILL_ERROR_CHECK(placeBossItems(worlds, itemPool, allLocations)); FILL_ERROR_CHECK(handleDungeonItems(worlds, itemPool)); // Recalculate major items again since new items may now be required depending on diff --git a/logic/Generate.cpp b/logic/Generate.cpp index 882b9d00..64407f9f 100644 --- a/logic/Generate.cpp +++ b/logic/Generate.cpp @@ -156,13 +156,13 @@ int generateWorlds(WorldPool& worlds, std::vector& settingsVector) // Now that all entrances have been randomized, we can flatten the world's // logic requirements for some useful operations later on - // Determine race mode dungeons after entrance randomizer to ensure we pick + // Determine required dungeons after entrance randomizer to ensure we pick // dungeons which can be properly reached depending on any entrance rando settings for (auto& world : worlds) { world.flattenLogicRequirements(); WORLD_LOADING_ERROR_CHECK(world.setDungeonLocations(worlds)); - WORLD_LOADING_ERROR_CHECK(world.determineRaceModeDungeons(worlds)); + WORLD_LOADING_ERROR_CHECK(world.determineRequiredDungeons(worlds)); } // Retry the main fill algorithm a couple times incase it completely fails. diff --git a/logic/Hints.cpp b/logic/Hints.cpp index 745accbe..d2b9b3f9 100644 --- a/logic/Hints.cpp +++ b/logic/Hints.cpp @@ -33,10 +33,10 @@ static HintError calculatePossiblePathLocations(WorldPool& worlds) world.goalLocations.push_back(world.locationTable["Ganon's Tower - Defeat Ganondorf"].get()); for (auto& [name, dungeon] : world.dungeons) { - // Race mode locations are also goal locations + // Boss locations are also goal locations if (dungeon.isRequiredDungeon) { - world.goalLocations.push_back(dungeon.raceModeLocation); + world.goalLocations.push_back(dungeon.bossLocation); } } @@ -311,7 +311,7 @@ static HintError generatePathHintLocations(World& world, std::list& hints) for (auto& goalLocation : world.goalLocations) { shufflePool(goalLocation->pathLocations); - // Initially we want to pull path hints from race mode dungeons before pulling from Ganondorf + // Initially we want to pull path hints from required dungeons before pulling from Ganondorf if (goalLocation->getName() != "Ganon's Tower - Defeat Ganondorf") { goalLocations.push_back(goalLocation); @@ -321,7 +321,7 @@ static HintError generatePathHintLocations(World& world, std::list& hints) bool addedGanonPathLocation = false; for (uint8_t i = 0; i < world.getSettings().path_hints; i++) { - // Try to get at least one hint for each race mode dungeon first + // Try to get at least one hint for each required dungeon first Location* goalLocation = nullptr; if (i < goalLocations.size()) { @@ -329,7 +329,7 @@ static HintError generatePathHintLocations(World& world, std::list& hints) } else { - // Once we've pulled from all race mode dungeons, then add Ganondorf to the list + // Once we've pulled from all required dungeons, then add Ganondorf to the list // and choose randomly if (i == goalLocations.size() && !addedGanonPathLocation) { @@ -650,7 +650,7 @@ static HintError generateLocationHintLocations(World& world, std::list& hi { if (location->progression && !location->hasBeenHinted && - !location->isRaceModeLocation && + !location->isBossLocation && location->hintPriority == "Sometimes" && !(world.getSettings().ho_ho_triforce_hints && location->currentItem.isTriforceShard())) { diff --git a/logic/Location.cpp b/logic/Location.cpp index e965e931..57056506 100644 --- a/logic/Location.cpp +++ b/logic/Location.cpp @@ -187,7 +187,7 @@ bool Location::currentItemCanBeBarren() const // if it's a required race mode location bool Location::isBarrenAsChainLocation() const { - return !progression || (currentItem.canBeInBarrenRegion() && !isRequiredRaceModeLocation); + return !progression || (currentItem.canBeInBarrenRegion() && !isRequiredBossLocation); } std::u16string Location::generateImportanceText(const std::string& language) diff --git a/logic/Location.hpp b/logic/Location.hpp index 9999e94e..159ad340 100644 --- a/logic/Location.hpp +++ b/logic/Location.hpp @@ -71,8 +71,8 @@ class Location std::unordered_map names = {}; std::unordered_set categories; bool progression; - bool isRaceModeLocation; - bool isRequiredRaceModeLocation; + bool isBossLocation; + bool isRequiredBossLocation; uint8_t stageId = 0; bool plandomized; bool hasBeenHinted; @@ -100,7 +100,7 @@ class Location // Message Label if this is a hint location std::string messageLabel; - // goal names if this is a race mode location (one for each language) + // goal names if this is a boss location (one for each language) std::unordered_map goalNames = {}; // Tracker properties @@ -112,8 +112,8 @@ class Location names({}), categories({LocationCategory::INVALID}), progression(false), - isRaceModeLocation(false), - isRequiredRaceModeLocation(false), + isBossLocation(false), + isRequiredBossLocation(false), stageId(0), plandomized(false), hasBeenHinted(false), diff --git a/logic/World.cpp b/logic/World.cpp index 0ebbe1d6..8e50211e 100644 --- a/logic/World.cpp +++ b/logic/World.cpp @@ -371,11 +371,11 @@ World::WorldLoadingError World::determineProgressionLocations() } // Properly set the dungeons for boss room locations -// for race mode incase boss/miniboss entrances are randomized +// in case boss/miniboss entrances are randomized World::WorldLoadingError World::setDungeonLocations(WorldPool& worlds) { - // Keep track of any unassigned race mode locations - LocationPool unassignedRaceModeLocations = {}; + // Keep track of any unassigned boss locations + LocationPool unassignedBossLocations = {}; for (auto& [areaName, area] : areaTable) { @@ -392,79 +392,79 @@ World::WorldLoadingError World::setDungeonLocations(WorldPool& worlds) auto& dungeon = getDungeon(dungeonName); LOG_TO_DEBUG(loc->getName() + " has been assigned to dungeon " + dungeonName); - if (loc->isRaceModeLocation) + if (loc->isBossLocation) { - if (dungeon.raceModeLocation == nullptr) + if (dungeon.bossLocation == nullptr) { - dungeon.raceModeLocation = loc; - dungeon.hasNaturalRaceModeLocation = true; + dungeon.bossLocation = loc; + dungeon.hasNaturalBossLocation = true; } else { - unassignedRaceModeLocations.push_back(loc); + unassignedBossLocations.push_back(loc); } } dungeon.locations.emplace_back(loc); loc->hintRegions.push_back(dungeonName); area->dungeon = dungeonName; } - // If the race mode location doesn't have a dungeon, it's unassigned - else if (loc->isRaceModeLocation) + // If the boss location doesn't have a dungeon, it's unassigned + else if (loc->isBossLocation) { - unassignedRaceModeLocations.push_back(loc); + unassignedBossLocations.push_back(loc); } } } } - // For any unassigned race mode locations, randomly + // For any unassigned boss locations, randomly // assign them to dungeons that don't have one, // but don't list them in the dungeon's locations for (auto& [dungeonName, dungeon] : dungeons) { dungeon.name = dungeonName; // Also make sure the name is set - if (dungeon.raceModeLocation == nullptr) + if (dungeon.bossLocation == nullptr) { - dungeon.raceModeLocation = popRandomElement(unassignedRaceModeLocations); - LOG_TO_DEBUG("Unconnected race mode location " + dungeon.raceModeLocation->getName() + " has been assigned to dungeon " + dungeonName); + dungeon.bossLocation = popRandomElement(unassignedBossLocations); + LOG_TO_DEBUG("Unconnected boss location " + dungeon.bossLocation->getName() + " has been assigned to dungeon " + dungeonName); } } return WorldLoadingError::NONE; } -World::WorldLoadingError World::determineRaceModeDungeons(WorldPool& worlds) +World::WorldLoadingError World::determineRequiredDungeons(WorldPool& worlds) { if (settings.progression_dungeons != ProgressionDungeons::Disabled) { std::vector dungeonPool = {}; for (auto& [name, dungeon] : dungeons) { - // Verify that each dungeon has a race mode location - if (dungeon.raceModeLocation == nullptr) + // Verify that each dungeon has a boss location + if (dungeon.bossLocation == nullptr) { - ErrorLog::getInstance().log("Dungeon \"" + dungeon.name + "\" has no set race mode location"); - LOG_ERR_AND_RETURN(WorldLoadingError::DUNGEON_HAS_NO_RACE_MODE_LOCATION); + ErrorLog::getInstance().log("Dungeon \"" + dungeon.name + "\" has no set boss location"); + LOG_ERR_AND_RETURN(WorldLoadingError::DUNGEON_HAS_NO_BOSS_LOCATION); } dungeonPool.push_back(dungeon); } LocationPool nonProgressRollbacks = {}; - bool successfullyChoseRaceModeDungeons = false; + bool successfullyChoseDungeons = false; // If the user only selects dungeons as their progression category, then - // we might need to reselect race mode dungeons a few times until we select + // we might need to reselect required dungeons a few times until we select // a combination that has sphere 0 locations open. do { shufflePool(dungeonPool); - size_t setRaceModeDungeons = 0; - // Loop through all the dungeons and see if any of them have items plandomized - // within them (or within their dependent locations). If they have major items - // plandomized, then select those dungeons as race mode dungeons + size_t setDungeons = 0; if (settings.plandomizer && settings.progression_dungeons == ProgressionDungeons::RaceMode) { + // Loop through all the dungeons and see if any of them have items plandomized + // within them (or within their dependent locations). If they have major items + // plandomized, then select those dungeons as race mode dungeons for (const Dungeon& dungeon : dungeonPool) { auto allDungeonLocations = dungeon.locations; @@ -476,37 +476,37 @@ World::WorldLoadingError World::determineRaceModeDungeons(WorldPool& worlds) if (plandomizer.locations.contains(dungeonLocation) && !plandomizer.locations[dungeonLocation].isJunkItem()) { if(settings.required_boss_items) { - // However, if the dungeon's naturally assigned race mode location is supposed to have a progress item and + // However, if the dungeon's naturally assigned boss location is supposed to have a progress item and // it is plandomized junk or excluded then that's an error on the user's part. - Location* raceModeLocation = dungeon.raceModeLocation; - bool raceModeLocationIsAcceptable = raceModeLocation->progression && (!plandomizer.locations.contains(raceModeLocation) || !plandomizer.locations[raceModeLocation].isJunkItem()); - if (dungeon.hasNaturalRaceModeLocation && !raceModeLocationIsAcceptable) + Location* bossLocation = dungeon.bossLocation; + bool bossLocationIsAcceptable = bossLocation->progression && (!plandomizer.locations.contains(bossLocation) || !plandomizer.locations[bossLocation].isJunkItem()); + if (dungeon.hasNaturalBossLocation && !bossLocationIsAcceptable) { - ErrorLog::getInstance().log("Plandomizer Error: Junk item placed at race mode location in dungeon \"" + dungeon.name + "\" with potentially major item"); + ErrorLog::getInstance().log("Plandomizer Error: Junk item placed at boss location in dungeon \"" + dungeon.name + "\" with potentially major item"); LOG_ERR_AND_RETURN(WorldLoadingError::PLANDOMIZER_ERROR); } } LOG_TO_DEBUG("Chose race mode dungeon : " + dungeon.name); dungeons[dungeon.name].isRequiredDungeon = true; - setRaceModeDungeons++; + setDungeons++; break; } } } - } - // If too many are set, return an error - if (setRaceModeDungeons > settings.num_required_dungeons) - { - ErrorLog::getInstance().log("Plandomizer Error: Too many dungeons set with potentially major items"); - ErrorLog::getInstance().log("Set number of race mode dungeons: " + std::to_string(setRaceModeDungeons)); - ErrorLog::getInstance().log("Maximum set race mode dungeons: " + std::to_string(settings.num_required_dungeons)); - LOG_ERR_AND_RETURN(WorldLoadingError::PLANDOMIZER_ERROR); + // If too many are set, return an error + if (setDungeons > settings.num_required_dungeons) + { + ErrorLog::getInstance().log("Plandomizer Error: Too many dungeons set with potentially major items"); + ErrorLog::getInstance().log("Set number of race mode dungeons: " + std::to_string(setDungeons)); + ErrorLog::getInstance().log("Maximum number of race mode dungeons: " + std::to_string(settings.num_required_dungeons)); + LOG_ERR_AND_RETURN(WorldLoadingError::PLANDOMIZER_ERROR); + } } - // Now check again and fill in any more dungeons that may be necessary - // Also set non-race mode dungeons locations as non-progress + // Now check again and choose any more dungeons that may be necessary + // Also set non-race mode dungeons' locations as non-progress for (const auto& dungeon : dungeonPool) { // If this dungeon was already selected, then skip it @@ -514,35 +514,35 @@ World::WorldLoadingError World::determineRaceModeDungeons(WorldPool& worlds) { continue; } - // If this dungeon's race mode location is (excluded) or (bosses have required items - // and this dungeon has junk placed at its race mode location), then skip it - auto raceModeLocation = dungeon.raceModeLocation; - bool raceModeLocationIsAcceptable = raceModeLocation->progression && (!settings.required_boss_items || (!plandomizer.locations.contains(raceModeLocation) || !plandomizer.locations[raceModeLocation].isJunkItem())); - if (raceModeLocationIsAcceptable && setRaceModeDungeons < settings.num_required_dungeons) + // If this dungeon's boss location is (excluded) or (bosses have required items + // and this dungeon has junk placed at its boss location), then skip it + auto bossLocation = dungeon.bossLocation; + bool bossLocationIsAcceptable = bossLocation->progression && (!settings.required_boss_items || (!plandomizer.locations.contains(bossLocation) || !plandomizer.locations[bossLocation].isJunkItem())); + if (bossLocationIsAcceptable && setDungeons < settings.num_required_dungeons) { - LOG_TO_DEBUG("Chose race mode dungeon : " + dungeon.name); + LOG_TO_DEBUG("Chose required dungeon : " + dungeon.name); dungeons[dungeon.name].isRequiredDungeon = true; - setRaceModeDungeons++; + setDungeons++; } else if (settings.progression_dungeons == ProgressionDungeons::RaceMode) { - // If we've already chosen our race mode dungeons, then set all - // the other dungeons' locations as non-progression. If dungeons - // are set as progression locations, we already set them all as - // progression previously, so here we unset those which aren't - // progression dungeons. + // If we haven't chosen this dungeon as a race mode dungeon, + // then set all of its locations as non-progression. + // Because dungeons were enabled, we already set their locations as + // progression previously, so we need to unset those which aren't in + // the selected dungeons. for (auto location : dungeon.locations) { location->progression = false; nonProgressRollbacks.push_back(location); } - // Dungeons without a naturally assigned race mode location won't - // have their race mode location in their list of locations, so + // Dungeons without a naturally assigned boss location won't + // have their boss location in their list of locations, so // manually add it to the non-progress checks - if (!dungeon.hasNaturalRaceModeLocation) + if (!dungeon.hasNaturalBossLocation) { - nonProgressRollbacks.push_back(dungeon.raceModeLocation); + nonProgressRollbacks.push_back(dungeon.bossLocation); } // Also set any progress locations outside the dungeon which @@ -564,20 +564,20 @@ World::WorldLoadingError World::determineRaceModeDungeons(WorldPool& worlds) // If we have locations available, flag a successful choosing if (!getAccessibleLocations(worlds, noItems, allowedLocations).empty()) { - successfullyChoseRaceModeDungeons = true; + successfullyChoseDungeons = true; - if (setRaceModeDungeons < settings.num_required_dungeons) + if (setDungeons < settings.num_required_dungeons) { - ErrorLog::getInstance().log("Not enough race mode locations for set number of race mode dungeons"); - ErrorLog::getInstance().log("Possible race mode locations: " + std::to_string(setRaceModeDungeons)); - ErrorLog::getInstance().log("Set number of race mode dungeons: " + std::to_string(settings.num_required_dungeons)); - LOG_ERR_AND_RETURN(WorldLoadingError::NOT_ENOUGH_RACE_MODE_LOCATIONS); + ErrorLog::getInstance().log("Not enough boss locations for set number of required dungeons"); + ErrorLog::getInstance().log("Possible boss locations: " + std::to_string(setDungeons)); + ErrorLog::getInstance().log("Set number of required dungeons: " + std::to_string(settings.num_required_dungeons)); + LOG_ERR_AND_RETURN(WorldLoadingError::NOT_ENOUGH_BOSS_LOCATIONS); } } // Otherwise, set all dungeon locations as progression and try again else { - LOG_TO_DEBUG("No sphere 0 progression locations with chosen race mode dungeon set"); + LOG_TO_DEBUG("No sphere 0 progression locations with chosen dungeon set"); for (auto location : nonProgressRollbacks) { location->progression = true; @@ -589,15 +589,15 @@ World::WorldLoadingError World::determineRaceModeDungeons(WorldPool& worlds) nonProgressRollbacks.clear(); } - } while (!successfullyChoseRaceModeDungeons); + } while (!successfullyChoseDungeons); // Set setting variables for required bosses for (const auto& [dungeonName, dungeon] : dungeons) { if (dungeon.isRequiredDungeon) { - settings.setRequiredBoss(dungeon.raceModeLocation->getName(), true); - dungeon.raceModeLocation->isRequiredRaceModeLocation = true; + settings.setRequiredBoss(dungeon.bossLocation->getName(), true); + dungeon.bossLocation->isRequiredBossLocation = true; } } } @@ -753,10 +753,10 @@ World::WorldLoadingError World::loadLocation(const YAML::Node& locationObject) const std::string& hintPriority = locationObject["Hint Priority"].as(); location->hintPriority = hintPriority; - if (locationObject["Race Mode Location"]) + if (locationObject["Boss Location"]) { - location->isRaceModeLocation = true; - raceModeLocations.push_back(location); + location->isBossLocation = true; + bossLocations.push_back(location); } if(locationObject["Stage ID"]) @@ -881,7 +881,7 @@ World::WorldLoadingError World::loadArea(const YAML::Node& areaObject) } // Check to see if this area is the first one in a dungeon. This is important - // for later finding which island leads to this dungeon in race mode + // for later finding which island leads to this dungeon. if (areaObject["Dungeon Starting Room"]) { const auto dungeon = areaObject["Dungeon Starting Room"].as(); @@ -1573,10 +1573,10 @@ std::string World::errorToName(WorldLoadingError err) return "BAD_REQUIREMENT"; case WorldLoadingError::PLANDOMIZER_ERROR: return "PLANDOMIZER_ERROR"; - case WorldLoadingError::DUNGEON_HAS_NO_RACE_MODE_LOCATION: - return "DUNGEON_HAS_NO_RACE_MODE_LOCATION"; - case WorldLoadingError::NOT_ENOUGH_RACE_MODE_LOCATIONS: - return "NOT_ENOUGH_RACE_MODE_LOCATIONS"; + case WorldLoadingError::DUNGEON_HAS_NO_BOSS_LOCATION: + return "DUNGEON_HAS_NO_BOSS_LOCATION"; + case WorldLoadingError::NOT_ENOUGH_BOSS_LOCATIONS: + return "NOT_ENOUGH_BOSS_LOCATIONS"; case WorldLoadingError::INVALID_DUNGEON_NAME: return "INVALID_DUNGEON_NAME"; case WorldLoadingError::DATA_FILE_ERROR: diff --git a/logic/World.hpp b/logic/World.hpp index d3c37cc7..b0889ceb 100644 --- a/logic/World.hpp +++ b/logic/World.hpp @@ -20,7 +20,7 @@ #define GET_COMPLETE_ITEM_POOL(itemPool, worlds) for (auto& world : worlds) {addElementsToPool(itemPool, world.getItemPool());} #define GET_COMPLETE_PROGRESSION_LOCATION_POOL(locationPool, worlds) for (auto& world : worlds) {addElementsToPool(locationPool, world.getProgressionLocations());} -#define ANY_WORLD_HAS_RACE_MODE(worlds) std::any_of(worlds.begin(), worlds.end(), [](World& world){return world.getSettings().progression_dungeons == ProgressionDungeons::RaceMode;}) +#define ANY_WORLD_HAS_RACE_MODE(worlds) std::ranges::any_of(worlds, [](const World& world){return world.getSettings().progression_dungeons == ProgressionDungeons::RaceMode;}) using LocationPool = std::vector; using EntrancePool = std::vector; @@ -57,8 +57,8 @@ class World INVALID_GAME_ITEM, BAD_REQUIREMENT, PLANDOMIZER_ERROR, - DUNGEON_HAS_NO_RACE_MODE_LOCATION, - NOT_ENOUGH_RACE_MODE_LOCATIONS, + DUNGEON_HAS_NO_BOSS_LOCATION, + NOT_ENOUGH_BOSS_LOCATIONS, INVALID_DUNGEON_NAME, DATA_FILE_ERROR, UNKNOWN, @@ -91,7 +91,7 @@ class World void determineChartMappings(); WorldLoadingError determineProgressionLocations(); WorldLoadingError setDungeonLocations(WorldPool& worlds); - WorldLoadingError determineRaceModeDungeons(WorldPool& worlds); + WorldLoadingError determineRequiredDungeons(WorldPool& worlds); int loadWorld(const fspath& worldFilePath, const fspath& macrosFilePath, const fspath& locationDataPath, const fspath& itemDataPath, const fspath& areaDataPath); Entrance* getEntrance(const std::string& parentArea, const std::string& connectedArea); Entrance* getEntrance(Area* parentArea, Area* connectedArea); @@ -125,7 +125,7 @@ class World std::unordered_map eventMap = {}; std::unordered_map reverseEventMap = {}; std::map dungeons = {}; - LocationPool raceModeLocations = {}; + LocationPool bossLocations = {}; std::list goalLocations = {}; std::map> barrenRegions = {}; std::list korlHints = {}; diff --git a/logic/data/location_data.yaml b/logic/data/location_data.yaml index 8e442e10..0d0e1618 100644 --- a/logic/data/location_data.yaml +++ b/logic/data/location_data.yaml @@ -328,7 +328,7 @@ Spanish: Isla del Diablo - Contenedor de corazón de Kranos French: Forteresse Maudite - Réceptacle de Cœur du Roi Cuirasse Original Item: Heart Container - Race Mode Location: true + Boss Location: true Stage ID: 2 Goal Names: English: Helmaroc King @@ -3737,7 +3737,7 @@ Spanish: Cueva del Dragón - Contenedor de Corazón de Gohma French: Caverne du Dragon - Réceptacle de Cœur de Gohma Original Item: Heart Container - Race Mode Location: true + Boss Location: true Stage ID: 3 Goal Names: English: Gohma @@ -3980,7 +3980,7 @@ Spanish: Bosque Prohibido - Contenedor de Corazón de Vilipendulia French: Bois Défendus - Réceptacle de Cœur de Karle Demos Original Item: Heart Container - Race Mode Location: true + Boss Location: true Stage ID: 4 Goal Names: English: Kalle Demos @@ -4199,7 +4199,7 @@ Spanish: Torre de los Dioses - Contenedor de Corazón de Deus Probatur French: Tour des Dieux - Réceptacle de Cœur de Gordon Original Item: Heart Container - Race Mode Location: true + Boss Location: true Stage ID: 5 Goal Names: English: Gohdan @@ -4442,7 +4442,7 @@ Spanish: Templo de la Tierra - Contenedor de Corazón de Fati Triputis French: Temple de la Terre - Réceptacle de Cœur de Jay Harla Original Item: Heart Container - Race Mode Location: true + Boss Location: true Stage ID: 6 Goal Names: English: Jalhalla @@ -4661,7 +4661,7 @@ Spanish: Templo del Viento - Contenedor de Corazón de Verminus French: Temple du Vent - Réceptacle de Cœur de Gayla Original Item: Heart Container - Race Mode Location: true + Boss Location: true Stage ID: 7 Goal Names: English: Molgera diff --git a/tweaks.cpp b/tweaks.cpp index 0ab69ded..43baa5b5 100644 --- a/tweaks.cpp +++ b/tweaks.cpp @@ -2223,7 +2223,7 @@ TweakError update_required_bosses(const World& world) { uint16_t required_boss_stages_bitset = 0x0000; for (const auto& [dungeonName, dungeon] : world.dungeons) { if (dungeon.isRequiredDungeon) { - required_boss_stages_bitset |= (1 << dungeon.raceModeLocation->stageId); + required_boss_stages_bitset |= (1 << dungeon.bossLocation->stageId); } } @@ -2762,8 +2762,8 @@ TweakError show_dungeon_markers_on_chart(World& world) { if (dungeon.isRequiredDungeon) { // Get island of associated boss room - auto raceModeArea = dungeon.raceModeLocation->accessPoints.front()->area; - auto bossIslands = raceModeArea->findIslands(); + const auto& bossArea = dungeon.bossLocation->accessPoints.front()->area; + const auto& bossIslands = bossArea->findIslands(); const std::string& islandName = bossIslands.front(); room_numbers.emplace(islandNameToRoomNum(islandName));