From 7522f31cc86effb624dabb9dab87ac5666c7b719 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Wed, 4 Mar 2026 00:44:56 +0000 Subject: [PATCH] Refactor DMC logic (#6294) Refactors Death Mountain Crater logic to work in a more straightforward, if verbose, applies Tunicless navigation consistently, and paves over some small oversights. As Child must be able to navigate DMC to some degree due to Child only checks, and logic should be consistent between Child and Adult, DMC no longer hard requires Tunic in any scenario. Instead checks and exits are split into regions, and each entrance has a "Fewer Tunic Requirements" heart count associated with it for each region which is then increased by 50% (rounding up) when FTR is off. This applies to both Child and Adult. --- soh/soh/Enhancements/randomizer/entrance.cpp | 38 +- .../Enhancements/randomizer/location_access.h | 1 + .../location_access/dungeons/fire_temple.cpp | 4 +- .../overworld/death_mountain_crater.cpp | 389 ++++++++++++++---- .../overworld/death_mountain_trail.cpp | 2 +- .../location_access/overworld/goron_city.cpp | 2 +- .../randomizer/location_access/root.cpp | 2 +- soh/soh/Enhancements/randomizer/logic.cpp | 14 + soh/soh/Enhancements/randomizer/logic.h | 3 + .../randomizer/randomizerEnums/LogicVal.h | 1 + .../randomizerEnums/RandomizerRegion.h | 30 +- soh/soh/Enhancements/randomizer/settings.cpp | 10 +- 12 files changed, 372 insertions(+), 124 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index e8f4073bb..f1532352f 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -263,8 +263,8 @@ void SetAllEntrancesData() { { EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU } }, { { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, ENTR_FOREST_TEMPLE_ENTRANCE }, { EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE } }, - { { EntranceType::Dungeon, RR_DMC_OUTSIDE_FIRE_TEMPLE, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE }, - { EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_OUTSIDE_FIRE_TEMPLE, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } }, + { { EntranceType::Dungeon, RR_DMC_TEMPLE_EXIT, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE }, + { EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_TEMPLE_EXIT, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } }, { { EntranceType::Dungeon, RR_LH_FROM_WATER_TEMPLE, RR_WATER_TEMPLE_ENTRYWAY, ENTR_WATER_TEMPLE_ENTRANCE }, { EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE } }, { { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, ENTR_SPIRIT_TEMPLE_ENTRANCE }, @@ -348,8 +348,8 @@ void SetAllEntrancesData() { // ENTR_POTION_SHOP_KAKARIKO_1 is an unused entrance index repurposed to differentiate between HC and OGC fairy fountain exits // (normally both use ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT) { EntranceType::Interior, RR_OGC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS_FROM_GREAT_FAIRY, ENTR_POTION_SHOP_KAKARIKO_1 } }, - { { EntranceType::Interior, RR_DMC_LOWER_NEARBY, RR_DMC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC }, - { EntranceType::Interior, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT } }, + { { EntranceType::Interior, RR_DMC_BLOCKED_EXIT, RR_DMC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC }, + { EntranceType::Interior, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_BLOCKED_ENTRY, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT } }, { { EntranceType::Interior, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT }, { EntranceType::Interior, RR_DMT_GREAT_FAIRY_FOUNTAIN, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT } }, { { EntranceType::Interior, RR_ZORAS_FOUNTAIN, RR_ZF_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF }, @@ -407,10 +407,10 @@ void SetAllEntrancesData() { { EntranceType::GrottoGrave, RR_ZR_FAIRY_GROTTO, RR_ZR_ATOP_LADDER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET) } }, { { EntranceType::GrottoGrave, RR_ZR_ATOP_LADDER, RR_ZR_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET) }, { EntranceType::GrottoGrave, RR_ZR_OPEN_GROTTO, RR_ZR_ATOP_LADDER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET) } }, - { { EntranceType::GrottoGrave, RR_DMC_LOWER_NEARBY, RR_DMC_HAMMER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET) }, - { EntranceType::GrottoGrave, RR_DMC_HAMMER_GROTTO, RR_DMC_LOWER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET) } }, - { { EntranceType::GrottoGrave, RR_DMC_UPPER_NEARBY, RR_DMC_UPPER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET) }, - { EntranceType::GrottoGrave, RR_DMC_UPPER_GROTTO, RR_DMC_UPPER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET) } }, + { { EntranceType::GrottoGrave, RR_DMC_POT_GROTTO_EXIT, RR_DMC_SCRUB_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET) }, + { EntranceType::GrottoGrave, RR_DMC_SCRUB_GROTTO, RR_DMC_POT_GROTTO_ENTRY, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET) } }, + { { EntranceType::GrottoGrave, RR_DMC_ROCK_GROTTO, RR_DMC_UPPER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET) }, + { EntranceType::GrottoGrave, RR_DMC_UPPER_GROTTO, RR_DMC_ROCKS_GROTTO_ENTRY, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET) } }, { { EntranceType::GrottoGrave, RR_GC_GROTTO_PLATFORM, RR_GC_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET) }, { EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET) } }, { { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET) }, @@ -518,10 +518,10 @@ void SetAllEntrancesData() { { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_KAK_BEHIND_GATE, ENTR_KAKARIKO_VILLAGE_GUARD_GATE } }, { { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_GORON_CITY, ENTR_GORON_CITY_UPPER_EXIT }, { EntranceType::Overworld, RR_GORON_CITY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT } }, - { { EntranceType::Overworld, RR_GC_DARUNIAS_CHAMBER, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT }, - { EntranceType::Overworld, RR_DMC_LOWER_NEARBY, RR_GC_DARUNIAS_CHAMBER, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT } }, - { { EntranceType::Overworld, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMC_UPPER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT }, - { EntranceType::Overworld, RR_DMC_UPPER_NEARBY, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT } }, + { { EntranceType::Overworld, RR_GC_DARUNIAS_CHAMBER, RR_DMC_POTS_ENTRY, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT }, + { EntranceType::Overworld, RR_DMC_POTS, RR_GC_DARUNIAS_CHAMBER, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT } }, + { { EntranceType::Overworld, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMC_UPPER_ENTRY, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT }, + { EntranceType::Overworld, RR_DMC_CRATE, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT } }, { { EntranceType::Overworld, RR_ZR_BEHIND_WATERFALL, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_ENTRANCE }, { EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_ZR_BEHIND_WATERFALL, ENTR_ZORAS_RIVER_WATERFALL_EXIT } }, { { EntranceType::Overworld, RR_ZD_BEHIND_KING_ZORA, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT }, @@ -542,7 +542,7 @@ void SetAllEntrancesData() { // Adult Spawn and prelude of light (normally they both use 0x5F4) { { EntranceType::WarpSong, RR_MINUET_OF_FOREST_WARP, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_WARP_PAD }, NO_RETURN_ENTRANCE }, - { { EntranceType::WarpSong, RR_BOLERO_OF_FIRE_WARP, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD }, + { { EntranceType::WarpSong, RR_BOLERO_OF_FIRE_WARP, RR_DMC_PAD_ENTRY, ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD }, NO_RETURN_ENTRANCE }, { { EntranceType::WarpSong, RR_SERENADE_OF_WATER_WARP, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WARP_PAD }, NO_RETURN_ENTRANCE }, @@ -581,7 +581,7 @@ void SetAllEntrancesData() { NO_RETURN_ENTRANCE }, { { EntranceType::BlueWarp, RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP }, NO_RETURN_ENTRANCE }, - { { EntranceType::BlueWarp, RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP }, + { { EntranceType::BlueWarp, RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_PAD_ENTRY, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP }, NO_RETURN_ENTRANCE }, { { EntranceType::BlueWarp, RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP }, NO_RETURN_ENTRANCE }, @@ -1192,7 +1192,7 @@ int EntranceShuffler::ShuffleAllEntrances() { mCurNumRandomizedEntrances = 0; std::map priorityEntranceTable = { - { "Bolero", { { RR_DMC_CENTRAL_LOCAL }, { EntranceType::OwlDrop, EntranceType::WarpSong } } }, + { "Bolero", { { RR_DMC_PAD_ENTRY }, { EntranceType::OwlDrop, EntranceType::WarpSong } } }, { "Nocturne", { { RR_GRAVEYARD_WARP_PAD_REGION }, { EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong } } }, @@ -1523,7 +1523,7 @@ int EntranceShuffler::ShuffleAllEntrances() { { EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY), GetEntrance(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW) }, { EntranceNameByRegions(RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY), - GetEntrance(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_OUTSIDE_FIRE_TEMPLE) }, + GetEntrance(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_TEMPLE_EXIT) }, { EntranceNameByRegions(RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY), GetEntrance(RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE) }, { EntranceNameByRegions(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY), @@ -1545,8 +1545,8 @@ int EntranceShuffler::ShuffleAllEntrances() { GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN) }, { EntranceNameByRegions(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW), GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW) }, - { EntranceNameByRegions(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_OUTSIDE_FIRE_TEMPLE), - GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL) }, + { EntranceNameByRegions(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_TEMPLE_EXIT), + GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_PAD_ENTRY) }, { EntranceNameByRegions(RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE), GetEntrance(RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA) }, { EntranceNameByRegions(RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE), @@ -1567,7 +1567,7 @@ int EntranceShuffler::ShuffleAllEntrances() { GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_EXIT) }, { GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW), GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY) }, - { GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL), + { GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_PAD_ENTRY), GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY) }, { GetEntrance(RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA), GetEntrance(RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY) }, diff --git a/soh/soh/Enhancements/randomizer/location_access.h b/soh/soh/Enhancements/randomizer/location_access.h index edd35d3ab..d80a10ebe 100644 --- a/soh/soh/Enhancements/randomizer/location_access.h +++ b/soh/soh/Enhancements/randomizer/location_access.h @@ -265,6 +265,7 @@ bool SpiritShared( ConditionFn otherCondition = [] { return false; }, RandomizerRegion thirdRegion = RR_NONE, ConditionFn thirdCondition = [] { return false; }); bool SpiritCertainAccess(RandomizerRegion region); +bool DMCPadToPots(); bool CanPlantBean(const RandomizerRegion region, RandomizerGet bean); bool BothAges(const RandomizerRegion region); bool ChildCanAccess(const RandomizerRegion region); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp index b41214216..8a5fdd08c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -11,7 +11,7 @@ void RegionTable_Init_FireTemple() { //Exits ENTRANCE(RR_FIRE_TEMPLE_FOYER, ctx->GetDungeon(FIRE_TEMPLE)->IsVanilla()), ENTRANCE(RR_FIRE_TEMPLE_MQ_FOYER_LOWER, ctx->GetDungeon(FIRE_TEMPLE)->IsMQ()), - ENTRANCE(RR_DMC_OUTSIDE_FIRE_TEMPLE, true), + ENTRANCE(RR_DMC_TEMPLE_EXIT, true), }); #pragma region Vanilla @@ -1069,7 +1069,7 @@ void RegionTable_Init_FireTemple() { }, { // Exits ENTRANCE(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, false), - ENTRANCE(RR_DMC_CENTRAL_LOCAL, logic->Get(LOGIC_FIRE_TEMPLE_CLEAR), false), + ENTRANCE(RR_DMC_PAD_ENTRY, logic->Get(LOGIC_FIRE_TEMPLE_CLEAR), false), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp index f1281e27b..e332e238b 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp @@ -3,46 +3,284 @@ using namespace Rando; +/* Notes for calculating timers: + - RT_DMC_BOLERO_JUMP takes about 16 seconds to perform. + - RT_DMC_BOULDER_SKIP assumes a setup that takes 14 seconds to fully execute + - Spawning and killing the bean skull takes around 10 seconds, as does getting the bean sprout, + as does getting the rupees on the near plank platform but as it's child only does not stack with + RT_DMC_BOLERO_JUMP or RT_DMC_BOULDER_SKIP + - Whatever number of hearts is used for Fewer Tunic Requirements, the default time check is that +50%, rounded up. + This applies to both adult and child + - All child only checks must be possible with 3 hearts, or minimal item pool breaks. + - I have Pot Grotto separate but not Rocks Grotto because it needs a different amount of hearts to reach blocked + exit, which will matter with mods RANDOTODO: when randomised entrances can be in more than 1 region, make it so the + player can always turn around and go back the way they came +*/ void RegionTable_Init_DeathMountainCrater() { // clang-format off - areaTable[RR_DMC_UPPER_NEARBY] = Region("DMC Upper Nearby", SCENE_DEATH_MOUNTAIN_CRATER, {}, {}, { + areaTable[RR_DMC_UPPER_ENTRY] = Region("DMC Upper Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { + //Locations + LOCATION(RC_DMC_WALL_FREESTANDING_POH, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), + LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS)) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->DMCPotsToPad() && logic->DMCUpperToPots() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + }, { //Exits - ENTRANCE(RR_DMC_UPPER_LOCAL, logic->FireTimer() >= 48), - ENTRANCE(RR_DEATH_MOUNTAIN_SUMMIT, true), - ENTRANCE(RR_DMC_UPPER_GROTTO, AnyAgeTime([]{return logic->BlastOrSmash() && (logic->FireTimer() >= 8 || logic->Hearts() >= 3);})) + ENTRANCE(RR_DMC_CRATE, true), + ENTRANCE(RR_DMC_ROCK_GROTTO, logic->FireTimer() >= 8 || logic->Hearts() >= 2), + ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), + ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 16 || logic->Hearts() >= 3), + ENTRANCE(RR_DMC_BLOCKED_EXIT, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->DMCUpperToPots()) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + ENTRANCE(RR_DMC_POTS, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + ENTRANCE(RR_DMC_POT_GROTTO_EXIT, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || + (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->TakeDamage()), + ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), }); - areaTable[RR_DMC_UPPER_LOCAL] = Region("DMC Upper Local", SCENE_DEATH_MOUNTAIN_CRATER, { + areaTable[RR_DMC_ROCKS_GROTTO_ENTRY] = Region("DMC Rocks Grotto Entry", SCENE_DEATH_MOUNTAIN_CRATER, { + }, { + //Locations + LOCATION(RC_DMC_WALL_FREESTANDING_POH, logic->FireTimer() >= 8 || logic->Hearts() >= 2), + LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS)) || + (logic->IsAdult && (logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCPotsToPad() && logic->DMCUpperToPots() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + }, { + //Exits + ENTRANCE(RR_DMC_CRATE, logic->FireTimer() >= 8 || logic->Hearts() >= 2), + ENTRANCE(RR_DMC_ROCK_GROTTO, true), + ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), + ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 16 || logic->Hearts() >= 3), + ENTRANCE(RR_DMC_BLOCKED_EXIT, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + ENTRANCE(RR_DMC_POTS, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCUpperToPots()) || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + ENTRANCE(RR_DMC_POT_GROTTO_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCUpperToPots()) || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCUpperToPots() && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || + (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->TakeDamage()), + ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && logic->DMCUpperToPots() && logic->DMCPotsToPad()) || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow() && logic->TakeDamage())), + }); + + areaTable[RR_DMC_BLOCKED_ENTRY] = Region("DMC Blocked Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { + //Locations + LOCATION(RC_DMC_WALL_FREESTANDING_POH, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))) || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, ((logic->FireTimer() >= 16 || logic->Hearts() >= 3) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS)) || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + }, { + //Exits + ENTRANCE(RR_DMC_CRATE, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_DMC_ROCK_GROTTO, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 8 || logic->Hearts() >= 2), + ENTRANCE(RR_DMC_BLOCKED_EXIT, true), + ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2), + ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 16 || logic->Hearts() >= 3), + ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && (logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && (logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad()) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && (logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + }); + + areaTable[RR_DMC_POTS_ENTRY] = Region("DMC Pots Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { + //Locations + LOCATION(RC_DMC_WALL_FREESTANDING_POH, (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, ((logic->FireTimer() >= 8 || logic->Hearts() >= 2) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS)) || + (logic->IsAdult && (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + }, { + //Exits + ENTRANCE(RR_DMC_CRATE, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_DMC_ROCK_GROTTO, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 16 || logic->Hearts() >= 3), + ENTRANCE(RR_DMC_BLOCKED_EXIT, logic->FireTimer() >= 8 || logic->Hearts() >= 2), + ENTRANCE(RR_DMC_POTS, true), + ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 8 || logic->Hearts() >= 2), + ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad()) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && (logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && (logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && (logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + }); + + areaTable[RR_DMC_POT_GROTTO_ENTRY] = Region("DMC Pot Grotto Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { + //Locations + LOCATION(RC_DMC_WALL_FREESTANDING_POH, (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) || + (logic->IsAdult && (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + }, { + //Exits + ENTRANCE(RR_DMC_CRATE, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_DMC_ROCK_GROTTO, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_DMC_SCRUB, logic->FireTimer() >= 24 || logic->Hearts() >= 5), + ENTRANCE(RR_DMC_BLOCKED_EXIT, logic->FireTimer() >= 16 || logic->Hearts() >= 3), + ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2), + ENTRANCE(RR_DMC_POT_GROTTO_EXIT, true), + ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad()) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && (logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || + ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->TakeDamage() && (logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && (logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + }); + + areaTable[RR_DMC_PAD_ENTRY] = Region("DMC Pad Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { + //Locations + LOCATION(RC_DMC_WALL_FREESTANDING_POH, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_CLIMB)) && logic->DMCPadToPots()) || + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->DMCPadToPots() || + (logic->IsAdult && (logic->FireTimer() >= 8 || logic->Hearts() >= 2) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + }, { + //Exits + ENTRANCE(RR_DMC_CRATE, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_CLIMB)) && logic->DMCPadToPots()) || + ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + ENTRANCE(RR_DMC_ROCK_GROTTO, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_CLIMB)) && logic->DMCPadToPots()) || + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_CLIMB)) && logic->DMCPadToPots() || + ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + ENTRANCE(RR_DMC_SCRUB, (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->DMCPadToPots() || + (logic->IsAdult && (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + ENTRANCE(RR_DMC_BLOCKED_EXIT, (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->DMCPadToPots() || + (logic->IsAdult && (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + ENTRANCE(RR_DMC_POTS, (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->DMCPadToPots() || + (logic->IsAdult && (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + ENTRANCE(RR_DMC_POT_GROTTO_EXIT, (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->DMCPadToPots() || + ((logic->IsAdult && logic->FireTimer() >= 24 || logic->Hearts() >= 5) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))), + ENTRANCE(RR_DMC_CENTRAL, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), + ENTRANCE(RR_DMC_FAR_PLATFORM, ((logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_CLIMB)) && logic->DMCPadToPots()) || + ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 24 || logic->Hearts() >= 5) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))|| + (logic->IsAdult && (logic->FireTimer() >= 16 || logic->Hearts() >= 3) && logic->ReachDistantScarecrow())), + ENTRANCE(RR_DMC_TEMPLE_EXIT, (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), + }); + + areaTable[RR_DMC_TEMPLE_ENTRY] = Region("DMC Temple Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { + //Locations + LOCATION(RC_DMC_WALL_FREESTANDING_POH, logic->HasItem(RG_CLIMB) && + (((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCPadToPots()) || + ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), + LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, logic->HasItem(RG_CLIMB) && + ((logic->FireTimer() >= 56 || logic->Hearts() >= 11) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->DMCPadToPots() || + (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), + }, { + //Exits + ENTRANCE(RR_DMC_CRATE, logic->HasItem(RG_CLIMB) && + (((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCPadToPots()) || + ((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), + ENTRANCE(RR_DMC_ROCK_GROTTO, logic->HasItem(RG_CLIMB) && + (((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && logic->DMCPadToPots()) || + ((logic->FireTimer() >= 64 || logic->Hearts() >= 12) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), + ENTRANCE(RR_DMC_CRACKED_WALL, logic->HasItem(RG_CLIMB) && + (((logic->FireTimer() >= 80 || logic->Hearts() >= 15) && logic->DMCPadToPots()) || + ((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), + ENTRANCE(RR_DMC_SCRUB, logic->HasItem(RG_CLIMB) && + (((logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->DMCPadToPots()) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), + ENTRANCE(RR_DMC_BLOCKED_EXIT, logic->HasItem(RG_CLIMB) && + (((logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->DMCPadToPots()) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), + ENTRANCE(RR_DMC_POTS, logic->HasItem(RG_CLIMB) && + (((logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPadToPots()) || + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), + ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->HasItem(RG_CLIMB) && + (((logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPadToPots()) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)))), + ENTRANCE(RR_DMC_CENTRAL, logic->HasItem(RG_CLIMB) && (logic->FireTimer() >= 48 || logic->Hearts() >= 9)), + ENTRANCE(RR_DMC_FAR_PLATFORM, logic->HasItem(RG_CLIMB) && + (((logic->FireTimer() >= 88 || logic->Hearts() >= 3) && logic->TakeDamage() && (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_CLIMB)) && logic->DMCPadToPots()) || + ((logic->FireTimer() >= 72 || logic->Hearts() >= 14) && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_LONGSHOT)) || + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL))|| + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow()))), + ENTRANCE(RR_DMC_TEMPLE_EXIT, true), + }); + + areaTable[RR_DMC_CRATE] = Region("DMC Crate", SCENE_DEATH_MOUNTAIN_CRATER, {}, { + //Locations + LOCATION(RC_DMC_GS_CRATE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA) && logic->CanBreakCrates()), + LOCATION(RC_DMC_CRATE, logic->IsChild && logic->CanBreakCrates()), + }, { + //Exits + ENTRANCE(RR_DEATH_MOUNTAIN_SUMMIT, true), + }); + + areaTable[RR_DMC_ROCK_GROTTO] = Region("DMC Rock Grotto", SCENE_DEATH_MOUNTAIN_CRATER, {}, {}, { + //Exits + ENTRANCE(RR_DMC_UPPER_GROTTO, AnyAgeTime([]{return logic->BlastOrSmash();})), + }); + + areaTable[RR_DMC_CRACKED_WALL] = Region("DMC Cracked Wall", SCENE_DEATH_MOUNTAIN_CRATER, { //Events - EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->HasExplosives() && logic->CallGossipFairyExceptSuns() && (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), + EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->HasExplosives() && logic->CallGossipFairyExceptSuns()), }, { //Locations - LOCATION(RC_DMC_WALL_FREESTANDING_POH, logic->FireTimer() >= 16 || logic->Hearts() >= 3), - LOCATION(RC_DMC_GS_CRATE, (logic->FireTimer() >= 8 || logic->Hearts() >= 3) && logic->IsChild && logic->CanAttack() && logic->CanBreakCrates()), - LOCATION(RC_DMC_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns() && logic->HasExplosives() && (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS) && logic->HasExplosives() && (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_GOSSIP_STONE, logic->HasExplosives() && (logic->FireTimer() >= 16 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_CRATE, (logic->FireTimer() >= 8 || logic->Hearts() >= 3) && logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_DMC_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns() && logic->HasExplosives()), + LOCATION(RC_DMC_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS) && logic->HasExplosives()), + LOCATION(RC_DMC_GOSSIP_STONE, true && logic->HasExplosives()), + }, {}); + areaTable[RR_DMC_SCRUB] = Region("DMC Scrub", SCENE_DEATH_MOUNTAIN_CRATER, { + //Events + EVENT_ACCESS(LOGIC_DMC_BOULDER, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && ctx->GetTrickOption(RT_DMC_BOULDER_JS)), }, { - //Exits - ENTRANCE(RR_DMC_UPPER_NEARBY, true), - ENTRANCE(RR_DMC_LADDER_AREA_NEARBY, logic->FireTimer() >= 16 || logic->Hearts() >= 3), - ENTRANCE(RR_DMC_CENTRAL_NEARBY, logic->IsAdult && logic->CanUse(RG_GORON_TUNIC) && logic->ReachDistantScarecrow() && ((logic->EffectiveHealth() > 2) || (logic->CanUse(RG_BOTTLE_WITH_FAIRY) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)) || logic->CanUse(RG_NAYRUS_LOVE))), - ENTRANCE(RR_DMC_LOWER_NEARBY, false), - ENTRANCE(RR_DMC_DISTANT_PLATFORM, (logic->FireTimer() >= 48 && logic->Hearts() >= 2) || logic->Hearts() >= 3), - }); - - areaTable[RR_DMC_LADDER_AREA_NEARBY] = Region("DMC Ladder Region Nearby", SCENE_DEATH_MOUNTAIN_CRATER, {}, { //Locations LOCATION(RC_DMC_DEKU_SCRUB, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()), - }, { + }, {}); + + areaTable[RR_DMC_BLOCKED_EXIT] = Region("DMC Blocked Exit", SCENE_DEATH_MOUNTAIN_CRATER, { + //Events + //All boulders here are only a perm flag for adult. + EVENT_ACCESS(LOGIC_DMC_BOULDER, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + }, {}, { //Exits - ENTRANCE(RR_DMC_UPPER_NEARBY, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->Hearts() >= 3), - ENTRANCE(RR_DMC_LOWER_NEARBY, logic->Hearts() >= 3 && (logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DMC_BOULDER_JS) && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)) || (ctx->GetTrickOption(RT_DMC_BOULDER_SKIP) && logic->IsAdult))), + ENTRANCE(RR_DMC_GREAT_FAIRY_FOUNTAIN, logic->CanUse(RG_MEGATON_HAMMER)), }); - areaTable[RR_DMC_LOWER_NEARBY] = Region("DMC Lower Nearby", SCENE_DEATH_MOUNTAIN_CRATER, {}, { + areaTable[RR_DMC_POTS] = Region("DMC Pots", SCENE_DEATH_MOUNTAIN_CRATER, {}, { // Locations LOCATION(RC_DMC_NEAR_GC_POT_1, logic->CanBreakPots()), LOCATION(RC_DMC_NEAR_GC_POT_2, logic->CanBreakPots()), @@ -50,53 +288,50 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_DMC_NEAR_GC_POT_4, logic->CanBreakPots()), }, { //Exits - ENTRANCE(RR_DMC_LOWER_LOCAL, logic->FireTimer() >= 48), - ENTRANCE(RR_GC_DARUNIAS_CHAMBER, true), - ENTRANCE(RR_DMC_GREAT_FAIRY_FOUNTAIN, logic->CanUse(RG_MEGATON_HAMMER)), - ENTRANCE(RR_DMC_HAMMER_GROTTO, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + ENTRANCE(RR_GC_DARUNIAS_CHAMBER, true), }); - - areaTable[RR_DMC_LOWER_LOCAL] = Region("DMC Lower Local", SCENE_DEATH_MOUNTAIN_CRATER, {}, {}, { + + areaTable[RR_DMC_POT_GROTTO_EXIT] = Region("DMC Pot Grotto Exit", SCENE_DEATH_MOUNTAIN_CRATER, {}, {}, { //Exits - ENTRANCE(RR_DMC_LOWER_NEARBY, true), - ENTRANCE(RR_DMC_LADDER_AREA_NEARBY, logic->FireTimer() >= 8 || logic->Hearts() >= 3), - ENTRANCE(RR_DMC_CENTRAL_NEARBY, (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - ENTRANCE(RR_DMC_CENTRAL_LOCAL, (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanShield() && ctx->GetTrickOption(RT_DMC_BOLERO_JUMP))) && logic->FireTimer() >= 24), + //Perm flag only as Adult + ENTRANCE(RR_DMC_SCRUB_GROTTO, logic->CanUse(RG_MEGATON_HAMMER)), }); - areaTable[RR_DMC_CENTRAL_NEARBY] = Region("DMC Central Nearby", SCENE_DEATH_MOUNTAIN_CRATER, {}, { - //Locations - LOCATION(RC_DMC_VOLCANO_FREESTANDING_POH, logic->IsAdult && logic->Hearts() >= 3 && (CanPlantBean(RR_DMC_CENTRAL_LOCAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) || (ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS)))), - LOCATION(RC_SHEIK_IN_CRATER, logic->IsAdult && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - }, { - //Exits - ENTRANCE(RR_DMC_CENTRAL_LOCAL, logic->FireTimer() >= 48), - }); - - areaTable[RR_DMC_CENTRAL_LOCAL] = Region("DMC Central Local", SCENE_DEATH_MOUNTAIN_CRATER, { + areaTable[RR_DMC_CENTRAL] = Region("DMC Central", SCENE_DEATH_MOUNTAIN_CRATER, { //Events - EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), + EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), }, { //Locations - LOCATION(RC_DMC_GS_BEAN_PATCH, (logic->FireTimer() >= 8 || logic->Hearts() >= 3) && logic->CanSpawnSoilSkull(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanAttack()), + LOCATION(RC_SHEIK_IN_CRATER, logic->IsAdult), + LOCATION(RC_DMC_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanKillEnemy(RE_GOLD_SKULLTULA)), LOCATION(RC_DMC_NEAR_PLATFORM_RED_RUPEE, logic->IsChild), - LOCATION(RC_DMC_MIDDLE_PLATFORM_RED_RUPEE, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_1, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_2, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_3, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_4, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_5, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_6, logic->IsChild && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), - }, { + LOCATION(RC_DMC_MIDDLE_PLATFORM_RED_RUPEE, logic->IsChild), + LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_1, logic->IsChild), + LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_2, logic->IsChild), + LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_3, logic->IsChild), + LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_4, logic->IsChild), + LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_5, logic->IsChild), + LOCATION(RC_DMC_MIDDLE_PLATFORM_BLUE_RUPEE_6, logic->IsChild), + LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + }, {}); + + + areaTable[RR_DMC_FAR_PLATFORM] = Region("DMC Far Platform", SCENE_DEATH_MOUNTAIN_CRATER, {}, { + //Locations + LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_1, logic->IsAdult), + LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_2, logic->IsAdult), + LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_3, logic->IsAdult), + LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_4, logic->IsAdult), + LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_5, logic->IsAdult), + LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_6, logic->IsAdult), + LOCATION(RC_DMC_DISTANT_PLATFORM_RED_RUPEE, logic->IsAdult), + }, {}); + + areaTable[RR_DMC_TEMPLE_EXIT] = Region("DMC Temple Exit", SCENE_DEATH_MOUNTAIN_CRATER, {}, {}, { //Exits - ENTRANCE(RR_DMC_CENTRAL_NEARBY, true), - ENTRANCE(RR_DMC_LOWER_NEARBY, (logic->IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || (logic->CanUse(RG_HOVER_BOOTS) && (logic->IsAdult || logic->HasItem(RG_CLIMB))) || logic->CanUse(RG_HOOKSHOT)), - ENTRANCE(RR_DMC_UPPER_NEARBY, logic->IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)), - ENTRANCE(RR_DMC_OUTSIDE_FIRE_TEMPLE, (logic->IsChild && logic->Hearts() >= 3 && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)) || (logic->IsAdult && logic->FireTimer() >= 24)), - ENTRANCE(RR_DMC_DISTANT_PLATFORM, logic->FireTimer() >= 48 && logic->IsAdult && logic->ReachDistantScarecrow()), + ENTRANCE(RR_FIRE_TEMPLE_ENTRYWAY, true), }); areaTable[RR_DMC_GREAT_FAIRY_FOUNTAIN] = Region("DMC Great Fairy Fountain", SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, {}, { @@ -104,7 +339,7 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_DMC_GREAT_FAIRY_REWARD, logic->CanUse(RG_ZELDAS_LULLABY)), }, { //Exits - ENTRANCE(RR_DMC_LOWER_LOCAL, true), + ENTRANCE(RR_DMC_BLOCKED_ENTRY, true), }); areaTable[RR_DMC_UPPER_GROTTO] = Region("DMC Upper Grotto", SCENE_GROTTOS, grottoEvents, { @@ -122,10 +357,10 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_DMC_UPPER_GROTTO_GRASS_4, logic->CanCutShrubs()), }, { //Exits - ENTRANCE(RR_DMC_UPPER_LOCAL, true), + ENTRANCE(RR_DMC_ROCKS_GROTTO_ENTRY, true), }); - areaTable[RR_DMC_HAMMER_GROTTO] = Region("DMC Hammer Grotto", SCENE_GROTTOS, {}, { + areaTable[RR_DMC_SCRUB_GROTTO] = Region("DMC Scrub Grotto", SCENE_GROTTOS, {}, { //Locations LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()), LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()), @@ -133,27 +368,7 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_DMC_HAMMER_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()), }, { //Exits - ENTRANCE(RR_DMC_LOWER_LOCAL, true), - }); - - areaTable[RR_DMC_DISTANT_PLATFORM] = Region("DMC Distant Platform", SCENE_DEATH_MOUNTAIN_CRATER, {}, { - //Locations - LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_1, logic->IsAdult), - LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_2, logic->IsAdult), - LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_3, logic->IsAdult), - LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_4, logic->IsAdult), - LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_5, logic->IsAdult), - LOCATION(RC_DMC_DISTANT_PLATFORM_GREEN_RUPEE_6, logic->IsAdult), - LOCATION(RC_DMC_DISTANT_PLATFORM_RED_RUPEE, logic->IsAdult), - }, { - //Exits - ENTRANCE(RR_DMC_CENTRAL_LOCAL, logic->FireTimer() >= 48 && logic->IsAdult && logic->ReachDistantScarecrow()), - }); - - areaTable[RR_DMC_OUTSIDE_FIRE_TEMPLE] = Region("DMC Outside Fire Temple", SCENE_DEATH_MOUNTAIN_CRATER, {}, {}, { - //Exits - ENTRANCE(RR_FIRE_TEMPLE_ENTRYWAY, true), - ENTRANCE(RR_DMC_CENTRAL_LOCAL, logic->FireTimer() >= 48 && logic->HasItem(RG_CLIMB)), + ENTRANCE(RR_DMC_POT_GROTTO_ENTRY, true), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp index fcf69ff1a..308bf031b 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp @@ -57,7 +57,7 @@ void RegionTable_Init_DeathMountainTrail() { }, { //Exits ENTRANCE(RR_DEATH_MOUNTAIN_ROCKFALL, true), - ENTRANCE(RR_DMC_UPPER_LOCAL, true), + ENTRANCE(RR_DMC_UPPER_ENTRY, true), ENTRANCE(RR_DMT_OWL_FLIGHT, logic->IsChild && (logic->HasItem(RG_SPEAK_DEKU) || logic->HasItem(RG_SPEAK_GERUDO) || logic->HasItem(RG_SPEAK_GORON) || logic->HasItem(RG_SPEAK_HYLIAN) || logic->HasItem(RG_SPEAK_ZORA))), ENTRANCE(RR_DMT_GREAT_FAIRY_FOUNTAIN, AnyAgeTime([]{return logic->BlastOrSmash();})), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp index e39dac9e6..e1995b0ce 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp @@ -82,7 +82,7 @@ void RegionTable_Init_GoronCity() { }, { //Exits ENTRANCE(RR_GORON_CITY, true), - ENTRANCE(RR_DMC_LOWER_LOCAL, logic->IsAdult && logic->HasItem(RG_POWER_BRACELET)), + ENTRANCE(RR_DMC_POTS_ENTRY, logic->IsAdult && logic->HasItem(RG_POWER_BRACELET)), }); areaTable[RR_GC_GROTTO_PLATFORM] = Region("GC Grotto Platform", SCENE_GORON_CITY, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/root.cpp b/soh/soh/Enhancements/randomizer/location_access/root.cpp index 5eef67215..4100ce875 100644 --- a/soh/soh/Enhancements/randomizer/location_access/root.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/root.cpp @@ -57,7 +57,7 @@ void RegionTable_Init_Root() { areaTable[RR_BOLERO_OF_FIRE_WARP] = Region("Bolero of Fire Warp", SCENE_ID_MAX, TIME_DOESNT_PASS, {RA_LINKS_POCKET}, {}, {}, { //Exits - ENTRANCE(RR_DMC_CENTRAL_LOCAL, true), + ENTRANCE(RR_DMC_PAD_ENTRY, true), }); areaTable[RR_SERENADE_OF_WATER_WARP] = Region("Serenade of Water Warp", SCENE_ID_MAX, TIME_DOESNT_PASS, {RA_LINKS_POCKET}, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 1e90099dd..7cf37df97 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -2562,6 +2562,20 @@ bool Logic::IsReverseAccessPossible() { (ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES)))); } +bool Logic::DMCUpperToPots() { + return CanUse(RG_HOVER_BOOTS) || (IsAdult && ((Get(LOGIC_DMC_BOULDER)) || + (ctx->GetTrickOption(RT_DMC_BOULDER_SKIP) /* && CanUse(RG_ROLL)*/))); +} + +bool Logic::DMCPotsToPad() { + return (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT) || + (IsAdult && CanShield() && ctx->GetTrickOption(RT_DMC_BOLERO_JUMP) && CanUse(RG_POWER_BRACELET))); +} + +bool Logic::DMCPadToPots() { + return ((CanUse(RG_HOVER_BOOTS) && (IsAdult || (HasItem(RG_CLIMB) /*&& CanUse(RG_ROLL)*/))) || CanUse(RG_HOOKSHOT)); +} + bool Logic::SpiritExplosiveKeyLogic() { return SmallKeys(SCENE_SPIRIT_TEMPLE, HasExplosives() ? 1 : 2); } diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index c5f9273a7..ec338b1a3 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -153,6 +153,9 @@ class Logic { static std::map RandoGetToEquipFlag; static std::map RandoGetToRandInf; bool IsReverseAccessPossible(); + bool DMCUpperToPots(); + bool DMCPotsToPad(); + bool DMCPadToPots(); bool SpiritEastToSwitch(); bool SpiritWestToSkull(); bool SpiritSunBlockSouthLedge(); diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h b/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h index 7c97e05ce..fc35b4bca 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h @@ -220,6 +220,7 @@ RANDO_ENUM_ITEM(LOGIC_GORON_CITY_CHILD_FIRE) RANDO_ENUM_ITEM(LOGIC_GORON_CITY_WOODS_WARP_OPEN) RANDO_ENUM_ITEM(LOGIC_GORON_CITY_DARUNIAS_DOOR_OPEN_CHILD) RANDO_ENUM_ITEM(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT) +RANDO_ENUM_ITEM(LOGIC_DMC_BOULDER) RANDO_ENUM_ITEM(LOGIC_DEKU_TREE_1F_BROKE_WEB) RANDO_ENUM_ITEM(LOGIC_DEKU_TREE_B1_BROKE_WEB) RANDO_ENUM_ITEM(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h index fdcfd3c67..32dfc295e 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h @@ -197,18 +197,26 @@ RANDO_ENUM_ITEM(RR_GC_DARUNIAS_CHAMBER) RANDO_ENUM_ITEM(RR_GC_GROTTO_PLATFORM) RANDO_ENUM_ITEM(RR_GC_SHOP) RANDO_ENUM_ITEM(RR_GC_GROTTO) -RANDO_ENUM_ITEM(RR_DMC_UPPER_LOCAL) -RANDO_ENUM_ITEM(RR_DMC_CENTRAL_LOCAL) -RANDO_ENUM_ITEM(RR_DMC_LOWER_LOCAL) -RANDO_ENUM_ITEM(RR_DMC_LOWER_NEARBY) -RANDO_ENUM_ITEM(RR_DMC_UPPER_NEARBY) -RANDO_ENUM_ITEM(RR_DMC_CENTRAL_NEARBY) -RANDO_ENUM_ITEM(RR_DMC_LADDER_AREA_NEARBY) -RANDO_ENUM_ITEM(RR_DMC_UPPER_GROTTO) -RANDO_ENUM_ITEM(RR_DMC_HAMMER_GROTTO) +RANDO_ENUM_ITEM(RR_DMC_UPPER_ENTRY) +RANDO_ENUM_ITEM(RR_DMC_ROCKS_GROTTO_ENTRY) +RANDO_ENUM_ITEM(RR_DMC_CRACKED_WALL) +RANDO_ENUM_ITEM(RR_DMC_POTS_ENTRY) +RANDO_ENUM_ITEM(RR_DMC_BLOCKED_ENTRY) +RANDO_ENUM_ITEM(RR_DMC_POT_GROTTO_ENTRY) +RANDO_ENUM_ITEM(RR_DMC_PAD_ENTRY) +RANDO_ENUM_ITEM(RR_DMC_TEMPLE_ENTRY) +RANDO_ENUM_ITEM(RR_DMC_CRATE) +RANDO_ENUM_ITEM(RR_DMC_ROCK_GROTTO) +RANDO_ENUM_ITEM(RR_DMC_SCRUB) +RANDO_ENUM_ITEM(RR_DMC_POTS) +RANDO_ENUM_ITEM(RR_DMC_CENTRAL) +RANDO_ENUM_ITEM(RR_DMC_FAR_PLATFORM) +RANDO_ENUM_ITEM(RR_DMC_BLOCKED_EXIT) +RANDO_ENUM_ITEM(RR_DMC_POT_GROTTO_EXIT) +RANDO_ENUM_ITEM(RR_DMC_TEMPLE_EXIT) RANDO_ENUM_ITEM(RR_DMC_GREAT_FAIRY_FOUNTAIN) -RANDO_ENUM_ITEM(RR_DMC_DISTANT_PLATFORM) -RANDO_ENUM_ITEM(RR_DMC_OUTSIDE_FIRE_TEMPLE) +RANDO_ENUM_ITEM(RR_DMC_UPPER_GROTTO) +RANDO_ENUM_ITEM(RR_DMC_SCRUB_GROTTO) RANDO_ENUM_ITEM(RR_ZR_FRONT) RANDO_ENUM_ITEM(RR_ZORAS_RIVER) RANDO_ENUM_ITEM(RR_ZR_ATOP_LADDER) diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 1ea4568af..cebca12a5 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1413,8 +1413,14 @@ void Settings::CreateOptions() { OPT_TRICK(RT_GROTTOS_WITHOUT_AGONY, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "Hidden Grottos without Stone of Agony", "NoSoA", "Allows entering hidden grottos without the Stone of Agony."); - OPT_TRICK(RT_FEWER_TUNIC_REQUIREMENTS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::INTERMEDIATE }, - "Fewer Tunic Requirements", "FTR", "Logic may require getting through areas with timers without tunics."); + OPT_TRICK( + RT_FEWER_TUNIC_REQUIREMENTS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::INTERMEDIATE }, "Fewer Tunic Requirements", + "FTR", + "Normally the only hot area logic expects you to navigate without a Goron Tunic is Death Mountain Crater\n" + "and you are not expected to navigate underwater sections without a Zora Tunic.\n\n" + "With this trick you are expected to do any underwater area except Central Pillar,\n" + "any hot area except Volvagia and the Block lift room in Fire Temple\n" + "and the health needed to logically navigate Crater is decreased."); OPT_TRICK(RT_UNINTUITIVE_JUMPS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "Unintuitive Jumps", "UnJmp", "Many ledges can be overcome with particular jumps which are simple to execute without items.\n" "This includes jumping from heights to dive deeper without scales,\n"