From 2698d453bb07a2933bc89574fcd4093797a27141 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Mon, 13 Nov 2023 13:25:37 -0500 Subject: [PATCH] More gap-bridging (#3323) * Initial StaticData and RandoItem class definitions * Initial implementation of RandoItem class. * Rerranges RandoItem Constructor parameters The parameters were rearranged for easy copy-paste from the GET_ITEM macro calls later on. * Switches static data from map to static array. Array is all that is needed, since the item list will be contiguous and indexed by the RandomizerGet Enum values. * Defines part of the randomizer item list. * Adds more item class instances to item_list.cpp Up through bottles, many more items still to go. * Adds song items * Adds Maps and Compasses to the item_list * Added Key Items to item_list * Added Key Rings to item_list * Added Dungeon Rewards to item_list * Adds generic items and refills to item_list * Adds shop items, triforce, and hints Also added constructors that put the GET_ITEM_NONE data in for these items, since there is no corresponding GetItemEntry for them. * Adds in the stages of progressive items These are present for GetItemEntry purposes, and aren't really meant to be used in seed generation (unless we find a need for it later on.) * Remove GetItemEntry data from progressive items * Moves/adds function definitions to item/item_list * Refactors GetItemEntry data It's now a pointer to memory instantiated on the heap in the constructor. These are shared pointers so the memory is freed if any of the item instances get deconstructed (which they shouldn't but just in case.) * Adds item class member for if item is progressive * Removes unneeded stuff from initializer list macro * Replaces relevant `uint32_t`s w/ `RandomizerGet`s Also replaces calls to the ItemTable method with StaticData::RetrieveItem * Switches our runtime code to use the new itemList. * Changes just enough hint gen code to compile * Initial Definition of Location Class * Initial Implementation of Location * Fixes some names and definitions. * Extracts ActorID and SceneID enums to separate files. This allows importing them without causing weird conflicts in cpp files when importing the z64scene.h and z64actor.h files directly. Now you can just import z64scene_enum.h and z64actor_enum.h instead. The two old files also import these new files so that existing setups still work as expected. * Replaces the forward definitions with the new imports. * Adds missing data for RandomizerCheckObjects. * Definition and first entry of locationTable * Added Mido's House Locations * Added locations up through lost woods. * Adds in Hyrule Field locations. * Adds Lake Hylia locations * Adds location name comments * Adds Gerudo Valley Locations * Adds Gerudo Fortress locations. * Adds the Wasteland and Collosus locations * Adds Market locations * Adds Hyrule Castle locations. * Adds Kakariko and Graveyard locations. * Adds Death Mountain checks. * Adds Goron City locations * Adds Death Mountain Crater locations * Adds Zora's River locations * Added Zora's Domain Locations. * Added Zora's Fountain locations * Adds Lon Lon Ranch locations. * Adds Deku Tree locations * Adds Dodongo's Cavern Locations. * Adds Jabu Jabu's Belly Locations * Adds Forest Temple Locations * Adds Fire Temple Locations * Adds Water Temple Locations * Added Spirit Temple Locations * Some of shadow temple locations. * Adds remaining Shadow Temple locations * Fixes a leftover merge conflict * Adds Bottom of the Well locations. * Adds Ice Cavern locations * Adds GTG locations. * Adds Ganon's Castle and Tower locations * Adds dungeon Gold Skulltula locations. * Adds Overworld Gold Skulltula locations * Adds dungeon reward locations * Adds Heart Container Locations * Adds Cutscene and Song locations * Adds Cow locations * Adds Shop locations. * Adds hint locations * Adds function for retrieving the Location data. * Initial definition of ItemLocation structure for tracking runtime data * First push on converting code to use new location definitions * Changes hints to use the new tables * Further conversion of hints to new definitions. * Adds new Hint and Location IDs to area tables * Moves areaTable to use new RandomizerRegion keys * Removal of 3drando/item_location files. * Uses new RandomizerRegion keys in entrance.cpp * Final push for removal of massive keys.hpp enum * Uses new SceneID Enum Values * Remove RandomizerCheckObject structs in favor of new location list. * Fix a few stragglers to successfully build * Rename of RandoItem to just Item, but in the Rando namespace * Adds static hints (Light Arrows, Altar text, etc) to the new Hint table. * More hint related fixes/edits * small fix for #include path * Fix various miscellaneous issues related to seed gen and spoiler parsing. * Handle progressive items correctly. * Fixes some hint generation logic * Fix a few GetItemEntry niche bugs. * Adds missing shop GI Entries * Formatting fixes * small formatting fix * Namespace StaticData under Rando * Added a note about a potential use-after-free. I confirmed the actual pointer in question isn't currently being used, but I added the note as a reminder to fix it later and/or as a warning to anyone who changes how the return value is used. * Fixes missing location table entries * Fixes LUS submodule and removes now-unused code * Resolves weird duplicate definition issue * Fix missing include It was missed because not being included wasn't an issue on Windows. * Fixes error present on Linux builds * Fixes some issues with excluding locations * Updates the Resolve Exclusion conflicts function not sure if actually used, will look into that more later * Removes some duplicate RGs * More fixes of duplicate RG values. * Fix a few duplication issues in the check tracker. * Fix progressive bombchus. * Minor typo fix, shouldn't really be affecting anything though * Should fix some of the remaining check tracker issues. * oops wrong boolean operator * Fix skulltulas in the check tracker. * oops, missing comma * re-formatting of HintStone locations * Fixes issue when picking up second Progressive Bullet Bag * Hide bombchu bowling bombchus * Fixes missed skullScene in location_list * Reformats shop items * Re-formats cow checks * reformat song locations * reformat "cutscene" checks * reformat heart container locaitons * reformat Boss/Dungeon reward checks * Hide Triforce Completed if not playing Triforce Hunt * Fixes incorrect chest param * reformat GS Tokens locations and cuts down on duplicate data * reformat Ganons Castle checks * reformat GTG check locations * Prevents Gift from Raoru from appearing in the check tracker * more reformatting (botw, ice cavern, shadow temple) * Should fix a couple more check tracker checks * reformat spirit temple checks * reformat water and fire temple checks * fix RC_ZR_GS_ABOVE_BRIDGE flag typo * reformat Forest Temple checks * Fix RC_LW_TRADE_ODD_POTION in check tracker * reformat child dungeon locations * reformat overworld locations * reformat item entries * New Item Override system * use new ItemOverrides and use ItemLocations table for getting items * Saves/Loads directly from/to new ItemLocation table with overrides for traps * Removes gSaveContext.itemLocations * Don't load spoiler file on boot automatically. Currently this means the old spoiler will have to be manually dropped or a new one generated in order to make a new rando file. Next I want to make it so that: 1. The Randomizer Quest button on the file select menu is always unlocked, even if a spoiler is not loaded. 2. If it's selected and a spoiler is not loaded, a menu will appear that asks if you want to generate a new seed or re-generate the previous one (if a spoiler file is present). 3. On choosing to generate a new one, you may also get an in-game menu to quickly apply a preset before generating (not sure if I'm going that far just yet). 4. After that, a seed is generated and you are taken back to the file select screen with the new file present. 5. If a seed is generated via the menu ahead of time, the CVar for loading the spoiler file will be set, but the spoiler file will not be parsed. All the data needed to actually play the randomizer at that point is already in memory and in the save file (or at least I'll make it so that it is if it isn't already). 6. If a spoiler file is dropped over the window, the spoiler file is loaded, but it will only be parsed to get the seed and the settings, then the playthrough will be generated from scratch with that data. Thus allowing for hints to be in the user's language of choice no matter what language the spoiler file was generated in. 7. Additionally, there will be a plandomizer mode that, if enabled, causes dragging and dropping a spoiler file to read the entire spoiler file instead of just the seed, and making a new file will use the data from there instead of generating a new seed. This in particular may be expanded to have a "plando file" that contains more info than a spoiler file would normally have, such as cosmetic data and a more fleshed out custom message syntax for various types of custom hints and whatnot. But that will be probably much later. * Auto-gen rando seed when making a new rando file. Also adds new logic for displaying the seed hash icons. Now, it is displayed in the following situations: 1. On the confirmation page when loading a rando save, the hash icons for *that save* are displayed. 2. On the name select screen after generating a seed, the hash icons for the seed that was just generated will be shown. 3. If you have dragged a spoiler log onto the window, the hash icons for that seed will be displayed while randomizer is selected on the quest select screen. Currently the spoiler is just ignored, as the logic for pulling the settings from the spoiler file and regenerating the same seed has not been coded yet. * Fix a few typos/bugs * Partial conversion to new Settings/Option class * Further conversion to new settings/options classes * New settings struct (not fully working, need to wire it up to SaveManager) * Move save files to new settings struct. Also fixes MQ options to match 3drando * Fixes some spoilerfile related issues * Cleans up now unused arrays * Fixes some unhandled entries in parse settings switch case * Reimplements parsing of settings on file drop to re-generate seeds * Move merchantPrices into ItemLocation tables. * Move hints to new struct * Fixes a few seed gen bugs surrounding hints * Fix treasure chest game. * Relocate Entrance Shuffle code into ctx * Move entrances to new context at runtime * Remove now unused code from SaveContext and randomizer.cpp/.h * Fix non-windows builds? * Moves Dungeon Quests to new context * Move trials into new context * Whoops, forgot to construct the Trials in the context. * Fixes accidental nullptr reference * Fixes bug with saving MQ dungeons * Implements plando mode and removes now unused code. Largely untested, expect some bugfixes. * prevent a multiple definition bug * another attempt to fix the gSeedTextures multiple def error * Fixes some minor hint issues from conflict resolution * Some additional glue needed for merge * Fixes another couple of miscellaneous issues/inconsistencies. * A few french corrections * Makes CVar gRandomizeWarpSongText match the checkbox default value. --- soh/include/z64save.h | 38 - soh/soh/Enhancements/enemyrandomizer.cpp | 3 +- soh/soh/Enhancements/mods.cpp | 3 +- .../randomizer/3drando/dungeon.cpp | 682 ----- .../randomizer/3drando/dungeon.hpp | 109 - .../randomizer/3drando/entrance.cpp | 1300 -------- .../randomizer/3drando/entrance.hpp | 289 -- .../Enhancements/randomizer/3drando/fill.cpp | 167 +- .../randomizer/3drando/hint_list.cpp | 93 +- .../Enhancements/randomizer/3drando/hints.cpp | 367 ++- .../Enhancements/randomizer/3drando/hints.hpp | 35 +- .../randomizer/3drando/item_pool.cpp | 327 +- .../randomizer/3drando/item_pool.hpp | 1 - .../randomizer/3drando/location_access.cpp | 49 +- .../randomizer/3drando/location_access.hpp | 36 +- .../locacc_bottom_of_the_well.cpp | 48 +- .../location_access/locacc_castle_town.cpp | 26 +- .../location_access/locacc_death_mountain.cpp | 35 +- .../location_access/locacc_deku_tree.cpp | 30 +- .../locacc_dodongos_cavern.cpp | 40 +- .../location_access/locacc_fire_temple.cpp | 54 +- .../location_access/locacc_forest_temple.cpp | 42 +- .../location_access/locacc_ganons_castle.cpp | 84 +- .../locacc_gerudo_training_grounds.cpp | 30 +- .../location_access/locacc_gerudo_valley.cpp | 28 +- .../location_access/locacc_hyrule_field.cpp | 10 +- .../location_access/locacc_ice_cavern.cpp | 20 +- .../locacc_jabujabus_belly.cpp | 28 +- .../location_access/locacc_kakariko.cpp | 26 +- .../location_access/locacc_lost_woods.cpp | 28 +- .../location_access/locacc_shadow_temple.cpp | 66 +- .../location_access/locacc_spirit_temple.cpp | 92 +- .../location_access/locacc_water_temple.cpp | 60 +- .../location_access/locacc_zoras_domain.cpp | 18 +- .../Enhancements/randomizer/3drando/logic.cpp | 151 +- .../Enhancements/randomizer/3drando/menu.cpp | 24 +- .../randomizer/3drando/playthrough.cpp | 32 +- .../randomizer/3drando/rando_main.cpp | 6 +- .../randomizer/3drando/settings.cpp | 2652 ----------------- .../randomizer/3drando/settings.hpp | 1179 -------- .../Enhancements/randomizer/3drando/shops.cpp | 212 +- .../randomizer/3drando/spoiler_log.cpp | 313 +- .../randomizer/3drando/starting_inventory.cpp | 199 +- .../Enhancements/randomizer/3drando/text.hpp | 18 + .../Enhancements/randomizer/3drando/trial.cpp | 26 - .../Enhancements/randomizer/3drando/trial.hpp | 51 - soh/soh/Enhancements/randomizer/context.cpp | 426 ++- soh/soh/Enhancements/randomizer/context.h | 56 +- soh/soh/Enhancements/randomizer/dungeon.cpp | 783 +++++ soh/soh/Enhancements/randomizer/dungeon.h | 96 + soh/soh/Enhancements/randomizer/entrance.cpp | 1597 ++++++++++ soh/soh/Enhancements/randomizer/entrance.h | 151 + soh/soh/Enhancements/randomizer/hint.cpp | 6 +- soh/soh/Enhancements/randomizer/hint.h | 11 +- soh/soh/Enhancements/randomizer/item.cpp | 43 +- soh/soh/Enhancements/randomizer/item.h | 8 +- soh/soh/Enhancements/randomizer/item_list.cpp | 2 +- .../Enhancements/randomizer/item_location.cpp | 46 +- .../Enhancements/randomizer/item_location.h | 53 +- .../Enhancements/randomizer/item_override.cpp | 30 + .../Enhancements/randomizer/item_override.h | 23 + soh/soh/Enhancements/randomizer/location.cpp | 1 + soh/soh/Enhancements/randomizer/option.cpp | 144 + soh/soh/Enhancements/randomizer/option.h | 100 + soh/soh/Enhancements/randomizer/rando_hash.h | 6 +- .../Enhancements/randomizer/randomizer.cpp | 1560 ++-------- soh/soh/Enhancements/randomizer/randomizer.h | 40 +- .../Enhancements/randomizer/randomizerTypes.h | 139 +- .../randomizer/randomizer_check_tracker.cpp | 28 +- .../randomizer/randomizer_entrance.c | 15 +- .../randomizer_entrance_tracker.cpp | 21 +- soh/soh/Enhancements/randomizer/savefile.cpp | 2 +- soh/soh/Enhancements/randomizer/settings.cpp | 1798 +++++++++++ soh/soh/Enhancements/randomizer/settings.h | 49 + soh/soh/Enhancements/randomizer/trial.cpp | 82 + soh/soh/Enhancements/randomizer/trial.h | 47 + soh/soh/OTRGlobals.cpp | 83 +- soh/soh/OTRGlobals.h | 18 +- soh/soh/SaveManager.cpp | 434 ++- soh/soh/SaveManager.h | 1 + soh/soh/SohMenuBar.cpp | 8 + soh/src/code/z_sram.c | 3 +- .../gamestates/ovl_file_choose/file_choose.h | 1 + .../ovl_file_choose/z_file_choose.c | 201 +- .../ovl_file_choose/z_file_nameset_PAL.c | 4 + 85 files changed, 7692 insertions(+), 9551 deletions(-) delete mode 100644 soh/soh/Enhancements/randomizer/3drando/dungeon.cpp delete mode 100644 soh/soh/Enhancements/randomizer/3drando/dungeon.hpp delete mode 100644 soh/soh/Enhancements/randomizer/3drando/entrance.cpp delete mode 100644 soh/soh/Enhancements/randomizer/3drando/entrance.hpp delete mode 100644 soh/soh/Enhancements/randomizer/3drando/settings.cpp delete mode 100644 soh/soh/Enhancements/randomizer/3drando/settings.hpp delete mode 100644 soh/soh/Enhancements/randomizer/3drando/trial.cpp delete mode 100644 soh/soh/Enhancements/randomizer/3drando/trial.hpp create mode 100644 soh/soh/Enhancements/randomizer/dungeon.cpp create mode 100644 soh/soh/Enhancements/randomizer/dungeon.h create mode 100644 soh/soh/Enhancements/randomizer/entrance.cpp create mode 100644 soh/soh/Enhancements/randomizer/entrance.h create mode 100644 soh/soh/Enhancements/randomizer/item_override.cpp create mode 100644 soh/soh/Enhancements/randomizer/item_override.h create mode 100644 soh/soh/Enhancements/randomizer/option.cpp create mode 100644 soh/soh/Enhancements/randomizer/option.h create mode 100644 soh/soh/Enhancements/randomizer/settings.cpp create mode 100644 soh/soh/Enhancements/randomizer/settings.h create mode 100644 soh/soh/Enhancements/randomizer/trial.cpp create mode 100644 soh/soh/Enhancements/randomizer/trial.h diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 9458f28c7..e3d1dd8d1 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -147,11 +147,6 @@ typedef struct { /* 0x24 */ s32 tempCollectFlags; } FaroresWindData; // size = 0x28 -typedef struct { - RandomizerCheck check; - RandomizerGetData get; -} ItemLocationRando; - typedef struct { RandomizerCheck check; RandomizerCheck hintedCheck; @@ -161,11 +156,6 @@ typedef struct { char hintText[200]; } HintLocationRando; -typedef struct { - RandomizerSettingKey key; - u8 value; -} RandoSetting; - typedef struct { /* 0x0000 */ s32 entranceIndex; // start of `save` substruct, originally called "memory" /* 0x0004 */ s32 linkAge; // 0: Adult; 1: Child (see enum `LinkAge`) @@ -286,7 +276,6 @@ typedef struct { /* */ uint8_t questId; /* */ uint32_t isBossRushPaused; /* */ uint8_t bossRushOptions[BOSSRUSH_OPTIONS_AMOUNT]; - /* */ u8 mqDungeonCount; /* */ u8 pendingIceTrapCount; /* */ SohStats sohStats; /* */ FaroresWindData backupFW; @@ -294,33 +283,6 @@ typedef struct { // #endregion // #region SOH [Randomizer] // Upstream TODO: Move these to their own struct or name to more obviously specific to Randomizer - /* */ RandoSetting randoSettings[300]; - /* */ ItemLocationRando itemLocations[RC_MAX]; - /* */ HintLocationRando hintLocations[50]; - /* */ EntranceOverride entranceOverrides[ENTRANCE_OVERRIDES_MAX_COUNT]; - /* */ char childAltarText[250]; - /* */ char adultAltarText[750]; - /* */ RandomizerCheck rewardCheck[9]; - /* */ char ganonHintText[300]; - /* */ char gregHintText[250]; - /* */ char ganonText[250]; - /* */ char dampeText[150]; - /* */ char sheikText[200]; - /* */ char sariaText[150]; - /* */ char warpMinuetText[100]; - /* */ char warpBoleroText[100]; - /* */ char warpSerenadeText[100]; - /* */ char warpRequiemText[100]; - /* */ char warpNocturneText[100]; - /* */ char warpPreludeText[100]; - /* */ RandomizerCheck masterSwordHintCheck; - /* */ RandomizerCheck lightArrowHintCheck; - /* */ RandomizerCheck sariaCheck; - /* */ RandomizerCheck gregCheck; - /* */ RandomizerCheck dampeCheck; - /* */ char inputSeed[1024]; - /* */ u32 finalSeed; - /* */ u8 seedIcons[5]; /* */ u16 randomizerInf[10]; /* */ u16 adultTradeItems; /* */ u8 triforcePiecesCollected; diff --git a/soh/soh/Enhancements/enemyrandomizer.cpp b/soh/soh/Enhancements/enemyrandomizer.cpp index a89400844..65dfb5f0d 100644 --- a/soh/soh/Enhancements/enemyrandomizer.cpp +++ b/soh/soh/Enhancements/enemyrandomizer.cpp @@ -2,6 +2,7 @@ #include "functions.h" #include "macros.h" #include "soh/Enhancements/randomizer/3drando/random.hpp" +#include "soh/Enhancements/randomizer/context.h" #include "soh/Enhancements/enhancementTypes.h" #include "variables.h" @@ -234,7 +235,7 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t *actorId, f32 *po EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) { if (CVarGetInteger("gRandomizedEnemies", ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) { - uint32_t finalSeed = seed + (IS_RANDO ? gSaveContext.finalSeed : gSaveContext.sohStats.fileCreatedAt); + uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed() : gSaveContext.sohStats.fileCreatedAt); Random_Init(finalSeed); } diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index a4a654f84..73110a7d6 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -604,7 +604,8 @@ void UpdateMirrorModeState(int32_t sceneNum) { (sceneNum == SCENE_GANON_BOSS); if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) { - uint32_t seed = sceneNum + (IS_RANDO ? gSaveContext.finalSeed : gSaveContext.sohStats.fileCreatedAt); + uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed() + : gSaveContext.sohStats.fileCreatedAt); Random_Init(seed); } diff --git a/soh/soh/Enhancements/randomizer/3drando/dungeon.cpp b/soh/soh/Enhancements/randomizer/3drando/dungeon.cpp deleted file mode 100644 index 511217036..000000000 --- a/soh/soh/Enhancements/randomizer/3drando/dungeon.cpp +++ /dev/null @@ -1,682 +0,0 @@ -#include "dungeon.hpp" - -#include "category.hpp" -#include "pool_functions.hpp" -#include "../context.h" -#include "../static_data.h" - -namespace Dungeon { - -DungeonInfo::DungeonInfo(std::string name_, RandomizerHintTextKey hintKey_, RandomizerGet map_, RandomizerGet compass_, - RandomizerGet smallKey_, RandomizerGet keyRing_, RandomizerGet bossKey_, - uint8_t vanillaKeyCount_, uint8_t mqKeyCount_, std::vector vanillaLocations_, - std::vector mqLocations_, std::vector sharedLocations_, - std::vector bossRoomLocations_) - : name(std::move(name_)), hintKey(hintKey_), map(map_), compass(compass_), smallKey(smallKey_), keyRing(keyRing_), - bossKey(bossKey_), vanillaKeyCount(vanillaKeyCount_), mqKeyCount(mqKeyCount_), - vanillaLocations(std::move(vanillaLocations_)), mqLocations(std::move(mqLocations_)), - sharedLocations(std::move(sharedLocations_)), bossRoomLocations(std::move(bossRoomLocations_)) { -} - -DungeonInfo::~DungeonInfo() = default; - -RandomizerHintTextKey DungeonInfo::GetHintKey() const { - return hintKey; -} - -RandomizerGet DungeonInfo::GetSmallKey() const { - return smallKey; -} - -RandomizerGet DungeonInfo::GetKeyRing() const { - return keyRing; -} - -RandomizerGet DungeonInfo::GetMap() const { - return map; -} - -RandomizerGet DungeonInfo::GetCompass() const { - return compass; -} - -RandomizerGet DungeonInfo::GetBossKey() const { - return bossKey; -} - -void DungeonInfo::PlaceVanillaMap() { - if (map == RG_NONE) { - return; - } - - auto dungeonLocations = GetDungeonLocations(); - auto mapLocation = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) { - return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cVanillaMap); - })[0]; - Rando::Context::GetInstance()->PlaceItemInLocation(mapLocation, map); -} - -void DungeonInfo::PlaceVanillaCompass() { - if (compass == RG_NONE) { - return; - } - - auto dungeonLocations = GetDungeonLocations(); - auto compassLocation = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) { - return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cVanillaCompass); - })[0]; - Rando::Context::GetInstance()->PlaceItemInLocation(compassLocation, compass); -} - -void DungeonInfo::PlaceVanillaBossKey() { - if (bossKey == RG_NONE || bossKey == RG_GANONS_CASTLE_BOSS_KEY) { - return; - } - - auto dungeonLocations = GetDungeonLocations(); - auto bossKeyLocation = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) { - return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cVanillaBossKey); - })[0]; - Rando::Context::GetInstance()->PlaceItemInLocation(bossKeyLocation, bossKey); -} - -void DungeonInfo::PlaceVanillaSmallKeys() { - if (smallKey == RG_NONE) { - return; - } - - auto dungeonLocations = GetDungeonLocations(); - auto smallKeyLocations = FilterFromPool(dungeonLocations, [](const RandomizerCheck loc) { - return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cVanillaSmallKey); - }); - for (auto location : smallKeyLocations) { - Rando::Context::GetInstance()->PlaceItemInLocation(location, smallKey); - } -} - -// Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla) -std::vector DungeonInfo::GetDungeonLocations() const { - auto locations = masterQuest ? mqLocations : vanillaLocations; - AddElementsToPool(locations, sharedLocations); - AddElementsToPool(locations, bossRoomLocations); - return locations; -} - -// Gets all dungeon locations (MQ + Vanilla) -std::vector DungeonInfo::GetEveryLocation() const { - auto locations = vanillaLocations; - AddElementsToPool(locations, mqLocations); - AddElementsToPool(locations, sharedLocations); - AddElementsToPool(locations, bossRoomLocations); - return locations; -} - -DungeonInfo DekuTree = - DungeonInfo("Deku Tree", RHT_DEKU_TREE, RG_DEKU_TREE_MAP, RG_DEKU_TREE_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0, - { - // Vanilla Locations - RC_DEKU_TREE_MAP_CHEST, - RC_DEKU_TREE_COMPASS_CHEST, - RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, - RC_DEKU_TREE_BASEMENT_CHEST, - RC_DEKU_TREE_SLINGSHOT_CHEST, - RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, - RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, - RC_DEKU_TREE_GS_BASEMENT_GATE, - RC_DEKU_TREE_GS_BASEMENT_VINES, - RC_DEKU_TREE_GS_COMPASS_ROOM, - }, - { - // MQ Locations - RC_DEKU_TREE_MQ_MAP_CHEST, - RC_DEKU_TREE_MQ_COMPASS_CHEST, - RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, - RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, - RC_DEKU_TREE_MQ_BASEMENT_CHEST, - RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, - RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, - RC_DEKU_TREE_MQ_DEKU_SCRUB, - RC_DEKU_TREE_MQ_GS_LOBBY, - RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, - RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, - RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, - }, - {}, - { - // Boss Room Locations - RC_DEKU_TREE_QUEEN_GOHMA_HEART, - RC_QUEEN_GOHMA, - }); - -DungeonInfo DodongosCavern = DungeonInfo("Dodongo's Cavern", RHT_DODONGOS_CAVERN, RG_DODONGOS_CAVERN_MAP, - RG_DODONGOS_CAVERN_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0, - { - // Vanilla Locations - RC_DODONGOS_CAVERN_MAP_CHEST, - RC_DODONGOS_CAVERN_COMPASS_CHEST, - RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, - RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, - RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, - RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, - RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, - RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, - RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, - RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, - RC_DODONGOS_CAVERN_GS_SCARECROW, - RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, - RC_DODONGOS_CAVERN_GS_BACK_ROOM, - RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, - }, - { - // MQ Locations - RC_DODONGOS_CAVERN_MQ_MAP_CHEST, - RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, - RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, - RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, - RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, - RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, - RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, - RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, - RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, - RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, - RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, - RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, - RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, - RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, - RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, - }, - {}, - { - // Boss Room Locations - RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, - RC_DODONGOS_CAVERN_KING_DODONGO_HEART, - RC_KING_DODONGO, - }); - -DungeonInfo JabuJabusBelly = DungeonInfo("Jabu Jabu's Belly", RHT_JABU_JABUS_BELLY, RG_JABU_JABUS_BELLY_MAP, - RG_JABU_JABUS_BELLY_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0, - { - // Vanilla Locations - RC_JABU_JABUS_BELLY_MAP_CHEST, - RC_JABU_JABUS_BELLY_COMPASS_CHEST, - RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, - RC_JABU_JABUS_BELLY_DEKU_SCRUB, - RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, - RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, - RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, - RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, - }, - { - // MQ Locations - RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, - RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, - RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, - RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, - RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, - RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, - RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, - RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, - RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, - RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, - RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, - RC_JABU_JABUS_BELLY_MQ_COW, - RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, - RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, - RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, - RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, - }, - {}, - { - // Boss Room Locations - RC_JABU_JABUS_BELLY_BARINADE_HEART, - RC_BARINADE, - }); - -DungeonInfo ForestTemple = - DungeonInfo("Forest Temple", RHT_FOREST_TEMPLE, RG_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_COMPASS, - RG_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_BOSS_KEY, 5, 6, - { - // Vanilla Locations - RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, - RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, - RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, - RC_FOREST_TEMPLE_MAP_CHEST, - RC_FOREST_TEMPLE_WELL_CHEST, - RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, - RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, - RC_FOREST_TEMPLE_BOSS_KEY_CHEST, - RC_FOREST_TEMPLE_FLOORMASTER_CHEST, - RC_FOREST_TEMPLE_BOW_CHEST, - RC_FOREST_TEMPLE_RED_POE_CHEST, - RC_FOREST_TEMPLE_BLUE_POE_CHEST, - RC_FOREST_TEMPLE_BASEMENT_CHEST, - RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, - RC_FOREST_TEMPLE_GS_FIRST_ROOM, - RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, - RC_FOREST_TEMPLE_GS_LOBBY, - RC_FOREST_TEMPLE_GS_BASEMENT, - }, - { - // MQ Locations - RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, - RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, - RC_FOREST_TEMPLE_MQ_BOW_CHEST, - RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, - RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, - RC_FOREST_TEMPLE_MQ_WELL_CHEST, - RC_FOREST_TEMPLE_MQ_MAP_CHEST, - RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, - RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, - RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, - RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, - RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, - RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, - RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, - RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, - RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, - RC_FOREST_TEMPLE_MQ_GS_WELL, - }, - {}, - { - // Boss Room Locations - RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, - RC_PHANTOM_GANON, - }); - -DungeonInfo FireTemple = DungeonInfo("Fire Temple", RHT_FIRE_TEMPLE, RG_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_COMPASS, - RG_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_BOSS_KEY, 8, 5, - { - // Vanilla Locations - RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, - RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, - RC_FIRE_TEMPLE_BOSS_KEY_CHEST, - RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, - RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, - RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, - RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, - RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, - RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, - RC_FIRE_TEMPLE_SCARECROW_CHEST, - RC_FIRE_TEMPLE_MAP_CHEST, - RC_FIRE_TEMPLE_COMPASS_CHEST, - RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, - RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, - RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, - RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, - RC_FIRE_TEMPLE_GS_BOULDER_MAZE, - RC_FIRE_TEMPLE_GS_SCARECROW_TOP, - RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, - }, - { - // MQ Locations - RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, - RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, - RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, - RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, - RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, - RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, - RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, - RC_FIRE_TEMPLE_MQ_MAP_CHEST, - RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, - RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, - RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, - RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, - RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, - RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, - RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, - RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, - RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, - }, - {}, - { - // Boos Room Locations - RC_FIRE_TEMPLE_VOLVAGIA_HEART, - RC_VOLVAGIA, - }); - -DungeonInfo WaterTemple = - DungeonInfo("Water Temple", RHT_WATER_TEMPLE, RG_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_COMPASS, - RG_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_BOSS_KEY, 6, 2, - { - // Vanilla Locations - RC_WATER_TEMPLE_MAP_CHEST, - RC_WATER_TEMPLE_COMPASS_CHEST, - RC_WATER_TEMPLE_TORCHES_CHEST, - RC_WATER_TEMPLE_DRAGON_CHEST, - RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, - RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, - RC_WATER_TEMPLE_CRACKED_WALL_CHEST, - RC_WATER_TEMPLE_BOSS_KEY_CHEST, - RC_WATER_TEMPLE_LONGSHOT_CHEST, - RC_WATER_TEMPLE_RIVER_CHEST, - RC_WATER_TEMPLE_GS_BEHIND_GATE, - RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, - RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, - RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, - RC_WATER_TEMPLE_GS_RIVER, - }, - { - // MQ Locations - RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, - RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, - RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, - RC_WATER_TEMPLE_MQ_COMPASS_CHEST, - RC_WATER_TEMPLE_MQ_MAP_CHEST, - RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, - RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, - RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, - RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, - RC_WATER_TEMPLE_MQ_GS_RIVER, - RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, - }, - {}, - { - // Boss Room Locations - RC_WATER_TEMPLE_MORPHA_HEART, - RC_MORPHA, - }); - -DungeonInfo SpiritTemple = - DungeonInfo("Spirit Temple", RHT_SPIRIT_TEMPLE, RG_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_COMPASS, - RG_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_BOSS_KEY, 5, 7, - { - // Vanilla Locations - RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, - RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, - RC_SPIRIT_TEMPLE_COMPASS_CHEST, - RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, - RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, - RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, - RC_SPIRIT_TEMPLE_MAP_CHEST, - RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, - RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, - RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, - RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, - RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, - RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, - RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, - RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, - RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, - RC_SPIRIT_TEMPLE_TOPMOST_CHEST, - RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, - RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, - RC_SPIRIT_TEMPLE_GS_LOBBY, - RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, - RC_SPIRIT_TEMPLE_GS_METAL_FENCE, - }, - { - // MQ Locations - RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, - RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, - RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, - RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, - RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, - RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, - RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, - RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, - RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, - RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, - RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, - RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, - RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, - RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, - RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, - RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, - RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, - RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, - RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, - RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, - RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, - RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, - RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, - RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, - RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, - }, - { - // Shared Locations - RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, - RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, - }, - { - // Boss Room Locations - RC_SPIRIT_TEMPLE_TWINROVA_HEART, - RC_TWINROVA, - }); - -DungeonInfo ShadowTemple = - DungeonInfo("Shadow Temple", RHT_SHADOW_TEMPLE, RG_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_COMPASS, - RG_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_BOSS_KEY, 5, 6, - { - // Vanilla Locations - RC_SHADOW_TEMPLE_MAP_CHEST, - RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, - RC_SHADOW_TEMPLE_COMPASS_CHEST, - RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, - RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, - RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, - RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, - RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, - RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, - RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, - RC_SHADOW_TEMPLE_WIND_HINT_CHEST, - RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, - RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, - RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, - RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, - RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, - RC_SHADOW_TEMPLE_FREESTANDING_KEY, - RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, - RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, - RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, - RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, - RC_SHADOW_TEMPLE_GS_NEAR_SHIP, - }, - { - // MQ Locations - RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, - RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, - RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, - RC_SHADOW_TEMPLE_MQ_MAP_CHEST, - RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, - RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, - RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, - RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, - RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, - RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, - RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, - RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, - RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, - RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, - RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, - RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, - RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, - RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, - RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, - RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, - RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, - RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, - RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, - RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, - RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, - }, - {}, - { - // Boss Room Locations - RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, - RC_BONGO_BONGO, - }); - -DungeonInfo BottomOfTheWell = - DungeonInfo("Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, RG_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_COMPASS, - RG_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_KEY_RING, RG_NONE, 3, 2, - { - // Vanilla Locations - RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, - RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, - RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, - RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, - RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, - RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, - RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, - RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, - RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, - RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, - RC_BOTTOM_OF_THE_WELL_MAP_CHEST, - RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, - RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, - RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, - RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, - RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, - RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, - }, - { - // MQ Locations - RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, - RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, - RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, - RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, - RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, - RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, - RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, - RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, - }, - {}, {}); - -DungeonInfo IceCavern = - DungeonInfo("Ice Cavern", RHT_ICE_CAVERN, RG_ICE_CAVERN_MAP, RG_ICE_CAVERN_COMPASS, RG_NONE, RG_NONE, RG_NONE, 0, 0, - { - // Vanilla Locations - RC_ICE_CAVERN_MAP_CHEST, - RC_ICE_CAVERN_COMPASS_CHEST, - RC_ICE_CAVERN_IRON_BOOTS_CHEST, - RC_ICE_CAVERN_FREESTANDING_POH, - RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, - RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, - RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, - }, - { - // MQ Locations - RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, - RC_ICE_CAVERN_MQ_COMPASS_CHEST, - RC_ICE_CAVERN_MQ_MAP_CHEST, - RC_ICE_CAVERN_MQ_FREESTANDING_POH, - RC_ICE_CAVERN_MQ_GS_SCARECROW, - RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, - RC_ICE_CAVERN_MQ_GS_RED_ICE, - }, - { - // Shared Locations - RC_SHEIK_IN_ICE_CAVERN, - }, - {}); - -DungeonInfo GerudoTrainingGrounds = - DungeonInfo("Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, RG_NONE, RG_NONE, - RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, RG_GERUDO_TRAINING_GROUNDS_KEY_RING, RG_NONE, 9, 3, - { - // Vanilla Locations - RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, - RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, - RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, - RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, - RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, - RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, - RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, - RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, - RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, - RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, - RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, - RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, - RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, - RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, - RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, - RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, - RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, - RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, - RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, - RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, - RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, - RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, - }, - { - // MQ Locations - RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, - RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, - }, - {}, {}); - -DungeonInfo GanonsCastle = - DungeonInfo("Ganon's Castle", RHT_GANONS_CASTLE, RG_NONE, RG_NONE, RG_GANONS_CASTLE_SMALL_KEY, - RG_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_BOSS_KEY, 2, 3, - { - // Vanilla Locations - RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, - RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, - RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, - RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, - RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, - RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, - RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, - RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, - RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, - RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, - RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, - RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, - RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, - RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, - RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, - RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, - RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, - RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, - RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, - }, - { - // MQ Locations - RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, - RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, - RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, - RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, - RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, - RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, - RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, - RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, - RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, - RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, - RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, - RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, - RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, - RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, - RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, - RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, - RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, - RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, - }, - { - // Shared Locations - RC_GANONS_TOWER_BOSS_KEY_CHEST, - RC_GANON, - }, - {}); - -const DungeonArray dungeonList = { - &DekuTree, &DodongosCavern, &JabuJabusBelly, &ForestTemple, - &FireTemple, &WaterTemple, &SpiritTemple, &ShadowTemple, - &BottomOfTheWell, &IceCavern, &GerudoTrainingGrounds, &GanonsCastle, -}; - -} // namespace Dungeon diff --git a/soh/soh/Enhancements/randomizer/3drando/dungeon.hpp b/soh/soh/Enhancements/randomizer/3drando/dungeon.hpp deleted file mode 100644 index 93f3017d6..000000000 --- a/soh/soh/Enhancements/randomizer/3drando/dungeon.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "../randomizerTypes.h" - -namespace Dungeon { -class DungeonInfo { -public: - DungeonInfo(std::string name_, RandomizerHintTextKey hintKey_, RandomizerGet map_, RandomizerGet compass_, RandomizerGet smallKey_, - RandomizerGet keyRing_, RandomizerGet bossKey_, - uint8_t vanillaKeyCount_, uint8_t mqKeyCount_, - std::vector vanillaLocations_, - std::vector mqLocations_, - std::vector sharedLocations_, - std::vector bossRoomLocations_); - ~DungeonInfo(); - - const std::string& GetName() const { - return name; - } - - void SetMQ() { - masterQuest = true; - } - - void ClearMQ() { - masterQuest = false; - } - - bool IsMQ() const { - return masterQuest; - } - - void SetKeyRing() { - hasKeyRing = true; - } - - void ClearKeyRing() { - hasKeyRing = false; - } - - bool HasKeyRing() const { - return hasKeyRing; - } - - bool IsVanilla() const { - return !masterQuest; - } - - uint8_t GetSmallKeyCount() const { - return (masterQuest) ? mqKeyCount : vanillaKeyCount; - } - - RandomizerHintTextKey GetHintKey() const; - RandomizerGet GetSmallKey() const; - RandomizerGet GetKeyRing() const; - RandomizerGet GetMap() const; - RandomizerGet GetCompass() const; - RandomizerGet GetBossKey() const; - - void PlaceVanillaMap(); - void PlaceVanillaCompass(); - void PlaceVanillaBossKey(); - void PlaceVanillaSmallKeys(); - - // Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla) - std::vector GetDungeonLocations() const; - - // Gets all dungeon locations (MQ + Vanilla) - std::vector GetEveryLocation() const; - -private: - std::string name; - RandomizerHintTextKey hintKey; - RandomizerGet map; - RandomizerGet compass; - RandomizerGet smallKey; - RandomizerGet keyRing; - RandomizerGet bossKey; - uint8_t vanillaKeyCount; - uint8_t mqKeyCount; - bool masterQuest = false; - bool hasKeyRing = false; - std::vector vanillaLocations; - std::vector mqLocations; - std::vector sharedLocations; - std::vector bossRoomLocations; -}; - -extern DungeonInfo DekuTree; -extern DungeonInfo DodongosCavern; -extern DungeonInfo JabuJabusBelly; -extern DungeonInfo ForestTemple; -extern DungeonInfo FireTemple; -extern DungeonInfo WaterTemple; -extern DungeonInfo SpiritTemple; -extern DungeonInfo ShadowTemple; -extern DungeonInfo BottomOfTheWell; -extern DungeonInfo IceCavern; -extern DungeonInfo GerudoTrainingGrounds; -extern DungeonInfo GanonsCastle; - -using DungeonArray = std::array; - -extern const DungeonArray dungeonList; -} // namespace Dungeon diff --git a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp deleted file mode 100644 index ccdf516f9..000000000 --- a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp +++ /dev/null @@ -1,1300 +0,0 @@ -#include "entrance.hpp" - -#include "fill.hpp" -#include "settings.hpp" -#include "item_pool.hpp" -#include "../context.h" -#include "spoiler_log.hpp" -#include "hints.hpp" -#include "location_access.hpp" -#include "soh/Enhancements/randomizer/static_data.h" - -#include -#include -#include -#include -#include - -std::list entranceOverrides = {}; -bool noRandomEntrances = false; -static bool entranceShuffleFailure = false; -static int totalRandomizableEntrances = 0; -static int curNumRandomizedEntrances = 0; - -typedef struct { - EntranceType type; - RandomizerRegion parentRegion; - RandomizerRegion connectedRegion; - int16_t index; - int16_t blueWarp; -} EntranceLinkInfo; - -EntranceLinkInfo NO_RETURN_ENTRANCE = {EntranceType::None, RR_NONE, RR_NONE, -1}; - -typedef struct { - std::list targetRegions; - std::list allowedTypes; -} PriorityEntrance; - //primary, secondary -using EntranceInfoPair = std::pair; -using EntrancePair = std::pair; -using EntrancePools = std::map>; - -//The entrance randomization algorithm used here is a direct copy of -//the algorithm used in the original N64 randomizer (except now in C++ instead -//of python). It may be easier to understand the algorithm by looking at the -//base randomizer's code instead: -// https://github.com/TestRunnerSRL/OoT-Randomizer/blob/Dev/EntranceShuffle.py - -// Updates the user on how many entrances are currently shuffled -static void DisplayEntranceProgress() { - std::string dots = "."; - float progress = (float)curNumRandomizedEntrances / (float)totalRandomizableEntrances; - if (progress > 0.33) { - dots += "."; - } else { - dots += " "; - } - if (progress > 0.66) { - dots += "."; - } else { - dots += " "; - } - printf("\x1b[7;29H%s", dots.c_str()); - #ifdef ENABLE_DEBUG - if (curNumRandomizedEntrances == totalRandomizableEntrances) { - Areas::DumpWorldGraph("Finish Validation"); - } - #endif -} - -void SetAllEntrancesData(std::vector& entranceShuffleTable) { - for (auto& entrancePair: entranceShuffleTable) { - - auto& forwardEntry = entrancePair.first; - auto& returnEntry = entrancePair.second; - - //set data - Entrance* forwardEntrance = AreaTable(forwardEntry.parentRegion)->GetExit(forwardEntry.connectedRegion); - forwardEntrance->SetIndex(forwardEntry.index); - forwardEntrance->SetBlueWarp(forwardEntry.blueWarp); - forwardEntrance->SetType(forwardEntry.type); - forwardEntrance->SetAsPrimary(); - - // When decouple entrances is on, mark it for entrances except boss rooms - if (Settings::DecoupleEntrances && forwardEntry.type != EntranceType::ChildBoss && - forwardEntry.type != EntranceType::AdultBoss) { - forwardEntrance->SetDecoupled(); - } - - if (returnEntry.parentRegion != RR_NONE) { - Entrance* returnEntrance = AreaTable(returnEntry.parentRegion)->GetExit(returnEntry.connectedRegion); - returnEntrance->SetIndex(returnEntry.index); - returnEntrance->SetBlueWarp(returnEntry.blueWarp); - returnEntrance->SetType(returnEntry.type); - forwardEntrance->BindTwoWay(returnEntrance); - - // Mark reverse entrance as decoupled - if (Settings::DecoupleEntrances && returnEntry.type != EntranceType::ChildBoss && - returnEntry.type != EntranceType::AdultBoss) { - returnEntrance->SetDecoupled(); - } - } - } -} - -static std::vector AssumeEntrancePool(std::vector& entrancePool) { - std::vector assumedPool = {}; - for (Entrance* entrance : entrancePool) { - totalRandomizableEntrances++; - Entrance* assumedForward = entrance->AssumeReachable(); - if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) { - Entrance* assumedReturn = entrance->GetReverse()->AssumeReachable(); - if (!(Settings::MixedEntrancePools && (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)))) { - auto type = entrance->GetType(); - if (((type == EntranceType::Dungeon || type == EntranceType::GrottoGrave) && entrance->GetReverse()->GetName() != "Spirit Temple Entryway -> Desert Colossus From Spirit Entryway") || - (type == EntranceType::Interior && Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL))) { - // In most cases, Dungeon, Grotto/Grave and Simple Interior exits shouldn't be assumed able to give access to their parent region - assumedReturn->SetCondition([]{return false;}); - } - } - assumedForward->BindTwoWay(assumedReturn); - } - assumedPool.push_back(assumedForward); - } - return assumedPool; -} - -static std::vector BuildOneWayTargets(std::vector typesToInclude, std::vector> exclude = {}/*, target_region_names*/) { - std::vector oneWayEntrances = {}; - // Get all entrances of the specified type - for (EntranceType poolType : typesToInclude) { - AddElementsToPool(oneWayEntrances, GetShuffleableEntrances(poolType, false)); - } - // Filter out any that are passed in the exclusion list - FilterAndEraseFromPool(oneWayEntrances, [&exclude](Entrance* entrance){ - std::pair entranceBeingChecked (entrance->GetParentRegionKey(), entrance->GetConnectedRegionKey()); - return ElementInContainer(entranceBeingChecked, exclude); - }); - - // The code below is part of the function in ootr, but no use of the function ever provides target_region_names - // if target_region_names: - // return [entrance.get_new_target() for entrance in valid_one_way_entrances - // if entrance.connected_region.name in target_region_names] - - std::vector newTargets = {}; - for (Entrance* entrance : oneWayEntrances) { - newTargets.push_back(entrance->GetNewTarget()); - } - return newTargets; -} - -//returns restrictive entrances and soft entrances in an array of size 2 (restrictive vector is index 0, soft is index 1) -static std::array, 2> SplitEntrancesByRequirements(std::vector& entrancesToSplit, std::vector& assumedEntrances) { - //First, disconnect all root assumed entrances and save which regions they were originally connected to, so we can reconnect them later - std::map originalConnectedRegions = {}; - std::set entrancesToDisconnect = {}; - for (Entrance* entrance : assumedEntrances) { - entrancesToDisconnect.insert(entrance); - if (entrance->GetReverse() != nullptr) { - entrancesToDisconnect.insert(entrance->GetReverse()); - } - } - - //disconnect each entrance temporarily to find restrictive vs soft entrances - //soft entrances are ones that can be accessed by both ages (child/adult) at both times of day (day/night) - //restrictive entrances are ones that do not meet this criteria - for (Entrance* entrance : entrancesToDisconnect) { - if (entrance->GetConnectedRegionKey() != RR_NONE) { - originalConnectedRegions[entrance] = entrance->Disconnect(); - } - } - - std::vector restrictiveEntrances = {}; - std::vector softEntrances = {}; - - Logic::LogicReset(); - // Apply the effects of all advancement items to search for entrance accessibility - std::vector items = - FilterFromPool(ItemPool, [](const RandomizerGet i){ return Rando::StaticData::RetrieveItem(i).IsAdvancement();}); - for (RandomizerGet unplacedItem : items) { - Rando::StaticData::RetrieveItem(unplacedItem).ApplyEffect(); - } - // run a search to see what's accessible - GetAccessibleLocations({}); - - for (Entrance* entrance : entrancesToSplit) { - // if an entrance is accessible at all times of day by both ages, it's a soft entrance with no restrictions - if (entrance->ConditionsMet(true)) { - softEntrances.push_back(entrance); - } else { - restrictiveEntrances.push_back(entrance); - } - } - - //Reconnect all disconnected entrances - for (Entrance* entrance : entrancesToDisconnect) { - entrance->Connect(originalConnectedRegions[entrance]); - } - - return {restrictiveEntrances, softEntrances}; -} - -static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::vector& rollbacks) { - - //Entrances shouldn't connect to their own scene, fail in this situation - if (entrance->GetParentRegion()->scene != "" && entrance->GetParentRegion()->scene == target->GetConnectedRegion()->scene) { - auto message = "Entrance " + entrance->GetName() + " attempted to connect with own scene target " + target->to_string() + ". Connection failed.\n"; - SPDLOG_DEBUG(message); - return false; - } - - // One way entrances shouldn't lead to the same scene as other already chosen one way entrances - auto type = entrance->GetType(); - const std::vector oneWayTypes = {EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong}; - if (ElementInContainer(type, oneWayTypes)) { - for (auto& rollback : rollbacks) { - if (rollback.first->GetConnectedRegion()->scene == target->GetConnectedRegion()->scene) { - auto message = "A one way entrance already leads to " + target->to_string() + ". Connection failed.\n"; - SPDLOG_DEBUG(message); - return false; - } - } - } - - return true; -} - -//Change connections between an entrance and a target assumed entrance, in order to test the connections afterwards if necessary -static void ChangeConnections(Entrance* entrance, Entrance* targetEntrance) { - auto message = "Attempting to connect " + entrance->GetName() + " to " + targetEntrance->to_string() + "\n"; - SPDLOG_DEBUG(message); - entrance->Connect(targetEntrance->Disconnect()); - entrance->SetReplacement(targetEntrance->GetReplacement()); - if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) { - targetEntrance->GetReplacement()->GetReverse()->Connect(entrance->GetReverse()->GetAssumed()->Disconnect()); - targetEntrance->GetReplacement()->GetReverse()->SetReplacement(entrance->GetReverse()); - } -} - -// In the event that we need to retry shuffling an entire group we can restore the -// original connections to reset the entrance and target entrance. -static void RestoreConnections(Entrance* entrance, Entrance* targetEntrance) { - targetEntrance->Connect(entrance->Disconnect()); - entrance->SetReplacement(nullptr); - if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) { - entrance->GetReverse()->GetAssumed()->Connect(targetEntrance->GetReplacement()->GetReverse()->Disconnect()); - targetEntrance->GetReplacement()->GetReverse()->SetReplacement(nullptr); - } -} - -static void DeleteTargetEntrance(Entrance* targetEntrance) { - if (targetEntrance->GetConnectedRegionKey() != RR_NONE) { - targetEntrance->Disconnect(); - } - if (targetEntrance->GetParentRegionKey() != RR_NONE) { - targetEntrance->GetParentRegion()->RemoveExit(targetEntrance); - targetEntrance->SetParentRegion(RR_NONE); - } -} - -static void ConfirmReplacement(Entrance* entrance, Entrance* targetEntrance) { - DeleteTargetEntrance(targetEntrance); - if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) { - auto replacedReverse = targetEntrance->GetReplacement()->GetReverse(); - DeleteTargetEntrance(replacedReverse->GetReverse()->GetAssumed()); - } -} - -// Returns whether or not we can affirm the entrance can never be accessed as the given age -static bool EntranceUnreachableAs(Entrance* entrance, uint8_t age, std::vector& alreadyChecked) { - - if (entrance == nullptr) { - SPDLOG_DEBUG("Entrance is nullptr in EntranceUnreachableAs()"); - return true; - } - - alreadyChecked.push_back(entrance); - auto type = entrance->GetType(); - - // The following cases determine when we say an entrance is not safe to affirm unreachable as the given age - if (type == EntranceType::WarpSong || type == EntranceType::Overworld) { - // Note that we consider all overworld entrances as potentially accessible as both ages, to be completely safe - return false; - } else if (type == EntranceType::OwlDrop) { - return age == AGE_ADULT; - } else if (type == EntranceType::Spawn && entrance->GetConnectedRegionKey() == RR_KF_LINKS_HOUSE) { - return age == AGE_ADULT; - } else if (type == EntranceType::Spawn && entrance->GetConnectedRegionKey() == RR_TEMPLE_OF_TIME) { - return age == AGE_CHILD; - } - - // Other entrances such as Interior, Dungeon or Grotto are fine unless they have a parent which is one of the above cases - // Recursively check parent entrances to verify that they are also not reachable as the wrong age - auto& parentEntrances = entrance->GetParentRegion()->entrances; - for (Entrance* parentEntrance : parentEntrances) { - - //if parentEntrance is in alreadyChecked, then continue - if (ElementInContainer(parentEntrance, alreadyChecked)) { - continue; - } - - bool unreachable = EntranceUnreachableAs(parentEntrance, age, alreadyChecked); - if (!unreachable) { - return false; - } - } - - return true; -} - -static bool ValidateWorld(Entrance* entrancePlaced) { - SPDLOG_DEBUG("Validating world\n"); - - //check certain conditions when certain types of ER are enabled - EntranceType type = EntranceType::None; - if (entrancePlaced != nullptr) { - type = entrancePlaced->GetType(); - } - - bool checkPoeCollectorAccess = (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)) && (entrancePlaced == nullptr || Settings::MixedEntrancePools || - type == EntranceType::Interior || type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn || type == EntranceType::WarpSong || type == EntranceType::OwlDrop); - bool checkOtherEntranceAccess = (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL) || Settings::ShuffleOverworldSpawns) && (entrancePlaced == nullptr || Settings::MixedEntrancePools || - type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn || type == EntranceType::WarpSong || type == EntranceType::OwlDrop); - - // Search the world to verify that all necessary conditions are still being held - // Conditions will be checked during the search and any that fail will be figured out - // afterwards - Logic::LogicReset(); - GetAccessibleLocations({}, SearchMode::ValidateWorld, "", checkPoeCollectorAccess, checkOtherEntranceAccess); - - if (!Settings::DecoupleEntrances) { - // Unless entrances are decoupled, we don't want the player to end up through certain entrances as the wrong age - // This means we need to hard check that none of the relevant entrances are ever reachable as that age - // This is mostly relevant when mixing entrance pools or shuffling special interiors (such as windmill or kak potion shop) - // Warp Songs and Overworld Spawns can also end up inside certain indoors so those need to be handled as well - std::array childForbidden = {"OGC Great Fairy Fountain -> Castle Grounds", "GV Carpenter Tent -> GV Fortress Side", "Ganon's Castle Entryway -> Castle Grounds From Ganon's Castle"}; - std::array adultForbidden = {"HC Great Fairy Fountain -> Castle Grounds", "HC Storms Grotto -> Castle Grounds"}; - - auto allShuffleableEntrances = GetShuffleableEntrances(EntranceType::All, false); - for (auto& entrance: allShuffleableEntrances) { - - std::vector alreadyChecked = {}; - - if (entrance->IsShuffled()) { - if (entrance->GetReplacement() != nullptr) { - - auto replacementName = entrance->GetReplacement()->GetName(); - alreadyChecked.push_back(entrance->GetReplacement()->GetReverse()); - - if (ElementInContainer(replacementName, childForbidden) && !EntranceUnreachableAs(entrance, AGE_CHILD, alreadyChecked)) { - auto message = replacementName + " is replaced by an entrance with a potential child access\n"; - SPDLOG_DEBUG(message); - return false; - } else if (ElementInContainer(replacementName, adultForbidden) && !EntranceUnreachableAs(entrance, AGE_ADULT, alreadyChecked)) { - auto message = replacementName + " is replaced by an entrance with a potential adult access\n"; - SPDLOG_DEBUG(message); - return false; - } - } - } else { - auto name = entrance->GetName(); - alreadyChecked.push_back(entrance->GetReverse()); - - if (ElementInContainer(name, childForbidden) && !EntranceUnreachableAs(entrance, AGE_CHILD, alreadyChecked)) { - auto message = name + " is potentially accessible as child\n"; - SPDLOG_DEBUG(message); - return false; - } else if (ElementInContainer(name, adultForbidden) && !EntranceUnreachableAs(entrance, AGE_ADULT, alreadyChecked)) { - auto message = name + " is potentially accessible as adult\n"; - SPDLOG_DEBUG(message); - return false; - } - } - } - } - - if (Settings::ShuffleInteriorEntrances.IsNot(SHUFFLEINTERIORS_OFF) && Settings::GossipStoneHints.IsNot(HINTS_NO_HINTS) && - (entrancePlaced == nullptr || type == EntranceType::Interior || type == EntranceType::SpecialInterior)) { - //When cows are shuffled, ensure both Impa's House entrances are in the same hint area because the cow is reachable from both sides - if (Settings::ShuffleCows) { - auto impasHouseFrontHintRegion = GetHintRegionHintKey(RR_KAK_IMPAS_HOUSE); - auto impasHouseBackHintRegion = GetHintRegionHintKey(RR_KAK_IMPAS_HOUSE_BACK); - if (impasHouseFrontHintRegion != RHT_NONE && impasHouseBackHintRegion != RHT_NONE && impasHouseBackHintRegion != RHT_LINKS_POCKET && impasHouseFrontHintRegion != RHT_LINKS_POCKET && impasHouseBackHintRegion != impasHouseFrontHintRegion) { - auto message = "Kak Impas House entrances are not in the same hint area\n"; - SPDLOG_DEBUG(message); - return false; - } - } - } - - // If all locations aren't reachable, that means that one of the conditions failed when searching - if (!Rando::Context::GetInstance()->allLocationsReachable) { - if (checkOtherEntranceAccess) { - // At least one valid starting region with all basic refills should be reachable without using any items at the beginning of the seed - if (!AreaTable(RR_KOKIRI_FOREST)->HasAccess() && !AreaTable(RR_KAKARIKO_VILLAGE)->HasAccess()) { - SPDLOG_DEBUG("Invalid starting area\n"); - return false; - } - - // Check that a region where time passes is always reachable as both ages without having collected any items - if (!Areas::HasTimePassAccess(AGE_CHILD) || !Areas::HasTimePassAccess(AGE_ADULT)) { - SPDLOG_DEBUG("Time passing is not guaranteed as both ages\n"); - return false; - } - - // The player should be able to get back to ToT after going through time, without having collected any items - // This is important to ensure that the player never loses access to the pedestal after going through time - if (Settings::ResolvedStartingAge == AGE_CHILD && !AreaTable(RR_TEMPLE_OF_TIME)->Adult()) { - SPDLOG_DEBUG("Path to Temple of Time as adult is not guaranteed\n"); - return false; - } else if (Settings::ResolvedStartingAge == AGE_ADULT && !AreaTable(RR_TEMPLE_OF_TIME)->Child()) { - SPDLOG_DEBUG("Path to Temple of Time as child is not guaranteed\n"); - return false; - } - } - - // The Big Poe shop should always be accessible as adult without the need to use any bottles - // This is important to ensure that players can never lock their only bottles by filling them with Big Poes they can't sell - if (checkPoeCollectorAccess) { - if (!AreaTable(RR_MARKET_GUARD_HOUSE)->Adult()) { - SPDLOG_DEBUG("Big Poe Shop access is not guarenteed as adult\n"); - return false; - } - } - SPDLOG_DEBUG("All Locations NOT REACHABLE\n"); - return false; - } - return true; -} - -static bool ReplaceEntrance(Entrance* entrance, Entrance* target, std::vector& rollbacks) { - - if (!AreEntrancesCompatible(entrance, target, rollbacks)) { - return false; - } - ChangeConnections(entrance, target); - if (ValidateWorld(entrance)) { - #ifdef ENABLE_DEBUG - std::string ticks = std::to_string(svcGetSystemTick()); - auto message = "Dumping World Graph at " + ticks + "\n"; - //SPDLOG_DEBUG(message); - //Areas::DumpWorldGraph(ticks); - #endif - rollbacks.push_back(EntrancePair{entrance, target}); - curNumRandomizedEntrances++; - DisplayEntranceProgress(); - return true; - } else { - #ifdef ENABLE_DEBUG - std::string ticks = std::to_string(svcGetSystemTick()); - auto message = "Dumping World Graph at " + ticks + "\n"; - //SPDLOG_DEBUG(message); - //Areas::DumpWorldGraph(ticks); - #endif - if (entrance->GetConnectedRegionKey() != RR_NONE) { - RestoreConnections(entrance, target); - } - } - DisplayEntranceProgress(); - return false; -} - -// Connect one random entrance from entrance pools to one random target in the respective target pool. -// Entrance chosen will have one of the allowed types. -// Target chosen will lead to one of the allowed regions. -static bool PlaceOneWayPriorityEntrance(std::string priorityName, std::list& allowedRegions, std::list& allowedTypes, std::vector& rollbacks, EntrancePools oneWayEntrancePools, EntrancePools oneWayTargetEntrancePools) { - // Combine the entrances for allowed types in one list. - // Shuffle this list. - // Pick the first one not already set, not adult spawn, that has a valid target entrance. - // Assemble then clear entrances from the pool and target pools as appropriate. - std::vector availPool = {}; - for (auto& pool : oneWayEntrancePools) { - auto entranceType = pool.first; - if (ElementInContainer(entranceType, allowedTypes)) { - AddElementsToPool(availPool, pool.second); - } - } - Shuffle(availPool); - - for (Entrance* entrance : availPool) { - if (entrance->GetReplacement() != nullptr) { - continue; - } - // Only allow Adult Spawn as sole Nocturne access if hints != mask. - // Otherwise, child access is required here (adult access assumed or guaranteed later). - if (entrance->GetParentRegionKey() == RR_ADULT_SPAWN) { - if (priorityName != "Nocturne" || Settings::GossipStoneHints.Is(HINTS_MASK_OF_TRUTH)) { - continue; - } - } - // If not shuffling dungeons, Nocturne requires adult access - if (!Settings::ShuffleDungeonEntrances && priorityName == "Nocturne") { - if (entrance->GetType() != EntranceType::WarpSong && entrance->GetParentRegionKey() != RR_ADULT_SPAWN) { - continue; - } - } - for (Entrance* target : oneWayTargetEntrancePools[entrance->GetType()]) { - RandomizerRegion targetRegionKey = target->GetConnectedRegionKey(); - if (targetRegionKey != RR_NONE && ElementInContainer(targetRegionKey, allowedRegions)) { - if (ReplaceEntrance(entrance, target, rollbacks)) { - // Return once the entrance has been replaced - return true; - } - } - } - } - #ifdef ENABLE_DEBUG - auto message = "ERROR: Unable to place priority one-way entrance for " + priorityName + "\n"; - SPDLOG_DEBUG(message); - PlacementLog_Write(); - #endif - return false; -} - -// Once the first entrance to Impas House has been placed, try to place the next one immediately to reduce chances of failure. -static bool PlaceOtherImpasHouseEntrance(std::vector entrances, std::vector targetEntrances, std::vector& rollbacks) { - // Get the other impas house entrance - auto otherImpaTargets = FilterFromPool(targetEntrances, [](const Entrance* target) { - return (target->GetConnectedRegionKey() == RR_KAK_IMPAS_HOUSE || - target->GetConnectedRegionKey() == RR_KAK_IMPAS_HOUSE_BACK); - }); - if (otherImpaTargets.empty()) { - return true; - } - - Entrance* otherImpaTarget = otherImpaTargets[0]; - auto m = "Now Placing Other Impa Target: " + otherImpaTarget->GetName() + "\n"; - SPDLOG_DEBUG(m); - RandomizerRegion otherImpaRegion = otherImpaTarget->GetConnectedRegionKey() != RR_KAK_IMPAS_HOUSE_BACK - ? RR_KAK_IMPAS_HOUSE_BACK - : RR_KAK_IMPAS_HOUSE; - for (Entrance* entrance : entrances) { - // If the entrance is already connected or it doesn't have the same hint region as the already placed impas house entrance, then don't try to use it - if (entrance->GetConnectedRegionKey() != RR_NONE || - (GetHintRegionHintKey(otherImpaRegion) != GetHintRegionHintKey(entrance->GetParentRegionKey()))) { - continue; - } - // If the placement succeeds, we return true - if (ReplaceEntrance(entrance, otherImpaTarget, rollbacks)) { - return true; - } - } - SPDLOG_DEBUG("No available entrances for placing other impa region.\n"); - return false; -} - -// Shuffle entrances by placing them instead of entrances in the provided target entrances list -static bool ShuffleEntrances(std::vector& entrances, std::vector& targetEntrances, std::vector& rollbacks) { - - Shuffle(entrances); - - //place all entrances in the pool, validating after every placement - for (Entrance* entrance : entrances) { - if (entrance->GetConnectedRegionKey() != RR_NONE) { - continue; - } - - Shuffle(targetEntrances); - for (Entrance* target : targetEntrances) { - if (target->GetConnectedRegionKey() == RR_NONE) { - continue; - } - - // Store whether or not we're about to attempt placing an entrance to Impas House - bool attemptedImpasHousePlacement = (target->GetConnectedRegionKey() == RR_KAK_IMPAS_HOUSE || target->GetConnectedRegionKey() == RR_KAK_IMPAS_HOUSE_BACK); - - if (ReplaceEntrance(entrance, target, rollbacks)) { - // If shuffle cows is enabled and the last entrance was one to Impas House, - // then immediately attempt to place the other entrance to Impas House - if (Settings::ShuffleCows && attemptedImpasHousePlacement) { - if (!PlaceOtherImpasHouseEntrance(entrances, targetEntrances, rollbacks)) { - return false; - } - } - break; - } - } - - if (entrance->GetConnectedRegionKey() == RR_NONE) { - return false; - } - } - - //all entrances were validly connected - return true; -} - -static bool ShuffleOneWayPriorityEntrances(std::map& oneWayPriorities, EntrancePools oneWayEntrancePools, EntrancePools oneWayTargetEntrancePools, int retryCount = 2) { - while (retryCount > 0) { - retryCount--; - std::vector rollbacks = {}; - - bool success = true; - for (auto& priority : oneWayPriorities) { - std::string key = priority.first; - auto& regions = priority.second.targetRegions; - auto& types = priority.second.allowedTypes; - success = PlaceOneWayPriorityEntrance(key, regions, types, rollbacks, oneWayEntrancePools, oneWayTargetEntrancePools); - if (!success) { - for (auto& pair : rollbacks) { - RestoreConnections(pair.first, pair.second); - } - break; - } - } - if (!success) { - continue; - } - // If there are no issues, log the connections and continue - for (auto& pair : rollbacks) { - ConfirmReplacement(pair.first, pair.second); - } - break; - } - - if (retryCount <= 0) { - SPDLOG_DEBUG("Entrance placement attempt count for one way priorities exceeded. Restarting randomization completely\n"); - entranceShuffleFailure = true; - return false; - } - return true; -} - -static void ShuffleEntrancePool(std::vector& entrancePool, std::vector& targetEntrances, int retryCount = 20) { - noRandomEntrances = false; - - auto splitEntrances = SplitEntrancesByRequirements(entrancePool, targetEntrances); - - auto& restrictiveEntrances = splitEntrances[0]; - auto& softEntrances = splitEntrances[1]; - - int retries = retryCount; - while (retries > 0) { - if (retries != retryCount) { - #ifdef ENABLE_DEBUG - std::string ticks = std::to_string(svcGetSystemTick()); - auto message = "Failed to connect entrances. Retrying " + std::to_string(retries) + " more times.\nDumping World Graph at " + ticks + "\n"; - SPDLOG_DEBUG(message); - //Areas::DumpWorldGraph(ticks); - #endif - } - retries--; - - std::vector rollbacks = {}; - - //Shuffle Restrictive Entrances first while more regions are available in - //order to heavily reduce the chances of the placement failing - bool success = ShuffleEntrances(restrictiveEntrances, targetEntrances, rollbacks); - if (success) { - success = ShuffleEntrances(softEntrances, targetEntrances, rollbacks); - if(!success) { - for (auto& pair : rollbacks) { - RestoreConnections(pair.first, pair.second); - curNumRandomizedEntrances--; - } - continue; - } - } else { - for (auto& pair : rollbacks) { - RestoreConnections(pair.first, pair.second); - curNumRandomizedEntrances--; - } - continue; - } - - //If there are no issues, log the connections and continue - for (auto& pair : rollbacks) { - ConfirmReplacement(pair.first, pair.second); - } - break; - } - - if (retries <= 0) { - SPDLOG_DEBUG("Entrance placement attempt count exceeded. Restarting randomization completely"); - entranceShuffleFailure = true; - } -} - -static void SetShuffledEntrances(EntrancePools entrancePools) { - for (auto& pool : entrancePools) { - for (Entrance* entrance : pool.second) { - entrance->SetAsShuffled(); - if (entrance->GetReverse() != nullptr) { - entrance->GetReverse()->SetAsShuffled(); - } - } - } -} - -//Process for setting up the shuffling of all entrances to be shuffled -int ShuffleAllEntrances() { - - totalRandomizableEntrances = 0; - curNumRandomizedEntrances = 0; - - std::vector entranceShuffleTable = { - // Parent Region Connected Region index blue warp - { { EntranceType::Dungeon, RR_KF_OUTSIDE_DEKU_TREE, RR_DEKU_TREE_ENTRYWAY, 0x0000 }, - { EntranceType::Dungeon, RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE, 0x0209, 0x0457 } }, - { { EntranceType::Dungeon, RR_DEATH_MOUNTAIN_TRAIL, RR_DODONGOS_CAVERN_ENTRYWAY, 0x0004 }, - { EntranceType::Dungeon, RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL, 0x0242, 0x047A } }, - { { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_JABU_JABUS_BELLY_ENTRYWAY, 0x0028 }, - { EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, 0x0221, 0x010E } }, - { { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, 0x0169 }, - { EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, 0x0215, 0x0608 } }, - { { EntranceType::Dungeon, RR_DMC_CENTRAL_LOCAL, RR_FIRE_TEMPLE_ENTRYWAY, 0x0165 }, - { EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, 0x024A, 0x0564 } }, - { { EntranceType::Dungeon, RR_LAKE_HYLIA, RR_WATER_TEMPLE_ENTRYWAY, 0x0010 }, - { EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA, 0x021D, 0x060C } }, - { { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, 0x0082 }, - { EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, 0x01E1, 0x0610 } }, - { { EntranceType::Dungeon, RR_GRAVEYARD_WARP_PAD_REGION, RR_SHADOW_TEMPLE_ENTRYWAY, 0x0037 }, - { EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, 0x0205, 0x0580 } }, - { { EntranceType::Dungeon, RR_KAKARIKO_VILLAGE, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, 0x0098 }, - { EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAKARIKO_VILLAGE, 0x02A6 } }, - { { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_ICE_CAVERN_ENTRYWAY, 0x0088 }, - { EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZORAS_FOUNTAIN, 0x03D4 } }, - { { EntranceType::Dungeon, RR_GERUDO_FORTRESS, RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, 0x0008 }, - { EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, RR_GERUDO_FORTRESS, 0x03A8 } }, - { { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, 0x0467 }, - { EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, 0x023D } }, - - { { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_MIDOS_HOUSE, 0x0433 }, - { EntranceType::Interior, RR_KF_MIDOS_HOUSE, RR_KOKIRI_FOREST, 0x0443 } }, - { { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_SARIAS_HOUSE, 0x0437 }, - { EntranceType::Interior, RR_KF_SARIAS_HOUSE, RR_KOKIRI_FOREST, 0x0447 } }, - { { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_HOUSE_OF_TWINS, 0x009C }, - { EntranceType::Interior, RR_KF_HOUSE_OF_TWINS, RR_KOKIRI_FOREST, 0x033C } }, - { { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KNOW_IT_ALL_HOUSE, 0x00C9 }, - { EntranceType::Interior, RR_KF_KNOW_IT_ALL_HOUSE, RR_KOKIRI_FOREST, 0x026A } }, - { { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KOKIRI_SHOP, 0x00C1 }, - { EntranceType::Interior, RR_KF_KOKIRI_SHOP, RR_KOKIRI_FOREST, 0x0266 } }, - { { EntranceType::Interior, RR_LAKE_HYLIA, RR_LH_LAB, 0x0043 }, - { EntranceType::Interior, RR_LH_LAB, RR_LAKE_HYLIA, 0x03CC } }, - { { EntranceType::Interior, RR_LH_FISHING_ISLAND, RR_LH_FISHING_HOLE, 0x045F }, - { EntranceType::Interior, RR_LH_FISHING_HOLE, RR_LH_FISHING_ISLAND, 0x0309 } }, - { { EntranceType::Interior, RR_GV_FORTRESS_SIDE, RR_GV_CARPENTER_TENT, 0x03A0 }, - { EntranceType::Interior, RR_GV_CARPENTER_TENT, RR_GV_FORTRESS_SIDE, 0x03D0 } }, - { { EntranceType::Interior, RR_MARKET_ENTRANCE, RR_MARKET_GUARD_HOUSE, 0x007E }, - { EntranceType::Interior, RR_MARKET_GUARD_HOUSE, RR_MARKET_ENTRANCE, 0x026E } }, - { { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_MASK_SHOP, 0x0530 }, - { EntranceType::Interior, RR_MARKET_MASK_SHOP, RR_THE_MARKET, 0x01D1 } }, - { { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BOMBCHU_BOWLING, 0x0507 }, - { EntranceType::Interior, RR_MARKET_BOMBCHU_BOWLING, RR_THE_MARKET, 0x03BC } }, - { { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_POTION_SHOP, 0x0388 }, - { EntranceType::Interior, RR_MARKET_POTION_SHOP, RR_THE_MARKET, 0x02A2 } }, - { { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_TREASURE_CHEST_GAME, 0x0063 }, - { EntranceType::Interior, RR_MARKET_TREASURE_CHEST_GAME, RR_THE_MARKET, 0x01D5 } }, - { { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_BOMBCHU_SHOP, 0x0528 }, - { EntranceType::Interior, RR_MARKET_BOMBCHU_SHOP, RR_MARKET_BACK_ALLEY, 0x03C0 } }, - { { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_MAN_IN_GREEN_HOUSE, 0x043B }, - { EntranceType::Interior, RR_MARKET_MAN_IN_GREEN_HOUSE, RR_MARKET_BACK_ALLEY, 0x0067 } }, - { { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_CARPENTER_BOSS_HOUSE, 0x02FD }, - { EntranceType::Interior, RR_KAK_CARPENTER_BOSS_HOUSE, RR_KAKARIKO_VILLAGE, 0x0349 } }, - { { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_HOUSE_OF_SKULLTULA, 0x0550 }, - { EntranceType::Interior, RR_KAK_HOUSE_OF_SKULLTULA, RR_KAKARIKO_VILLAGE, 0x04EE } }, - { { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_IMPAS_HOUSE, 0x039C }, - { EntranceType::Interior, RR_KAK_IMPAS_HOUSE, RR_KAKARIKO_VILLAGE, 0x0345 } }, - { { EntranceType::Interior, RR_KAK_IMPAS_LEDGE, RR_KAK_IMPAS_HOUSE_BACK, 0x05C8 }, - { EntranceType::Interior, RR_KAK_IMPAS_HOUSE_BACK, RR_KAK_IMPAS_LEDGE, 0x05DC } }, - { { EntranceType::Interior, RR_KAK_BACKYARD, RR_KAK_ODD_POTION_BUILDING, 0x0072 }, - { EntranceType::Interior, RR_KAK_ODD_POTION_BUILDING, RR_KAK_BACKYARD, 0x034D } }, - { { EntranceType::Interior, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_HOUSE, 0x030D }, - { EntranceType::Interior, RR_GRAVEYARD_DAMPES_HOUSE, RR_THE_GRAVEYARD, 0x0355 } }, - { { EntranceType::Interior, RR_GORON_CITY, RR_GC_SHOP, 0x037C }, - { EntranceType::Interior, RR_GC_SHOP, RR_GORON_CITY, 0x03FC } }, - { { EntranceType::Interior, RR_ZORAS_DOMAIN, RR_ZD_SHOP, 0x0380 }, - { EntranceType::Interior, RR_ZD_SHOP, RR_ZORAS_DOMAIN, 0x03C4 } }, - { { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TALONS_HOUSE, 0x004F }, - { EntranceType::Interior, RR_LLR_TALONS_HOUSE, RR_LON_LON_RANCH, 0x0378 } }, - { { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_STABLES, 0x02F9 }, - { EntranceType::Interior, RR_LLR_STABLES, RR_LON_LON_RANCH, 0x042F } }, - { { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TOWER, 0x05D0 }, - { EntranceType::Interior, RR_LLR_TOWER, RR_LON_LON_RANCH, 0x05D4 } }, - { { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BAZAAR, 0x052C }, - { EntranceType::Interior, RR_MARKET_BAZAAR, RR_THE_MARKET, 0x03B8 } }, - { { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_SHOOTING_GALLERY, 0x016D }, - { EntranceType::Interior, RR_MARKET_SHOOTING_GALLERY, RR_THE_MARKET, 0x01CD } }, - { { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_BAZAAR, 0x00B7 }, - { EntranceType::Interior, RR_KAK_BAZAAR, RR_KAKARIKO_VILLAGE, 0x0201 } }, - { { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_SHOOTING_GALLERY, 0x003B }, - { EntranceType::Interior, RR_KAK_SHOOTING_GALLERY, RR_KAKARIKO_VILLAGE, 0x0463 } }, - { { EntranceType::Interior, RR_DESERT_COLOSSUS, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, 0x0588 }, - { EntranceType::Interior, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, RR_DESERT_COLOSSUS, 0x057C } }, - { { EntranceType::Interior, RR_HYRULE_CASTLE_GROUNDS, RR_HC_GREAT_FAIRY_FOUNTAIN, 0x0578 }, - { EntranceType::Interior, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, 0x0340 } }, - { { EntranceType::Interior, RR_GANONS_CASTLE_GROUNDS, RR_OGC_GREAT_FAIRY_FOUNTAIN, 0x04C2 }, - { EntranceType::Interior, RR_OGC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, - 0x03E8 } }, // 0x3E8 is an unused entrance index repruposed to differentiate between the HC and OGC fairy - // fountain exits (normally they both use 0x340) - { { EntranceType::Interior, RR_DMC_LOWER_NEARBY, RR_DMC_GREAT_FAIRY_FOUNTAIN, 0x04BE }, - { EntranceType::Interior, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_LOWER_LOCAL, 0x0482 } }, - { { EntranceType::Interior, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_GREAT_FAIRY_FOUNTAIN, 0x0315 }, - { EntranceType::Interior, RR_DMT_GREAT_FAIRY_FOUNTAIN, RR_DEATH_MOUNTAIN_SUMMIT, 0x045B } }, - { { EntranceType::Interior, RR_ZORAS_FOUNTAIN, RR_ZF_GREAT_FAIRY_FOUNTAIN, 0x0371 }, - { EntranceType::Interior, RR_ZF_GREAT_FAIRY_FOUNTAIN, RR_ZORAS_FOUNTAIN, 0x0394 } }, - - { { EntranceType::SpecialInterior, RR_KOKIRI_FOREST, RR_KF_LINKS_HOUSE, 0x0272 }, - { EntranceType::SpecialInterior, RR_KF_LINKS_HOUSE, RR_KOKIRI_FOREST, 0x0211 } }, - { { EntranceType::SpecialInterior, RR_TOT_ENTRANCE, RR_TEMPLE_OF_TIME, 0x0053 }, - { EntranceType::SpecialInterior, RR_TEMPLE_OF_TIME, RR_TOT_ENTRANCE, 0x0472 } }, - { { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_WINDMILL, 0x0453 }, - { EntranceType::SpecialInterior, RR_KAK_WINDMILL, RR_KAKARIKO_VILLAGE, 0x0351 } }, - { { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_POTION_SHOP_FRONT, 0x0384 }, - { EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_FRONT, RR_KAKARIKO_VILLAGE, 0x044B } }, - { { EntranceType::SpecialInterior, RR_KAK_BACKYARD, RR_KAK_POTION_SHOP_BACK, 0x03EC }, - { EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_BACK, RR_KAK_BACKYARD, 0x04FF } }, - - // Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the - // grottoLoadTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c - // Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the - // grottoReturnTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c - { { EntranceType::GrottoGrave, RR_DESERT_COLOSSUS, RR_COLOSSUS_GROTTO, 0x0700 }, - { EntranceType::GrottoGrave, RR_COLOSSUS_GROTTO, RR_DESERT_COLOSSUS, 0x0800 } }, - { { EntranceType::GrottoGrave, RR_LAKE_HYLIA, RR_LH_GROTTO, 0x0701 }, - { EntranceType::GrottoGrave, RR_LH_GROTTO, RR_LAKE_HYLIA, 0x0801 } }, - { { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_STORMS_GROTTO, 0x0702 }, - { EntranceType::GrottoGrave, RR_ZR_STORMS_GROTTO, RR_ZORAS_RIVER, 0x0802 } }, - { { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_FAIRY_GROTTO, 0x0703 }, - { EntranceType::GrottoGrave, RR_ZR_FAIRY_GROTTO, RR_ZORAS_RIVER, 0x0803 } }, - { { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_OPEN_GROTTO, 0x0704 }, - { EntranceType::GrottoGrave, RR_ZR_OPEN_GROTTO, RR_ZORAS_RIVER, 0x0804 } }, - { { EntranceType::GrottoGrave, RR_DMC_LOWER_NEARBY, RR_DMC_HAMMER_GROTTO, 0x0705 }, - { EntranceType::GrottoGrave, RR_DMC_HAMMER_GROTTO, RR_DMC_LOWER_LOCAL, 0x0805 } }, - { { EntranceType::GrottoGrave, RR_DMC_UPPER_NEARBY, RR_DMC_UPPER_GROTTO, 0x0706 }, - { EntranceType::GrottoGrave, RR_DMC_UPPER_GROTTO, RR_DMC_UPPER_LOCAL, 0x0806 } }, - { { EntranceType::GrottoGrave, RR_GC_GROTTO_PLATFORM, RR_GC_GROTTO, 0x0707 }, - { EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, 0x0807 } }, - { { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, 0x0708 }, - { EntranceType::GrottoGrave, RR_DMT_STORMS_GROTTO, RR_DEATH_MOUNTAIN_TRAIL, 0x0808 } }, - { { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_COW_GROTTO, 0x0709 }, - { EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_SUMMIT, 0x0809 } }, - { { EntranceType::GrottoGrave, RR_KAK_BACKYARD, RR_KAK_OPEN_GROTTO, 0x070A }, - { EntranceType::GrottoGrave, RR_KAK_OPEN_GROTTO, RR_KAK_BACKYARD, 0x080A } }, - { { EntranceType::GrottoGrave, RR_KAKARIKO_VILLAGE, RR_KAK_REDEAD_GROTTO, 0x070B }, - { EntranceType::GrottoGrave, RR_KAK_REDEAD_GROTTO, RR_KAKARIKO_VILLAGE, 0x080B } }, - { { EntranceType::GrottoGrave, RR_HYRULE_CASTLE_GROUNDS, RR_HC_STORMS_GROTTO, 0x070C }, - { EntranceType::GrottoGrave, RR_HC_STORMS_GROTTO, RR_CASTLE_GROUNDS, 0x080C } }, - { { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_TEKTITE_GROTTO, 0x070D }, - { EntranceType::GrottoGrave, RR_HF_TEKTITE_GROTTO, RR_HYRULE_FIELD, 0x080D } }, - { { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_KAK_GROTTO, 0x070E }, - { EntranceType::GrottoGrave, RR_HF_NEAR_KAK_GROTTO, RR_HYRULE_FIELD, 0x080E } }, - { { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_FAIRY_GROTTO, 0x070F }, - { EntranceType::GrottoGrave, RR_HF_FAIRY_GROTTO, RR_HYRULE_FIELD, 0x080F } }, - { { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_MARKET_GROTTO, 0x0710 }, - { EntranceType::GrottoGrave, RR_HF_NEAR_MARKET_GROTTO, RR_HYRULE_FIELD, 0x0810 } }, - { { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_COW_GROTTO, 0x0711 }, - { EntranceType::GrottoGrave, RR_HF_COW_GROTTO, RR_HYRULE_FIELD, 0x0811 } }, - { { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_INSIDE_FENCE_GROTTO, 0x0712 }, - { EntranceType::GrottoGrave, RR_HF_INSIDE_FENCE_GROTTO, RR_HYRULE_FIELD, 0x0812 } }, - { { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_OPEN_GROTTO, 0x0713 }, - { EntranceType::GrottoGrave, RR_HF_OPEN_GROTTO, RR_HYRULE_FIELD, 0x0813 } }, - { { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_SOUTHEAST_GROTTO, 0x0714 }, - { EntranceType::GrottoGrave, RR_HF_SOUTHEAST_GROTTO, RR_HYRULE_FIELD, 0x0814 } }, - { { EntranceType::GrottoGrave, RR_LON_LON_RANCH, RR_LLR_GROTTO, 0x0715 }, - { EntranceType::GrottoGrave, RR_LLR_GROTTO, RR_LON_LON_RANCH, 0x0815 } }, - { { EntranceType::GrottoGrave, RR_SFM_ENTRYWAY, RR_SFM_WOLFOS_GROTTO, 0x0716 }, - { EntranceType::GrottoGrave, RR_SFM_WOLFOS_GROTTO, RR_SFM_ENTRYWAY, 0x0816 } }, - { { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_STORMS_GROTTO, 0x0717 }, - { EntranceType::GrottoGrave, RR_SFM_STORMS_GROTTO, RR_SACRED_FOREST_MEADOW, 0x0817 } }, - { { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_FAIRY_GROTTO, 0x0718 }, - { EntranceType::GrottoGrave, RR_SFM_FAIRY_GROTTO, RR_SACRED_FOREST_MEADOW, 0x0818 } }, - { { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_LW_SCRUBS_GROTTO, 0x0719 }, - { EntranceType::GrottoGrave, RR_LW_SCRUBS_GROTTO, RR_LW_BEYOND_MIDO, 0x0819 } }, - { { EntranceType::GrottoGrave, RR_THE_LOST_WOODS, RR_LW_NEAR_SHORTCUTS_GROTTO, 0x071A }, - { EntranceType::GrottoGrave, RR_LW_NEAR_SHORTCUTS_GROTTO, RR_THE_LOST_WOODS, 0x081A } }, - { { EntranceType::GrottoGrave, RR_KOKIRI_FOREST, RR_KF_STORMS_GROTTO, 0x071B }, - { EntranceType::GrottoGrave, RR_KF_STORMS_GROTTO, RR_KOKIRI_FOREST, 0x081B } }, - { { EntranceType::GrottoGrave, RR_ZORAS_DOMAIN, RR_ZD_STORMS_GROTTO, 0x071C }, - { EntranceType::GrottoGrave, RR_ZD_STORMS_GROTTO, RR_ZORAS_DOMAIN, 0x081C } }, - { { EntranceType::GrottoGrave, RR_GERUDO_FORTRESS, RR_GF_STORMS_GROTTO, 0x071D }, - { EntranceType::GrottoGrave, RR_GF_STORMS_GROTTO, RR_GERUDO_FORTRESS, 0x081D } }, - { { EntranceType::GrottoGrave, RR_GV_FORTRESS_SIDE, RR_GV_STORMS_GROTTO, 0x071E }, - { EntranceType::GrottoGrave, RR_GV_STORMS_GROTTO, RR_GV_FORTRESS_SIDE, 0x081E } }, - { { EntranceType::GrottoGrave, RR_GV_GROTTO_LEDGE, RR_GV_OCTOROK_GROTTO, 0x071F }, - { EntranceType::GrottoGrave, RR_GV_OCTOROK_GROTTO, RR_GV_GROTTO_LEDGE, 0x081F } }, - { { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_DEKU_THEATER, 0x0720 }, - { EntranceType::GrottoGrave, RR_DEKU_THEATER, RR_LW_BEYOND_MIDO, 0x0820 } }, - - // Graves have their own specified entrance indices - { { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_SHIELD_GRAVE, 0x004B }, - { EntranceType::GrottoGrave, RR_GRAVEYARD_SHIELD_GRAVE, RR_THE_GRAVEYARD, 0x035D } }, - { { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_HEART_PIECE_GRAVE, 0x031C }, - { EntranceType::GrottoGrave, RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_THE_GRAVEYARD, 0x0361 } }, - { { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_COMPOSERS_GRAVE, 0x002D }, - { EntranceType::GrottoGrave, RR_GRAVEYARD_COMPOSERS_GRAVE, RR_THE_GRAVEYARD, 0x050B } }, - { { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_GRAVE, 0x044F }, - { EntranceType::GrottoGrave, RR_GRAVEYARD_DAMPES_GRAVE, RR_THE_GRAVEYARD, 0x0359 } }, - - { { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_LW_BRIDGE_FROM_FOREST, 0x05E0 }, - { EntranceType::Overworld, RR_LW_BRIDGE, RR_KOKIRI_FOREST, 0x020D } }, - { { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_THE_LOST_WOODS, 0x011E }, - { EntranceType::Overworld, RR_LW_FOREST_EXIT, RR_KOKIRI_FOREST, 0x0286 } }, - { { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_GC_WOODS_WARP, 0x04E2 }, - { EntranceType::Overworld, RR_GC_WOODS_WARP, RR_THE_LOST_WOODS, 0x04D6 } }, - { { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_ZORAS_RIVER, 0x01DD }, - { EntranceType::Overworld, RR_ZORAS_RIVER, RR_THE_LOST_WOODS, 0x04DA } }, - { { EntranceType::Overworld, RR_LW_BEYOND_MIDO, RR_SFM_ENTRYWAY, 0x00FC }, - { EntranceType::Overworld, RR_SFM_ENTRYWAY, RR_LW_BEYOND_MIDO, 0x01A9 } }, - { { EntranceType::Overworld, RR_LW_BRIDGE, RR_HYRULE_FIELD, 0x0185 }, - { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LW_BRIDGE, 0x04DE } }, - { { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LAKE_HYLIA, 0x0102 }, - { EntranceType::Overworld, RR_LAKE_HYLIA, RR_HYRULE_FIELD, 0x0189 } }, - { { EntranceType::Overworld, RR_HYRULE_FIELD, RR_GERUDO_VALLEY, 0x0117 }, - { EntranceType::Overworld, RR_GERUDO_VALLEY, RR_HYRULE_FIELD, 0x018D } }, - { { EntranceType::Overworld, RR_HYRULE_FIELD, RR_MARKET_ENTRANCE, 0x0276 }, - { EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_HYRULE_FIELD, 0x01FD } }, - { { EntranceType::Overworld, RR_HYRULE_FIELD, RR_KAKARIKO_VILLAGE, 0x00DB }, - { EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_HYRULE_FIELD, 0x017D } }, - { { EntranceType::Overworld, RR_HYRULE_FIELD, RR_ZR_FRONT, 0x00EA }, - { EntranceType::Overworld, RR_ZR_FRONT, RR_HYRULE_FIELD, 0x0181 } }, - { { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LON_LON_RANCH, 0x0157 }, - { EntranceType::Overworld, RR_LON_LON_RANCH, RR_HYRULE_FIELD, 0x01F9 } }, - { { EntranceType::Overworld, RR_LAKE_HYLIA, RR_ZORAS_DOMAIN, 0x0328 }, - { EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_LAKE_HYLIA, 0x0560 } }, - { { EntranceType::Overworld, RR_GV_FORTRESS_SIDE, RR_GERUDO_FORTRESS, 0x0129 }, - { EntranceType::Overworld, RR_GERUDO_FORTRESS, RR_GV_FORTRESS_SIDE, 0x022D } }, - { { EntranceType::Overworld, RR_GF_OUTSIDE_GATE, RR_WASTELAND_NEAR_FORTRESS, 0x0130 }, - { EntranceType::Overworld, RR_WASTELAND_NEAR_FORTRESS, RR_GF_OUTSIDE_GATE, 0x03AC } }, - { { EntranceType::Overworld, RR_WASTELAND_NEAR_COLOSSUS, RR_DESERT_COLOSSUS, 0x0123 }, - { EntranceType::Overworld, RR_DESERT_COLOSSUS, RR_WASTELAND_NEAR_COLOSSUS, 0x0365 } }, - { { EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_THE_MARKET, 0x00B1 }, - { EntranceType::Overworld, RR_THE_MARKET, RR_MARKET_ENTRANCE, 0x0033 } }, - { { EntranceType::Overworld, RR_THE_MARKET, RR_CASTLE_GROUNDS, 0x0138 }, - { EntranceType::Overworld, RR_CASTLE_GROUNDS, RR_THE_MARKET, 0x025A } }, - { { EntranceType::Overworld, RR_THE_MARKET, RR_TOT_ENTRANCE, 0x0171 }, - { EntranceType::Overworld, RR_TOT_ENTRANCE, RR_THE_MARKET, 0x025E } }, - { { EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_THE_GRAVEYARD, 0x00E4 }, - { EntranceType::Overworld, RR_THE_GRAVEYARD, RR_KAKARIKO_VILLAGE, 0x0195 } }, - { { EntranceType::Overworld, RR_KAK_BEHIND_GATE, RR_DEATH_MOUNTAIN_TRAIL, 0x013D }, - { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_KAK_BEHIND_GATE, 0x0191 } }, - { { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_GORON_CITY, 0x014D }, - { EntranceType::Overworld, RR_GORON_CITY, RR_DEATH_MOUNTAIN_TRAIL, 0x01B9 } }, - { { EntranceType::Overworld, RR_GC_DARUNIAS_CHAMBER, RR_DMC_LOWER_LOCAL, 0x0246 }, - { EntranceType::Overworld, RR_DMC_LOWER_NEARBY, RR_GC_DARUNIAS_CHAMBER, 0x01C1 } }, - { { EntranceType::Overworld, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMC_UPPER_LOCAL, 0x0147 }, - { EntranceType::Overworld, RR_DMC_UPPER_NEARBY, RR_DEATH_MOUNTAIN_SUMMIT, 0x01BD } }, - { { EntranceType::Overworld, RR_ZR_BEHIND_WATERFALL, RR_ZORAS_DOMAIN, 0x0108 }, - { EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_ZR_BEHIND_WATERFALL, 0x019D } }, - { { EntranceType::Overworld, RR_ZD_BEHIND_KING_ZORA, RR_ZORAS_FOUNTAIN, 0x0225 }, - { EntranceType::Overworld, RR_ZORAS_FOUNTAIN, RR_ZD_BEHIND_KING_ZORA, 0x01A1 } }, - - { { EntranceType::Overworld, RR_GV_LOWER_STREAM, RR_LAKE_HYLIA, 0x0219 }, NO_RETURN_ENTRANCE }, - - { { EntranceType::OwlDrop, RR_LH_OWL_FLIGHT, RR_HYRULE_FIELD, 0x027E }, NO_RETURN_ENTRANCE }, - { { EntranceType::OwlDrop, RR_DMT_OWL_FLIGHT, RR_KAK_IMPAS_ROOFTOP, 0x0554 }, NO_RETURN_ENTRANCE }, - - { { EntranceType::Spawn, RR_CHILD_SPAWN, RR_KF_LINKS_HOUSE, 0x00BB }, NO_RETURN_ENTRANCE }, - { { EntranceType::Spawn, RR_ADULT_SPAWN, RR_TEMPLE_OF_TIME, 0x0282 }, - NO_RETURN_ENTRANCE }, // 0x282 is an unused entrance index repurposed to differentiate between - // Adult Spawn and prelude of light (normally they both use 0x5F4) - { { EntranceType::WarpSong, RR_MINUET_OF_FOREST_WARP, RR_SACRED_FOREST_MEADOW, 0x0600 }, NO_RETURN_ENTRANCE }, - { { EntranceType::WarpSong, RR_BOLERO_OF_FIRE_WARP, RR_DMC_CENTRAL_LOCAL, 0x04F6 }, NO_RETURN_ENTRANCE }, - { { EntranceType::WarpSong, RR_SERENADE_OF_WATER_WARP, RR_LAKE_HYLIA, 0x0604 }, NO_RETURN_ENTRANCE }, - { { EntranceType::WarpSong, RR_REQUIEM_OF_SPIRIT_WARP, RR_DESERT_COLOSSUS, 0x01F1 }, NO_RETURN_ENTRANCE }, - { { EntranceType::WarpSong, RR_NOCTURNE_OF_SHADOW_WARP, RR_GRAVEYARD_WARP_PAD_REGION, 0x0568 }, - NO_RETURN_ENTRANCE }, - { { EntranceType::WarpSong, RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME, 0x05F4 }, NO_RETURN_ENTRANCE }, - - { { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ENTRYWAY, RR_DEKU_TREE_BOSS_ROOM, 0x040F }, - { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY, 0x0252, 0x0457 } }, - { { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, RR_DODONGOS_CAVERN_BOSS_ROOM, 0x040B }, - { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, 0x00C5, 0x047A } }, - { { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, RR_JABU_JABUS_BELLY_BOSS_ROOM, 0x0301 }, - { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, 0x0407, 0x010E } }, - { { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, RR_FOREST_TEMPLE_BOSS_ROOM, 0x000C }, - { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, 0x024E, 0x0608 } }, - { { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, RR_FIRE_TEMPLE_BOSS_ROOM, 0x0305 }, - { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, 0x0175, 0x0564 } }, - { { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ENTRYWAY, RR_WATER_TEMPLE_BOSS_ROOM, 0x0417 }, - { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY, 0x0423, 0x060C } }, - { { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, RR_SPIRIT_TEMPLE_BOSS_ROOM, 0x008D }, - { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, 0x02F5, 0x0610 } }, - { { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, 0x0413 }, - { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, 0x02B2, 0x0580 } }, - }; - - std::map priorityEntranceTable = { - { "Bolero", { { RR_DMC_CENTRAL_LOCAL }, { EntranceType::OwlDrop, EntranceType::WarpSong } } }, - { "Nocturne", - { { RR_GRAVEYARD_WARP_PAD_REGION }, { EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong } } }, - { "Requiem", - { { RR_DESERT_COLOSSUS, RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY }, - { EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong } } }, - }; - - entranceShuffleFailure = false; - SetAllEntrancesData(entranceShuffleTable); - - EntrancePools oneWayEntrancePools = {}; - EntrancePools entrancePools = {}; - std::map oneWayPriorities = {}; - - // Owl Drops - if (Settings::ShuffleOwlDrops) { - oneWayEntrancePools[EntranceType::OwlDrop] = GetShuffleableEntrances(EntranceType::OwlDrop); - } - - // Spawns - if (Settings::ShuffleOverworldSpawns) { - oneWayEntrancePools[EntranceType::Spawn] = GetShuffleableEntrances(EntranceType::Spawn); - } - - // Warpsongs - if (Settings::ShuffleWarpSongs) { - oneWayEntrancePools[EntranceType::WarpSong] = GetShuffleableEntrances(EntranceType::WarpSong); - // In Glitchless, there aren't any other ways to access these areas - if (Settings::Logic.Is(LOGIC_GLITCHLESS)) { - oneWayPriorities["Bolero"] = priorityEntranceTable["Bolero"]; - oneWayPriorities["Nocturne"] = priorityEntranceTable["Nocturne"]; - if (!Settings::ShuffleDungeonEntrances && !Settings::ShuffleOverworldEntrances) { - oneWayPriorities["Requiem"] = priorityEntranceTable["Requiem"]; - } - } - } - - // Shuffle Bosses - if (Settings::ShuffleBossEntrances.IsNot(SHUFFLEBOSSES_OFF)) { - if (Settings::ShuffleBossEntrances.Is(SHUFFLEBOSSES_FULL)) { - entrancePools[EntranceType::Boss] = GetShuffleableEntrances(EntranceType::ChildBoss); - AddElementsToPool(entrancePools[EntranceType::Boss], GetShuffleableEntrances(EntranceType::AdultBoss)); - // If forest is closed, ensure Ghoma is inside the Deku tree - // Deku tree being in its vanilla location is handled below - if (Settings::OpenForest.Is(OPENFOREST_CLOSED) && !(Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances)) { - FilterAndEraseFromPool(entrancePools[EntranceType::Boss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == RR_DEKU_TREE_BOSS_ENTRYWAY && - entrance->GetConnectedRegionKey() == RR_DEKU_TREE_BOSS_ROOM;}); - } - } else { - entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss); - entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss); - // If forest is closed, ensure Ghoma is inside the Deku tree - if (Settings::OpenForest.Is(OPENFOREST_CLOSED) && !(Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances)) { - FilterAndEraseFromPool(entrancePools[EntranceType::ChildBoss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == RR_DEKU_TREE_BOSS_ENTRYWAY && - entrance->GetConnectedRegionKey() == RR_DEKU_TREE_BOSS_ROOM;}); - } - } - } - - //Shuffle Dungeon Entrances - if (Settings::ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) { - entrancePools[EntranceType::Dungeon] = GetShuffleableEntrances(EntranceType::Dungeon); - //Add Ganon's Castle, if set to On + Ganon - if (Settings::ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_GANON)) { - AddElementsToPool(entrancePools[EntranceType::Dungeon], GetShuffleableEntrances(EntranceType::GanonDungeon)); - } - //If forest is closed don't allow a forest escape via spirit temple hands - if (Settings::OpenForest.Is(OPENFOREST_CLOSED) && !(Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances)) { - FilterAndEraseFromPool(entrancePools[EntranceType::Dungeon], [](const Entrance* entrance){return entrance->GetParentRegionKey() == RR_KF_OUTSIDE_DEKU_TREE && - entrance->GetConnectedRegionKey() == RR_DEKU_TREE_ENTRYWAY;}); - } - if (Settings::DecoupleEntrances) { - for (Entrance* entrance : entrancePools[EntranceType::Dungeon]) { - entrancePools[EntranceType::DungeonReverse].push_back(entrance->GetReverse()); - } - } - } - - // Interior entrances - if (Settings::ShuffleInteriorEntrances.IsNot(SHUFFLEINTERIORS_OFF)) { - entrancePools[EntranceType::Interior] = GetShuffleableEntrances(EntranceType::Interior); - // Special interiors - if (Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)) { - AddElementsToPool(entrancePools[EntranceType::Interior], GetShuffleableEntrances(EntranceType::SpecialInterior)); - } - if (Settings::DecoupleEntrances) { - for (Entrance* entrance : entrancePools[EntranceType::Interior]) { - entrancePools[EntranceType::InteriorReverse].push_back(entrance->GetReverse()); - } - } - } - - //grotto entrances - if (Settings::ShuffleGrottoEntrances) { - entrancePools[EntranceType::GrottoGrave] = GetShuffleableEntrances(EntranceType::GrottoGrave); - - if (Settings::DecoupleEntrances) { - for (Entrance* entrance : entrancePools[EntranceType::GrottoGrave]) { - entrancePools[EntranceType::GrottoGraveReverse].push_back(entrance->GetReverse()); - } - } - } - - //overworld entrances - if (Settings::ShuffleOverworldEntrances) { - bool excludeOverworldReverse = Settings::MixOverworld && !Settings::DecoupleEntrances; - entrancePools[EntranceType::Overworld] = GetShuffleableEntrances(EntranceType::Overworld, excludeOverworldReverse); - // Only shuffle GV Lower Stream -> Lake Hylia if decoupled entrances are on - if (!Settings::DecoupleEntrances) { - FilterAndEraseFromPool(entrancePools[EntranceType::Overworld], [](const Entrance* entrance){return entrance->GetParentRegionKey() == RR_GV_LOWER_STREAM && - entrance->GetConnectedRegionKey() == RR_LAKE_HYLIA;}); - } - } - - // Set shuffled entrances as such - SetShuffledEntrances(entrancePools); - SetShuffledEntrances(oneWayEntrancePools); - - //combine entrance pools if mixing pools. Only continue if more than one pool is selected. - int totalMixedPools = (Settings::MixDungeons ? 1 : 0) + (Settings::MixOverworld ? 1 : 0) + (Settings::MixInteriors ? 1 : 0) + (Settings::MixGrottos ? 1 : 0); - if (totalMixedPools < 2) { - Settings::MixedEntrancePools.SetSelectedIndex(OFF); - Settings::MixDungeons.SetSelectedIndex(OFF); - Settings::MixOverworld.SetSelectedIndex(OFF); - Settings::MixInteriors.SetSelectedIndex(OFF); - Settings::MixGrottos.SetSelectedIndex(OFF); - } - if (Settings::MixedEntrancePools) { - std::set poolsToMix = {}; - if (Settings::MixDungeons) { - poolsToMix.insert(EntranceType::Dungeon); - // Insert reverse entrances when decoupled entrances is on - if (Settings::DecoupleEntrances) { - poolsToMix.insert(EntranceType::DungeonReverse); - } - } - if (Settings::MixOverworld) { - poolsToMix.insert(EntranceType::Overworld); - } - if (Settings::MixInteriors) { - poolsToMix.insert(EntranceType::Interior); - if (Settings::DecoupleEntrances) { - poolsToMix.insert(EntranceType::InteriorReverse); - } - } - if (Settings::MixGrottos) { - poolsToMix.insert(EntranceType::GrottoGrave); - if (Settings::DecoupleEntrances) { - poolsToMix.insert(EntranceType::GrottoGraveReverse); - } - } - - for (auto& pool : entrancePools) { - - auto type = pool.first; - - if (poolsToMix.count(type) > 0) { - AddElementsToPool(entrancePools[EntranceType::Mixed], pool.second); - entrancePools[type].clear(); - } - } - } - - // Build target entrance pools and set the assumption for entrances being reachable - EntrancePools oneWayTargetEntrancePools = {}; - for (auto& pool : oneWayEntrancePools) { - - std::vector validTargetTypes = {}; - EntranceType poolType = pool.first; - - if (poolType == EntranceType::OwlDrop) { - validTargetTypes = {EntranceType::WarpSong, EntranceType::OwlDrop, EntranceType::Overworld, EntranceType::Extra}; - oneWayTargetEntrancePools[poolType] = BuildOneWayTargets(validTargetTypes, {std::make_pair(RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME)}); - // Owl Drops are only accessible as child, so targets should reflect that - for (Entrance* target : oneWayTargetEntrancePools[poolType]) { - target->SetCondition([]{return Logic::IsChild;}); - } - - } else if (poolType == EntranceType::Spawn) { - validTargetTypes = {EntranceType::Spawn, EntranceType::WarpSong, EntranceType::OwlDrop, EntranceType::Overworld, EntranceType::Interior, EntranceType::SpecialInterior, EntranceType::GrottoGrave, EntranceType::Extra}; - oneWayTargetEntrancePools[poolType] = BuildOneWayTargets(validTargetTypes); - - } else if (poolType == EntranceType::WarpSong) { - validTargetTypes = {EntranceType::Spawn, EntranceType::WarpSong, EntranceType::OwlDrop, EntranceType::Overworld, EntranceType::Interior, EntranceType::SpecialInterior, EntranceType::GrottoGrave, EntranceType::Extra}; - oneWayTargetEntrancePools[poolType] = BuildOneWayTargets(validTargetTypes); - } - // for target in one_way_target_entrance_pools[pool_type]: - // target.add_rule((lambda entrances=entrance_pool: (lambda state, **kwargs: any(entrance.connected_region == None for entrance in entrances)))()) - } - - // Disconnect all one way entrances at this point (they need to be connected during all of the above process) - for (auto& pool : oneWayEntrancePools) { - for (Entrance* entrance : pool.second) { - totalRandomizableEntrances++; - entrance->Disconnect(); - } - } - - // Assume entrance pools for each type - EntrancePools targetEntrancePools = {}; - for (auto& pool : entrancePools) { - targetEntrancePools[pool.first] = AssumeEntrancePool(pool.second); - } - - //distribution stuff - - //check placed on-way entrances - //remove replaced entrances so we don't place two in one target - //remvoe priority targets if any placed entrances point at their regions - - // Place priority entrances - ShuffleOneWayPriorityEntrances(oneWayPriorities, oneWayEntrancePools, oneWayTargetEntrancePools); - if (entranceShuffleFailure) { - return ENTRANCE_SHUFFLE_FAILURE; - } - - // Delete all targets that we just placed from one way target pools so - // multiple one way entrances don't use the same target - std::vector replacedEntrances = {}; - for (auto& pool : oneWayEntrancePools) { - for (Entrance* entrance : pool.second) { - if (entrance->GetReplacement() != nullptr) { - replacedEntrances.push_back(entrance); - } - } - } - for (auto& pool : oneWayTargetEntrancePools) { - for (Entrance* remainingTarget : pool.second) { - auto replacement = remainingTarget->GetReplacement(); - if (ElementInContainer(replacement, replacedEntrances)) { - DeleteTargetEntrance(remainingTarget); - } - } - } - - // Shuffle all one way entrances among pools to shuffle - for (auto& pool : oneWayEntrancePools) { - ShuffleEntrancePool(pool.second, oneWayTargetEntrancePools[pool.first], 5); - if (entranceShuffleFailure) { - return ENTRANCE_SHUFFLE_FAILURE; - } - // Delete all targets that we just placed from other one way target pools so - // multiple one way entrances don't use the same target - replacedEntrances = FilterFromPool(pool.second, [](Entrance* entrance){ - return entrance->GetReplacement() != nullptr; - }); - for (auto& targetPool : oneWayTargetEntrancePools) { - for (Entrance* remainingTarget : targetPool.second) { - auto replacement = remainingTarget->GetReplacement(); - if (ElementInContainer(replacement, replacedEntrances)) { - DeleteTargetEntrance(remainingTarget); - } - } - } - // Delete all unused extra targets after placing a one way pool, since the - // unused targets won't ever be replaced - for (Entrance* unusedTarget : oneWayTargetEntrancePools[pool.first]) { - DeleteTargetEntrance(unusedTarget); - } - } - - //shuffle all entrances among pools to shuffle - for (auto& pool : entrancePools) { - ShuffleEntrancePool(pool.second, targetEntrancePools[pool.first]); - if (entranceShuffleFailure) { - return ENTRANCE_SHUFFLE_FAILURE; - } - } - - return ENTRANCE_SHUFFLE_SUCCESS; -} - -// Save the set of shuffled entrances that will be sent to the patch -void CreateEntranceOverrides() { - entranceOverrides.clear(); - if (noRandomEntrances) { - return; - } - SPDLOG_DEBUG("\nCREATING ENTRANCE OVERRIDES\n"); - auto allShuffleableEntrances = GetShuffleableEntrances(EntranceType::All, false); - - for (Entrance* entrance : allShuffleableEntrances) { - - //Double-check to make sure the entrance is actually shuffled - if (!entrance->IsShuffled()) { - continue; - } - - auto message = "Setting " + entrance->to_string() + "\n"; - SPDLOG_DEBUG(message); - - int16_t originalIndex = entrance->GetIndex(); - int16_t originalBlueWarp = entrance->GetBlueWarp(); - int16_t replacementIndex = entrance->GetReplacement()->GetIndex(); - - int16_t destinationIndex = -1; - int16_t replacementDestinationIndex = -1; - - // Only set destination indices for two way entrances and when decouple entrances - // is off - if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) { - replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex(); - destinationIndex = entrance->GetReverse()->GetIndex(); - } - - entranceOverrides.push_back({ - .index = originalIndex, - .destination = destinationIndex, - .blueWarp = originalBlueWarp, - .override = replacementIndex, - .overrideDestination = replacementDestinationIndex, - }); - - message = "\tOriginal: " + std::to_string(originalIndex) + "\n"; - SPDLOG_DEBUG(message); - message = "\tReplacement " + std::to_string(replacementIndex) + "\n"; - SPDLOG_DEBUG(message); - } -} - -std::vector> playthroughEntrances; diff --git a/soh/soh/Enhancements/randomizer/3drando/entrance.hpp b/soh/soh/Enhancements/randomizer/3drando/entrance.hpp deleted file mode 100644 index d9c62a5fb..000000000 --- a/soh/soh/Enhancements/randomizer/3drando/entrance.hpp +++ /dev/null @@ -1,289 +0,0 @@ -#pragma once - -#include "location_access.hpp" - -#include -#include - -#include "../randomizer_entrance.h" - -#define ENTRANCE_SHUFFLE_SUCCESS 0 -#define ENTRANCE_SHUFFLE_FAILURE 1 - -extern std::list entranceOverrides; - -enum class EntranceType { - None, - OwlDrop, - Spawn, - WarpSong, - Dungeon, - GanonDungeon, - DungeonReverse, - Boss, - ChildBoss, - AdultBoss, - Interior, - InteriorReverse, - SpecialInterior, - GrottoGrave, - GrottoGraveReverse, - Overworld, - Extra, - Mixed, - All, -}; - -class Entrance { -public: - - Entrance(RandomizerRegion connectedRegion_, std::vector conditions_met_) - : connectedRegion(connectedRegion_) { - conditions_met.resize(2); - for (size_t i = 0; i < conditions_met_.size(); i++) { - conditions_met[i] = conditions_met_[i]; - } - } - - // Resets the glitchless condition for the entrance - void SetCondition(ConditionFn newCondition) { - conditions_met[0] = newCondition; - } - - bool GetConditionsMet() const { - if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) { - return true; - } else if (Settings::Logic.Is(LOGIC_GLITCHLESS)) { - return conditions_met[0](); - } else if (Settings::Logic.Is(LOGIC_GLITCHED)) { - if (conditions_met[0]()) { - return true; - } else if (conditions_met[1] != NULL) { - return conditions_met[1](); - } - } - return false; - } - - std::string to_string() const { - return AreaTable(parentRegion)->regionName + " -> " + AreaTable(connectedRegion)->regionName; - } - - void SetName(std::string name_ = "") { - if (name_ == "") { - name = AreaTable(parentRegion)->regionName + " -> " + AreaTable(connectedRegion)->regionName; - } else { - name = std::move(name_); - } - - } - - std::string GetName() const { - return name; - } - - void printAgeTimeAccess() { - //CitraPrint("Name: "); - //CitraPrint(name); - auto message = "Child Day: " + std::to_string(CheckConditionAtAgeTime(Logic::IsChild, Logic::AtDay)) + "\t" - "Child Night: " + std::to_string(CheckConditionAtAgeTime(Logic::IsChild, Logic::AtNight)) + "\t" - "Adult Day: " + std::to_string(CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtDay)) + "\t" - "Adult Night: " + std::to_string(CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtNight)); - //CitraPrint(message); - } - - bool ConditionsMet(bool allAgeTimes = false) const { - - Area* parent = AreaTable(parentRegion); - int conditionsMet = 0; - - if (allAgeTimes && !parent->AllAccess()) { - return false; - } - - //check all possible day/night condition combinations - conditionsMet = (parent->childDay && CheckConditionAtAgeTime(Logic::IsChild, Logic::AtDay, allAgeTimes)) + - (parent->childNight && CheckConditionAtAgeTime(Logic::IsChild, Logic::AtNight, allAgeTimes)) + - (parent->adultDay && CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtDay, allAgeTimes)) + - (parent->adultNight && CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtNight, allAgeTimes)); - - return conditionsMet && (!allAgeTimes || conditionsMet == 4); - } - - uint32_t Getuint32_t() const { - return connectedRegion; - } - - //set the logic to be a specific age and time of day and see if the condition still holds - bool CheckConditionAtAgeTime(bool& age, bool& time, bool passAnyway = false) const { - - Logic::IsChild = false; - Logic::IsAdult = false; - Logic::AtDay = false; - Logic::AtNight = false; - - time = true; - age = true; - - Logic::UpdateHelpers(); - return GetConditionsMet() && (connectedRegion != RR_NONE || passAnyway); - } - - RandomizerRegion GetConnectedRegionKey() const { - return connectedRegion; - } - - Area* GetConnectedRegion() const { - return AreaTable(connectedRegion); - } - - void SetParentRegion(RandomizerRegion newParent) { - parentRegion = newParent; - } - - RandomizerRegion GetParentRegionKey() const { - return parentRegion; - } - - Area* GetParentRegion() const { - return AreaTable(parentRegion); - } - - void SetNewEntrance(RandomizerRegion newRegion) { - connectedRegion = newRegion; - } - - void SetAsShuffled() { - shuffled = true; - } - - bool IsShuffled() const { - return shuffled; - } - - bool IsAddedToPool() const { - return addedToPool; - } - - void AddToPool() { - addedToPool = true; - } - - void RemoveFromPool() { - addedToPool = false; - } - - void SetAsPrimary() { - primary = true; - } - - bool IsPrimary() const { - return primary; - } - - bool IsDecoupled() const { - return decoupled; - } - - void SetDecoupled() { - decoupled = true; - } - - int16_t GetIndex() const { - return index; - } - - void SetIndex(int16_t newIndex) { - index = newIndex; - } - - int16_t GetBlueWarp() const { - return blueWarp; - } - - void SetBlueWarp(int16_t newBlueWarp) { - blueWarp = newBlueWarp; - } - - Entrance* GetAssumed() const { - return assumed; - } - - void SetReplacement(Entrance* newReplacement) { - replacement = newReplacement; - } - - Entrance* GetReplacement() const { - return replacement; - } - - EntranceType GetType() const { - return type; - } - - void SetType(EntranceType newType) { - type = newType; - } - - Entrance* GetReverse() const { - return reverse; - } - - void Connect(RandomizerRegion newConnectedRegion) { - connectedRegion = newConnectedRegion; - AreaTable(newConnectedRegion)->entrances.push_front(this); - } - - RandomizerRegion Disconnect() { - AreaTable(connectedRegion)->entrances.remove_if([this](const auto entrance){return this == entrance;}); - RandomizerRegion previouslyConnected = connectedRegion; - connectedRegion = RR_NONE; - return previouslyConnected; - } - - void BindTwoWay(Entrance* otherEntrance) { - reverse = otherEntrance; - otherEntrance->reverse = this; - } - - Entrance* GetNewTarget() { - AreaTable(RR_ROOT)->AddExit(RR_ROOT, connectedRegion, []{return true;}); - Entrance* targetEntrance = AreaTable(RR_ROOT)->GetExit(connectedRegion); - targetEntrance->SetReplacement(this); - targetEntrance->SetName(GetParentRegion()->regionName + " -> " + GetConnectedRegion()->regionName); - return targetEntrance; - } - - Entrance* AssumeReachable() { - if (assumed == nullptr) { - assumed = GetNewTarget(); - Disconnect(); - } - return assumed; - } - -private: - RandomizerRegion parentRegion; - RandomizerRegion connectedRegion; - std::vector conditions_met; - - //Entrance Randomizer stuff - EntranceType type = EntranceType::None; - Entrance* target = nullptr; - Entrance* reverse = nullptr; - Entrance* assumed = nullptr; - Entrance* replacement = nullptr; - int16_t index = 0xFFFF; - int16_t blueWarp = 0; - bool shuffled = false; - bool primary = false; - bool addedToPool = false; - bool decoupled = false; - std::string name = ""; -}; - -int ShuffleAllEntrances(); -void CreateEntranceOverrides(); - -extern std::vector> playthroughEntrances; -extern bool noRandomEntrances; diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index a3db898b3..3effc3840 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -1,7 +1,7 @@ #include "fill.hpp" #include "custom_messages.hpp" -#include "dungeon.hpp" +#include "../dungeon.h" #include "../context.h" #include "item_pool.hpp" #include "location_access.hpp" @@ -11,8 +11,9 @@ #include "starting_inventory.hpp" #include "hints.hpp" #include "hint_list.hpp" -#include "entrance.hpp" +#include "../entrance.h" #include "shops.hpp" +#include "pool_functions.hpp" //#include "debug.hpp" #include "soh/Enhancements/randomizer/static_data.h" @@ -22,7 +23,7 @@ using namespace CustomMessages; using namespace Logic; -using namespace Settings; +using namespace Rando; static bool placementFailure = false; @@ -90,14 +91,15 @@ static bool UpdateToDAccess(Entrance* entrance, SearchMode mode) { // Various checks that need to pass for the world to be validated as completable static void ValidateWorldChecks(SearchMode& mode, bool checkPoeCollectorAccess, bool checkOtherEntranceAccess, std::vector& areaPool) { + auto ctx = Rando::Context::GetInstance(); // Condition for validating Temple of Time Access - if (mode == SearchMode::TempleOfTimeAccess && ((Settings::ResolvedStartingAge == AGE_CHILD && AreaTable(RR_TEMPLE_OF_TIME)->Adult()) || (Settings::ResolvedStartingAge == AGE_ADULT && AreaTable(RR_TEMPLE_OF_TIME)->Child()) || !checkOtherEntranceAccess)) { + if (mode == SearchMode::TempleOfTimeAccess && ((ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD && AreaTable(RR_TEMPLE_OF_TIME)->Adult()) || (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_ADULT && AreaTable(RR_TEMPLE_OF_TIME)->Child()) || !checkOtherEntranceAccess)) { mode = SearchMode::ValidStartingRegion; } // Condition for validating a valid starting region if (mode == SearchMode::ValidStartingRegion) { - bool childAccess = Settings::ResolvedStartingAge == AGE_CHILD || AreaTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Child(); - bool adultAccess = Settings::ResolvedStartingAge == AGE_ADULT || AreaTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Adult(); + bool childAccess = ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD || AreaTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Child(); + bool adultAccess = ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_ADULT || AreaTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Adult(); Area* kokiri = AreaTable(RR_KOKIRI_FOREST); Area* kakariko = AreaTable(RR_KAKARIKO_VILLAGE); @@ -119,7 +121,7 @@ static void ValidateWorldChecks(SearchMode& mode, bool checkPoeCollectorAccess, Rando::StaticData::RetrieveItem(unplacedItem).ApplyEffect(); } // Reset access as the non-starting age - if (Settings::ResolvedStartingAge == AGE_CHILD) { + if (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) { for (RandomizerRegion areaKey : areaPool) { AreaTable(areaKey)->adultDay = false; AreaTable(areaKey)->adultNight = false; @@ -142,11 +144,11 @@ static int GetMaxGSCount() { //If bridge or LACS is set to tokens, get how many are required int maxBridge = 0; int maxLACS = 0; - if (Settings::Bridge.Is(RAINBOWBRIDGE_TOKENS)) { - maxBridge = Settings::BridgeTokenCount.Value(); + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) { + maxBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value(); } - if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_TOKENS)) { - maxLACS = Settings::LACSTokenCount.Value(); + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) { + maxLACS = ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value(); } maxBridge = std::max(maxBridge, maxLACS); //Get the max amount of GS which could be useful from token reward locations @@ -171,7 +173,7 @@ static int GetMaxGSCount() { maxUseful = 10; } //Return max of the two possible reasons tokens could be important, minus the tokens in the starting inventory - return std::max(maxUseful, maxBridge) - StartingSkulltulaToken.Value(); + return std::max(maxUseful, maxBridge) - ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Value(); } std::string GetShopItemBaseName(std::string itemName) { @@ -306,7 +308,7 @@ std::vector GetAccessibleLocations(const std::vectorGetEntranceShuffler()->HasNoRandomEntrances()) { entranceSphere.push_back(&exit); exit.AddToPool(); // Don't list a two-way coupled entrance from both directions @@ -384,7 +386,8 @@ std::vector GetAccessibleLocations(const std::vector GetAccessibleLocations(const std::vector GetAccessibleLocations(const std::vector 0) { ctx->playthroughLocations.push_back(itemSphere); } - if (mode == SearchMode::GeneratePlaythrough && entranceSphere.size() > 0 && !noRandomEntrances) { - playthroughEntrances.push_back(entranceSphere); + if (mode == SearchMode::GeneratePlaythrough && entranceSphere.size() > 0 && !ctx->GetEntranceShuffler()->HasNoRandomEntrances()) { + ctx->GetEntranceShuffler()->playthroughEntrances.push_back(entranceSphere); } } @@ -605,7 +608,7 @@ static void AssumedFill(const std::vector& items, const std::vect return; } - if (Settings::Logic.Is(LOGIC_NONE)) { + if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC)) { FastFill(items, GetEmptyLocations(allowedLocations), true); return; } @@ -683,7 +686,7 @@ static void AssumedFill(const std::vector& items, const std::vect // If ALR is off, then we check beatability after placing the item. // If the game is beatable, then we can stop placing items with logic. - if (!LocationsReachable) { + if (!ctx->GetOption(RSK_ALL_LOCATIONS_REACHABLE)) { ctx->playthroughBeatable = false; LogicReset(); GetAccessibleLocations(ctx->allLocations, SearchMode::CheckBeatable); @@ -702,22 +705,23 @@ static void AssumedFill(const std::vector& items, const std::vect //setting, or randomize one dungeon reward to Link's Pocket if that setting is on static void RandomizeDungeonRewards() { auto ctx = Rando::Context::GetInstance(); + std::array rDungeonRewardOverrides{}; //quest item bit mask of each stone/medallion for the savefile - static constexpr std::array bitMaskTable = { - 0x00040000, //Kokiri Emerald - 0x00080000, //Goron Ruby - 0x00100000, //Zora Sapphire - 0x00000001, //Forest Medallion - 0x00000002, //Fire Medallion - 0x00000004, //Water Medallion - 0x00000008, //Spirit Medallion - 0x00000010, //Shadow Medallion - 0x00000020, //Light Medallion - }; + // static constexpr std::array bitMaskTable = { + // 0x00040000, //Kokiri Emerald + // 0x00080000, //Goron Ruby + // 0x00100000, //Zora Sapphire + // 0x00000001, //Forest Medallion + // 0x00000002, //Fire Medallion + // 0x00000004, //Water Medallion + // 0x00000008, //Spirit Medallion + // 0x00000010, //Shadow Medallion + // 0x00000020, //Light Medallion + // }; int baseOffset = Rando::StaticData::RetrieveItem(RG_KOKIRI_EMERALD).GetItemID(); //End of Dungeons includes Link's Pocket - if (ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON)) { + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) { //get stones and medallions std::vector rewards = FilterAndEraseFromPool(ItemPool, [](const auto i) {return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;}); @@ -727,7 +731,7 @@ static void RandomizeDungeonRewards() { ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE); } - if (Settings::Logic.Is(LOGIC_VANILLA)) { //Place dungeon rewards in vanilla locations + if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) { //Place dungeon rewards in vanilla locations for (RandomizerCheck loc : Rando::StaticData::dungeonRewardLocations) { ctx->GetItemLocation(loc)->PlaceVanillaItem(); } @@ -742,11 +746,11 @@ static void RandomizeDungeonRewards() { //set the player's dungeon reward on file creation instead of pushing it to them at the start. //This is done mainly because players are already familiar with seeing their dungeon reward //before opening up their file - if (i == Rando::StaticData::dungeonRewardLocations.size()-1) { - LinksPocketRewardBitMask = bitMaskTable[index]; - } + // if (i == Rando::StaticData::dungeonRewardLocations.size()-1) { + // LinksPocketRewardBitMask = bitMaskTable[index]; + // } } - } else if (LinksPocketItem.Is(LINKSPOCKETITEM_DUNGEON_REWARD)) { + } else if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_DUNGEON_REWARD)) { //get 1 stone/medallion std::vector rewards = FilterFromPool( ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD; }); @@ -757,7 +761,7 @@ static void RandomizeDungeonRewards() { } RandomizerGet startingReward = RandomElement(rewards, true); - LinksPocketRewardBitMask = bitMaskTable[Rando::StaticData::RetrieveItem(startingReward).GetItemID() - baseOffset]; + //LinksPocketRewardBitMask = bitMaskTable[Rando::StaticData::RetrieveItem(startingReward).GetItemID() - baseOffset]; ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingReward); //erase the stone/medallion from the Item Pool FilterAndEraseFromPool(ItemPool, [startingReward](const RandomizerGet i) {return i == startingReward;}); @@ -779,7 +783,7 @@ static void FillExcludedLocations() { } //Function to handle the Own Dungeon setting -static void RandomizeOwnDungeon(const Dungeon::DungeonInfo* dungeon) { +static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) { auto ctx = Rando::Context::GetInstance(); std::vector dungeonItems; @@ -791,24 +795,24 @@ static void RandomizeOwnDungeon(const Dungeon::DungeonInfo* dungeon) { }); //filter out locations that may be required to have songs placed at them - dungeonLocations = FilterFromPool(dungeonLocations, [](const auto loc){ - if (ShuffleSongs.Is(SONGSHUFFLE_SONG_LOCATIONS)) { + dungeonLocations = FilterFromPool(dungeonLocations, [ctx](const auto loc){ + if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_SONG_LOCATIONS)) { return !(Rando::StaticData::GetLocation(loc)->IsCategory(Category::cSong)); } - if (ShuffleSongs.Is(SONGSHUFFLE_DUNGEON_REWARDS)) { + if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_SONG_LOCATIONS)) { return !(Rando::StaticData::GetLocation(loc)->IsCategory(Category::cSongDungeonReward)); } return true; }); //Add specific items that need be randomized within this dungeon - if (Keysanity.Is(KEYSANITY_OWN_DUNGEON) && dungeon->GetSmallKey() != RG_NONE) { + if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetSmallKey() != RG_NONE) { std::vector dungeonSmallKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());}); AddElementsToPool(dungeonItems, dungeonSmallKeys); } - if ((BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) || - (GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON) && dungeon->GetBossKey() == RG_GANONS_CASTLE_BOSS_KEY)) { + if ((ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) || + (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON) && dungeon->GetBossKey() == RG_GANONS_CASTLE_BOSS_KEY)) { auto dungeonBossKey = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return i == dungeon->GetBossKey();}); AddElementsToPool(dungeonItems, dungeonBossKey); } @@ -817,7 +821,7 @@ static void RandomizeOwnDungeon(const Dungeon::DungeonInfo* dungeon) { AssumedFill(dungeonItems, dungeonLocations); //randomize map and compass separately since they're not progressive - if (MapsAndCompasses.Is(MAPSANDCOMPASSES_OWN_DUNGEON) && dungeon->GetMap() != RG_NONE && dungeon->GetCompass() != RG_NONE) { + if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetMap() != RG_NONE && dungeon->GetCompass() != RG_NONE) { auto dungeonMapAndCompass = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){ return i == dungeon->GetMap() || i == dungeon->GetCompass();}); AssumedFill(dungeonMapAndCompass, dungeonLocations); } @@ -833,7 +837,6 @@ static void RandomizeOwnDungeon(const Dungeon::DungeonInfo* dungeon) { are randomized separately once the dungeon advancement items have all been placed.*/ static void RandomizeDungeonItems() { auto ctx = Rando::Context::GetInstance(); - using namespace Dungeon; //Get Any Dungeon and Overworld group locations std::vector anyDungeonLocations = FilterFromPool(ctx->allLocations, [](const auto loc){return Rando::StaticData::GetLocation(loc)->IsDungeon();}); @@ -843,45 +846,45 @@ static void RandomizeDungeonItems() { std::vector anyDungeonItems; std::vector overworldItems; - for (auto dungeon : dungeonList) { - if (Keysanity.Is(KEYSANITY_ANY_DUNGEON)) { + for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { + if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON)) { auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());}); AddElementsToPool(anyDungeonItems, dungeonKeys); - } else if (Keysanity.Is(KEYSANITY_OVERWORLD)) { + } else if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) { auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());}); AddElementsToPool(overworldItems, dungeonKeys); } - if (BossKeysanity.Is(BOSSKEYSANITY_ANY_DUNGEON) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) { + if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) { auto bossKey = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetBossKey();}); AddElementsToPool(anyDungeonItems, bossKey); - } else if (BossKeysanity.Is(BOSSKEYSANITY_OVERWORLD) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) { + } else if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) && dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) { auto bossKey = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetBossKey();}); AddElementsToPool(overworldItems, bossKey); } - if (GanonsBossKey.Is(GANONSBOSSKEY_ANY_DUNGEON)) { + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) { auto ganonBossKey = FilterAndEraseFromPool(ItemPool, [](const auto i){return i == RG_GANONS_CASTLE_BOSS_KEY;}); AddElementsToPool(anyDungeonItems, ganonBossKey); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_OVERWORLD)) { + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) { auto ganonBossKey = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; }); AddElementsToPool(overworldItems, ganonBossKey); } } - if (GerudoKeys.Is(GERUDOKEYS_ANY_DUNGEON)) { + if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_ANY_DUNGEON)) { auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GERUDO_FORTRESS_SMALL_KEY; }); AddElementsToPool(anyDungeonItems, gerudoKeys); - } else if (GerudoKeys.Is(GERUDOKEYS_OVERWORLD)) { + } else if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_OVERWORLD)) { auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GERUDO_FORTRESS_SMALL_KEY; }); AddElementsToPool(overworldItems, gerudoKeys); } - if (ShuffleRewards.Is(REWARDSHUFFLE_ANY_DUNGEON)) { + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_ANY_DUNGEON)) { auto rewards = FilterAndEraseFromPool( ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD; }); AddElementsToPool(anyDungeonItems, rewards); - } else if (ShuffleRewards.Is(REWARDSHUFFLE_OVERWORLD)) { + } else if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_OVERWORLD)) { auto rewards = FilterAndEraseFromPool( ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD; }); AddElementsToPool(overworldItems, rewards); @@ -892,11 +895,11 @@ static void RandomizeDungeonItems() { AssumedFill(overworldItems, Rando::StaticData::overworldLocations, true); //Randomize maps and compasses after since they're not advancement items - for (auto dungeon : dungeonList) { - if (MapsAndCompasses.Is(MAPSANDCOMPASSES_ANY_DUNGEON)) { + for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { + if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) { auto mapAndCompassItems = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetMap() || i == dungeon->GetCompass();}); AssumedFill(mapAndCompassItems, anyDungeonLocations, true); - } else if (MapsAndCompasses.Is(MAPSANDCOMPASSES_OVERWORLD)) { + } else if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) { auto mapAndCompassItems = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return i == dungeon->GetMap() || i == dungeon->GetCompass();}); AssumedFill(mapAndCompassItems, Rando::StaticData::overworldLocations, true); } @@ -905,7 +908,7 @@ static void RandomizeDungeonItems() { static void RandomizeLinksPocket() { auto ctx = Rando::Context::GetInstance(); - if (LinksPocketItem.Is(LINKSPOCKETITEM_ADVANCEMENT)) { + if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_ADVANCEMENT)) { //Get all the advancement items don't include tokens std::vector advancementItems = FilterAndEraseFromPool(ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement() && Rando::StaticData::RetrieveItem(i).GetItemType() != ITEMTYPE_TOKEN; @@ -916,7 +919,7 @@ static void RandomizeLinksPocket() { AddElementsToPool(ItemPool, advancementItems); ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingItem); - } else if (LinksPocketItem.Is(LINKSPOCKETITEM_NOTHING)) { + } else if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_NOTHING)) { ctx->PlaceItemInLocation(RC_LINKS_POCKET, RG_GREEN_RUPEE); } } @@ -934,14 +937,14 @@ void VanillaFill() { ctx->GetItemLocation(loc)->PlaceVanillaItem(); } //If necessary, handle ER stuff - if (ShuffleEntrances) { + if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) { printf("\x1b[7;10HShuffling Entrances..."); - ShuffleAllEntrances(); + ctx->GetEntranceShuffler()->ShuffleAllEntrances(); printf("\x1b[7;32HDone"); } //Finish up ctx->CreateItemOverrides(); - CreateEntranceOverrides(); + ctx->GetEntranceShuffler()->CreateEntranceOverrides(); CreateWarpSongTexts(); } @@ -960,7 +963,7 @@ int Fill() { placementFailure = false; //showItemProgress = false; ctx->playthroughLocations.clear(); - playthroughEntrances.clear(); + ctx->GetEntranceShuffler()->playthroughEntrances.clear(); ctx->wothLocations.clear(); AreaTable_Init(); //Reset the world graph to intialize the proper locations ctx->ItemReset(); //Reset shops incase of shopsanity random @@ -973,9 +976,9 @@ int Fill() { //Temporarily add shop items to the ItemPool so that entrance randomization //can validate the world using deku/hylian shields AddElementsToPool(ItemPool, GetMinVanillaShopItems(32)); //assume worst case shopsanity 4 - if (ShuffleEntrances) { + if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) { printf("\x1b[7;10HShuffling Entrances"); - if (ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) { + if (ctx->GetEntranceShuffler()->ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) { retries++; ClearProgress(); continue; @@ -988,11 +991,11 @@ int Fill() { //ctx->showItemProgress = true; //Place shop items first, since a buy shield is needed to place a dungeon reward on Gohma due to access NonShopItems = {}; - if (Shopsanity.Is(SHOPSANITY_OFF)) { + if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF)) { PlaceVanillaShopItems(); //Place vanilla shop items in vanilla location } else { int total_replaced = 0; - if (Shopsanity.IsNot(SHOPSANITY_ZERO)) { //Shopsanity 1-4, random + if (ctx->GetOption(RSK_SHOPSANITY).IsNot(RO_SHOPSANITY_ZERO_ITEMS)) { //Shopsanity 1-4, random //Initialize NonShopItems ItemAndPrice init; init.Name = Text{"No Item", "Sin objeto", "Pas d'objet"}; @@ -1010,7 +1013,7 @@ int Fill() { int shopsanityPrice = GetRandomShopPrice(); NonShopItems[TransformShopIndex(i * 8 + itemindex - 1)].Price = shopsanityPrice; // Set price to be retrieved by the patch and textboxes - ctx->GetItemLocation(Rando::StaticData::shopLocationLists[i][itemindex - 1])->SetShopsanityPrice(shopsanityPrice); + ctx->GetItemLocation(Rando::StaticData::shopLocationLists[i][itemindex - 1])->SetCustomPrice(shopsanityPrice); } } } @@ -1023,7 +1026,7 @@ int Fill() { for (size_t i = 0; i < Rando::StaticData::shopLocationLists.size(); i++) { for (size_t j = 0; j < Rando::StaticData::shopLocationLists[i].size(); j++) { RandomizerCheck loc = Rando::StaticData::shopLocationLists[i][j]; - if (!(ctx->GetItemLocation(loc)->HasShopsanityPrice())) { + if (!(ctx->GetItemLocation(loc)->HasCustomPrice())) { shopLocations.push_back(loc); } } @@ -1036,12 +1039,12 @@ int Fill() { RandomizeDungeonRewards(); //Place dungeon items restricted to their Own Dungeon - for (auto dungeon : Dungeon::dungeonList) { + for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { RandomizeOwnDungeon(dungeon); } //Then Place songs if song shuffle is set to specific locations - if (ShuffleSongs.IsNot(SONGSHUFFLE_ANYWHERE)) { + if (ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_ANYWHERE)) { //Get each song std::vector songs = FilterAndEraseFromPool( @@ -1049,11 +1052,11 @@ int Fill() { //Get each song location std::vector songLocations; - if (ShuffleSongs.Is(SONGSHUFFLE_SONG_LOCATIONS)) { + if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_SONG_LOCATIONS)) { songLocations = FilterFromPool( ctx->allLocations, [](const auto loc) { return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cSong); }); - } else if (ShuffleSongs.Is(SONGSHUFFLE_DUNGEON_REWARDS)) { + } else if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_DUNGEON_REWARDS)) { songLocations = FilterFromPool(ctx->allLocations, [](const auto loc) { return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cSongDungeonReward); }); @@ -1077,14 +1080,14 @@ int Fill() { FastFill(remainingPool, GetAllEmptyLocations(), false); //Add prices for scrubsanity, this is unique to SoH because we write/read scrub prices to/from the spoilerfile. - if (Scrubsanity.Is(SCRUBSANITY_AFFORDABLE)) { + if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_AFFORDABLE)) { for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) { - ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetScrubsanityPrice(10); + ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10); } - } else if (Scrubsanity.Is(SCRUBSANITY_RANDOM_PRICES)) { + } else if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_RANDOM)) { for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) { int randomPrice = GetRandomScrubPrice(); - ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetScrubsanityPrice(randomPrice); + ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(randomPrice); } } @@ -1097,8 +1100,8 @@ int Fill() { CalculateWotH(); printf("Done"); ctx->CreateItemOverrides(); - CreateEntranceOverrides(); - + ctx->GetEntranceShuffler()->CreateEntranceOverrides(); + //funny ganon line Text ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText(); CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText)); diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 51764763e..4931c147d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -2,6 +2,7 @@ #include "custom_messages.hpp" #include "../randomizerTypes.h" +#include "../context.h" #include @@ -3238,58 +3239,61 @@ void HintTable_Init() { } int32_t StonesRequiredBySettings() { + auto ctx = Rando::Context::GetInstance(); int32_t stones = 0; - if (Settings::Bridge.Is(RAINBOWBRIDGE_STONES)) { - stones = std::max({ stones, (int32_t)Settings::BridgeStoneCount.Value() }); + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) { + stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Value() }); } - if (Settings::Bridge.Is(RAINBOWBRIDGE_REWARDS)) { - stones = std::max({ stones, (int32_t)Settings::BridgeRewardCount.Value() - 6 }); + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { + stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value() - 6 }); } - if ((Settings::Bridge.Is(RAINBOWBRIDGE_DUNGEONS)) && (Settings::ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON))) { - stones = std::max({ stones, (int32_t)Settings::BridgeDungeonCount.Value() - 6 }); + if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) { + stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value() - 6 }); } - if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_STONES)) { - stones = std::max({ stones, (int32_t)Settings::LACSStoneCount.Value() }); + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { + stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_LACS_STONE_COUNT).Value() }); } - if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_REWARDS)) { - stones = std::max({ stones, (int32_t)Settings::LACSRewardCount.Value() - 6 }); + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { + stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_LACS_REWARD_COUNT).Value() - 6 }); } - if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_DUNGEONS)) { - stones = std::max({ stones, (int32_t)Settings::LACSDungeonCount.Value() - 6 }); + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { + stones = std::max({ stones, (int32_t)ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value() - 6 }); } return stones; } int32_t MedallionsRequiredBySettings() { + auto ctx = Rando::Context::GetInstance(); int32_t medallions = 0; - if (Settings::Bridge.Is(RAINBOWBRIDGE_MEDALLIONS)) { - medallions = std::max({ medallions, (int32_t)Settings::BridgeMedallionCount.Value() }); + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) { + medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Value() }); } - if (Settings::Bridge.Is(RAINBOWBRIDGE_REWARDS)) { - medallions = std::max({ medallions, (int32_t)Settings::BridgeRewardCount.Value() - 3 }); + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { + medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value() - 3 }); } - if ((Settings::Bridge.Is(RAINBOWBRIDGE_DUNGEONS)) && (Settings::ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON))) { - medallions = std::max({ medallions, (int32_t)Settings::BridgeDungeonCount.Value() - 3 }); + if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) { + medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value() - 3 }); } - if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_MEDALLIONS)) { - medallions = std::max({ medallions, (int32_t)Settings::LACSMedallionCount.Value() }); + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) { + medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Value() }); } - if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_REWARDS)) { - medallions = std::max({ medallions, (int32_t)Settings::LACSRewardCount.Value() - 3 }); + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) { + medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_LACS_REWARD_COUNT).Value() - 3 }); } - if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_DUNGEONS)) { - medallions = std::max({ medallions, (int32_t)Settings::LACSDungeonCount.Value() - 3 }); + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { + medallions = std::max({ medallions, (int32_t)ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value() - 3 }); } return medallions; } int32_t TokensRequiredBySettings() { + auto ctx = Rando::Context::GetInstance(); int32_t tokens = 0; - if (Settings::Bridge.Is(RAINBOWBRIDGE_TOKENS)) { - tokens = std::max({ tokens, (int32_t)Settings::BridgeTokenCount.Value() }); + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) { + tokens = std::max({ tokens, (int32_t)ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value() }); } - if (Settings::GanonsBossKey.Is(GANONSBOSSKEY_LACS_TOKENS)) { - tokens = std::max({ tokens, (int32_t)Settings::LACSTokenCount.Value() }); + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) { + tokens = std::max({ tokens, (int32_t)ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value() }); } return tokens; } @@ -3297,17 +3301,38 @@ int32_t TokensRequiredBySettings() { std::array conditionalAlwaysHints = { std::make_pair(RC_MARKET_10_BIG_POES, []() { - return Settings::BigPoeTargetCount.Value() >= 3; + auto ctx = Rando::Context::GetInstance(); + return ctx->GetOption(RSK_BIG_POE_COUNT).Value() >= 3; }), // Remember, the option's value being 3 means 4 are required - std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() { return !Settings::CompleteMaskQuest; }), + std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, + []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_COMPLETE_MASK_QUEST); + }), std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME, []() { return StonesRequiredBySettings() < 2; }), std::make_pair(RC_HF_OCARINA_OF_TIME_ITEM, []() { return StonesRequiredBySettings() < 2; }), std::make_pair(RC_SHEIK_IN_KAKARIKO, []() { return MedallionsRequiredBySettings() < 5; }), std::make_pair(RC_DMT_TRADE_CLAIM_CHECK, []() { return false; }), - std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 30 && !Settings::Kak30GSHintText; }), - std::make_pair(RC_KAK_40_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 40 && !Settings::Kak40GSHintText; }), - std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD, []() { return TokensRequiredBySettings() < 50 && !Settings::Kak50GSHintText; }), - std::make_pair(RC_ZR_FROGS_OCARINA_GAME, []() { return !Settings::FrogsHintText; }), + std::make_pair(RC_KAK_30_GOLD_SKULLTULA_REWARD, + []() { + auto ctx = Rando::Context::GetInstance(); + return TokensRequiredBySettings() < 30 && !ctx->GetOption(RSK_KAK_30_SKULLS_HINT); + }), + std::make_pair(RC_KAK_40_GOLD_SKULLTULA_REWARD, + []() { + auto ctx = Rando::Context::GetInstance(); + return TokensRequiredBySettings() < 40 && !ctx->GetOption(RSK_KAK_40_SKULLS_HINT); + }), + std::make_pair(RC_KAK_50_GOLD_SKULLTULA_REWARD, + []() { + auto ctx = Rando::Context::GetInstance(); + return TokensRequiredBySettings() < 50 && !ctx->GetOption(RSK_KAK_50_SKULLS_HINT); + }), + std::make_pair(RC_ZR_FROGS_OCARINA_GAME, + []() { + auto ctx = Rando::Context::GetInstance(); + return !ctx->GetOption(RSK_FROGS_HINT); + }), }; const HintText& Hint(const RandomizerHintTextKey hintKey) { diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index dc57a5b71..3892c70d9 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -1,24 +1,45 @@ #include "hints.hpp" #include "custom_messages.hpp" -#include "dungeon.hpp" #include "item_pool.hpp" #include "logic.hpp" #include "random.hpp" #include "spoiler_log.hpp" #include "fill.hpp" #include "hint_list.hpp" -#include "trial.hpp" -#include "entrance.hpp" +#include "../trial.h" +#include "../entrance.h" #include "z64item.h" #include #include "../randomizerTypes.h" #include "../context.h" +#include "pool_functions.hpp" using namespace CustomMessages; using namespace Logic; -using namespace Settings; -using namespace Trial; +using namespace Rando; + +const Text& HintText::GetText() const { + auto ctx = Rando::Context::GetInstance(); + if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)) { + return GetObscure(); + } else if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS)) { + return GetAmbiguous(); + } else { + return GetClear(); + } +} + +const Text HintText::GetTextCopy() const { + auto ctx = Rando::Context::GetInstance(); + if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_OBSCURE)) { + return GetObscure(); + } else if (ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS)) { + return GetAmbiguous(); + } else { + return GetClear(); + } +} std::array hintTypeNames = { "Static", @@ -126,6 +147,61 @@ constexpr std::array hintSettingTable{{ }, }}; +Text AutoFormatHintText(Text unformattedHintText) { + std::array strings; + for (int i = 0; i < LANGUAGE_MAX; i++) { + std::string textStr = unformattedHintText.GetForLanguage(i); + // RANDOTODO: don't just make manual exceptions + bool needsAutomaicNewlines = true; + if (textStr == "Erreur 0x69a504:&Traduction manquante^C'est de la faute à Purple Hato!&J'vous jure!" || + textStr == "Mon très cher @:&Viens vite au château, je t'ai préparé&un délicieux gâteau...^À bientôt, Princesse Zelda" || + textStr == "What about Zelda makes you think&she'd be a better ruler than I?^I saved Lon Lon Ranch,&fed the hungry,&and my castle floats." || + textStr == "Many tricks are up my sleeve,&to save yourself&you'd better leave!" || + textStr == "I've learned this spell,&it's really neat,&I'll keep it later&for your treat!" || + textStr == "Sale petit garnement,&tu fais erreur!&C'est maintenant que marque&ta dernière heure!" || + textStr == "Gamin, ton destin achève,&sous mon sort tu périras!&Cette partie ne fut pas brève,&et cette mort, tu subiras!" || + textStr == "Oh! It's @.&I was expecting someone called Sheik.&Do you know what happened to them?" || + textStr == "Ah, c'est @.&J'attendais un certain Sheik.&Tu sais ce qui lui est arrivé?" || + textStr == "They say \"Forgive me, but-^Your script will not be used.&....After all...^The one writing the rest of the script...&will be me.\"") { + needsAutomaicNewlines = false; + } + + if (needsAutomaicNewlines) { + // insert newlines either manually or when encountering a '&' + constexpr size_t lineLength = 34; + size_t lastNewline = 0; + while (lastNewline + lineLength < textStr.length()) { + size_t carrot = textStr.find('^', lastNewline); + size_t ampersand = textStr.find('&', lastNewline); + size_t lastSpace = textStr.rfind(' ', lastNewline + lineLength); + size_t lastPeriod = textStr.rfind('.', lastNewline + lineLength); + // replace '&' first if it's within the newline range + if (ampersand < lastNewline + lineLength) { + lastNewline = ampersand; + // or move the lastNewline cursor to the next line if a '^' is encountered + } else if (carrot < lastNewline + lineLength) { + lastNewline = carrot + 1; + // some lines need to be split but don't have spaces, look for periods instead + } else if (lastSpace == std::string::npos) { + textStr.replace(lastPeriod, 1, ".&"); + lastNewline = lastPeriod + 2; + } else { + textStr.replace(lastSpace, 1, "&"); + lastNewline = lastSpace + 1; + } + } + } + + // todo add colors (see `AddColorsAndFormat` in `custom_messages.cpp`) + textStr.erase(std::remove(textStr.begin(), textStr.end(), '#'), textStr.end()); + strings[i] = textStr; + } + + return Text(strings[0], strings[1], strings[2]); +} + +std::array dungeonInfoData; + Text childAltarText; Text adultAltarText; Text ganonText; @@ -328,7 +404,7 @@ static void AddHint(Text hint, const RandomizerCheck gossipStone, const std::vec //GetLocation(gossipStone)->SetPlacedItem(gossipStone); auto ctx = Rando::Context::GetInstance(); - ctx->AddHint((RandomizerHintKey)((gossipStone - RC_DMC_GOSSIP_STONE) + 1), hint, hintedLocation, hintType, GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText()); + ctx->AddHint((RandomizerHintKey)((gossipStone - RC_COLOSSUS_GOSSIP_STONE) + 1), AutoFormatHintText(hint), hintedLocation, hintType, GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText()); ctx->GetItemLocation(gossipStone)->SetPlacedItem(RG_HINT); } @@ -366,31 +442,31 @@ static bool CreateHint(RandomizerCheck hintedLocation, uint8_t copies, HintType //make hint text Text finalHint; - Text prefix = Hint(RHT_PREFIX).GetText(); + Text prefix = ::Hint(RHT_PREFIX).GetText(); std::vector colours = {QM_GREEN, QM_RED}; if (type == HINT_TYPE_WOTH){ Text regionText = GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText(); - finalHint = prefix + "%r#" + regionText + "#%w" + Hint(RHT_WAY_OF_THE_HERO).GetText(); + finalHint = prefix + "%r#" + regionText + "#%w" + ::Hint(RHT_WAY_OF_THE_HERO).GetText(); colours = {QM_LBLUE}; } else if(type == HINT_TYPE_BARREN){ Text regionText = GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText(); - finalHint = prefix + Hint(RHT_PLUNDERING).GetText() + "%r#" + regionText + "#%w" + Hint(RHT_FOOLISH).GetText(); + finalHint = prefix + ::Hint(RHT_PLUNDERING).GetText() + "%r#" + regionText + "#%w" + ::Hint(RHT_FOOLISH).GetText(); colours = {QM_PINK}; } else { Text itemText = ctx->GetItemLocation(hintedLocation)->GetPlacedItem().GetHint().GetText(); if (type >= HINT_TYPE_ALWAYS && type < HINT_TYPE_NAMED_ITEM){ Text locationText = Rando::StaticData::GetLocation(hintedLocation)->GetHint()->GetText(); - finalHint = prefix + locationText + " #"+itemText+"#."; + finalHint = prefix + "%r" + locationText + " %g#"+itemText+"#%w."; } else if (type == HINT_TYPE_NAMED_ITEM || type == HINT_TYPE_RANDOM){ Text regionText = GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText(); // RANDOTODO: reconsider dungeon vs non-dungeon item location hints when boss shuffle mixed pools happens if (Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()) { - finalHint = prefix+"%r#"+regionText+"#%w "+Hint(RHT_HOARDS).GetText()+" %g#"+itemText+"#%w."; + finalHint = prefix+"%r#"+regionText+"#%w "+::Hint(RHT_HOARDS).GetText()+" %g#"+itemText+"#%w."; } else { - finalHint = prefix+"%r#"+itemText+"#%w "+Hint(RHT_CAN_BE_FOUND_AT).GetText()+" %g#"+regionText+"#%w."; + finalHint = prefix+"%r#"+itemText+"#%w "+::Hint(RHT_CAN_BE_FOUND_AT).GetText()+" %g#"+regionText+"#%w."; colours = {QM_RED, QM_GREEN}; } } @@ -500,37 +576,40 @@ static std::vector CalculateBarrenRegions() { } static void CreateTrialHints(uint8_t copies) { - Text prefix = Hint(RHT_PREFIX).GetText(); + auto ctx = Rando::Context::GetInstance(); + Text prefix = ::Hint(RHT_PREFIX).GetText(); //six trials - if (RandomGanonsTrials && GanonsTrialsCount.Is(6)) { - AddHintCopies(copies, prefix + Hint(RHT_SIX_TRIALS).GetText(), {QM_PINK}, HINT_TYPE_TRIAL); + if (ctx->GetOption(RSK_GANONS_TRIALS).IsNot(RO_GANONS_TRIALS_SKIP) && ctx->GetOption(RSK_TRIAL_COUNT).Is(6)) { + AddHintCopies(copies, prefix + ::Hint(RHT_SIX_TRIALS).GetText(), {QM_PINK}, HINT_TYPE_TRIAL); //zero trials - } else if (RandomGanonsTrials && GanonsTrialsCount.Is(0)) { - AddHintCopies(copies, prefix + Hint(RHT_ZERO_TRIALS).GetText(), {QM_YELLOW}, HINT_TYPE_TRIAL); + } else if (ctx->GetOption(RSK_GANONS_TRIALS).IsNot(RO_GANONS_TRIALS_SKIP) && ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) { + AddHintCopies(copies, prefix + ::Hint(RHT_ZERO_TRIALS).GetText(), {QM_YELLOW}, HINT_TYPE_TRIAL); //4 or 5 required trials - } else if (GanonsTrialsCount.Is(5) || GanonsTrialsCount.Is(4)) { + } else if (ctx->GetOption(RSK_TRIAL_COUNT).Is(5) || ctx->GetOption(RSK_TRIAL_COUNT).Is(4)) { //get skipped trials std::vector trials = {}; + auto trialList = ctx->GetTrials()->GetTrialList(); trials.assign(trialList.begin(), trialList.end()); auto skippedTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsSkipped();}); //create a hint for each skipped trial for (auto& trial : skippedTrials) { //make hint - auto hint = prefix+"#"+trial->GetName()+"#"+Hint(RHT_FOUR_TO_FIVE_TRIALS).GetText(); + auto hint = prefix+"#"+trial->GetName()+"#"+::Hint(RHT_FOUR_TO_FIVE_TRIALS).GetText(); AddHintCopies(copies, hint, {QM_YELLOW}, HINT_TYPE_TRIAL); } //1 to 3 trials - } else if (GanonsTrialsCount.Value() >= 1 && GanonsTrialsCount.Value() <= 3) { + } else if (ctx->GetOption(RSK_TRIAL_COUNT).Value() >= 1 && ctx->GetOption(RSK_TRIAL_COUNT).Value() <= 3) { //get requried trials std::vector trials = {}; + auto trialList = ctx->GetTrials()->GetTrialList(); trials.assign(trialList.begin(), trialList.end()); auto requiredTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsRequired();}); //create a hint for each required trial for (auto& trial : requiredTrials) { //make hint - auto hint = prefix+"#"+trial->GetName()+"#"+Hint(RHT_ONE_TO_THREE_TRIALS).GetText(); + auto hint = prefix+"#"+trial->GetName()+"#"+::Hint(RHT_ONE_TO_THREE_TRIALS).GetText(); AddHintCopies(copies, hint, {QM_PINK}, HINT_TYPE_TRIAL); } } @@ -539,7 +618,7 @@ static void CreateTrialHints(uint8_t copies) { //RANDOTODO clean this mess up once starting items are expanded void CreateGanonAndSheikText() { auto ctx = Rando::Context::GetInstance(); - if(Settings::LightArrowHintText){ + if(ctx->GetOption(RSK_LIGHT_ARROWS_HINT)){ //Get the location of the light arrows auto lightArrowLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) { return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_LIGHT_ARROWS; @@ -548,9 +627,9 @@ void CreateGanonAndSheikText() { std::vector locsToCheck = {RC_GANONDORF_HINT}; //If there is no light arrow location, it was in the player's inventory at the start - auto hint = Hint(RHT_LIGHT_ARROW_LOCATION_HINT); + auto hint = ::Hint(RHT_LIGHT_ARROW_LOCATION_HINT); if (lightArrowLocation.empty()) { - ganonHintText = hint.GetText()+Hint(RHT_YOUR_POCKET).GetText(); + ganonHintText = hint.GetText()+::Hint(RHT_YOUR_POCKET).GetText(); lightArrowHintLoc = "Link's Pocket"; } else { ganonHintText = hint.GetText() + "%r" + lightArrowArea + "%w"; @@ -564,36 +643,37 @@ void CreateGanonAndSheikText() { }); Text masterSwordArea = GetHintRegion(ctx->GetItemLocation(masterSwordLocation[0])->GetParentRegionKey())->GetHint().GetText(); - if (ShuffleMasterSword) { + if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) { // Add second text box ganonHintText = ganonHintText + "^"; if (masterSwordLocation.empty()) { - ganonHintText = ganonHintText + Hint(RHT_MASTER_SWORD_LOCATION_HINT).GetText() + "%r" + Hint(RHT_YOUR_POCKET).GetText() + "%w"; + ganonHintText = ganonHintText + ::Hint(RHT_MASTER_SWORD_LOCATION_HINT).GetText() + "%r" + ::Hint(RHT_YOUR_POCKET).GetText() + "%w"; masterSwordHintLoc = "Link's Pocket"; } else { - ganonHintText = ganonHintText + Hint(RHT_MASTER_SWORD_LOCATION_HINT).GetText() + "%r" + masterSwordArea + "%w"; + ganonHintText = ganonHintText + ::Hint(RHT_MASTER_SWORD_LOCATION_HINT).GetText() + "%r" + masterSwordArea + "%w"; masterSwordHintLoc = Rando::StaticData::GetLocation(masterSwordLocation[0])->GetName(); } ganonHintText = ganonHintText + "!"; } - CreateMessageFromTextObject(0x70CC, 0, 2, 3, AddColorsAndFormat(ganonHintText)); - ctx->AddHint(RH_GANONDORF_HINT, ganonHintText, lightArrowLocation[0], HINT_TYPE_STATIC, GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText()); + //CreateMessageFromTextObject(0x70CC, 0, 2, 3, AddColorsAndFormat(ganonHintText)); + ctx->AddHint(RH_GANONDORF_HINT, AutoFormatHintText(ganonHintText), lightArrowLocation[0], HINT_TYPE_STATIC, GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText()); - if (!Settings::GanonsTrialsCount.Is(0)) { - sheikText = Hint(RHT_SHEIK_LIGHT_ARROW_HINT).GetText() + lightArrowArea + "%w."; + if(!ctx->GetOption(RSK_TRIAL_COUNT).Is(0)){ + sheikText = ::Hint(RHT_SHEIK_LIGHT_ARROW_HINT).GetText() + lightArrowArea + "%w."; locsToCheck = {RC_GANONDORF_HINT, RC_SHEIK_HINT_GC, RC_SHEIK_HINT_MQ_GC}; - if (ShuffleMasterSword) { - sheikText = sheikText + "^" + Hint(RHT_SHEIK_MASTER_SWORD_LOCATION_HINT).GetText() + masterSwordArea + "%w."; + if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) { + sheikText = sheikText + "^" + ::Hint(RHT_SHEIK_MASTER_SWORD_LOCATION_HINT).GetText() + masterSwordArea + "%w."; } } if (IsReachableWithout(locsToCheck, lightArrowLocation[0], true)) { ctx->GetItemLocation(lightArrowLocation[0])->SetAsHinted(); } + ctx->AddHint(RH_SHEIK_LIGHT_ARROWS, AutoFormatHintText(sheikText), lightArrowLocation[0], HINT_TYPE_STATIC, lightArrowArea); - if (ShuffleMasterSword) { + if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) { if (IsReachableWithout(locsToCheck, masterSwordLocation[0], true)) { ctx->GetItemLocation(masterSwordLocation[0])->SetHintKey(RH_GANONDORF_HINT); ctx->GetItemLocation(masterSwordLocation[0])->SetAsHinted(); @@ -610,7 +690,7 @@ static Text BuildDungeonRewardText(const RandomizerGet itemKey, bool isChild) { RandomizerCheck location = FilterFromPool(ctx->allLocations, [itemKey, ctx](const RandomizerCheck loc) { return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == itemKey; })[0]; - if (IsReachableWithout({altarLoc}, location, true) || ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON)){ //RANDOTODO check if works properly + if (IsReachableWithout({altarLoc}, location, true) || ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)){ //RANDOTODO check if works properly ctx->GetItemLocation(location)->SetAsHinted(); } @@ -623,28 +703,29 @@ static Text BuildDungeonRewardText(const RandomizerGet itemKey, bool isChild) { } static Text BuildDoorOfTimeText() { + auto ctx = Rando::Context::GetInstance(); std::string itemObtained; Text doorOfTimeText; - if (OpenDoorOfTime.Is(OPENDOOROFTIME_OPEN)) { + if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN)) { itemObtained = "$o"; - doorOfTimeText = Hint(RHT_CHILD_ALTAR_TEXT_END_DOTOPEN).GetText(); + doorOfTimeText = ::Hint(RHT_CHILD_ALTAR_TEXT_END_DOTOPEN).GetText(); - } else if (OpenDoorOfTime.Is(OPENDOOROFTIME_SONGONLY)) { + } else if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_SONGONLY)) { itemObtained = "$c"; - doorOfTimeText = Hint(RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY).GetText(); + doorOfTimeText = ::Hint(RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY).GetText(); - } else if (OpenDoorOfTime.Is(OPENDOOROFTIME_CLOSED)) { + } else if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_CLOSED)) { itemObtained = "$i"; - doorOfTimeText = Hint(RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED).GetText(); + doorOfTimeText = ::Hint(RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED).GetText(); } return Text()+itemObtained+doorOfTimeText; } //insert the required number into the hint and set the singular/plural form -static Text BuildCountReq(const RandomizerHintTextKey req, const Option& count) { - Text requirement = Hint(req).GetTextCopy(); +static Text BuildCountReq(const RandomizerHintTextKey req, const Rando::Option& count) { + Text requirement = ::Hint(req).GetTextCopy(); if (count.Value() == 1) { requirement.SetForm(SINGULAR); } else { @@ -655,80 +736,82 @@ static Text BuildCountReq(const RandomizerHintTextKey req, const Option& count) } static Text BuildBridgeReqsText() { + auto ctx = Rando::Context::GetInstance(); Text bridgeText; - if (Bridge.Is(RAINBOWBRIDGE_OPEN)) { - bridgeText = Hint(RHT_BRIDGE_OPEN_HINT).GetText(); + if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN)) { + bridgeText = ::Hint(RHT_BRIDGE_OPEN_HINT).GetText(); - } else if (Bridge.Is(RAINBOWBRIDGE_VANILLA)) { - bridgeText = Hint(RHT_BRIDGE_VANILLA_HINT).GetText(); + } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA)) { + bridgeText = ::Hint(RHT_BRIDGE_VANILLA_HINT).GetText(); - } else if (Bridge.Is(RAINBOWBRIDGE_STONES)) { - bridgeText = BuildCountReq(RHT_BRIDGE_STONES_HINT, BridgeStoneCount); + } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) { + bridgeText = BuildCountReq(RHT_BRIDGE_STONES_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT)); - } else if (Bridge.Is(RAINBOWBRIDGE_MEDALLIONS)) { - bridgeText = BuildCountReq(RHT_BRIDGE_MEDALLIONS_HINT, BridgeMedallionCount); + } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) { + bridgeText = BuildCountReq(RHT_BRIDGE_MEDALLIONS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT)); - } else if (Bridge.Is(RAINBOWBRIDGE_REWARDS)) { - bridgeText = BuildCountReq(RHT_BRIDGE_REWARDS_HINT, BridgeRewardCount); + } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { + bridgeText = BuildCountReq(RHT_BRIDGE_REWARDS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT)); - } else if (Bridge.Is(RAINBOWBRIDGE_DUNGEONS)) { - bridgeText = BuildCountReq(RHT_BRIDGE_DUNGEONS_HINT, BridgeDungeonCount); + } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) { + bridgeText = BuildCountReq(RHT_BRIDGE_DUNGEONS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT)); - } else if (Bridge.Is(RAINBOWBRIDGE_TOKENS)) { - bridgeText = BuildCountReq(RHT_BRIDGE_TOKENS_HINT, BridgeTokenCount); - - } else if (Bridge.Is(RAINBOWBRIDGE_GREG)) { - bridgeText = Hint(RHT_BRIDGE_GREG_HINT).GetText(); + } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) { + bridgeText = BuildCountReq(RHT_BRIDGE_TOKENS_HINT, ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT)); + + } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)) { + bridgeText = ::Hint(RHT_BRIDGE_GREG_HINT).GetText(); } return Text()+"$l"+bridgeText+"^"; } static Text BuildGanonBossKeyText() { + auto ctx = Rando::Context::GetInstance(); Text ganonBossKeyText; - if (GanonsBossKey.Is(GANONSBOSSKEY_START_WITH)) { - ganonBossKeyText = Hint(RHT_GANON_BK_START_WITH_HINT).GetText(); + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH)) { + ganonBossKeyText = ::Hint(RHT_GANON_BK_START_WITH_HINT).GetText(); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA)) { - ganonBossKeyText = Hint(RHT_GANON_BK_VANILLA_HINT).GetText(); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) { + ganonBossKeyText = ::Hint(RHT_GANON_BK_VANILLA_HINT).GetText(); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON)) { - ganonBossKeyText = Hint(RHT_GANON_BK_OWN_DUNGEON_HINT).GetText(); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON)) { + ganonBossKeyText = ::Hint(RHT_GANON_BK_OWN_DUNGEON_HINT).GetText(); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_ANY_DUNGEON)) { - ganonBossKeyText = Hint(RHT_GANON_BK_ANY_DUNGEON_HINT).GetText(); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) { + ganonBossKeyText = ::Hint(RHT_GANON_BK_ANY_DUNGEON_HINT).GetText(); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_OVERWORLD)) { - ganonBossKeyText = Hint(RHT_GANON_BK_OVERWORLD_HINT).GetText(); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) { + ganonBossKeyText = ::Hint(RHT_GANON_BK_OVERWORLD_HINT).GetText(); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_ANYWHERE)) { - ganonBossKeyText = Hint(RHT_GANON_BK_ANYWHERE_HINT).GetText(); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANYWHERE)) { + ganonBossKeyText = ::Hint(RHT_GANON_BK_ANYWHERE_HINT).GetText(); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_FINAL_GS_REWARD)) { - ganonBossKeyText = Hint(RHT_GANON_BK_SKULLTULA_HINT).GetText(); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) { + ganonBossKeyText = ::Hint(RHT_GANON_BK_SKULLTULA_HINT).GetText(); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_VANILLA)) { - ganonBossKeyText = Hint(RHT_LACS_VANILLA_HINT).GetText(); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_VANILLA)) { + ganonBossKeyText = ::Hint(RHT_LACS_VANILLA_HINT).GetText(); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_STONES)) { - ganonBossKeyText = BuildCountReq(RHT_LACS_STONES_HINT, LACSStoneCount); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { + ganonBossKeyText = BuildCountReq(RHT_LACS_STONES_HINT, ctx->GetOption(RSK_LACS_STONE_COUNT)); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_MEDALLIONS)) { - ganonBossKeyText = BuildCountReq(RHT_LACS_MEDALLIONS_HINT, LACSMedallionCount); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) { + ganonBossKeyText = BuildCountReq(RHT_LACS_MEDALLIONS_HINT, ctx->GetOption(RSK_LACS_MEDALLION_COUNT)); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_REWARDS)) { - ganonBossKeyText = BuildCountReq(RHT_LACS_REWARDS_HINT, LACSRewardCount); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) { + ganonBossKeyText = BuildCountReq(RHT_LACS_REWARDS_HINT, ctx->GetOption(RSK_LACS_REWARD_COUNT)); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_DUNGEONS)) { - ganonBossKeyText = BuildCountReq(RHT_LACS_DUNGEONS_HINT, LACSDungeonCount); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { + ganonBossKeyText = BuildCountReq(RHT_LACS_DUNGEONS_HINT, ctx->GetOption(RSK_LACS_DUNGEON_COUNT)); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_TOKENS)) { - ganonBossKeyText = BuildCountReq(RHT_LACS_TOKENS_HINT, LACSTokenCount); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) { + ganonBossKeyText = BuildCountReq(RHT_LACS_TOKENS_HINT, ctx->GetOption(RSK_LACS_TOKEN_COUNT)); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_TRIFORCE_HUNT)) { - ganonBossKeyText = Hint(RHT_GANON_BK_TRIFORCE_HINT).GetText(); + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) { + ganonBossKeyText = ::Hint(RHT_GANON_BK_TRIFORCE_HINT).GetText(); } return Text()+"$b"+ganonBossKeyText+"^"; @@ -738,14 +821,15 @@ void CreateAltarText() { auto ctx = Rando::Context::GetInstance(); //Child Altar Text - if (AltarHintText) { - childAltarText = Hint(RHT_SPIRITUAL_STONE_TEXT_START).GetText()+"^"+ + if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { + childAltarText = ::Hint(RHT_SPIRITUAL_STONE_TEXT_START).GetText()+"^"+ //Spiritual Stones - (StartingKokiriEmerald.Value() ? Text{ "##", "##", "##" } + // TODO: Starting Inventory Dungeon Rewards + (/*StartingKokiriEmerald.Value()*/false ? Text{ "##", "##", "##" } : BuildDungeonRewardText(RG_KOKIRI_EMERALD, true)) + - (StartingGoronRuby.Value() ? Text{ "##", "##", "##" } + (/*StartingGoronRuby.Value()*/false ? Text{ "##", "##", "##" } : BuildDungeonRewardText(RG_GORON_RUBY, true)) + - (StartingZoraSapphire.Value() ? Text{ "##", "##", "##" } + (/*StartingZoraSapphire.Value()*/false ? Text{ "##", "##", "##" } : BuildDungeonRewardText(RG_ZORA_SAPPHIRE, true)) + //How to open Door of Time, the event trigger is necessary to read the altar multiple times BuildDoorOfTimeText(); @@ -754,24 +838,24 @@ void CreateAltarText() { } ctx->AddHint(RH_ALTAR_CHILD, childAltarText, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text()); - CreateMessageFromTextObject(0x7040, 0, 2, 3, AddColorsAndFormat(childAltarText, {QM_GREEN, QM_RED, QM_BLUE})); + //CreateMessageFromTextObject(0x7040, 0, 2, 3, AddColorsAndFormat(childAltarText, {QM_GREEN, QM_RED, QM_BLUE})); //Adult Altar Text - adultAltarText = Hint(RHT_ADULT_ALTAR_TEXT_START).GetText() + "^"; - if (AltarHintText) { + adultAltarText = ::Hint(RHT_ADULT_ALTAR_TEXT_START).GetText() + "^"; + if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { adultAltarText = adultAltarText + //Medallion Areas - (StartingLightMedallion.Value() ? Text{ "##", "##", "##" } + (/*StartingLightMedallion.Value()*/false ? Text{ "##", "##", "##" } : BuildDungeonRewardText(RG_LIGHT_MEDALLION, false)) + - (StartingForestMedallion.Value() ? Text{ "##", "##", "##" } + (/*StartingForestMedallion.Value()*/false ? Text{ "##", "##", "##" } : BuildDungeonRewardText(RG_FOREST_MEDALLION, false)) + - (StartingFireMedallion.Value() ? Text{ "##", "##", "##" } + (/*StartingFireMedallion.Value()*/false ? Text{ "##", "##", "##" } : BuildDungeonRewardText(RG_FIRE_MEDALLION, false)) + - (StartingWaterMedallion.Value() ? Text{ "##", "##", "##" } + (/*StartingWaterMedallion.Value()*/false ? Text{ "##", "##", "##" } : BuildDungeonRewardText(RG_WATER_MEDALLION, false)) + - (StartingSpiritMedallion.Value() ? Text{ "##", "##", "##" } + (/*StartingSpiritMedallion.Value()*/false ? Text{ "##", "##", "##" } : BuildDungeonRewardText(RG_SPIRIT_MEDALLION, false)) + - (StartingShadowMedallion.Value() ? Text{ "##", "##", "##" } + (/*StartingShadowMedallion.Value()*/false ? Text{ "##", "##", "##" } : BuildDungeonRewardText(RG_SHADOW_MEDALLION, false)); } adultAltarText = adultAltarText + @@ -782,8 +866,8 @@ void CreateAltarText() { BuildGanonBossKeyText()+ //End - Hint(RHT_ADULT_ALTAR_TEXT_END).GetText(); - CreateMessageFromTextObject(0x7088, 0, 2, 3, AddColorsAndFormat(adultAltarText, {QM_RED, QM_YELLOW, QM_GREEN, QM_RED, QM_BLUE, QM_YELLOW, QM_PINK, QM_RED, QM_RED, QM_RED, QM_RED})); + ::Hint(RHT_ADULT_ALTAR_TEXT_END).GetText(); + //CreateMessageFromTextObject(0x7088, 0, 2, 3, AddColorsAndFormat(adultAltarText, {QM_RED, QM_YELLOW, QM_GREEN, QM_RED, QM_BLUE, QM_YELLOW, QM_PINK, QM_RED, QM_RED, QM_RED, QM_RED})); ctx->AddHint(RH_ALTAR_ADULT, adultAltarText, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text()); } @@ -798,25 +882,25 @@ void CreateMerchantsHints() { Text medigoronText = - Hint(RHT_MEDIGORON_DIALOG_FIRST).GetText() + medigoronItemText + Hint(RHT_MEDIGORON_DIALOG_SECOND).GetText(); - Text grannyText = grannyItemText + Hint(RHT_GRANNY_DIALOG).GetText(); - Text carpetSalesmanTextOne = Hint(RHT_CARPET_SALESMAN_DIALOG_FIRST).GetText() + carpetSalesmanItemText + - Hint(RHT_CARPET_SALESMAN_DIALOG_SECOND).GetText(); - Text carpetSalesmanTextTwo = Hint(RHT_CARPET_SALESMAN_DIALOG_THIRD).GetText() + carpetSalesmanItemClearText + - Hint(RHT_CARPET_SALESMAN_DIALOG_FOURTH).GetText(); + ::Hint(RHT_MEDIGORON_DIALOG_FIRST).GetText() + medigoronItemText + ::Hint(RHT_MEDIGORON_DIALOG_SECOND).GetText(); + Text grannyText = grannyItemText + ::Hint(RHT_GRANNY_DIALOG).GetText(); + Text carpetSalesmanTextOne = ::Hint(RHT_CARPET_SALESMAN_DIALOG_FIRST).GetText() + carpetSalesmanItemText + + ::Hint(RHT_CARPET_SALESMAN_DIALOG_SECOND).GetText(); + Text carpetSalesmanTextTwo = ::Hint(RHT_CARPET_SALESMAN_DIALOG_THIRD).GetText() + carpetSalesmanItemClearText + + ::Hint(RHT_CARPET_SALESMAN_DIALOG_FOURTH).GetText(); - CreateMessageFromTextObject(0x9120, 0, 2, 3, AddColorsAndFormat(medigoronText, { QM_RED, QM_GREEN })); - CreateMessageFromTextObject(0x9121, 0, 2, 3, AddColorsAndFormat(grannyText, { QM_RED, QM_GREEN })); - CreateMessageFromTextObject(0x6077, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextOne, { QM_RED, QM_GREEN })); - CreateMessageFromTextObject(0x6078, 0, 2, 3, - AddColorsAndFormat(carpetSalesmanTextTwo, { QM_RED, QM_YELLOW, QM_RED })); - ctx->AddHint(RH_MEDIGORON, medigoronText, RC_GC_MEDIGORON, HINT_TYPE_STATIC, GetHintRegion(RR_GORON_CITY)->GetHint().GetText()); - ctx->AddHint(RH_GRANNYS_SHOP, grannyText, RC_KAK_GRANNYS_SHOP, HINT_TYPE_STATIC, GetHintRegion(RR_KAKARIKO_VILLAGE)->GetHint().GetText()); - ctx->AddHint(RH_WASTELAND_BOMBCHU_SALESMAN, carpetSalesmanTextOne, RC_WASTELAND_BOMBCHU_SALESMAN, HINT_TYPE_STATIC, GetHintRegion(RR_HAUNTED_WASTELAND)->GetHint().GetText()); + // CreateMessageFromTextObject(0x9120, 0, 2, 3, AddColorsAndFormat(medigoronText, { QM_RED, QM_GREEN })); + // CreateMessageFromTextObject(0x9121, 0, 2, 3, AddColorsAndFormat(grannyText, { QM_RED, QM_GREEN })); + // CreateMessageFromTextObject(0x6077, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextOne, { QM_RED, QM_GREEN })); + // CreateMessageFromTextObject(0x6078, 0, 2, 3, + // AddColorsAndFormat(carpetSalesmanTextTwo, { QM_RED, QM_YELLOW, QM_RED })); + // ctx->AddHint(RH_MEDIGORON, AutoFormatHintText(medigoronText), RC_GC_MEDIGORON, HINT_TYPE_STATIC, GetHintRegion(RR_GORON_CITY)->GetHint().GetText()); + // ctx->AddHint(RH_GRANNYS_SHOP, AutoFormatHintText(grannyText), RC_KAK_GRANNYS_SHOP, HINT_TYPE_STATIC, GetHintRegion(RR_KAKARIKO_VILLAGE)->GetHint().GetText()); + // ctx->AddHint(RH_WASTELAND_BOMBCHU_SALESMAN, AutoFormatHintText(carpetSalesmanTextOne), RC_WASTELAND_BOMBCHU_SALESMAN, HINT_TYPE_STATIC, GetHintRegion(RR_HAUNTED_WASTELAND)->GetHint().GetText()); } //RANDOTODO add Better Links Pocket and starting item handling once more starting items are added -void CreateSpecialItemHint(uint32_t item, std::vector hints, RandomizerHintTextKey text1, RandomizerHintTextKey text2, Text& textLoc, std::string& nameLoc, bool condition, bool yourpocket = false) { +void CreateSpecialItemHint(uint32_t item, RandomizerHintKey hintKey, std::vector hints, RandomizerHintTextKey text1, RandomizerHintTextKey text2, Text& textLoc, std::string& nameLoc, bool condition, bool yourpocket = false) { auto ctx = Rando::Context::GetInstance(); if(condition){ RandomizerCheck location = FilterFromPool(ctx->allLocations, [item, ctx](const RandomizerCheck loc) { @@ -828,8 +912,9 @@ void CreateSpecialItemHint(uint32_t item, std::vector hints, Ra } Text area = GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText(); - textLoc = Hint(text1).GetText() + area + Hint(text2).GetText(); + textLoc = ::Hint(text1).GetText() + area + ::Hint(text2).GetText(); nameLoc = Rando::StaticData::GetLocation(location)->GetName(); + ctx->AddHint(hintKey, AutoFormatHintText(textLoc), location, HINT_TYPE_STATIC, area); } else { textLoc = Text(); nameLoc = ""; @@ -838,7 +923,8 @@ void CreateSpecialItemHint(uint32_t item, std::vector hints, Ra void CreateWarpSongTexts() { - if (!ShuffleWarpSongs) { + auto ctx = Rando::Context::GetInstance(); + if (!ctx->GetOption(RSK_WARP_SONG_HINTS)) { warpMinuetText = Text(); warpBoleroText = Text(); warpSerenadeText = Text(); @@ -865,21 +951,27 @@ void CreateWarpSongTexts() { switch (entrance->GetIndex()) { case 0x0600: // minuet warpMinuetText = resolvedHint; + ctx->AddHint(RH_MINUET_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint); break; case 0x04F6: // bolero warpBoleroText = resolvedHint; + ctx->AddHint(RH_BOLERO_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint); break; case 0x0604: // serenade warpSerenadeText = resolvedHint; + ctx->AddHint(RH_SERENADE_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint); break; case 0x01F1: // requiem warpRequiemText = resolvedHint; + ctx->AddHint(RH_REQUIEM_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint); break; case 0x0568: // nocturne - warpNocturneText = resolvedHint; - break; + warpNocturneText = resolvedHint; + ctx->AddHint(RH_NOCTURNE_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint); + break; case 0x05F4: // prelude warpPreludeText = resolvedHint; + ctx->AddHint(RH_PRELUDE_WARP_LOC, resolvedHint, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, resolvedHint); break; } } @@ -1008,32 +1100,32 @@ uint8_t PlaceHints(std::array& selectedHints, void CreateStoneHints() { auto ctx = Rando::Context::GetInstance(); SPDLOG_DEBUG("\nNOW CREATING HINTS\n"); - const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value()]; + const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).Value()]; std::array distTable = hintSetting.distTable; uint8_t* remainingDungeonWothHints = new uint8_t(hintSetting.dungeonsWothLimit); uint8_t* remainingDungeonBarrenHints = new uint8_t(hintSetting.dungeonsBarrenLimit); // Apply Special hint exclusions with no requirements - if (Settings::Kak10GSHintText){ + if (ctx->GetOption(RSK_KAK_10_SKULLS_HINT)){ ctx->GetItemLocation(RC_KAK_10_GOLD_SKULLTULA_REWARD)->SetAsHinted(); } - if (Settings::Kak20GSHintText){ + if (ctx->GetOption(RSK_KAK_20_SKULLS_HINT)){ ctx->GetItemLocation(RC_KAK_20_GOLD_SKULLTULA_REWARD)->SetAsHinted(); } - if (Settings::Kak30GSHintText){ + if (ctx->GetOption(RSK_KAK_30_SKULLS_HINT)){ ctx->GetItemLocation(RC_KAK_30_GOLD_SKULLTULA_REWARD)->SetAsHinted(); } - if (Settings::Kak40GSHintText){ + if (ctx->GetOption(RSK_KAK_40_SKULLS_HINT)){ ctx->GetItemLocation(RC_KAK_40_GOLD_SKULLTULA_REWARD)->SetAsHinted(); } - if (Settings::Kak50GSHintText){ + if (ctx->GetOption(RSK_KAK_50_SKULLS_HINT)){ ctx->GetItemLocation(RC_KAK_50_GOLD_SKULLTULA_REWARD)->SetAsHinted(); } - if (Settings::FrogsHintText){ + if (ctx->GetOption(RSK_FROGS_HINT)){ ctx->GetItemLocation(RC_ZR_FROGS_OCARINA_GAME)->SetAsHinted(); } - if (Settings::skipChildZelda){ + if (ctx->GetOption(RSK_SKIP_CHILD_ZELDA)){ ctx->GetItemLocation(RC_SONG_FROM_IMPA)->SetAsHinted(); } @@ -1045,7 +1137,7 @@ void CreateStoneHints() { auto alwaysHintLocations = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) { return ((Rando::StaticData::GetLocation(loc)->GetHint()->GetType() == HintCategory::Always) || // If we have Rainbow Bridge set to Greg, add a hint for where Greg is - (Bridge.Is(RAINBOWBRIDGE_GREG) && + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG) && ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) && ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsHintedAt()); }); @@ -1086,16 +1178,17 @@ void CreateStoneHints() { } void CreateAllHints(){ + auto ctx = Rando::Context::GetInstance(); CreateGanonAndSheikText(); CreateAltarText(); - CreateSpecialItemHint(RG_PROGRESSIVE_HOOKSHOT, {RC_DAMPE_HINT}, RHT_DAMPE_DIARY01, RHT_DAMPE_DIARY02, dampesText, dampeHintLoc, (bool)DampeHintText); - CreateSpecialItemHint(RG_GREG_RUPEE, {RC_GREG_HINT}, RHT_GREG_HINT01, RHT_GREG_HINT02, gregText, gregHintLoc, (bool)GregHintText); - CreateSpecialItemHint(RG_PROGRESSIVE_MAGIC_METER, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, RHT_SARIA_TEXT01, RHT_SARIA_TEXT02, sariaText, sariaHintLoc, (bool)SariaHintText); + CreateSpecialItemHint(RG_PROGRESSIVE_HOOKSHOT, RH_DAMPES_DIARY, {RC_DAMPE_HINT}, RHT_DAMPE_DIARY01, RHT_DAMPE_DIARY02, dampesText, dampeHintLoc, (bool)ctx->GetOption(RSK_DAMPES_DIARY_HINT)); + CreateSpecialItemHint(RG_GREG_RUPEE, RH_GREG_RUPEE, {RC_GREG_HINT}, RHT_GREG_HINT01, RHT_GREG_HINT02, gregText, gregHintLoc, (bool)ctx->GetOption(RSK_GREG_HINT)); + CreateSpecialItemHint(RG_PROGRESSIVE_MAGIC_METER, RH_SARIA, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, RHT_SARIA_TEXT01, RHT_SARIA_TEXT02, sariaText, sariaHintLoc, (bool)ctx->GetOption(RSK_SARIA_HINT)); - if (ShuffleMerchants.Is(SHUFFLEMERCHANTS_HINTS)) { + if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ON_HINT)) { CreateMerchantsHints(); } - if (GossipStoneHints.IsNot(HINTS_NO_HINTS)) { + if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE)) { printf("\x1b[10;10HCreating Hints..."); CreateStoneHints(); printf("Done"); diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.hpp b/soh/soh/Enhancements/randomizer/3drando/hints.hpp index 501f0b36a..eb9b9fd05 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.hpp @@ -6,10 +6,7 @@ #include "text.hpp" #include "random.hpp" -#include "settings.hpp" -#include "dungeon.hpp" #include - struct HintDistributionSetting { HintType type; size_t weight; @@ -55,7 +52,8 @@ public: : obscureText(std::move(obscureText_)), ambiguousText(std::move(ambiguousText_)), clearText(std::move(clearText_)), - type(type_) {} + type(type_) { + } static auto Item(std::vector&& obscureText, std::vector&& ambiguousText = {}, Text&& clearText = {}) { return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Item}; @@ -162,25 +160,9 @@ public: return clearText; } - const Text& GetText() const { - if (Settings::ClearerHints.Is(HINTMODE_OBSCURE)) { - return GetObscure(); - } else if (Settings::ClearerHints.Is(HINTMODE_AMBIGUOUS)){ - return GetAmbiguous(); - } else { - return GetClear(); - } - } + const Text& GetText() const; - const Text GetTextCopy() const { - if (Settings::ClearerHints.Is(HINTMODE_OBSCURE)) { - return GetObscure(); - } else if (Settings::ClearerHints.Is(HINTMODE_AMBIGUOUS)){ - return GetAmbiguous(); - } else { - return GetClear(); - } - } + const Text GetTextCopy() const; HintCategory GetType() const { return type; @@ -204,8 +186,15 @@ private: using ConditionalAlwaysHint = std::pair>; +typedef enum { + DUNGEON_NEITHER, + DUNGEON_BARREN, + DUNGEON_WOTH, +} DungeonHintInfo; + //10 dungeons as GTG and GC are excluded -extern std::array dungeonInfoData; +extern std::array dungeonInfoData; + extern std::array conditionalAlwaysHints; extern RandomizerHintTextKey GetHintRegionHintKey(const RandomizerRegion area); diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 3b29ad195..6a3c4d744 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -1,23 +1,17 @@ #include "item_pool.hpp" -#include "dungeon.hpp" +#include "../dungeon.h" #include "fill.hpp" #include "../static_data.h" #include "../context.h" #include "pool_functions.hpp" #include "random.hpp" -#include "settings.hpp" #include "spoiler_log.hpp" #include "z64item.h" #include - -using namespace Settings; -using namespace Dungeon; - std::vector ItemPool = {}; std::vector PendingJunkPool = {}; -std::vector IceTrapModels = {}; const std::array dungeonRewards = { RG_KOKIRI_EMERALD, RG_GORON_RUBY, @@ -432,9 +426,10 @@ static void AddRandomBottle(std::vector& bottlePool) { } RandomizerGet GetJunkItem() { - if (IceTrapValue.Is(ICETRAPS_MAYHEM) || IceTrapValue.Is(ICETRAPS_ONSLAUGHT)) { + auto ctx = Rando::Context::GetInstance(); + if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_MAYHEM) || ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_ONSLAUGHT)) { return RG_ICE_TRAP; - } else if (IceTrapValue.Is(ICETRAPS_EXTRA)) { + } else if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_EXTRA)) { return RandomElement(JunkPoolItems); } //Ice Trap is the last item in JunkPoolItems, so subtract 1 to never hit that index @@ -504,10 +499,10 @@ static void PlaceVanillaDekuScrubItems() { ctx->PlaceItemInLocation(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RG_DEKU_SEEDS_30, false, true); //Dungeon Scrubs - if (DekuTree.IsMQ()) { + if (ctx->GetDungeon(Rando::DEKU_TREE)->IsMQ()) { ctx->PlaceItemInLocation(RC_DEKU_TREE_MQ_DEKU_SCRUB, RG_DEKU_SHIELD, false, true); } - if (DodongosCavern.IsMQ()) { + if (ctx->GetDungeon(Rando::DODONGOS_CAVERN)->IsMQ()) { ctx->PlaceItemInLocation(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RG_DEKU_STICK_1, false, true); ctx->PlaceItemInLocation(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RG_DEKU_SEEDS_30, false, true); ctx->PlaceItemInLocation(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RG_DEKU_SHIELD, false, true); @@ -519,10 +514,10 @@ static void PlaceVanillaDekuScrubItems() { ctx->PlaceItemInLocation(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RG_DEKU_SEEDS_30, false, true); ctx->PlaceItemInLocation(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RG_DEKU_SHIELD, false, true); } - if (JabuJabusBelly.IsVanilla()) { + if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsVanilla()) { ctx->PlaceItemInLocation(RC_JABU_JABUS_BELLY_DEKU_SCRUB, RG_DEKU_NUTS_5, false, true); } - if (GanonsCastle.IsMQ()) { + if (ctx->GetDungeon(Rando::GANONS_CASTLE)->IsMQ()) { ctx->PlaceItemInLocation(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RG_GREEN_POTION_REFILL, false, true); ctx->PlaceItemInLocation(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RG_BOMBS_5, false, true); ctx->PlaceItemInLocation(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RG_ARROWS_30, false, true); @@ -539,23 +534,28 @@ static void PlaceVanillaDekuScrubItems() { } static void PlaceVanillaMapsAndCompasses() { - for (auto dungeon : dungeonList) { + auto ctx = Rando::Context::GetInstance(); + for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { dungeon->PlaceVanillaMap(); dungeon->PlaceVanillaCompass(); } } static void PlaceVanillaSmallKeys() { - for (auto dungeon : dungeonList) { + auto ctx = Rando::Context::GetInstance(); + for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { dungeon->PlaceVanillaSmallKeys(); } } static void PlaceVanillaBossKeys() { - for (auto dungeon : dungeonList) { + auto ctx = Rando::Context::GetInstance(); + for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { dungeon->PlaceVanillaBossKey(); } } +// TODO: This feels like it could be moved to Dungeons class and probably shorten +// a few function call chains. Needs investigation. static void PlaceVanillaCowMilk() { auto ctx = Rando::Context::GetInstance(); @@ -569,7 +569,7 @@ static void PlaceVanillaCowMilk() { ctx->PlaceItemInLocation(RC_LLR_TOWER_LEFT_COW, RG_MILK, false, true); ctx->PlaceItemInLocation(RC_LLR_TOWER_RIGHT_COW, RG_MILK, false, true); - if (JabuJabusBelly.IsMQ()) { + if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsMQ()) { ctx->PlaceItemInLocation(RC_JABU_JABUS_BELLY_MQ_COW, RG_MILK, false, true); } } @@ -590,6 +590,7 @@ static void SetScarceItemPool() { } static void SetMinimalItemPool() { + auto ctx = Rando::Context::GetInstance(); ReplaceMaxItem(RG_PROGRESSIVE_BOMBCHUS, 1); ReplaceMaxItem(RG_BOMBCHU_5, 1); ReplaceMaxItem(RG_BOMBCHU_10, 0); @@ -604,7 +605,7 @@ static void SetMinimalItemPool() { ReplaceMaxItem(RG_PROGRESSIVE_BOMB_BAG, 1); ReplaceMaxItem(RG_PIECE_OF_HEART, 0); // Need an extra heart container when starting with 1 heart to be able to reach 3 hearts - ReplaceMaxItem(RG_HEART_CONTAINER, (StartingHearts.Value() == 18)? 1 : 0); + ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).Value() == 18)? 1 : 0); } void GenerateItemPool() { @@ -613,63 +614,63 @@ void GenerateItemPool() { PendingJunkPool.clear(); //Initialize ice trap models to always major items - IceTrapModels = { - GI_SHIELD_MIRROR, - GI_BOOMERANG, - GI_LENS, - GI_HAMMER, - GI_BOOTS_IRON, - GI_BOOTS_HOVER, - GI_STONE_OF_AGONY, - GI_DINS_FIRE, - GI_FARORES_WIND, - GI_NAYRUS_LOVE, - GI_ARROW_FIRE, - GI_ARROW_ICE, - GI_ARROW_LIGHT, - 0xB8, //Double defense - GI_CLAIM_CHECK, - 0x80, //Progressive hookshot - 0x81, //Progressive strength - 0x82, //Progressive bomb bag - 0x83, //Progressive bow - 0x84, //Progressive slingshot - 0x85, //Progressive wallet - 0x86, //Progressive scale - 0x8A, //Progressive magic + ctx->possibleIceTrapModels = { + RG_MIRROR_SHIELD, + RG_BOOMERANG, + RG_LENS_OF_TRUTH, + RG_MEGATON_HAMMER, + RG_IRON_BOOTS, + RG_HOVER_BOOTS, + RG_STONE_OF_AGONY, + RG_DINS_FIRE, + RG_FARORES_WIND, + RG_NAYRUS_LOVE, + RG_FIRE_ARROWS, + RG_ICE_ARROWS, + RG_LIGHT_ARROWS, + RG_DOUBLE_DEFENSE, //Double defense + RG_CLAIM_CHECK, + RG_PROGRESSIVE_HOOKSHOT, //Progressive hookshot + RG_PROGRESSIVE_STRENGTH, //Progressive strength + RG_PROGRESSIVE_BOMB_BAG, //Progressive bomb bag + RG_PROGRESSIVE_BOW, //Progressive bow + RG_PROGRESSIVE_SLINGSHOT, //Progressive slingshot + RG_PROGRESSIVE_WALLET, //Progressive wallet + RG_PROGRESSIVE_SCALE, //Progressive scale + RG_PROGRESSIVE_MAGIC_METER, //Progressive magic }; //Check song shuffle and dungeon reward shuffle just for ice traps - if (ShuffleSongs.Is(SONGSHUFFLE_ANYWHERE)) { + if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE)) { //Push item ids for songs - IceTrapModels.push_back(0xC1); - IceTrapModels.push_back(0xC2); - IceTrapModels.push_back(0xC3); - IceTrapModels.push_back(0xC4); - IceTrapModels.push_back(0xC5); - IceTrapModels.push_back(0xC6); - IceTrapModels.push_back(0xBB); - IceTrapModels.push_back(0xBC); - IceTrapModels.push_back(0xBD); - IceTrapModels.push_back(0xBE); - IceTrapModels.push_back(0xBF); - IceTrapModels.push_back(0xC0); + ctx->possibleIceTrapModels.push_back(RG_ZELDAS_LULLABY); + ctx->possibleIceTrapModels.push_back(RG_EPONAS_SONG); + ctx->possibleIceTrapModels.push_back(RG_SARIAS_SONG); + ctx->possibleIceTrapModels.push_back(RG_SUNS_SONG); + ctx->possibleIceTrapModels.push_back(RG_SONG_OF_TIME); + ctx->possibleIceTrapModels.push_back(RG_SONG_OF_STORMS); + ctx->possibleIceTrapModels.push_back(RG_MINUET_OF_FOREST); + ctx->possibleIceTrapModels.push_back(RG_BOLERO_OF_FIRE); + ctx->possibleIceTrapModels.push_back(RG_SERENADE_OF_WATER); + ctx->possibleIceTrapModels.push_back(RG_REQUIEM_OF_SPIRIT); + ctx->possibleIceTrapModels.push_back(RG_NOCTURNE_OF_SHADOW); + ctx->possibleIceTrapModels.push_back(RG_PRELUDE_OF_LIGHT); } - if (ShuffleRewards.Is(REWARDSHUFFLE_ANYWHERE)) { + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_ANYWHERE)) { //Push item ids for dungeon rewards - IceTrapModels.push_back(0xCB); - IceTrapModels.push_back(0xCC); - IceTrapModels.push_back(0xCD); - IceTrapModels.push_back(0xCE); - IceTrapModels.push_back(0xCF); - IceTrapModels.push_back(0xD0); - IceTrapModels.push_back(0xD1); - IceTrapModels.push_back(0xD2); - IceTrapModels.push_back(0xD3); + ctx->possibleIceTrapModels.push_back(RG_KOKIRI_EMERALD); + ctx->possibleIceTrapModels.push_back(RG_GORON_RUBY); + ctx->possibleIceTrapModels.push_back(RG_ZORA_SAPPHIRE); + ctx->possibleIceTrapModels.push_back(RG_FOREST_MEDALLION); + ctx->possibleIceTrapModels.push_back(RG_FIRE_MEDALLION); + ctx->possibleIceTrapModels.push_back(RG_WATER_MEDALLION); + ctx->possibleIceTrapModels.push_back(RG_SPIRIT_MEDALLION); + ctx->possibleIceTrapModels.push_back(RG_SHADOW_MEDALLION); + ctx->possibleIceTrapModels.push_back(RG_LIGHT_MEDALLION); } - if (TriforceHunt.Is(TRIFORCE_HUNT_ON)) { - IceTrapModels.push_back(0xDF); - AddItemToMainPool(RG_TRIFORCE_PIECE, Settings::TriforceHuntTotal.Value()); + if (ctx->GetOption(RSK_TRIFORCE_HUNT)) { + ctx->possibleIceTrapModels.push_back(RG_TRIFORCE_PIECE); + AddItemToMainPool(RG_TRIFORCE_PIECE, ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Value()); ctx->PlaceItemInLocation(RC_TRIFORCE_COMPLETED, RG_TRIFORCE); // Win condition ctx->PlaceItemInLocation(RC_GANON, GetJunkItem(), false, true); } else { @@ -680,66 +681,66 @@ void GenerateItemPool() { ctx->PlaceItemInLocation(RC_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER); ctx->PlaceItemInLocation(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP); - if (ShuffleKokiriSword) { + if (ctx->GetOption(RSK_SHUFFLE_KOKIRI_SWORD)) { AddItemToMainPool(RG_KOKIRI_SWORD); - IceTrapModels.push_back(GI_SWORD_KOKIRI); + ctx->possibleIceTrapModels.push_back(RG_KOKIRI_SWORD); } else { ctx->PlaceItemInLocation(RC_KF_KOKIRI_SWORD_CHEST, RG_KOKIRI_SWORD, false, true); } - if (ShuffleMasterSword) { + if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) { AddItemToMainPool(RG_MASTER_SWORD); - IceTrapModels.push_back(0xE0); //Master Sword without the GI enum + ctx->possibleIceTrapModels.push_back(RG_MASTER_SWORD); //Master Sword without the GI enum } else { ctx->PlaceItemInLocation(RC_TOT_MASTER_SWORD, RG_MASTER_SWORD, false, true); } - if (ShuffleWeirdEgg) { + if (ctx->GetOption(RSK_SHUFFLE_WEIRD_EGG)) { AddItemToMainPool(RG_WEIRD_EGG); - IceTrapModels.push_back(GI_WEIRD_EGG); + ctx->possibleIceTrapModels.push_back(RG_WEIRD_EGG); } else { ctx->PlaceItemInLocation(RC_HC_MALON_EGG, RG_WEIRD_EGG, false, true); } - if (ShuffleOcarinas) { + if (ctx->GetOption(RSK_SHUFFLE_OCARINA)) { AddItemToMainPool(RG_PROGRESSIVE_OCARINA, 2); - if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) { + if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { AddItemToPool(PendingJunkPool, RG_PROGRESSIVE_OCARINA); } - IceTrapModels.push_back(0x8B); //Progressive ocarina + ctx->possibleIceTrapModels.push_back(RG_PROGRESSIVE_OCARINA); //Progressive ocarina } else { ctx->PlaceItemInLocation(RC_LW_GIFT_FROM_SARIA, RG_PROGRESSIVE_OCARINA, false, true); ctx->PlaceItemInLocation(RC_HF_OCARINA_OF_TIME_ITEM, RG_PROGRESSIVE_OCARINA, false, true); } - if (ShuffleCows) { + if (ctx->GetOption(RSK_SHUFFLE_COWS)) { //9 total cow locations for (uint8_t i = 0; i < 9; i++) { AddItemToMainPool(GetJunkItem()); } //extra location for Jabu MQ - if (JabuJabusBelly.IsMQ()) { + if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsMQ()) { AddItemToMainPool(GetJunkItem()); } } else { PlaceVanillaCowMilk(); } - if (ShuffleMagicBeans) { + if (ctx->GetOption(RSK_SHUFFLE_MAGIC_BEANS)) { AddItemToMainPool(RG_MAGIC_BEAN_PACK); - if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) { + if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { AddItemToPool(PendingJunkPool, RG_MAGIC_BEAN_PACK); } - IceTrapModels.push_back(0xC9); //Magic bean pack + ctx->possibleIceTrapModels.push_back(RG_MAGIC_BEAN_PACK); //Magic bean pack } else { ctx->PlaceItemInLocation(RC_ZR_MAGIC_BEAN_SALESMAN, RG_MAGIC_BEAN, false, true); } - if (ShuffleMerchants.IsNot(SHUFFLEMERCHANTS_OFF)) { - if (!ProgressiveGoronSword) { + if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).IsNot(RO_SHUFFLE_MERCHANTS_OFF)) { + if (/*!ProgressiveGoronSword TODO: Implement Progressive Goron Sword*/true) { AddItemToMainPool(RG_GIANTS_KNIFE); } - if (BombchusInLogic) { + if (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) { AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS); } else { AddItemToMainPool(RG_BOMBCHU_10); @@ -750,7 +751,7 @@ void GenerateItemPool() { ctx->PlaceItemInLocation(RC_WASTELAND_BOMBCHU_SALESMAN, RG_BOMBCHU_10, false, true); } - if (ShuffleFrogSongRupees) { + if (ctx->GetOption(RSK_SHUFFLE_FROG_SONG_RUPEES)) { AddItemToMainPool(RG_PURPLE_RUPEE, 5); } else { ctx->PlaceItemInLocation(RC_ZR_FROGS_ZELDAS_LULLABY, RG_PURPLE_RUPEE, false, true); @@ -760,7 +761,7 @@ void GenerateItemPool() { ctx->PlaceItemInLocation(RC_ZR_FROGS_SONG_OF_TIME, RG_PURPLE_RUPEE, false, true); } - if (ShuffleAdultTradeQuest) { + if (ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE)) { AddItemToMainPool(RG_POCKET_EGG); AddItemToMainPool(RG_COJIRO); AddItemToMainPool(RG_ODD_MUSHROOM); @@ -783,9 +784,9 @@ void GenerateItemPool() { } AddItemToMainPool(RG_CLAIM_CHECK); - if (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS)) { + if (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS)) { AddItemToMainPool(RG_TREASURE_GAME_SMALL_KEY, 6); // 6 individual keys - } else if (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK)) { + } else if (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK)) { AddItemToMainPool(RG_TREASURE_GAME_SMALL_KEY); // 1 key which will behave as a pack of 6 } else { ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, false, true); @@ -795,11 +796,11 @@ void GenerateItemPool() { ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_TREASURE_GAME_SMALL_KEY, false, true); }; - if (Tokensanity.Is(TOKENSANITY_OFF)) { + if (ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF)) { for (RandomizerCheck loc : ctx->GetLocations(ctx->allLocations, Category::cSkulltula)) { ctx->PlaceItemInLocation(loc, RG_GOLD_SKULLTULA_TOKEN, false, true); } - } else if (Tokensanity.Is(TOKENSANITY_DUNGEONS)) { + } else if (ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_DUNGEONS)) { for (RandomizerCheck loc : ctx->GetLocations(ctx->allLocations, Category::cSkulltula)) { if (Rando::StaticData::GetLocation(loc)->IsOverworld()) { ctx->PlaceItemInLocation((RandomizerCheck)loc, RG_GOLD_SKULLTULA_TOKEN, false, true); @@ -807,7 +808,7 @@ void GenerateItemPool() { AddItemToMainPool(RG_GOLD_SKULLTULA_TOKEN); } } - } else if (Tokensanity.Is(TOKENSANITY_OVERWORLD)) { + } else if (ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OVERWORLD)) { for (RandomizerCheck loc : ctx->GetLocations(ctx->allLocations, Category::cSkulltula)) { if (Rando::StaticData::GetLocation(loc)->IsDungeon()) { ctx->PlaceItemInLocation((RandomizerCheck)loc, RG_GOLD_SKULLTULA_TOKEN, false, true); @@ -819,8 +820,8 @@ void GenerateItemPool() { AddItemToMainPool(RG_GOLD_SKULLTULA_TOKEN, 100); } - if (Shuffle100GSReward) { - if (Tokensanity.IsNot(TOKENSANITY_OFF) && ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) { + if (ctx->GetOption(RSK_SHUFFLE_100_GS_REWARD)) { + if (ctx->GetOption(RSK_SHUFFLE_TOKENS).IsNot(RO_TOKENSANITY_OFF) && ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { AddItemToPool(PendingJunkPool, RG_GOLD_SKULLTULA_TOKEN, 10); } AddItemToMainPool(RG_HUGE_RUPEE); @@ -828,7 +829,7 @@ void GenerateItemPool() { ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, false, true); } - if (BombchusInLogic) { + if (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) { AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS, 5); } else { AddItemToMainPool(RG_BOMBCHU_5); @@ -838,28 +839,28 @@ void GenerateItemPool() { //Ice Traps AddItemToMainPool(RG_ICE_TRAP); - if (GerudoTrainingGrounds.IsVanilla()) { + if (ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUNDS)->IsVanilla()) { AddItemToMainPool(RG_ICE_TRAP); } - if (GanonsCastle.IsVanilla()) { + if (ctx->GetDungeon(Rando::GANONS_CASTLE)->IsVanilla()) { AddItemToMainPool(RG_ICE_TRAP, 4); } //Gerudo Fortress - if (GerudoFortress.Is(GERUDOFORTRESS_OPEN)) { + if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_OPEN)) { ctx->PlaceItemInLocation(RC_GF_NORTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true); ctx->PlaceItemInLocation(RC_GF_NORTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true); ctx->PlaceItemInLocation(RC_GF_SOUTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true); ctx->PlaceItemInLocation(RC_GF_SOUTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true); - } else if (GerudoKeys.IsNot(GERUDOKEYS_VANILLA)) { - if (GerudoFortress.Is(GERUDOFORTRESS_FAST)) { + } else if (ctx->GetOption(RSK_GERUDO_KEYS).IsNot(RO_GERUDO_KEYS_VANILLA)) { + if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_FAST)) { AddItemToMainPool(RG_GERUDO_FORTRESS_SMALL_KEY); ctx->PlaceItemInLocation(RC_GF_NORTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true); ctx->PlaceItemInLocation(RC_GF_SOUTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true); ctx->PlaceItemInLocation(RC_GF_SOUTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true); } else { //Only add key ring if 4 Fortress keys necessary - if (RingFortress) { + if (ctx->GetOption(RSK_KEYRINGS_GERUDO_FORTRESS)) { AddItemToMainPool(RG_GERUDO_FORTRESS_KEY_RING); //Add junk to make up for missing keys for (uint8_t i = 0; i < 3; i++) { @@ -869,15 +870,15 @@ void GenerateItemPool() { AddItemToMainPool(RG_GERUDO_FORTRESS_SMALL_KEY, 4); } } - if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) { - if (RingFortress && GerudoFortress.Is(GERUDOFORTRESS_NORMAL)) { + if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { + if (ctx->GetOption(RSK_KEYRINGS_GERUDO_FORTRESS) && ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_NORMAL)) { AddItemToPool(PendingJunkPool, RG_GERUDO_FORTRESS_KEY_RING); } else { AddItemToPool(PendingJunkPool, RG_GERUDO_FORTRESS_SMALL_KEY); } } } else { - if (GerudoFortress.Is(GERUDOFORTRESS_FAST)) { + if (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_FAST)) { ctx->PlaceItemInLocation(RC_GF_NORTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, false, true); ctx->PlaceItemInLocation(RC_GF_NORTH_F2_CARPENTER, RG_RECOVERY_HEART, false, true); ctx->PlaceItemInLocation(RC_GF_SOUTH_F1_CARPENTER, RG_RECOVERY_HEART, false, true); @@ -891,10 +892,10 @@ void GenerateItemPool() { } //Gerudo Membership Card - if (ShuffleGerudoToken && GerudoFortress.IsNot(GERUDOFORTRESS_OPEN)) { + if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD) && ctx->GetOption(RSK_GERUDO_FORTRESS).IsNot(RO_GF_OPEN)) { AddItemToMainPool(RG_GERUDO_MEMBERSHIP_CARD); - IceTrapModels.push_back(GI_GERUDO_CARD); - } else if (ShuffleGerudoToken) { + ctx->possibleIceTrapModels.push_back(RG_GERUDO_MEMBERSHIP_CARD); + } else if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { AddItemToPool(PendingJunkPool, RG_GERUDO_MEMBERSHIP_CARD); ctx->PlaceItemInLocation(RC_GF_GERUDO_MEMBERSHIP_CARD, RG_ICE_TRAP, false, true); } else { @@ -904,9 +905,9 @@ void GenerateItemPool() { //Keys //For key rings, need to add as many junk items as "missing" keys - if (KeyRings.IsNot(KEYRINGS_OFF)) { + if (ctx->GetOption(RSK_KEYRINGS).IsNot(RO_KEYRINGS_OFF)) { uint8_t ringJunkAmt = 0; - for (auto dungeon : dungeonList) { + for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { if (dungeon->HasKeyRing()) { ringJunkAmt += dungeon->GetSmallKeyCount() - 1; } @@ -916,56 +917,56 @@ void GenerateItemPool() { } } - if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) { - if (ShuffleGerudoToken) { + if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { + if (ctx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { AddItemToPool(PendingJunkPool, RG_GERUDO_MEMBERSHIP_CARD); } //Plentiful small keys - if (Keysanity.Is(KEYSANITY_ANYWHERE) || Keysanity.Is(KEYSANITY_ANY_DUNGEON) || Keysanity.Is(KEYSANITY_OVERWORLD)) { - if (BottomOfTheWell.HasKeyRing()) { + if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) { + if (ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->HasKeyRing()) { AddItemToPool(PendingJunkPool, RG_BOTTOM_OF_THE_WELL_KEY_RING); } else { AddItemToPool(PendingJunkPool, RG_BOTTOM_OF_THE_WELL_SMALL_KEY); } - if (ForestTemple.HasKeyRing()) { + if (ctx->GetDungeon(Rando::FOREST_TEMPLE)->HasKeyRing()) { AddItemToPool(PendingJunkPool, RG_FOREST_TEMPLE_KEY_RING); } else { AddItemToPool(PendingJunkPool, RG_FOREST_TEMPLE_SMALL_KEY); } - if (FireTemple.HasKeyRing()) { + if (ctx->GetDungeon(Rando::FIRE_TEMPLE)->HasKeyRing()) { AddItemToPool(PendingJunkPool, RG_FIRE_TEMPLE_KEY_RING); } else { AddItemToPool(PendingJunkPool, RG_FIRE_TEMPLE_SMALL_KEY); } - if (WaterTemple.HasKeyRing()) { + if (ctx->GetDungeon(Rando::WATER_TEMPLE)->HasKeyRing()) { AddItemToPool(PendingJunkPool, RG_WATER_TEMPLE_KEY_RING); } else { AddItemToPool(PendingJunkPool, RG_WATER_TEMPLE_SMALL_KEY); } - if (SpiritTemple.HasKeyRing()) { + if (ctx->GetDungeon(Rando::SPIRIT_TEMPLE)->HasKeyRing()) { AddItemToPool(PendingJunkPool, RG_SPIRIT_TEMPLE_KEY_RING); } else { AddItemToPool(PendingJunkPool, RG_SPIRIT_TEMPLE_SMALL_KEY); } - if (ShadowTemple.HasKeyRing()) { + if (ctx->GetDungeon(Rando::SHADOW_TEMPLE)->HasKeyRing()) { AddItemToPool(PendingJunkPool, RG_SHADOW_TEMPLE_KEY_RING); } else { AddItemToPool(PendingJunkPool, RG_SHADOW_TEMPLE_SMALL_KEY); } - if (GerudoTrainingGrounds.HasKeyRing()) { + if (ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUNDS)->HasKeyRing()) { AddItemToPool(PendingJunkPool, RG_GERUDO_TRAINING_GROUNDS_KEY_RING); } else { AddItemToPool(PendingJunkPool, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY); } - if (GanonsCastle.HasKeyRing()) { + if (ctx->GetDungeon(Rando::GANONS_CASTLE)->HasKeyRing()) { AddItemToPool(PendingJunkPool, RG_GANONS_CASTLE_KEY_RING); } else { AddItemToPool(PendingJunkPool, RG_GANONS_CASTLE_SMALL_KEY); } } - if (BossKeysanity.Is(BOSSKEYSANITY_ANYWHERE) || BossKeysanity.Is(BOSSKEYSANITY_ANY_DUNGEON) || BossKeysanity.Is(BOSSKEYSANITY_OVERWORLD)) { + if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) || ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) { AddItemToPool(PendingJunkPool, RG_FOREST_TEMPLE_BOSS_KEY); AddItemToPool(PendingJunkPool, RG_FIRE_TEMPLE_BOSS_KEY); AddItemToPool(PendingJunkPool, RG_WATER_TEMPLE_BOSS_KEY); @@ -973,36 +974,36 @@ void GenerateItemPool() { AddItemToPool(PendingJunkPool, RG_SHADOW_TEMPLE_BOSS_KEY); } - if (GanonsBossKey.Is(GANONSBOSSKEY_ANYWHERE) || GanonsBossKey.Is(GANONSBOSSKEY_ANY_DUNGEON) || GanonsBossKey.Is(GANONSBOSSKEY_OVERWORLD)) { + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANYWHERE) || ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON) || ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) { AddItemToPool(PendingJunkPool, RG_GANONS_CASTLE_BOSS_KEY); } } //Shopsanity - if (Settings::Shopsanity.Is(SHOPSANITY_OFF) || Settings::Shopsanity.Is(SHOPSANITY_ZERO)) { + if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF) || ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_ZERO_ITEMS)) { AddItemsToPool(ItemPool, normalRupees); } else { //Shopsanity 1-4, random AddItemsToPool(ItemPool, shopsanityRupees); //Shopsanity gets extra large rupees } //Scrubsanity - if (Settings::Scrubsanity.IsNot(SCRUBSANITY_OFF)) { + if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).IsNot(RO_SCRUBS_OFF)) { //Deku Tree - if (DekuTree.IsMQ()) { + if (ctx->GetDungeon(Rando::DEKU_TREE)->IsMQ()) { AddItemToMainPool(RG_DEKU_SHIELD); } //Dodongos Cavern AddItemToMainPool(RG_DEKU_STICK_1); AddItemToMainPool(RG_DEKU_SHIELD); - if (DodongosCavern.IsMQ()) { + if (ctx->GetDungeon(Rando::DODONGOS_CAVERN)->IsMQ()) { AddItemToMainPool(RG_RECOVERY_HEART); } else { AddItemToMainPool(RG_DEKU_NUTS_5); } //Jabu Jabus Belly - if (JabuJabusBelly.IsVanilla()) { + if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsVanilla()) { AddItemToMainPool(RG_DEKU_NUTS_5); } @@ -1010,7 +1011,7 @@ void GenerateItemPool() { AddItemToMainPool(RG_BOMBS_5); AddItemToMainPool(RG_RECOVERY_HEART); AddItemToMainPool(RG_BLUE_RUPEE); - if (GanonsCastle.IsMQ()) { + if (ctx->GetDungeon(Rando::GANONS_CASTLE)->IsMQ()) { AddItemToMainPool(RG_DEKU_NUTS_5); } @@ -1033,55 +1034,55 @@ void GenerateItemPool() { AddItemsToPool(ItemPool, dungeonRewards); //Dungeon pools - if (DekuTree.IsMQ()) { + if (ctx->GetDungeon(Rando::DEKU_TREE)->IsMQ()) { AddItemsToPool(ItemPool, DT_MQ); } else { AddItemsToPool(ItemPool, DT_Vanilla); } - if (DodongosCavern.IsMQ()) { + if (ctx->GetDungeon(Rando::DODONGOS_CAVERN)->IsMQ()) { AddItemsToPool(ItemPool, DC_MQ); } else { AddItemsToPool(ItemPool, DC_Vanilla); } - if (JabuJabusBelly.IsMQ()) { + if (ctx->GetDungeon(Rando::JABU_JABUS_BELLY)->IsMQ()) { AddItemsToPool(ItemPool, JB_MQ); } - if (ForestTemple.IsMQ()) { + if (ctx->GetDungeon(Rando::FOREST_TEMPLE)->IsMQ()) { AddItemsToPool(ItemPool, FoT_MQ); } else { AddItemsToPool(ItemPool, FoT_Vanilla); } - if (FireTemple.IsMQ()) { + if (ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsMQ()) { AddItemsToPool(ItemPool, FiT_MQ); } else { AddItemsToPool(ItemPool, FiT_Vanilla); } - if (SpiritTemple.IsMQ()) { + if (ctx->GetDungeon(Rando::SPIRIT_TEMPLE)->IsMQ()) { AddItemsToPool(ItemPool, SpT_MQ); } else { AddItemsToPool(ItemPool, SpT_Vanilla); } - if (ShadowTemple.IsMQ()) { + if (ctx->GetDungeon(Rando::SHADOW_TEMPLE)->IsMQ()) { AddItemsToPool(ItemPool, ShT_MQ); } else { AddItemsToPool(ItemPool, ShT_Vanilla); } - if (BottomOfTheWell.IsVanilla()) { + if (ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla()) { AddItemsToPool(ItemPool, BW_Vanilla); } - if (GerudoTrainingGrounds.IsMQ()) { + if (ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUNDS)->IsMQ()) { AddItemsToPool(ItemPool, GTG_MQ); } else { AddItemsToPool(ItemPool, GTG_Vanilla); } - if (GanonsCastle.IsMQ()) { + if (ctx->GetDungeon(Rando::GANONS_CASTLE)->IsMQ()) { AddItemsToPool(ItemPool, GC_MQ); } else { AddItemsToPool(ItemPool, GC_Vanilla); } uint8_t rutoBottles = 1; - if (ZorasFountain.Is(ZORASFOUNTAIN_OPEN)) { + if (ctx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN)) { rutoBottles = 0; } @@ -1089,11 +1090,11 @@ void GenerateItemPool() { uint8_t bottleCount = 4; std::vector bottles; bottles.assign(normalBottles.begin(), normalBottles.end()); - IceTrapModels.push_back( - Rando::StaticData::RetrieveItem(RandomElement(bottles)).GetItemID()); // Get one random bottle type for ice traps + ctx->possibleIceTrapModels.push_back( + Rando::StaticData::RetrieveItem(RandomElement(bottles)).GetRandomizerGet()); // Get one random bottle type for ice traps for (uint8_t i = 0; i < bottleCount; i++) { if (i >= rutoBottles) { - if ((i == bottleCount - 1) && ShuffleMerchants.IsNot(SHUFFLEMERCHANTS_OFF)) { + if ((i == bottleCount - 1) && ctx->GetOption(RSK_SHUFFLE_MERCHANTS).IsNot(RO_SHUFFLE_MERCHANTS_OFF)) { AddItemToMainPool(RG_BOTTLE_WITH_BLUE_POTION); } else { AddRandomBottle(bottles); @@ -1105,7 +1106,7 @@ void GenerateItemPool() { //add extra songs only if song shuffle is anywhere AddItemsToPool(ItemPool, songList); - if (ShuffleSongs.Is(SONGSHUFFLE_ANYWHERE) && ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) { + if (ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE) && ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { AddItemsToPool(PendingJunkPool, songList); } @@ -1116,10 +1117,10 @@ void GenerateItemPool() { | advancement items that haven't been placed yet for placing higher priority | items like stones/medallions.*/ - if (MapsAndCompasses.Is(MAPSANDCOMPASSES_VANILLA)) { + if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_VANILLA)) { PlaceVanillaMapsAndCompasses(); } else { - for (auto dungeon : dungeonList) { + for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { if (dungeon->GetMap() != RG_NONE) { AddItemToMainPool(dungeon->GetMap()); } @@ -1130,11 +1131,11 @@ void GenerateItemPool() { } } - if (Keysanity.Is(KEYSANITY_VANILLA)) { + if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA)) { PlaceVanillaSmallKeys(); } else { - for (auto dungeon : dungeonList) { - if (dungeon->HasKeyRing() && Keysanity.IsNot(KEYSANITY_START_WITH)) { + for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) { + if (dungeon->HasKeyRing() && ctx->GetOption(RSK_KEYSANITY).IsNot(RO_DUNGEON_ITEM_LOC_STARTWITH)) { AddItemToMainPool(dungeon->GetKeyRing()); } else { if (dungeon->GetSmallKeyCount() > 0) { @@ -1144,7 +1145,7 @@ void GenerateItemPool() { } } - if (BossKeysanity.Is(BOSSKEYSANITY_VANILLA)) { + if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_VANILLA)) { PlaceVanillaBossKeys(); } else { AddItemToMainPool(RG_FOREST_TEMPLE_BOSS_KEY); @@ -1154,54 +1155,54 @@ void GenerateItemPool() { AddItemToMainPool(RG_SHADOW_TEMPLE_BOSS_KEY); } - if (GanonsBossKey.Is(GANONSBOSSKEY_FINAL_GS_REWARD)) { + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) { ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_GANONS_CASTLE_BOSS_KEY); - } else if (GanonsBossKey.Value() >= GANONSBOSSKEY_LACS_VANILLA && GanonsBossKey.IsNot(GANONSBOSSKEY_TRIFORCE_HUNT)) { + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Value() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) { ctx->PlaceItemInLocation(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_GANONS_CASTLE_BOSS_KEY); - } else if (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA)) { + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) { ctx->PlaceItemInLocation(RC_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY); } else { AddItemToMainPool(RG_GANONS_CASTLE_BOSS_KEY); } - if (ItemPoolValue.Is(ITEMPOOL_PLENTIFUL)) { + if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { AddItemsToPool(ItemPool, easyItems); } else { AddItemsToPool(ItemPool, normalItems); } - if (!ShuffleKokiriSword) { + if (!ctx->GetOption(RSK_SHUFFLE_KOKIRI_SWORD)) { ReplaceMaxItem(RG_KOKIRI_SWORD, 0); } - if (!ShuffleMasterSword) { + if (!ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD)) { ReplaceMaxItem(RG_MASTER_SWORD, 0); } - if (ProgressiveGoronSword) { + if (/*ProgressiveGoronSword TODO: Implement Setting*/false) { ReplaceMaxItem(RG_BIGGORON_SWORD, 0); AddItemToMainPool(RG_PROGRESSIVE_GORONSWORD, 2); - IceTrapModels.push_back(0xD4); // Progressive Goron Sword + ctx->possibleIceTrapModels.push_back(RG_PROGRESSIVE_GORONSWORD); // Progressive Goron Sword } else { - IceTrapModels.push_back(GI_SWORD_BGS); + ctx->possibleIceTrapModels.push_back(RG_BIGGORON_SWORD); } //Replace ice traps with junk from the pending junk pool if necessary - if (IceTrapValue.Is(ICETRAPS_OFF)) { + if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_OFF)) { ReplaceMaxItem(RG_ICE_TRAP, 0); } //Replace all junk items with ice traps for onslaught mode - else if (IceTrapValue.Is(ICETRAPS_ONSLAUGHT)) { + else if (ctx->GetOption(RSK_ICE_TRAPS).Is(RO_ICE_TRAPS_ONSLAUGHT)) { for (uint8_t i = 0; i < JunkPoolItems.size() - 3; i++) { // -3 Omits Huge Rupees and Deku Nuts 10 ReplaceMaxItem(JunkPoolItems[i], 0); } } - if (ItemPoolValue.Is(ITEMPOOL_SCARCE)) { + if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_SCARCE)) { SetScarceItemPool(); - } else if (ItemPoolValue.Is(ITEMPOOL_MINIMAL)) { + } else if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_MINIMAL)) { SetMinimalItemPool(); - } else if (RemoveDoubleDefense) { + } else if (/*RemoveDoubleDefense TODO: Implement setting*/ false) { ReplaceMaxItem(RG_DOUBLE_DEFENSE, 0); } diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.hpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.hpp index 749a2a46d..4ef583001 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.hpp @@ -14,4 +14,3 @@ void GenerateItemPool(); void AddJunk(); extern std::vector ItemPool; -extern std::vector IceTrapModels; diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp index f2e227324..50d53f698 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp @@ -1,20 +1,18 @@ #include "location_access.hpp" -#include "dungeon.hpp" +#include "../dungeon.h" #include "../static_data.h" #include "../context.h" #include "item_pool.hpp" #include "logic.hpp" -#include "settings.hpp" #include "spoiler_log.hpp" -#include "trial.hpp" -#include "entrance.hpp" +#include "../trial.h" +#include "../entrance.h" #include #include using namespace Logic; -using namespace Settings; //generic grotto event list std::vector grottoEvents = { @@ -80,7 +78,8 @@ bool LocationAccess::CanBuy() const { } // If bombchus in logic, need to have found chus to buy; if not just need bomb bag else if (placed == RG_BUY_BOMBCHU_10 || placed == RG_BUY_BOMBCHU_20) { - OtherCondition = (!BombchusInLogic && Bombs) || (BombchusInLogic && FoundBombchus); + OtherCondition = + (!ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && Bombs) || (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && FoundBombchus); } return SufficientWallet && OtherCondition; @@ -91,7 +90,7 @@ Area::Area(std::string regionName_, std::string scene_, RandomizerHintTextKey hi bool timePass_, std::vector events_, std::vector locations_, - std::list exits_) + std::list exits_) : regionName(std::move(regionName_)), scene(std::move(scene_)), hintKey(hintKey_), @@ -139,13 +138,13 @@ bool Area::UpdateEvents(SearchMode mode) { } void Area::AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition) { - Entrance newExit = Entrance(newExitKey, {condition}); + Rando::Entrance newExit = Rando::Entrance(newExitKey, {condition}); newExit.SetParentRegion(parentKey); exits.push_front(newExit); } //The exit will be completely removed from this area -void Area::RemoveExit(Entrance* exitToRemove) { +void Area::RemoveExit(Rando::Entrance* exitToRemove) { exits.remove_if([exitToRemove](const auto exit){return &exit == exitToRemove;}); } @@ -158,7 +157,7 @@ void Area::SetAsPrimary(RandomizerRegion exitToBePrimary) { } } -Entrance* Area::GetExit(RandomizerRegion exitToReturn) { +Rando::Entrance* Area::GetExit(RandomizerRegion exitToReturn) { for (auto& exit : exits) { if (exit.Getuint32_t() == exitToReturn) { return &exit; @@ -200,7 +199,7 @@ bool Area::CheckAllAccess(const RandomizerRegion exitKey) { return false; } - for (Entrance& exit : exits) { + for (Rando::Entrance& exit : exits) { if (exit.GetConnectedRegionKey() == exitKey) { return exit.CheckConditionAtAgeTime(Logic::IsChild, Logic::AtDay) && exit.CheckConditionAtAgeTime(Logic::IsChild, Logic::AtNight) && @@ -248,9 +247,11 @@ bool HasAccessTo(const RandomizerRegion area) { return areaTable[area].HasAccess(); } - +std::shared_ptr randoCtx; void AreaTable_Init() { + using namespace Rando; + randoCtx = Context::GetInstance(); //Clear the array from any previous playthrough attempts. This is important so that //locations which appear in both MQ and Vanilla dungeons don't get set in both areas. areaTable.fill(Area("Invalid Area", "Invalid Area", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {})); @@ -380,18 +381,19 @@ namespace Areas { } void AccessReset() { + auto ctx = Rando::Context::GetInstance(); for (const RandomizerRegion area : GetAllAreas()) { AreaTable(area)->ResetVariables(); } - if(Settings::HasNightStart) { - if(Settings::ResolvedStartingAge == AGE_CHILD) { + if(/*Settings::HasNightStart TODO:: Randomize Starting Time*/ false) { + if(ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) { AreaTable(RR_ROOT)->childNight = true; } else { AreaTable(RR_ROOT)->adultNight = true; } } else { - if(Settings::ResolvedStartingAge == AGE_CHILD) { + if(ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) { AreaTable(RR_ROOT)->childDay = true; } else { AreaTable(RR_ROOT)->adultDay = true; @@ -401,6 +403,7 @@ namespace Areas { //Reset exits and clear items from locations void ResetAllLocations() { + auto ctx = Rando::Context::GetInstance(); for (const RandomizerRegion area : GetAllAreas()) { AreaTable(area)->ResetVariables(); //Erase item from every location in this exit @@ -410,14 +413,14 @@ namespace Areas { } } - if(Settings::HasNightStart) { - if(Settings::ResolvedStartingAge == AGE_CHILD) { + if (/*Settings::HasNightStart TODO:: Randomize Starting Time*/ false) { + if(ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) { AreaTable(RR_ROOT)->childNight = true; } else { AreaTable(RR_ROOT)->adultNight = true; } - } else { - if(Settings::ResolvedStartingAge == AGE_CHILD) { + } else { + if(ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) { AreaTable(RR_ROOT)->childDay = true; } else { AreaTable(RR_ROOT)->adultDay = true; @@ -428,7 +431,7 @@ namespace Areas { bool HasTimePassAccess(uint8_t age) { for (const RandomizerRegion areaKey : GetAllAreas()) { auto area = AreaTable(areaKey); - if (area->timePass && ((age == AGE_CHILD && area->Child()) || (age == AGE_ADULT && area->Adult()))) { + if (area->timePass && ((age == RO_AGE_CHILD && area->Child()) || (age == RO_AGE_ADULT && area->Adult()))) { return true; } } @@ -495,11 +498,11 @@ Area* AreaTable(const RandomizerRegion areaKey) { } //Retrieve all the shuffable entrances of a specific type -std::vector GetShuffleableEntrances(EntranceType type, bool onlyPrimary /*= true*/) { - std::vector entrancesToShuffle = {}; +std::vector GetShuffleableEntrances(Rando::EntranceType type, bool onlyPrimary /*= true*/) { + std::vector entrancesToShuffle = {}; for (RandomizerRegion area : Areas::GetAllAreas()) { for (auto& exit: AreaTable(area)->exits) { - if ((exit.GetType() == type || type == EntranceType::All) && (exit.IsPrimary() || !onlyPrimary) && exit.GetType() != EntranceType::None) { + if ((exit.GetType() == type || type == Rando::EntranceType::All) && (exit.IsPrimary() || !onlyPrimary) && exit.GetType() != Rando::EntranceType::None) { entrancesToShuffle.push_back(&exit); } } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp index 54bb39f50..aadc8d0b2 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp @@ -7,9 +7,13 @@ #include "logic.hpp" #include "hint_list.hpp" #include "fill.hpp" +#include "../context.h" typedef bool (*ConditionFn)(); +// I hate this but every alternative I can think of right now is worse +extern std::shared_ptr randoCtx; + class EventAccess { public: @@ -23,11 +27,12 @@ public: } bool ConditionsMet() const { - if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) { + auto ctx = Rando::Context::GetInstance(); + if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) { return true; - } else if (Settings::Logic.Is(LOGIC_GLITCHLESS)) { + } else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) { return conditions_met[0](); - } else if (Settings::Logic.Is(LOGIC_GLITCHED)) { + } else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) { if (conditions_met[0]()) { return true; } else if (conditions_met[1] != NULL) { @@ -77,11 +82,12 @@ public: } bool GetConditionsMet() const { - if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) { + auto ctx = Rando::Context::GetInstance(); + if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) { return true; - } else if (Settings::Logic.Is(LOGIC_GLITCHLESS)) { + } else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) { return conditions_met[0](); - } else if (Settings::Logic.Is(LOGIC_GLITCHED)) { + } else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) { if (conditions_met[0]()) { return true; } else if (conditions_met[1] != NULL) { @@ -107,8 +113,10 @@ protected: bool CanBuy() const; }; -class Entrance; -enum class EntranceType; +namespace Rando { + class Entrance; + enum class EntranceType; +} class Area { public: @@ -117,7 +125,7 @@ public: bool timePass_, std::vector events_, std::vector locations_, - std::list exits_); + std::list exits_); ~Area(); std::string regionName; @@ -126,8 +134,8 @@ public: bool timePass; std::vector events; std::vector locations; - std::list exits; - std::list entrances; + std::list exits; + std::list entrances; //^ The above exits are now stored in a list instead of a vector because //the entrance randomization algorithm plays around with pointers to these //entrances a lot. By putting the entrances in a list, we don't have to @@ -144,11 +152,11 @@ public: void AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition); - void RemoveExit(Entrance* exitToRemove); + void RemoveExit(Rando::Entrance* exitToRemove); void SetAsPrimary(RandomizerRegion exitToBePrimary); - Entrance* GetExit(RandomizerRegion exit); + Rando::Entrance* GetExit(RandomizerRegion exit); bool Child() const { return childDay || childNight; @@ -240,7 +248,7 @@ namespace Areas { void AreaTable_Init(); Area* AreaTable(const RandomizerRegion areaKey); -std::vector GetShuffleableEntrances(EntranceType type, bool onlyPrimary = true); +std::vector GetShuffleableEntrances(Rando::EntranceType type, bool onlyPrimary = true); // Overworld void AreaTable_Init_LostWoods(); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp index 31cbf7c44..b9499ff23 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_BottomOfTheWell() { /*-------------------------- @@ -12,38 +12,38 @@ void AreaTable_Init_BottomOfTheWell() { ---------------------------*/ areaTable[RR_BOTTOM_OF_THE_WELL_ENTRYWAY] = Area("Bottom of the Well Entryway", "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_MAIN_AREA, {[]{return Dungeon::BottomOfTheWell.IsVanilla() && IsChild && (CanChildAttack || Nuts);}}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, {[]{return Dungeon::BottomOfTheWell.IsMQ() && IsChild;}}), + Entrance(RR_BOTTOM_OF_THE_WELL_MAIN_AREA, {[]{return randoCtx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla() && IsChild && (CanChildAttack || Nuts);}}), + Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, {[]{return randoCtx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsMQ() && IsChild;}}), Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::BottomOfTheWell.IsVanilla()) { + if (randoCtx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla()) { areaTable[RR_BOTTOM_OF_THE_WELL_MAIN_AREA] = Area("Bottom of the Well Main Area", "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&StickPot, {[]{return true;}}), EventAccess(&NutPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH);}}), LocationAccess(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, {[]{return HasExplosives;}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, {[]{return (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH);}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH);}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH);}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}), LocationAccess(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, {[]{return Sticks || CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, {[]{return CanPlay(ZeldasLullaby) && (KokiriSword || (Sticks && LogicChildDeadhand));}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, {[]{return CanPlay(ZeldasLullaby) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH));}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, {[]{return CanPlay(ZeldasLullaby) && (KokiriSword || (Sticks && randoCtx->GetTrickOption(RT_BOTW_CHILD_DEADHAND)));}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, {[]{return CanPlay(ZeldasLullaby) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH));}}), LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, {[]{return CanPlay(ZeldasLullaby);}}), LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, {[]{return CanPlay(ZeldasLullaby);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, {[]{return HasExplosives || (((SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH))) || CanUse(RG_DINS_FIRE) || (Sticks && LogicBotwBasement)) && GoronBracelet);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, {[]{return Boomerang && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, {[]{return Boomerang && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && Boomerang;}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, {[]{return HasExplosives || (((SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH))) || CanUse(RG_DINS_FIRE) || (Sticks && randoCtx->GetTrickOption(RT_BOTW_BASEMENT))) && GoronBracelet);}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH));}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH));}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, {[]{return Boomerang && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH)) && SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, {[]{return Boomerang && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH)) && SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH)) && Boomerang;}}), }, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}), @@ -53,21 +53,21 @@ void AreaTable_Init_BottomOfTheWell() { /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::BottomOfTheWell.IsMQ()) { + if (randoCtx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsMQ()) { areaTable[RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER] = Area("Bottom of the Well MQ Perimeter", "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, { //Events //EventAccess(&WallFairy, {[]{return WallFairy || Slingshot;}}), }, { //Locations - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, {[]{return KokiriSword || (Sticks && LogicChildDeadhand);}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, {[]{return HasExplosives || (LogicBotwMQDeadHandKey && Boomerang);}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, {[]{return KokiriSword || (Sticks && randoCtx->GetTrickOption(RT_BOTW_CHILD_DEADHAND));}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, {[]{return HasExplosives || (randoCtx->GetTrickOption(RT_BOTW_MQ_DEADHAND_KEY) && Boomerang);}}), //Trick: HasExplosives || (LogicBotWMQDeadHandKey && Boomerang) LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, {[]{return CanChildAttack;}}), LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, {[]{return CanChildAttack && SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}}), }, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, {[]{return CanPlay(ZeldasLullaby) || (LogicBotwMQPits && HasExplosives);}}), + Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, {[]{return CanPlay(ZeldasLullaby) || (randoCtx->GetTrickOption(RT_BOTW_MQ_PITS) && HasExplosives);}}), //Trick: CanPlay(ZeldasLullaby) || (LogicBotWMQPits && HasExplosives) }); @@ -76,7 +76,7 @@ void AreaTable_Init_BottomOfTheWell() { LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, {[]{return true;}}), LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, {[]{return HasExplosives && SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}}), LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, {[]{return true;}}), - LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, {[]{return CanChildAttack && (LogicBotwMQPits || HasExplosives);}}), + LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, {[]{return CanChildAttack && (randoCtx->GetTrickOption(RT_BOTW_MQ_PITS) || HasExplosives);}}), //Trick: CanChildAttack && (LogicBotWMQPits || HasExplosives) }, { //Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp index edcf795ad..dd4f942de 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp @@ -1,9 +1,9 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" +#include "../../entrance.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_ENTRANCE] = Area("Market Entrance", "Market Entrance", RHT_THE_MARKET, NO_DAY_NIGHT_CYCLE, {}, {}, { @@ -58,7 +58,7 @@ void AreaTable_Init_CastleTown() { }, { //Exits Entrance(RR_TOT_ENTRANCE, {[]{return true;}}), - Entrance(RR_TOT_BEYOND_DOOR_OF_TIME, {[]{return OpenDoorOfTime.Is(OPENDOOROFTIME_OPEN) || (CanPlay(SongOfTime) && (OpenDoorOfTime.Is(OPENDOOROFTIME_SONGONLY) || (HasAllStones && OcarinaOfTime)));}}), + Entrance(RR_TOT_BEYOND_DOOR_OF_TIME, {[]{return randoCtx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN) || (CanPlay(SongOfTime) && (randoCtx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_SONGONLY) || (HasAllStones && OcarinaOfTime)));}}), }); areaTable[RR_TOT_BEYOND_DOOR_OF_TIME] = Area("Beyond Door of Time", "Beyond Door of Time", RHT_TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, { @@ -94,7 +94,7 @@ void AreaTable_Init_CastleTown() { }, { //Exits Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}), - Entrance(RR_HC_GARDEN, {[]{return WeirdEgg || !ShuffleWeirdEgg;}}), + Entrance(RR_HC_GARDEN, {[]{return WeirdEgg || !randoCtx->GetOption(RSK_SHUFFLE_WEIRD_EGG);}}), Entrance(RR_HC_GREAT_FAIRY_FOUNTAIN, {[]{return CanBlastOrSmash;}}), Entrance(RR_HC_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}), }); @@ -125,7 +125,7 @@ void AreaTable_Init_CastleTown() { EventAccess(&WanderingBugs, {[]{return WanderingBugs || CanBlastOrSmash;}}), }, { //Locations - LocationAccess(RC_HC_GS_STORMS_GROTTO, {[]{return (CanBlastOrSmash && HookshotOrBoomerang) || (Boomerang && LogicCastleStormsGS);}}), + LocationAccess(RC_HC_GS_STORMS_GROTTO, {[]{return (CanBlastOrSmash && HookshotOrBoomerang) || (Boomerang && randoCtx->GetTrickOption(RT_HC_STORMS_GS));}}), LocationAccess(RC_HC_STORMS_GROTTO_GOSSIP_STONE, {[]{return CanBlastOrSmash;}}), }, { //Exits @@ -192,8 +192,8 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_MASK_SHOP] = Area("Market Mask Shop", "Market Mask Shop", RHT_NONE, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&SkullMask, {[]{return SkullMask || (ZeldasLetter && (CompleteMaskQuest || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}}), - EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (CompleteMaskQuest || (ChildCanAccess(RR_THE_LOST_WOODS) && CanPlay(SariasSong) && AreaTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && HasAllStones)));}}), + EventAccess(&SkullMask, {[]{return SkullMask || (ZeldasLetter && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}}), + EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && CanPlay(SariasSong) && AreaTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && HasAllStones)));}}), }, {}, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), @@ -235,12 +235,12 @@ void AreaTable_Init_CastleTown() { areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "Market Treasure Chest Game", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_GREG_HINT, {[]{return true;}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1));}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}), - LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME));}}), }, { //Exits Entrance(RR_THE_MARKET, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp index 65c6a4c2c..ced34dcd9 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp @@ -1,26 +1,27 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" +#include "../../entrance.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_DeathMountain() { + auto ctx = Rando::Context::GetInstance(); areaTable[RR_DEATH_MOUNTAIN_TRAIL] = Area("Death Mountain", "Death Mountain", RHT_DEATH_MOUNTAIN_TRAIL, DAY_NIGHT_CYCLE, { //Events EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && CanPlay(SongOfStorms) && (HasExplosives || GoronBracelet));}}), }, { //Locations - LocationAccess(RC_DMT_CHEST, {[]{return CanBlastOrSmash || (LogicDMTBombable && IsChild && GoronBracelet);}}), + LocationAccess(RC_DMT_CHEST, {[]{return CanBlastOrSmash || (randoCtx->GetTrickOption(RT_DMT_BOMBABLE) && IsChild && GoronBracelet);}}), LocationAccess(RC_DMT_FREESTANDING_POH, {[]{return CanTakeDamage || CanUse(RG_HOVER_BOOTS) || (IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && (HasExplosives || GoronBracelet));}}), - LocationAccess(RC_DMT_GS_BEAN_PATCH, {[]{return CanPlantBugs && (HasExplosives || GoronBracelet || (LogicDMTSoilGS && (CanTakeDamage || CanUse(RG_HOVER_BOOTS)) && CanUse(RG_BOOMERANG)));}}), + LocationAccess(RC_DMT_GS_BEAN_PATCH, {[]{return CanPlantBugs && (HasExplosives || GoronBracelet || (randoCtx->GetTrickOption(RT_DMT_SOIL_GS) && (CanTakeDamage || CanUse(RG_HOVER_BOOTS)) && CanUse(RG_BOOMERANG)));}}), LocationAccess(RC_DMT_GS_NEAR_KAK, {[]{return CanBlastOrSmash;}}), - LocationAccess(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, {[]{return IsAdult && AtNight && (CanUse(RG_MEGATON_HAMMER) || (LogicDMTGSLowerHookshot && CanUse(RG_HOOKSHOT)) || (LogicDMTGSLowerBean && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL)) || (LogicDMTGSLowerHovers && CanUse(RG_HOVER_BOOTS)) || LogicDMTGSLowerJS) && CanGetNightTimeGS;}}), + LocationAccess(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, {[]{return IsAdult && AtNight && (CanUse(RG_MEGATON_HAMMER) || (randoCtx->GetTrickOption(RT_DMT_HOOKSHOT_LOWER_GS) && CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL)) || (randoCtx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && CanUse(RG_HOVER_BOOTS)) || randoCtx->GetTrickOption(RT_DMT_JS_LOWER_GS)) && CanGetNightTimeGS;}}), }, { //Exits Entrance(RR_KAK_BEHIND_GATE, {[]{return true;}}), Entrance(RR_GORON_CITY, {[]{return true;}}), - Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return Here(RR_DEATH_MOUNTAIN_TRAIL, []{return CanBlastOrSmash;}) || (IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && GoronBracelet) || (HoverBoots && LogicDMTClimbHovers)));}}), + Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return Here(RR_DEATH_MOUNTAIN_TRAIL, []{return CanBlastOrSmash;}) || (IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && GoronBracelet) || (HoverBoots && randoCtx->GetTrickOption(RT_DMT_CLIMB_HOVERS))));}}), Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, {[]{return HasExplosives || GoronBracelet || IsAdult;}}), Entrance(RR_DMT_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}), }); @@ -35,7 +36,7 @@ void AreaTable_Init_DeathMountain() { LocationAccess(RC_DMT_TRADE_BROKEN_SWORD, {[]{return IsAdult && BrokenSword;}}), LocationAccess(RC_DMT_TRADE_EYEDROPS, {[]{return IsAdult && Eyedrops;}}), LocationAccess(RC_DMT_TRADE_CLAIM_CHECK, {[]{return IsAdult && ClaimCheck;}}), - LocationAccess(RC_DMT_GS_FALLING_ROCKS_PATH, {[]{return IsAdult && AtNight && (CanUse(RG_MEGATON_HAMMER) || LogicDMTGSUpper) && CanGetNightTimeGS;}}), + LocationAccess(RC_DMT_GS_FALLING_ROCKS_PATH, {[]{return IsAdult && AtNight && (CanUse(RG_MEGATON_HAMMER) || randoCtx->GetTrickOption(RT_DMT_UPPER_GS)) && CanGetNightTimeGS;}}), LocationAccess(RC_DMT_GOSSIP_STONE, {[]{return true;}}), }, { //Exits @@ -85,14 +86,14 @@ void AreaTable_Init_DeathMountain() { EventAccess(&GoronCityChildFire, {[]{return GoronCityChildFire || (IsChild && CanUse(RG_DINS_FIRE));}}), EventAccess(&GCWoodsWarpOpen, {[]{return GCWoodsWarpOpen || (CanBlastOrSmash || CanUse(RG_DINS_FIRE) || CanUse(RG_FAIRY_BOW) || GoronBracelet || GoronCityChildFire);}}), EventAccess(&GCDaruniasDoorOpenChild, {[]{return GCDaruniasDoorOpenChild || (IsChild && CanPlay(ZeldasLullaby));}}), - EventAccess(&StopGCRollingGoronAsAdult, {[]{return StopGCRollingGoronAsAdult || (IsAdult && (GoronBracelet || HasExplosives || Bow || (LogicGoronCityLinkGoronDins && CanUse(RG_DINS_FIRE))));}}), + EventAccess(&StopGCRollingGoronAsAdult, {[]{return StopGCRollingGoronAsAdult || (IsAdult && (GoronBracelet || HasExplosives || Bow || (randoCtx->GetTrickOption(RT_GC_LINK_GORON_DINS) && CanUse(RG_DINS_FIRE))));}}), }, { //Locations - LocationAccess(RC_GC_MAZE_LEFT_CHEST, {[]{return CanUse(RG_MEGATON_HAMMER) || CanUse(RG_SILVER_GAUNTLETS) || (LogicGoronCityLeftMost && HasExplosives && CanUse(RG_HOVER_BOOTS));}}), + LocationAccess(RC_GC_MAZE_LEFT_CHEST, {[]{return CanUse(RG_MEGATON_HAMMER) || CanUse(RG_SILVER_GAUNTLETS) || (randoCtx->GetTrickOption(RT_GC_LEFTMOST) && HasExplosives && CanUse(RG_HOVER_BOOTS));}}), LocationAccess(RC_GC_MAZE_CENTER_CHEST, {[]{return CanBlastOrSmash || CanUse(RG_SILVER_GAUNTLETS);}}), LocationAccess(RC_GC_MAZE_RIGHT_CHEST, {[]{return CanBlastOrSmash || CanUse(RG_SILVER_GAUNTLETS);}}), - LocationAccess(RC_GC_POT_FREESTANDING_POH, {[]{return IsChild && GoronCityChildFire && (Bombs || (GoronBracelet && LogicGoronCityPotWithStrength) || (HasBombchus && LogicGoronCityPot));}}), - LocationAccess(RC_GC_ROLLING_GORON_AS_CHILD, {[]{return IsChild && (HasExplosives || (GoronBracelet && LogicChildRollingWithStrength));}}), + LocationAccess(RC_GC_POT_FREESTANDING_POH, {[]{return IsChild && GoronCityChildFire && (Bombs || (GoronBracelet && randoCtx->GetTrickOption(RT_GC_POT_STRENGTH)) || (HasBombchus && randoCtx->GetTrickOption(RT_GC_POT)));}}), + LocationAccess(RC_GC_ROLLING_GORON_AS_CHILD, {[]{return IsChild && (HasExplosives || (GoronBracelet && randoCtx->GetTrickOption(RT_GC_ROLLING_STRENGTH)));}}), LocationAccess(RC_GC_ROLLING_GORON_AS_ADULT, {[]{return StopGCRollingGoronAsAdult;}}), LocationAccess(RC_GC_GS_BOULDER_MAZE, {[]{return IsChild && CanBlastOrSmash;}}), LocationAccess(RC_GC_GS_CENTER_PLATFORM, {[]{return CanAdultAttack;}}), @@ -105,7 +106,7 @@ void AreaTable_Init_DeathMountain() { Entrance(RR_GC_WOODS_WARP, {[]{return GCWoodsWarpOpen;}}), Entrance(RR_GC_SHOP, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || (IsChild && (CanBlastOrSmash || GoronBracelet || GoronCityChildFire || CanUse(RG_FAIRY_BOW)));}}), Entrance(RR_GC_DARUNIAS_CHAMBER, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || GCDaruniasDoorOpenChild;}}), - Entrance(RR_GC_GROTTO_PLATFORM, {[]{return IsAdult && ((CanPlay(SongOfTime) && ((EffectiveHealth > 2) || CanUse(RG_GORON_TUNIC) || CanUse(RG_LONGSHOT) || CanUse(RG_NAYRUS_LOVE))) || (EffectiveHealth > 1 && CanUse(RG_GORON_TUNIC) && CanUse(RG_HOOKSHOT)) || (CanUse(RG_NAYRUS_LOVE) && CanUse(RG_HOOKSHOT)) || (EffectiveHealth > 2 && CanUse(RG_HOOKSHOT) && LogicGoronCityGrotto));}}), + Entrance(RR_GC_GROTTO_PLATFORM, {[]{return IsAdult && ((CanPlay(SongOfTime) && ((EffectiveHealth > 2) || CanUse(RG_GORON_TUNIC) || CanUse(RG_LONGSHOT) || CanUse(RG_NAYRUS_LOVE))) || (EffectiveHealth > 1 && CanUse(RG_GORON_TUNIC) && CanUse(RG_HOOKSHOT)) || (CanUse(RG_NAYRUS_LOVE) && CanUse(RG_HOOKSHOT)) || (EffectiveHealth > 2 && CanUse(RG_HOOKSHOT) && randoCtx->GetTrickOption(RT_GC_GROTTO)));}}), }); areaTable[RR_GC_WOODS_WARP] = Area("GC Woods Warp", "Goron City", RHT_GORON_CITY, NO_DAY_NIGHT_CYCLE, { @@ -179,7 +180,7 @@ void AreaTable_Init_DeathMountain() { //Exits Entrance(RR_DMC_UPPER_NEARBY, {[]{return true;}}), Entrance(RR_DMC_LADDER_AREA_NEARBY, {[]{return FireTimer >= 16 || Hearts >= 3;}}), - Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && CanUse(RG_DISTANT_SCARECROW) && ((EffectiveHealth > 2) || (Fairy && ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) || CanUse(RG_NAYRUS_LOVE));}}), + Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && CanUse(RG_DISTANT_SCARECROW) && ((EffectiveHealth > 2) || (Fairy && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)) || CanUse(RG_NAYRUS_LOVE));}}), Entrance(RR_DMC_LOWER_NEARBY, {[]{return false;}}), }); @@ -189,7 +190,7 @@ void AreaTable_Init_DeathMountain() { }, { //Exits Entrance(RR_DMC_UPPER_NEARBY, {[]{return Hearts >= 3;}}), - Entrance(RR_DMC_LOWER_NEARBY, {[]{return Hearts >= 3 && (CanUse(RG_HOVER_BOOTS) || (LogicCraterBoulderJS && IsAdult && CanUse(RG_MEGATON_HAMMER)) || (LogicCraterBoulderSkip && IsAdult));}}), + Entrance(RR_DMC_LOWER_NEARBY, {[]{return Hearts >= 3 && (CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_DMC_BOULDER_JS) && IsAdult && CanUse(RG_MEGATON_HAMMER)) || (randoCtx->GetTrickOption(RT_DMC_BOULDER_SKIP) && IsAdult));}}), }); areaTable[RR_DMC_LOWER_NEARBY] = Area("DMC Lower Nearby", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {}, { @@ -205,12 +206,12 @@ void AreaTable_Init_DeathMountain() { Entrance(RR_DMC_LOWER_NEARBY, {[]{return true;}}), Entrance(RR_DMC_LADDER_AREA_NEARBY, {[]{return FireTimer >= 8 || Hearts >= 3;}}), Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT)) && (FireTimer >= 8 || Hearts >= 3);}}), - Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT) || (IsAdult && CanShield && LogicCraterBoleroJump)) && FireTimer >= 24;}}), + Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT) || (IsAdult && CanShield && randoCtx->GetTrickOption(RT_DMC_BOLERO_JUMP))) && FireTimer >= 24;}}), }); areaTable[RR_DMC_CENTRAL_NEARBY] = Area("DMC Central Nearby", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DMC_VOLCANO_FREESTANDING_POH, {[]{return IsAdult && Hearts >= 3 && (CanPlantBean(RR_DMC_CENTRAL_LOCAL) || (LogicCraterBeanPoHWithHovers && HoverBoots));}}), + LocationAccess(RC_DMC_VOLCANO_FREESTANDING_POH, {[]{return IsAdult && Hearts >= 3 && (CanPlantBean(RR_DMC_CENTRAL_LOCAL) || (randoCtx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && HoverBoots));}}), LocationAccess(RC_SHEIK_IN_CRATER, {[]{return IsAdult && (FireTimer >= 8 || Hearts >= 3);}}), }, { //Exits @@ -228,7 +229,7 @@ void AreaTable_Init_DeathMountain() { Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return true;}}), Entrance(RR_DMC_LOWER_NEARBY, {[]{return (IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL)) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT);}}), Entrance(RR_DMC_UPPER_NEARBY, {[]{return IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL);}}), - Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return (IsChild && Hearts >= 3 && ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) || (IsAdult && FireTimer >= 24);}}), + Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return (IsChild && Hearts >= 3 && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)) || (IsAdult && FireTimer >= 24);}}), }); areaTable[RR_DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "DMC Great Fairy Fountain", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp index fa78e021b..fd0fbe6f0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_DekuTree() { /*-------------------------- @@ -12,15 +12,15 @@ void AreaTable_Init_DekuTree() { ---------------------------*/ areaTable[RR_DEKU_TREE_ENTRYWAY] = Area("Deku Tree Entryway", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_DEKU_TREE_LOBBY, {[]{return Dungeon::DekuTree.IsVanilla();}}), - Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return Dungeon::DekuTree.IsMQ();}}), + Entrance(RR_DEKU_TREE_LOBBY, {[]{return randoCtx->GetDungeon(DEKU_TREE)->IsVanilla();}}), + Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return randoCtx->GetDungeon(DEKU_TREE)->IsMQ();}}), Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::DekuTree.IsVanilla()) { + if (randoCtx->GetDungeon(DEKU_TREE)->IsVanilla()) { areaTable[RR_DEKU_TREE_LOBBY] = Area("Deku Tree Lobby", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_BOOMERANG));}}), @@ -77,12 +77,12 @@ void AreaTable_Init_DekuTree() { //Locations LocationAccess(RC_DEKU_TREE_BASEMENT_CHEST, {[]{return true;}}), LocationAccess(RC_DEKU_TREE_GS_BASEMENT_GATE, {[]{return CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_DEKU_TREE_GS_BASEMENT_VINES, {[]{return CanUseProjectile || CanUse(RG_DINS_FIRE) || (LogicDekuBasementGS && CanJumpslash);}}), + LocationAccess(RC_DEKU_TREE_GS_BASEMENT_VINES, {[]{return CanUseProjectile || CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && CanJumpslash);}}), }, { //Exits Entrance(RR_DEKU_TREE_LOBBY, {[]{return true;}}), Entrance(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, {[]{return Here(RR_DEKU_TREE_BASEMENT_LOWER, []{return HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW);});}}), - Entrance(RR_DEKU_TREE_BASEMENT_UPPER, {[]{return IsAdult || LogicDekuB1Skip || HasAccessTo(RR_DEKU_TREE_BASEMENT_UPPER);}}), + Entrance(RR_DEKU_TREE_BASEMENT_UPPER, {[]{return IsAdult || randoCtx->GetTrickOption(RT_DEKU_B1_SKIP) || HasAccessTo(RR_DEKU_TREE_BASEMENT_UPPER);}}), Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return false;}}), }); @@ -137,7 +137,7 @@ void AreaTable_Init_DekuTree() { //Exits Entrance(RR_DEKU_TREE_BASEMENT_LOWER, {[]{return true;}}), Entrance(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, {[]{return IsChild;}}), - Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return Here(RR_DEKU_TREE_BASEMENT_UPPER, []{return HasFireSourceWithTorch || (LogicDekuB1WebsWithBow && IsAdult && CanUse(RG_FAIRY_BOW));});}}), + Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return Here(RR_DEKU_TREE_BASEMENT_UPPER, []{return HasFireSourceWithTorch || (randoCtx->GetTrickOption(RT_DEKU_B1_BOW_WEBS) && IsAdult && CanUse(RG_FAIRY_BOW));});}}), }); areaTable[RR_DEKU_TREE_OUTSIDE_BOSS_ROOM] = Area("Deku Tree Outside Boss Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, { @@ -150,7 +150,7 @@ void AreaTable_Init_DekuTree() { /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::DekuTree.IsMQ()) { + if (randoCtx->GetDungeon(DEKU_TREE)->IsMQ()) { areaTable[RR_DEKU_TREE_MQ_LOBBY] = Area("Deku Tree MQ Lobby", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_BOOMERANG));}}), @@ -169,7 +169,7 @@ void AreaTable_Init_DekuTree() { Here(RR_DEKU_TREE_MQ_LOBBY, []{return HasFireSourceWithTorch || (IsAdult && CanUse(RG_FAIRY_BOW));});}}), Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, {[]{return Here(RR_DEKU_TREE_MQ_LOBBY, []{return (IsChild && CanUse(RG_FAIRY_SLINGSHOT)) || (IsAdult && CanUse(RG_FAIRY_BOW));}) && Here(RR_DEKU_TREE_MQ_LOBBY, []{return HasFireSourceWithTorch;});}}), - Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return LogicDekuB1Skip || Here(RR_DEKU_TREE_MQ_LOBBY, []{return IsAdult;});}}), + Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return randoCtx->GetTrickOption(RT_DEKU_B1_SKIP) || Here(RR_DEKU_TREE_MQ_LOBBY, []{return IsAdult;});}}), }); areaTable[RR_DEKU_TREE_MQ_COMPASS_ROOM] = Area("Deku Tree MQ Compass Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, { @@ -178,7 +178,7 @@ void AreaTable_Init_DekuTree() { LocationAccess(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, {[]{return HookshotOrBoomerang && Here(RR_DEKU_TREE_MQ_COMPASS_ROOM, []{return HasBombchus || (Bombs && (CanPlay(SongOfTime) || IsAdult)) || - (IsAdult && CanUse(RG_MEGATON_HAMMER) && (CanPlay(SongOfTime) || LogicDekuMQCompassGS));});}}), + (IsAdult && CanUse(RG_MEGATON_HAMMER) && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS)));});}}), }, { //Exits Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return true;}}), @@ -189,7 +189,7 @@ void AreaTable_Init_DekuTree() { LocationAccess(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, {[]{return true;}}), }, { //Exits - Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return LogicDekuMQLog || (IsChild && (DekuShield || HylianShield)) || + Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return randoCtx->GetTrickOption(RT_DEKU_MQ_LOG) || (IsChild && (DekuShield || HylianShield)) || (IsAdult && (CanUse(RG_LONGSHOT) || (CanUse(RG_HOOKSHOT) && CanUse(RG_IRON_BOOTS))));}}), Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return true;}}), }); @@ -244,8 +244,8 @@ void AreaTable_Init_DekuTree() { Area("Deku Tree Boss Entryway", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, { [] { return Dungeon::DekuTree.IsVanilla(); } }), - Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, { [] { return Dungeon::DekuTree.IsMQ(); } }), + Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, { [] { return randoCtx->GetDungeon(DEKU_TREE)->IsVanilla(); } }), + Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, { [] { return randoCtx->GetDungeon(DEKU_TREE)->IsMQ(); } }), Entrance(RR_DEKU_TREE_BOSS_ROOM, { [] { return true; } }), }); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp index 984ce8dc5..ed9502b77 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_DodongosCavern() { /*-------------------------- @@ -12,15 +12,15 @@ void AreaTable_Init_DodongosCavern() { ---------------------------*/ areaTable[RR_DODONGOS_CAVERN_ENTRYWAY] = Area("Dodongos Cavern Entryway", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_DODONGOS_CAVERN_BEGINNING, {[]{return Dungeon::DodongosCavern.IsVanilla();}}), - Entrance(RR_DODONGOS_CAVERN_MQ_BEGINNING, {[]{return Dungeon::DodongosCavern.IsMQ();}}), + Entrance(RR_DODONGOS_CAVERN_BEGINNING, {[]{return randoCtx->GetDungeon(DODONGOS_CAVERN)->IsVanilla();}}), + Entrance(RR_DODONGOS_CAVERN_MQ_BEGINNING, {[]{return randoCtx->GetDungeon(DODONGOS_CAVERN)->IsMQ();}}), Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::DodongosCavern.IsVanilla()) { + if (randoCtx->GetDungeon(DODONGOS_CAVERN)->IsVanilla()) { areaTable[RR_DODONGOS_CAVERN_BEGINNING] = Area("Dodongos Cavern Beginning", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, {[]{return true;}}), @@ -54,7 +54,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_SE_CORRIDOR] = Area("Dodongos Cavern SE Corridor", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_DODONGOS_CAVERN_GS_SCARECROW, {[]{return CanUse(RG_SCARECROW) || (IsAdult && CanUse(RG_LONGSHOT)) || (LogicDCScarecrowGS && (CanAdultAttack || CanChildAttack));}}), + LocationAccess(RC_DODONGOS_CAVERN_GS_SCARECROW, {[]{return CanUse(RG_SCARECROW) || (IsAdult && CanUse(RG_LONGSHOT)) || (randoCtx->GetTrickOption(RT_DC_SCARECROW_GS) && (CanAdultAttack || CanChildAttack));}}), }, { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}), @@ -102,14 +102,14 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_STAIRS_LOWER] = Area("Dodongos Cavern Stairs Lower", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}), - Entrance(RR_DODONGOS_CAVERN_STAIRS_UPPER, {[]{return HasExplosives || GoronBracelet || CanUse(RG_DINS_FIRE) || (LogicDCStaircase && CanUse(RG_FAIRY_BOW));}}), + Entrance(RR_DODONGOS_CAVERN_STAIRS_UPPER, {[]{return HasExplosives || GoronBracelet || CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_DC_STAIRCASE) && CanUse(RG_FAIRY_BOW));}}), Entrance(RR_DODONGOS_CAVERN_COMPASS_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_STAIRS_LOWER, []{return CanBlastOrSmash || GoronBracelet;});}}), }); areaTable[RR_DODONGOS_CAVERN_STAIRS_UPPER] = Area("Dodongos Cavern Stairs Upper", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, {[]{return Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return HookshotOrBoomerang;}) || CanUse(RG_LONGSHOT);}}), - LocationAccess(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, {[]{return IsAdult || CanChildAttack || (HasAccessTo(RR_DODONGOS_CAVERN_STAIRS_LOWER) && CanUse(RG_LONGSHOT) && LogicDCVinesGS);}}), + LocationAccess(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, {[]{return IsAdult || CanChildAttack || (HasAccessTo(RR_DODONGOS_CAVERN_STAIRS_LOWER) && CanUse(RG_LONGSHOT) && randoCtx->GetTrickOption(RT_DC_VINES_GS));}}), }, { //Exits Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, {[]{return true;}}), @@ -135,9 +135,9 @@ void AreaTable_Init_DodongosCavern() { LocationAccess(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, {[]{return true;}}), }, { //Exits - Entrance(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || (LogicDCScrubRoom && GoronBracelet);});}}), + Entrance(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || (randoCtx->GetTrickOption(RT_DC_SCRUB_ROOM) && GoronBracelet);});}}), Entrance(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || GoronBracelet;});}}), - Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return (IsAdult && LogicDCJump) || CanUse(RG_HOVER_BOOTS) || (IsAdult && CanUse(RG_LONGSHOT));}}), + Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return (IsAdult && randoCtx->GetTrickOption(RT_DC_JUMP)) || CanUse(RG_HOVER_BOOTS) || (IsAdult && CanUse(RG_LONGSHOT));}}), }); areaTable[RR_DODONGOS_CAVERN_2F_SIDE_ROOM] = Area("Dodongos Cavern 2F Side Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { @@ -152,7 +152,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM] = Area("Dodongos Cavern First Slingshot Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}), - Entrance(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || LogicDCSlingshotSkip;}}), + Entrance(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || randoCtx->GetTrickOption(RT_DC_SLINGSHOT_SKIP);}}), }); areaTable[RR_DODONGOS_CAVERN_UPPER_LIZALFOS] = Area("Dodongos Cavern Upper Lizalfos", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { @@ -167,7 +167,7 @@ void AreaTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM] = Area("Dodongos Cavern Second Slingshot Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return true;}}), - Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || LogicDCSlingshotSkip;}}), + Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || randoCtx->GetTrickOption(RT_DC_SLINGSHOT_SKIP);}}), }); areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER] = Area("Dodongos Cavern Bomb Room Upper", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { @@ -211,7 +211,7 @@ void AreaTable_Init_DodongosCavern() { /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::DodongosCavern.IsMQ()) { + if (randoCtx->GetDungeon(DODONGOS_CAVERN)->IsMQ()) { areaTable[RR_DODONGOS_CAVERN_MQ_BEGINNING] = Area("Dodongos Cavern MQ Beginning", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, {[]{return true;}}), @@ -227,7 +227,7 @@ void AreaTable_Init_DodongosCavern() { LocationAccess(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, {[]{return true;}}), LocationAccess(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, {[]{return CanAdultAttack || CanChildAttack || Nuts;}}), LocationAccess(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, {[]{return (IsChild && CanUse(RG_STICKS)) || HasFireSource;}}), - LocationAccess(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, {[]{return CanBlastOrSmash || (IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) || (IsAdult && (LogicDCJump || HoverBoots || Hookshot));}}), + LocationAccess(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, {[]{return CanBlastOrSmash || (IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) || (IsAdult && (randoCtx->GetTrickOption(RT_DC_JUMP) || HoverBoots || Hookshot));}}), LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, {[]{return CanPlay(SongOfTime) && (CanChildAttack || CanAdultAttack);}}), LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, {[]{return (IsChild && CanUse(RG_STICKS)) || HasFireSource;}}), LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, {[]{return CanBlastOrSmash;}}), @@ -238,9 +238,9 @@ void AreaTable_Init_DodongosCavern() { }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return CanBlastOrSmash || (((IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE)) && CanTakeDamage);});}}), - Entrance(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return IsAdult || (Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return IsAdult;}) && HasExplosives) || (LogicDCMQChildBombs && CanJumpslash && CanTakeDamage);}}), + Entrance(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return IsAdult || (Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return IsAdult;}) && HasExplosives) || (randoCtx->GetTrickOption(RT_DC_MQ_CHILD_BOMBS) && CanJumpslash && CanTakeDamage);}}), //Trick: IsAdult || HasExplosives || (LogicDCMQChildBombs && (KokiriSword || Sticks) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO)) - Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, {[]{return HasExplosives || (GoronBracelet && ((IsAdult && LogicDCMQEyesAdult) || (IsChild && LogicDCMQEyesChild)) && ((IsChild && (CanUse(RG_STICKS))) || CanUse(RG_DINS_FIRE) || (IsAdult && (LogicDCJump || Hammer || HoverBoots || Hookshot))));}}), + Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, {[]{return HasExplosives || (GoronBracelet && ((IsAdult && randoCtx->GetTrickOption(RT_DC_MQ_ADULT_EYES)) || (IsChild && randoCtx->GetTrickOption(RT_DC_MQ_CHILD_EYES))) && ((IsChild && (CanUse(RG_STICKS))) || CanUse(RG_DINS_FIRE) || (IsAdult && (randoCtx->GetTrickOption(RT_DC_JUMP) || Hammer || HoverBoots || Hookshot))));}}), //Trick: HasExplosives || (LogicDCMQEyes && GoronBracelet && (IsAdult || LogicDCMQChildBack) && ((IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) || (IsAdult && (LogicDCJump || Hammer || HoverBoots || Hookshot)))) }); @@ -283,8 +283,8 @@ void AreaTable_Init_DodongosCavern() { Area("Dodongos Cavern Boss Entryway", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, { [] { return Dungeon::DodongosCavern.IsVanilla(); } }), - Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, { [] { return Dungeon::DodongosCavern.IsMQ(); } }), + Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, { [] { return randoCtx->GetDungeon(DODONGOS_CAVERN)->IsVanilla(); } }), + Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, { [] { return randoCtx->GetDungeon(DODONGOS_CAVERN)->IsMQ(); } }), Entrance(RR_DODONGOS_CAVERN_BOSS_ROOM, { [] { return true; } }), }); @@ -296,7 +296,7 @@ void AreaTable_Init_DodongosCavern() { { [] { return DodongosCavernClear || (Here(RR_DODONGOS_CAVERN_BOSS_ROOM, - [] { return HasExplosives || (CanUse(RG_MEGATON_HAMMER) && LogicDCHammerFloor); }) && + [] { return HasExplosives || (CanUse(RG_MEGATON_HAMMER) && randoCtx->GetTrickOption(RT_DC_HAMMER_FLOOR)); }) && (Bombs || GoronBracelet) && CanJumpslash); /*todo add chu kill to tricks*/ }}), }, diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp index fc274f1b2..9b43ecff4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_FireTemple() { /*-------------------------- @@ -12,15 +12,15 @@ void AreaTable_Init_FireTemple() { ---------------------------*/ areaTable[RR_FIRE_TEMPLE_ENTRYWAY] = Area("Fire Temple Entryway", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return Dungeon::FireTemple.IsVanilla();}}), - Entrance(RR_FIRE_TEMPLE_MQ_LOWER, {[]{return Dungeon::FireTemple.IsMQ();}}), + Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return randoCtx->GetDungeon(FIRE_TEMPLE)->IsVanilla();}}), + Entrance(RR_FIRE_TEMPLE_MQ_LOWER, {[]{return randoCtx->GetDungeon(FIRE_TEMPLE)->IsMQ();}}), Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::FireTemple.IsVanilla()) { + if (randoCtx->GetDungeon(FIRE_TEMPLE)->IsVanilla()) { areaTable[RR_FIRE_TEMPLE_FIRST_ROOM] = Area("Fire Temple First Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { }, { //Exits @@ -40,7 +40,7 @@ void AreaTable_Init_FireTemple() { }, { //Exits Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}), - Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && LogicFireBossDoorJump) || CanUse(RG_HOVER_BOOTS) || Here(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(RG_MEGATON_HAMMER);}));}}), + Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && randoCtx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP)) || CanUse(RG_HOVER_BOOTS) || Here(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(RG_MEGATON_HAMMER);}));}}), }); areaTable[RR_FIRE_TEMPLE_LOOP_ENEMIES] = Area("Fire Temple Loop Enemies", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { @@ -96,7 +96,7 @@ void AreaTable_Init_FireTemple() { //Exits Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 2);}}), Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON, {[]{return true;}}), - Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, {[]{return IsAdult && (CanPlay(SongOfTime) || LogicFireSongOfTime);}}), + Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, {[]{return IsAdult && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_FIRE_SOT));}}), Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON, {[]{return IsAdult && HasExplosives;}}), Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 3);}}), }); @@ -138,7 +138,7 @@ void AreaTable_Init_FireTemple() { //Exits Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 4);}}), Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, {[]{return Here(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;});}}), - Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return IsAdult && (GoronBracelet || LogicFireStrength) && (HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT));}}), + Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return IsAdult && (GoronBracelet || randoCtx->GetTrickOption(RT_FIRE_STRENGTH)) && (HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT));}}), }); areaTable[RR_FIRE_TEMPLE_SHORTCUT_CLIMB] = Area("Fire Temple Shortcut Climb", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { @@ -199,7 +199,7 @@ void AreaTable_Init_FireTemple() { Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, {[]{return HasExplosives;}}), Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return true;}}), Entrance(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, {[]{return true;}}), - Entrance(RR_FIRE_TEMPLE_SCARECROW_ROOM, {[]{return CanUse(RG_SCARECROW) || (LogicFireScarecrow && IsAdult && CanUse(RG_LONGSHOT));}}), + Entrance(RR_FIRE_TEMPLE_SCARECROW_ROOM, {[]{return CanUse(RG_SCARECROW) || (randoCtx->GetTrickOption(RT_FIRE_SCARECROW) && IsAdult && CanUse(RG_LONGSHOT));}}), }); areaTable[RR_FIRE_TEMPLE_SCARECROW_ROOM] = Area("Fire Temple Scarecrow Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { @@ -233,7 +233,7 @@ void AreaTable_Init_FireTemple() { Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return CanUse(RG_HOVER_BOOTS);}}), Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM, {[]{return true;}}), Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER, {[]{return SmallKeys(RR_FIRE_TEMPLE, 8);}}), - Entrance(RR_FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return LogicFireFlameMaze || false;}}), + Entrance(RR_FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return randoCtx->GetTrickOption(RT_FIRE_FLAME_MAZE) || false;}}), }); areaTable[RR_FIRE_TEMPLE_FIRE_MAZE_UPPER] = Area("Fire Temple Fire Maze Upper", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { @@ -253,7 +253,7 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER] = Area("Fire Temple West Central Lower", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, {[]{return Here(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (CanPlay(SongOfTime) || LogicRustedSwitches) && CanUse(RG_MEGATON_HAMMER);});}}), + LocationAccess(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, {[]{return Here(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && CanUse(RG_MEGATON_HAMMER);});}}), }, { //Exits Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 8);}}), @@ -314,16 +314,16 @@ void AreaTable_Init_FireTemple() { /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::FireTemple.IsMQ()) { + if (randoCtx->GetDungeon(FIRE_TEMPLE)->IsMQ()) { areaTable[RR_FIRE_TEMPLE_MQ_LOWER] = Area("Fire Temple MQ Lower", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, {[]{return CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || Bombs || CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, {[]{return IsAdult && (LogicFewerTunicRequirements || CanUse(RG_GORON_TUNIC)) && (((CanUse(RG_HOVER_BOOTS) || (LogicFireMQNearBoss && CanUse(RG_FAIRY_BOW))) && HasFireSource) || (CanUse(RG_HOOKSHOT) && CanUse(RG_FIRE_ARROWS) || (CanUse(RG_DINS_FIRE) && ((DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_QUADRUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OCTUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_SEXDECUPLE)) || CanUse(RG_GORON_TUNIC) || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)))));}}), + LocationAccess(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, {[]{return IsAdult && (randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_GORON_TUNIC)) && (((CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && CanUse(RG_FAIRY_BOW))) && HasFireSource) || (CanUse(RG_HOOKSHOT) && CanUse(RG_FIRE_ARROWS) || (CanUse(RG_DINS_FIRE) && ((randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_QUADRUPLE) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OCTUPLE) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_SEXDECUPLE)) || CanUse(RG_GORON_TUNIC) || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)))));}}), //Trick: IsAdult && (LogicFewerTunicRequirements || CanUse(RG_GORON_TUNIC)) && (((CanUse(RG_HOVER_BOOTS) || (LogicFireMQNearBoss && CanUse(RG_FAIRY_BOW))) && HasFireSource) || (CanUse(RG_HOOKSHOT) && CanUse(RG_FIRE_ARROWS) || (CanUse(RG_DINS_FIRE) && ((DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_QUADRUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OCTUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_SEXDECUPLE)) || CanUse(RG_GORON_TUNIC) || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT))))) }, { //Exits Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return true;}}), - Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && CanUse(RG_MEGATON_HAMMER) && BossKeyFireTemple && ((HasFireSource && (LogicFireBossDoorJump || HoverBoots)) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER));}}), + Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && CanUse(RG_MEGATON_HAMMER) && BossKeyFireTemple && ((HasFireSource && (randoCtx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || HoverBoots)) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER));}}), Entrance(RR_FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR, {[]{return SmallKeys(RR_FIRE_TEMPLE, 5) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD));}}), Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, {[]{return IsAdult && FireTimer >= 24 && CanUse(RG_MEGATON_HAMMER);}}), }); @@ -339,29 +339,29 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM] = Area("Fire Temple MQ Big Lava Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&FairyPot, {[]{return FairyPot || (HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireSongOfTime));}}), + EventAccess(&FairyPot, {[]{return FairyPot || (HasFireSource && (Bow || randoCtx->GetTrickOption(RT_FIRE_MQ_BK_CHEST)) && IsAdult && (CanUse(RG_HOOKSHOT) || randoCtx->GetTrickOption(RT_FIRE_SOT)));}}), //Trick: HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireSongOfTime) }, { //Locations - LocationAccess(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && CanUse(RG_HOOKSHOT);}}), + LocationAccess(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return HasFireSource && (Bow || randoCtx->GetTrickOption(RT_FIRE_MQ_BK_CHEST)) && IsAdult && CanUse(RG_HOOKSHOT);}}), //Trick: HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && CanUse(RG_HOOKSHOT) - LocationAccess(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return HasFireSource && HasExplosives && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireMQBlockedChest);}}), + LocationAccess(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return HasFireSource && HasExplosives && IsAdult && (CanUse(RG_HOOKSHOT) || randoCtx->GetTrickOption(RT_FIRE_MQ_BLOCKED_CHEST));}}), //Trick: HasFireSource && HasExplosives && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireMQBlockedChest) LocationAccess(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, {[]{return true;}}), }, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && SmallKeys(RR_FIRE_TEMPLE, 2) && (HasFireSource || (LogicFireMQClimb && HoverBoots));}}), + Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && SmallKeys(RR_FIRE_TEMPLE, 2) && (HasFireSource || (randoCtx->GetTrickOption(RT_FIRE_MQ_CLIMB) && HoverBoots));}}), //Trick: IsAdult && CanUse(RG_GORON_TUNIC) && SmallKeys(RR_FIRE_TEMPLE, 2) && (HasFireSource || (LogicFireMQClimb && HoverBoots)) }); areaTable[RR_FIRE_TEMPLE_MQ_LOWER_MAZE] = Area("Fire Temple MQ Lower Maze", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, {[]{return CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD);}}), - LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, {[]{return HasExplosives && (LogicFireMQMazeSideRoom || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER_MAZE));}}), + LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, {[]{return HasExplosives && (randoCtx->GetTrickOption(RT_FIRE_MQ_MAZE_SIDE_ROOM) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER_MAZE));}}), //Trick: HasExplosives && (LogicFireMQMazeSideRoom || FIRE_TEMPLE_MQ_UPPER_MAZE.Adult()) }, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return (IsAdult && ((HasExplosives && CanUse(RG_HOOKSHOT)) || (LogicFireMQMazeHovers && CanUse(RG_HOVER_BOOTS)))) || LogicFireMQMazeJump;}}), + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return (IsAdult && ((HasExplosives && CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_FIRE_MQ_MAZE_HOVERS) && CanUse(RG_HOVER_BOOTS)))) || randoCtx->GetTrickOption(RT_FIRE_MQ_MAZE_JUMP);}}), //Trick: (IsAdult && ((HasExplosives && CanUse(RG_HOOKSHOT)) || (LogicFireMQMazeHovers && CanUse(RG_HOVER_BOOTS)))) || LogicFireMQMazeJump }); @@ -381,14 +381,14 @@ void AreaTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_UPPER] = Area("Fire Temple MQ Upper", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, {[]{return ((CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG)) && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze;}}), + LocationAccess(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, {[]{return ((CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG)) && CanUse(RG_HOOKSHOT)) || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}), //Trick: (IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze - LocationAccess(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, {[]{return ((IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze) && SmallKeys(RR_FIRE_TEMPLE, 4);}}), + LocationAccess(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, {[]{return ((IsAdult && CanUse(RG_HOOKSHOT)) || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE)) && SmallKeys(RR_FIRE_TEMPLE, 4);}}), //Trick: ((IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze) && SmallKeys(RR_FIRE_TEMPLE, 4) - LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, {[]{return CanPlay(SongOfTime) || HoverBoots || LogicFireMQFlameMaze;}}), + LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, {[]{return CanPlay(SongOfTime) || HoverBoots || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}), //Trick: CanPlay(SongOfTime) || HoverBoots || LogicFireMQFlameMaze LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, {[]{return HasExplosives;}}), - LocationAccess(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, {[]{return (IsAdult && CanUse(RG_HOOKSHOT) && SmallKeys(RR_FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(RG_LONGSHOT));}}), + LocationAccess(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, {[]{return (IsAdult && CanUse(RG_HOOKSHOT) && SmallKeys(RR_FIRE_TEMPLE, 5)) || (randoCtx->GetTrickOption(RT_FIRE_MQ_ABOVE_MAZE_GS) && IsAdult && CanUse(RG_LONGSHOT));}}), //Trick: (IsAdult && CanUse(RG_HOOKSHOT) && SmallKeys(RR_FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(RG_LONGSHOT)) }, {}); } @@ -400,8 +400,8 @@ void AreaTable_Init_FireTemple() { Area("Fire Temple Boss Entryway", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, { [] { return Dungeon::FireTemple.IsVanilla() && false; } }), - Entrance(RR_FIRE_TEMPLE_MQ_LOWER, { [] { return Dungeon::FireTemple.IsMQ() && false; } }), + Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, { [] { return randoCtx->GetDungeon(FIRE_TEMPLE)->IsVanilla() && false; } }), + Entrance(RR_FIRE_TEMPLE_MQ_LOWER, { [] { return randoCtx->GetDungeon(FIRE_TEMPLE)->IsMQ() && false; } }), Entrance(RR_FIRE_TEMPLE_BOSS_ROOM, { [] { return true; } }), }); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp index 46eb64343..1f542e0e9 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_ForestTemple() { /*-------------------------- @@ -12,19 +12,19 @@ void AreaTable_Init_ForestTemple() { ---------------------------*/ areaTable[RR_FOREST_TEMPLE_ENTRYWAY] = Area("Forest Temple Entryway", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_FOREST_TEMPLE_FIRST_ROOM, {[]{return Dungeon::ForestTemple.IsVanilla();}}), - Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, {[]{return Dungeon::ForestTemple.IsMQ();}}), + Entrance(RR_FOREST_TEMPLE_FIRST_ROOM, {[]{return randoCtx->GetDungeon(FOREST_TEMPLE)->IsVanilla();}}), + Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, {[]{return randoCtx->GetDungeon(FOREST_TEMPLE)->IsMQ();}}), Entrance(RR_SACRED_FOREST_MEADOW, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::ForestTemple.IsVanilla()) { + if (randoCtx->GetDungeon(FOREST_TEMPLE)->IsVanilla()) { areaTable[RR_FOREST_TEMPLE_FIRST_ROOM] = Area("Forest Temple First Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, {[]{return true;}}), - LocationAccess(RC_FOREST_TEMPLE_GS_FIRST_ROOM, {[]{return (IsAdult && Bombs) || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG) || CanUse(RG_FAIRY_SLINGSHOT) || HasBombchus || CanUse(RG_DINS_FIRE) || (LogicForestFirstGS && (CanJumpslash || (IsChild && Bombs)));}}), + LocationAccess(RC_FOREST_TEMPLE_GS_FIRST_ROOM, {[]{return (IsAdult && Bombs) || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG) || CanUse(RG_FAIRY_SLINGSHOT) || HasBombchus || CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_FOREST_FIRST_GS) && (CanJumpslash || (IsChild && Bombs)));}}), }, { //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, {[]{return true;}}), @@ -106,12 +106,12 @@ void AreaTable_Init_ForestTemple() { EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_MEGATON_HAMMER) || HasExplosives || CanUse(RG_DINS_FIRE));}}), }, { //Locations - LocationAccess(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, {[]{return CanUse(RG_HOOKSHOT) || HasAccessTo(RR_FOREST_TEMPLE_FALLING_ROOM) || (HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) && IsAdult && LogicForestOutdoorsLedge && HoverBoots);}}), - LocationAccess(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, {[]{return CanUse(RG_HOOKSHOT) || (LogicForestOutdoorEastGS && CanUse(RG_BOOMERANG)) || Here(RR_FOREST_TEMPLE_FALLING_ROOM, []{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_DINS_FIRE) || HasExplosives;});}}), + LocationAccess(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, {[]{return CanUse(RG_HOOKSHOT) || HasAccessTo(RR_FOREST_TEMPLE_FALLING_ROOM) || (HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) && IsAdult && randoCtx->GetTrickOption(RT_FOREST_OUTDOORS_LEDGE) && HoverBoots);}}), + LocationAccess(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, {[]{return CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_FOREST_OUTDOORS_EAST_GS) && CanUse(RG_BOOMERANG)) || Here(RR_FOREST_TEMPLE_FALLING_ROOM, []{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_DINS_FIRE) || HasExplosives;});}}), }, { //Exits Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return true;}}), - Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER, {[]{return CanUse(RG_LONGSHOT) || (LogicForestVines && CanUse(RG_HOOKSHOT));}}), + Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER, {[]{return CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_FOREST_VINES) && CanUse(RG_HOOKSHOT));}}), Entrance(RR_FOREST_TEMPLE_SEWER, {[]{return GoldScale || CanUse(RG_IRON_BOOTS) || HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}), Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, {[]{return false;}}), }); @@ -124,7 +124,7 @@ void AreaTable_Init_ForestTemple() { //Exits Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return true;}}), Entrance(RR_FOREST_TEMPLE_MAP_ROOM, {[]{return true;}}), - Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, {[]{return LogicForestDoorFrame && CanJumpslash && CanUse(RG_HOVER_BOOTS) && CanUse(RG_SCARECROW);}}), + Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, {[]{return randoCtx->GetTrickOption(RT_FOREST_DOORFRAME) && CanJumpslash && CanUse(RG_HOVER_BOOTS) && CanUse(RG_SCARECROW);}}), }); areaTable[RR_FOREST_TEMPLE_MAP_ROOM] = Area("Forest Temple Map Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { @@ -170,7 +170,7 @@ void AreaTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, {[]{return true;}}), - Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return CanUse(RG_HOVER_BOOTS) || (LogicForestOutsideBackdoor && CanJumpslash && GoronBracelet);}}), + Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && CanJumpslash && GoronBracelet);}}), Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return IsAdult && GoronBracelet && SmallKeys(RR_FOREST_TEMPLE, 2);}}), Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT)) && GoronBracelet && SmallKeys(RR_FOREST_TEMPLE, 2);}}), }); @@ -279,7 +279,7 @@ void AreaTable_Init_ForestTemple() { /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::ForestTemple.IsMQ()) { + if (randoCtx->GetDungeon(FOREST_TEMPLE)->IsMQ()) { areaTable[RR_FOREST_TEMPLE_MQ_LOBBY] = Area("Forest Temple MQ Lobby", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, {[]{return CanJumpslash || Bombs || CanUse(RG_STICKS) || Nuts || HookshotOrBoomerang || CanUse(RG_DINS_FIRE) || KokiriSword || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOVER_BOOTS);}}), @@ -301,9 +301,9 @@ void AreaTable_Init_ForestTemple() { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT);}}), Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT);}}), //This is as far as child can get - Entrance(RR_FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE, {[]{return IsAdult && (GoronBracelet || (LogicForestMQBlockPuzzle && HasBombchus && IsAdult && CanUse(RG_HOOKSHOT)));}}), + Entrance(RR_FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE, {[]{return IsAdult && (GoronBracelet || (randoCtx->GetTrickOption(RT_FOREST_MQ_BLOCK_PUZZLE) && HasBombchus && IsAdult && CanUse(RG_HOOKSHOT)));}}), //Trick: IsAdult && (GoronBracelet || (LogicForestMQBlockPuzzle && HasBombchus && IsAdult && CanUse(RG_HOOKSHOT))) - Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return (LogicForestMQHallwaySwitchJS && IsAdult && CanUse(RG_HOVER_BOOTS)) || (LogicForestMQHallwaySwitchBoomerang && CanUse(RG_BOOMERANG)) || (LogicForestMQHallwaySwitchHookshot && IsAdult && CanUse(RG_HOOKSHOT));}}), + Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return (randoCtx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && IsAdult && CanUse(RG_HOVER_BOOTS)) || (randoCtx->GetTrickOption(RT_FOREST_MQ_RANG_HALLWAY_SWITCH) && CanUse(RG_BOOMERANG)) || (randoCtx->GetTrickOption(RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH) && IsAdult && CanUse(RG_HOOKSHOT));}}), //Trick (Hookshot trick not added to either n64 or oot3d rando as of yet, to enable in SoH needs uncommenting in randomizer_tricks.cpp): (LogicForestMQHallwaySwitchJS && IsAdult && CanUse(RG_HOVER_BOOTS)) || (LogicForestMQHallwaySwitchHookshot && IsAdult && CanUse(RG_HOOKSHOT)) Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, {[]{return ForestTempleJoAndBeth && ForestTempleAmyAndMeg;}}), }); @@ -314,7 +314,7 @@ void AreaTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_BOW_REGION, {[]{return SmallKeys(RR_FOREST_TEMPLE, 4);}}), - Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return SmallKeys(RR_FOREST_TEMPLE, 3) || (LogicForestMQHallwaySwitchJS && ((IsAdult && CanUse(RG_HOOKSHOT)) || (LogicForestOutsideBackdoor && (IsAdult || (IsChild && CanUse(RG_STICKS))))));}}), + Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return SmallKeys(RR_FOREST_TEMPLE, 3) || (randoCtx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && ((IsAdult && CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && (IsAdult || (IsChild && CanUse(RG_STICKS))))));}}), //Trick (Doing the hallway switch jumpslash as child requires sticks and has been added above): SmallKeys(RR_FOREST_TEMPLE, 3) || (LogicForestMQHallwaySwitchJS && ((IsAdult && CanUse(RG_HOOKSHOT)) || LogicForestOutsideBackdoor)) Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return SmallKeys(RR_FOREST_TEMPLE, 2);}}), }); @@ -332,7 +332,7 @@ void AreaTable_Init_ForestTemple() { LocationAccess(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, {[]{return CanAdultAttack || CanChildAttack;}}), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return (IsAdult && (CanUse(RG_IRON_BOOTS) || CanUse(RG_LONGSHOT) || (LogicForestMQWellSwim && CanUse(RG_HOOKSHOT)))) || ProgressiveScale >= 2;}}), + Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return (IsAdult && (CanUse(RG_IRON_BOOTS) || CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_FOREST_MQ_WELL_SWIM) && CanUse(RG_HOOKSHOT)))) || ProgressiveScale >= 2;}}), //Trick: (IsAdult && (CanUse(RG_IRON_BOOTS) || CanUse(RG_LONGSHOT) || (LogicForestMQWellSwim && CanUse(RG_HOOKSHOT)))) || ProgressiveScale >= 2 Entrance(RR_FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, {[]{return IsAdult && CanUse(RG_FIRE_ARROWS);}}), }); @@ -344,7 +344,7 @@ void AreaTable_Init_ForestTemple() { }, { //Locations LocationAccess(RC_FOREST_TEMPLE_MQ_WELL_CHEST, {[]{return (IsAdult && CanUse(RG_FAIRY_BOW)) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}), - LocationAccess(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, {[]{return HookshotOrBoomerang || (IsAdult && CanUse(RG_FIRE_ARROWS) && (CanPlay(SongOfTime) || (CanUse(RG_HOVER_BOOTS) && LogicForestDoorFrame)));}}), + LocationAccess(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, {[]{return HookshotOrBoomerang || (IsAdult && CanUse(RG_FIRE_ARROWS) && (CanPlay(SongOfTime) || (CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_FOREST_DOORFRAME))));}}), LocationAccess(RC_FOREST_TEMPLE_MQ_GS_WELL, {[]{return (IsAdult && ((CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT)) || CanUse(RG_FAIRY_BOW))) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}), }, { //Exits @@ -358,7 +358,7 @@ void AreaTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return true;}}), - Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return LogicForestOutdoorsLedge && IsAdult && CanUse(RG_HOVER_BOOTS);}}), + Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return randoCtx->GetTrickOption(RT_FOREST_OUTDOORS_LEDGE) && IsAdult && CanUse(RG_HOVER_BOOTS);}}), //Trick: LogicForestOutdoorsLedge && IsAdult && CanUse(RG_HOVER_BOOTS) }); @@ -411,8 +411,8 @@ void AreaTable_Init_ForestTemple() { Area("Forest Temple Boss Entryway", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(RR_FOREST_TEMPLE_BOSS_REGION, { [] { return Dungeon::ForestTemple.IsVanilla() && false; } }), - Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, { [] { return Dungeon::ForestTemple.IsMQ() && false; } }), + Entrance(RR_FOREST_TEMPLE_BOSS_REGION, { [] { return randoCtx->GetDungeon(FOREST_TEMPLE)->IsVanilla() && false; } }), + Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, { [] { return randoCtx->GetDungeon(FOREST_TEMPLE)->IsMQ() && false; } }), Entrance(RR_FOREST_TEMPLE_BOSS_ROOM, { [] { return true; } }), }); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp index 63365b178..3538b567f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp @@ -1,11 +1,11 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" -#include "../trial.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" +#include "../../trial.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_GanonsCastle() { /*-------------------------- @@ -13,15 +13,15 @@ void AreaTable_Init_GanonsCastle() { ---------------------------*/ areaTable[RR_GANONS_CASTLE_ENTRYWAY] = Area("Ganon's Castle Entryway", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_GANONS_CASTLE_LOBBY, {[]{return Dungeon::GanonsCastle.IsVanilla();}}), - Entrance(RR_GANONS_CASTLE_MQ_LOBBY, {[]{return Dungeon::GanonsCastle.IsMQ();}}), + Entrance(RR_GANONS_CASTLE_LOBBY, {[]{return randoCtx->GetDungeon(GANONS_CASTLE)->IsVanilla();}}), + Entrance(RR_GANONS_CASTLE_MQ_LOBBY, {[]{return randoCtx->GetDungeon(GANONS_CASTLE)->IsMQ();}}), Entrance(RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::GanonsCastle.IsVanilla()) { + if (randoCtx->GetDungeon(GANONS_CASTLE)->IsVanilla()) { areaTable[RR_GANONS_CASTLE_LOBBY] = Area("Ganon's Castle Lobby", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_SHEIK_HINT_GC, {[]{return true;}}), @@ -34,13 +34,13 @@ void AreaTable_Init_GanonsCastle() { Entrance(RR_GANONS_CASTLE_SHADOW_TRIAL, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL, {[]{return CanUse(RG_GOLDEN_GAUNTLETS);}}), - Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || Trial::ForestTrial.IsSkipped()) && - (FireTrialClear || Trial::FireTrial.IsSkipped()) && - (WaterTrialClear || Trial::WaterTrial.IsSkipped()) && - (ShadowTrialClear || Trial::ShadowTrial.IsSkipped()) && - (SpiritTrialClear || Trial::SpiritTrial.IsSkipped()) && - (LightTrialClear || Trial::LightTrial.IsSkipped());}}), - Entrance(RR_GANONS_CASTLE_DEKU_SCRUBS, {[]{return LogicLensCastle || CanUse(RG_LENS_OF_TRUTH);}}), + Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || randoCtx->GetTrial(Rando::FOREST_TRIAL)->IsSkipped()) && + (FireTrialClear || randoCtx->GetTrial(Rando::FIRE_TRIAL)->IsSkipped()) && + (WaterTrialClear || randoCtx->GetTrial(Rando::WATER_TRIAL)->IsSkipped()) && + (ShadowTrialClear || randoCtx->GetTrial(Rando::SHADOW_TRIAL)->IsSkipped()) && + (SpiritTrialClear || randoCtx->GetTrial(Rando::SPIRIT_TRIAL)->IsSkipped()) && + (LightTrialClear || randoCtx->GetTrial(Rando::LIGHT_TRIAL)->IsSkipped());}}), + Entrance(RR_GANONS_CASTLE_DEKU_SCRUBS, {[]{return randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH);}}), }); areaTable[RR_GANONS_CASTLE_DEKU_SCRUBS] = Area("Ganon's Castle Deku Scrubs", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -80,7 +80,7 @@ void AreaTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL] = Area("Ganon's Castle Shadow Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&ShadowTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && CanUse(RG_MEGATON_HAMMER) && ((FireArrows && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH))) || (CanUse(RG_LONGSHOT) && (CanUse(RG_HOVER_BOOTS) || (DinsFire && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH))))));}}), + EventAccess(&ShadowTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && CanUse(RG_MEGATON_HAMMER) && ((FireArrows && (randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH))) || (CanUse(RG_LONGSHOT) && (CanUse(RG_HOVER_BOOTS) || (DinsFire && (randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH))))));}}), }, { //Locations LocationAccess(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, {[]{return CanUse(RG_FIRE_ARROWS) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || CanPlay(SongOfTime) || IsChild;}}), @@ -89,17 +89,17 @@ void AreaTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL] = Area("Ganon's Castle Spirit Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&NutPot, {[]{return NutPot || (((LogicSpiritTrialHookshot && CanJumpslash) || CanUse(RG_HOOKSHOT)) && HasBombchus && CanUse(RG_FAIRY_BOW) && (CanUse(RG_MIRROR_SHIELD) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS))));}}), - EventAccess(&SpiritTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_MIRROR_SHIELD) || SunlightArrows) && HasBombchus && ((LogicSpiritTrialHookshot && CanJumpslash) || CanUse(RG_HOOKSHOT));}}), + EventAccess(&NutPot, {[]{return NutPot || (((randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && CanJumpslash) || CanUse(RG_HOOKSHOT)) && HasBombchus && CanUse(RG_FAIRY_BOW) && (CanUse(RG_MIRROR_SHIELD) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))));}}), + EventAccess(&SpiritTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_MIRROR_SHIELD) || randoCtx->GetOption(RSK_SUNLIGHT_ARROWS)) && HasBombchus && ((randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && CanJumpslash) || CanUse(RG_HOOKSHOT));}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, {[]{return (LogicSpiritTrialHookshot || CanUse(RG_HOOKSHOT)) && CanJumpslash;}}), - LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return (LogicSpiritTrialHookshot || CanUse(RG_HOOKSHOT)) && HasBombchus && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH));}}), + LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, {[]{return (randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || CanUse(RG_HOOKSHOT)) && CanJumpslash;}}), + LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || CanUse(RG_HOOKSHOT)) && HasBombchus && (randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH));}}), }, {}); areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL] = Area("Ganon's Castle Light Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&LightTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && CanUse(RG_HOOKSHOT) && SmallKeys(RR_GANONS_CASTLE, 2) && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH));}}), + EventAccess(&LightTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && CanUse(RG_HOOKSHOT) && SmallKeys(RR_GANONS_CASTLE, 2) && (randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH));}}), }, { //Locations LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, {[]{return true;}}), @@ -108,7 +108,7 @@ void AreaTable_Init_GanonsCastle() { LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, {[]{return true;}}), LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, {[]{return true;}}), LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, {[]{return true;}}), - LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, {[]{return LogicLensCastle || CanUse(RG_LENS_OF_TRUTH);}}), + LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH);}}), LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(RR_GANONS_CASTLE, 1);}}), }, {}); } @@ -123,7 +123,7 @@ void AreaTable_Init_GanonsCastle() { /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::GanonsCastle.IsMQ()) { + if (randoCtx->GetDungeon(GANONS_CASTLE)->IsMQ()) { areaTable[RR_GANONS_CASTLE_MQ_LOBBY] = Area("Ganon's Castle MQ Lobby", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_SHEIK_HINT_MQ_GC, {[]{return true;}}), @@ -136,13 +136,13 @@ void AreaTable_Init_GanonsCastle() { Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL, {[]{return true;}}), Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL, {[]{return CanUse(RG_GOLDEN_GAUNTLETS);}}), - Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || Trial::ForestTrial.IsSkipped()) && - (FireTrialClear || Trial::FireTrial.IsSkipped()) && - (WaterTrialClear || Trial::WaterTrial.IsSkipped()) && - (ShadowTrialClear || Trial::ShadowTrial.IsSkipped()) && - (SpiritTrialClear || Trial::SpiritTrial.IsSkipped()) && - (LightTrialClear || Trial::LightTrial.IsSkipped());}}), - Entrance(RR_GANONS_CASTLE_MQ_DEKU_SCRUBS, {[]{return LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH);}}), + Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || randoCtx->GetTrial(Rando::FOREST_TRIAL)->IsSkipped()) && + (FireTrialClear || randoCtx->GetTrial(Rando::FIRE_TRIAL)->IsSkipped()) && + (WaterTrialClear || randoCtx->GetTrial(Rando::WATER_TRIAL)->IsSkipped()) && + (ShadowTrialClear || randoCtx->GetTrial(Rando::SHADOW_TRIAL)->IsSkipped()) && + (SpiritTrialClear || randoCtx->GetTrial(Rando::SPIRIT_TRIAL)->IsSkipped()) && + (LightTrialClear || randoCtx->GetTrial(Rando::LIGHT_TRIAL)->IsSkipped());}}), + Entrance(RR_GANONS_CASTLE_MQ_DEKU_SCRUBS, {[]{return randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH);}}), }); areaTable[RR_GANONS_CASTLE_MQ_DEKU_SCRUBS] = Area("Ganon's Castle MQ Deku Scrubs", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { @@ -169,7 +169,7 @@ void AreaTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL] = Area("Ganon's Castle MQ Fire Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&FireTrialClear, {[]{return CanUse(RG_GORON_TUNIC) && CanUse(RG_GOLDEN_GAUNTLETS) && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_LONGSHOT) || HoverBoots || (LogicFireTrialMQ && CanUse(RG_HOOKSHOT)));}}), + EventAccess(&FireTrialClear, {[]{return CanUse(RG_GORON_TUNIC) && CanUse(RG_GOLDEN_GAUNTLETS) && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_LONGSHOT) || HoverBoots || (randoCtx->GetTrickOption(RT_GANON_MQ_FIRE_TRIAL) && CanUse(RG_HOOKSHOT)));}}), //Trick: CanUse(RG_GORON_TUNIC) && CanUse(RG_GOLDEN_GAUNTLETS) && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_LONGSHOT) || HoverBoots || (LogicFireTrialMQ && CanUse(RG_HOOKSHOT))) }, {}, {}); @@ -184,32 +184,32 @@ void AreaTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL] = Area("Ganon's Castle MQ Shadow Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&ShadowTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)));}}), + EventAccess(&ShadowTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || randoCtx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL))));}}), //Trick: IsAdult && CanUse(RG_LIGHT_ARROWS) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ))) }, { //Locations - LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, {[]{return IsAdult && ((Bow && (CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS))) || (CanUse(RG_HOVER_BOOTS) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HasExplosives || GoronBracelet || CanUse(RG_DINS_FIRE))));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, {[]{return IsAdult && Bow && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)));}}), + LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, {[]{return IsAdult && ((Bow && (CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS))) || (CanUse(RG_HOVER_BOOTS) && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH)) && (HasExplosives || GoronBracelet || CanUse(RG_DINS_FIRE))));}}), + LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, {[]{return IsAdult && Bow && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || randoCtx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL))));}}), //Trick: IsAdult && Bow && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ))) }, {}); areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL] = Area("Ganon's Castle MQ Spirit Castle", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&SpiritTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && Hammer && HasBombchus && ((FireArrows && MirrorShield) || SunlightArrows);}}), - EventAccess(&NutPot, {[]{return NutPot || (Hammer && HasBombchus && IsAdult && ((CanUse(RG_FIRE_ARROWS) && MirrorShield) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS))));}}), + EventAccess(&SpiritTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && Hammer && HasBombchus && ((FireArrows && MirrorShield) || randoCtx->GetOption(RSK_SUNLIGHT_ARROWS));}}), + EventAccess(&NutPot, {[]{return NutPot || (Hammer && HasBombchus && IsAdult && ((CanUse(RG_FIRE_ARROWS) && MirrorShield) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))));}}), }, { //Locations - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, {[]{return IsAdult && (Bow || LogicRustedSwitches) && Hammer;}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return IsAdult && (Bow || LogicRustedSwitches) && Hammer && HasBombchus && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}), - LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}), + LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, {[]{return IsAdult && (Bow || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && Hammer;}}), + LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return IsAdult && (Bow || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && Hammer && HasBombchus && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH));}}), + LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}), + LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}), + LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}), + LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}), }, {}); areaTable[RR_GANONS_CASTLE_MQ_LIGHT_TRIAL] = Area("Ganon's Castle MQ Light Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&LightTrialClear, {[]{return IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD)) && CanUse(RG_LIGHT_ARROWS) && SmallKeys(RR_GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (Hookshot || LogicLightTrialMQ);}}), + EventAccess(&LightTrialClear, {[]{return IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD)) && CanUse(RG_LIGHT_ARROWS) && SmallKeys(RR_GANONS_CASTLE, 3) && (randoCtx->GetTrickOption(RT_LENS_GANON_MQ) || CanUse(RG_LENS_OF_TRUTH)) && (Hookshot || randoCtx->GetTrickOption(RT_GANON_MQ_LIGHT_TRIAL));}}), //Trick: IsAdult && CanUse(RG_LIGHT_ARROWS) && SmallKeys(RR_GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (Hookshot || LogicLightTrialMQ) }, { //Locations diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp index 7316baf3c..2412dbfce 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_GerudoTrainingGrounds() { /*-------------------------- @@ -12,15 +12,15 @@ void AreaTable_Init_GerudoTrainingGrounds() { ---------------------------*/ areaTable[RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY] = Area("Gerudo Training Grounds Entryway", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUNDS_LOBBY, {[]{return Dungeon::GerudoTrainingGrounds.IsVanilla();}}), - Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY, {[]{return Dungeon::GerudoTrainingGrounds.IsMQ();}}), + Entrance(RR_GERUDO_TRAINING_GROUNDS_LOBBY, {[]{return randoCtx->GetDungeon(GERUDO_TRAINING_GROUNDS)->IsVanilla();}}), + Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY, {[]{return randoCtx->GetDungeon(GERUDO_TRAINING_GROUNDS)->IsMQ();}}), Entrance(RR_GERUDO_FORTRESS, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::GerudoTrainingGrounds.IsVanilla()) { + if (randoCtx->GetDungeon(GERUDO_TRAINING_GROUNDS)->IsVanilla()) { areaTable[RR_GERUDO_TRAINING_GROUNDS_LOBBY] = Area("Gerudo Training Grounds Lobby", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, {[]{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT);}}), @@ -30,14 +30,14 @@ void AreaTable_Init_GerudoTrainingGrounds() { }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return true;}}), - Entrance(RR_GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (CanUse(RG_HOOKSHOT) || LogicGtgWithoutHookshot);}}), + Entrance(RR_GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (CanUse(RG_HOOKSHOT) || randoCtx->GetTrickOption(RT_GTG_WITHOUT_HOOKSHOT));}}), Entrance(RR_GERUDO_TRAINING_GROUNDS_LAVA_ROOM, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_LOBBY, []{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && HasExplosives;});}}), Entrance(RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE, {[]{return true;}}), }); areaTable[RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE] = Area("Gerudo Training Grounds Central Maze", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 3) && (LogicLensGtg || CanUse(RG_LENS_OF_TRUTH));}}), + LocationAccess(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 3) && (randoCtx->GetTrickOption(RT_LENS_GTG) || CanUse(RG_LENS_OF_TRUTH));}}), LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 4);}}), LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 6);}}), LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 7);}}), @@ -70,7 +70,7 @@ void AreaTable_Init_GerudoTrainingGrounds() { areaTable[RR_GERUDO_TRAINING_GROUNDS_HAMMER_ROOM] = Area("Gerudo Training Grounds Hammer Room", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, {[]{return CanAdultAttack || CanChildAttack;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, {[]{return CanUse(RG_MEGATON_HAMMER) || (CanTakeDamage && LogicFlamingChests);}}), + LocationAccess(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, {[]{return CanUse(RG_MEGATON_HAMMER) || (CanTakeDamage && randoCtx->GetTrickOption(RT_FLAMING_CHESTS));}}), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, {[]{return CanUse(RG_MEGATON_HAMMER) && CanUse(RG_FAIRY_BOW);}}), @@ -98,8 +98,8 @@ void AreaTable_Init_GerudoTrainingGrounds() { LocationAccess(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, {[]{return CanJumpslash;}}), }, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER, {[]{return (LogicLensGtg || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOOKSHOT) || (LogicGtgFakeWall && CanUse(RG_HOVER_BOOTS)));}}), - Entrance(RR_GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM, {[]{return (LogicLensGtg || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOOKSHOT) || (LogicGtgFakeWall && CanUse(RG_HOVER_BOOTS))) && CanUse(RG_SILVER_GAUNTLETS);}}), + Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER, {[]{return (randoCtx->GetTrickOption(RT_LENS_GTG) || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_GTG_FAKE_WALL) && CanUse(RG_HOVER_BOOTS)));}}), + Entrance(RR_GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM, {[]{return (randoCtx->GetTrickOption(RT_LENS_GTG) || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_GTG_FAKE_WALL) && CanUse(RG_HOVER_BOOTS))) && CanUse(RG_SILVER_GAUNTLETS);}}), }); areaTable[RR_GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM] = Area("Gerudo Training Grounds Like Like Room", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { @@ -114,12 +114,12 @@ void AreaTable_Init_GerudoTrainingGrounds() { /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::GerudoTrainingGrounds.IsMQ()) { + if (randoCtx->GetDungeon(GERUDO_TRAINING_GROUNDS)->IsMQ()) { areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY] = Area("Gerudo Training Grounds MQ Lobby", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, {[]{return true;}}), LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, {[]{return true;}}), - LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, {[]{return LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH);}}), + LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_GTG_MQ) || CanUse(RG_LENS_OF_TRUTH);}}), LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, {[]{return true;}}), LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, {[]{return true;}}), LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 1);}}), @@ -151,7 +151,7 @@ void AreaTable_Init_GerudoTrainingGrounds() { LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || HasExplosives;}}), }, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, {[]{return (IsAdult && CanUse(RG_LONGSHOT)) || LogicGtgMQWithoutHookshot || (LogicGtgMQWithHookshot && IsAdult && CanUse(RG_HOOKSHOT));}}), + Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, {[]{return (IsAdult && CanUse(RG_LONGSHOT)) || randoCtx->GetTrickOption(RT_GTG_MQ_WIHTOUT_HOOKSHOT) || (randoCtx->GetTrickOption(RT_GTG_MQ_WITH_HOOKSHOT) && IsAdult && CanUse(RG_HOOKSHOT));}}), //Trick: (IsAdult && CanUse(RG_LONGSHOT)) || LogicGtgMQWithoutHookshot || (LogicGtgMQWithHookshot && IsAdult && CanUse(RG_HOOKSHOT)) }); @@ -164,7 +164,7 @@ void AreaTable_Init_GerudoTrainingGrounds() { LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, {[]{return CanUse(RG_SILVER_GAUNTLETS) && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD));}}), }, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, {[]{return IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (LogicGtgFakeWall && IsAdult && CanUse(RG_HOVER_BOOTS)));}}), + Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, {[]{return IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (randoCtx->GetTrickOption(RT_LENS_GTG_MQ) || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_GTG_FAKE_WALL) && IsAdult && CanUse(RG_HOVER_BOOTS)));}}), //Trick: IsAdult && (LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (LogicGtgFakeWall && IsAdult && CanUse(RG_HOVER_BOOTS))) }); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp index 3ec4d52d7..568b7f028 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp @@ -1,9 +1,9 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" +#include "../../entrance.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_GerudoValley() { areaTable[RR_GERUDO_VALLEY] = Area("Gerudo Valley", "Gerudo Valley", RHT_GERUDO_VALLEY, DAY_NIGHT_CYCLE, { @@ -18,7 +18,7 @@ void AreaTable_Init_GerudoValley() { Entrance(RR_GV_UPPER_STREAM, {[]{return true;}}), Entrance(RR_GV_CRATE_LEDGE, {[]{return IsChild || CanUse(RG_LONGSHOT);}}), Entrance(RR_GV_GROTTO_LEDGE, {[]{return true;}}), - Entrance(RR_GV_FORTRESS_SIDE, {[]{return (IsAdult && (CanRideEpona || CanUse(RG_LONGSHOT) || GerudoFortress.Is(GERUDOFORTRESS_OPEN) || CarpenterRescue)) || (IsChild && CanUse(RG_HOOKSHOT));}}), + Entrance(RR_GV_FORTRESS_SIDE, {[]{return (IsAdult && (CanRideEpona || CanUse(RG_LONGSHOT) || randoCtx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_OPEN) || CarpenterRescue)) || (IsChild && CanUse(RG_HOOKSHOT));}}), }); areaTable[RR_GV_UPPER_STREAM] = Area("GV Upper Stream", "Gerudo Valley", RHT_GERUDO_VALLEY, DAY_NIGHT_CYCLE, { @@ -69,7 +69,7 @@ void AreaTable_Init_GerudoValley() { //Exits Entrance(RR_GERUDO_FORTRESS, {[]{return true;}}), Entrance(RR_GV_UPPER_STREAM, {[]{return true;}}), - Entrance(RR_GERUDO_VALLEY, {[]{return IsChild || CanRideEpona || CanUse(RG_LONGSHOT) || GerudoFortress.Is(GERUDOFORTRESS_OPEN) || CarpenterRescue;}}), + Entrance(RR_GERUDO_VALLEY, {[]{return IsChild || CanRideEpona || CanUse(RG_LONGSHOT) || randoCtx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_OPEN) || CarpenterRescue;}}), Entrance(RR_GV_CARPENTER_TENT, {[]{return IsAdult;}}), Entrance(RR_GV_STORMS_GROTTO, {[]{return IsAdult && CanOpenStormGrotto;}}), Entrance(RR_GV_CRATE_LEDGE, {[]{return false;}}), @@ -105,26 +105,26 @@ void AreaTable_Init_GerudoValley() { LocationAccess(RC_GF_HBA_1000_POINTS, {[]{return GerudoToken && CanRideEpona && Bow && AtDay;}}), LocationAccess(RC_GF_HBA_1500_POINTS, {[]{return GerudoToken && CanRideEpona && Bow && AtDay;}}), LocationAccess(RC_GF_NORTH_F1_CARPENTER, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}), - LocationAccess(RC_GF_NORTH_F2_CARPENTER, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || LogicGerudoKitchen);}}), + LocationAccess(RC_GF_NORTH_F2_CARPENTER, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || randoCtx->GetTrickOption(RT_GF_KITCHEN));}}), LocationAccess(RC_GF_SOUTH_F1_CARPENTER, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}), LocationAccess(RC_GF_SOUTH_F2_CARPENTER, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}), LocationAccess(RC_GF_GERUDO_MEMBERSHIP_CARD, {[]{return CanFinishGerudoFortress;}}), LocationAccess(RC_GF_GS_ARCHERY_RANGE, {[]{return IsAdult && HookshotOrBoomerang && GerudoToken && AtNight && CanGetNightTimeGS;}}), - LocationAccess(RC_GF_GS_TOP_FLOOR, {[]{return IsAdult && AtNight && (CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || LogicGerudoKitchen || LogicGFJump) && CanGetNightTimeGS;}}), + LocationAccess(RC_GF_GS_TOP_FLOOR, {[]{return IsAdult && AtNight && (CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || randoCtx->GetTrickOption(RT_GF_KITCHEN) || randoCtx->GetTrickOption(RT_GF_JUMP)) && CanGetNightTimeGS;}}), }, { //Exits Entrance(RR_GV_FORTRESS_SIDE, {[]{return true;}}), Entrance(RR_GF_OUTSIDE_GATE, {[]{return GF_GateOpen;}}), - Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return GtG_GateOpen && (IsAdult || ShuffleDungeonEntrances);}}), + Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return GtG_GateOpen && (IsAdult || randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}}), Entrance(RR_GF_STORMS_GROTTO, {[]{return IsAdult && CanOpenStormGrotto;}}), }); areaTable[RR_GF_OUTSIDE_GATE] = Area("GF Outside Gate", "Gerudo Fortress", RHT_GERUDO_FORTRESS, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&GF_GateOpen, {[]{return IsAdult && GerudoToken && (ShuffleGerudoToken || ShuffleOverworldEntrances /*|| ShuffleSpecialIndoorEntrances*/);}}), + EventAccess(&GF_GateOpen, {[]{return IsAdult && GerudoToken && (randoCtx->GetOption(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD) || randoCtx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) /*|| ShuffleSpecialIndoorEntrances*/);}}), }, {}, { //Exits - Entrance(RR_GERUDO_FORTRESS, {[]{return (IsAdult && (Hookshot || !ShuffleOverworldEntrances)) || GF_GateOpen;}}), + Entrance(RR_GERUDO_FORTRESS, {[]{return (IsAdult && (Hookshot || !randoCtx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES))) || GF_GateOpen;}}), Entrance(RR_WASTELAND_NEAR_FORTRESS, {[]{return true;}}), }); @@ -139,7 +139,7 @@ void AreaTable_Init_GerudoValley() { areaTable[RR_WASTELAND_NEAR_FORTRESS] = Area("Wasteland Near Fortress", "Haunted Wasteland", RHT_HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_GF_OUTSIDE_GATE, {[]{return true;}}), - Entrance(RR_HAUNTED_WASTELAND, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT) || LogicWastelandCrossing;}}), + Entrance(RR_HAUNTED_WASTELAND, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT) || randoCtx->GetTrickOption(RT_HW_CROSSING);}}), }); areaTable[RR_HAUNTED_WASTELAND] = Area("Haunted Wasteland", "Haunted Wasteland", RHT_HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, { @@ -153,14 +153,14 @@ void AreaTable_Init_GerudoValley() { LocationAccess(RC_WASTELAND_GS, {[]{return HookshotOrBoomerang;}}), }, { //Exits - Entrance(RR_WASTELAND_NEAR_COLOSSUS, {[]{return LogicLensWasteland || CanUse(RG_LENS_OF_TRUTH);}}), - Entrance(RR_WASTELAND_NEAR_FORTRESS, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT) || LogicWastelandCrossing;}}), + Entrance(RR_WASTELAND_NEAR_COLOSSUS, {[]{return randoCtx->GetTrickOption(RT_LENS_HW) || CanUse(RG_LENS_OF_TRUTH);}}), + Entrance(RR_WASTELAND_NEAR_FORTRESS, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT) || randoCtx->GetTrickOption(RT_HW_CROSSING);}}), }); areaTable[RR_WASTELAND_NEAR_COLOSSUS] = Area("Wasteland Near Colossus", "Haunted Wasteland", RHT_HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}), - Entrance(RR_HAUNTED_WASTELAND, {[]{return LogicReverseWasteland || false;}}), + Entrance(RR_HAUNTED_WASTELAND, {[]{return randoCtx->GetTrickOption(RT_HW_REVERSE) || false;}}), }); areaTable[RR_DESERT_COLOSSUS] = Area("Desert Colossus", "Desert Colossus", RHT_DESERT_COLOSSUS, DAY_NIGHT_CYCLE, { @@ -172,7 +172,7 @@ void AreaTable_Init_GerudoValley() { LocationAccess(RC_COLOSSUS_FREESTANDING_POH, {[]{return IsAdult && CanPlantBean(RR_DESERT_COLOSSUS);}}), LocationAccess(RC_COLOSSUS_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}), LocationAccess(RC_COLOSSUS_GS_TREE, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}), - LocationAccess(RC_COLOSSUS_GS_HILL, {[]{return IsAdult && AtNight && ((CanPlantBean(RR_DESERT_COLOSSUS) && CanAdultAttack) || CanUse(RG_LONGSHOT) || (LogicColossusGS && CanUse(RG_HOOKSHOT))) && CanGetNightTimeGS;}}), + LocationAccess(RC_COLOSSUS_GS_HILL, {[]{return IsAdult && AtNight && ((CanPlantBean(RR_DESERT_COLOSSUS) && CanAdultAttack) || CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_COLOSSUS_GS) && CanUse(RG_HOOKSHOT))) && CanGetNightTimeGS;}}), LocationAccess(RC_COLOSSUS_GOSSIP_STONE, {[]{return true;}}), }, { //Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp index 1e4e15807..cf7438e5e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp @@ -1,9 +1,9 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" +#include "../../entrance.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_HyruleField() { areaTable[RR_HYRULE_FIELD] = Area("Hyrule Field", "Hyrule Field", RHT_HYRULE_FIELD, DAY_NIGHT_CYCLE, { @@ -115,7 +115,7 @@ void AreaTable_Init_HyruleField() { LocationAccess(RC_LH_SUN, {[]{return IsAdult && WaterTempleClear && CanUse(RG_FAIRY_BOW);}}), LocationAccess(RC_LH_FREESTANDING_POH, {[]{return IsAdult && (CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA));}}), LocationAccess(RC_LH_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}), - LocationAccess(RC_LH_GS_LAB_WALL, {[]{return IsChild && (HookshotOrBoomerang || (LogicLabWallGS && CanJumpslash)) && AtNight && CanGetNightTimeGS;}}), + LocationAccess(RC_LH_GS_LAB_WALL, {[]{return IsChild && (HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_LH_LAB_WALL_GS) && CanJumpslash)) && AtNight && CanGetNightTimeGS;}}), LocationAccess(RC_LH_GS_SMALL_ISLAND, {[]{return IsChild && CanChildAttack && AtNight && CanGetNightTimeGS;}}), LocationAccess(RC_LH_GS_TREE, {[]{return IsAdult && CanUse(RG_LONGSHOT) && AtNight && CanGetNightTimeGS;}}), LocationAccess(RC_LH_LAB_GOSSIP_STONE, {[]{return true;}}), @@ -128,7 +128,7 @@ void AreaTable_Init_HyruleField() { Entrance(RR_LH_OWL_FLIGHT, {[]{return IsChild;}}), Entrance(RR_LH_FISHING_ISLAND, {[]{return IsChild || CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA) || WaterTempleClear;}}), Entrance(RR_LH_LAB, {[]{return true;}}), - Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_HOOKSHOT) && ((CanUse(RG_IRON_BOOTS) || (LogicWaterHookshotEntry && ProgressiveScale >= 2)) || (IsAdult && CanUse(RG_LONGSHOT) && ProgressiveScale >= 2));}}), + Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_HOOKSHOT) && ((CanUse(RG_IRON_BOOTS) || (randoCtx->GetTrickOption(RT_LH_WATER_HOOKSHOT) && ProgressiveScale >= 2)) || (IsAdult && CanUse(RG_LONGSHOT) && ProgressiveScale >= 2));}}), Entrance(RR_LH_GROTTO, {[]{return true;}}), }); @@ -148,7 +148,7 @@ void AreaTable_Init_HyruleField() { EventAccess(&EyedropsAccess, {[]{return EyedropsAccess || (IsAdult && (EyeballFrogAccess || (EyeballFrog && DisableTradeRevert)));}}), }, { //Locations - LocationAccess(RC_LH_LAB_DIVE, {[]{return ProgressiveScale >= 2 || (LogicLabDiving && CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT));}}), + LocationAccess(RC_LH_LAB_DIVE, {[]{return ProgressiveScale >= 2 || (randoCtx->GetTrickOption(RT_LH_LAB_DIVING) && CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT));}}), LocationAccess(RC_LH_TRADE_FROG, {[]{return IsAdult && EyeballFrog;}}), LocationAccess(RC_LH_GS_LAB_CRATE, {[]{return CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT);}}), }, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp index 4386b97ae..3cbbd94e3 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_IceCavern() { /*-------------------------- @@ -12,15 +12,15 @@ void AreaTable_Init_IceCavern() { ---------------------------*/ areaTable[RR_ICE_CAVERN_ENTRYWAY] = Area("Ice Cavern Entryway", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_ICE_CAVERN_BEGINNING, {[]{return Dungeon::IceCavern.IsVanilla();}}), - Entrance(RR_ICE_CAVERN_MQ_BEGINNING, {[]{return Dungeon::IceCavern.IsMQ() && CanUseProjectile;}}), + Entrance(RR_ICE_CAVERN_BEGINNING, {[]{return randoCtx->GetDungeon(ICE_CAVERN)->IsVanilla();}}), + Entrance(RR_ICE_CAVERN_MQ_BEGINNING, {[]{return randoCtx->GetDungeon(ICE_CAVERN)->IsMQ() && CanUseProjectile;}}), Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::IceCavern.IsVanilla()) { + if (randoCtx->GetDungeon(ICE_CAVERN)->IsVanilla()) { areaTable[RR_ICE_CAVERN_BEGINNING] = Area("Ice Cavern Beginning", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_ICE_CAVERN_ENTRYWAY, {[]{return true;}}), @@ -39,14 +39,14 @@ void AreaTable_Init_IceCavern() { LocationAccess(RC_ICE_CAVERN_FREESTANDING_POH, {[]{return BlueFire;}}), LocationAccess(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, {[]{return HookshotOrBoomerang;}}), LocationAccess(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, {[]{return BlueFire && HookshotOrBoomerang;}}), - LocationAccess(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, {[]{return BlueFire && (HookshotOrBoomerang || (LogicIceBlockGS && IsAdult && CanUse(RG_HOVER_BOOTS)));}}), + LocationAccess(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, {[]{return BlueFire && (HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_ICE_BLOCK_GS) && IsAdult && CanUse(RG_HOVER_BOOTS)));}}), }, {}); } /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::IceCavern.IsMQ()) { + if (randoCtx->GetDungeon(ICE_CAVERN)->IsMQ()) { areaTable[RR_ICE_CAVERN_MQ_BEGINNING] = Area("Ice Cavern MQ Beginning", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&FairyPot, {[]{return true;}}), @@ -71,7 +71,7 @@ void AreaTable_Init_IceCavern() { LocationAccess(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, {[]{return IsAdult && (CanJumpslash || CanUse(RG_MEGATON_HAMMER));}}), LocationAccess(RC_SHEIK_IN_ICE_CAVERN, {[]{return IsAdult && (CanJumpslash || CanUse(RG_MEGATON_HAMMER));}}), LocationAccess(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, {[]{return CanAdultAttack || CanChildAttack;}}), - LocationAccess(RC_ICE_CAVERN_MQ_GS_SCARECROW, {[]{return CanUse(RG_SCARECROW) || (HoverBoots && CanUse(RG_LONGSHOT)) || (LogicIceMQScarecrow && IsAdult);}}), + LocationAccess(RC_ICE_CAVERN_MQ_GS_SCARECROW, {[]{return CanUse(RG_SCARECROW) || (HoverBoots && CanUse(RG_LONGSHOT)) || (randoCtx->GetTrickOption(RT_ICE_MQ_SCARECROW) && IsAdult);}}), //Tricks: (CanUse(RG_SCARECROW) || (HoverBoots && CanUse(RG_LONGSHOT)) || LogicIceMQScarecrow) && IsAdult }, {}); @@ -79,7 +79,7 @@ void AreaTable_Init_IceCavern() { //Locations LocationAccess(RC_ICE_CAVERN_MQ_COMPASS_CHEST, {[]{return true;}}), LocationAccess(RC_ICE_CAVERN_MQ_FREESTANDING_POH, {[]{return HasExplosives;}}), - LocationAccess(RC_ICE_CAVERN_MQ_GS_RED_ICE, {[]{return CanPlay(SongOfTime) || LogicIceMQRedIceGS;}}), + LocationAccess(RC_ICE_CAVERN_MQ_GS_RED_ICE, {[]{return CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_ICE_MQ_RED_ICE_GS);}}), //Trick: CanPlay(SongOfTime) || LogicIceMQRedIceGS }, {}); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp index 2ca264328..4ddcbf58f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_JabuJabusBelly() { /*-------------------------- @@ -12,15 +12,15 @@ void AreaTable_Init_JabuJabusBelly() { ---------------------------*/ areaTable[RR_JABU_JABUS_BELLY_ENTRYWAY] = Area("Jabu Jabus Belly Entryway", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_JABU_JABUS_BELLY_BEGINNING, {[]{return Dungeon::JabuJabusBelly.IsVanilla();}}), - Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return Dungeon::JabuJabusBelly.IsMQ();}}), + Entrance(RR_JABU_JABUS_BELLY_BEGINNING, {[]{return randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsVanilla();}}), + Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsMQ();}}), Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::JabuJabusBelly.IsVanilla()) { + if (randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsVanilla()) { areaTable[RR_JABU_JABUS_BELLY_BEGINNING] = Area("Jabu Jabus Belly Beginning", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}), @@ -32,7 +32,7 @@ void AreaTable_Init_JabuJabusBelly() { Entrance(RR_JABU_JABUS_BELLY_BEGINNING, {[]{return true;}}), Entrance(RR_JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}), Entrance(RR_JABU_JABUS_BELLY_LIFT_LOWER, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, {[]{return HasAccessTo(RR_JABU_JABUS_BELLY_LIFT_UPPER) || (LogicJabuBossHover && IsAdult && CanUse(RG_HOVER_BOOTS));}}), + Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, {[]{return HasAccessTo(RR_JABU_JABUS_BELLY_LIFT_UPPER) || (randoCtx->GetTrickOption(RT_JABU_BOSS_HOVER) && IsAdult && CanUse(RG_HOVER_BOOTS));}}), }); areaTable[RR_JABU_JABUS_BELLY_MAIN_UPPER] = Area("Jabu Jabus Belly Main Upper", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, { @@ -76,7 +76,7 @@ void AreaTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_LIFT_LOWER] = Area("Jabu Jabus Belly Lift Lower", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_JABU_JABUS_BELLY_DEKU_SCRUB, {[]{return (IsChild || CanDive || LogicJabuAlcoveJumpDive || CanUse(RG_IRON_BOOTS)) && CanStunDeku;}}), + LocationAccess(RC_JABU_JABUS_BELLY_DEKU_SCRUB, {[]{return (IsChild || CanDive || randoCtx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE) || CanUse(RG_IRON_BOOTS)) && CanStunDeku;}}), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_SHABOMB_CORRIDOR, {[]{return true;}}), @@ -154,14 +154,14 @@ void AreaTable_Init_JabuJabusBelly() { }, { //Exits Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return CanUse(RG_BOOMERANG) || (LogicJabuNearBossRanged && ((IsAdult && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW))) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT)))) || (LogicJabuNearBossExplosives && (HasBombchus || (IsAdult && CanUse(RG_HOVER_BOOTS) && Bombs)));}}), + Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return CanUse(RG_BOOMERANG) || (randoCtx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && ((IsAdult && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW))) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT)))) || (randoCtx->GetTrickOption(RT_JABU_NEAR_BOSS_EXPLOSIVES) && (HasBombchus || (IsAdult && CanUse(RG_HOVER_BOOTS) && Bombs)));}}), }); } /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::JabuJabusBelly.IsMQ()) { + if (randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsMQ()) { areaTable[RR_JABU_JABUS_BELLY_MQ_BEGINNING] = Area("Jabu Jabus Belly MQ Beginning", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&NutPot, {[]{return true;}}), @@ -184,7 +184,7 @@ void AreaTable_Init_JabuJabusBelly() { LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return true;}}), LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, {[]{return true;}}), LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, {[]{return true;}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(RG_BOOMERANG));}}), + LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_JABU_MQ_SOT_GS) && IsChild && CanUse(RG_BOOMERANG));}}), //Trick: CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(RG_BOOMERANG)) }, { //Exits @@ -196,7 +196,7 @@ void AreaTable_Init_JabuJabusBelly() { //Locations LocationAccess(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, {[]{return true;}}), LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, {[]{return Sticks || CanUse(RG_DINS_FIRE);}}), - LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, {[]{return (LogicLensJabuMQ || CanUse(RG_LENS_OF_TRUTH)) || Here(RR_JABU_JABUS_BELLY_MQ_MAIN, []{return IsAdult && CanUse(RG_HOVER_BOOTS) && CanUse(RG_HOOKSHOT);});}}), + LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, {[]{return (randoCtx->GetTrickOption(RT_LENS_JABU_MQ) || CanUse(RG_LENS_OF_TRUTH)) || Here(RR_JABU_JABUS_BELLY_MQ_MAIN, []{return IsAdult && CanUse(RG_HOVER_BOOTS) && CanUse(RG_HOOKSHOT);});}}), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}), @@ -225,8 +225,8 @@ void AreaTable_Init_JabuJabusBelly() { Area("Jabu Jabus Belly Boss Entryway", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, { [] { return Dungeon::JabuJabusBelly.IsVanilla(); } }), - Entrance(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA, { [] { return Dungeon::JabuJabusBelly.IsMQ(); } }), + Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, { [] { return randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsVanilla(); } }), + Entrance(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA, { [] { return randoCtx->GetDungeon(JABU_JABUS_BELLY)->IsMQ(); } }), Entrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, { [] { return true; } }), }); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp index 786bd19cc..47176d0fd 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp @@ -1,16 +1,16 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" +#include "../../entrance.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_Kakariko() { areaTable[RR_KAKARIKO_VILLAGE] = Area("Kakariko Village", "Kakariko Village", RHT_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&CojiroAccess, {[]{return CojiroAccess || (IsAdult && WakeUpAdultTalon);}}), EventAccess(&BugRock, {[]{return true;}}), - EventAccess(&KakarikoVillageGateOpen, {[]{return KakarikoVillageGateOpen || (IsChild && (ZeldasLetter || OpenKakariko.Is(OPENKAKARIKO_OPEN)));}}), + EventAccess(&KakarikoVillageGateOpen, {[]{return KakarikoVillageGateOpen || (IsChild && (ZeldasLetter || randoCtx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN)));}}), }, { //Locations LocationAccess(RC_SHEIK_IN_KAKARIKO, {[]{return IsAdult && ForestMedallion && FireMedallion && WaterMedallion;}}), @@ -21,7 +21,7 @@ void AreaTable_Init_Kakariko() { LocationAccess(RC_KAK_GS_SKULLTULA_HOUSE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}), LocationAccess(RC_KAK_GS_GUARDS_HOUSE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}), LocationAccess(RC_KAK_GS_TREE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}), - LocationAccess(RC_KAK_GS_WATCHTOWER, {[]{return IsChild && (Slingshot || HasBombchus || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT) || (LogicKakarikoTowerGS && CanJumpslash)) && AtNight && CanGetNightTimeGS;}}), + LocationAccess(RC_KAK_GS_WATCHTOWER, {[]{return IsChild && (Slingshot || HasBombchus || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_KAK_TOWER_GS) && CanJumpslash)) && AtNight && CanGetNightTimeGS;}}), }, { //Exits Entrance(RR_HYRULE_FIELD, {[]{return true;}}), @@ -31,12 +31,12 @@ void AreaTable_Init_Kakariko() { Entrance(RR_KAK_WINDMILL, {[]{return true;}}), Entrance(RR_KAK_BAZAAR, {[]{return IsAdult && AtDay;}}), Entrance(RR_KAK_SHOOTING_GALLERY, {[]{return IsAdult && AtDay;}}), - Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return DrainWell && (IsChild || ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF));}}), + Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return DrainWell && (IsChild || randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF));}}), Entrance(RR_KAK_POTION_SHOP_FRONT, {[]{return AtDay || IsChild;}}), Entrance(RR_KAK_REDEAD_GROTTO, {[]{return CanOpenBombGrotto;}}), - Entrance(RR_KAK_IMPAS_LEDGE, {[]{return (IsChild && AtDay) || CanUse(RG_HOOKSHOT) || (IsAdult && LogicVisibleCollision);}}), - Entrance(RR_KAK_ROOFTOP, {[]{return CanUse(RG_HOOKSHOT) || (LogicManOnRoof && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)));}}), - Entrance(RR_KAK_IMPAS_ROOFTOP, {[]{return CanUse(RG_HOOKSHOT) || (LogicKakarikoRooftopGS && CanUse(RG_HOVER_BOOTS));}}), + Entrance(RR_KAK_IMPAS_LEDGE, {[]{return (IsChild && AtDay) || CanUse(RG_HOOKSHOT) || (IsAdult && randoCtx->GetTrickOption(RT_VISIBLE_COLLISION));}}), + Entrance(RR_KAK_ROOFTOP, {[]{return CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_KAK_MAN_ON_ROOF) && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)));}}), + Entrance(RR_KAK_IMPAS_ROOFTOP, {[]{return CanUse(RG_HOOKSHOT) || (randoCtx->GetTrickOption(RT_KAK_ROOFTOP_GS) && CanUse(RG_HOVER_BOOTS));}}), Entrance(RR_THE_GRAVEYARD, {[]{return true;}}), Entrance(RR_KAK_BEHIND_GATE, {[]{return IsAdult || (KakarikoVillageGateOpen);}}), }); @@ -118,7 +118,7 @@ void AreaTable_Init_Kakariko() { EventAccess(&DrainWell, {[]{return DrainWell || (IsChild && CanPlay(SongOfStorms));}}), }, { //Locations - LocationAccess(RC_KAK_WINDMILL_FREESTANDING_POH, {[]{return CanUse(RG_BOOMERANG) || DampesWindmillAccess || (IsAdult && LogicAdultWindmillPoH) || (IsChild && CanJumpslash && LogicChildWindmillPoH);}}), + LocationAccess(RC_KAK_WINDMILL_FREESTANDING_POH, {[]{return CanUse(RG_BOOMERANG) || DampesWindmillAccess || (IsAdult && randoCtx->GetTrickOption(RT_KAK_ADULT_WINDMILL_POH)) || (IsChild && CanJumpslash && randoCtx->GetTrickOption(RT_KAK_CHILD_WINDMILL_POH));}}), //PoH as child not added to trick options yet (needs uncommenting in randomizer_tricks.cpp) LocationAccess(RC_SONG_FROM_WINDMILL, {[]{return IsAdult && Ocarina;}}), }, { @@ -212,7 +212,7 @@ void AreaTable_Init_Kakariko() { EventAccess(&BugRock, {[]{return true;}}), }, { //Locations - LocationAccess(RC_GRAVEYARD_FREESTANDING_POH, {[]{return (IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || CanUse(RG_LONGSHOT) || (LogicGraveyardPoH && CanUse(RG_BOOMERANG));}}), + LocationAccess(RC_GRAVEYARD_FREESTANDING_POH, {[]{return (IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_GY_POH) && CanUse(RG_BOOMERANG));}}), LocationAccess(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, {[]{return IsChild && AtNight;}}), //TODO: This needs to change LocationAccess(RC_GRAVEYARD_GS_WALL, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}), LocationAccess(RC_GRAVEYARD_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}), @@ -260,7 +260,7 @@ void AreaTable_Init_Kakariko() { }, { //Locations LocationAccess(RC_GRAVEYARD_HOOKSHOT_CHEST, {[]{return true;}}), - LocationAccess(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, {[]{return IsAdult || LogicChildDampeRacePoH;}}), + LocationAccess(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, {[]{return IsAdult || randoCtx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH);}}), }, { //Exits Entrance(RR_THE_GRAVEYARD, {[]{return true;}}), @@ -284,12 +284,12 @@ void AreaTable_Init_Kakariko() { }, { //Exits Entrance(RR_THE_GRAVEYARD, {[]{return true;}}), - Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_DINS_FIRE) || (LogicShadowFireArrowEntry && IsAdult && CanUse(RG_FIRE_ARROWS));}}), + Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_DINS_FIRE) || (randoCtx->GetTrickOption(RT_GY_SHADOW_FIRE_ARROWS) && IsAdult && CanUse(RG_FIRE_ARROWS));}}), }); areaTable[RR_KAK_BEHIND_GATE] = Area("Kak Behind Gate", "Kakariko Village", RHT_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_KAKARIKO_VILLAGE, {[]{return IsAdult || LogicVisibleCollision || KakarikoVillageGateOpen || OpenKakariko.Is(OPENKAKARIKO_OPEN);}}), + Entrance(RR_KAKARIKO_VILLAGE, {[]{return IsAdult || randoCtx->GetTrickOption(RT_VISIBLE_COLLISION) || KakarikoVillageGateOpen || randoCtx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN);}}), Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}), }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp index 833c8eebf..94699a271 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp @@ -1,9 +1,9 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" +#include "../../entrance.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_LostWoods() { areaTable[RR_KOKIRI_FOREST] = Area("Kokiri Forest", "Kokiri Forest", RHT_KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, { @@ -14,9 +14,9 @@ void AreaTable_Init_LostWoods() { }, { //Locations LocationAccess(RC_KF_KOKIRI_SWORD_CHEST, {[]{return IsChild;}}), - LocationAccess(RC_KF_GS_KNOW_IT_ALL_HOUSE, {[]{return IsChild && CanChildAttack && AtNight && (HasNightStart || CanLeaveForest || CanPlay(SunsSong)) && CanGetNightTimeGS;}}), + LocationAccess(RC_KF_GS_KNOW_IT_ALL_HOUSE, {[]{return IsChild && CanChildAttack && AtNight && (/*TODO: HasNightStart ||*/ CanLeaveForest || CanPlay(SunsSong)) && CanGetNightTimeGS;}}), LocationAccess(RC_KF_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}), - LocationAccess(RC_KF_GS_HOUSE_OF_TWINS, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || (LogicAdultKokiriGS && CanUse(RG_HOVER_BOOTS))) && CanGetNightTimeGS;}}), + LocationAccess(RC_KF_GS_HOUSE_OF_TWINS, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_KF_ADULT_GS) && CanUse(RG_HOVER_BOOTS))) && CanGetNightTimeGS;}}), LocationAccess(RC_KF_GOSSIP_STONE, {[]{return true;}}), }, { //Exits @@ -26,16 +26,16 @@ void AreaTable_Init_LostWoods() { Entrance(RR_KF_HOUSE_OF_TWINS, {[]{return true;}}), Entrance(RR_KF_KNOW_IT_ALL_HOUSE, {[]{return true;}}), Entrance(RR_KF_KOKIRI_SHOP, {[]{return true;}}), - Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return IsAdult || OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield;}}), + Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return IsAdult || randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || ShowedMidoSwordAndShield;}}), Entrance(RR_THE_LOST_WOODS, {[]{return true;}}), - Entrance(RR_LW_BRIDGE_FROM_FOREST, {[]{return IsAdult || OpenForest.IsNot(OPENFOREST_CLOSED) || DekuTreeClear;}}), + Entrance(RR_LW_BRIDGE_FROM_FOREST, {[]{return IsAdult || randoCtx->GetOption(RSK_FOREST).IsNot(RO_FOREST_CLOSED) || DekuTreeClear;}}), Entrance(RR_KF_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}), }); areaTable[RR_KF_OUTSIDE_DEKU_TREE] = Area("KF Outside Deku Tree", "Kokiri Forest", RHT_KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || ((IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_KOKIRI_SWORD)) && !ShuffleEntrances) || (IsChild && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BOOMERANG))));}}), - EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || ((IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_KOKIRI_SWORD)) && !ShuffleEntrances) || (IsChild && (CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || HasExplosives || CanUse(RG_DINS_FIRE))));}}), + EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || ((IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_KOKIRI_SWORD)) && !randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES)) || (IsChild && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BOOMERANG))));}}), + EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || ((IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_KOKIRI_SWORD)) && !randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES)) || (IsChild && (CanJumpslash || CanUse(RG_FAIRY_SLINGSHOT) || HasExplosives || CanUse(RG_DINS_FIRE))));}}), EventAccess(&ShowedMidoSwordAndShield, {[]{return ShowedMidoSwordAndShield || (IsChild && KokiriSword && DekuShield);}}), }, { //Locations @@ -43,8 +43,8 @@ void AreaTable_Init_LostWoods() { LocationAccess(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, {[]{return true;}}), }, { //Exits - Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return IsChild || (ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF) && (OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield));}}), - Entrance(RR_KOKIRI_FOREST, {[]{return IsAdult || OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield;}}), + Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return IsChild || (randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && (randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || ShowedMidoSwordAndShield));}}), + Entrance(RR_KOKIRI_FOREST, {[]{return IsAdult || randoCtx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || ShowedMidoSwordAndShield;}}), }); areaTable[RR_KF_LINKS_HOUSE] = Area("KF Link's House", "KF Link's House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, { @@ -131,9 +131,9 @@ void AreaTable_Init_LostWoods() { //Exits Entrance(RR_LW_FOREST_EXIT, {[]{return true;}}), Entrance(RR_GC_WOODS_WARP, {[]{return true;}}), - Entrance(RR_LW_BRIDGE, {[]{return CanLeaveForest && ((IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || LogicLostWoodsBridge)) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT));}}), + Entrance(RR_LW_BRIDGE, {[]{return CanLeaveForest && ((IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || randoCtx->GetTrickOption(RT_LW_BRIDGE))) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT));}}), Entrance(RR_ZORAS_RIVER, {[]{return CanLeaveForest && (CanDive || CanUse(RG_IRON_BOOTS));}}), - Entrance(RR_LW_BEYOND_MIDO, {[]{return IsChild || CanPlay(SariasSong) || LogicMidoBackflip;}}), + Entrance(RR_LW_BEYOND_MIDO, {[]{return IsChild || CanPlay(SariasSong) || randoCtx->GetTrickOption(RT_LW_MIDO_BACKFLIP);}}), Entrance(RR_LW_NEAR_SHORTCUTS_GROTTO, {[]{return Here(RR_THE_LOST_WOODS, []{return CanBlastOrSmash;});}}), }); @@ -144,8 +144,8 @@ void AreaTable_Init_LostWoods() { //Locations LocationAccess(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, {[]{return IsChild && CanStunDeku;}}), LocationAccess(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, {[]{return IsChild && CanStunDeku;}}), - LocationAccess(RC_LW_GS_ABOVE_THEATER, {[]{return IsAdult && AtNight && ((CanPlantBean(RR_LW_BEYOND_MIDO) && CanAdultAttack) || (LogicLostWoodsGSBean && CanUse(RG_HOOKSHOT) && (CanUse(RG_LONGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || HasBombchus || CanUse(RG_DINS_FIRE)))) && CanGetNightTimeGS;}}), - LocationAccess(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, {[]{return CanPlantBugs && (CanChildAttack || (Scrubsanity.Is(SCRUBSANITY_OFF) && DekuShield));}}), + LocationAccess(RC_LW_GS_ABOVE_THEATER, {[]{return IsAdult && AtNight && ((CanPlantBean(RR_LW_BEYOND_MIDO) && CanAdultAttack) || (randoCtx->GetTrickOption(RT_LW_GS_BEAN) && CanUse(RG_HOOKSHOT) && (CanUse(RG_LONGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || HasBombchus || CanUse(RG_DINS_FIRE)))) && CanGetNightTimeGS;}}), + LocationAccess(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, {[]{return CanPlantBugs && (CanChildAttack || (randoCtx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF) && DekuShield));}}), }, { //Exits Entrance(RR_LW_FOREST_EXIT, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp index 21c9ac641..5b935fe5e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_ShadowTemple() { /*-------------------------- @@ -12,15 +12,15 @@ void AreaTable_Init_ShadowTemple() { ---------------------------*/ areaTable[RR_SHADOW_TEMPLE_ENTRYWAY] = Area("Shadow Temple Entryway", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_SHADOW_TEMPLE_BEGINNING, {[]{return Dungeon::ShadowTemple.IsVanilla() && (LogicLensShadow || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}), - Entrance(RR_SHADOW_TEMPLE_MQ_BEGINNING, {[]{return Dungeon::ShadowTemple.IsMQ() && (LogicLensShadowMQ || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}), + Entrance(RR_SHADOW_TEMPLE_BEGINNING, {[]{return randoCtx->GetDungeon(SHADOW_TEMPLE)->IsVanilla() && (randoCtx->GetTrickOption(RT_LENS_SHADOW) || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}), + Entrance(RR_SHADOW_TEMPLE_MQ_BEGINNING, {[]{return randoCtx->GetDungeon(SHADOW_TEMPLE)->IsMQ() && (randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}), Entrance(RR_GRAVEYARD_WARP_PAD_REGION, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::ShadowTemple.IsVanilla()) { + if (randoCtx->GetDungeon(SHADOW_TEMPLE)->IsVanilla()) { areaTable[RR_SHADOW_TEMPLE_BEGINNING] = Area("Shadow Temple Beginning", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&NutPot, {[]{return true;}}), @@ -53,16 +53,16 @@ void AreaTable_Init_ShadowTemple() { LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanJumpslash;}}), LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanJumpslash;}}), LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}), - LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}), - LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_SHADOW_TEMPLE_FREESTANDING_KEY, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && (Bombs || GoronBracelet || (LogicShadowFreestandingKey && HasBombchus));}}), + LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && HoverBoots) || GoronBracelet;}}), + LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && HoverBoots) || GoronBracelet;}}), + LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || CanUse(RG_LENS_OF_TRUTH));}}), + LocationAccess(RC_SHADOW_TEMPLE_FREESTANDING_KEY, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && (Bombs || GoronBracelet || (randoCtx->GetTrickOption(RT_SHADOW_FREESTANDING_KEY) && HasBombchus));}}), LocationAccess(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, {[]{return CanJumpslash;}}), - LocationAccess(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (LogicShadowUmbrellaGS && HoverBoots);}}), - LocationAccess(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot;}}), + LocationAccess(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && HoverBoots);}}), + LocationAccess(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot;}}), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_WIND_TUNNEL, {[]{return ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && SmallKeys(RR_SHADOW_TEMPLE, 3, 4);}}), + Entrance(RR_SHADOW_TEMPLE_WIND_TUNNEL, {[]{return ((randoCtx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && randoCtx->GetTrickOption(RT_LENS_SHADOW)) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && SmallKeys(RR_SHADOW_TEMPLE, 3, 4);}}), }); areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL] = Area("Shadow Temple Wind Tunnel", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { @@ -84,18 +84,18 @@ void AreaTable_Init_ShadowTemple() { LocationAccess(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, {[]{return CanAdultAttack;}}), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus)) && SmallKeys(RR_SHADOW_TEMPLE, 5) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}}) + Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_DISTANT_SCARECROW) || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && HasBombchus)) && SmallKeys(RR_SHADOW_TEMPLE, 5) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}}) }); } /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::ShadowTemple.IsMQ()) { + if (randoCtx->GetDungeon(SHADOW_TEMPLE)->IsMQ()) { areaTable[RR_SHADOW_TEMPLE_MQ_BEGINNING] = Area("Shadow Temple MQ Beginning", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, {[]{return true;}}), - Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, {[]{return IsAdult && (CanUse(RG_FIRE_ARROWS) || HoverBoots || (LogicShadowMQGap && CanUse(RG_LONGSHOT)));}}), + Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, {[]{return IsAdult && (CanUse(RG_FIRE_ARROWS) || HoverBoots || (randoCtx->GetTrickOption(RT_SHADOW_MQ_GAP) && CanUse(RG_LONGSHOT)));}}), //Trick: IsAdult && (CanUse(RG_FIRE_ARROWS) || HoverBoots || (LogicShadowMQGap && CanUse(RG_LONGSHOT))) Entrance(RR_SHADOW_TEMPLE_MQ_DEAD_HAND_AREA, {[]{return HasExplosives && SmallKeys(RR_SHADOW_TEMPLE, 6);}}), }); @@ -118,13 +118,13 @@ void AreaTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT] = Area("Shadow Temple MQ Upper Huge Pit", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO));}}), + LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO));}}), //Trick: CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO)) - LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO));}}), + LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO));}}), //Trick: CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO)) }, { //Exits - Entrance(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, {[]{return HasFireSource || LogicShadowMQHugePit;}}), + Entrance(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, {[]{return HasFireSource || randoCtx->GetTrickOption(RT_SHADOW_MQ_HUGE_PIT);}}), //Trick: HasFireSource || LogicShadowMQHugePit }); @@ -132,15 +132,15 @@ void AreaTable_Init_ShadowTemple() { //Locations LocationAccess(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, {[]{return IsAdult && CanUse(RG_LONGSHOT);}}), LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, {[]{return CanJumpslash && HoverBoots && SmallKeys(RR_SHADOW_TEMPLE, 3) && ((LogicLensShadowMQ && LogicLensShadowMQPlatform) || CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && HoverBoots && SmallKeys(RR_SHADOW_TEMPLE, 3) && Hookshot && ((LogicLensShadowMQ && - LogicLensShadowMQInvisibleBlades && LogicLensShadowMQPlatform) || CanUse(RG_LENS_OF_TRUTH));}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (LogicShadowUmbrellaGS && HoverBoots);}}), + LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && HoverBoots) || GoronBracelet;}}), + LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, {[]{return (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA) && HoverBoots) || GoronBracelet;}}), + LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, {[]{return CanJumpslash && HoverBoots && SmallKeys(RR_SHADOW_TEMPLE, 3) && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || CanUse(RG_LENS_OF_TRUTH));}}), + LocationAccess(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && HoverBoots && SmallKeys(RR_SHADOW_TEMPLE, 3) && Hookshot && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) && + randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || CanUse(RG_LENS_OF_TRUTH));}}), + LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (randoCtx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && HoverBoots);}}), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL, {[]{return HoverBoots && ((LogicLensShadowMQ && LogicLensShadowMQPlatform) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && SmallKeys(RR_SHADOW_TEMPLE, 4);}}), + Entrance(RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL, {[]{return HoverBoots && ((randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ) && randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM)) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && SmallKeys(RR_SHADOW_TEMPLE, 4);}}), }); areaTable[RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL] = Area("Shadow Temple MQ Wind Tunnel", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, { @@ -161,11 +161,11 @@ void AreaTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT] = Area("Shadow Temple MQ Beyond Boat", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, {[]{return true;}}), - LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, {[]{return Bow || (LogicShadowStatue && HasBombchus);}}), + LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, {[]{return Bow || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && HasBombchus);}}), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, {[]{return Bow && CanPlay(SongOfTime) && IsAdult && CanUse(RG_LONGSHOT);}}), - Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || (LogicShadowStatue && HasBombchus)) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}}), + Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && HasBombchus)) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}}), }); areaTable[RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE] = Area("Shadow Temple MQ Invisible Maze", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { @@ -173,7 +173,7 @@ void AreaTable_Init_ShadowTemple() { LocationAccess(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, {[]{return CanUse(RG_DINS_FIRE) && SmallKeys(RR_SHADOW_TEMPLE, 6);}}), LocationAccess(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return CanUse(RG_DINS_FIRE) && SmallKeys(RR_SHADOW_TEMPLE, 6);}}), //below previously returned true - LocationAccess(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, {[]{return CanUse(RG_LENS_OF_TRUTH) || LogicLensShadowMQDeadHand;}}), + LocationAccess(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, {[]{return CanUse(RG_LENS_OF_TRUTH) || randoCtx->GetTrickOption(RT_LENS_SHADOW_MQ_DEADHAND);}}), LocationAccess(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, {[]{return true;}}), }, {}); } @@ -185,8 +185,8 @@ void AreaTable_Init_ShadowTemple() { Area("Shadow Temple Boss Entryway", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, { [] { return Dungeon::ShadowTemple.IsVanilla() && false; } }), - Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, { [] { return Dungeon::ShadowTemple.IsMQ() && false; } }), + Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, { [] { return randoCtx->GetDungeon(SHADOW_TEMPLE)->IsVanilla() && false; } }), + Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, { [] { return randoCtx->GetDungeon(SHADOW_TEMPLE)->IsMQ() && false; } }), Entrance(RR_SHADOW_TEMPLE_BOSS_ROOM, { [] { return true; } }), }); @@ -196,9 +196,9 @@ void AreaTable_Init_ShadowTemple() { // Events EventAccess(&ShadowTempleClear, { [] { return ShadowTempleClear || - ((CanUse(RG_LENS_OF_TRUTH) || LogicLensBongo) && + ((CanUse(RG_LENS_OF_TRUTH) || randoCtx->GetTrickOption(RT_LENS_BONGO)) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && - (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || LogicShadowBongo)); + (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || randoCtx->GetTrickOption(RT_SHADOW_BONGO))); } }), }, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp index e9b67bb63..c5ab8348f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_SpiritTemple() { /*-------------------------- @@ -12,15 +12,15 @@ void AreaTable_Init_SpiritTemple() { ---------------------------*/ areaTable[RR_SPIRIT_TEMPLE_ENTRYWAY] = Area("Spirit Temple Entryway", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_SPIRIT_TEMPLE_LOBBY, {[]{return Dungeon::SpiritTemple.IsVanilla();}}), - Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, {[]{return Dungeon::SpiritTemple.IsMQ();}}), + Entrance(RR_SPIRIT_TEMPLE_LOBBY, {[]{return randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla();}}), + Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, {[]{return randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsMQ();}}), Entrance(RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::SpiritTemple.IsVanilla()) { + if (randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla()) { areaTable[RR_SPIRIT_TEMPLE_LOBBY] = Area("Spirit Temple Lobby", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}), @@ -33,9 +33,9 @@ void AreaTable_Init_SpiritTemple() { EventAccess(&NutCrate, {[]{return true;}}), }, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}), - LocationAccess(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot))) && (Sticks || CanUse(RG_DINS_FIRE));}}), - LocationAccess(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}), + LocationAccess(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}), + LocationAccess(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot))) && (Sticks || CanUse(RG_DINS_FIRE));}}), + LocationAccess(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, {[]{return (Boomerang || Slingshot || (HasBombchus && randoCtx->GetTrickOption(RT_SPIRIT_CHILD_CHU))) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_CHILD_CLIMB, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 1);}}), @@ -43,24 +43,24 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Area("Child Spirit Temple Climb", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}), - LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}), + LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}), + LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}), LocationAccess(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, {[]{return HasProjectile(HasProjectileAge::Both) || CanUse(RG_DINS_FIRE) || (CanTakeDamage && (CanJumpslash || HasProjectile(HasProjectileAge::Child))) || (IsChild && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasProjectile(HasProjectileAge::Child)) || - ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && (HasProjectile(HasProjectileAge::Adult) || (CanTakeDamage && CanJumpslash)));}}), + ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && (HasProjectile(HasProjectileAge::Adult) || (CanTakeDamage && CanJumpslash)));}}), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return HasExplosives || (SunlightArrows && CanUse(RG_LIGHT_ARROWS));}}), + Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return HasExplosives || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS));}}), }); areaTable[RR_SPIRIT_TEMPLE_EARLY_ADULT] = Area("Early Adult Spirit Temple", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_SPIRIT_TEMPLE_COMPASS_CHEST, {[]{return CanUse(RG_HOOKSHOT) && CanPlay(ZeldasLullaby);}}), - LocationAccess(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasBombchus || (Bombs && IsAdult && LogicSpiritLowerAdultSwitch)) && (CanUse(RG_HOVER_BOOTS) || CanJumpslash);}}), + LocationAccess(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasBombchus || (Bombs && IsAdult && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (CanUse(RG_HOVER_BOOTS) || CanJumpslash);}}), LocationAccess(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3);}}), LocationAccess(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3);}}), - LocationAccess(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, {[]{return CanPlay(SongOfTime) && (Bow || Hookshot || HasBombchus || (Bombs && LogicSpiritLowerAdultSwitch));}}), + LocationAccess(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, {[]{return CanPlay(SongOfTime) && (Bow || Hookshot || HasBombchus || (Bombs && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH)));}}), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 1);}}), @@ -68,34 +68,34 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Area("Spirit Temple Central Chamber", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_MAP_CHEST, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && + LocationAccess(RC_SPIRIT_TEMPLE_MAP_CHEST, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && (CanUse(RG_DINS_FIRE) || - (((MagicMeter && FireArrows) || LogicSpiritMapChest) && Bow && Sticks))) || + (((MagicMeter && FireArrows) || randoCtx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && Bow && Sticks))) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives && CanUse(RG_STICKS)) || (SmallKeys(RR_SPIRIT_TEMPLE, 3) && - (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMapChest && Bow)) && + (CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && Bow)) && CanUse(RG_SILVER_GAUNTLETS));}}), - LocationAccess(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && + LocationAccess(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && (CanUse(RG_DINS_FIRE) || - (((MagicMeter && FireArrows) || LogicSpiritSunChest) && Bow && Sticks))) || + (((MagicMeter && FireArrows) || randoCtx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && Bow && Sticks))) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives && CanUse(RG_STICKS)) || (SmallKeys(RR_SPIRIT_TEMPLE, 3) && - (CanUse(RG_FIRE_ARROWS) || (LogicSpiritSunChest && Bow)) && + (CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && Bow)) && CanUse(RG_SILVER_GAUNTLETS));}}), LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby);}}), - LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby) && (Hookshot || HoverBoots || LogicSpiritLobbyJump);}}), + LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby) && (Hookshot || HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP));}}), LocationAccess(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, {[]{return (HasExplosives && Boomerang && Hookshot) || (CanUse(RG_BOOMERANG) && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives) || (Hookshot && CanUse(RG_SILVER_GAUNTLETS) && (SmallKeys(RR_SPIRIT_TEMPLE, 3) || - (SmallKeys(RR_SPIRIT_TEMPLE, 2) && Boomerang && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))));}}), - LocationAccess(RC_SPIRIT_TEMPLE_GS_LOBBY, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && - LogicSpiritLobbyGS && Boomerang && (Hookshot || HoverBoots || LogicSpiritLobbyJump)) || - (LogicSpiritLobbyGS && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives && CanUse(RG_BOOMERANG)) || - (SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && (Hookshot || HoverBoots || LogicSpiritLobbyJump));}}), + (SmallKeys(RR_SPIRIT_TEMPLE, 2) && Boomerang && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))));}}), + LocationAccess(RC_SPIRIT_TEMPLE_GS_LOBBY, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && randoCtx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && randoCtx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && + randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && Boomerang && (Hookshot || HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) || + (randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives && CanUse(RG_BOOMERANG)) || + (SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && (Hookshot || HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)));}}), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_OUTDOOR_HANDS, {[]{return CanJumpslash || HasExplosives;}}), @@ -114,18 +114,18 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Central Locked Door", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, {[]{return (MirrorShield || (SunlightArrows && CanUse(RG_LIGHT_ARROWS))) && HasExplosives;}}), - LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, {[]{return (LogicLensSpirit || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}), - LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, {[]{return (LogicLensSpirit || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}), + LocationAccess(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, {[]{return (MirrorShield || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))) && HasExplosives;}}), + LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_SPIRIT) || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}), + LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_SPIRIT) || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && (LogicSpiritWall || CanUse(RG_LONGSHOT) || HasBombchus || ((Bombs || Nuts || CanUse(RG_DINS_FIRE)) && (Bow || CanUse(RG_HOOKSHOT) || Hammer)));}}), + Entrance(RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && (randoCtx->GetTrickOption(RT_SPIRIT_WALL) || CanUse(RG_LONGSHOT) || HasBombchus || ((Bombs || Nuts || CanUse(RG_DINS_FIRE)) && (Bow || CanUse(RG_HOOKSHOT) || Hammer)));}}), }); areaTable[RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Final Locked Door", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return CanPlay(ZeldasLullaby) && ((CanTakeDamage && LogicFlamingChests) || (Bow && Hookshot));}}), - LocationAccess(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, {[]{return (MirrorShield && CanAdultAttack) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS));}}), + LocationAccess(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return CanPlay(ZeldasLullaby) && ((CanTakeDamage && randoCtx->GetTrickOption(RT_FLAMING_CHESTS)) || (Bow && Hookshot));}}), + LocationAccess(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, {[]{return (MirrorShield && CanAdultAttack) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS));}}), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, {[]{return MirrorShield && HasExplosives && Hookshot;}}), @@ -143,7 +143,7 @@ void AreaTable_Init_SpiritTemple() { /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::SpiritTemple.IsMQ()) { + if (randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsMQ()) { areaTable[RR_SPIRIT_TEMPLE_MQ_LOBBY] = Area("Spirit Temple MQ Lobby", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, {[]{return true;}}), @@ -164,7 +164,7 @@ void AreaTable_Init_SpiritTemple() { LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return SmallKeys(RR_SPIRIT_TEMPLE, 7) && Hammer;});}}), LocationAccess(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, {[]{return KokiriSword && HasBombchus && Slingshot && CanUse(RG_DINS_FIRE);}}), LocationAccess(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, {[]{return KokiriSword || Bombs;}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, {[]{return HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(RG_FAIRY_BOW) && CanPlay(SongOfTime)));})));}}), + LocationAccess(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, {[]{return HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return IsAdult && (CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && CanUse(RG_FAIRY_BOW) && CanPlay(SongOfTime)));})));}}), //Trick: HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (SPIRIT_TEMPLE_MQ_ADULT.Adult() && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(RG_FAIRY_BOW) && CanPlay(SongOfTime))))) }, { //Exits @@ -175,34 +175,34 @@ void AreaTable_Init_SpiritTemple() { //Locations LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}), LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby) && (CanJumpslash || CanUse(RG_HOVER_BOOTS));}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, {[]{return (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH));}}), + LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH));}}), LocationAccess(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5);}}), LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime);}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && (MirrorShield || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}), + LocationAccess(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && (MirrorShield || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}), LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}), LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT, {[]{return MirrorShield && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQLowerAdult && CanUse(RG_DINS_FIRE) && Bow));}}), + Entrance(RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT, {[]{return MirrorShield && IsAdult && (CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && CanUse(RG_DINS_FIRE) && Bow));}}), //Trick: MirrorShield && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQLowerAdult && CanUse(RG_DINS_FIRE) && Bow)) Entrance(RR_SPIRIT_TEMPLE_MQ_SHARED, {[]{return true;}}), Entrance(RR_SPIRIT_TEMPLE_MQ_BOSS_AREA, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 6) && CanPlay(ZeldasLullaby) && Hammer;}}), - Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && CanJumpslash && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH));}}), + Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH));}}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_SHARED] = Area("Spirit Temple MQ Shared", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 6);}}), LocationAccess(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, {[]{return (IsChild && CanUse(RG_FAIRY_SLINGSHOT) && SmallKeys(RR_SPIRIT_TEMPLE, 7)) || (IsAdult && CanUse(RG_FAIRY_BOW)) || (Bow && Slingshot);}}), - LocationAccess(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, {[]{return CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult;}}), + LocationAccess(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, {[]{return CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult;}}), //Trick: CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult - LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, {[]{return (LogicSpiritMQSunBlockGS && Boomerang && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT)) || IsAdult;}}), + LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, {[]{return (randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && Boomerang && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT))) || IsAdult;}}), //Trick: (LogicSpiritMQSunBlockGS && Boomerang && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT)) || IsAdult }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && CanJumpslash && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)));}}), + Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)));}}), //Trick: (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH))) - Entrance(RR_DESERT_COLOSSUS, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && CanJumpslash && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)) && IsAdult);}}), + Entrance(RR_DESERT_COLOSSUS, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)) && IsAdult);}}), //Trick: (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)) && IsAdult) }); @@ -217,7 +217,7 @@ void AreaTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_BOSS_AREA] = Area("Spirit Temple MQ Boss Area", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, {[]{return LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH);}}), + LocationAccess(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH);}}), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, {[]{return MirrorShield && Hookshot;}}), @@ -249,8 +249,8 @@ void AreaTable_Init_SpiritTemple() { "Spirit Temple Boss Entryway", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, { [] { return Dungeon::SpiritTemple.IsVanilla() && false; } }), - Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, { [] { return Dungeon::SpiritTemple.IsMQ() && false; } }), + Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, { [] { return randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla() && false; } }), + Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, { [] { return randoCtx->GetDungeon(SPIRIT_TEMPLE)->IsMQ() && false; } }), Entrance(RR_SPIRIT_TEMPLE_BOSS_ROOM, { [] { return true; } }), }); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp index 07a3bd517..8b50289e1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp @@ -1,10 +1,10 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" -#include "../dungeon.hpp" +#include "../../entrance.h" +#include "../../dungeon.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_WaterTemple() { /*-------------------------- @@ -12,29 +12,29 @@ void AreaTable_Init_WaterTemple() { ---------------------------*/ areaTable[RR_WATER_TEMPLE_ENTRYWAY] = Area("Water Temple Entryway", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return Dungeon::WaterTemple.IsVanilla();}}), - Entrance(RR_WATER_TEMPLE_MQ_LOBBY, {[]{return Dungeon::WaterTemple.IsMQ();}}), + Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return randoCtx->GetDungeon(WATER_TEMPLE)->IsVanilla();}}), + Entrance(RR_WATER_TEMPLE_MQ_LOBBY, {[]{return randoCtx->GetDungeon(WATER_TEMPLE)->IsMQ();}}), Entrance(RR_LAKE_HYLIA, {[]{return true;}}), }); /*-------------------------- | VANILLA DUNGEON | ---------------------------*/ - if (Dungeon::WaterTemple.IsVanilla()) { + if (randoCtx->GetDungeon(WATER_TEMPLE)->IsVanilla()) { //Water Temple logic currently assumes that the locked door leading to the upper water raising location is unlocked from the start areaTable[RR_WATER_TEMPLE_LOBBY] = Area("Water Temple Lobby", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return true;}}), - Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC)) && (CanUse(RG_IRON_BOOTS) || (CanUse(RG_LONGSHOT) && LogicWaterTempleTorchLongshot)));}}), - Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}), - Entrance(RR_WATER_TEMPLE_SOUTH_LOWER, {[]{return WaterTempleLow && HasExplosives && (CanDive || CanUse(RG_IRON_BOOTS)) && (LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC));}}), - Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return WaterTempleLow && GoronBracelet && (IsChild || CanDive || CanUse(RG_IRON_BOOTS)) && (LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC));}}), + Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return WaterTempleLow || ((randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC)) && (CanUse(RG_IRON_BOOTS) || (CanUse(RG_LONGSHOT) && randoCtx->GetTrickOption(RT_WATER_LONGSHOT_TORCH))));}}), + Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return WaterTempleLow || ((randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}), + Entrance(RR_WATER_TEMPLE_SOUTH_LOWER, {[]{return WaterTempleLow && HasExplosives && (CanDive || CanUse(RG_IRON_BOOTS)) && (randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC));}}), + Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return WaterTempleLow && GoronBracelet && (IsChild || CanDive || CanUse(RG_IRON_BOOTS)) && (randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC));}}), Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return WaterTempleLow && SmallKeys(RR_WATER_TEMPLE, 5);}}), Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER, {[]{return (WaterTempleLow || WaterTempleMiddle) && (HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW));}}), Entrance(RR_WATER_TEMPLE_EAST_MIDDLE, {[]{return (WaterTempleLow || WaterTempleMiddle || (CanUse(RG_IRON_BOOTS) && WaterTimer >= 16)) && CanUse(RG_HOOKSHOT);}}), Entrance(RR_WATER_TEMPLE_WEST_MIDDLE, {[]{return WaterTempleMiddle;}}), - Entrance(RR_WATER_TEMPLE_HIGH_WATER, {[]{return IsAdult && (CanUse(RG_HOVER_BOOTS) || (LogicDamageBoost && Bombs && CanTakeDamage));}}), - Entrance(RR_WATER_TEMPLE_BLOCK_CORRIDOR, {[]{return (WaterTempleLow || WaterTempleMiddle) && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (CanUse(RG_LONGSHOT) || CanUse(RG_HOVER_BOOTS) || (LogicWaterCentralBow && (IsAdult || WaterTempleMiddle)));}}), + Entrance(RR_WATER_TEMPLE_HIGH_WATER, {[]{return IsAdult && (CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_DAMAGE_BOOST) && Bombs && CanTakeDamage));}}), + Entrance(RR_WATER_TEMPLE_BLOCK_CORRIDOR, {[]{return (WaterTempleLow || WaterTempleMiddle) && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (CanUse(RG_LONGSHOT) || CanUse(RG_HOVER_BOOTS) || (randoCtx->GetTrickOption(RT_WATER_CENTRAL_BOW) && (IsAdult || WaterTempleMiddle)));}}), Entrance(RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM, {[]{return WaterTempleHigh && SmallKeys(RR_WATER_TEMPLE, 4);}}), Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, {[]{return WaterTempleHigh && CanUse(RG_LONGSHOT);}}), }); @@ -44,9 +44,9 @@ void AreaTable_Init_WaterTemple() { EventAccess(&WaterTempleLow, {[]{return WaterTempleLow || CanPlay(ZeldasLullaby);}}), }, {}, { //Exits - Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}), + Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return WaterTempleLow || ((randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}), Entrance(RR_WATER_TEMPLE_MAP_ROOM, {[]{return WaterTempleHigh;}}), - Entrance(RR_WATER_TEMPLE_CRACKED_WALL, {[]{return WaterTempleMiddle || (WaterTempleHigh && WaterTempleLow && ((CanUse(RG_HOVER_BOOTS) && LogicWaterCrackedWallHovers) || LogicWaterCrackedWallNothing));}}), + Entrance(RR_WATER_TEMPLE_CRACKED_WALL, {[]{return WaterTempleMiddle || (WaterTempleHigh && WaterTempleLow && ((CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_WATER_CRACKED_WALL_HOVERS)) || randoCtx->GetTrickOption(RT_WATER_CRACKED_WALL)));}}), Entrance(RR_WATER_TEMPLE_TORCH_ROOM, {[]{return WaterTempleLow && (HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW));}}), }); @@ -77,7 +77,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_NORTH_LOWER] = Area("Water Temple North Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}), - Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, {[]{return (CanUse(RG_LONGSHOT) || (LogicWaterBossKeyRegion && CanUse(RG_HOVER_BOOTS))) && SmallKeys(RR_WATER_TEMPLE, 4);}}), + Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, {[]{return (CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_WATER_BK_REGION) && CanUse(RG_HOVER_BOOTS))) && SmallKeys(RR_WATER_TEMPLE, 4);}}), }); areaTable[RR_WATER_TEMPLE_BOULDERS_LOWER] = Area("Water Temple Boulders Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { @@ -87,7 +87,7 @@ void AreaTable_Init_WaterTemple() { //Exits Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return SmallKeys(RR_WATER_TEMPLE, 4);}}), Entrance(RR_WATER_TEMPLE_BLOCK_ROOM, {[]{return true;}}), - Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (IsAdult && (CanUse(RG_HOVER_BOOTS) || LogicWaterNorthBasementLedgeJump)) || (CanUse(RG_HOVER_BOOTS) && CanUse(RG_IRON_BOOTS));}}), + Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (IsAdult && (CanUse(RG_HOVER_BOOTS) || randoCtx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP))) || (CanUse(RG_HOVER_BOOTS) && CanUse(RG_IRON_BOOTS));}}), }); areaTable[RR_WATER_TEMPLE_BLOCK_ROOM] = Area("Water Temple Block Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { @@ -106,7 +106,7 @@ void AreaTable_Init_WaterTemple() { //Exits Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, {[]{return true;}}), Entrance(RR_WATER_TEMPLE_JETS_ROOM, {[]{return IsAdult;}}), - Entrance(RR_WATER_TEMPLE_BOSS_KEY_ROOM, {[]{return (CanUse(RG_IRON_BOOTS) || (IsAdult && LogicWaterBKJumpDive)) && SmallKeys(RR_WATER_TEMPLE, 5);}}), + Entrance(RR_WATER_TEMPLE_BOSS_KEY_ROOM, {[]{return (CanUse(RG_IRON_BOOTS) || (IsAdult && randoCtx->GetTrickOption(RT_WATER_BK_JUMP_DIVE))) && SmallKeys(RR_WATER_TEMPLE, 5);}}), }); areaTable[RR_WATER_TEMPLE_BOSS_KEY_ROOM] = Area("Water Temple Boss Key Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, { @@ -117,7 +117,7 @@ void AreaTable_Init_WaterTemple() { LocationAccess(RC_WATER_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}), }, { //Exits - Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (CanUse(RG_IRON_BOOTS) || (IsAdult && LogicWaterBKJumpDive) || IsChild || CanDive) && SmallKeys(RR_WATER_TEMPLE, 5);}}), + Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (CanUse(RG_IRON_BOOTS) || (IsAdult && randoCtx->GetTrickOption(RT_WATER_BK_JUMP_DIVE)) || IsChild || CanDive) && SmallKeys(RR_WATER_TEMPLE, 5);}}), }); areaTable[RR_WATER_TEMPLE_SOUTH_LOWER] = Area("Water Temple South Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { @@ -136,8 +136,8 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_DRAGON_ROOM] = Area("Water Temple Dragon Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_DRAGON_CHEST, {[]{return (CanUse(RG_HOOKSHOT) && CanUse(RG_IRON_BOOTS)) || (((IsAdult && LogicWaterDragonAdult && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || HasBombchus)) || (IsChild && LogicWaterDragonChild && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasBombchus))) && (CanDive || CanUse(RG_IRON_BOOTS))) || - Here(RR_WATER_TEMPLE_RIVER, []{return IsAdult && CanUse(RG_FAIRY_BOW) && ((LogicWaterDragonAdult && (CanDive || CanUse(RG_IRON_BOOTS))) || LogicWaterDragonJumpDive);});}}), + LocationAccess(RC_WATER_TEMPLE_DRAGON_CHEST, {[]{return (CanUse(RG_HOOKSHOT) && CanUse(RG_IRON_BOOTS)) || (((IsAdult && randoCtx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || HasBombchus)) || (IsChild && randoCtx->GetTrickOption(RT_WATER_CHILD_DRAGON) && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasBombchus))) && (CanDive || CanUse(RG_IRON_BOOTS))) || + Here(RR_WATER_TEMPLE_RIVER, []{return IsAdult && CanUse(RG_FAIRY_BOW) && ((randoCtx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (CanDive || CanUse(RG_IRON_BOOTS))) || randoCtx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE));});}}), }, { //Exits Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return true;}}), @@ -155,7 +155,7 @@ void AreaTable_Init_WaterTemple() { EventAccess(&WaterTempleMiddle, {[]{return WaterTempleMiddle || CanPlay(ZeldasLullaby);}}), }, { //Locations - LocationAccess(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, {[]{return CanUse(RG_LONGSHOT) || (((LogicWaterCentralGSFW && CanUse(RG_FARORES_WIND) && (CanUse(RG_FAIRY_BOW) || CanUse(RG_DINS_FIRE) || SmallKeys(RR_WATER_TEMPLE, 5))) || (LogicWaterCentralGSIrons && CanUse(RG_IRON_BOOTS) && ((CanUse(RG_HOOKSHOT) && CanUse(RG_FAIRY_BOW)) || (CanUse(RG_DINS_FIRE))))) && WaterTempleHigh && HookshotOrBoomerang);}}), + LocationAccess(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, {[]{return CanUse(RG_LONGSHOT) || (((randoCtx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && CanUse(RG_FARORES_WIND) && (CanUse(RG_FAIRY_BOW) || CanUse(RG_DINS_FIRE) || SmallKeys(RR_WATER_TEMPLE, 5))) || (randoCtx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && CanUse(RG_IRON_BOOTS) && ((CanUse(RG_HOOKSHOT) && CanUse(RG_FAIRY_BOW)) || (CanUse(RG_DINS_FIRE))))) && WaterTempleHigh && HookshotOrBoomerang);}}), }, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}), @@ -202,7 +202,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM] = Area("Water Temple Falling Platform Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, {[]{return CanUse(RG_LONGSHOT) || (LogicWaterFallingPlatformGSBoomerang && IsChild && CanUse(RG_BOOMERANG)) || (LogicWaterFallingPlatformGSHookshot && IsAdult && CanUse(RG_HOOKSHOT));}}), + LocationAccess(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, {[]{return CanUse(RG_LONGSHOT) || (randoCtx->GetTrickOption(RT_WATER_RANG_FALLING_PLATFORM_GS) && IsChild && CanUse(RG_BOOMERANG)) || (randoCtx->GetTrickOption(RT_WATER_HOOKSHOT_FALLING_PLATFORM_GS) && IsAdult && CanUse(RG_HOOKSHOT));}}), }, { //Exits Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return CanUse(RG_HOOKSHOT) && SmallKeys(RR_WATER_TEMPLE, 4);}}), @@ -233,7 +233,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_RIVER] = Area("Water Temple River", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_WATER_TEMPLE_RIVER_CHEST, {[]{return (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (IsAdult || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}), - LocationAccess(RC_WATER_TEMPLE_GS_RIVER, {[]{return (CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT)) || (LogicWaterRiverGS && CanUse(RG_LONGSHOT));}}), + LocationAccess(RC_WATER_TEMPLE_GS_RIVER, {[]{return (CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT)) || (randoCtx->GetTrickOption(RT_WATER_RIVER_GS) && CanUse(RG_LONGSHOT));}}), }, { //Exits Entrance(RR_WATER_TEMPLE_DRAGON_ROOM, {[]{return (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (IsAdult || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}), @@ -252,7 +252,7 @@ void AreaTable_Init_WaterTemple() { /*--------------------------- | MASTER QUEST DUNGEON | ---------------------------*/ - if (Dungeon::WaterTemple.IsMQ()) { + if (randoCtx->GetDungeon(WATER_TEMPLE)->IsMQ()) { areaTable[RR_WATER_TEMPLE_MQ_LOBBY] = Area("Water Temple MQ Lobby", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return true;}}), @@ -264,7 +264,7 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_DIVE] = Area("Water Temple MQ Dive", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(RC_WATER_TEMPLE_MQ_MAP_CHEST, {[]{return HasFireSource && IsAdult && CanUse(RG_HOOKSHOT);}}), - LocationAccess(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, {[]{return IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanPlay(SongOfTime)));}}), + LocationAccess(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, {[]{return IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((randoCtx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanPlay(SongOfTime)));}}), //Trick: IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanPlay(SongOfTime))) }, { //Exits @@ -286,7 +286,7 @@ void AreaTable_Init_WaterTemple() { EventAccess(&NutPot, {[]{return true;}}), }, { //Locations - LocationAccess(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return IsAdult && WaterTimer >= 24 && CanUse(RG_DINS_FIRE) && (LogicWaterDragonJumpDive || CanDive || CanUse(RG_IRON_BOOTS));}}), + LocationAccess(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return IsAdult && WaterTimer >= 24 && CanUse(RG_DINS_FIRE) && (randoCtx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE) || CanDive || CanUse(RG_IRON_BOOTS));}}), LocationAccess(RC_WATER_TEMPLE_MQ_GS_RIVER, {[]{return true;}}), }, { //Exits @@ -295,9 +295,9 @@ void AreaTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS] = Area("Water Temple MQ Basement Gated Areas", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, {[]{return HoverBoots || CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump;}}), + LocationAccess(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, {[]{return HoverBoots || CanUse(RG_SCARECROW) || randoCtx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP);}}), LocationAccess(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, {[]{return CanUse(RG_FIRE_ARROWS) && (HoverBoots || CanUse(RG_SCARECROW));}}), - LocationAccess(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, {[]{return LogicWaterMQLockedGS || (SmallKeys(RR_WATER_TEMPLE, 2) && (HoverBoots || CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump) && CanJumpslash);}}), + LocationAccess(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, {[]{return randoCtx->GetTrickOption(RT_WATER_MQ_LOCKED_GS) || (SmallKeys(RR_WATER_TEMPLE, 2) && (HoverBoots || CanUse(RG_SCARECROW) || randoCtx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP)) && CanJumpslash);}}), //Trick: LogicWaterMQLockedGS || (SmallKeys(RR_WATER_TEMPLE, 2) && (HoverBoots || CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump)) }, {}); } @@ -309,8 +309,8 @@ void AreaTable_Init_WaterTemple() { Area("Water Temple Boss Entryway", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, { [] { return Dungeon::WaterTemple.IsVanilla() && false; } }), - Entrance(RR_WATER_TEMPLE_MQ_LOBBY, { [] { return Dungeon::WaterTemple.IsMQ() && false; } }), + Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, { [] { return randoCtx->GetDungeon(WATER_TEMPLE)->IsVanilla() && false; } }), + Entrance(RR_WATER_TEMPLE_MQ_LOBBY, { [] { return randoCtx->GetDungeon(WATER_TEMPLE)->IsMQ() && false; } }), Entrance(RR_WATER_TEMPLE_BOSS_ROOM, { [] { return true; } }), }); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp index 346186255..a6f49c4b3 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp @@ -1,9 +1,9 @@ #include "../location_access.hpp" #include "../logic.hpp" -#include "../entrance.hpp" +#include "../../entrance.h" using namespace Logic; -using namespace Settings; +using namespace Rando; void AreaTable_Init_ZorasDomain() { areaTable[RR_ZR_FRONT] = Area("ZR Front", "Zora River", RHT_ZORAS_RIVER, DAY_NIGHT_CYCLE, {}, { @@ -31,8 +31,8 @@ void AreaTable_Init_ZorasDomain() { LocationAccess(RC_ZR_FROGS_SARIAS_SONG, {[]{return IsChild && CanPlay(SariasSong);}}), LocationAccess(RC_ZR_FROGS_SUNS_SONG, {[]{return IsChild && CanPlay(SunsSong);}}), LocationAccess(RC_ZR_FROGS_SONG_OF_TIME, {[]{return IsChild && CanPlay(SongOfTime);}}), - LocationAccess(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && LogicZoraRiverLower);}}), - LocationAccess(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && LogicZoraRiverUpper);}}), + LocationAccess(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && randoCtx->GetTrickOption(RT_ZR_LOWER));}}), + LocationAccess(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && randoCtx->GetTrickOption(RT_ZR_UPPER));}}), LocationAccess(RC_ZR_GS_LADDER, {[]{return IsChild && AtNight && CanChildAttack && CanGetNightTimeGS;}}), LocationAccess(RC_ZR_GS_NEAR_RAISED_GROTTOS, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}), LocationAccess(RC_ZR_GS_ABOVE_BRIDGE, {[]{return IsAdult && CanUse(RG_HOOKSHOT) && AtNight && CanGetNightTimeGS;}}), @@ -45,7 +45,7 @@ void AreaTable_Init_ZorasDomain() { Entrance(RR_ZR_FAIRY_GROTTO, {[]{return Here(RR_ZORAS_RIVER, []{return CanBlastOrSmash;});}}), Entrance(RR_THE_LOST_WOODS, {[]{return CanDive || CanUse(RG_IRON_BOOTS);}}), Entrance(RR_ZR_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}), - Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return CanPlay(ZeldasLullaby) || (IsChild && LogicZoraWithCucco) || (IsAdult && CanUse(RG_HOVER_BOOTS) && LogicZoraWithHovers);}}), + Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return CanPlay(ZeldasLullaby) || (IsChild && randoCtx->GetTrickOption(RT_ZR_CUCCO)) || (IsAdult && CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_ZR_HOVERS));}}), }); areaTable[RR_ZR_BEHIND_WATERFALL] = Area("ZR Behind Waterfall", "Zora River", RHT_ZORAS_RIVER, DAY_NIGHT_CYCLE, {}, {}, { @@ -88,27 +88,27 @@ void AreaTable_Init_ZorasDomain() { EventAccess(&StickPot, {[]{return StickPot || IsChild;}}), EventAccess(&FishGroup, {[]{return FishGroup || IsChild;}}), EventAccess(&KingZoraThawed, {[]{return KingZoraThawed || (IsAdult && BlueFire);}}), - EventAccess(&DeliverLetter, {[]{return DeliverLetter || (RutosLetter && IsChild && ZorasFountain.IsNot(ZORASFOUNTAIN_OPEN));}}), + EventAccess(&DeliverLetter, {[]{return DeliverLetter || (RutosLetter && IsChild && randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).IsNot(RO_ZF_OPEN));}}), }, { //Locations LocationAccess(RC_ZD_DIVING_MINIGAME, {[]{return IsChild;}}), LocationAccess(RC_ZD_CHEST, {[]{return IsChild && CanUse(RG_STICKS);}}), LocationAccess(RC_ZD_KING_ZORA_THAWED, {[]{return KingZoraThawed;}}), LocationAccess(RC_ZD_TRADE_PRESCRIPTION, {[]{return KingZoraThawed && Prescription;}}), - LocationAccess(RC_ZD_GS_FROZEN_WATERFALL, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || CanUse(RG_FAIRY_SLINGSHOT) || Bow || (MagicMeter && (CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD))) || (LogicDomainGS && CanJumpslash)) && CanGetNightTimeGS;}}), + LocationAccess(RC_ZD_GS_FROZEN_WATERFALL, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || CanUse(RG_FAIRY_SLINGSHOT) || Bow || (MagicMeter && (CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD))) || (randoCtx->GetTrickOption(RT_ZD_GS) && CanJumpslash)) && CanGetNightTimeGS;}}), LocationAccess(RC_ZD_GOSSIP_STONE, {[]{return true;}}), }, { //Exits Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return true;}}), Entrance(RR_LAKE_HYLIA, {[]{return IsChild && (CanDive || CanUse(RG_IRON_BOOTS));}}), - Entrance(RR_ZD_BEHIND_KING_ZORA, {[]{return DeliverLetter || ZorasFountain.Is(ZORASFOUNTAIN_OPEN) || (ZorasFountain.Is(ZORASFOUNTAIN_ADULT) && IsAdult) || (LogicKingZoraSkip && IsAdult);}}), + Entrance(RR_ZD_BEHIND_KING_ZORA, {[]{return DeliverLetter || randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN) || (randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_CLOSED_CHILD) && IsAdult) || (randoCtx->GetTrickOption(RT_ZD_KING_ZORA_SKIP) && IsAdult);}}), Entrance(RR_ZD_SHOP, {[]{return IsChild || BlueFire;}}), Entrance(RR_ZD_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}), }); areaTable[RR_ZD_BEHIND_KING_ZORA] = Area("ZD Behind King Zora", "Zoras Domain", RHT_ZORAS_DOMAIN, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_ZORAS_DOMAIN, {[]{return DeliverLetter || ZorasFountain.Is(ZORASFOUNTAIN_OPEN) || (ZorasFountain.Is(ZORASFOUNTAIN_ADULT) && IsAdult);}}), + Entrance(RR_ZORAS_DOMAIN, {[]{return DeliverLetter || randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_OPEN) || (randoCtx->GetOption(RSK_ZORAS_FOUNTAIN).Is(RO_ZF_CLOSED_CHILD) && IsAdult);}}), Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}), }); diff --git a/soh/soh/Enhancements/randomizer/3drando/logic.cpp b/soh/soh/Enhancements/randomizer/3drando/logic.cpp index d7b8f018a..5e16727b6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/logic.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/logic.cpp @@ -6,10 +6,8 @@ #include #include -#include "settings.hpp" -#include "dungeon.hpp" - -using namespace Settings; +#include "../dungeon.h" +#include "../context.h" namespace Logic { @@ -430,29 +428,30 @@ namespace Logic { switch (itemName) { // Adult items - case RG_FAIRY_BOW: return IsAdult || BowAsChild; - case RG_MEGATON_HAMMER: return IsAdult || HammerAsChild; - case RG_IRON_BOOTS: return IsAdult || IronBootsAsChild; - case RG_HOVER_BOOTS: return IsAdult || HoverBootsAsChild; - case RG_HOOKSHOT: return IsAdult || HookshotAsChild; - case RG_LONGSHOT: return IsAdult || HookshotAsChild; + // TODO: Uncomment those if we ever implement more item usability settings + case RG_FAIRY_BOW: return IsAdult;// || BowAsChild; + case RG_MEGATON_HAMMER: return IsAdult;// || HammerAsChild; + case RG_IRON_BOOTS: return IsAdult;// || IronBootsAsChild; + case RG_HOVER_BOOTS: return IsAdult;// || HoverBootsAsChild; + case RG_HOOKSHOT: return IsAdult;// || HookshotAsChild; + case RG_LONGSHOT: return IsAdult;// || HookshotAsChild; case RG_SILVER_GAUNTLETS: return IsAdult; case RG_GOLDEN_GAUNTLETS: return IsAdult; - case RG_GORON_TUNIC: return IsAdult || GoronTunicAsChild; - case RG_ZORA_TUNIC: return IsAdult || ZoraTunicAsChild; - case RG_SCARECROW: return IsAdult || HookshotAsChild; - case RG_DISTANT_SCARECROW: return IsAdult || HookshotAsChild; + case RG_GORON_TUNIC: return IsAdult;// || GoronTunicAsChild; + case RG_ZORA_TUNIC: return IsAdult;// || ZoraTunicAsChild; + case RG_SCARECROW: return IsAdult;// || HookshotAsChild; + case RG_DISTANT_SCARECROW: return IsAdult;// || HookshotAsChild; case RG_HYLIAN_SHIELD: return IsAdult; - case RG_MIRROR_SHIELD: return IsAdult || MirrorShieldAsChild; - case RG_MASTER_SWORD: return IsAdult || MasterSwordAsChild; - case RG_BIGGORON_SWORD: return IsAdult || BiggoronSwordAsChild; + case RG_MIRROR_SHIELD: return IsAdult;// || MirrorShieldAsChild; + case RG_MASTER_SWORD: return IsAdult;// || MasterSwordAsChild; + case RG_BIGGORON_SWORD: return IsAdult;// || BiggoronSwordAsChild; // Child items - case RG_FAIRY_SLINGSHOT: return IsChild || SlingshotAsAdult; - case RG_BOOMERANG: return IsChild || BoomerangAsAdult; - case RG_KOKIRI_SWORD: return IsChild || KokiriSwordAsAdult; - case RG_STICKS: return IsChild || StickAsAdult; - case RG_DEKU_SHIELD: return IsChild || DekuShieldAsAdult; + case RG_FAIRY_SLINGSHOT: return IsChild;// || SlingshotAsAdult; + case RG_BOOMERANG: return IsChild;// || BoomerangAsAdult; + case RG_KOKIRI_SWORD: return IsChild;// || KokiriSwordAsAdult; + case RG_STICKS: return IsChild;// || StickAsAdult; + case RG_DEKU_SHIELD: return IsChild;// || DekuShieldAsAdult; // Magic items default: return MagicMeter && (IsMagicItem(itemName) || (IsMagicArrow(itemName) && CanUse(RG_FAIRY_BOW))); @@ -467,7 +466,7 @@ namespace Logic { (age == HasProjectileAge::Either && (Slingshot || Boomerang || Hookshot || Bow)); } - uint8_t GetDifficultyValueFromString(Option& glitchOption) { + uint8_t GetDifficultyValueFromString(Rando::Option& glitchOption) { return 0; } @@ -484,11 +483,12 @@ namespace Logic { } bool CanDoGlitch(GlitchType glitch) { + // TODO: Uncomment when glitches are implemented switch(glitch) { case GlitchType::EquipSwapDins: - return ((IsAdult && HasItem(RG_DINS_FIRE)) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_DINS_FIRE)))) && GlitchEquipSwapDins; + return ((IsAdult && HasItem(RG_DINS_FIRE)) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_DINS_FIRE)))) && false;//GlitchEquipSwapDins; case GlitchType::EquipSwap: // todo: add bunny hood to adult item equippable list and child trade item to child item equippable list - return ((IsAdult && (HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE))) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_FAIRY_SLINGSHOT) || HasItem(RG_BOOMERANG) || HasBottle || Nuts || Ocarina || HasItem(RG_LENS_OF_TRUTH) || HasExplosives || (MagicBean || MagicBeanPack) || HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE)))) && GlitchEquipSwap; + return ((IsAdult && (HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE))) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_FAIRY_SLINGSHOT) || HasItem(RG_BOOMERANG) || HasBottle || Nuts || Ocarina || HasItem(RG_LENS_OF_TRUTH) || HasExplosives || (MagicBean || MagicBeanPack) || HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE)))) && false;//GlitchEquipSwap; } //Shouldn't be reached @@ -497,6 +497,7 @@ namespace Logic { //Updates all logic helpers. Should be called whenever a non-helper is changed void UpdateHelpers() { + auto ctx = Rando::Context::GetInstance(); NumBottles = ((NoBottles) ? 0 : (Bottles + ((DeliverLetter) ? 1 : 0))); HasBottle = NumBottles >= 1; Slingshot = (ProgressiveBulletBag >= 1) && (BuySeed || AmmoCanDrop); @@ -515,7 +516,7 @@ namespace Logic { AdultsWallet = ProgressiveWallet >= 1; BiggoronSword = BiggoronSword || ProgressiveGiantKnife >= 2; - ScarecrowSong = ScarecrowSong || FreeScarecrow || (ChildScarecrow && AdultScarecrow); + ScarecrowSong = ScarecrowSong || ctx->GetOption(RSK_SKIP_SCARECROWS_SONG) || (ChildScarecrow && AdultScarecrow); Scarecrow = Hookshot && CanPlay(ScarecrowSong); DistantScarecrow = Longshot && CanPlay(ScarecrowSong); @@ -532,28 +533,29 @@ namespace Logic { Nuts = DekuNutDrop || Nuts; Sticks = DekuStickDrop || Sticks; Bugs = HasBottle && BugsAccess; - BlueFire = (HasBottle && BlueFireAccess) || (BlueFireArrows && CanUse(RG_ICE_ARROWS)); + BlueFire = (HasBottle && BlueFireAccess) || (ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && CanUse(RG_ICE_ARROWS)); Fish = HasBottle && FishAccess; Fairy = HasBottle && FairyAccess; FoundBombchus = (BombchuDrop || Bombchus || Bombchus5 || Bombchus10 || Bombchus20); - CanPlayBowling = (BombchusInLogic && FoundBombchus) || (!BombchusInLogic && BombBag); - HasBombchus = (BuyBombchus10 || BuyBombchus20 || (AmmoDrops.Is(AMMODROPS_BOMBCHU) && FoundBombchus)); + CanPlayBowling = (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && FoundBombchus) || (!ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && BombBag); + // TODO: Implement Ammo Drop Setting in place of bombchu drops + HasBombchus = (BuyBombchus10 || BuyBombchus20 || (ctx->GetOption(RSK_ENABLE_BOMBCHU_DROPS).Is(RO_AMMO_DROPS_ON_PLUS_BOMBCHU) && FoundBombchus)); - HasExplosives = Bombs || (BombchusInLogic && HasBombchus); + HasExplosives = Bombs || (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && HasBombchus); HasBoots = IronBoots || HoverBoots; //Unshuffled adult trade quest - Eyedrops = Eyedrops || (!ShuffleAdultTradeQuest && ClaimCheck); - EyeballFrog = EyeballFrog || (!ShuffleAdultTradeQuest && Eyedrops); - Prescription = Prescription || (!ShuffleAdultTradeQuest && EyeballFrog); - BrokenSword = BrokenSword || (!ShuffleAdultTradeQuest && Prescription); - PoachersSaw = PoachersSaw || (!ShuffleAdultTradeQuest && BrokenSword); - OddPoultice = OddPoultice || (!ShuffleAdultTradeQuest && PoachersSaw); - OddMushroom = OddMushroom || (!ShuffleAdultTradeQuest && OddPoultice); - Cojiro = Cojiro || (!ShuffleAdultTradeQuest && OddMushroom); - PocketEgg = PocketEgg || (!ShuffleAdultTradeQuest && Cojiro); + Eyedrops = Eyedrops || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && ClaimCheck); + EyeballFrog = EyeballFrog || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Eyedrops); + Prescription = Prescription || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && EyeballFrog); + BrokenSword = BrokenSword || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Prescription); + PoachersSaw = PoachersSaw || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && BrokenSword); + OddPoultice = OddPoultice || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && PoachersSaw); + OddMushroom = OddMushroom || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && OddPoultice); + Cojiro = Cojiro || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && OddMushroom); + PocketEgg = PocketEgg || (!ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) && Cojiro); // IsChild = Age == AGE_CHILD; // IsAdult = Age == AGE_ADULT; @@ -566,34 +568,34 @@ namespace Logic { CanStunDeku = CanAdultAttack || CanChildAttack || Nuts || HasShield; CanCutShrubs = CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BOOMERANG) || HasExplosives || CanUse(RG_MASTER_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_BIGGORON_SWORD); CanDive = ProgressiveScale >= 1; - CanLeaveForest = OpenForest.IsNot(OPENFOREST_CLOSED) || IsAdult || DekuTreeClear || ShuffleInteriorEntrances || ShuffleOverworldEntrances; + CanLeaveForest = ctx->GetOption(RSK_FOREST).IsNot(RO_FOREST_CLOSED) || IsAdult || DekuTreeClear || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES); CanPlantBugs = IsChild && Bugs; CanRideEpona = IsAdult && Epona && CanPlay(EponasSong); CanSummonGossipFairy = Ocarina && (ZeldasLullaby || EponasSong || SongOfTime || SunsSong); CanSummonGossipFairyWithoutSuns = Ocarina && (ZeldasLullaby || EponasSong || SongOfTime); Hearts = BaseHearts + HeartContainer + (PieceOfHeart >> 2); EffectiveHealth = ((Hearts << (2 + DoubleDefense)) >> Multiplier) + ((Hearts << (2 + DoubleDefense)) % (1 << Multiplier) > 0); //Number of half heart hits to die, ranges from 1 to 160 - FireTimer = CanUse(RG_GORON_TUNIC) ? 255 : (LogicFewerTunicRequirements) ? (Hearts * 8) : 0; - WaterTimer = CanUse(RG_ZORA_TUNIC) ? 255 : (LogicFewerTunicRequirements) ? (Hearts * 8) : 0; + FireTimer = CanUse(RG_GORON_TUNIC) ? 255 : (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS)) ? (Hearts * 8) : 0; + WaterTimer = CanUse(RG_ZORA_TUNIC) ? 255 : (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS)) ? (Hearts * 8) : 0; NeedNayrusLove = (EffectiveHealth == 1); CanSurviveDamage = !NeedNayrusLove || CanUse(RG_NAYRUS_LOVE); CanTakeDamage = Fairy || CanSurviveDamage; CanTakeDamageTwice = (Fairy && NumBottles >= 2) || ((EffectiveHealth == 2) && (CanUse(RG_NAYRUS_LOVE) || Fairy)) || (EffectiveHealth > 2); //CanPlantBean = IsChild && (MagicBean || MagicBeanPack); - CanOpenBombGrotto = CanBlastOrSmash && (ShardOfAgony || LogicGrottosWithoutAgony); - CanOpenStormGrotto = CanPlay(SongOfStorms) && (ShardOfAgony || LogicGrottosWithoutAgony); + CanOpenBombGrotto = CanBlastOrSmash && (ShardOfAgony || ctx->GetTrickOption(RT_GROTTOS_WITHOUT_AGONY)); + CanOpenStormGrotto = CanPlay(SongOfStorms) && (ShardOfAgony || ctx->GetTrickOption(RT_GROTTOS_WITHOUT_AGONY)); HookshotOrBoomerang = CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG); - CanGetNightTimeGS = (CanPlay(SunsSong) || !NightGSExpectSuns); + CanGetNightTimeGS = (CanPlay(SunsSong) || !ctx->GetOption(RSK_SKULLS_SUNS_SONG)); - GuaranteeTradePath = ShuffleInteriorEntrances || ShuffleOverworldEntrances || LogicBiggoronBolero || CanBlastOrSmash || StopGCRollingGoronAsAdult; + GuaranteeTradePath = ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetTrickOption(RT_DMT_BOLERO_BIGGORON) || CanBlastOrSmash || StopGCRollingGoronAsAdult; //GuaranteeHint = (hints == "Mask" && MaskofTruth) || (hints == "Agony") || (hints != "Mask" && hints != "Agony"); HasFireSource = CanUse(RG_DINS_FIRE) || CanUse(RG_FIRE_ARROWS); HasFireSourceWithTorch = HasFireSource || CanUse(RG_STICKS); //Gerudo Fortress - CanFinishGerudoFortress = (GerudoFortress.Is(GERUDOFORTRESS_NORMAL) && GerudoFortressKeys >= 4 && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || LogicGerudoKitchen)) || - (GerudoFortress.Is(GERUDOFORTRESS_FAST) && GerudoFortressKeys >= 1 && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))) || - (GerudoFortress.IsNot(GERUDOFORTRESS_NORMAL) && GerudoFortress.IsNot(GERUDOFORTRESS_FAST)); + CanFinishGerudoFortress = (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_NORMAL) && GerudoFortressKeys >= 4 && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_GF_KITCHEN))) || + (ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_FAST) && GerudoFortressKeys >= 1 && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))) || + (ctx->GetOption(RSK_GERUDO_FORTRESS).IsNot(RO_GF_NORMAL) && ctx->GetOption(RSK_GERUDO_FORTRESS).IsNot(RO_GF_FAST)); HasShield = CanUse(RG_HYLIAN_SHIELD) || CanUse(RG_DEKU_SHIELD); //Mirror shield can't reflect attacks CanShield = CanUse(RG_MIRROR_SHIELD) || HasShield; @@ -611,25 +613,25 @@ namespace Logic { DungeonCount = (DekuTreeClear ? 1:0) + (DodongosCavernClear ? 1:0) + (JabuJabusBellyClear ? 1:0) + (ForestTempleClear ? 1:0) + (FireTempleClear ? 1:0) + (WaterTempleClear ? 1:0) + (SpiritTempleClear ? 1:0) + (ShadowTempleClear ? 1:0); HasAllStones = StoneCount == 3; HasAllMedallions = MedallionCount == 6; - GregInBridgeLogic = BridgeRewardOptions.Is(BRIDGE_OPTION_GREG); - GregInLacsLogic = LACSRewardOptions.Is(LACS_OPTION_GREG); + GregInBridgeLogic = ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG); + GregInLacsLogic = ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD); - CanBuildRainbowBridge = Bridge.Is(RAINBOWBRIDGE_OPEN) || - (Bridge.Is(RAINBOWBRIDGE_VANILLA) && ShadowMedallion && SpiritMedallion && LightArrows) || - (Bridge.Is(RAINBOWBRIDGE_STONES) && StoneCount + (Greg && GregInBridgeLogic ? 1 : 0) >= BridgeStoneCount.Value()) || - (Bridge.Is(RAINBOWBRIDGE_MEDALLIONS) && MedallionCount + (Greg && GregInBridgeLogic ? 1 : 0) >= BridgeMedallionCount.Value()) || - (Bridge.Is(RAINBOWBRIDGE_REWARDS) && StoneCount + MedallionCount + (Greg && GregInBridgeLogic ? 1 : 0) >= BridgeRewardCount.Value()) || - (Bridge.Is(RAINBOWBRIDGE_DUNGEONS) && DungeonCount + (Greg && GregInBridgeLogic ? 1 : 0) >= BridgeDungeonCount.Value()) || - (Bridge.Is(RAINBOWBRIDGE_TOKENS) && GoldSkulltulaTokens >= BridgeTokenCount.Value()) || - (Bridge.Is(RAINBOWBRIDGE_GREG) && Greg); + CanBuildRainbowBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA) && ShadowMedallion && SpiritMedallion && LightArrows) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES) && StoneCount + (Greg && GregInBridgeLogic ? 1 : 0) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Value()) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS) && MedallionCount + (Greg && GregInBridgeLogic ? 1 : 0) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Value()) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS) && StoneCount + MedallionCount + (Greg && GregInBridgeLogic ? 1 : 0) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value()) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && DungeonCount + (Greg && GregInBridgeLogic ? 1 : 0) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value()) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) && GoldSkulltulaTokens >= ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value()) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG) && Greg); - CanTriggerLACS = (LACSCondition == LACSCONDITION_VANILLA && ShadowMedallion && SpiritMedallion) || - (LACSCondition == LACSCONDITION_STONES && StoneCount + (Greg && GregInLacsLogic ? 1 : 0) >= LACSStoneCount.Value()) || - (LACSCondition == LACSCONDITION_MEDALLIONS && MedallionCount + (Greg && GregInLacsLogic ? 1 : 0) >= LACSMedallionCount.Value()) || - (LACSCondition == LACSCONDITION_REWARDS && StoneCount + MedallionCount + (Greg && GregInLacsLogic ? 1 : 0) >= LACSRewardCount.Value()) || - (LACSCondition == LACSCONDITION_DUNGEONS && DungeonCount + (Greg && GregInLacsLogic ? 1 : 0) >= LACSDungeonCount.Value()) || - (LACSCondition == LACSCONDITION_TOKENS && GoldSkulltulaTokens >= LACSTokenCount.Value()); - CanCompleteTriforce = TriforcePieces >= TriforceHuntRequired.Value(); + CanTriggerLACS = (ctx->GetSettings()->LACSCondition() == RO_LACS_VANILLA && ShadowMedallion && SpiritMedallion) || + (ctx->GetSettings()->LACSCondition() == RO_LACS_STONES && StoneCount + (Greg && GregInLacsLogic ? 1 : 0) >= ctx->GetOption(RSK_LACS_STONE_COUNT).Value()) || + (ctx->GetSettings()->LACSCondition() == RO_LACS_MEDALLIONS && MedallionCount + (Greg && GregInLacsLogic ? 1 : 0) >= ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Value()) || + (ctx->GetSettings()->LACSCondition() == RO_LACS_REWARDS && StoneCount + MedallionCount + (Greg && GregInLacsLogic ? 1 : 0) >= ctx->GetOption(RSK_LACS_REWARD_COUNT).Value()) || + (ctx->GetSettings()->LACSCondition() == RO_LACS_DUNGEONS && DungeonCount + (Greg && GregInLacsLogic ? 1 : 0) >= ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value()) || + (ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS && GoldSkulltulaTokens >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value()); + CanCompleteTriforce = TriforcePieces >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Value(); } bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount) { @@ -730,9 +732,12 @@ namespace Logic { //Reset All Logic to false void LogicReset() { + auto ctx = Rando::Context::GetInstance(); //Settings-dependent variables - IsKeysanity = Keysanity.Is(KEYSANITY_ANYWHERE) || Keysanity.Is(KEYSANITY_OVERWORLD) || Keysanity.Is(KEYSANITY_ANY_DUNGEON); - AmmoCanDrop = AmmoDrops.IsNot(AMMODROPS_NONE); + IsKeysanity = ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || + ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || + ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE); + AmmoCanDrop = /*AmmoDrops.IsNot(AMMODROPS_NONE) TODO: AmmoDrop setting*/ true; //Child item logic KokiriSword = false; @@ -858,7 +863,7 @@ namespace Logic { //Keys ForestTempleKeys = 0; //If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in vanilla FiT - FireTempleKeys = IsKeysanity || Dungeon::FireTemple.IsMQ() ? 0 : 1; + FireTempleKeys = IsKeysanity || ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsMQ() ? 0 : 1; WaterTempleKeys = 0; SpiritTempleKeys = 0; ShadowTempleKeys = 0; @@ -968,7 +973,7 @@ namespace Logic { HasBoots = false; IsChild = false; IsAdult = false; - IsGlitched = Settings::Logic.Is(LOGIC_GLITCHED); + IsGlitched = ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED); CanBlastOrSmash = false; CanChildAttack = false; CanChildDamage = false; @@ -986,9 +991,9 @@ namespace Logic { BigPoeKill = false; HookshotOrBoomerang = false; - BaseHearts = StartingHearts.Value() + 1; + BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).Value() + 1; Hearts = 0; - Multiplier = (DamageMultiplier.Value() < 6) ? DamageMultiplier.Value() : 10; + Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Value() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Value() : 10; EffectiveHealth = 0; FireTimer = 0; WaterTimer = 0; @@ -1020,7 +1025,7 @@ namespace Logic { //Other AtDay = false; AtNight = false; - Age = Settings::ResolvedStartingAge; + Age = ctx->GetSettings()->ResolvedStartingAge(); //Events ShowedMidoSwordAndShield = false; diff --git a/soh/soh/Enhancements/randomizer/3drando/menu.cpp b/soh/soh/Enhancements/randomizer/3drando/menu.cpp index 5da2b618c..f6131cd87 100644 --- a/soh/soh/Enhancements/randomizer/3drando/menu.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/menu.cpp @@ -8,7 +8,6 @@ #include "menu.hpp" #include "playthrough.hpp" #include "randomizer.hpp" -#include "settings.hpp" #include "spoiler_log.hpp" #include "location_access.hpp" #include @@ -19,11 +18,12 @@ namespace { bool seedChanged; uint16_t pastSeedLength; std::vector presetEntries; -Option* currentSetting; +Rando::Option* currentSetting; } // namespace std::string GenerateRandomizer(std::unordered_map cvarSettings, std::set excludedLocations, std::set enabledTricks, std::string seedString) { + auto ctx = Rando::Context::GetInstance(); srand(time(NULL)); // if a blank seed was entered, make a random one @@ -42,11 +42,11 @@ std::string GenerateRandomizer(std::unordered_map return ""; } - Settings::seedString = seedString; - uint32_t seedHash = boost::hash_32{}(Settings::seedString); - Settings::seed = seedHash & 0xFFFFFFFF; + ctx->GetSettings()->SetSeedString(seedString); + uint32_t seedHash = boost::hash_32{}(ctx->GetSettings()->GetSeedString()); + ctx->GetSettings()->SetSeed(seedHash & 0xFFFFFFFF); - int ret = Playthrough::Playthrough_Init(Settings::seed, cvarSettings, excludedLocations, enabledTricks); + int ret = Playthrough::Playthrough_Init(ctx->GetSettings()->GetSeed(), cvarSettings, excludedLocations, enabledTricks); if (ret < 0) { if (ret == -1) { // Failed to generate after 5 tries printf("\n\nFailed to generate after 5 tries.\nPress B to go back to the menu.\nA different seed might be " @@ -60,21 +60,21 @@ std::string GenerateRandomizer(std::unordered_map } // Restore settings that were set to a specific value for vanilla logic - if (Settings::Logic.Is(LOGIC_VANILLA)) { - for (Option* setting : Settings::vanillaLogicDefaults) { + if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) { + for (Rando::Option* setting : ctx->GetSettings()->VanillaLogicDefaults) { setting->RestoreDelayedOption(); } - Settings::Keysanity.RestoreDelayedOption(); + ctx->GetOption(RSK_KEYSANITY).RestoreDelayedOption(); } std::ostringstream fileNameStream; - for (int i = 0; i < Settings::hashIconIndexes.size(); i++) { + for (int i = 0; i < ctx->hashIconIndexes.size(); i++) { if (i) { fileNameStream << '-'; } - if (Settings::hashIconIndexes[i] < 10) { + if (ctx->hashIconIndexes[i] < 10) { fileNameStream << '0'; } - fileNameStream << std::to_string(Settings::hashIconIndexes[i]); + fileNameStream << std::to_string(ctx->hashIconIndexes[i]); } std::string fileName = fileNameStream.str(); return "./Randomizer/" + fileName + ".json"; diff --git a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp index 4ae1c3b67..8dfa38d7e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp @@ -8,6 +8,8 @@ #include "random.hpp" #include "spoiler_log.hpp" #include "soh/Enhancements/randomizer/randomizerTypes.h" +#include +#include "../option.h" namespace Playthrough { @@ -23,30 +25,29 @@ int Playthrough_Init(uint32_t seed, std::unordered_mapHintReset(); Areas::AccessReset(); - Settings::UpdateSettings(cvarSettings, excludedLocations, enabledTricks); + ctx->GetSettings()->UpdateSettings(cvarSettings, excludedLocations, enabledTricks); // once the settings have been finalized turn them into a string for hashing std::string settingsStr; - for (Menu* menu : Settings::GetAllOptionMenus()) { + for (const Rando::OptionGroup& optionGroup : ctx->GetSettings()->GetOptionGroups()) { // don't go through non-menus - if (menu->mode != OPTION_SUB_MENU) { + if (optionGroup.GetContainsType() != Rando::OptionGroupType::SUBGROUP) { continue; } - for (size_t i = 0; i < menu->settingsList->size(); i++) { - Option* setting = menu->settingsList->at(i); - if (setting->IsCategory(OptionCategory::Setting)) { - settingsStr += setting->GetSelectedOptionText(); + for (Rando::Option* option : optionGroup.GetOptions()) { + if (option->IsCategory(Rando::OptionCategory::Setting)) { + settingsStr += option->GetSelectedOptionText(); } } } - uint32_t finalHash = boost::hash_32{}(std::to_string(Settings::seed) + settingsStr); + uint32_t finalHash = boost::hash_32{}(std::to_string(ctx->GetSettings()->GetSeed()) + settingsStr); Random_Init(finalHash); - Settings::hash = std::to_string(finalHash); + ctx->GetSettings()->SetHash(std::to_string(finalHash)); Logic::UpdateHelpers(); - if (Settings::Logic.Is(LOGIC_VANILLA)) { + if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) { VanillaFill(); // Just place items in their vanilla locations } else { // Fill locations with logic int ret = Fill(); @@ -58,7 +59,7 @@ int Playthrough_Init(uint32_t seed, std::unordered_map cvarSettings, std::set excludedLocations, std::set enabledTricks, int count /*= 1*/) { printf("\x1b[0;0HGENERATING %d SEEDS", count); + auto ctx = Rando::Context::GetInstance(); uint32_t repeatedSeed = 0; for (int i = 0; i < count; i++) { - Settings::seedString = std::to_string(rand() % 0xFFFFFFFF); - repeatedSeed = boost::hash_32{}(Settings::seedString); - Settings::seed = repeatedSeed % 0xFFFFFFFF; + ctx->GetSettings()->SetSeedString(std::to_string(rand() % 0xFFFFFFFF)); + repeatedSeed = boost::hash_32{}(ctx->GetSettings()->GetSeedString()); + ctx->GetSettings()->SetSeed(repeatedSeed % 0xFFFFFFFF); //CitraPrint("testing seed: " + std::to_string(Settings::seed)); ClearProgress(); - Playthrough_Init(Settings::seed, cvarSettings, excludedLocations, enabledTricks); + Playthrough_Init(ctx->GetSettings()->GetSeed(), cvarSettings, excludedLocations, enabledTricks); printf("\x1b[15;15HSeeds Generated: %d\n", i + 1); } diff --git a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp index 5b35a85ab..2c2ea3158 100644 --- a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp @@ -4,6 +4,7 @@ #include "../item_location.h" #include "location_access.hpp" #include "rando_main.hpp" +#include "../context.h" // #include #include #include @@ -17,9 +18,10 @@ void RandoMain::GenerateRando(std::unordered_map cvarS // CVarSetString("gLoadedPreset", settingsFileName.c_str()); std::string fileName = LUS::Context::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations, enabledTricks, seedString).c_str()); - CVarSetString("gSpoilerLog", fileName.c_str()); CVarSave(); CVarLoad(); - CVarSetInteger("gNewSeedGenerated", 1); + Rando::Context::GetInstance()->SetSeedGenerated(); + Rando::Context::GetInstance()->SetSpoilerLoaded(false); + Rando::Context::GetInstance()->SetPlandoLoaded(false); } \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp deleted file mode 100644 index f5d3e41b6..000000000 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ /dev/null @@ -1,2652 +0,0 @@ -#include "settings.hpp" - -#include "dungeon.hpp" -#include "fill.hpp" -#include "../context.h" -#include "../item_location.h" -#include "random.hpp" -#include "randomizer.hpp" -#include "trial.hpp" - -using namespace Dungeon; -using namespace Trial; - -namespace Settings { - uint32_t seed; - std::string hash; - std::string version = RANDOMIZER_VERSION "-" COMMIT_NUMBER; - std::array hashIconIndexes; - std::string seedString; - - bool skipChildZelda = false; - - std::vector NumOpts(int min, int max, int step = 1, std::string textBefore = {}, std::string textAfter = {}) { - std::vector options; - options.reserve((max - min) / step + 1); - for (int i = min; i <= max; i += step) { - options.push_back(textBefore + std::to_string(i) + textAfter); - } - return options; - } - - std::vector MultiVecOpts(std::vector> optionsVector) { - uint32_t totalSize = 0; - for (auto vector : optionsVector) { - totalSize += vector.size(); - } - std::vector options; - options.reserve(totalSize); - for (auto vector : optionsVector) { - for (auto op : vector) { - options.push_back(op); - } - } - return options; - } - - // Setting name, Options, Category (default: Setting),Default index (default: 0), Default hidden (default: false) - //Open Settings - Option RandomizeOpen = Option::Bool("Randomize Settings", {"No","Yes"}, OptionCategory::Toggle); - Option OpenForest = Option::U8 ("Forest", {"Closed", "Closed Deku", "Open"}, OptionCategory::Setting, OPENFOREST_CLOSED); - Option OpenKakariko = Option::U8 ("Kakariko Gate", {"Closed", "Open"}); - Option OpenDoorOfTime = Option::U8 ("Door of Time", {"Closed", "Song only", "Open"}); - Option ZorasFountain = Option::U8 ("Zora's Fountain", {"Closed", "Closed as child", "Open"}); - Option GerudoFortress = Option::U8 ("Gerudo Fortress", {"Normal", "Fast", "Open"}); - Option Bridge = Option::U8 ("Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, RAINBOWBRIDGE_VANILLA); - Option BridgeStoneCount = Option::U8 ("Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, 1, true); - Option BridgeMedallionCount= Option::U8 ("Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, 1, true); - Option BridgeRewardCount = Option::U8 ("Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, 1, true); - Option BridgeDungeonCount = Option::U8 ("Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, 1, true); - Option BridgeTokenCount = Option::U8 ("Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, 1, true); - Option BridgeRewardOptions = Option::U8 ("Bridge Reward Options", {"Standard Rewards", "Greg as Reward", "Greg as Wildcard"}); - Option RandomGanonsTrials = Option::Bool("Random Ganon's Trials", {"Off", "On"}, OptionCategory::Setting, ON); - Option GanonsTrialsCount = Option::U8 ("Trial Count", {NumOpts(0, 6)}, OptionCategory::Setting, 1, true); - std::vector