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 687f697c2..34aa8af15 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 939bc4ff1..b2a629bc8 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); @@ -852,7 +853,7 @@ void GenerateItemPool() { } } - if (BombchusInLogic) { + if (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) { AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS, 5); } else { AddItemToMainPool(RG_BOMBCHU_5); @@ -862,28 +863,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++) { @@ -893,15 +894,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); @@ -915,10 +916,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 { @@ -928,9 +929,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; } @@ -940,56 +941,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); @@ -997,36 +998,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); } @@ -1034,7 +1035,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); } @@ -1057,55 +1058,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; } @@ -1113,11 +1114,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); @@ -1129,7 +1130,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); } @@ -1140,10 +1141,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()); } @@ -1154,11 +1155,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) { @@ -1168,7 +1169,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); @@ -1178,54 +1179,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 cba524f62..c1bc935a7 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 74881c406..b758be53e 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 || (HasBossSoul(RG_KING_DODONGO_SOUL) && (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 6c8f1c17c..df3ddbbf0 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 240c35e67..285f759dc 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 c47bf63ba..52c4b378b 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 4c634135a..32bba0660 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 94aded196..addde6403 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 || (HasBossSoul(RG_BONGO_BONGO_SOUL) && - ((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 b0991705f..35efc3135 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 d41dc64c9..75255a4d4 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 04b8e71bc..38382c542 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 { @@ -440,29 +438,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))); @@ -505,7 +504,7 @@ namespace Logic { } } - uint8_t GetDifficultyValueFromString(Option& glitchOption) { + uint8_t GetDifficultyValueFromString(Rando::Option& glitchOption) { return 0; } @@ -522,11 +521,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 @@ -535,6 +535,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); @@ -553,7 +554,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); @@ -570,28 +571,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; @@ -604,34 +606,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; @@ -649,26 +651,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); - - 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(); + 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 = (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) { @@ -769,9 +770,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; @@ -897,7 +901,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; @@ -1018,7 +1022,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; @@ -1036,9 +1040,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; @@ -1070,7 +1074,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 8bb1f8a3f..000000000 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ /dev/null @@ -1,2654 +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