Repository: HarbourMasters/Shipwright
Pull request #5121: Some location access fixes
Author: login: serprex
Created: 2025-03-16T16:27:43Z | Merged: 2025-03-19T11:42:19Z

Split out a few fixes I've made while working on #5105

<!--- section:artifacts:start -->
### Build Artifacts
  - [soh-linux.zip](https://nightly.link/HarbourMasters/Shipwright/actions/artifacts/2777368810.zip)
  - [soh-mac.zip](https://nightly.link/HarbourMasters/Shipwright/actions/artifacts/2777373689.zip)
  - [soh-windows.zip](https://nightly.link/HarbourMasters/Shipwright/actions/artifacts/2777385739.zip)
<!--- section:artifacts:end -->


Diff:
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp
index 2500e499691..4740a754160 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp
@@ -71,8 +71,8 @@ void RegionTable_Init_DekuTree() {
     }, {
         //Locations
         LOCATION(RC_DEKU_TREE_BASEMENT_CHEST,    true),
-        LOCATION(RC_DEKU_TREE_GS_BASEMENT_GATE,  logic->CanJumpslashExceptHammer() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE)),
-        LOCATION(RC_DEKU_TREE_GS_BASEMENT_VINES, logic->CanUseProjectile() || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->CanJumpslashExceptHammer())),
+        LOCATION(RC_DEKU_TREE_GS_BASEMENT_GATE,  logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH)),
+        LOCATION(RC_DEKU_TREE_GS_BASEMENT_VINES, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) ? ED_SHORT_JUMPSLASH : ED_BOMB_THROW)),
     }, {
         //Exits
         Entrance(RR_DEKU_TREE_LOBBY,               []{return true;}),
@@ -84,7 +84,7 @@ void RegionTable_Init_DekuTree() {
     areaTable[RR_DEKU_TREE_BASEMENT_SCRUB_ROOM] = Region("Deku Tree Basement Scrub Room", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
         //Exits
         Entrance(RR_DEKU_TREE_BASEMENT_LOWER,            []{return true;}),
-        Entrance(RR_DEKU_TREE_BASEMENT_WATER_ROOM_FRONT, []{return Here(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, []{return logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW);});}),
+        Entrance(RR_DEKU_TREE_BASEMENT_WATER_ROOM_FRONT, []{return Here(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, []{return logic->CanHitEyeTargets();});}),
     });
 
     areaTable[RR_DEKU_TREE_BASEMENT_WATER_ROOM_FRONT] = Region("Deku Tree Basement Water Room Front", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
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 bb5e1754f0f..4ae2e1e7075 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
@@ -154,6 +154,7 @@ void RegionTable_Init_DodongosCavern() {
         LOCATION(RC_DODONGOS_CAVERN_BLADE_ROOM_HEART,           true),
     }, {
         //Exits
+        Entrance(RR_DODONGOS_CAVERN_ARMOS_ROOM,           []{return true;}),
         Entrance(RR_DODONGOS_CAVERN_2F_SIDE_ROOM,         []{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return logic->CanBreakMudWalls() || (ctx->GetTrickOption(RT_DC_SCRUB_ROOM) && logic->HasItem(RG_GORONS_BRACELET));});}),
         Entrance(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, []{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);});}),
         Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER,      []{return (logic->IsAdult && ctx->GetTrickOption(RT_DC_JUMP)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}),
@@ -304,6 +305,7 @@ void RegionTable_Init_DodongosCavern() {
         LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_4, logic->CanBreakPots()),
     }, {
         //Exits
+        Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY,               []{return true;}),
         //This is possible with sticks and shield, igniting a first flower by "touch" then very quickly crouch stabbing in a way that cuts the corner to light the 3rd bomb on the other side, but that's a trick
         Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER,         []{return Here(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return logic->HasExplosives() || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_DC_STAIRCASE) && logic->CanUse(RG_FAIRY_BOW));});}),
         Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_MUD_WALL, []{return Here(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return logic->CanBreakMudWalls();});}),
@@ -460,9 +462,9 @@ void RegionTable_Init_DodongosCavern() {
         LOCATION(RC_DODONGOS_CAVERN_MQ_POE_ROOM_POT_4, logic->CanBreakPots()),
     }, {
         //Exits
-        Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, []{return Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);});}),
-        Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_LIZALFOS,   []{return true;}),
-        Entrance(RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM,   []{return Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);});}),
+        Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY,          []{return Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);});}),
+        Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_LIZALFOS, []{return true;}),
+        Entrance(RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM, []{return Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);});}),
     });
 
     areaTable[RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM] = Region("Dodongos Cavern Mad Scrub Room", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp
index c9f4ebc23e8..04efd49945e 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp
@@ -28,7 +28,7 @@ void RegionTable_Init_ForestTemple() {
     areaTable[RR_FOREST_TEMPLE_SOUTH_CORRIDOR] = Region("Forest Temple South Corridor", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
         //Exits
         Entrance(RR_FOREST_TEMPLE_FIRST_ROOM, []{return true;}),
-        Entrance(RR_FOREST_TEMPLE_LOBBY,      []{return logic->CanAttack() || logic->CanUse(RG_NUTS);}),
+        Entrance(RR_FOREST_TEMPLE_LOBBY,      []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
     });
 
     areaTable[RR_FOREST_TEMPLE_LOBBY] = Region("Forest Temple Lobby", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp
index 982ac16fcc1..c1a84656427 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp
@@ -61,7 +61,7 @@ void RegionTable_Init_GanonsCastle() {
         EventAccess(&logic->ForestTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_DINS_FIRE));}),
     }, {
         //Locations
-        LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanDamage()),
+        LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanKillEnemy(RE_WOLFOS)),
         LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_POT_1, logic->CanBreakPots() && (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_DINS_FIRE))),
         LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_POT_2, logic->CanBreakPots() && (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_DINS_FIRE))),
     }, {});
@@ -78,7 +78,7 @@ void RegionTable_Init_GanonsCastle() {
 
     areaTable[RR_GANONS_CASTLE_WATER_TRIAL] = Region("Ganon's Castle Water Trial", "Ganon's Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {
         //Events
-        EventAccess(&logic->BlueFireAccess,  []{return logic->BlueFireAccess || logic->HasBottle();}),
+        EventAccess(&logic->BlueFireAccess,  []{return true;}),
         EventAccess(&logic->FairyPot,        []{return logic->FairyPot || (logic->BlueFire() && logic->CanKillEnemy(RE_FREEZARD));}),
         EventAccess(&logic->WaterTrialClear, []{return logic->BlueFire() && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_LIGHT_ARROWS);}),
     }, {
@@ -112,7 +112,7 @@ void RegionTable_Init_GanonsCastle() {
         EventAccess(&logic->SpiritTrialClear, []{return logic->CanUse(RG_LIGHT_ARROWS) && (logic->CanUse(RG_MIRROR_SHIELD) || ctx->GetOption(RSK_SUNLIGHT_ARROWS)) && logic->CanUse(RG_BOMBCHU_5) && ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT));}),
     }, {
         //Locations
-        LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && logic->CanJumpslashExceptHammer()),
+        LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && (logic->CanJumpslashExceptHammer() || logic->CanUse(RG_BOMBCHU_5))),
         LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST,      (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))),
         LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_POT_1,                ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))),
         LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_POT_2,                ((ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslashExceptHammer()) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)))),
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp
index f0b9de5c3e5..0c45d755c07 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp
@@ -17,8 +17,8 @@ void RegionTable_Init_GerudoTrainingGround() {
 
     areaTable[RR_GERUDO_TRAINING_GROUND_LOBBY] = Region("Gerudo Training Ground Lobby", "Gerudo Training Ground", {RA_GERUDO_TRAINING_GROUND}, NO_DAY_NIGHT_CYCLE, {}, {
         //Locations
-        LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST,      logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)),
-        LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST,     logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)),
+        LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST,      logic->CanHitEyeTargets()),
+        LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST,     logic->CanHitEyeTargets()),
         LOCATION(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST,         logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true)),
         LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST,          logic->CanKillEnemy(RE_BEAMOS) && logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true)),
         LOCATION(RC_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)),
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp
index ff9b171c821..879ac1dce7f 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp
@@ -21,18 +21,18 @@ void RegionTable_Init_IceCavern() {
     }, {
         //Exits
         Entrance(RR_ICE_CAVERN_ENTRYWAY, []{return true;}),
-        Entrance(RR_ICE_CAVERN_MAIN,     []{return Here(RR_ICE_CAVERN_BEGINNING, []{return (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives() || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE);});}),
+        Entrance(RR_ICE_CAVERN_MAIN,     []{return Here(RR_ICE_CAVERN_BEGINNING, []{return logic->CanKillEnemy(RE_FREEZARD, ED_CLOSE, true, 4);});}),
     });
 
     areaTable[RR_ICE_CAVERN_MAIN] = Region("Ice Cavern", "Ice Cavern", {RA_ICE_CAVERN}, NO_DAY_NIGHT_CYCLE, {
         //Events
-        EventAccess(&logic->BlueFireAccess, []{return logic->BlueFireAccess || (logic->IsAdult && logic->HasBottle());}),
+        EventAccess(&logic->BlueFireAccess, []{return logic->IsAdult;}),
     }, {
         //Locations
         LOCATION(RC_ICE_CAVERN_MAP_CHEST,               logic->BlueFire() && logic->IsAdult),
         LOCATION(RC_ICE_CAVERN_COMPASS_CHEST,           logic->BlueFire()),
-        LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST,        logic->BlueFire() && (logic->CanJumpslash() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE))),
-        LOCATION(RC_SHEIK_IN_ICE_CAVERN,                logic->BlueFire() && (logic->CanJumpslash() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE)) && logic->IsAdult),
+        LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST,        logic->BlueFire() && logic->CanKillEnemy(RE_WOLFOS)),
+        LOCATION(RC_SHEIK_IN_ICE_CAVERN,                logic->BlueFire() && logic->CanKillEnemy(RE_WOLFOS) && logic->IsAdult),
         LOCATION(RC_ICE_CAVERN_FREESTANDING_POH,        logic->BlueFire()),
         LOCATION(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, logic->HookshotOrBoomerang()),
         LOCATION(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM,     logic->BlueFire() && logic->HookshotOrBoomerang()),
@@ -125,8 +125,8 @@ void RegionTable_Init_IceCavern() {
         LOCATION(RC_SHEIK_IN_ICE_CAVERN,            logic->CanKillEnemy(RE_STALFOS)),
     }, {
         //Exits
-        Entrance(RR_ICE_CAVERN_MQ_SCARECROW_ROOM, []{return logic->BlueFire() && Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
-        Entrance(RR_ICE_CAVERN_MQ_BEGINNING,      []{return logic->CanUse(RG_IRON_BOOTS) && Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
+        Entrance(RR_ICE_CAVERN_MQ_WEST_CORRIDOR, []{return Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
+        Entrance(RR_ICE_CAVERN_MQ_BEGINNING,     []{return logic->CanUse(RG_IRON_BOOTS) && Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
     });
 
     areaTable[RR_ICE_CAVERN_MQ_COMPASS_ROOM] = Region("Ice Cavern MQ Compass Room", "Ice Cavern", {RA_ICE_CAVERN}, NO_DAY_NIGHT_CYCLE, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
index fa9c7b085e8..7bfb98a870e 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
@@ -24,7 +24,6 @@ void RegionTable_Init_JabuJabusBelly() {
     //Combines Lift room middle and lower, 1F holes room, the forked corridor, and it's side rooms
     areaTable[RR_JABU_JABUS_BELLY_MAIN] = Region("Jabu Jabus Belly Main", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
         //Events
-        EventAccess(&logic->JabuRutoInB1,     []{return true;}),
         EventAccess(&logic->JabuWestTentacle, []{return logic->JabuRutoIn1F && logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}),
     }, {
         //Locations
@@ -263,7 +262,7 @@ void RegionTable_Init_JabuJabusBelly() {
 
     areaTable[RR_JABU_JABUS_BELLY_MQ_WEST_FORKED_ROOMS] = Region("Jabu Jabus Belly MQ West Forked Rooms", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
         //Events
-        EventAccess(&logic->JabuWestTentacle, []{return logic->CanUse(RG_BOOMERANG);}),
+        EventAccess(&logic->JabuWestTentacle, []{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}),
     }, {
         //Locations
         LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, Here(RR_JABU_JABUS_BELLY_MQ_WEST_FORKED_ROOMS, []{return logic->HasExplosives();}) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
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 bdcf8a4fa0a..8cf70fc3f3e 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp
@@ -79,8 +79,8 @@ void RegionTable_Init_ShadowTemple() {
     areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL] = Region("Shadow Temple Wind Tunnel", "Shadow Temple", {RA_SHADOW_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
         //Locations
         LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_CHEST,         true),
-        LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST,  logic->CanJumpslashExceptHammer()),
-        LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, true),
+        LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST,  logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 2)),
+        LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives()),
         LOCATION(RC_SHADOW_TEMPLE_GS_NEAR_SHIP,            logic->CanUse(RG_LONGSHOT) && logic->SmallKeys(RR_SHADOW_TEMPLE, 4, 5)),
         LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY,     logic->CanUse(RG_SUNS_SONG)),
         LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_POT_1,        logic->CanBreakPots()),
@@ -96,7 +96,7 @@ void RegionTable_Init_ShadowTemple() {
         //Locations
         LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST,       logic->CanUse(RG_DINS_FIRE)),
         LOCATION(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST,               logic->CanUse(RG_DINS_FIRE)),
-        LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST,  logic->CanJumpslashExceptHammer()),
+        LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST,  logic->CanKillEnemy(RE_FLOORMASTER)),
         //RANDOTODO check if child can reach the token
         LOCATION(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT,          logic->IsAdult && logic->CanAttack()),
         LOCATION(RC_SHADOW_TEMPLE_AFTER_BOAT_POT_1,             logic->CanBreakPots()),
@@ -181,7 +181,7 @@ void RegionTable_Init_ShadowTemple() {
     //Room exists for if it's ever possible to go backwards or void warp into the middle of shadow
     areaTable[RR_SHADOW_TEMPLE_MQ_B2_TO_B3_CORRIDOR] = Region("Shadow Temple MQ B2 to B3 Corridor", "Shadow Temple", {RA_SHADOW_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
         //Exits
-        Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS,   []{return logic->HasExplosives() && logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}),
+        Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS,   []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}),
         Entrance(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, []{return true;}),
         //bunnyhovers + lens lets you go from the very top of upper pit to the stationary invisible platform below quite easily
     });
diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp
index 408ded72e2b..dd3083743fa 100644
--- a/soh/soh/Enhancements/randomizer/logic.cpp
+++ b/soh/soh/Enhancements/randomizer/logic.cpp
@@ -671,7 +671,7 @@ namespace Rando {
                 }
                 return killed;
             case RE_BIG_OCTO:
-                //If chasing octo is annoying but with rolls you can catch him, and you need rang to get into this room without shenanigains anyway. Bunny makes it free
+                //If chasing octo is annoying but with rolls you can catch him, and you need rang to get into this room without shenanigans anyway. Bunny makes it free
                 return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_STICKS) || CanUse(RG_MASTER_SWORD);
             case RE_GOHMA:
                 return HasBossSoul(RG_GOHMA_SOUL) && CanJumpslash() &&
@@ -2338,7 +2338,6 @@ namespace Rando {
         MQSpiritMapRoomEnemies    = false;
         MQSpirit3SunsEnemies      = false;
         Spirit1FSilverRupees      = false;
-        JabuRutoInB1              = false;
         JabuRutoIn1F              = false;
 
         StopPerformanceTimer(PT_LOGIC_RESET);
diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h
index 4286cc5c363..d8fa9864bb5 100644
--- a/soh/soh/Enhancements/randomizer/logic.h
+++ b/soh/soh/Enhancements/randomizer/logic.h
@@ -175,7 +175,6 @@ class Logic {
     bool MQSpiritTimeTravelChest = false;
     bool MQSpirit3SunsEnemies = false;
     bool Spirit1FSilverRupees = false;
-    bool JabuRutoInB1 = false;
     bool JabuRutoIn1F = false;
 
     /* --- END OF HELPERS AND LOCATION ACCESS --- */
diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c
index 3ad26b1f6f4..26592b0cec4 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c
+++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c
@@ -201,12 +201,12 @@ void Entrance_Init(void) {
         }
 
         // Overwrite grotto related indices
-        if (originalIndex >= ENTRANCE_GROTTO_EXIT_START) {
+        if (originalIndex >= ENTRANCE_GROTTO_EXIT_START && originalIndex < ENTRANCE_GROTTO_EXIT_START + NUM_GROTTOS) {
             Grotto_SetExitOverride(originalIndex, overrideIndex);
             continue;
         }
 
-        if (originalIndex >= ENTRANCE_GROTTO_LOAD_START && originalIndex < ENTRANCE_GROTTO_EXIT_START) {
+        if (originalIndex >= ENTRANCE_GROTTO_LOAD_START && originalIndex < ENTRANCE_GROTTO_LOAD_START + NUM_GROTTOS) {
             Grotto_SetLoadOverride(originalIndex, overrideIndex);
             continue;
         }


Reviews:
user: login: Malkierian
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T20:10:57Z
user: login: serprex
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-18T20:18:34Z
user: login: Malkierian
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T20:49:32Z
user: login: serprex
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-18T23:38:12Z
user: login: Malkierian
body: The one other thing I saw is that a `CanGetEnemyDrop()` function exists in `logic.cpp`, and my thought was that it would be useful for GS locations, but considering it requires boomerang even for ED_CLOSE for gold skulltulas, I don't think it's finished, so :shipit:
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T00:49:33Z
user: login: Pepper0ni
body: Minor things I noticed, though none of them are blocking (maybe the shadow trick should be, but it's basically irrelevant as you need to do a hover to get that far backwards...)
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T01:23:00Z
user: login: serprex
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-19T01:39:07Z
user: login: serprex
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-19T01:40:14Z
user: login: Pepper0ni
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-19T01:40:40Z
user: login: serprex
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-19T11:09:26Z

Review comments:
diff_hunk: @@ -1807,7 +1807,6 @@ PotIdentity Randomizer::IdentifyPot(s32 sceneNum, s32 posX, s32 posZ) {
 
     if (location->GetRandomizerCheck() == RC_UNKNOWN_CHECK) {
         LUSLOG_WARN("IdentifyPot did not receive a valid RC value (%d).", location->GetRandomizerCheck());
-        assert(false);
path: soh/soh/Enhancements/randomizer/randomizer.cpp
user: login: Malkierian
body: Not entirely sure why this is being removed. It's already proved useful several times over, and it only does something in debug mode.
created_at: 2025-03-18T20:10:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1807,7 +1807,6 @@ PotIdentity Randomizer::IdentifyPot(s32 sceneNum, s32 posX, s32 posZ) {
 
     if (location->GetRandomizerCheck() == RC_UNKNOWN_CHECK) {
         LUSLOG_WARN("IdentifyPot did not receive a valid RC value (%d).", location->GetRandomizerCheck());
-        assert(false);
path: soh/soh/Enhancements/randomizer/randomizer.cpp
user: login: serprex
body: crashed in water temple
created_at: 2025-03-18T20:18:34Z
author_association: MEMBER
diff_hunk: @@ -1807,7 +1807,6 @@ PotIdentity Randomizer::IdentifyPot(s32 sceneNum, s32 posX, s32 posZ) {
 
     if (location->GetRandomizerCheck() == RC_UNKNOWN_CHECK) {
         LUSLOG_WARN("IdentifyPot did not receive a valid RC value (%d).", location->GetRandomizerCheck());
-        assert(false);
path: soh/soh/Enhancements/randomizer/randomizer.cpp
user: login: Malkierian
body: Then that means we need to add the exception for the non-existent pot to potsanity. That's exactly why the assert is there.
created_at: 2025-03-18T20:49:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1807,7 +1807,6 @@ PotIdentity Randomizer::IdentifyPot(s32 sceneNum, s32 posX, s32 posZ) {
 
     if (location->GetRandomizerCheck() == RC_UNKNOWN_CHECK) {
         LUSLOG_WARN("IdentifyPot did not receive a valid RC value (%d).", location->GetRandomizerCheck());
-        assert(false);
path: soh/soh/Enhancements/randomizer/randomizer.cpp
user: login: serprex
body: removed removing assert
created_at: 2025-03-18T23:38:12Z
author_association: MEMBER
diff_hunk: @@ -21,18 +21,18 @@ void RegionTable_Init_IceCavern() {
     }, {
         //Exits
         Entrance(RR_ICE_CAVERN_ENTRYWAY, []{return true;}),
-        Entrance(RR_ICE_CAVERN_MAIN,     []{return Here(RR_ICE_CAVERN_BEGINNING, []{return (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives() || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_DINS_FIRE);});}),
+        Entrance(RR_ICE_CAVERN_MAIN,     []{return Here(RR_ICE_CAVERN_BEGINNING, []{return logic->CanKillEnemy(RE_FREEZARD, ED_CLOSE, true, 3);});}),
path: soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp
user: login: Pepper0ni
body: There's 4 freezards, 1 just spawns later.
created_at: 2025-03-19T01:06:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -125,8 +125,8 @@ void RegionTable_Init_IceCavern() {
         LOCATION(RC_SHEIK_IN_ICE_CAVERN,            logic->CanKillEnemy(RE_STALFOS)),
     }, {
         //Exits
-        Entrance(RR_ICE_CAVERN_MQ_SCARECROW_ROOM, []{return logic->BlueFire() && Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
-        Entrance(RR_ICE_CAVERN_MQ_BEGINNING,      []{return logic->CanUse(RG_IRON_BOOTS) && Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
+        Entrance(RR_ICE_CAVERN_MQ_WEST_CORRIDOR, []{return logic->BlueFire() && Here(RR_ICE_CAVERN_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
path: soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp
user: login: Pepper0ni
body: I don't think the blue fire check is needed here anymore with this oversight fixed, as the red ice is on the border between the scarecrow room and the west corridor. WEST_CORRIDOR was probably a late addition for the pots that wasn't properly integrated.
created_at: 2025-03-19T01:10:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -24,7 +24,6 @@ void RegionTable_Init_JabuJabusBelly() {
     //Combines Lift room middle and lower, 1F holes room, the forked corridor, and it's side rooms
     areaTable[RR_JABU_JABUS_BELLY_MAIN] = Region("Jabu Jabus Belly Main", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
         //Events
-        EventAccess(&logic->JabuRutoInB1,     []{return true;}),
path: soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
user: login: Pepper0ni
body: With the way ruto cutscene skip works in VB, you need to find her in the upper part of holes room before she spawns in the lower part. If the ability to climb is ever shuffled and doorsanity is complete, it's possible that the player may have basement of jabu holes room access and not the first floor, meaning ruto cannot be carried.

Because of this I would comment out this event rather than remove it, as a reminder of this niche interaction for whoever has to untangle that hell. I am happy to see the event removed from current processing for minor seed gen performance reasons (events cause rechecks in playthrough creation).
created_at: 2025-03-19T01:16:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -181,7 +181,7 @@ void RegionTable_Init_ShadowTemple() {
     //Room exists for if it's ever possible to go backwards or void warp into the middle of shadow
     areaTable[RR_SHADOW_TEMPLE_MQ_B2_TO_B3_CORRIDOR] = Region("Shadow Temple MQ B2 to B3 Corridor", "Shadow Temple", {RA_SHADOW_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
         //Exits
-        Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS,   []{return logic->HasExplosives() && logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}),
+        Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS,   []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}),
path: soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp
user: login: Pepper0ni
body: Good catch on this wall being 1 way collision, but there's a trick for moving through such walls (RT_VISIBLE_COLLISION).

I tend to forget this trick exists too, so it probably needs adding to a lot more places....
created_at: 2025-03-19T01:19:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -24,7 +24,6 @@ void RegionTable_Init_JabuJabusBelly() {
     //Combines Lift room middle and lower, 1F holes room, the forked corridor, and it's side rooms
     areaTable[RR_JABU_JABUS_BELLY_MAIN] = Region("Jabu Jabus Belly Main", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
         //Events
-        EventAccess(&logic->JabuRutoInB1,     []{return true;}),
path: soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
user: login: serprex
body: The flag is never used atm, seems like correct handling of it should be left to choose which events are needed (eg, it gets way weirder if this isn't handled until after doors)
created_at: 2025-03-19T01:39:07Z
author_association: MEMBER
diff_hunk: @@ -181,7 +181,7 @@ void RegionTable_Init_ShadowTemple() {
     //Room exists for if it's ever possible to go backwards or void warp into the middle of shadow
     areaTable[RR_SHADOW_TEMPLE_MQ_B2_TO_B3_CORRIDOR] = Region("Shadow Temple MQ B2 to B3 Corridor", "Shadow Temple", {RA_SHADOW_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
         //Exits
-        Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS,   []{return logic->HasExplosives() && logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}),
+        Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS,   []{return logic->SmallKeys(RR_SHADOW_TEMPLE, 2);}),
path: soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp
user: login: serprex
body: Yes, doors runs into it a lot

Looks like it only applies to couple kak checks. In particular it refers to visible one way collision. But in this case the bombable wall is not visible when facing it from the wrong side
created_at: 2025-03-19T01:40:13Z
author_association: MEMBER
diff_hunk: @@ -24,7 +24,6 @@ void RegionTable_Init_JabuJabusBelly() {
     //Combines Lift room middle and lower, 1F holes room, the forked corridor, and it's side rooms
     areaTable[RR_JABU_JABUS_BELLY_MAIN] = Region("Jabu Jabus Belly Main", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
         //Events
-        EventAccess(&logic->JabuRutoInB1,     []{return true;}),
path: soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
user: login: Pepper0ni
body: It makes sense that doors has to do weird things for ruto, and i can't remember what other paranoid thought had me leave this in, so it can go then.
created_at: 2025-03-19T01:40:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1807,7 +1807,6 @@ PotIdentity Randomizer::IdentifyPot(s32 sceneNum, s32 posX, s32 posZ) {
 
     if (location->GetRandomizerCheck() == RC_UNKNOWN_CHECK) {
         LUSLOG_WARN("IdentifyPot did not receive a valid RC value (%d).", location->GetRandomizerCheck());
-        assert(false);
path: soh/soh/Enhancements/randomizer/randomizer.cpp
user: login: serprex
body: #5145
created_at: 2025-03-19T11:09:25Z
author_association: MEMBER

PR comments:
user: login: Pepper0ni
created_at: 2025-03-19T00:51:05Z
body: CanGetEnemyDrop globally returns true if range is less than or equal to MS jumpslash and you can kill the enemy.
author_association: CONTRIBUTOR
user: login: Malkierian
created_at: 2025-03-19T00:52:26Z
body: Then perhaps those cases should be removed from the gold skulltula flow to avoid confusion. I was looking directly at that rather than what came before XD. Not in this PR, though, probably.
author_association: CONTRIBUTOR
user: login: Pepper0ni
created_at: 2025-03-19T00:56:03Z
body: The enemy kill functions are not in anything close to a final state, I'm not even 100% is I want to handle gold skulls and other drops in the same function, it just doesn't matter until we get proper enemy logic. The logic for the catch-all was to not bother processing cases where the player can just pick the thing up without height or distance issues. 

A different style option would be to remove the shortest ranges and add a default to suppress a warning.
author_association: CONTRIBUTOR