summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPepper0ni <93387759+Pepper0ni@users.noreply.github.com>2026-03-07 18:21:04 +0000
committerGitHub <noreply@github.com>2026-03-07 18:21:04 +0000
commit60ec65592a32777b7e46ec591af592cbcfe3e95a (patch)
treeae3de9561c1d718229373e1a5c69bc11c064d763
parent6deff6d749868dc97a699ef362402af89ed77add (diff)
Add trick for Hookshotting ladders (#6329)
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp6
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp4
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp2
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp36
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp21
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp4
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp2
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp22
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp4
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp2
-rw-r--r--soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp2
-rw-r--r--soh/soh/Enhancements/randomizer/logic.cpp8
-rw-r--r--soh/soh/Enhancements/randomizer/logic.h2
-rw-r--r--soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h2
-rw-r--r--soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h3
-rw-r--r--soh/soh/Enhancements/randomizer/settings.cpp17
16 files changed, 90 insertions, 47 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 a61b936a0..88e62856d 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
@@ -20,7 +20,7 @@ void RegionTable_Init_BottomOfTheWell() {
areaTable[RR_BOTW_CORRIDOR] = Region("Bottom of the Well Corridor", SCENE_BOTTOM_OF_THE_WELL, {}, {}, {
//Exits
- ENTRANCE(RR_BOTW_ENTRYWAY, logic->CanUse(RG_CRAWL) && logic->HasItem(RG_CLIMB)),
+ ENTRANCE(RR_BOTW_ENTRYWAY, logic->CanUse(RG_CRAWL) && logic->CanClimbLadder()),
ENTRANCE(RR_BOTW_PERIMETER, logic->CanPassEnemy(RE_BIG_SKULLTULA)),
});
@@ -205,7 +205,7 @@ void RegionTable_Init_BottomOfTheWell() {
LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_GRASS_3, logic->CanCutShrubs()),
}, {
//Exits
- ENTRANCE(RR_BOTW_HIDDEN_POTS, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)),
+ ENTRANCE(RR_BOTW_HIDDEN_POTS, logic->CanClimbHighLadder()),
//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_BOTW_B3_BOMB_FLOWERS, AnyAgeTime([]{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_BOTW_BASEMENT) && logic->CanUse(RG_STICKS)) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_FAIRY_BOW));})),
@@ -424,7 +424,7 @@ void RegionTable_Init_BottomOfTheWell() {
LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)),
}, {
//Exits
- ENTRANCE(RR_BOTW_MQ_PERIMETER, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)),
+ ENTRANCE(RR_BOTW_MQ_PERIMETER, logic->CanClimbHighLadder()),
});
areaTable[RR_BOTW_MQ_B3_PLATFORM] = Region("Bottom of the Well MQ B3 Platform", SCENE_BOTTOM_OF_THE_WELL, {}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
index 1853ed072..62b9fe823 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
@@ -156,7 +156,7 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_ARMOS_ROOM] = Region("Dodongos Cavern Armos Room", SCENE_DODONGOS_CAVERN, {}, {}, {
//Exits
ENTRANCE(RR_DODONGOS_CAVERN_STAIRS_UPPER, true),
- ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, logic->IsAdult || (logic->HasItem(RG_POWER_BRACELET) && logic->HasItem(RG_CLIMB)) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)),
+ ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, logic->IsAdult || (logic->HasItem(RG_POWER_BRACELET) && logic->HasItem(RG_CLIMB)) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->CanUse(RG_HOOKSHOT)),
});
areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER] = Region("Dodongos Cavern Bomb Room Lower", SCENE_DODONGOS_CAVERN, {}, {
@@ -390,7 +390,7 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM] = Region("Dodongos Cavern MQ Dodongo Room", SCENE_DODONGOS_CAVERN, {}, {
//Locations
- LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, (logic->CanKillEnemy(RE_DODONGO) || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)),
+ LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, (logic->CanKillEnemy(RE_DODONGO) || (logic->HasItem(RG_GORONS_BRACELET) && logic->CanClimbLadder())) && logic->HasItem(RG_OPEN_CHEST)),
LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_1, logic->CanCutShrubs()),
LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_2, logic->CanCutShrubs()),
LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()),
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp
index 0251e45bb..f19b69cb9 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp
@@ -268,7 +268,7 @@ void RegionTable_Init_ShadowTemple() {
//Exits
ENTRANCE(RR_SHADOW_TEMPLE_ROOM_TO_BOAT, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)),
ENTRANCE(RR_SHADOW_TEMPLE_SPINNING_BLADES, logic->Get(LOGIC_SHADOW_SHORTCUT_BLOCK) && logic->HasItem(RG_CLIMB)),
- ENTRANCE(RR_SHADOW_TEMPLE_BEYOND_BOAT, ((logic->IsAdult && ((logic->HasItem(RG_GORONS_BRACELET) && logic->HasItem(RG_CLIMB)) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_ZELDAS_LULLABY)),
+ ENTRANCE(RR_SHADOW_TEMPLE_BEYOND_BOAT, ((logic->IsAdult && ((logic->HasItem(RG_GORONS_BRACELET) && logic->HasItem(RG_CLIMB)) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))) || (ctx->GetTrickOption(RT_HOOKSHOT_LADDERS) && logic->CanUse(RG_HOOKSHOT))) && logic->CanUse(RG_ZELDAS_LULLABY)),
});
areaTable[RR_SHADOW_TEMPLE_BEYOND_BOAT] = Region("Shadow Temple Beyond Boat", SCENE_SHADOW_TEMPLE, {
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 e332e238b..4bad37381 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
@@ -71,20 +71,20 @@ void RegionTable_Init_DeathMountainCrater() {
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))) ||
+ LOCATION(RC_DMC_WALL_FREESTANDING_POH, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->CanClimbLadder()) ||
(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))) ||
+ ENTRANCE(RR_DMC_CRATE, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->CanClimbLadder()) ||
(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))) ||
+ ENTRANCE(RR_DMC_ROCK_GROTTO, ((logic->FireTimer() >= 24 || logic->Hearts() >= 5) && logic->CanClimbLadder()) ||
(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)) ||
+ ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->CanClimbLadder() ||
(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),
@@ -103,20 +103,20 @@ void RegionTable_Init_DeathMountainCrater() {
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)) ||
+ LOCATION(RC_DMC_WALL_FREESTANDING_POH, (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->CanClimbLadder() ||
(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)) ||
+ ENTRANCE(RR_DMC_CRATE, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->CanClimbLadder() ||
(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)) ||
+ ENTRANCE(RR_DMC_ROCK_GROTTO, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->CanClimbLadder() ||
(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)) ||
+ ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->CanClimbLadder() ||
(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),
@@ -133,20 +133,20 @@ void RegionTable_Init_DeathMountainCrater() {
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)) ||
+ LOCATION(RC_DMC_WALL_FREESTANDING_POH, (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->CanClimbLadder() ||
(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)) ||
+ ENTRANCE(RR_DMC_CRATE, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->CanClimbLadder() ||
(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)) ||
+ ENTRANCE(RR_DMC_ROCK_GROTTO, (logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->CanClimbLadder() ||
(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)) ||
+ ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->CanClimbLadder() ||
(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),
@@ -163,20 +163,20 @@ void RegionTable_Init_DeathMountainCrater() {
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()) ||
+ LOCATION(RC_DMC_WALL_FREESTANDING_POH, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->CanClimbLadder() && 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()) ||
+ ENTRANCE(RR_DMC_CRATE, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->CanClimbLadder() && 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()) ||
+ ENTRANCE(RR_DMC_ROCK_GROTTO, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->CanClimbLadder() && 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() ||
+ ENTRANCE(RR_DMC_CRACKED_WALL, (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->CanClimbLadder() && 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() ||
@@ -188,7 +188,7 @@ void RegionTable_Init_DeathMountainCrater() {
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()) ||
+ ENTRANCE(RR_DMC_FAR_PLATFORM, ((logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->CanClimbLadder() && 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())),
@@ -232,7 +232,7 @@ void RegionTable_Init_DeathMountainCrater() {
(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() >= 88 || logic->Hearts() >= 3) && logic->TakeDamage() && logic->CanClimbLadder() && 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()))),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp
index 6f2f2bf31..a15ef2745 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp
@@ -7,10 +7,7 @@ using namespace Rando;
void RegionTable_Init_GerudoFortress() {
#pragma region Ground
- areaTable[RR_GF_OUTSKIRTS] = Region("Gerudo Fortress Outskirts", SCENE_GERUDOS_FORTRESS, {
- //Events
- EVENT_ACCESS(LOGIC_GF_GATE_OPEN, logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CLIMB) && logic->HasItem(RG_SPEAK_GERUDO)), // longshot can get up without climb, but jank is hard
- }, {
+ areaTable[RR_GF_OUTSKIRTS] = Region("Gerudo Fortress Outskirts", SCENE_GERUDOS_FORTRESS, {}, {
//Locations
LOCATION(RC_GF_OUTSKIRTS_NE_CRATE, (logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)) && logic->CanBreakCrates()),
LOCATION(RC_GF_OUTSKIRTS_NW_CRATE, (logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)) && logic->CanBreakCrates()),
@@ -18,10 +15,11 @@ void RegionTable_Init_GerudoFortress() {
//Exits
ENTRANCE(RR_GV_FORTRESS_SIDE, true),
ENTRANCE(RR_TH_1_TORCH_CELL, true),
- ENTRANCE(RR_GF_OUTSIDE_GATE, logic->Get(LOGIC_GF_GATE_OPEN) || (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->CanGroundJump() /* && climb */) && (ctx->GetTrickOption(RT_GF_CHILD_SKIP_WASTELAND_GATE) && logic->IsChild)),
+ ENTRANCE(RR_GF_OUTSIDE_GATE, logic->Get(LOGIC_GF_GATE_OPEN)),
ENTRANCE(RR_GF_NEAR_GROTTO, logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)),
ENTRANCE(RR_GF_OUTSIDE_GTG, logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)),
//You can talk to the guards to get yourself thrown in jail, so long as you have a hookshot to actually end up there
+ ENTRANCE(RR_GF_TOWER, (logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD)) && logic->CanClimbHighLadder()),
ENTRANCE(RR_GF_JAIL_WINDOW, logic->CanUse(RG_HOOKSHOT)),
});
@@ -187,6 +185,16 @@ void RegionTable_Init_GerudoFortress() {
#pragma endregion
+//Assumes IsChild || HasItem(RG_GERUDO_MEMBERSHIP_CARD) is checked on entry
+ areaTable[RR_GF_TOWER] = Region("Gerudo Fortress Tower", SCENE_GERUDOS_FORTRESS, {
+ //Events
+ EVENT_ACCESS(LOGIC_GF_GATE_OPEN, logic->IsAdult && logic->HasItem(RG_SPEAK_GERUDO)),
+ }, {}, {
+ //Exits
+ ENTRANCE(RR_GF_OUTSKIRTS, true),
+ ENTRANCE(RR_GF_OUTSIDE_GATE, (logic->IsAdult && logic->CanGroundJump()) || ctx->GetTrickOption(RT_GF_WASTELAND_GATE_SIDEHOP_SKIP)),
+ });
+
areaTable[RR_GF_ABOVE_JAIL] = Region("GF Above Jail", SCENE_GERUDOS_FORTRESS, {}, {
//Locations
LOCATION(RC_GF_ABOVE_JAIL_CRATE, true),
@@ -199,7 +207,8 @@ void RegionTable_Init_GerudoFortress() {
ENTRANCE(RR_GF_BELOW_CHEST, logic->TakeDamage()),
ENTRANCE(RR_GF_JAIL_WINDOW, logic->CanUse(RG_HOOKSHOT)),
ENTRANCE(RR_TH_BREAK_ROOM_CORRIDOR, true),
- ENTRANCE(RR_GF_OUTSIDE_GATE, ctx->GetTrickOption(RT_GF_ADULT_SKIP_WASTELAND_GATE) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanJumpslashExceptHammer()),
+ ENTRANCE(RR_GF_TOWER, ctx->GetTrickOption(RT_GF_ADULT_SKIP_WASTELAND_GATE) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanJumpslash() && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD)),
+ ENTRANCE(RR_GF_OUTSIDE_GATE, ctx->GetTrickOption(RT_GF_ADULT_SKIP_WASTELAND_GATE) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanJumpslash()),
});
areaTable[RR_GF_JAIL_WINDOW] = Region("GF Jail Window", SCENE_GERUDOS_FORTRESS, {}, {}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp
index c3a7eeecc..6691f0e94 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp
@@ -177,7 +177,7 @@ void RegionTable_Init_HyruleField() {
ENTRANCE(RR_ZR_FRONT, true),
ENTRANCE(RR_LON_LON_RANCH, true),
ENTRANCE(RR_HF_SOUTHEAST_GROTTO, AnyAgeTime([]{return logic->BlastOrSmash();})),
- ENTRANCE(RR_HF_TO_LAKE_HYLIA, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->SummonEpona()),
+ ENTRANCE(RR_HF_TO_LAKE_HYLIA, logic->CanClimbLadder() || logic->SummonEpona()),
ENTRANCE(RR_HF_OPEN_GROTTO, true),
ENTRANCE(RR_HF_INSIDE_FENCE_GROTTO, logic->CanOpenBombGrotto()),
ENTRANCE(RR_HF_COW_GROTTO, (logic->CanUse(RG_MEGATON_HAMMER) || logic->IsChild) && logic->CanOpenBombGrotto()),
@@ -190,7 +190,7 @@ void RegionTable_Init_HyruleField() {
areaTable[RR_HF_TO_LAKE_HYLIA] = Region("HF to Lake Hylia", SCENE_HYRULE_FIELD, {}, {}, {
//Exits
ENTRANCE(RR_LAKE_HYLIA, true),
- ENTRANCE(RR_HYRULE_FIELD, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->SummonEpona()),
+ ENTRANCE(RR_HYRULE_FIELD, logic->CanClimbLadder() || logic->SummonEpona()),
});
areaTable[RR_HF_SOUTHEAST_GROTTO] = Region("HF Southeast Grotto", SCENE_GROTTOS, grottoEvents, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp
index d6b1674b2..99f947cec 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp
@@ -70,7 +70,7 @@ void RegionTable_Init_KokiriForest() {
}, {
//Exits
ENTRANCE(RR_KF_BOULDER_LOOP, logic->CanUse(RG_CRAWL)),
- ENTRANCE(RR_KF_LINKS_PORCH, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOVER_BOOTS)),
+ ENTRANCE(RR_KF_LINKS_PORCH, logic->IsChild ? logic->CanClimbLadder() : logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOVER_BOOTS)),
ENTRANCE(RR_KF_MIDOS_HOUSE, true),
ENTRANCE(RR_KF_SARIAS_HOUSE, true),
ENTRANCE(RR_KF_HOUSE_OF_TWINS, true),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp
index d65ff8d14..6df779cf6 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp
@@ -12,7 +12,7 @@ void RegionTable_Init_LostWoods() {
areaTable[RR_THE_LOST_WOODS] = Region("Lost Woods", SCENE_LOST_WOODS, {
//Events
- EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairyExceptSuns() || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS))),
+ EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)),
EVENT_ACCESS(LOGIC_BUG_ACCESS, logic->IsChild && logic->CanCutShrubs()),
EVENT_ACCESS(LOGIC_BORROW_SPOOKY_MASK, logic->IsChild && logic->Get(LOGIC_BORROW_SKULL_MASK) && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_KOKIRI) && logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
@@ -31,7 +31,6 @@ void RegionTable_Init_LostWoods() {
//5 buttons => 100%
LOCATION(RC_LW_OCARINA_MEMORY_GAME, logic->IsChild && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 5),
LOCATION(RC_LW_TARGET_IN_WOODS, logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)),
- LOCATION(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, logic->CanSpawnSoilSkull(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanAttack()),
//RANDOTODO handle collecting some of these as you leave the shortcut from the other side
LOCATION(RC_LW_SHORTCUT_RUPEE_1, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_BOOMERANG))),
@@ -45,21 +44,34 @@ void RegionTable_Init_LostWoods() {
LOCATION(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_LW_BEAN_SPROUT_NEAR_BRIDGE_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)),
- LOCATION(RC_LW_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()),
- LOCATION(RC_LW_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_LW_SHORTCUT_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)),
- LOCATION(RC_LW_GOSSIP_STONE, true),
LOCATION(RC_LW_GRASS_1, logic->CanCutShrubs()),
LOCATION(RC_LW_GRASS_2, logic->CanCutShrubs()),
LOCATION(RC_LW_GRASS_3, logic->CanCutShrubs()),
}, {
//Exits
ENTRANCE(RR_LW_FOREST_EXIT, true),
+ ENTRANCE(RR_LW_UNDER_BRIDGE, true),
ENTRANCE(RR_GC_WOODS_WARP, true),
ENTRANCE(RR_LW_BRIDGE, (logic->IsAdult && (CanPlantBean(RR_THE_LOST_WOODS, RG_LOST_WOODS_BRIDGE_BEAN_SOUL) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT)),
ENTRANCE(RR_ZR_FROM_SHORTCUT, logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LOST_WOOD_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash())),
ENTRANCE(RR_LW_BEYOND_MIDO, logic->IsChild || logic->CanUse(RG_SARIAS_SONG) || ctx->GetTrickOption(RT_LW_MIDO_BACKFLIP)),
ENTRANCE(RR_LW_NEAR_SHORTCUTS_GROTTO, AnyAgeTime([]{return logic->BlastOrSmash();})),
+ });
+
+ areaTable[RR_LW_UNDER_BRIDGE] = Region("Lost Woods Under the Bridge", SCENE_LOST_WOODS, {
+ //Events
+ EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairyExceptSuns()),
+ }, {
+ //Locations
+ LOCATION(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LW_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()),
+ LOCATION(RC_LW_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)),
+ LOCATION(RC_LW_GOSSIP_STONE, true),
+ }, {
+ //Exits
+ ENTRANCE(RR_LW_BRIDGE, logic->CanUse(RG_LONGSHOT)),
+ ENTRANCE(RR_THE_LOST_WOODS, logic->CanClimbLadder()),
});
areaTable[RR_LW_BEYOND_MIDO] = Region("LW Beyond Mido", SCENE_LOST_WOODS, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp
index ce5d08f04..8d6c7700e 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp
@@ -46,14 +46,14 @@ void RegionTable_Init_SacredForestMeadow() {
ENTRANCE(RR_FOREST_TEMPLE_ENTRYWAY, logic->CanUse(RG_HOOKSHOT)),
ENTRANCE(RR_SFM_ENTRYWAY, true),
// adult can jump up, but it's a trick. being hit directly by club moblin while wearing hover boots also works, but relies on coming from LW
- ENTRANCE(RR_SFM_ABOVE_MAZE, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump())),
+ ENTRANCE(RR_SFM_ABOVE_MAZE, logic->CanClimbLadder() || (logic->IsAdult && logic->CanGroundJump())),
ENTRANCE(RR_SFM_STORMS_GROTTO, logic->CanOpenStormsGrotto()),
});
areaTable[RR_SFM_OUTSIDE_FAIRY_GROTTO] = Region("SFM Outside Fairy Grotto", SCENE_SACRED_FOREST_MEADOW, {}, {}, {
//Exits
ENTRANCE(RR_SFM_FAIRY_GROTTO, true),
- ENTRANCE(RR_SFM_ABOVE_MAZE, logic->HasItem(RG_CLIMB) || logic->HasItem(RG_HOOKSHOT)),
+ ENTRANCE(RR_SFM_ABOVE_MAZE, logic->CanClimbLadder()),
});
areaTable[RR_SFM_FAIRY_GROTTO] = Region("SFM Fairy Grotto", SCENE_GROTTOS, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp
index fe82c7d0c..87c97f6b3 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp
@@ -46,7 +46,7 @@ void RegionTable_Init_ZorasDomain() {
areaTable[RR_ZORAS_DOMAIN_ISLAND] = Region("Zoras Domain Island", SCENE_ZORAS_DOMAIN, {}, {}, {
//Exits
- ENTRANCE(RR_ZORAS_DOMAIN, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE)),
+ ENTRANCE(RR_ZORAS_DOMAIN, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && ctx->GetTrickOption(RT_HOOKSHOT_LADDERS))),
ENTRANCE(RR_ZD_STORMS_GROTTO, logic->CanOpenStormsGrotto()),
});
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
index 9c897538d..ae03c6df0 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
@@ -59,7 +59,7 @@ void RegionTable_Init_ZoraRiver() {
}, {
//Exits
ENTRANCE(RR_ZR_FRONT, true),
- ENTRANCE(RR_ZR_ATOP_LADDER, (logic->IsAdult || logic->HasItem(RG_POWER_BRACELET)) && (logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || CanPlantBean(RR_ZORAS_RIVER, RG_ZORAS_RIVER_BEAN_SOUL))),
+ ENTRANCE(RR_ZR_ATOP_LADDER, (logic->IsAdult || logic->HasItem(RG_POWER_BRACELET)) && (logic->CanClimbLadder() || CanPlantBean(RR_ZORAS_RIVER, RG_ZORAS_RIVER_BEAN_SOUL))),
ENTRANCE(RR_ZR_PILLAR, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_LOWER))),
ENTRANCE(RR_ZR_FROM_SHORTCUT, logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)),
ENTRANCE(RR_ZR_STORMS_GROTTO, logic->CanOpenStormsGrotto()),
diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp
index 7cf37df97..b6b0806b1 100644
--- a/soh/soh/Enhancements/randomizer/logic.cpp
+++ b/soh/soh/Enhancements/randomizer/logic.cpp
@@ -2547,6 +2547,14 @@ bool Logic::ReachDistantScarecrow() {
return ScarecrowsSong() && CanUse(RG_LONGSHOT);
}
+bool Logic::CanClimbLadder() {
+ return CanUse(RG_CLIMB) || (ctx->GetTrickOption(RT_HOOKSHOT_LADDERS) && CanUse(RG_HOOKSHOT));
+}
+
+bool Logic::CanClimbHighLadder() {
+ return CanUse(RG_CLIMB) || (ctx->GetTrickOption(RT_HOOKSHOT_LADDERS) && CanUse(RG_LONGSHOT));
+}
+
bool Logic::SummonEpona() {
return IsAdult && Get(LOGIC_FREED_EPONA) && CanUse(RG_EPONAS_SONG);
}
diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h
index ec338b1a3..4141ad598 100644
--- a/soh/soh/Enhancements/randomizer/logic.h
+++ b/soh/soh/Enhancements/randomizer/logic.h
@@ -117,6 +117,8 @@ class Logic {
bool IsFireLoopLocked();
bool ReachScarecrow();
bool ReachDistantScarecrow();
+ bool CanClimbLadder();
+ bool CanClimbHighLadder();
bool SummonEpona();
void Reset(bool resetSaveContext = true);
void SetContext(std::shared_ptr<Context> _ctx);
diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h
index 32dfc295e..a8fa7e4ab 100644
--- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h
+++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h
@@ -37,6 +37,7 @@ RANDO_ENUM_ITEM(RR_KF_OUTSIDE_LOST_WOODS)
RANDO_ENUM_ITEM(RR_KF_RUPEE_ALCOVE)
RANDO_ENUM_ITEM(RR_KF_STORMS_GROTTO)
RANDO_ENUM_ITEM(RR_THE_LOST_WOODS)
+RANDO_ENUM_ITEM(RR_LW_UNDER_BRIDGE)
RANDO_ENUM_ITEM(RR_LW_BRIDGE_FROM_FOREST)
RANDO_ENUM_ITEM(RR_LW_BRIDGE)
RANDO_ENUM_ITEM(RR_LW_FOREST_EXIT)
@@ -98,6 +99,7 @@ RANDO_ENUM_ITEM(RR_GF_NEAR_CHEST)
RANDO_ENUM_ITEM(RR_GF_LONG_ROOF)
RANDO_ENUM_ITEM(RR_GF_BELOW_GS)
RANDO_ENUM_ITEM(RR_GF_BELOW_CHEST)
+RANDO_ENUM_ITEM(RR_GF_TOWER)
RANDO_ENUM_ITEM(RR_GF_HBA_RANGE)
RANDO_ENUM_ITEM(RR_GF_ABOVE_JAIL)
RANDO_ENUM_ITEM(RR_GF_JAIL_WINDOW)
diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h
index e9b6ea035..2e3bf7836 100644
--- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h
+++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h
@@ -26,6 +26,7 @@ RANDO_ENUM_ITEM(RT_BUNNY_HOOD_JUMPS)
RANDO_ENUM_ITEM(RT_DAMAGE_BOOST_SIMPLE)
RANDO_ENUM_ITEM(RT_HOVER_BOOST_SIMPLE)
RANDO_ENUM_ITEM(RT_BOMBCHU_BEEHIVES)
+RANDO_ENUM_ITEM(RT_HOOKSHOT_LADDERS)
RANDO_ENUM_ITEM(RT_BLUE_FIRE_MUD_WALLS)
RANDO_ENUM_ITEM(RT_OPEN_UNDERWATER_CHEST)
RANDO_ENUM_ITEM(RT_DISTANT_BOULDER_COLLISION)
@@ -76,7 +77,7 @@ RANDO_ENUM_ITEM(RT_GV_CRATE_HOVERS)
RANDO_ENUM_ITEM(RT_GV_CHILD_TENT)
RANDO_ENUM_ITEM(RT_GV_CHILD_CUCCO_JUMP)
RANDO_ENUM_ITEM(RT_PASS_GUARDS_WITH_NOTHING)
-RANDO_ENUM_ITEM(RT_GF_CHILD_SKIP_WASTELAND_GATE)
+RANDO_ENUM_ITEM(RT_GF_WASTELAND_GATE_SIDEHOP_SKIP)
RANDO_ENUM_ITEM(RT_GF_ADULT_SKIP_WASTELAND_GATE)
RANDO_ENUM_ITEM(RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON)
RANDO_ENUM_ITEM(RT_GF_LEDGE_CLIP_INTO_GTG)
diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp
index 873f17b9d..98248e03f 100644
--- a/soh/soh/Enhancements/randomizer/settings.cpp
+++ b/soh/soh/Enhancements/randomizer/settings.cpp
@@ -1464,6 +1464,12 @@ void Settings::CreateOptions() {
"after recoil. Can be combined with \"Simple damage boosts\" for greater uses.");
OPT_TRICK(RT_BOMBCHU_BEEHIVES, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "Bombchu Beehives", "ChuBee",
"Allows exploding beehives with Bombchus.");
+ OPT_TRICK(RT_HOOKSHOT_LADDERS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "Hookshot Ladders", "HSLad",
+ "You can skip climb for hookshottable ladders can be skipped by hookshotting the top of the ladder from "
+ "the correct distance and angle.\n"
+ "This is more difficult for some ladders than others, and a few are not possible.\n"
+ "Hookshotting climbable walls in the same way is not a trick, as it is trivial to get an angle that "
+ "correctly ledge grabs.");
OPT_TRICK(RT_BLUE_FIRE_MUD_WALLS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "Blue Fire Beyond Red Ice",
"BluFire",
"Use Blue Fire to break mud walls, detonate bomb flowers, and break floor to King Dodongo.\nDoes not "
@@ -1676,12 +1682,15 @@ void Settings::CreateOptions() {
"Sneak Past Moving Gerudo Guards with No Items", "Guards",
"The logic normally guarantees Bow or Hookshot to stun them from a distance,"
"but every moving guard can be passed with basic movement and AI manipulation");
- OPT_TRICK(RT_GF_CHILD_SKIP_WASTELAND_GATE, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE },
- "Gerudo\'s Fortress Skip Wasteland Gate as Child", "GFHWC",
- "As child a sidehop out of bounds off the tower can be used to get past the gate.");
+ OPT_TRICK(RT_GF_WASTELAND_GATE_SIDEHOP_SKIP, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE },
+ "Gerudo\'s Fortress Gate Skip with Sidehop", "GFHWC",
+ "You can sidehop out of bounds from the tower, then sidehop again on the other side of the gate.\n\n"
+ "This is easiest and most useful for Child, but Adult can also do this to skip the Gerudo Jabber Nut.");
OPT_TRICK(RT_GF_ADULT_SKIP_WASTELAND_GATE, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::INTERMEDIATE },
"Gerudo\'s Fortress Skip Wasteland Gate as Adult", "GFHWA",
- "As adult a precise jumpslash out of bounds with hoverboots can be used to get past the gate.");
+ "As adult a precise jumpslash out of bounds with hoverboots from above the jail can be used to get past "
+ "the gate.\n\n"
+ "This can also be used to reach the tower and lower the gate for child without climb.");
OPT_TRICK(RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE },
"Gerudo\'s Fortress Warriors with Difficult Weapons", "GWDiff",
"Warriors can be defeated with Slingshot or Bombchus.");