From 20e5ec16430e7e6aab3bb77d91b953cbd3c0b113 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Thu, 3 Jul 2025 18:00:20 +0100 Subject: [PATCH 1/5] Update well logic for doorsanity Co-authored-by: Demur Rumed --- soh/soh/Enhancements/randomizer/entrance.cpp | 4 +- .../dungeons/bottom_of_the_well.cpp | 402 +++++++++++------- .../location_access/overworld/kakariko.cpp | 2 +- soh/soh/Enhancements/randomizer/logic.cpp | 2 +- soh/soh/Enhancements/randomizer/logic.h | 1 + .../Enhancements/randomizer/randomizerTypes.h | 58 ++- soh/soh/Enhancements/randomizer/settings.cpp | 3 +- 7 files changed, 301 insertions(+), 171 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 1cd4160de..d34f19b46 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -269,8 +269,8 @@ void SetAllEntrancesData() { { EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE } }, { { EntranceType::Dungeon, RR_GRAVEYARD_WARP_PAD_REGION, RR_SHADOW_TEMPLE_ENTRYWAY, ENTR_SHADOW_TEMPLE_ENTRANCE }, { EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_OUTSIDE_TEMPLE } }, - { { EntranceType::Dungeon, RR_KAK_WELL, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE }, - { EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } }, + { { EntranceType::Dungeon, RR_KAK_WELL, RR_BOTW_ENTRYWAY, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE }, + { EntranceType::Dungeon, RR_BOTW_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } }, { { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE }, { EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } }, { { EntranceType::Dungeon, RR_GF_TO_GTG, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE }, diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp index 001ad5d81..3c63cb318 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp @@ -7,24 +7,33 @@ using namespace Rando; void RegionTable_Init_BottomOfTheWell() { // clang-format off // Vanilla/MQ Decider - areaTable[RR_BOTTOM_OF_THE_WELL_ENTRYWAY] = Region("Bottom of the Well Entryway", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { + areaTable[RR_BOTW_ENTRYWAY] = Region("Bottom of the Well Entryway", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { //Exits //Technically involves an fake wall, but passing it lensless is intended in vanilla and it is well telegraphed - Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla() && logic->IsChild && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsMQ() && logic->IsChild;}), - Entrance(RR_KAK_WELL, []{return true;}), + Entrance(RR_BOTW_CORRIDOR, []{return ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla() && logic->IsChild/*CanCrawl*/;}), + Entrance(RR_BOTW_MQ_PERIMETER, []{return ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsMQ() && logic->IsChild/*CanCrawl*/;}), + Entrance(RR_KAK_WELL, []{return true;}), }); #pragma region Vanilla - areaTable[RR_BOTTOM_OF_THE_WELL_PERIMETER] = Region("Bottom of the Well Perimeter", SCENE_BOTTOM_OF_THE_WELL, { + areaTable[RR_BOTW_CORRIDOR] = Region("Bottom of the Well Corridor", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { + //Exits + Entrance(RR_BOTW_ENTRYWAY, []{return logic->IsChild/*CanCrawl && CanClimb*/;}), + Entrance(RR_BOTW_PERIMETER, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), + }); + + areaTable[RR_BOTW_PERIMETER] = Region("Bottom of the Well Perimeter", SCENE_BOTTOM_OF_THE_WELL, { //Events EventAccess(&logic->StickPot, []{return true;}), EventAccess(&logic->NutPot, []{return true;}), EventAccess(&logic->LoweredWaterInsideBotw, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }, { //Locations + LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->LoweredWaterInsideBotw || logic->CanOpenUnderwaterChest()), LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->LoweredWaterInsideBotw || logic->CanOpenUnderwaterChest()), LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_1, logic->CanBreakPots()), @@ -32,217 +41,351 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_POT, (logic->CanBreakPots() && logic->LoweredWaterInsideBotw) || logic->CanUse(RG_BOOMERANG)), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->IsChild && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), - Entrance(RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), - Entrance(RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), - Entrance(RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), - Entrance(RR_BOTTOM_OF_THE_WELL_COFFIN_ROOM, []{return logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE);}), - Entrance(RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM, []{return logic->LoweredWaterInsideBotw && logic->IsChild;}), + Entrance(RR_BOTW_CORRIDOR, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), + Entrance(RR_BOTW_MIDDLE, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), + Entrance(RR_BOTW_WEST_CAGE, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), + Entrance(RR_BOTW_SOUTHWEST_ROOM, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), + Entrance(RR_BOTW_NORTHEAST_CRAWLSPACE, []{return logic->IsChild/*CanCrawl*/;}), + //Climb always needed in case water is lowered out of logic + Entrance(RR_BOTW_WEST_LEDGE, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE))/*CanClimb*/;}), + Entrance(RR_BOTW_SE_CRAWLSPACE_LOWER, []{return logic->LoweredWaterInsideBotw && logic->IsChild/*CanCrawl*/;}), //Falling down into basement requires nothing, but falling down somewhere specific requires lens or lens trick //kinda questionable given several drops are blocked by rocks, but that's how it was handled before and on N64 - Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return true;}), + Entrance(RR_BOTW_B3, []{return true;}), + Entrance(RR_BOTW_B3_WEST, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), }); //This region combines the Middle with the perimeter's hidden areas. If a warp puts link into the middle without crossing the perimeter or using lens, it will need it's own region - areaTable[RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS] = Region("Bottom of the Well Behind Fake Walls", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_MIDDLE] = Region("Bottom of the Well Middle", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, true), - LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, true), - LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, true), //You can just barely pass the spider on the right side without damage or items, but it's probably tight enough to count as as a trick - LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()), - //Not technically behind a wall, but still logically needs lens due to pits - LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives()), + LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), - Entrance(RR_BOTTOM_OF_THE_WELL_INNER_ROOMS, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), - Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return true;}), - Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), + Entrance(RR_BOTW_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), + Entrance(RR_BOTW_WEST_CAGE, []{return ctx->GetTrickOption(RT_BOTW_PITS) && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}), + Entrance(RR_BOTW_WEST_INNER_ROOM, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), + Entrance(RR_BOTW_EAST_INNER_ROOM, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), + Entrance(RR_BOTW_B3, []{return true;}), + Entrance(RR_BOTW_B3_PLATFORM, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), }); - //This area can be reached without lens in logic from basement, but that could require silver rupees if they are shuffled. - areaTable[RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM] = Region("Bottom of the Well Southwest Room", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_SOUTHWEST_ROOM] = Region("Bottom of the Well Southwest Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations LOCATION(RC_BOTTOM_OF_THE_WELL_LEFT_SIDE_POT_1, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_LEFT_SIDE_POT_2, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_LEFT_SIDE_POT_3, logic->CanBreakPots()), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), + Entrance(RR_BOTW_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), + }); + + areaTable[RR_BOTW_NORTHEAST_CRAWLSPACE] = Region("Bottom of the Well Northwest Crawlspace", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { + //Exits + Entrance(RR_BOTW_PERIMETER, []{return logic->IsChild;}), + Entrance(RR_BOTW_KEESE_BEAMOS_ROOM, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), }); //Passing through this area needs lens, but entering doesn't, so that the fire keese can be killed without crossing the pits if enemy drops are ever shuffled - areaTable[RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM] = Region("Bottom of the Well Keese-Beamos Room", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_KEESE_BEAMOS_ROOM] = Region("Bottom of the Well Keese-Beamos Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_POT_1, logic->CanBreakPots() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}), - Entrance(RR_BOTTOM_OF_THE_WELL_LIKE_LIKE_CAGE, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), + Entrance(RR_BOTW_NORTHEAST_CRAWLSPACE, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}), + Entrance(RR_BOTW_LOCKED_CAGE, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), //not sure if this lens check is needed, these holes are a bit too easy to find, but it matches existing logic - Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), + Entrance(RR_BOTW_B3_EAST, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_LIKE_LIKE_CAGE] = Region("Bottom of the Well Like-Like Cage", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_LOCKED_CAGE] = Region("Bottom of the Well Locked Cage", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations LOCATION(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, true), LOCATION(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, []{return true;}), + Entrance(RR_BOTW_KEESE_BEAMOS_ROOM, []{return true;}), }); - //If the player can voidwarp into one of these rooms they will need splitting up, and Fake walls will need specifying into middle and the rest moved to perimeter - areaTable[RR_BOTTOM_OF_THE_WELL_INNER_ROOMS] = Region("Bottom of the Well Inner Rooms", SCENE_BOTTOM_OF_THE_WELL, { + areaTable[RR_BOTW_WEST_CAGE] = Region("Bottom of the Well West Cage", SCENE_BOTTOM_OF_THE_WELL, {}, { + //Locations + LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, true), + }, { + //Exits + Entrance(RR_BOTW_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), + Entrance(RR_BOTW_MIDDLE, []{return ctx->GetTrickOption(RT_BOTW_PITS) && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH));}), + Entrance(RR_BOTW_B3, []{return true;}), + }); + + areaTable[RR_BOTW_WEST_INNER_ROOM] = Region("Bottom of the Well West Inner Room", SCENE_BOTTOM_OF_THE_WELL, { //Events EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}), EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations LOCATION(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), + }, { + //Exits + Entrance(RR_BOTW_MIDDLE, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), + }); + + areaTable[RR_BOTW_EAST_INNER_ROOM] = Region("Bottom of the Well East Inner Room", SCENE_BOTTOM_OF_THE_WELL, {}, { + //Locations LOCATION(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), + Entrance(RR_BOTW_MIDDLE, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}), + Entrance(RR_BOTW_B3, []{return true;}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_COFFIN_ROOM] = Region("Bottom of the Well Coffin Room", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_WEST_LEDGE] = Region("Bottom of the Well West Ledge", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), - LOCATION(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_FRONT_LEFT_HEART, true), - LOCATION(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->LoweredWaterInsideBotw || logic->CanOpenUnderwaterChest()), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE);}), + //Climb always needed in case water is lowered out of logic + Entrance(RR_BOTW_PERIMETER, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE))/*CanClimb()*/;}), + Entrance(RR_BOTW_COFFIN_ROOM, []{return true;}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM] = Region("Bottom of the Well Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_COFFIN_ROOM] = Region("Bottom of the Well Coffin Room", SCENE_BOTTOM_OF_THE_WELL, {}, { + //Locations + LOCATION(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_FRONT_LEFT_HEART, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), + }, { + //Exits + //Climb always needed in case water is lowered out of logic + Entrance(RR_BOTW_WEST_LEDGE, []{return true;}), + }); + + areaTable[RR_BOTW_SE_CRAWLSPACE_LOWER] = Region("Bottom of the Well SE Crawlspace Lower", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { + //Exits + Entrance(RR_BOTW_PERIMETER, []{return logic->IsChild/*CanCrawl*/ && (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE));}), + Entrance(RR_BOTW_SE_CRAWLSPACE_UPPER, []{return true/*CanClimb*/;}), + }); + + areaTable[RR_BOTW_SE_CRAWLSPACE_UPPER] = Region("Bottom of the Well SE Crawlspace Upper", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { + //Exits + Entrance(RR_BOTW_SE_CRAWLSPACE_LOWER, []{return true;}), + Entrance(RR_BOTW_DEAD_HAND_ROOM, []{return true;}), + }); + + areaTable[RR_BOTW_DEAD_HAND_ROOM] = Region("Bottom of the Well Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations LOCATION(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), LOCATION(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), }, { //Exits - //This assumes we spawned in dead hand's room, if whatever trick made this relevant instead puts us in the previous room, remove the kill Dead Hand check. - Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, []{return logic->IsChild && logic->CanKillEnemy(RE_DEAD_HAND);}), + Entrance(RR_BOTW_SE_CRAWLSPACE_UPPER, []{return logic->CanKillEnemy(RE_DEAD_HAND);}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_BASEMENT] = Region("Bottom of the Well Basement", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_B3] = Region("Bottom of the Well B3", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, logic->BlastOrSmash()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_1, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_2, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_3, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_4, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_5, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_6, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_7, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_8, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_9, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_10, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_11, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_12, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_GRASS_1, logic->CanCutShrubs()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_GRASS_2, logic->CanCutShrubs()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_GRASS_3, logic->CanCutShrubs()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_1, logic->CanCutShrubs() && logic->BlastOrSmash()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_2, logic->CanCutShrubs() && logic->BlastOrSmash()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_3, logic->CanCutShrubs() && logic->BlastOrSmash()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_4, logic->CanCutShrubs() && logic->BlastOrSmash()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_5, logic->CanCutShrubs() && logic->BlastOrSmash()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_6, logic->CanCutShrubs() && logic->BlastOrSmash()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_7, logic->CanCutShrubs() && logic->BlastOrSmash()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_8, logic->CanCutShrubs() && logic->BlastOrSmash()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_9, logic->CanCutShrubs() && logic->BlastOrSmash()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_1, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_2, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_3, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_4, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_5, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_6, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_7, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_8, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_9, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_10, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_11, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_12, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_GRASS_1, logic->CanCutShrubs()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_GRASS_2, logic->CanCutShrubs()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_GRASS_3, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, []{return logic->IsChild && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), + Entrance(RR_BOTW_SOUTHWEST_ROOM, []{return true/*CanClimbHigh()*/;}), //It's possible to abuse boulder's limited range of collision detection to detonate the flowers through the boulder with bow, but this is a glitch //the exact range is just past the furthest away plank in the green goo section - Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS, []{return Here(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || (logic->CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_BASEMENT));});}), + Entrance(RR_BOTW_B3_EAST, []{return Here(RR_BOTW_B3, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || (logic->CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_BASEMENT));});}), + Entrance(RR_BOTW_B3_WEST, []{return Here(RR_BOTW_B3, []{return logic->BlastOrSmash();});}), + Entrance(RR_BOTW_B3_SOUTH, []{return Here(RR_BOTW_B3, []{return logic->BlastOrSmash();});}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS] = Region("Bottom of the Well Basement Useful Bomb Flowers", SCENE_BOTTOM_OF_THE_WELL, {}, { - //Locations - //Assumes RR_BOTTOM_OF_THE_WELL_BASEMENT access - LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, logic->HasItem(RG_GORONS_BRACELET)), - }, { + areaTable[RR_BOTW_B3_EAST] = Region("Bottom of the Well B3 East", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return logic->CanDetonateUprightBombFlower();}), + Entrance(RR_BOTW_B3, []{return logic->CanDetonateUprightBombFlower();}), + Entrance(RR_BOTW_B3_WEST, []{return logic->HasItem(RG_GORONS_BRACELET);}), + Entrance(RR_BOTW_B3_SOUTH, []{return logic->HasItem(RG_GORONS_BRACELET);}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM] = Region("Bottom of the Well Basement Platform", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_B3_WEST] = Region("Bottom of the Well B3 East", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_LEFT_RUPEE, true), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_BACK_LEFT_RUPEE, true), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_MIDDLE_RUPEE, true), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_BACK_RIGHT_RUPEE, true), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_RIGHT_RUPEE, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_1, logic->CanCutShrubs()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_2, logic->CanCutShrubs()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_3, logic->CanCutShrubs()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_4, logic->CanCutShrubs()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_5, logic->CanCutShrubs()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_6, logic->CanCutShrubs()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_7, logic->CanCutShrubs()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_8, logic->CanCutShrubs()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_9, logic->CanCutShrubs()), + }, { + //Exits + Entrance(RR_BOTW_B3, []{return Here(RR_BOTW_B3_WEST, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}), + }); + + areaTable[RR_BOTW_B3_SOUTH] = Region("Bottom of the Well B3 South", SCENE_BOTTOM_OF_THE_WELL, {}, { + //Locations + LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, true), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return true;}), + Entrance(RR_BOTW_B3, []{return Here(RR_BOTW_B3_SOUTH, []{return logic->BlastOrSmash();});}), + }); + + areaTable[RR_BOTW_B3_PLATFORM] = Region("Bottom of the Well B3 Platform", SCENE_BOTTOM_OF_THE_WELL, {}, { + //Locations + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_LEFT_RUPEE, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_BACK_LEFT_RUPEE, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_MIDDLE_RUPEE, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_BACK_RIGHT_RUPEE, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_RIGHT_RUPEE, true), + }, { + //Exits + Entrance(RR_BOTW_B3, []{return true;}), }); #pragma endregion #pragma region MQ - areaTable[RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER] = Region("Bottom of the Well MQ Perimeter", SCENE_BOTTOM_OF_THE_WELL, { + areaTable[RR_BOTW_MQ_PERIMETER] = Region("Bottom of the Well MQ Perimeter", SCENE_BOTTOM_OF_THE_WELL, { //Events //technically obsolete due to a wonder item fairy which only needs a projectile, but we don't have an event var for it yet - EventAccess(&logic->FairyPot, []{return Here(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets();}), - //It is possible to hit the water switch with a pot from RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, however the hitbox for making it activate is very unintuitive + EventAccess(&logic->FairyPot, []{return Here(RR_BOTW_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets();}), + //It is possible to hit the water switch with a pot from RR_BOTW_MQ_MIDDLE, however the hitbox for making it activate is very unintuitive //You have to throw the pot from further back to hit the switch from the front instead of the top, trying to hit the "fingers" directly //This unintuitiveness means it should be a trick. ZL is needed to get a clear path to carry the pot - EventAccess(&logic->LoweredWaterInsideBotw, []{return logic->CanJumpslash() || logic->CanUseProjectile();}), + EventAccess(&logic->LoweredWaterInsideBotw, []{return logic->CanHitSwitch(ED_SHORT_JUMPSLASH);}), + EventAccess(&logic->OpenedMQBotwGates, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }, { //Locations - //Implies CanBreakPots() - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_OUTER_LOBBY_POT, Here(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()), + //Implies CanBreakPots(). Hitting this with rang through the wall is possible but would be a trick. + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_OUTER_LOBBY_POT, Here(RR_BOTW_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BOMB_LEFT_HEART, logic->HasExplosives()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BOMB_RIGHT_HEART, logic->HasExplosives()), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->IsChild;}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_WEST_ROOM_SWITCH, []{return Here(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE)) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_LOCKED_CAGE, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2) && logic->CanUseProjectile();}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_ROOM, []{return logic->IsChild && logic->LoweredWaterInsideBotw;}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT, []{return true;}), + Entrance(RR_BOTW_ENTRYWAY, []{return logic->IsChild/*CanCrawl() && CanClimb()*/;}), + Entrance(RR_BOTW_MQ_MIDDLE, []{return logic->OpenedMQBotwGates;}), + Entrance(RR_BOTW_MQ_WEST_CAGE, []{return Here(RR_BOTW_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), + //Climb always needed in case water is lowered out of logic + Entrance(RR_BOTW_MQ_WEST_LEDGE, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE)) /*&& CanClimb()*/;}), + Entrance(RR_BOTW_MQ_NORTHEAST_CRAWLSPACE, []{return logic->IsChild/*CanCrawl()*/;}), + Entrance(RR_BOTW_MQ_SE_CRAWLSPACE_LOWER, []{return logic->IsChild/*CanCrawl()*/ && logic->LoweredWaterInsideBotw;}), + Entrance(RR_BOTW_MQ_B3, []{return true;}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_MQ_WEST_ROOM_SWITCH] = Region("Bottom of the Well MQ West Room Switch", SCENE_BOTTOM_OF_THE_WELL, { + areaTable[RR_BOTW_MQ_MIDDLE] = Region("Bottom of the Well MQ Middle", SCENE_BOTTOM_OF_THE_WELL, {}, { + //Locations + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_1, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_2, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_3, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), + }, { + //Exits + Entrance(RR_BOTW_MQ_PERIMETER, []{return logic->OpenedMQBotwGates;}), + Entrance(RR_BOTW_MQ_WEST_CAGE, []{return (bool)ctx->GetTrickOption(RT_BOTW_PITS);}), + Entrance(RR_BOTW_MQ_SWITCH_PLATFORM, []{return logic->OpenedMiddleHoleMQBotw;}), + Entrance(RR_BOTW_MQ_B3, []{return true;}), + Entrance(RR_BOTW_MQ_EAST_INNER_ROOM, []{return true/*str0 or CanHitSwitch(ED_BOMB_THROW)*/;}), + Entrance(RR_BOTW_MQ_WEST_INNER_ROOM, []{return logic->OpenedWestRoomMQBotw;}), + }); + + areaTable[RR_BOTW_MQ_EAST_INNER_ROOM] = Region("Bottom of the Well East Inner Room", SCENE_BOTTOM_OF_THE_WELL, {}, { + //Locations + //This location technically involves an invisible platform, but it's intended to do lensless in vanilla and is clearly signposted by pots. + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_1, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_2, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_3, logic->CanBreakPots()), + }, { + //Exits + Entrance(RR_BOTW_MQ_MIDDLE, []{return true;}), + Entrance(RR_BOTW_MQ_B3, []{return true;}), + }); + + areaTable[RR_BOTW_MQ_WEST_INNER_ROOM] = Region("Bottom of the Well West Inner Room", SCENE_BOTTOM_OF_THE_WELL, {}, { + //Locations + //The enemies in this room are invisible and crowd around the player, being awkward to deal with blind unless you already know how. + //the right wall is safe, and can be followed to get behind the grave which you can then pull easily assuming you can tank invisible keese + //Using a deku nut however stuns everything easily. and if you have a melee weapon you can kill the skull through the grave then grab the drop + //though it can be hard to tell where the safe direct path to the grave is without lens. + //Also you get cheap shotted on entry sometimes. + //An MQ lens trick is recommended here, and a review of this room for OHKO logic what that is added is advised. + //In the meantime I assume damage taken or the easy answer (nuts) + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, (logic->TakeDamage() || logic->CanUse(RG_NUTS)) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), + }, { + //Exits + Entrance(RR_BOTW_MQ_MIDDLE, []{return true;}), + }); + + areaTable[RR_BOTW_MQ_WEST_CAGE] = Region("Bottom of the Well MQ West Room Switch", SCENE_BOTTOM_OF_THE_WELL, { //Events EventAccess(&logic->OpenedWestRoomMQBotw, []{return true;}), }, {}, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->BlastOrSmash() && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || ctx->GetTrickOption(RT_BOTW_MQ_PITS));}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, []{return (bool)ctx->GetTrickOption(RT_BOTW_MQ_PITS);}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT, []{return true;}), + Entrance(RR_BOTW_MQ_PERIMETER, []{return logic->BlastOrSmash() && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || ctx->GetTrickOption(RT_BOTW_PITS));}), + Entrance(RR_BOTW_MQ_MIDDLE, []{return (bool)ctx->GetTrickOption(RT_BOTW_PITS);}), + Entrance(RR_BOTW_MQ_B3, []{return true;}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM] = Region("Bottom of the Well MQ Coffin Room", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_MQ_WEST_LEDGE] = Region("Bottom of the Well MQ West Ledge", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { + //Exits + Entrance(RR_BOTW_MQ_PERIMETER, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE))/* && CanClimb*/;}), + Entrance(RR_BOTW_MQ_COFFIN_ROOM, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), + }); + + areaTable[RR_BOTW_MQ_COFFIN_ROOM] = Region("Bottom of the Well MQ Coffin Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_FRONT_RIGHT_HEART, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_MIDDLE_LEFT_HEART, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE)) && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), + //Climb always needed in case water is lowered out of logic + Entrance(RR_BOTW_MQ_WEST_LEDGE, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_MQ_LOCKED_CAGE] = Region("Bottom of the Well MQ Locked Cage", SCENE_BOTTOM_OF_THE_WELL, { + areaTable[RR_BOTW_MQ_NORTHEAST_CRAWLSPACE] = Region("Bottom of the Well MQ Northeast Crawlspace", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { + Entrance(RR_BOTW_MQ_PERIMETER, []{return logic->IsChild;}), + Entrance(RR_BOTW_MQ_FLOORMASTER_ROOM, []{return logic->CanUseProjectile();}), + }); + + areaTable[RR_BOTW_MQ_FLOORMASTER_ROOM] = Region("Bottom of the Well MQ Floormaster Room", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { + Entrance(RR_BOTW_MQ_NORTHEAST_CRAWLSPACE, []{return true;}), + Entrance(RR_BOTW_MQ_LOCKED_CAGE, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), + }); + + areaTable[RR_BOTW_MQ_LOCKED_CAGE] = Region("Bottom of the Well MQ Locked Cage", SCENE_BOTTOM_OF_THE_WELL, { //Events EventAccess(&logic->OpenedMiddleHoleMQBotw, []{return logic->HasExplosives();}), }, {}, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), + Entrance(RR_BOTW_MQ_FLOORMASTER_ROOM, []{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_ROOM] = Region("Bottom of the Well MQ Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_MQ_SE_CRAWLSPACE_LOWER] = Region("Bottom of the Well MQ SE Crawlspace Lower", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { + //Exits + Entrance(RR_BOTW_MQ_PERIMETER, []{return logic->IsChild/*CanCrawl()*/ && (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE));}), + Entrance(RR_BOTW_MQ_SE_CRAWLSPACE_UPPER, []{return true/*CanClimb*/;}), + }); + + areaTable[RR_BOTW_MQ_SE_CRAWLSPACE_UPPER] = Region("Bottom of the Well MQ SE Crawlspace Upper", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { + //Exits + Entrance(RR_BOTW_MQ_SE_CRAWLSPACE_LOWER, []{return true;}), + Entrance(RR_BOTW_MQ_DEAD_HAND_ROOM, []{return true;}), + }); + + areaTable[RR_BOTW_MQ_DEAD_HAND_ROOM] = Region("Bottom of the Well MQ Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, logic->HasExplosives() || (ctx->GetTrickOption(RT_BOTW_MQ_DEADHAND_KEY) && logic->CanUse(RG_BOOMERANG))), @@ -252,38 +395,10 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_GRASS_4, logic->CanCutShrubs()), }, { //Exits - //This assumes we spawned in dead hand's room, if whatever trick made this relevant instead puts us in the previous room, remove the kill Dead Hand check. - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return logic->IsChild && logic->CanKillEnemy(RE_DEAD_HAND);}), + Entrance(RR_BOTW_MQ_SE_CRAWLSPACE_UPPER, []{return logic->CanKillEnemy(RE_DEAD_HAND);}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE] = Region("Bottom of the Well MQ Middle", SCENE_BOTTOM_OF_THE_WELL, {}, { - //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, true), - //This location technically involves an invisible platform, but it's intended to do lensless in vanilla and is clearly signposted by pots. - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, true), - //The enemies in this room are invisible and crowd around the player, being awkward to deal with blind unless you already know how. - //the right wall is safe, and can be followed to get behind the grave which you can then pull easily assuming you can tank invisible keese - //Using a deku nut however stuns everything easily. and if you have a melee weapon you can kill the skull through the grave then grab the drop - //though it can be hard to tell where the safe direct path to the grave is without lens. - //Also you get cheap shotted on entry sometimes. - //An MQ lens trick is recommended here, and a review of this room for OHKO logic what that is added is advised. - //In the meantime I assume damage taken or the easy answer (nuts) - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, logic->OpenedWestRoomMQBotw && (logic->TakeDamage() || logic->CanUse(RG_NUTS)) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_1, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_2, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_3, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_1, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_2, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_3, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), - }, { - //Exits - //If a relevant trick causes you to be able to warp into here without going through PERIMETER, a new eventAccess will be needed for lowering the gates with ZL - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SWITCH_PLATFORM, []{return logic->OpenedMiddleHoleMQBotw;}), - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT, []{return true;}), - }); - - areaTable[RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT] = Region("Bottom of the Well MQ Basement", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_MQ_B3] = Region("Bottom of the Well MQ B3", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations //behind invisible big skulltulas, but with navi spotting it's easy to avoid them, or at worst, tank your way through as they do not block the path LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), @@ -293,19 +408,16 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, []{return true;}), + Entrance(RR_BOTW_MQ_PERIMETER, []{return true/*CanClimbHigh()*/;}), }); - areaTable[RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SWITCH_PLATFORM] = Region("Bottom of the Well MQ Basement Switch Platform", SCENE_BOTTOM_OF_THE_WELL, {}, { + areaTable[RR_BOTW_MQ_SWITCH_PLATFORM] = Region("Bottom of the Well MQ Switch Platform", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - //Assumes RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT access - //it is technically possible to get the chest before you get screamed at without rolling, but hard enough to be a trick if that is the requirement for something to be logical - //With some kind of movement tech it's much easier, easy enough to be default logic, as the redeads don't lock on immediately in addition to the extra speed - //leaving with no requirements for now but up for discussion. - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, true), + //Assumes RR_BOTW_MQ_B3 access + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, logic->CanPassEnemy(RE_REDEAD)), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT, []{return true;}), + Entrance(RR_BOTW_MQ_B3, []{return true;}), }); #pragma endregion diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index 92bc9aa37..c42beea98 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -270,7 +270,7 @@ void RegionTable_Init_Kakariko() { areaTable[RR_KAK_WELL] = Region("Kak Well", SCENE_KAKARIKO_VILLAGE, {}, {}, { //Exits Entrance(RR_KAKARIKO_VILLAGE, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->DrainWell;}), - Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->IsChild || (logic->DrainWell && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF));}), + Entrance(RR_BOTW_ENTRYWAY, []{return logic->IsChild || (logic->DrainWell && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF));}), }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index eea79e92d..ab3f72a49 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -852,7 +852,7 @@ bool Logic::CanPassEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal case RE_REDEAD: // we need a way to check if suns won't force a reload // RANDOTODO: check if stealthing past these guys works everywhere - return CanUse(RG_HOOKSHOT) || CanUse(RG_SUNS_SONG); + return true;//CanUse(RG_HOOKSHOT) || CanUse(RG_SUNS_SONG); case RE_IRON_KNUCKLE: case RE_BIG_OCTO: return false; diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 2bfea75e9..c9c58071c 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -144,6 +144,7 @@ class Logic { bool DeliverLetter = false; bool ClearMQDCUpperLobbyRocks = false; bool LoweredWaterInsideBotw = false; + bool OpenedMQBotwGates = false; bool OpenedWestRoomMQBotw = false; bool OpenedMiddleHoleMQBotw = false; bool BrokeDeku1FWeb = false; diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 15a2fbd37..8c4491e82 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -568,7 +568,7 @@ typedef enum { RR_WATER_TEMPLE_ENTRYWAY, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_SHADOW_TEMPLE_ENTRYWAY, - RR_BOTTOM_OF_THE_WELL_ENTRYWAY, + RR_BOTW_ENTRYWAY, RR_ICE_CAVERN_ENTRYWAY, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GANONS_CASTLE_ENTRYWAY, @@ -968,26 +968,42 @@ typedef enum { RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, - RR_BOTTOM_OF_THE_WELL_PERIMETER, - RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, - RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, - RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, - RR_BOTTOM_OF_THE_WELL_LIKE_LIKE_CAGE, - RR_BOTTOM_OF_THE_WELL_INNER_ROOMS, - RR_BOTTOM_OF_THE_WELL_COFFIN_ROOM, - RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM, - RR_BOTTOM_OF_THE_WELL_BASEMENT, - RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS, - RR_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM, + RR_BOTW_CORRIDOR, + RR_BOTW_PERIMETER, + RR_BOTW_MIDDLE, + RR_BOTW_WEST_CAGE, + RR_BOTW_SOUTHWEST_ROOM, + RR_BOTW_NORTHEAST_CRAWLSPACE, + RR_BOTW_KEESE_BEAMOS_ROOM, + RR_BOTW_LOCKED_CAGE, + RR_BOTW_WEST_INNER_ROOM, + RR_BOTW_EAST_INNER_ROOM, + RR_BOTW_WEST_LEDGE, + RR_BOTW_COFFIN_ROOM, + RR_BOTW_SE_CRAWLSPACE_LOWER, + RR_BOTW_SE_CRAWLSPACE_UPPER, + RR_BOTW_DEAD_HAND_ROOM, + RR_BOTW_B3, + RR_BOTW_B3_EAST, + RR_BOTW_B3_WEST, + RR_BOTW_B3_SOUTH, + RR_BOTW_B3_PLATFORM, - RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, - RR_BOTTOM_OF_THE_WELL_MQ_WEST_ROOM_SWITCH, - RR_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM, - RR_BOTTOM_OF_THE_WELL_MQ_LOCKED_CAGE, - RR_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_ROOM, - RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, - RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT, - RR_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SWITCH_PLATFORM, + RR_BOTW_MQ_PERIMETER, + RR_BOTW_MQ_MIDDLE, + RR_BOTW_MQ_EAST_INNER_ROOM, + RR_BOTW_MQ_WEST_INNER_ROOM, + RR_BOTW_MQ_WEST_CAGE, + RR_BOTW_MQ_WEST_LEDGE, + RR_BOTW_MQ_COFFIN_ROOM, + RR_BOTW_MQ_NORTHEAST_CRAWLSPACE, + RR_BOTW_MQ_FLOORMASTER_ROOM, + RR_BOTW_MQ_LOCKED_CAGE, + RR_BOTW_MQ_SE_CRAWLSPACE_LOWER, + RR_BOTW_MQ_SE_CRAWLSPACE_UPPER, + RR_BOTW_MQ_DEAD_HAND_ROOM, + RR_BOTW_MQ_B3, + RR_BOTW_MQ_SWITCH_PLATFORM, RR_ICE_CAVERN_BEGINNING, RR_ICE_CAVERN_MAIN, @@ -3615,7 +3631,7 @@ typedef enum { RT_LENS_BOTW, RT_BOTW_CHILD_DEADHAND, RT_BOTW_BASEMENT, - RT_BOTW_MQ_PITS, + RT_BOTW_PITS, RT_BOTW_MQ_DEADHAND_KEY, RT_FOREST_FIRST_GS, RT_FOREST_OUTDOORS_EAST_GS, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 5f8c60ac0..5625ec32d 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -735,7 +735,8 @@ void Settings::CreateOptions() { "Bottom of the Well Map Chest with Strength & Sticks", "The chest in the basement can be reached with strength by doing a jump slash with a lit stick to access " "the Bomb Flowers."); - OPT_TRICK(RT_BOTW_MQ_PITS, RCQUEST_MQ, RA_BOTTOM_OF_THE_WELL, { Tricks::Tag::NOVICE }, + // RANDOTODO with doorsanity, this can be relevant in Vanilla + OPT_TRICK(RT_BOTW_PITS, RCQUEST_MQ, RA_BOTTOM_OF_THE_WELL, { Tricks::Tag::NOVICE }, "Bottom of the Well MQ Jump Over the Pits", "While the pits in Bottom of the Well don't allow you to jump just by running straight at them, you can " "still get over them by side-hopping or backflipping across. With explosives, this allows you to access " From 70f79fa4f08f6be9df3ba18a6a482a31ac2f8027 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Thu, 3 Jul 2025 18:10:18 +0100 Subject: [PATCH 2/5] clang --- soh/soh/Enhancements/randomizer/logic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index ab3f72a49..9758b3ec4 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -852,7 +852,7 @@ bool Logic::CanPassEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal case RE_REDEAD: // we need a way to check if suns won't force a reload // RANDOTODO: check if stealthing past these guys works everywhere - return true;//CanUse(RG_HOOKSHOT) || CanUse(RG_SUNS_SONG); + return true; // CanUse(RG_HOOKSHOT) || CanUse(RG_SUNS_SONG); case RE_IRON_KNUCKLE: case RE_BIG_OCTO: return false; From a7a52bf2125b6289b3dd1eafc9c6cd8823ab0a45 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Thu, 3 Jul 2025 18:36:40 +0100 Subject: [PATCH 3/5] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Philip Dubé --- soh/soh/Enhancements/randomizer/logic.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 9758b3ec4..1d34d0eeb 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -851,7 +851,6 @@ bool Logic::CanPassEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal case RE_GIBDO: case RE_REDEAD: // we need a way to check if suns won't force a reload - // RANDOTODO: check if stealthing past these guys works everywhere return true; // CanUse(RG_HOOKSHOT) || CanUse(RG_SUNS_SONG); case RE_IRON_KNUCKLE: case RE_BIG_OCTO: From 27ab69a056c2d20ef6d7ea00a776e7106d15d221 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Thu, 10 Jul 2025 17:57:50 +0100 Subject: [PATCH 4/5] Add adult + irons + hook to getting to west ledge --- .../dungeons/bottom_of_the_well.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp index 3c63cb318..22d4dcf69 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp @@ -47,7 +47,8 @@ void RegionTable_Init_BottomOfTheWell() { Entrance(RR_BOTW_SOUTHWEST_ROOM, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), Entrance(RR_BOTW_NORTHEAST_CRAWLSPACE, []{return logic->IsChild/*CanCrawl*/;}), //Climb always needed in case water is lowered out of logic - Entrance(RR_BOTW_WEST_LEDGE, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE))/*CanClimb*/;}), + Entrance(RR_BOTW_WEST_LEDGE, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE) || + (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))/*CanClimb*/);}), Entrance(RR_BOTW_SE_CRAWLSPACE_LOWER, []{return logic->LoweredWaterInsideBotw && logic->IsChild/*CanCrawl*/;}), //Falling down into basement requires nothing, but falling down somewhere specific requires lens or lens trick //kinda questionable given several drops are blocked by rocks, but that's how it was handled before and on N64 @@ -145,7 +146,8 @@ void RegionTable_Init_BottomOfTheWell() { }, { //Exits //Climb always needed in case water is lowered out of logic - Entrance(RR_BOTW_PERIMETER, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE))/*CanClimb()*/;}), + Entrance(RR_BOTW_PERIMETER, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE) || + (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))/* && CanClimb()*/);}), Entrance(RR_BOTW_COFFIN_ROOM, []{return true;}), }); @@ -156,7 +158,6 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), }, { //Exits - //Climb always needed in case water is lowered out of logic Entrance(RR_BOTW_WEST_LEDGE, []{return true;}), }); @@ -277,7 +278,8 @@ void RegionTable_Init_BottomOfTheWell() { Entrance(RR_BOTW_MQ_MIDDLE, []{return logic->OpenedMQBotwGates;}), Entrance(RR_BOTW_MQ_WEST_CAGE, []{return Here(RR_BOTW_MQ_PERIMETER, []{return logic->BlastOrSmash();}) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), //Climb always needed in case water is lowered out of logic - Entrance(RR_BOTW_MQ_WEST_LEDGE, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE)) /*&& CanClimb()*/;}), + Entrance(RR_BOTW_MQ_WEST_LEDGE, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE) || + (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))/*&& CanClimb()*/);}), Entrance(RR_BOTW_MQ_NORTHEAST_CRAWLSPACE, []{return logic->IsChild/*CanCrawl()*/;}), Entrance(RR_BOTW_MQ_SE_CRAWLSPACE_LOWER, []{return logic->IsChild/*CanCrawl()*/ && logic->LoweredWaterInsideBotw;}), Entrance(RR_BOTW_MQ_B3, []{return true;}), @@ -340,7 +342,9 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_MQ_WEST_LEDGE] = Region("Bottom of the Well MQ West Ledge", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { //Exits - Entrance(RR_BOTW_MQ_PERIMETER, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE))/* && CanClimb*/;}), + //Climb always needed in case water is lowered out of logic + Entrance(RR_BOTW_MQ_PERIMETER, []{return (logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE) || + (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))/* && CanClimb*/);}), Entrance(RR_BOTW_MQ_COFFIN_ROOM, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), }); @@ -351,7 +355,6 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COFFIN_ROOM_MIDDLE_LEFT_HEART, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), }, { //Exits - //Climb always needed in case water is lowered out of logic Entrance(RR_BOTW_MQ_WEST_LEDGE, []{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}), }); From bd905fb55d940a3deb4568305450d645b10ebde4 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Sun, 13 Jul 2025 10:51:55 +0100 Subject: [PATCH 5/5] Update soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Philip Dubé --- .../randomizer/location_access/dungeons/bottom_of_the_well.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp index 22d4dcf69..6b25a61de 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp @@ -322,7 +322,7 @@ void RegionTable_Init_BottomOfTheWell() { //Using a deku nut however stuns everything easily. and if you have a melee weapon you can kill the skull through the grave then grab the drop //though it can be hard to tell where the safe direct path to the grave is without lens. //Also you get cheap shotted on entry sometimes. - //An MQ lens trick is recommended here, and a review of this room for OHKO logic what that is added is advised. + //An MQ lens trick is recommended here, and a review of this room for OHKO logic when that is added is advised. //In the meantime I assume damage taken or the easy answer (nuts) LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, (logic->TakeDamage() || logic->CanUse(RG_NUTS)) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), }, {