From 164f7480943bc8f1389de07897f68953549c0768 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Sat, 22 Mar 2025 15:28:05 +0000 Subject: [PATCH 01/18] Rando: Shuffle Climb --- .../vanilla-behavior/GIVanillaBehavior.h | 8 ++++ .../3drando/hint_list/hint_list_item.cpp | 4 +- .../randomizer/3drando/item_pool.cpp | 4 ++ soh/soh/Enhancements/randomizer/draw.cpp | 19 ++++++++ soh/soh/Enhancements/randomizer/draw.h | 1 + soh/soh/Enhancements/randomizer/entrance.cpp | 36 +++++++-------- .../Enhancements/randomizer/hook_handlers.cpp | 11 +++++ soh/soh/Enhancements/randomizer/item_list.cpp | 2 + .../dungeons/bottom_of_the_well.cpp | 16 +++---- .../location_access/dungeons/deku_tree.cpp | 46 +++++++++++++------ .../dungeons/dodongos_cavern.cpp | 4 +- .../location_access/dungeons/fire_temple.cpp | 27 ++++++----- .../dungeons/forest_temple.cpp | 30 ++++++------ .../dungeons/gerudo_training_ground.cpp | 4 +- .../dungeons/jabujabus_belly.cpp | 10 ++-- .../dungeons/spirit_temple.cpp | 5 +- .../overworld/castle_grounds.cpp | 44 ++++++++++++------ .../overworld/death_mountain_crater.cpp | 8 +++- .../overworld/death_mountain_trail.cpp | 19 +++++--- .../overworld/gerudo_fortress.cpp | 6 +-- .../overworld/gerudo_valley.cpp | 3 +- .../overworld/hyrule_field.cpp | 8 +++- .../location_access/overworld/kakariko.cpp | 8 ++-- .../overworld/kokiri_forest.cpp | 20 ++++++-- .../location_access/overworld/lake_hylia.cpp | 4 +- .../location_access/overworld/lost_woods.cpp | 2 +- .../overworld/sacred_forest_meadow.cpp | 36 +++++++++++---- .../overworld/zoras_fountain.cpp | 2 +- .../location_access/overworld/zoras_river.cpp | 15 +++++- soh/soh/Enhancements/randomizer/logic.cpp | 15 +++++- .../randomizer/option_descriptions.cpp | 1 + .../Enhancements/randomizer/randomizer.cpp | 5 +- .../Enhancements/randomizer/randomizerTypes.h | 16 +++++++ .../Enhancements/randomizer/randomizer_inf.h | 1 + soh/soh/Enhancements/randomizer/savefile.cpp | 4 ++ soh/soh/Enhancements/randomizer/settings.cpp | 3 ++ .../actors/ovl_player_actor/z_player.c | 4 ++ 37 files changed, 322 insertions(+), 129 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 153358a4c91..7fcd45f478a 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -294,6 +294,14 @@ typedef enum { // - `*EnGm` VB_CHECK_RANDO_PRICE_OF_MEDIGORON, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - None + VB_CLIMB, + // #### `result` // ```c // CHECK_BTN_ALL(input->press.button, BTN_START) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index 6a0c8babe64..3f833a4ca0c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -2108,7 +2108,9 @@ void StaticData::HintTable_Init_Item() { { CustomMessage("a master unlocker", /*german*/ "ein Meisterentsperrer", /*french*/ "un Kit de Déverrouillage") }); // /*spanish*/un desbloqueador maestro - //RANDOTODO if these are ever used for anything other than name, they want abscure and ambiguous hints + //RANDOTODO if these are ever used for anything other than name, they want obscure and ambiguous hints + hintTextTable[RHT_CLIMB] = HintText(CustomMessage("the ability to climb", /*german*/"!!!", /*french*/"la capacité de grimper")); + hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("an infinite Quiver", /*german*/"der unendliche Köcher", /*french*/"un Carquois Infini")); hintTextTable[RHT_BOMB_BAG_INF] = HintText(CustomMessage("an infinite Bomb Bag", /*german*/"die unendliche Bombentasche", /*french*/"un Sac de Bombe sans fond")); diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 78f09a8d9ef..390951e0db4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -392,6 +392,10 @@ void GenerateItemPool() { int bronzeScale = ctx->GetOption(RSK_SHUFFLE_SWIM) ? 1 : 0; AddItemToPool(RG_PROGRESSIVE_SCALE, 3 + bronzeScale, 2 + bronzeScale, 2 + bronzeScale, 2 + bronzeScale); + if (ctx->GetOption(RSK_SHUFFLE_CLIMB)) { + AddFixedItemToPool(RG_CLIMB, 1); + } + if (ctx->GetOption(RSK_SHUFFLE_BEEHIVES)) { PlaceItemsForType(RCTYPE_BEEHIVE, true, true); } diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 78295f45c50..ec2bdfb80ff 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -30,6 +30,7 @@ extern "C" { #include "objects/object_fd/object_fd.h" #include "objects/object_mamenoki/object_mamenoki.h" #include "objects/object_mo/object_mo.h" +#include "objects/object_mori_objects/object_mori_objects.h" #include "objects/object_sst/object_sst.h" #include "overlays/actors/ovl_Boss_Goma/z_boss_goma.h" #include "overlays/ovl_Boss_Sst/ovl_Boss_Sst.h" @@ -1136,6 +1137,24 @@ extern "C" void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getIte CLOSE_DISPS(play->state.gfxCtx); } +extern "C" void Randomizer_DrawLadder(PlayState* play, GetItemEntry* getItemEntry) { + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + gSPSegment(POLY_OPA_DISP++, 0x08, (uintptr_t)gMoriHashiraTex); + Matrix_Translate(0, -30, 0, MTXMODE_APPLY); + Matrix_Scale(1.0f, 0.375f, 1.0f, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gMoriHashigoLadderDL); + + Matrix_RotateY(M_PIf, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gMoriHashigoLadderDL); + + CLOSE_DISPS(play->state.gfxCtx); +} + extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry) { Vec3f pos; OPEN_DISPS(play->state.gfxCtx); diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index 474835c53ca..885acb1442f 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -22,6 +22,7 @@ void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawLadder(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry* getItemEntry); diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index f008c33a192..13a95f993aa 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -261,8 +261,8 @@ void SetAllEntrancesData() { { EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU } }, { { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, ENTR_FOREST_TEMPLE_ENTRANCE }, { EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE } }, - { { EntranceType::Dungeon, RR_DMC_CENTRAL_LOCAL, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE }, - { EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } }, + { { EntranceType::Dungeon, RR_DMC_OUTSIDE_FIRE_TEMPLE, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE }, + { EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_OUTSIDE_FIRE_TEMPLE, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } }, { { EntranceType::Dungeon, RR_LH_FROM_WATER_TEMPLE, RR_WATER_TEMPLE_ENTRYWAY, ENTR_WATER_TEMPLE_ENTRANCE }, { EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE } }, { { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, ENTR_SPIRIT_TEMPLE_ENTRANCE }, @@ -353,8 +353,8 @@ void SetAllEntrancesData() { { { EntranceType::Interior, RR_ZORAS_FOUNTAIN, RR_ZF_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF }, { EntranceType::Interior, RR_ZF_GREAT_FAIRY_FOUNTAIN, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY } }, - { { EntranceType::SpecialInterior, RR_KOKIRI_FOREST, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_1 }, - { EntranceType::SpecialInterior, RR_KF_LINKS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE } }, + { { EntranceType::SpecialInterior, RR_KF_LINKS_PORCH, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_1 }, + { EntranceType::SpecialInterior, RR_KF_LINKS_HOUSE, RR_KF_LINKS_PORCH, ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE } }, { { EntranceType::SpecialInterior, RR_TOT_ENTRANCE, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_ENTRANCE }, { EntranceType::SpecialInterior, RR_TEMPLE_OF_TIME, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE } }, { { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_WINDMILL_LOWER, ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL }, @@ -413,14 +413,14 @@ void SetAllEntrancesData() { { EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET) } }, { { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET) }, { EntranceType::GrottoGrave, RR_DMT_STORMS_GROTTO, RR_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET) } }, - { { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET) }, - { EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_SUMMIT, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET) } }, + { { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_AVALANCHE, RR_DMT_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET) }, + { EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_AVALANCHE, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET) } }, { { EntranceType::GrottoGrave, RR_KAK_BACKYARD, RR_KAK_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET) }, { EntranceType::GrottoGrave, RR_KAK_OPEN_GROTTO, RR_KAK_BACKYARD, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET) } }, { { EntranceType::GrottoGrave, RR_KAKARIKO_VILLAGE, RR_KAK_REDEAD_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET) }, { EntranceType::GrottoGrave, RR_KAK_REDEAD_GROTTO, RR_KAKARIKO_VILLAGE, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET) } }, - { { EntranceType::GrottoGrave, RR_HYRULE_CASTLE_GROUNDS, RR_HC_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET) }, - { EntranceType::GrottoGrave, RR_HC_STORMS_GROTTO, RR_CASTLE_GROUNDS, ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET) } }, + { { EntranceType::GrottoGrave, RR_HC_MOAT, RR_HC_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET) }, + { EntranceType::GrottoGrave, RR_HC_STORMS_GROTTO, RR_HC_MOAT, ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET) } }, { { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_TEKTITE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET) }, { EntranceType::GrottoGrave, RR_HF_TEKTITE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET) } }, { { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_KAK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET) }, @@ -443,14 +443,14 @@ void SetAllEntrancesData() { { EntranceType::GrottoGrave, RR_SFM_WOLFOS_GROTTO, RR_SFM_ENTRYWAY, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET) } }, { { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET) }, { EntranceType::GrottoGrave, RR_SFM_STORMS_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET) } }, - { { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET) }, - { EntranceType::GrottoGrave, RR_SFM_FAIRY_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET) } }, + { { EntranceType::GrottoGrave, RR_SFM_OUTSIDE_FAIRY_GROTTO, RR_SFM_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET) }, + { EntranceType::GrottoGrave, RR_SFM_FAIRY_GROTTO, RR_SFM_OUTSIDE_FAIRY_GROTTO, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET) } }, { { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_LW_SCRUBS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET) }, { EntranceType::GrottoGrave, RR_LW_SCRUBS_GROTTO, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET) } }, { { EntranceType::GrottoGrave, RR_THE_LOST_WOODS, RR_LW_NEAR_SHORTCUTS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) }, { EntranceType::GrottoGrave, RR_LW_NEAR_SHORTCUTS_GROTTO, RR_THE_LOST_WOODS, ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) } }, - { { EntranceType::GrottoGrave, RR_KOKIRI_FOREST, RR_KF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET) }, - { EntranceType::GrottoGrave, RR_KF_STORMS_GROTTO, RR_KOKIRI_FOREST, ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET) } }, + { { EntranceType::GrottoGrave, RR_KF_OUTSIDE_LOST_WOODS, RR_KF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET) }, + { EntranceType::GrottoGrave, RR_KF_STORMS_GROTTO, RR_KF_OUTSIDE_LOST_WOODS, ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET) } }, { { EntranceType::GrottoGrave, RR_ZORAS_DOMAIN_ISLAND, RR_ZD_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET) }, { EntranceType::GrottoGrave, RR_ZD_STORMS_GROTTO, RR_ZORAS_DOMAIN_ISLAND, ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET) } }, { { EntranceType::GrottoGrave, RR_GF_NEAR_GROTTO, RR_GF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET) }, @@ -474,8 +474,8 @@ void SetAllEntrancesData() { { { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_LW_BRIDGE_FROM_FOREST, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT }, { EntranceType::Overworld, RR_LW_BRIDGE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_LOWER_EXIT } }, - { { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_SOUTH_EXIT }, - { EntranceType::Overworld, RR_LW_FOREST_EXIT, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_UPPER_EXIT } }, + { { EntranceType::Overworld, RR_KF_OUTSIDE_LOST_WOODS, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_SOUTH_EXIT }, + { EntranceType::Overworld, RR_LW_FOREST_EXIT, RR_KF_OUTSIDE_LOST_WOODS, ENTR_KOKIRI_FOREST_UPPER_EXIT } }, { { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_GC_WOODS_WARP, ENTR_GORON_CITY_TUNNEL_SHORTCUT }, { EntranceType::Overworld, RR_GC_WOODS_WARP, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_TUNNEL_SHORTCUT } }, { { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_ZR_FROM_SHORTCUT, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT }, @@ -484,8 +484,8 @@ void SetAllEntrancesData() { { EntranceType::Overworld, RR_SFM_ENTRYWAY, RR_LW_BEYOND_MIDO, ENTR_LOST_WOODS_NORTH_EXIT } }, { { EntranceType::Overworld, RR_LW_BRIDGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_WOODED_EXIT }, { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LW_BRIDGE, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT } }, - { { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_NORTH_EXIT }, - { EntranceType::Overworld, RR_LAKE_HYLIA, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_FENCE_EXIT } }, + { { EntranceType::Overworld, RR_HF_TO_LAKE_HYLIA, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_NORTH_EXIT }, + { EntranceType::Overworld, RR_LAKE_HYLIA, RR_HF_TO_LAKE_HYLIA, ENTR_HYRULE_FIELD_FENCE_EXIT } }, { { EntranceType::Overworld, RR_HYRULE_FIELD, RR_GERUDO_VALLEY, ENTR_GERUDO_VALLEY_EAST_EXIT }, { EntranceType::Overworld, RR_GERUDO_VALLEY, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ROCKY_PATH } }, { { EntranceType::Overworld, RR_HYRULE_FIELD, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT }, @@ -1520,7 +1520,7 @@ int EntranceShuffler::ShuffleAllEntrances() { { EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY), GetEntrance(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW) }, { EntranceNameByRegions(RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY), - GetEntrance(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL) }, + GetEntrance(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_OUTSIDE_FIRE_TEMPLE) }, { EntranceNameByRegions(RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY), GetEntrance(RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE) }, { EntranceNameByRegions(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY), @@ -1540,7 +1540,7 @@ int EntranceShuffler::ShuffleAllEntrances() { GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN) }, { EntranceNameByRegions(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW), GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW) }, - { EntranceNameByRegions(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL), + { EntranceNameByRegions(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_OUTSIDE_FIRE_TEMPLE), GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL) }, { EntranceNameByRegions(RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE), GetEntrance(RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA) }, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index acf4262bd43..8305ce33393 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -850,6 +850,17 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l va_copy(args, originalArgs); switch (id) { + case VB_CLIMB: + if (RAND_GET_OPTION(RSK_SHUFFLE_CLIMB) && !Flags_GetRandomizerInf(RAND_INF_CAN_CLIMB)) { + s32* x = va_arg(args, s32*); + s32* y = va_arg(args, s32*); + + *x = 0; + if (*y > 0) { + *y = 0; + } + } + break; case VB_ALLOW_ENTRANCE_CS_FOR_EITHER_AGE: { s32 entranceIndex = va_arg(args, s32); diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 4ff3e1e0460..b5db01fb15c 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -371,6 +371,8 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); + itemTable[RG_CLIMB] = Item(RG_CLIMB, Text{ "Climb", "", "" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_CLIMB, RG_CLIMB, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_CLIMB].SetCustomDrawFunc(Randomizer_DrawLadder); itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_PROGRESSIVE_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag); 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 a66c7e43f4c..b3be5e1330c 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 @@ -48,8 +48,8 @@ void RegionTable_Init_BottomOfTheWell() { Entrance(RR_BOTW_HIDDEN_POTS, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), Entrance(RR_BOTW_CORNER_CRAWLSPACE, []{return logic->IsChild/*CanCrawl*/;}), //Climb always needed in case water is lowered out of logic - Entrance(RR_BOTW_BEHIND_MOAT, []{return (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE) || - (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))/*CanClimb*/);}), + Entrance(RR_BOTW_BEHIND_MOAT, []{return ((logic->Get(LOGIC_BOTW_LOWERED_WATER) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))) || logic->HasItem(RG_BRONZE_SCALE) || + (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)));}), Entrance(RR_BOTW_NEAR_BOSS_LOWER, []{return logic->Get(LOGIC_BOTW_LOWERED_WATER) && 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 @@ -148,7 +148,7 @@ void RegionTable_Init_BottomOfTheWell() { //Exits //Climb always needed in case water is lowered out of logic Entrance(RR_BOTW_PERIMETER, []{return (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE) || - (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))/* && CanClimb()*/);}), + (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_BOTW_CRYPT, []{return true;}), }); @@ -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, []{return true/*CanClimbHigh()*/;}), + Entrance(RR_BOTW_HIDDEN_POTS, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), //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, []{return 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));});}), @@ -280,12 +280,12 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BOMB_RIGHT_HEART, logic->HasExplosives()), }, { //Exits - Entrance(RR_BOTW_ENTRYWAY, []{return logic->IsChild/*CanCrawl() && CanClimb()*/;}), + Entrance(RR_BOTW_ENTRYWAY, []{return logic->IsChild/*CanCrawl()*/ && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_BOTW_MQ_MIDDLE, []{return logic->Get(LOGIC_BOTW_MQ_OPENED_GATES);}), Entrance(RR_BOTW_MQ_PIT_CAGE, []{return AnyAgeTime([]{return logic->BlastOrSmash();}) && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), //Climb always needed in case water is lowered out of logic - Entrance(RR_BOTW_MQ_BEHIND_MOAT, []{return (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE) || - (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))/*&& CanClimb()*/);}), + Entrance(RR_BOTW_MQ_BEHIND_MOAT, []{return ((logic->Get(LOGIC_BOTW_LOWERED_WATER) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))) || logic->HasItem(RG_BRONZE_SCALE) || + (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)));}), Entrance(RR_BOTW_MQ_CORNER_CRAWLSPACE, []{return logic->IsChild/*CanCrawl()*/;}), Entrance(RR_BOTW_MQ_NEAR_BOSS_LOWER, []{return logic->IsChild/*CanCrawl()*/ && logic->Get(LOGIC_BOTW_LOWERED_WATER);}), Entrance(RR_BOTW_MQ_B3, []{return true;}), @@ -419,7 +419,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, []{return true/*CanClimbHigh()*/;}), + Entrance(RR_BOTW_MQ_PERIMETER, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), }); 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/deku_tree.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp index eb6ef545b31..9caf1db9d56 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -33,13 +33,33 @@ void RegionTable_Init_DekuTree() { }, { //Exits Entrance(RR_DEKU_TREE_ENTRYWAY, []{return true;}), - Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return true;}), - Entrance(RR_DEKU_TREE_COMPASS_ROOM, []{return true;}), - Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return AnyAgeTime([]{return logic->CanAttack() || logic->CanUse(RG_NUTS);});}), + Entrance(RR_DEKU_TREE_LOBBY_2F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return AnyAgeTime([]{return logic->HasFireSource();});}), Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return false;}), Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, []{return false;}), }); + areaTable[RR_DEKU_TREE_LOBBY_2F] = Region("Deku Tree Lobby 2F", SCENE_DEKU_TREE, {}, { + //Locations + LOCATION(RC_DEKU_TREE_MAP_CHEST, true), + LOCATION(RC_DEKU_TREE_LOBBY_LOWER_HEART, true), + }, { + //Exits + Entrance(RR_DEKU_TREE_LOBBY, []{return true;}), + Entrance(RR_DEKU_TREE_LOBBY_3F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return true;}), + }); + + areaTable[RR_DEKU_TREE_LOBBY_3F] = Region("Deku Tree Lobby 3F", SCENE_DEKU_TREE, {}, { + //Locations + LOCATION(RC_DEKU_TREE_LOBBY_UPPER_HEART, logic->CanPassEnemy(RE_BIG_SKULLTULA)), + }, { + //Exits + Entrance(RR_DEKU_TREE_LOBBY_2F, []{return true;}), + Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return AnyAgeTime([]{return logic->CanPassEnemy(RE_BIG_SKULLTULA);});}), + Entrance(RR_DEKU_TREE_COMPASS_ROOM, []{return true;}), + }); + areaTable[RR_DEKU_TREE_2F_MIDDLE_ROOM] = Region("Deku Tree 2F Middle Room", SCENE_DEKU_TREE, {}, {}, { //Exits Entrance(RR_DEKU_TREE_LOBBY, []{return AnyAgeTime([]{return logic->CanReflectNuts() || logic->CanUse(RG_MEGATON_HAMMER);});}), @@ -48,8 +68,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_SLINGSHOT_ROOM] = Region("Deku Tree Slingshot Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, true), - LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, true), + LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_1, logic->CanCutShrubs() && logic->CanReflectNuts()), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_2, logic->CanCutShrubs() && logic->CanReflectNuts()), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_3, logic->CanCutShrubs() && logic->CanReflectNuts()), @@ -89,7 +109,7 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_BASEMENT_GRASS_2, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEKU_TREE_LOBBY, []{return true;}), + Entrance(RR_DEKU_TREE_LOBBY, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), Entrance(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, []{return AnyAgeTime([]{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);});}), Entrance(RR_DEKU_TREE_BASEMENT_UPPER, []{return logic->IsAdult || ctx->GetTrickOption(RT_DEKU_B1_SKIP) || logic->CanGroundJump() || logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK);}), Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return false;}), @@ -103,7 +123,7 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_BASEMENT_SCRUB_ROOM_GRASS_4, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return true;}), + Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return logic->HasItem(RG_CLIMB);}), Entrance(RR_DEKU_TREE_BASEMENT_WATER_ROOM_FRONT, []{return AnyAgeTime([]{return logic->CanHitEyeTargets();});}), }); @@ -205,7 +225,7 @@ void RegionTable_Init_DekuTree() { //Exits Entrance(RR_DEKU_TREE_ENTRYWAY, []{return true;}), //may need canAvoid logic with enemy shuffle - Entrance(RR_DEKU_TREE_MQ_2F, []{return true;}), + Entrance(RR_DEKU_TREE_MQ_2F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), //Swim is not required because you can jump with enough momentum to hit land. //You even avoid fall damage if you hit the shallow water, though it's obscure knowledge so may be a trick //if it is, then we need a landing room with (IsAdult || HasItem(RG_BRONZE_SCALE) || TakeDamage() || that trick) to reach basement @@ -228,7 +248,7 @@ void RegionTable_Init_DekuTree() { //Exits Entrance(RR_DEKU_TREE_MQ_1F, []{return true;}), //Will need canAvoid logic with enemy shuffle - Entrance(RR_DEKU_TREE_MQ_3F, []{return true;}), + Entrance(RR_DEKU_TREE_MQ_3F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), Entrance(RR_DEKU_TREE_MQ_EYE_TARGET_ROOM, []{return logic->Get(LOGIC_DEKU_TREE_MQ_2F_BURNED_WEB);}), }); @@ -284,7 +304,7 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_COMPASS_ROOM] = Region("Deku Tree MQ Compass Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()), @@ -292,7 +312,7 @@ void RegionTable_Init_DekuTree() { }, { //Exits Entrance(RR_DEKU_TREE_MQ_EYE_TARGET_ROOM, []{return logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_HOVER_BOOTS);}), - Entrance(RR_DEKU_TREE_MQ_PAST_BOULDER_VINES, []{return AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))) || (logic->CanUse(RG_MEGATON_HAMMER) && (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS)));});}), + Entrance(RR_DEKU_TREE_MQ_PAST_BOULDER_VINES, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))) || (logic->CanUse(RG_MEGATON_HAMMER) && (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->HasItem(RG_CLIMB)));});}), }); areaTable[RR_DEKU_TREE_MQ_PAST_BOULDER_VINES] = Region("Deku Tree MQ Past Boulder Vines", SCENE_DEKU_TREE, {}, { @@ -317,7 +337,7 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LOWER_GRASS_4, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEKU_TREE_MQ_1F, []{return true;}), + Entrance(RR_DEKU_TREE_MQ_1F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), Entrance(RR_DEKU_TREE_MQ_BASEMENT_SOUTHEAST_ROOM, []{return AnyAgeTime([]{return logic->CanHitEyeTargets();});}), //includes RR_DEKU_TREE_MQ_BASEMENT_SOUTHEAST_ROOM Access, other fire sources clear directly from there Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, []{return AnyAgeTime([]{return logic->CanHitEyeTargets();}) && logic->Get(LOGIC_DEKU_TREE_MQ_CLEARED_SE_ROOM) && AnyAgeTime([]{return logic->CanUse(RG_STICKS);});}), @@ -442,7 +462,7 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_MQ_BEFORE_BOSS_GRASS_3, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, []{return logic->HasItem(RG_CLIMB) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, []{return AnyAgeTime([]{return logic->CanReflectNuts();});}), }); 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 a0f380fd5a1..5e7230ae50c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp @@ -134,7 +134,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_STAIRS_UPPER] = Region("Dodongos Cavern Stairs Upper", SCENE_DODONGOS_CAVERN, {}, { //Locations LOCATION(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, logic->Get(LOGIC_DC_LIFT_PLATFORM) ? ED_BOOMERANG : ED_LONGSHOT)), - LOCATION(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, logic->IsAdult || logic->CanAttack()), + LOCATION(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, (logic->HasItem(RG_CLIMB) && (logic->IsAdult || logic->CanAttack())) || logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), LOCATION(RC_DODONGOS_CAVERN_STAIRCASE_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_STAIRCASE_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_STAIRCASE_POT_3, logic->CanBreakPots()), @@ -167,7 +167,7 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_BLADE_GRASS, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DODONGOS_CAVERN_ARMOS_ROOM, []{return true;}), + Entrance(RR_DODONGOS_CAVERN_ARMOS_ROOM, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, []{return AnyAgeTime([]{return logic->CanBreakMudWalls() || (ctx->GetTrickOption(RT_DC_SCRUB_ROOM) && logic->HasItem(RG_GORONS_BRACELET));});}), Entrance(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, []{return AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);});}), Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, []{return (logic->IsAdult && (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->CanGroundJump())) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp index a0d39399c39..2e5307de3d9 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -143,7 +143,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LAVA_GEYSER_1F] = Region("Fire Temple Lava Geyser 1F", SCENE_FIRE_TEMPLE, {}, {}, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 3);}), - Entrance(RR_FIRE_TEMPLE_LAVA_GEYSER_GRATE, []{return logic->FireTimer() >= 40/* && CanClimbHigh()*/;}), + Entrance(RR_FIRE_TEMPLE_LAVA_GEYSER_GRATE, []{return logic->FireTimer() >= 40 && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_FIRE_TEMPLE_LAVA_GEYSER_TORCH, []{return logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 40;}), }); @@ -176,7 +176,7 @@ void RegionTable_Init_FireTemple() { //Exits Entrance(RR_FIRE_TEMPLE_LAVA_GEYSER_1F, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 4);}), Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);}), - Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, []{return logic->IsAdult && (((logic->HasItem(RG_GORONS_BRACELET) || ctx->GetTrickOption(RT_FIRE_STRENGTH))/*CanUse(RG_CLIMB)*/) || logic->CanGroundJump()) && logic->CanHitSwitch(ED_BOMB_THROW);}), + Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, []{return logic->IsAdult && logic->HasItem(RG_CLIMB) && ((logic->HasItem(RG_GORONS_BRACELET) || ctx->GetTrickOption(RT_FIRE_STRENGTH)) || logic->CanGroundJump()) && logic->CanHitSwitch(ED_BOMB_THROW);}), }); areaTable[RR_FIRE_TEMPLE_SHORTCUT_CLIMB] = Region("Fire Temple Shortcut Climb", SCENE_FIRE_TEMPLE, { @@ -188,7 +188,7 @@ void RegionTable_Init_FireTemple() { }, { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, []{return true;}), - Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, []{return true/*CanUse(RG_CLIMB)*/;}), + Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, []{return logic->HasItem(RG_CLIMB);}), }); areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER] = Region("Fire Temple Boulder Maze Lower", SCENE_FIRE_TEMPLE, {}, { @@ -258,15 +258,18 @@ void RegionTable_Init_FireTemple() { Entrance(RR_FIRE_TEMPLE_GS_CLIMB_4F, []{return logic->ReachScarecrow() || (ctx->GetTrickOption(RT_FIRE_SCARECROW) && logic->IsAdult && logic->CanUse(RG_LONGSHOT));}), }); - areaTable[RR_FIRE_TEMPLE_GS_CLIMB_4F] = Region("Fire Temple GS Climb 4F", SCENE_FIRE_TEMPLE, {}, {}, { + areaTable[RR_FIRE_TEMPLE_GS_CLIMB_4F] = Region("Fire Temple GS Climb 4F", SCENE_FIRE_TEMPLE, {}, { + //Locations + LOCATION(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT)), + }, { //Exits Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, []{return true;}), - Entrance(RR_FIRE_TEMPLE_GS_CLIMB_5F, []{return true/*CanUse(RG_CLIMB)*/;}), + Entrance(RR_FIRE_TEMPLE_GS_CLIMB_5F, []{return logic->HasItem(RG_CLIMB);}), }); areaTable[RR_FIRE_TEMPLE_GS_CLIMB_5F] = Region("Fire Temple GS Climb 5F", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, logic->CanKillEnemy(RE_GOLD_SKULLTULA, /*CanUse(RG_CLIMB) ?*/ED_SHORT_JUMPSLASH/*: ED_BOMB_THROW*/)), + LOCATION(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->HasItem(RG_CLIMB) ? ED_SHORT_JUMPSLASH : ED_BOMB_THROW)), }, { //Exits Entrance(RR_FIRE_TEMPLE_GS_CLIMB_4F, []{return true;}), @@ -384,7 +387,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_SWITCH_CLIMB] = Region("Fire Temple Switch Climb", SCENE_FIRE_TEMPLE, {}, {}, { //Exits Entrance(RR_FIRE_TEMPLE_ABOVE_3F_FLARE_DANCER, []{return true;}), - Entrance(RR_FIRE_TEMPLE_NARROW_STAIRS, []{return logic->CanHitSwitch(ED_BOMB_THROW)/* && CanUse(RG_CLIMB)*/;}), + Entrance(RR_FIRE_TEMPLE_NARROW_STAIRS, []{return logic->CanHitSwitch(ED_BOMB_THROW) && logic->CanUse(RG_CLIMB);}), }); areaTable[RR_FIRE_TEMPLE_NARROW_STAIRS] = Region("Fire Temple Narrow Stairs", SCENE_FIRE_TEMPLE, {}, { @@ -633,13 +636,13 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LAVA_GEYSER_1F] = Region("Fire Temple MQ Lava Geyser 1F", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_LEFT_HEART, true), - LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_RIGHT_HEART, true), - LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_LOWER_HEART, true), + LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_LEFT_HEART, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_RIGHT_HEART, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_LOWER_HEART, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, []{return true;}), - Entrance(RR_FIRE_TEMPLE_MQ_LAVA_GEYSER_GRATE, []{return logic->FireTimer() >= 40/* && CanClimbHigh()*/;}), + Entrance(RR_FIRE_TEMPLE_MQ_LAVA_GEYSER_GRATE, []{return logic->FireTimer() >= 40 && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}), //this technically only reaches torch pillar, but the heart pillar can be reached from there with longshot Entrance(RR_FIRE_TEMPLE_MQ_LAVA_GEYSER_PILLARS, []{return logic->FireTimer() >= 40 && logic->CanUse(RG_LONGSHOT);}), }); @@ -802,7 +805,7 @@ void RegionTable_Init_FireTemple() { }, {}, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_ABOVE_MAZE, []{return true;}), - Entrance(RR_FIRE_TEMPLE_MQ_BURNING_BLOCK, []{return logic->CanUse(RG_HOOKSHOT)/*&& CanUse(RG_CLIMB)*/;}), + Entrance(RR_FIRE_TEMPLE_MQ_BURNING_BLOCK, []{return logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_CLIMB);}), }); areaTable[RR_FIRE_TEMPLE_MQ_BURNING_BLOCK] = Region("Fire Temple MQ Burning Block", SCENE_FIRE_TEMPLE, {}, { 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 05253e5b2e8..db27df433ef 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -20,8 +20,8 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_TREES] = Region("Forest Temple Trees", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, true), - LOCATION(RC_FOREST_TEMPLE_GS_FIRST_ROOM, (logic->IsAdult && logic->CanUse(RG_BOMB_BAG)) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOMBCHU_5) || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_FOREST_FIRST_GS) && (logic->CanJumpslashExceptHammer() || (logic->IsChild && logic->CanUse(RG_BOMB_BAG))))), + LOCATION(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_FOREST_TEMPLE_GS_FIRST_ROOM, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && ((logic->IsAdult && logic->CanUse(RG_BOMB_BAG)) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOMBCHU_5) || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_FOREST_FIRST_GS) && (logic->CanJumpslashExceptHammer() || (logic->IsChild && logic->CanUse(RG_BOMB_BAG)))))), }, { //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, []{return true;}), @@ -96,8 +96,8 @@ void RegionTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_LOBBY, []{return true;}), - Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()))) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}), - Entrance(RR_FOREST_TEMPLE_MAP_ROOM, []{return true;}), + Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()))) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}), + Entrance(RR_FOREST_TEMPLE_MAP_ROOM, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), Entrance(RR_FOREST_TEMPLE_SEWER, []{return logic->HasItem(RG_GOLDEN_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL);}), Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return false;}), @@ -206,8 +206,8 @@ void RegionTable_Init_ForestTemple() { LOCATION(RC_FOREST_TEMPLE_WELL_EAST_HEART, true), }, { //Exits - Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_LOWER, []{return true;}), - Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, []{return true;}), + Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_LOWER, []{return logic->HasItem(RG_CLIMB);}), + Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), }); areaTable[RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST] = Region("Forest Temple Below Boss Key Chest", SCENE_FOREST_TEMPLE, {}, {}, { @@ -238,7 +238,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM] = Region("Forest Temple Lower Block Push Room", SCENE_FOREST_TEMPLE, {}, {}, { //Exits Entrance(RR_FOREST_TEMPLE_RED_DOORMAT_HALLWAY_DOORMAT, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MIDDLE_BLOCK_PUSH_ROOM, []{return logic->HasItem(RG_GORONS_BRACELET);}), + Entrance(RR_FOREST_TEMPLE_MIDDLE_BLOCK_PUSH_ROOM, []{return logic->HasItem(RG_CLIMB) && logic->HasItem(RG_GORONS_BRACELET);}), Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_COURTYARD_ALCOVE, []{return logic->CanUse(RG_HOVER_BOOTS);}), }); @@ -249,12 +249,12 @@ void RegionTable_Init_ForestTemple() { //Exits Entrance(RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM, []{return true;}), Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_COURTYARD_ALCOVE, []{return ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && logic->CanJumpslashExceptHammer();}), - Entrance(RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM, []{return logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET);}), + Entrance(RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM, []{return logic->IsAdult && logic->HasItem(RG_CLIMB) && logic->HasItem(RG_GORONS_BRACELET);}), }); areaTable[RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM] = Region("Forest Temple Upper Block Push Room", SCENE_FOREST_TEMPLE, {}, {}, { //Exits - Entrance(RR_FOREST_TEMPLE_MIDDLE_BLOCK_PUSH_ROOM, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MIDDLE_BLOCK_PUSH_ROOM, []{return true;}), Entrance(RR_FOREST_TEMPLE_NW_HALLWAY_TWISTED, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), Entrance(RR_FOREST_TEMPLE_NW_HALLWAY_STRAIGHTENED, []{return logic->CanHitEyeTargets() && logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), }); @@ -399,7 +399,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_TREES] = Region("Forest Temple MQ Trees", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA, ED_SHORT_JUMPSLASH, false) || logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && (logic->CanPassEnemy(RE_BIG_SKULLTULA, ED_SHORT_JUMPSLASH, false) || logic->CanUse(RG_HOVER_BOOTS))), }, { //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, []{return true;}), @@ -481,7 +481,7 @@ void RegionTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_RED_DOORMAT_HALLWAY, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS);});}), - Entrance(RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE, []{return logic->HasItem(RG_GORONS_BRACELET) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE, []{return (logic->HasItem(RG_CLIMB) && logic->HasItem(RG_GORONS_BRACELET)) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}), }); @@ -492,7 +492,7 @@ void RegionTable_Init_ForestTemple() { }, {}, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return (logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET)) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return (logic->IsAdult && logic->HasItem(RG_CLIMB) && logic->HasItem(RG_GORONS_BRACELET)) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), //Hammer cannot recoil from here, but can make the jump forwards with a hammer jumpslash as adult Entrance(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && (logic->CanJumpslashExceptHammer() || (logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER))));}), }); @@ -568,8 +568,8 @@ void RegionTable_Init_ForestTemple() { LOCATION(RC_FOREST_TEMPLE_MQ_WELL_EAST_HEART, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL) || ((((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16);}), - Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE, []{return logic->Get(LOGIC_FOREST_MQ_BURNED_WEB) && (logic->CanKillEnemy(RE_BIG_SKULLTULA, ED_LONGSHOT) || logic->CanUse(RG_BOMBCHU_5));}), + Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD, []{return logic->HasItem(RG_CLIMB) && (logic->Get(LOGIC_FOREST_DRAINED_WELL) || ((((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16));}), + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->Get(LOGIC_FOREST_MQ_BURNED_WEB) && (logic->CanKillEnemy(RE_BIG_SKULLTULA, ED_LONGSHOT) || logic->CanUse(RG_BOMBCHU_5));}), Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}), }); @@ -609,7 +609,7 @@ void RegionTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16;}), + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16;}), Entrance(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES, []{return logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && ((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanUse(RG_SONG_OF_TIME)));}), Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND, []{return logic->CanUse(RG_LONGSHOT);}), }); 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 6cf954250c6..d195d98196e 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 @@ -45,7 +45,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE] = Region("Gerudo Training Ground Central Maze", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3) && (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3) && (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_CLIMB))), LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 4)), LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 6)), LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 7)), @@ -203,7 +203,7 @@ void RegionTable_Init_GerudoTrainingGround() { //Locations LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, true), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, (ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), 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 ec0d3245751..b847c915c1e 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -84,7 +84,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Exits //there's tricks for getting here with bunny-jumps or just side-hops - Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return (logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_CLIMB)) || logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), Entrance(RR_JABU_JABUS_BELLY_HOLES_BASEMENT, []{return true;}), }); @@ -243,11 +243,11 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM] = Region("Jabu Jabus Belly Near Boss Room", SCENE_JABU_JABU, {}, { //Locations //can also use ruto - LOCATION(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)), + LOCATION(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW) && (logic->HasItem(RG_CLIMB) || logic->HookshotOrBoomerang())), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_LIFT_ROOM, []{return true;}), - Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, []{return logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_EXPLOSIVES) && (logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_BOMB_BAG))));}), + Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, []{return (logic->HasItem(RG_CLIMB) && logic->CanUse(RG_BOOMERANG)) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_EXPLOSIVES) && (logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_BOMB_BAG))));}), }); #pragma endregion @@ -348,7 +348,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, true), - LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanKillEnemy(RE_LIZALFOS)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, (logic->IsAdult || logic->HasItem(RG_CLIMB)) && logic->CanKillEnemy(RE_LIZALFOS)), LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, (logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)) || (ctx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->CanUse(RG_BOOMERANG))), LOCATION(RC_JABU_JABUS_BELLY_MQ_TIME_BLOCK_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_TIME_BLOCK_POT_2, logic->CanBreakPots()), @@ -531,7 +531,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), - LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT))), + LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, logic->HasItem(RG_CLIMB) && (logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT)))), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_GRASS_2, logic->CanCutShrubs()), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index 75a8163060a..ae7f6b24fbd 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -81,7 +81,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_NORTH] = Region("Spirit Temple Rupee Bridge North", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE, []{return true/*CanClimb()*/;}), + EventAccess(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), }, { //Locations // these assume SpiritRupeeBridge, silver rupee shuffle & shuffle climb will want to adjust @@ -121,7 +121,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits Entrance(RR_SPIRIT_TEMPLE_CHILD_BOXES, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5);}), - Entrance(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return true/*CanClimbHigh()*/;}), + Entrance(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), }); areaTable[RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F] = Region("Spirit Temple Sun On Floor 2F", SCENE_SPIRIT_TEMPLE, {}, { @@ -134,7 +134,6 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits Entrance(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, []{return true;}), - ///*CanClimbHigh() &&*/ (HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))) Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->SpiritSunOnFloorToStatue();}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp index 6ec8114a094..ef562e65045 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp @@ -12,24 +12,43 @@ void RegionTable_Init_CastleGrounds() { areaTable[RR_CASTLE_GROUNDS] = Region("Castle Grounds", SCENE_OUTSIDE_GANONS_CASTLE, TIME_DOESNT_PASS, {RA_CASTLE_GROUNDS}, {}, {}, { //Exits Entrance(RR_THE_MARKET, []{return true;}), - Entrance(RR_HYRULE_CASTLE_GROUNDS, []{return logic->IsChild;}), + Entrance(RR_HC_GATE, []{return logic->IsChild;}), Entrance(RR_GANONS_CASTLE_GROUNDS, []{return logic->IsAdult;}), }); + areaTable[RR_HC_GATE] = Region("Hyrule Castle Gate", SCENE_HYRULE_CASTLE, { + //Events + EventAccess(LOGIC_BUG_ACCESS, []{return true /*str0*/;}), + }, { + //Locations + LOCATION(RC_HC_MALON_EGG, true), + LOCATION(RC_HC_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)), + }, { + //Exits + Entrance(RR_CASTLE_GROUNDS, []{return true;}), + Entrance(RR_HYRULE_CASTLE_GROUNDS, []{return logic->HasItem(RG_ZELDAS_LETTER) || logic->HasItem(RG_CLIMB);}), + }); + areaTable[RR_HYRULE_CASTLE_GROUNDS] = Region("Hyrule Castle Grounds", SCENE_HYRULE_CASTLE, { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy() || logic->CanUse(RG_STICKS);}), - EventAccess(LOGIC_BUG_ACCESS, []{return true;}), }, { //Locations - LOCATION(RC_HC_MALON_EGG, true), - LOCATION(RC_HC_GS_TREE, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE) && logic->CanBonkTrees()), - LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), - LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), + LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), + // jumping past guard would be a trick + LOCATION(RC_HC_MALON_GOSSIP_STONE, logic->HasItem(RG_CLIMB)), + }, { + //Exits + Entrance(RR_HC_MOAT, []{return logic->HasItem(RG_CLIMB);}), + Entrance(RR_HC_GREAT_FAIRY_FOUNTAIN, []{return logic->BlastOrSmash();}), + }); + + areaTable[RR_HC_MOAT] = Region("Hyrule Castle Grounds", SCENE_HYRULE_CASTLE, {}, { + //Locations + LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE, true), LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_HC_MALON_GOSSIP_STONE, true), - LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE, true), LOCATION(RC_HC_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_HC_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_HC_GROTTO_TREE, logic->CanBonkTrees()), @@ -44,10 +63,9 @@ void RegionTable_Init_CastleGrounds() { LOCATION(RC_HC_NEAR_GUARDS_TREE_6, logic->CanBonkTrees()), }, { //Exits - Entrance(RR_CASTLE_GROUNDS, []{return true;}), - Entrance(RR_HC_GARDEN, []{return logic->CanUse(RG_WEIRD_EGG) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}), - Entrance(RR_HC_GREAT_FAIRY_FOUNTAIN, []{return logic->BlastOrSmash();}), - Entrance(RR_HC_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), + Entrance(RR_HC_GATE, []{return true;}), + Entrance(RR_HC_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), + Entrance(RR_HC_GARDEN, []{return logic->CanUse(RG_WEIRD_EGG) || !ctx->GetOption(RSK_SHUFFLE_WEIRD_EGG) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}), }); areaTable[RR_HC_GARDEN] = Region("HC Garden", SCENE_CASTLE_COURTYARD_ZELDA, {}, { @@ -72,7 +90,7 @@ void RegionTable_Init_CastleGrounds() { LOCATION(RC_HC_GS_STORMS_GROTTO, logic->CanUse(RG_BOOMERANG) && ctx->GetTrickOption(RT_HC_STORMS_GS)), }, { //Exits - Entrance(RR_CASTLE_GROUNDS, []{return true;}), + Entrance(RR_HC_MOAT, []{return true;}), Entrance(RR_HC_STORMS_GROTTO_BEHIND_WALLS, []{return logic->CanBreakMudWalls();}), }); 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 5d337222354..8544f4e47d0 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 @@ -38,7 +38,7 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_DMC_DEKU_SCRUB, logic->IsChild && logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()), }, { //Exits - Entrance(RR_DMC_UPPER_NEARBY, []{return logic->Hearts() >= 3;}), + Entrance(RR_DMC_UPPER_NEARBY, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->Hearts() >= 3;}), Entrance(RR_DMC_LOWER_NEARBY, []{return logic->Hearts() >= 3 && (logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DMC_BOULDER_JS) && logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)) || (ctx->GetTrickOption(RT_DMC_BOULDER_SKIP) && logic->IsAdult));}), }); @@ -150,5 +150,11 @@ void RegionTable_Init_DeathMountainCrater() { Entrance(RR_DMC_CENTRAL_LOCAL, []{return logic->FireTimer() >= 48 && logic->IsAdult && logic->ReachDistantScarecrow();}), }); + areaTable[RR_DMC_OUTSIDE_FIRE_TEMPLE] = Region("DMC Outside Fire Temple", SCENE_DEATH_MOUNTAIN_CRATER, {}, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_ENTRYWAY, []{return true;}), + Entrance(RR_DMC_CENTRAL_LOCAL, []{return logic->FireTimer() >= 48 && logic->HasItem(RG_CLIMB);}), + }); + // clang-format on } diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp index d59043ab487..f8d282553ed 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp @@ -25,11 +25,21 @@ void RegionTable_Init_DeathMountainTrail() { //Exits Entrance(RR_KAK_BEHIND_GATE, []{return true;}), Entrance(RR_GORON_CITY, []{return true;}), - Entrance(RR_DEATH_MOUNTAIN_SUMMIT, []{return AnyAgeTime([]{return logic->BlastOrSmash();}) || (logic->IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->HasItem(RG_GORONS_BRACELET)) || (logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_DMT_CLIMB_HOVERS))));}), + Entrance(RR_DEATH_MOUNTAIN_AVALANCHE, []{return AnyAgeTime([]{return logic->BlastOrSmash();}) || (logic->IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->HasItem(RG_GORONS_BRACELET)) || (logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_DMT_CLIMB_HOVERS))));}), Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, []{return logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET) || logic->IsAdult;}), Entrance(RR_DMT_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), }); + areaTable[RR_DEATH_MOUNTAIN_AVALANCHE] = Region("Death Mountain Avalanche", SCENE_DEATH_MOUNTAIN_TRAIL, {}, { + //Locations + LOCATION(RC_DMT_GS_FALLING_ROCKS_PATH, logic->IsAdult && logic->CanGetNightTimeGS() && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DMT_UPPER_GS) && (logic->CanJumpslash() || logic->HasExplosives() || ((ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) || ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))))) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)))), + }, { + //Exits + Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return true;}), + Entrance(RR_DEATH_MOUNTAIN_SUMMIT, []{return logic->HasItem(RG_CLIMB);}), + Entrance(RR_DMT_COW_GROTTO, []{return AnyAgeTime([]{return logic->BlastOrSmash();});}), + }); + areaTable[RR_DEATH_MOUNTAIN_SUMMIT] = Region("Death Mountain Summit", SCENE_DEATH_MOUNTAIN_TRAIL, { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy();}), @@ -39,17 +49,14 @@ void RegionTable_Init_DeathMountainTrail() { LOCATION(RC_DMT_TRADE_BROKEN_SWORD, logic->IsAdult && logic->CanUse(RG_BROKEN_SWORD)), LOCATION(RC_DMT_TRADE_EYEDROPS, logic->IsAdult && logic->CanUse(RG_EYEDROPS)), LOCATION(RC_DMT_TRADE_CLAIM_CHECK, logic->IsAdult && logic->CanUse(RG_CLAIM_CHECK)), - // backflip can collect token, allowing use of explosives (or bow from afar), but it's a trick - LOCATION(RC_DMT_GS_FALLING_ROCKS_PATH, logic->IsAdult && logic->CanGetNightTimeGS() && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DMT_UPPER_GS) && (logic->CanJumpslash() || logic->HasExplosives() || ((ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) || ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))))) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)))), LOCATION(RC_DMT_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_DMT_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_DMT_GOSSIP_STONE, true), }, { //Exits - Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return true;}), + Entrance(RR_DEATH_MOUNTAIN_AVALANCHE, []{return true;}), Entrance(RR_DMC_UPPER_LOCAL, []{return true;}), Entrance(RR_DMT_OWL_FLIGHT, []{return logic->IsChild;}, false), - Entrance(RR_DMT_COW_GROTTO, []{return AnyAgeTime([]{return logic->BlastOrSmash();});}), Entrance(RR_DMT_GREAT_FAIRY_FOUNTAIN, []{return AnyAgeTime([]{return logic->BlastOrSmash();});}), }); @@ -78,7 +85,7 @@ void RegionTable_Init_DeathMountainTrail() { LOCATION(RC_DMT_COW_GROTTO_GRASS_2, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEATH_MOUNTAIN_SUMMIT, []{return true;}), + Entrance(RR_DEATH_MOUNTAIN_AVALANCHE, []{return true;}), }); areaTable[RR_DMT_STORMS_GROTTO] = Region("DMT Storms Grotto", SCENE_GROTTOS, grottoEvents, { 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 f921c5483cd..642cdf2319c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp @@ -9,7 +9,7 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_OUTSKIRTS] = Region("Gerudo Fortress Outskirts", SCENE_GERUDOS_FORTRESS, { //Events - EventAccess(LOGIC_GF_GATE_OPEN, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), //needs climb + EventAccess(LOGIC_GF_GATE_OPEN, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->CanUse(RG_CLIMB);}), }, { //Locations LOCATION(RC_GF_OUTSKIRTS_NE_CRATE, (logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)) && logic->CanBreakCrates()), @@ -92,7 +92,7 @@ void RegionTable_Init_GerudoFortress() { //Exits Entrance(RR_TH_STEEP_SLOPE_CELL, []{return true;}), Entrance(RR_GF_NEAR_GROTTO, []{return true;}), - Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true /* logic->CanClimb() */;}), + Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_GF_ABOVE_GTG, []{return true;}), Entrance(RR_GF_BELOW_GS, []{return logic->IsAdult && logic->CanGroundJump();}), }); @@ -134,7 +134,7 @@ void RegionTable_Init_GerudoFortress() { Entrance(RR_GF_OUTSIDE_GTG, []{return true;}), Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true;}), Entrance(RR_GF_SLOPED_ROOF, []{return logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS));}), - Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return true /* logic->CanClimb() */;}), + Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_GF_TO_GTG, []{return logic->IsAdult && ctx->GetTrickOption(RT_GF_LEDGE_CLIP_INTO_GTG).Get();}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp index 370fdf0b1a9..870abd6c3cb 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -11,6 +11,7 @@ void RegionTable_Init_GerudoValley() { }, { //Locations LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), + LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, logic->IsChild), //can use cucco as child }, { //Exits Entrance(RR_HYRULE_FIELD, []{return true;}), @@ -27,7 +28,7 @@ void RegionTable_Init_GerudoValley() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy() || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS));}), }, { //Locations - LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, logic->IsChild || logic->HasItem(RG_BRONZE_SCALE) || CanPlantBean(RR_GV_UPPER_STREAM, RG_GERUDO_VALLEY_BEAN_SOUL)),//can use cucco as child + LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, ((logic->IsChild || logic->HasItem(RG_BRONZE_SCALE)) && logic->HasItem(RG_CLIMB)) || CanPlantBean(RR_GV_UPPER_STREAM, RG_GERUDO_VALLEY_BEAN_SOUL)),//can use cucco as child LOCATION(RC_GV_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanAttack()), LOCATION(RC_GV_COW, logic->IsChild && logic->CanUse(RG_EPONAS_SONG)), LOCATION(RC_GV_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), 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 83bbfcff7ed..54fa95f135d 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp @@ -171,13 +171,13 @@ void RegionTable_Init_HyruleField() { }, { //Exits Entrance(RR_LW_BRIDGE, []{return true;}), - Entrance(RR_LAKE_HYLIA, []{return true;}), Entrance(RR_GERUDO_VALLEY, []{return true;}), Entrance(RR_MARKET_ENTRANCE, []{return true;}), Entrance(RR_KAKARIKO_VILLAGE, []{return true;}), Entrance(RR_ZR_FRONT, []{return true;}), Entrance(RR_LON_LON_RANCH, []{return true;}), Entrance(RR_HF_SOUTHEAST_GROTTO, []{return AnyAgeTime([]{return logic->BlastOrSmash();});}), + Entrance(RR_HF_TO_LAKE_HYLIA, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->SummonEpona();}), Entrance(RR_HF_OPEN_GROTTO, []{return true;}), Entrance(RR_HF_INSIDE_FENCE_GROTTO, []{return logic->CanOpenBombGrotto();}), Entrance(RR_HF_COW_GROTTO, []{return (logic->CanUse(RG_MEGATON_HAMMER) || logic->IsChild) && logic->CanOpenBombGrotto();}), @@ -187,6 +187,12 @@ void RegionTable_Init_HyruleField() { Entrance(RR_HF_TEKTITE_GROTTO, []{return logic->CanOpenBombGrotto();}), }); + areaTable[RR_HF_TO_LAKE_HYLIA] = Region("HF to Lake Hylia", SCENE_HYRULE_FIELD, {}, {}, { + //Exits + Entrance(RR_LAKE_HYLIA, []{return true;}), + Entrance(RR_HYRULE_FIELD, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->SummonEpona();}), + }); + areaTable[RR_HF_SOUTHEAST_GROTTO] = Region("HF Southeast Grotto", SCENE_GROTTOS, grottoEvents, { //Locations LOCATION(RC_HF_SOUTHEAST_GROTTO_CHEST, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index 77444333a78..b51c4ac0a2a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -15,7 +15,7 @@ void RegionTable_Init_Kakariko() { }, { //Locations LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->HasItem(RG_FOREST_MEDALLION) && logic->HasItem(RG_FIRE_MEDALLION) && logic->HasItem(RG_WATER_MEDALLION)), - LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay), + LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay && logic->HasItem(RG_CLIMB)), // RANDOTODO only require climb if all 7 cuccos required LOCATION(RC_KAK_ANJU_AS_ADULT, logic->IsAdult && logic->AtDay), LOCATION(RC_KAK_TRADE_POCKET_CUCCO, logic->IsAdult && logic->AtDay && (logic->CanUse(RG_POCKET_EGG) && logic->Get(LOGIC_WAKE_UP_ADULT_TALON))), //Can kill lower kak skulls with pots @@ -23,7 +23,7 @@ void RegionTable_Init_Kakariko() { LOCATION(RC_KAK_GS_SKULLTULA_HOUSE, logic->IsChild && logic->CanGetNightTimeGS()), LOCATION(RC_KAK_GS_GUARDS_HOUSE, logic->IsChild && logic->CanGetNightTimeGS()), LOCATION(RC_KAK_GS_TREE, logic->IsChild && logic->CanGetNightTimeGS() && logic->CanBonkTrees()), - LOCATION(RC_KAK_GS_WATCHTOWER, logic->IsChild && (logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT) || (ctx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), + LOCATION(RC_KAK_GS_WATCHTOWER, logic->IsChild && logic->HasItem(RG_CLIMB) && (logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT) || (ctx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), LOCATION(RC_KAK_NEAR_POTION_SHOP_POT_1, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_KAK_NEAR_POTION_SHOP_POT_2, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_KAK_NEAR_POTION_SHOP_POT_3, logic->IsChild && logic->CanBreakPots()), @@ -73,7 +73,7 @@ void RegionTable_Init_Kakariko() { Entrance(RR_KAK_POTION_SHOP_FRONT, []{return (logic->AtDay || logic->IsChild) && logic->CanOpenOverworldDoor(RG_KAK_POTION_SHOP_KEY);}), Entrance(RR_KAK_REDEAD_GROTTO, []{return logic->CanOpenBombGrotto();}), Entrance(RR_KAK_IMPAS_LEDGE, []{return (logic->IsChild && logic->AtDay) || (logic->IsAdult && ctx->GetTrickOption(RT_VISIBLE_COLLISION));}), - Entrance(RR_KAK_WATCHTOWER, []{return logic->IsAdult || logic->AtDay || logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT) || (ctx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslashExceptHammer());}), + Entrance(RR_KAK_WATCHTOWER, []{return logic->HasItem(RG_CLIMB) && (logic->IsAdult || logic->AtDay || logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT) || (ctx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslashExceptHammer()));}), Entrance(RR_KAK_ROOFTOP, []{return logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->IsAdult);}), Entrance(RR_KAK_IMPAS_ROOFTOP, []{return logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_KAK_ROOFTOP_GS) && logic->CanUse(RG_HOVER_BOOTS));}), Entrance(RR_THE_GRAVEYARD, []{return true;}), @@ -279,7 +279,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->Get(LOGIC_DRAIN_WELL);}), + Entrance(RR_KAKARIKO_VILLAGE, []{return logic->HasItem(RG_CLIMB) && (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->Get(LOGIC_DRAIN_WELL));}), Entrance(RR_BOTW_ENTRYWAY, []{return logic->IsChild || (logic->Get(LOGIC_DRAIN_WELL) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF));}), }); 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 df36eb19056..6b4691a0458 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -78,14 +78,15 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_ADULT_GRASS_20, logic->IsAdult && logic->CanCutShrubs()), }, { //Exits - Entrance(RR_KF_LINKS_HOUSE, []{return true;}), + Entrance(RR_KF_LINKS_PORCH, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_KF_MIDOS_HOUSE, []{return true;}), Entrance(RR_KF_SARIAS_HOUSE, []{return true;}), Entrance(RR_KF_HOUSE_OF_TWINS, []{return true;}), Entrance(RR_KF_KNOW_IT_ALL_HOUSE, []{return true;}), Entrance(RR_KF_KOKIRI_SHOP, []{return true;}), Entrance(RR_KF_OUTSIDE_DEKU_TREE, []{return (logic->IsAdult && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->Get(LOGIC_FOREST_TEMPLE_CLEAR))) || ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_OFF) || logic->Get(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD);}), - Entrance(RR_THE_LOST_WOODS, []{return true;}), + // Maybe adult jumping to Mido's Roof is trick, in which case bean can also get adult up here + Entrance(RR_KF_OUTSIDE_LOST_WOODS, []{return logic->IsAdult || logic->HasItem(RG_CLIMB);}), Entrance(RR_LW_BRIDGE_FROM_FOREST, []{return logic->IsAdult || ctx->GetOption(RSK_FOREST).IsNot(RO_CLOSED_FOREST_ON) || logic->Get(LOGIC_DEKU_TREE_CLEAR);}), Entrance(RR_KF_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), }); @@ -110,13 +111,18 @@ void RegionTable_Init_KokiriForest() { Entrance(RR_KOKIRI_FOREST, []{return (logic->IsAdult && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->Get(LOGIC_DEKU_TREE_CLEAR))) || ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_OFF) || logic->Get(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD);}), }); + areaTable[RR_KF_LINKS_PORCH] = Region("KF Link's Porch", SCENE_KOKIRI_FOREST, {}, {}, { + Entrance(RR_KOKIRI_FOREST, []{return true;}), + Entrance(RR_KF_LINKS_HOUSE, []{return true;}), + }); + areaTable[RR_KF_LINKS_HOUSE] = Region("KF Link's House", SCENE_LINKS_HOUSE, {}, { //Locations LOCATION(RC_KF_LINKS_HOUSE_COW, logic->IsAdult && logic->CanUse(RG_EPONAS_SONG) && logic->Get(LOGIC_LINKS_COW)), LOCATION(RC_KF_LINKS_HOUSE_POT, logic->CanBreakPots()), }, { //Exits - Entrance(RR_KOKIRI_FOREST, []{return true;}) + Entrance(RR_KF_LINKS_PORCH, []{return true;}) }); areaTable[RR_KF_MIDOS_HOUSE] = Region("KF Mido's House", SCENE_MIDOS_HOUSE, {}, { @@ -174,6 +180,12 @@ void RegionTable_Init_KokiriForest() { Entrance(RR_KOKIRI_FOREST, []{return true;}), }); + areaTable[RR_KF_OUTSIDE_LOST_WOODS] = Region("KF Outside Lost Woods", SCENE_KOKIRI_FOREST, {}, {}, { + Entrance(RR_KOKIRI_FOREST, []{return true;}), + Entrance(RR_THE_LOST_WOODS, []{return true;}), + Entrance(RR_KF_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), + }); + areaTable[RR_KF_STORMS_GROTTO] = Region("KF Storms Grotto", SCENE_GROTTOS, grottoEvents, { //Locations LOCATION(RC_KF_STORMS_GROTTO_CHEST, true), @@ -189,7 +201,7 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_STORMS_GROTTO_GRASS_4, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_KOKIRI_FOREST, []{return true;}) + Entrance(RR_KF_OUTSIDE_LOST_WOODS, []{return true;}) }); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp index 344b609dace..ce67919a52c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp @@ -15,7 +15,7 @@ void RegionTable_Init_LakeHylia() { //Locations LOCATION(RC_LH_UNDERWATER_ITEM, logic->IsChild && logic->HasItem(RG_SILVER_SCALE)), LOCATION(RC_LH_SUN, logic->IsAdult && ((logic->Get(LOGIC_WATER_TEMPLE_CLEAR) && logic->HasItem(RG_BRONZE_SCALE)) || logic->ReachDistantScarecrow()) && logic->CanUse(RG_FAIRY_BOW)), - LOCATION(RC_LH_FREESTANDING_POH, logic->IsAdult && (logic->ReachScarecrow() || CanPlantBean(RR_LAKE_HYLIA, RG_LAKE_HYLIA_BEAN_SOUL)) && logic->CanAvoidEnemy(RE_GUAY, false)), + LOCATION(RC_LH_FREESTANDING_POH, logic->IsAdult && (logic->ReachScarecrow() || CanPlantBean(RR_LAKE_HYLIA, RG_LAKE_HYLIA_BEAN_SOUL)) && logic->CanAvoidEnemy(RE_GUAY, false) && logic->HasItem(RG_CLIMB)), LOCATION(RC_LH_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_LAKE_HYLIA_BEAN_SOUL) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_LH_GS_LAB_WALL, logic->IsChild && (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (ctx->GetTrickOption(RT_LH_LAB_WALL_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), LOCATION(RC_LH_GS_SMALL_ISLAND, logic->IsChild && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) && logic->CanGetNightTimeGS() && logic->HasItem(RG_BRONZE_SCALE)), @@ -81,7 +81,7 @@ void RegionTable_Init_LakeHylia() { LOCATION(RC_LH_WARP_PAD_GRASS_2, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_HYRULE_FIELD, []{return true;}), + Entrance(RR_HF_TO_LAKE_HYLIA, []{return true;}), Entrance(RR_LH_FROM_SHORTCUT, []{return true;}), Entrance(RR_LH_OWL_FLIGHT, []{return logic->IsChild;}), Entrance(RR_LH_FISHING_ISLAND, []{return ((logic->IsChild || logic->Get(LOGIC_WATER_TEMPLE_CLEAR)) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->ReachScarecrow() || CanPlantBean(RR_LAKE_HYLIA, RG_LAKE_HYLIA_BEAN_SOUL)));}), 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 0dc30809619..63ef6490af9 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -7,7 +7,7 @@ void RegionTable_Init_LostWoods() { // clang-format off areaTable[RR_LW_FOREST_EXIT] = Region("LW Forest Exit", SCENE_LOST_WOODS, {}, {}, { //Exits - Entrance(RR_KOKIRI_FOREST, []{return true;}) + Entrance(RR_KF_OUTSIDE_LOST_WOODS, []{return true;}) }); areaTable[RR_THE_LOST_WOODS] = Region("Lost Woods", 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 c813a812157..30aac60bc5f 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 @@ -12,31 +12,49 @@ void RegionTable_Init_SacredForestMeadow() { Entrance(RR_SFM_WOLFOS_GROTTO, []{return logic->CanOpenBombGrotto();}), }); - areaTable[RR_SACRED_FOREST_MEADOW] = Region("Sacred Forest Meadow", SCENE_SACRED_FOREST_MEADOW, { + areaTable[RR_SFM_ABOVE_MAZE] = Region("SFM Maze", SCENE_SACRED_FOREST_MEADOW, { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairyExceptSuns();}), }, { //Locations - LOCATION(RC_SONG_FROM_SARIA, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER)), - LOCATION(RC_SHEIK_IN_FOREST, logic->IsAdult), LOCATION(RC_SFM_GS, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), LOCATION(RC_SFM_MAZE_LOWER_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), LOCATION(RC_SFM_MAZE_UPPER_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_SFM_SARIA_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), - LOCATION(RC_SFM_SARIA_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_SFM_MAZE_LOWER_GOSSIP_STONE, true), LOCATION(RC_SFM_MAZE_UPPER_GOSSIP_STONE, true), - LOCATION(RC_SFM_SARIA_GOSSIP_STONE, true), }, { //Exits - Entrance(RR_SFM_ENTRYWAY, []{return true;}), + Entrance(RR_SFM_ENTRYWAY, []{return true;}), + Entrance(RR_SFM_OUTSIDE_FAIRY_GROTTO, []{return true;}), + Entrance(RR_SACRED_FOREST_MEADOW, []{return true;}), + }); + + areaTable[RR_SACRED_FOREST_MEADOW] = Region("Sacred Forest Meadow", SCENE_SACRED_FOREST_MEADOW, { + //Events + EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairyExceptSuns();}), + }, { + //Locations + LOCATION(RC_SONG_FROM_SARIA, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER)), + LOCATION(RC_SHEIK_IN_FOREST, logic->IsAdult), + LOCATION(RC_SFM_SARIA_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), + LOCATION(RC_SFM_SARIA_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_SFM_SARIA_GOSSIP_STONE, true), + }, { + //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, []{return logic->CanUse(RG_HOOKSHOT);}), - Entrance(RR_SFM_FAIRY_GROTTO, []{return true;}), + Entrance(RR_SFM_ENTRYWAY, []{return true;}), + Entrance(RR_SFM_ABOVE_MAZE, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump());}), Entrance(RR_SFM_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), }); + areaTable[RR_SFM_OUTSIDE_FAIRY_GROTTO] = Region("SFM Outside Fairy Grotto", SCENE_SACRED_FOREST_MEADOW, {}, {}, { + //Exits + Entrance(RR_SFM_FAIRY_GROTTO, []{return true;}), + Entrance(RR_SFM_ABOVE_MAZE, []{return logic->HasItem(RG_CLIMB) || logic->HasItem(RG_HOOKSHOT);}), + }); + areaTable[RR_SFM_FAIRY_GROTTO] = Region("SFM Fairy Grotto", SCENE_GROTTOS, { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return true;}), @@ -52,7 +70,7 @@ void RegionTable_Init_SacredForestMeadow() { LOCATION(RC_SFM_FAIRY_GROTTO_FAIRY_8, true), }, { //Exits - Entrance(RR_SACRED_FOREST_MEADOW, []{return true;}), + Entrance(RR_SFM_OUTSIDE_FAIRY_GROTTO, []{return true;}), }); areaTable[RR_SFM_WOLFOS_GROTTO] = Region("SFM Wolfos Grotto", SCENE_GROTTOS, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp index 83ce7061fa9..613109a1fd3 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp @@ -95,7 +95,7 @@ void RegionTable_Init_ZorasFountain() { //Exits //There are invisible big skultullas here as adult but they do not block the path and can be "seen" with Z-target //Lens is not currently needed for this either, implying they are not considered blocking, but it's open for discussion long-term - Entrance(RR_ZF_HIDDEN_LEDGE, []{return true;}), + Entrance(RR_ZF_HIDDEN_LEDGE, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), }); areaTable[RR_ZF_HIDDEN_LEDGE] = Region("ZF Hidden Ledge", SCENE_ZORAS_FOUNTAIN, {}, { 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 883a3f8a749..ca376a304a8 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, []{return true;}), - Entrance(RR_ZR_ATOP_LADDER, []{return true/*(logic->IsAdult || str0) && (logic->CanUse(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)))*/;}), + Entrance(RR_ZR_ATOP_LADDER, []{return (/*(logic->IsAdult || str0) &&*/ logic->CanUse(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_HOOKSHOT))) || CanPlantBean(RR_ZORAS_RIVER, RG_ZORAS_RIVER_BEAN_SOUL);}), Entrance(RR_ZR_PILLAR, []{return (logic->IsChild/* && str0*/) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_LOWER));}), Entrance(RR_THE_LOST_WOODS, []{return logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_ZR_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), @@ -107,6 +107,19 @@ void RegionTable_Init_ZoraRiver() { Entrance(RR_ZORAS_DOMAIN, []{return true;}), }); + areaTable[RR_ZR_UPPER_GROTTOS] = Region("ZR Upper Grottos", SCENE_ZORAS_RIVER, {}, { + //Locations + LOCATION(RC_ZR_GS_NEAR_RAISED_GROTTOS, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), + LOCATION(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), + LOCATION(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, true), + }, { + //Exits + Entrance(RR_ZORAS_RIVER, []{return true;}), + Entrance(RR_ZR_OPEN_GROTTO, []{return true;}), + Entrance(RR_ZR_FAIRY_GROTTO, []{return AnyAgeTime([]{return logic->BlastOrSmash();});}), + }); + areaTable[RR_ZR_OPEN_GROTTO] = Region("ZR Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations LOCATION(RC_ZR_OPEN_GROTTO_CHEST, true), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 0d3045c98ac..1ef9fbb3318 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -227,6 +227,8 @@ bool Logic::HasItem(RandomizerGet itemName) { return CurrentUpgrade(UPG_SCALE) >= 1; case RG_GOLDEN_SCALE: return CurrentUpgrade(UPG_SCALE) >= 2; + case RG_CLIMB: + return CheckRandoInf(RAND_INF_CAN_CLIMB); case RG_POCKET_EGG: return CheckRandoInf(RAND_INF_ADULT_TRADES_HAS_POCKET_EGG); case RG_COJIRO: @@ -1713,6 +1715,9 @@ void Logic::ApplyItemEffect(Item& item, bool state) { case RG_CLAIM_CHECK: SetRandoInf(randoGet - RG_COJIRO + RAND_INF_ADULT_TRADES_HAS_COJIRO, state); break; + case RG_CLIMB: + SetRandoInf(RAND_INF_CAN_CLIMB, state); + break; case RG_PROGRESSIVE_HOOKSHOT: { uint8_t i; for (i = 0; i < 3; i++) { @@ -2459,7 +2464,8 @@ bool Logic::IsReverseAccessPossible() { } bool Logic::SpiritSunOnFloorToStatue() { - return /*CanClimbHigh() &&*/ (HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))); + return (HasItem(RG_CLIMB) || CanUse(RG_LONGSHOT)) && + (HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))); } bool Logic::SpiritExplosiveKeyLogic() { @@ -2497,7 +2503,7 @@ bool Logic::MQSpiritStatueToSunBlock() { bool Logic::MQSpiritStatueSouthDoor() { return HasFireSource() || (ctx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && CanUse(RG_FAIRY_BOW) && - CanUse(RG_SONG_OF_TIME) /* && CanClimb()*/); + CanUse(RG_SONG_OF_TIME) && (HasItem(RG_CLIMB) || CanUse(RG_HOOKSHOT))); } bool Logic::MQSpirit4KeyColossus() { @@ -2576,6 +2582,11 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { SetRandoInf(RAND_INF_CAN_SWIM, true); } + // If we're not shuffling climb, we start with it + if (ctx->GetOption(RSK_SHUFFLE_CLIMB).Is(false)) { + SetRandoInf(RAND_INF_CAN_CLIMB, true); + } + // If we're not shuffling child's wallet, we start with it if (ctx->GetOption(RSK_SHUFFLE_CHILD_WALLET).Is(false)) { SetRandoInf(RAND_INF_HAS_WALLET, true); diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index be68728a519..6e91d5e890b 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -256,6 +256,7 @@ void Settings::CreateOptionDescriptions() { "\n" "If you enter a water entrance without swim you will be respawned on land to prevent infinite death loops.\n" "If you void out in Water Temple you will immediately be kicked out to prevent a softlock."; + mOptionDescriptions[RSK_SHUFFLE_CLIMB] = "Shuffle the ability to climb ladders into the item pool."; mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG] = "Shuffles the Weird Egg from Malon in to the item pool. Enabling " "\"Skip Child Zelda\" disables this feature.\n" "\n" diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index c2e60dd5b7d..d95c44d2644 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4945,7 +4945,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = { { + const std::array getItemMessages = { { GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn&wirklich gefunden!", "Félicitation! Vous avez trouvé %gGreg%w!"), GIMESSAGE(RG_MASTER_SWORD, ITEM_SWORD_MASTER, "You found the %gMaster Sword%w!", @@ -5290,6 +5290,8 @@ void Randomizer::CreateCustomMessages() { GIMESSAGE(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!", "Du hast die %rBronzene Schuppe%w&erhalten! Die Fähigkeit zu&Schwimmen ist nun dein!", "Vous obtenez l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est&à vous!"), + GIMESSAGE_NO_GERMAN(RG_CLIMB, ITEM_SCALE_SILVER, "You got the %rAbility to Climb%w!", + "Vous obtenez la %rCapacité&de grimper%w!"), GIMESSAGE(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!", "Du hast eine verlorene %rAngelrute%w&gefunden!&Zeit, im Teich&zu angeln!", "Vous obtenez une %rCanne à pêche%w&perdue!&Il est temps d'aller à %gl'étang%w!"), @@ -5454,6 +5456,7 @@ extern "C" u8 Return_Item_Entry(GetItemEntry itemEntry, u8 returnItem); std::map randomizerGetToRandInf = { { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }, { RG_BRONZE_SCALE, RAND_INF_CAN_SWIM }, + { RG_CLIMB, RAND_INF_CAN_CLIMB }, { RG_QUIVER_INF, RAND_INF_HAS_INFINITE_QUIVER }, { RG_BOMB_BAG_INF, RAND_INF_HAS_INFINITE_BOMB_BAG }, { RG_BULLET_BAG_INF, RAND_INF_HAS_INFINITE_BULLET_BAG }, diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 6934199468c..d37a982c8f1 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -530,6 +530,7 @@ typedef enum { RR_NOCTURNE_OF_SHADOW_WARP, RR_PRELUDE_OF_LIGHT_WARP, RR_KOKIRI_FOREST, + RR_KF_LINKS_PORCH, RR_KF_LINKS_HOUSE, RR_KF_MIDOS_HOUSE, RR_KF_SARIAS_HOUSE, @@ -537,6 +538,7 @@ typedef enum { RR_KF_KNOW_IT_ALL_HOUSE, RR_KF_KOKIRI_SHOP, RR_KF_OUTSIDE_DEKU_TREE, + RR_KF_OUTSIDE_LOST_WOODS, RR_KF_STORMS_GROTTO, RR_THE_LOST_WOODS, RR_LW_BRIDGE_FROM_FOREST, @@ -547,11 +549,15 @@ typedef enum { RR_DEKU_THEATER, RR_LW_SCRUBS_GROTTO, RR_SFM_ENTRYWAY, + RR_SFM_MAZE, + RR_SFM_ABOVE_MAZE, + RR_SFM_OUTSIDE_FAIRY_GROTTO, RR_SACRED_FOREST_MEADOW, RR_SFM_WOLFOS_GROTTO, RR_SFM_FAIRY_GROTTO, RR_SFM_STORMS_GROTTO, RR_HYRULE_FIELD, + RR_HF_TO_LAKE_HYLIA, RR_HF_SOUTHEAST_GROTTO, RR_HF_OPEN_GROTTO, RR_HF_INSIDE_FENCE_GROTTO, @@ -635,8 +641,10 @@ typedef enum { RR_TOT_BEYOND_DOOR_OF_TIME, RR_CASTLE_GROUNDS, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, + RR_HC_GATE, RR_HYRULE_CASTLE_GROUNDS, RR_HC_GARDEN, + RR_HC_MOAT, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_HC_STORMS_GROTTO, RR_HC_STORMS_GROTTO_BEHIND_WALLS, @@ -673,6 +681,7 @@ typedef enum { RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_GRAVEYARD_WARP_PAD_REGION, RR_DEATH_MOUNTAIN_TRAIL, + RR_DEATH_MOUNTAIN_AVALANCHE, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_OWL_FLIGHT, RR_DMT_GREAT_FAIRY_FOUNTAIN, @@ -696,12 +705,14 @@ typedef enum { RR_DMC_HAMMER_GROTTO, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_DISTANT_PLATFORM, + RR_DMC_OUTSIDE_FIRE_TEMPLE, RR_ZR_FRONT, RR_ZORAS_RIVER, RR_ZR_ATOP_LADDER, RR_ZR_PILLAR, RR_ZR_FROM_SHORTCUT, RR_ZR_BEHIND_WATERFALL, + RR_ZR_UPPER_GROTTOS, RR_ZR_OPEN_GROTTO, RR_ZR_FAIRY_GROTTO, RR_ZR_STORMS_GROTTO, @@ -738,6 +749,8 @@ typedef enum { RR_GANONS_CASTLE_ENTRYWAY, RR_DEKU_TREE_LOBBY, + RR_DEKU_TREE_LOBBY_2F, + RR_DEKU_TREE_LOBBY_3F, RR_DEKU_TREE_2F_MIDDLE_ROOM, RR_DEKU_TREE_SLINGSHOT_ROOM, RR_DEKU_TREE_COMPASS_ROOM, @@ -4603,6 +4616,7 @@ typedef enum { RG_HINT, RG_TYCOON_WALLET, RG_BRONZE_SCALE, + RG_CLIMB, RG_CHILD_WALLET, RG_PROGRESSIVE_BOMBCHU_BAG, RG_QUIVER_INF, @@ -5809,6 +5823,7 @@ typedef enum { RHT_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RHT_BRONZE_SCALE, + RHT_CLIMB, RHT_FISHING_POLE, RHT_SKELETON_KEY, RHT_EPONA, @@ -6405,6 +6420,7 @@ typedef enum { RSK_SHUFFLE_OCARINA, RSK_SHUFFLE_OCARINA_BUTTONS, RSK_SHUFFLE_SWIM, + RSK_SHUFFLE_CLIMB, RSK_STARTING_DEKU_SHIELD, RSK_STARTING_KOKIRI_SWORD, RSK_STARTING_MASTER_SWORD, diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index f15f7c1d1c7..06974dece64 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -1139,6 +1139,7 @@ DEFINE_RAND_INF(RAND_INF_ZF_BUSH_6) DEFINE_RAND_INF(RAND_INF_CAUGHT_LOACH) DEFINE_RAND_INF(RAND_INF_CAN_SWIM) +DEFINE_RAND_INF(RAND_INF_CAN_CLIMB) DEFINE_RAND_INF(RAND_INF_HAS_WALLET) diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index f130f10a3bc..73746e596b7 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -313,6 +313,10 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetRandomizerInf(RAND_INF_CAN_SWIM); } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CLIMB) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_CLIMB); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHILD_WALLET) == RO_GENERIC_OFF) { Flags_SetRandomizerInf(RAND_INF_HAS_WALLET); } diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index e78d0b74367..94d67e985c7 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -778,6 +778,7 @@ void Settings::CreateOptions() { }); OPT_BOOL(RSK_SHUFFLE_OCARINA_BUTTONS, "Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]); OPT_BOOL(RSK_SHUFFLE_SWIM, "Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]); + OPT_BOOL(RSK_SHUFFLE_CLIMB, "Shuffle Climb", CVAR_RANDOMIZER_SETTING("ShuffleClimb"), mOptionDescriptions[RSK_SHUFFLE_CLIMB]); OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]); OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_POTS_OFF); @@ -2388,6 +2389,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_DEKU_NUT_BAG], &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], + &mOptions[RSK_SHUFFLE_CLIMB], &mOptions[RSK_SHUFFLE_BEAN_SOULS], &mOptions[RSK_ROCS_FEATHER], &mOptions[RSK_BOMBCHU_BAG], @@ -2605,6 +2607,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_OCARINA], &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], + &mOptions[RSK_SHUFFLE_CLIMB], &mOptions[RSK_SHUFFLE_WEIRD_EGG], &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD], &mOptions[RSK_SHUFFLE_MERCHANTS], diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 433ae8c2c70..cc872e8b417 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -13374,6 +13374,10 @@ void Player_Action_8084BF1C(Player* this, PlayState* play) { this->fallStartHeight = this->actor.world.pos.y; this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; + if (!GameInteractor_Should(VB_CLIMB, true, &sp80, &sp84)) { + return; + } + if ((this->av1.actionVar1 != 0) && (ABS(sp84) < ABS(sp80))) { phi_f0 = ABS(sp80) * 0.0325f; sp84 = 0; From e80bba77d682c485ca209ab8c8f1f9e1636368a0 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:54:25 +0000 Subject: [PATCH 02/18] fix seed generation --- .../randomizer/location_access/dungeons/fire_temple.cpp | 4 ++-- .../location_access/overworld/gerudo_fortress.cpp | 6 +++--- .../randomizer/location_access/overworld/zoras_river.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp index 2e5307de3d9..14e1cec6221 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -11,7 +11,7 @@ void RegionTable_Init_FireTemple() { //Exits Entrance(RR_FIRE_TEMPLE_FOYER, []{return ctx->GetDungeon(FIRE_TEMPLE)->IsVanilla();}), Entrance(RR_FIRE_TEMPLE_MQ_FOYER_LOWER, []{return ctx->GetDungeon(FIRE_TEMPLE)->IsMQ();}), - Entrance(RR_DMC_CENTRAL_LOCAL, []{return true;}), + Entrance(RR_DMC_OUTSIDE_FIRE_TEMPLE, []{return true;}), }); #pragma region Vanilla @@ -387,7 +387,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_SWITCH_CLIMB] = Region("Fire Temple Switch Climb", SCENE_FIRE_TEMPLE, {}, {}, { //Exits Entrance(RR_FIRE_TEMPLE_ABOVE_3F_FLARE_DANCER, []{return true;}), - Entrance(RR_FIRE_TEMPLE_NARROW_STAIRS, []{return logic->CanHitSwitch(ED_BOMB_THROW) && logic->CanUse(RG_CLIMB);}), + Entrance(RR_FIRE_TEMPLE_NARROW_STAIRS, []{return logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_CLIMB);}), }); areaTable[RR_FIRE_TEMPLE_NARROW_STAIRS] = Region("Fire Temple Narrow Stairs", SCENE_FIRE_TEMPLE, {}, { 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 642cdf2319c..adb8a9b03d1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp @@ -9,7 +9,7 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_OUTSKIRTS] = Region("Gerudo Fortress Outskirts", SCENE_GERUDOS_FORTRESS, { //Events - EventAccess(LOGIC_GF_GATE_OPEN, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->CanUse(RG_CLIMB);}), + EventAccess(LOGIC_GF_GATE_OPEN, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CLIMB);}), }, { //Locations LOCATION(RC_GF_OUTSKIRTS_NE_CRATE, (logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)) && logic->CanBreakCrates()), @@ -92,7 +92,7 @@ void RegionTable_Init_GerudoFortress() { //Exits Entrance(RR_TH_STEEP_SLOPE_CELL, []{return true;}), Entrance(RR_GF_NEAR_GROTTO, []{return true;}), - Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_GF_ABOVE_GTG, []{return true;}), Entrance(RR_GF_BELOW_GS, []{return logic->IsAdult && logic->CanGroundJump();}), }); @@ -134,7 +134,7 @@ void RegionTable_Init_GerudoFortress() { Entrance(RR_GF_OUTSIDE_GTG, []{return true;}), Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true;}), Entrance(RR_GF_SLOPED_ROOF, []{return logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS));}), - Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return logic->CanUse(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_GF_TO_GTG, []{return logic->IsAdult && ctx->GetTrickOption(RT_GF_LEDGE_CLIP_INTO_GTG).Get();}), }); 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 ca376a304a8..9972c11bade 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, []{return true;}), - Entrance(RR_ZR_ATOP_LADDER, []{return (/*(logic->IsAdult || str0) &&*/ logic->CanUse(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_HOOKSHOT))) || CanPlantBean(RR_ZORAS_RIVER, RG_ZORAS_RIVER_BEAN_SOUL);}), + Entrance(RR_ZR_ATOP_LADDER, []{return (/*(logic->IsAdult || str0) &&*/ logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_HOOKSHOT))) || CanPlantBean(RR_ZORAS_RIVER, RG_ZORAS_RIVER_BEAN_SOUL);}), Entrance(RR_ZR_PILLAR, []{return (logic->IsChild/* && str0*/) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_LOWER));}), Entrance(RR_THE_LOST_WOODS, []{return logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_ZR_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), From dfdf312fb96e331d19a5cc76f0768f9e5bef81f7 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Sun, 4 Jan 2026 23:12:29 +0000 Subject: [PATCH 03/18] item pool, gv, french --- .../randomizer/3drando/hint_list/hint_list_item.cpp | 2 +- soh/soh/Enhancements/randomizer/3drando/item_pool.cpp | 2 +- soh/soh/Enhancements/randomizer/3drando/shops.cpp | 5 +++++ soh/soh/Enhancements/randomizer/item_list.cpp | 2 +- .../randomizer/location_access/overworld/gerudo_valley.cpp | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index 3f833a4ca0c..4f6a8fae075 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -2109,7 +2109,7 @@ void StaticData::HintTable_Init_Item() { // /*spanish*/un desbloqueador maestro //RANDOTODO if these are ever used for anything other than name, they want obscure and ambiguous hints - hintTextTable[RHT_CLIMB] = HintText(CustomMessage("the ability to climb", /*german*/"!!!", /*french*/"la capacité de grimper")); + hintTextTable[RHT_CLIMB] = HintText(CustomMessage("the ability to climb", /*german*/TODO_TRANSLATE, /*french*/"la capacité de grimper")); hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("an infinite Quiver", /*german*/"der unendliche Köcher", /*french*/"un Carquois Infini")); diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 390951e0db4..8bbff782f85 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -393,7 +393,7 @@ void GenerateItemPool() { AddItemToPool(RG_PROGRESSIVE_SCALE, 3 + bronzeScale, 2 + bronzeScale, 2 + bronzeScale, 2 + bronzeScale); if (ctx->GetOption(RSK_SHUFFLE_CLIMB)) { - AddFixedItemToPool(RG_CLIMB, 1); + AddItemToPool(RG_CLIMB, 2, 1, 1, 1); } if (ctx->GetOption(RSK_SHUFFLE_BEEHIVES)) { diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp index 01683eec466..4cad2112910 100644 --- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp @@ -997,6 +997,11 @@ void InitTrickNames() { Text{ "Stalfos Key" }, Text{ "Nightmare Key" }, Text{ "Graveyard Key" }, Text{ "King's Key" }, Text{ "Hero's Key" }, }; + trickNameTable[RG_CLIMB] = { + // TODO_TRANSLATE + Text{ "Cling" }, + }; + trickNameTable[RG_OCARINA_A_BUTTON] = { Text{ "Ocarina J Button", "Touche Ha de l'Ocarina", "J-Taste der Okarina" }, Text{ "Ocarina Ayy Button", "Touche Ah de l'Ocarina", "A-Taste der Flöte" }, diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index b5db01fb15c..2e1e46841f3 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -371,7 +371,7 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); - itemTable[RG_CLIMB] = Item(RG_CLIMB, Text{ "Climb", "", "" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_CLIMB, RG_CLIMB, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_CLIMB] = Item(RG_CLIMB, Text{ "Climb", TODO_TRANSLATE, "Grimper" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_CLIMB, RG_CLIMB, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_CLIMB].SetCustomDrawFunc(Randomizer_DrawLadder); itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp index 870abd6c3cb..df390738f4a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -28,7 +28,7 @@ void RegionTable_Init_GerudoValley() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy() || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS));}), }, { //Locations - LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, ((logic->IsChild || logic->HasItem(RG_BRONZE_SCALE)) && logic->HasItem(RG_CLIMB)) || CanPlantBean(RR_GV_UPPER_STREAM, RG_GERUDO_VALLEY_BEAN_SOUL)),//can use cucco as child + LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, (logic->HasItem(RG_CLIMB) && (logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)))) || logic->CanUse(RG_LONGSHOT) || CanPlantBean(RR_GV_UPPER_STREAM, RG_GERUDO_VALLEY_BEAN_SOUL)), LOCATION(RC_GV_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanAttack()), LOCATION(RC_GV_COW, logic->IsChild && logic->CanUse(RG_EPONAS_SONG)), LOCATION(RC_GV_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), From 3d47bf4ff28042cb12aaec0b119ee6c72e2d994d Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Mon, 5 Jan 2026 01:03:19 +0000 Subject: [PATCH 04/18] logic,feedback --- .../randomizer/location_access.cpp | 138 ++++++++++++++---- .../dungeons/bottom_of_the_well.cpp | 14 +- .../dungeons/spirit_temple.cpp | 16 +- .../overworld/gerudo_valley.cpp | 21 +-- soh/soh/Enhancements/randomizer/logic.cpp | 9 +- 5 files changed, 141 insertions(+), 57 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index 05f3851ddc2..9cc6b39c2b1 100644 --- a/soh/soh/Enhancements/randomizer/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/location_access.cpp @@ -1,11 +1,7 @@ #include "location_access.h" -#include "soh/Enhancements/randomizer/dungeon.h" #include "soh/Enhancements/randomizer/static_data.h" #include "soh/Enhancements/randomizer/SeedContext.h" -#include "soh/Enhancements/randomizer/3drando/item_pool.hpp" -#include "soh/Enhancements/randomizer/3drando/spoiler_log.hpp" -#include "soh/Enhancements/randomizer/trial.h" #include "soh/Enhancements/randomizer/entrance.h" #include "soh/Enhancements/debugger/performanceTimer.h" @@ -626,31 +622,117 @@ std::array areaTable; // clang-format off std::map Region::spiritLogicData = { //Vanilla Child uses ExplosiveKeyLogic here because they need to exist for shared adult checks - {RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, {5, 0, 3, 0, []{return true;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;}}}, - {RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, {5, 0, 3, 0, []{return true/*logic->CanClimbHigh()*/;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;}}}, - {RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, {5, 0, 3, 0, []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritSunOnFloorToStatue();}, []{return true/*logic->CanClimbHigh()*/;}, []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}}}, - {RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh()*/;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;}}}, - {RR_SPIRIT_TEMPLE_INNER_WEST_HAND, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh()*/;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;}}}, - {RR_SPIRIT_TEMPLE_GS_LEDGE, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->SpiritWestToSkull()/* && logic->CanClimbHigh()*/;}, []{return logic->SpiritExplosiveKeyLogic() && logic->SpiritWestToSkull()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SpiritWestToSkull()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;}}}, - {RR_SPIRIT_TEMPLE_STATUE_ROOM, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic();}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true;}}}, + {RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, {5, 0, 3, 0, + []{return true;}, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + }}, + {RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, {5, 0, 3, 0, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + }}, + {RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, {5, 0, 3, 0, + []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritSunOnFloorToStatue();}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}, + []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + }}, + {RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, {5, 0, 3, 0, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + }}, + {RR_SPIRIT_TEMPLE_INNER_WEST_HAND, {5, 0, 3, 0, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + }}, + {RR_SPIRIT_TEMPLE_GS_LEDGE, {5, 0, 3, 0, + []{return logic->SpiritExplosiveKeyLogic() && logic->SpiritWestToSkull() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return logic->SpiritExplosiveKeyLogic() && logic->SpiritWestToSkull() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->SpiritWestToSkull() && ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS));}, + }}, + {RR_SPIRIT_TEMPLE_STATUE_ROOM, {5, 0, 3, 0, + []{return logic->SpiritExplosiveKeyLogic();}, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return true;}, + }}, //Assumes SpiritSunBlockSouthLedge() for all access - {RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*((logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)) && str0) || (logic->CanKillEnemy(RE_BEAMOS) && logic->CanUse(RG_LONGSHOT))*/;}}}, - {RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*((logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)) && str0) || (logic->CanKillEnemy(RE_BEAMOS) && logic->CanUse(RG_LONGSHOT))*/;}}}, - {RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND, {5, 5, 3, 3, []{return logic->OuterWestHandLogic();}, []{return logic->OuterWestHandLogic();}, []{return logic->OuterWestHandLogic();}}}, - {RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT)/* && logic->CanClimbHigh()*/;}, []{return true/*logic->CanClimbHigh() && str0*/;}, []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}}}, - {RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT)/* && logic->CanClimbHigh()*/;}, []{return true/*logic->CanClimbHigh() && str0*/;}, []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}}}, - {RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT) && logic->SpiritEastToSwitch();}, []{return logic->SpiritEastToSwitch()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SpiritEastToSwitch() && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}}}, - //MQ /*&& logic->CanClimbHigh()*/ - {RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, {7, 6, 7, 7, []{return logic->StatueRoomMQKeyLogic();}, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6) && logic->CanHitSwitch()/* && logic->Climb*/;}, []{return logic->StatueRoomMQKeyLogic() && logic->CanHitSwitch()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;}}}, - {RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, {7, 6, 7, 7, []{return logic->StatueRoomMQKeyLogic() && logic->CanHitSwitch()/* && logic->CanClimbHigh()*/;}, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6)/* && logic->Climb*/;}, []{return logic->StatueRoomMQKeyLogic()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;}}}, - {RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_CHILD, {7, 0, 0, 0, []{return logic->CanHitSwitch()/* && logic->CanClimbHigh()*/;}, []{return true/*logic->Climb*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;}}}, - {RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, {7, 0, 0, 0, []{return logic->CanHitSwitch() && logic->MQSpiritWestToPots()/* && logic->CanClimbHigh()*/;}, []{return logic->MQSpiritWestToPots()/* && logic->Climb*/;}, []{return /*logic->CanUse(RG_HOVER_BOOTS) || (logic->CanClimb() && */logic->MQSpiritWestToPots()/*)*/;}}}, - {RR_SPIRIT_TEMPLE_MQ_INNER_RIGHT_HAND, {7, 0, 0, 0, []{return logic->CanHitSwitch() && logic->MQSpiritWestToPots()/* && logic->CanClimbHigh()*/;}, []{return logic->MQSpiritWestToPots()/* && logic->Climb*/;}, []{return /*logic->CanUse(RG_HOVER_BOOTS) || (logic->CanClimb() && */logic->MQSpiritWestToPots()/*)*/;}}}, - {RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, {7, 0, 0, 0, []{return logic->CanHitSwitch()/* && logic->CanClimbHigh()*/;}, []{return true;}, []{return true;}}}, - {RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, {7, 0, 0, 0, []{return logic->CanHitSwitch() && logic->MQSpiritStatueToSunBlock()/* && logic->CanClimbHigh()*/;}, []{return logic->MQSpiritStatueToSunBlock()/* && logic->Climb*/;}, []{return logic->MQSpiritStatueToSunBlock()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;}}}, - {RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, {7, 7, 4, 4, []{return logic->CanHitSwitch() && logic->OuterWestHandMQLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->OuterWestHandMQLogic();}, []{return logic->OuterWestHandMQLogic();}}}, - {RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR, {7, 0, 0, 0, []{return logic->CanHitSwitch() && /* logic->CanClimbHigh() &&*/ - areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR].AnyAgeTime([]{return logic->MQSpiritStatueSouthDoor();});}, []{return true;}, []{return areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR].AnyAgeTime([]{return logic->MQSpiritStatueSouthDoor();});}}}, + {RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, {5, 0, 3, 0, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return (((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS))/* && str0*/) || (logic->CanKillEnemy(RE_BEAMOS) && logic->CanUse(RG_LONGSHOT));}, + }}, + {RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, {5, 0, 3, 0, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return (((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS))/* && str0*/) || (logic->CanKillEnemy(RE_BEAMOS) && logic->CanUse(RG_LONGSHOT));}, + }}, + {RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND, {5, 5, 3, 3, + []{return logic->OuterWestHandLogic();}, + []{return logic->OuterWestHandLogic();}, + []{return logic->OuterWestHandLogic();}, + }}, + {RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, {5, 0, 3, 0, + []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + }}, + {RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, {5, 0, 3, 0, + []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + }}, + {RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, {5, 0, 3, 0, + []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT) && logic->SpiritEastToSwitch();}, + []{return logic->SpiritEastToSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->SpiritEastToSwitch() && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}}}, + //MQ + {RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, {7, 6, 7, 7, + []{return logic->StatueRoomMQKeyLogic();}, + []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6) && logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, + []{return logic->StatueRoomMQKeyLogic() && logic->CanHitSwitch() && ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS));}, + }}, + {RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, {7, 6, 7, 7, + []{return logic->StatueRoomMQKeyLogic() && logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, + []{return logic->StatueRoomMQKeyLogic() && ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS));}, + }}, + {RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_CHILD, {7, 0, 0, 0, + []{return logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + }}, + {RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, {7, 0, 0, 0, + []{return logic->CanHitSwitch() && logic->MQSpiritWestToPots() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return logic->MQSpiritWestToPots() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, + []{return logic->CanUse(RG_HOVER_BOOTS) || ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->MQSpiritWestToPots());}, + }}, + {RR_SPIRIT_TEMPLE_MQ_INNER_RIGHT_HAND, {7, 0, 0, 0, + []{return logic->CanHitSwitch() && logic->MQSpiritWestToPots() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return logic->MQSpiritWestToPots() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, + []{return logic->CanUse(RG_HOVER_BOOTS) || ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->MQSpiritWestToPots());}, + }}, + {RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, {7, 0, 0, 0, + []{return logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return true;}, + []{return true;}, + }}, + {RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, {7, 0, 0, 0, + []{return logic->CanHitSwitch() && logic->MQSpiritStatueToSunBlock() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, + []{return logic->MQSpiritStatueToSunBlock() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, + []{return logic->MQSpiritStatueToSunBlock() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}, + }}, + {RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, {7, 7, 4, 4, + []{return logic->CanHitSwitch() && logic->OuterWestHandMQLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))/* && str0*/;}, + []{return logic->OuterWestHandMQLogic();}, + []{return logic->OuterWestHandMQLogic();}, + }}, + {RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR, {7, 0, 0, 0, + []{return logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR].AnyAgeTime([]{return logic->MQSpiritStatueSouthDoor();});}, + []{return true;}, + []{return areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR].AnyAgeTime([]{return logic->MQSpiritStatueSouthDoor();});}, + }}, }; // clang-format on 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 b3be5e1330c..3b4364e6d94 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, []{return logic->IsChild/*CanCrawl && CanClimb*/;}), + Entrance(RR_BOTW_ENTRYWAY, []{return logic->IsChild/*CanCrawl*/ && logic->HasItem(RG_CLIMB);}), Entrance(RR_BOTW_PERIMETER, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), }); @@ -166,8 +166,8 @@ void RegionTable_Init_BottomOfTheWell() { //Exits //Climb always needed in case the water is lowered out of logic //Adult can ground jump out of the pit without climb but needs a way through the crawlspace - Entrance(RR_BOTW_PERIMETER, []{return logic->IsChild/*CanCrawl*/ && (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE))/*&& CanClimb*/;}), - Entrance(RR_BOTW_NEAR_BOSS_UPPER, []{return true/*CanClimb or (isAdult && CanGroundJump)*/;}), + Entrance(RR_BOTW_PERIMETER, []{return logic->IsChild/*CanCrawl*/ && (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE)) && logic->HasItem(RG_CLIMB);}), + Entrance(RR_BOTW_NEAR_BOSS_UPPER, []{return logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanGroundJump());}), }); areaTable[RR_BOTW_NEAR_BOSS_UPPER] = Region("Bottom of the Well Near Boss Upper", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { @@ -349,8 +349,8 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_MQ_BEHIND_MOAT] = Region("Bottom of the Well MQ Behind Moat", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { //Exits //Climb always needed in case water is lowered out of logic - Entrance(RR_BOTW_MQ_PERIMETER, []{return (logic->Get(LOGIC_BOTW_LOWERED_WATER)|| logic->HasItem(RG_BRONZE_SCALE) || - (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))/* && CanClimb*/);}), + Entrance(RR_BOTW_MQ_PERIMETER, []{return ((logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE)) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))) || + (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_BOTW_MQ_CRYPT, []{return logic->SmallKeys(SCENE_BOTTOM_OF_THE_WELL, 2);}), }); @@ -386,8 +386,8 @@ void RegionTable_Init_BottomOfTheWell() { //Exits //Climb always needed in case the water is lowered out of logic //Adult can ground jump out of the pit without climb but needs a way through the crawlspace - Entrance(RR_BOTW_MQ_PERIMETER, []{return logic->IsChild/*CanCrawl*/ && (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE))/*&& CanClimb*/;}), - Entrance(RR_BOTW_MQ_NEAR_BOSS_UPPER, []{return true/*CanClimb*/;}), + Entrance(RR_BOTW_MQ_PERIMETER, []{return logic->IsChild/*CanCrawl*/ && (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->HasItem(RG_BRONZE_SCALE)) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_BOTW_MQ_NEAR_BOSS_UPPER, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), }); areaTable[RR_BOTW_MQ_NEAR_BOSS_UPPER] = Region("Bottom of the Well MQ Near Boss Upper", SCENE_BOTTOM_OF_THE_WELL, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index ae7f6b24fbd..1fdab773f58 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -170,7 +170,7 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, logic->CanUse(RG_SONG_OF_TIME) && logic->CanKillEnemy(RE_GOLD_SKULLTULA)), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_ABOVE_BOULDERS, []{return true/*CanClimb() || IsAdult() || CanGroundJump*/;}), + Entrance(RR_SPIRIT_TEMPLE_ABOVE_BOULDERS, []{return logic->IsAdult || logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanGroundJump();}), Entrance(RR_SPIRIT_TEMPLE_PAST_BOULDERS, []{return logic->Get(LOGIC_SPIRIT_BOUNDERS_SILVERS);}), }); @@ -186,7 +186,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_1F_MIRROR_ROOM] = Region("Spirit Temple 1F Mirror Room", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits Entrance(RR_SPIRIT_TEMPLE_ADULT_SIDE_HUB, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5);}), - Entrance(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return true/*CanClimbHigh()*/;}), + Entrance(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), }); areaTable[RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM] = Region("Spirit Temple 2F Mirror Room", SCENE_SPIRIT_TEMPLE, {}, { @@ -259,7 +259,7 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->CanBreakPots();})), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return true/*CanClimb()*/;}), + Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)));}), //explicit adult check here is a precaution against possible child logic leaking, child with a hookshot can do this @@ -273,8 +273,8 @@ void RegionTable_Init_SpiritTemple() { //If you do not have explosives to kill Beamos, but do have a way to defeat Iron Knuckles, this becomes possible with 4 keys instead. Entrance(RR_SPIRIT_TEMPLE_ADULT_SIDE_HUB, []{return ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->IsAdult && - ((logic->CanKillEnemy(RE_BEAMOS) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, /*CanClimb() && str0 ?*/ 2 /*: 3*/)) || - (/*CanClimb() && str0 && */logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4)));}), + ((logic->CanKillEnemy(RE_BEAMOS) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))/* && str0*/ ? 2 : 3)) || + ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))/* && str0*/ && logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4)));}), }); areaTable[RR_SPIRIT_TEMPLE_EMPTY_STAIRS] = Region("Spirit Temple Empty Stairs", SCENE_SPIRIT_TEMPLE, {}, {}, { @@ -357,7 +357,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_INNER_LEFT_HAND] = Region("Spirit Temple Inner Left Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations //Assumes RR_SPIRIT_TEMPLE_INNER_WEST_HAND access via RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD and RR_SPIRIT_TEMPLE_STATUE_ROOM. - LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, []{return logic->CanUse(RG_ZELDAS_LULLABY)/* && CanClimb()*/;})), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, []{return logic->CanUse(RG_ZELDAS_LULLABY) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}), @@ -771,7 +771,7 @@ void RegionTable_Init_SpiritTemple() { (logic->CanUse(RG_BOOMERANG) && logic->HasExplosives());})), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_CHILD, []{return true/*logic->CanClimb()*/;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_CHILD, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR, []{return logic->Get(LOGIC_SPIRIT_STATUE_SOUTH_DOOR);}), //explicit adult check here is a precaution against possible Child logic leaking, Child with a hookshot can do this //It's possible to climb the legs of the statue to line up a longshot hit, but you can just go via West @@ -946,7 +946,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_LOWER] = Region("Spirit Temple MQ Symphony Room Lower", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_UPPER, []{return true/*CanClimb() || IsAdult || CanGroundJump()*/;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_UPPER, []{return logic->IsAdult || logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanGroundJump();}), //Implies CanPassEnemy(RE_MOBLIN_CHIEF) Entrance(RR_SPIRIT_TEMPLE_MQ_SKULLTULA_ROOM, []{return logic->Get(LOGIC_SPIRIT_MQ_SYMPHONY_ROOM_DOOR);}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp index df390738f4a..518c27143d8 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -10,8 +10,8 @@ void RegionTable_Init_GerudoValley() { EventAccess(LOGIC_BUG_ACCESS, []{return logic->IsChild;}), }, { //Locations - LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), - LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, logic->IsChild), //can use cucco as child + LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), + LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, logic->IsChild || ((logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_CLIMB))), }, { //Exits Entrance(RR_HYRULE_FIELD, []{return true;}), @@ -69,14 +69,15 @@ void RegionTable_Init_GerudoValley() { areaTable[RR_GV_FORTRESS_SIDE] = Region("GV Fortress Side", SCENE_GERUDO_VALLEY, {}, { //Locations - LOCATION(RC_GV_CHEST, logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)))), - LOCATION(RC_GV_TRADE_SAW, logic->IsAdult && logic->CanUse(RG_POACHERS_SAW)), - LOCATION(RC_GV_GS_BEHIND_TENT, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), - LOCATION(RC_GV_GS_PILLAR, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), - LOCATION(RC_GV_CRATE_BRIDGE_1, logic->IsChild && logic->CanBreakCrates()), - LOCATION(RC_GV_CRATE_BRIDGE_2, logic->IsChild && logic->CanBreakCrates()), - LOCATION(RC_GV_CRATE_BRIDGE_3, logic->IsChild && logic->CanBreakCrates()), - LOCATION(RC_GV_CRATE_BRIDGE_4, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_GV_CHEST, logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)))), + LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, (logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_CLIMB)), + LOCATION(RC_GV_TRADE_SAW, logic->IsAdult && logic->CanUse(RG_POACHERS_SAW)), + LOCATION(RC_GV_GS_BEHIND_TENT, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), + LOCATION(RC_GV_GS_PILLAR, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), + LOCATION(RC_GV_CRATE_BRIDGE_1, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_GV_CRATE_BRIDGE_2, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_GV_CRATE_BRIDGE_3, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_GV_CRATE_BRIDGE_4, logic->IsChild && logic->CanBreakCrates()), }, { //Exits Entrance(RR_GF_OUTSKIRTS, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 1ef9fbb3318..7e8043fea7f 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -1,7 +1,6 @@ #include "logic.h" #include "../debugger/performanceTimer.h" -#include #include #include @@ -2539,7 +2538,7 @@ bool Logic::CouldMQSpirit4KeyWestHand() { // If we have the longshot, we can also guarantee access to the outer west hand as you can longshot from the east hand // to the west Implies CanKillEnemy(RE_IRON_KNUCKLE) bool Logic::OuterWestHandLogic() { - return HasExplosives() /* && CanClimbHigh() && str0*/ && + return HasExplosives() && (HasItem(RG_CLIMB) || CanUse(RG_LONGSHOT)) /*&& str0*/ && SmallKeys(SCENE_SPIRIT_TEMPLE, HasItem(RG_LONGSHOT) ? 3 : 5); } @@ -2553,8 +2552,10 @@ bool Logic::StatueRoomMQKeyLogic() { // the ability to hit switches and the ability to climb because only child can reach the initial child lock // without opening the Statue room to Broken Wall Room lock first // if adult can ever cross crawlspaces this becomes more complicated. - return SmallKeys(SCENE_SPIRIT_TEMPLE, - IsChild && Get(LOGIC_REVERSE_SPIRIT_CHILD) && CanHitSwitch() /* && CanClimbHigh()*/ ? 6 : 7); + return SmallKeys(SCENE_SPIRIT_TEMPLE, IsChild && Get(LOGIC_REVERSE_SPIRIT_CHILD) && CanHitSwitch() && + (HasItem(RG_CLIMB) || CanUse(RG_LONGSHOT)) + ? 6 + : 7); } void Logic::Reset(bool resetSaveContext /*= true*/) { From ba0917391116121e483f4d410d31a1487702b4e2 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Mon, 5 Jan 2026 02:50:51 +0000 Subject: [PATCH 05/18] twinrova needs climb or hookshot --- .../randomizer/location_access/dungeons/spirit_temple.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index 1fdab773f58..42cf932f0df 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -1143,7 +1143,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BOSS_ROOM] = Region("Spirit Temple Boss Room", SCENE_SPIRIT_TEMPLE_BOSS, { // Events - EventAccess(LOGIC_SPIRIT_TEMPLE_CLEAR, []{return logic->CanKillEnemy(RE_TWINROVA);}), + EventAccess(LOGIC_SPIRIT_TEMPLE_CLEAR, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->CanKillEnemy(RE_TWINROVA);}), }, { // Locations LOCATION(RC_SPIRIT_TEMPLE_TWINROVA_HEART, logic->Get(LOGIC_SPIRIT_TEMPLE_CLEAR)), From 77365afaefe32a34ee7e11587027f60f05fcab21 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Tue, 6 Jan 2026 01:42:41 +0000 Subject: [PATCH 06/18] shadow --- .../randomizer/location_access/dungeons/shadow_temple.cpp | 8 ++++---- soh/soh/Enhancements/randomizer/randomizerTypes.h | 1 + soh/soh/Enhancements/randomizer/settings.cpp | 3 +++ 3 files changed, 8 insertions(+), 4 deletions(-) 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 45973796d68..b654c5b2469 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp @@ -267,8 +267,8 @@ void RegionTable_Init_ShadowTemple() { }, { //Exits Entrance(RR_SHADOW_TEMPLE_ROOM_TO_BOAT, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4);}), - Entrance(RR_SHADOW_TEMPLE_SPINNING_BLADES, []{return logic->HasItem(RG_GORONS_BRACELET);}), - Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, []{return ((logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_ZELDAS_LULLABY);}), + Entrance(RR_SHADOW_TEMPLE_SPINNING_BLADES, []{return logic->Get(LOGIC_SHADOW_SHORTCUT_BLOCK) && logic->HasItem(RG_CLIMB);}), + Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, []{return ((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);}), }); areaTable[RR_SHADOW_TEMPLE_BEYOND_BOAT] = Region("Shadow Temple Beyond Boat", SCENE_SHADOW_TEMPLE, { @@ -640,9 +640,9 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_MQ_SCARECROW_SOUTH_HEART, logic->ReachDistantScarecrow()), }, { //Exits - Entrance(RR_SHADOW_TEMPLE_MQ_SHORTCUT_PATH, []{return logic->Get(LOGIC_SHADOW_SHORTCUT_BLOCK);}), + Entrance(RR_SHADOW_TEMPLE_MQ_SHORTCUT_PATH, []{return logic->Get(LOGIC_SHADOW_SHORTCUT_BLOCK) && logic->HasItem(RG_CLIMB);}), Entrance(RR_SHADOW_TEMPLE_MQ_B4_GIBDO_ROOM, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 5);}), - Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, []{return ((logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_ZELDAS_LULLABY);}), + Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, []{return ((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);}), }); areaTable[RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT] = Region("Shadow Temple MQ Beyond Boat", SCENE_SHADOW_TEMPLE, { diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index d37a982c8f1..e2e1a8189e7 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -4263,6 +4263,7 @@ typedef enum { RT_SHADOW_UMBRELLA_CLIP, RT_SHADOW_UMBRELLA_GS, RT_SHADOW_FREESTANDING_KEY, + RT_SHADOW_BOAT_JUMP, RT_SHADOW_STATUE, RT_SHADOW_BONGO, RT_LENS_SHADOW_MQ, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 94d67e985c7..9bbfe43ee09 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1982,6 +1982,9 @@ void Settings::CreateOptions() { OPT_TRICK(RT_SHADOW_FREESTANDING_KEY, RCQUEST_VANILLA, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "Shadow Temple Freestanding Key with Bombchu", "Release the Bombchu with good timing so that it explodes near the bottom of the pot."); + OPT_TRICK(RT_SHADOW_BOAT_JUMP, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, + "Shadow Temple Boat Jump", + "Boat can be boarded by jumping on wheel, skipping block and ladder."); OPT_TRICK(RT_SHADOW_STATUE, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "Shadow Temple River Statue with Bombchu", "By sending a Bombchu around the edge of the gorge, you can knock down the statue without needing a Bow. " From 0cc904570c0f43b98033e5535f50abfa48a634a1 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Tue, 6 Jan 2026 20:23:43 +0000 Subject: [PATCH 07/18] fix kf --- .../randomizer/location_access/overworld/kokiri_forest.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 6b4691a0458..6219e4f6f43 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -78,15 +78,14 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_ADULT_GRASS_20, logic->IsAdult && logic->CanCutShrubs()), }, { //Exits - Entrance(RR_KF_LINKS_PORCH, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_KF_LINKS_PORCH, []{return logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS));}), Entrance(RR_KF_MIDOS_HOUSE, []{return true;}), Entrance(RR_KF_SARIAS_HOUSE, []{return true;}), Entrance(RR_KF_HOUSE_OF_TWINS, []{return true;}), Entrance(RR_KF_KNOW_IT_ALL_HOUSE, []{return true;}), Entrance(RR_KF_KOKIRI_SHOP, []{return true;}), Entrance(RR_KF_OUTSIDE_DEKU_TREE, []{return (logic->IsAdult && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->Get(LOGIC_FOREST_TEMPLE_CLEAR))) || ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_OFF) || logic->Get(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD);}), - // Maybe adult jumping to Mido's Roof is trick, in which case bean can also get adult up here - Entrance(RR_KF_OUTSIDE_LOST_WOODS, []{return logic->IsAdult || logic->HasItem(RG_CLIMB);}), + Entrance(RR_KF_OUTSIDE_LOST_WOODS, []{return logic->HasItem(RG_CLIMB) || (logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)));}), Entrance(RR_LW_BRIDGE_FROM_FOREST, []{return logic->IsAdult || ctx->GetOption(RSK_FOREST).IsNot(RO_CLOSED_FOREST_ON) || logic->Get(LOGIC_DEKU_TREE_CLEAR);}), Entrance(RR_KF_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), }); From 6b1b7a93672774a5e5bdb495dabbc32188c5763c Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Thu, 8 Jan 2026 07:48:06 +0000 Subject: [PATCH 08/18] feedback pt 1 --- soh/soh/Enhancements/randomizer/entrance.cpp | 4 +- soh/soh/Enhancements/randomizer/item_list.cpp | 4 +- .../location_access/dungeons/deku_tree.cpp | 25 ++++++----- .../dungeons/dodongos_cavern.cpp | 4 +- .../location_access/dungeons/fire_temple.cpp | 18 +++----- .../dungeons/forest_temple.cpp | 6 +-- .../dungeons/jabujabus_belly.cpp | 10 ++--- .../dungeons/spirit_temple.cpp | 15 +++---- .../overworld/castle_grounds.cpp | 4 +- .../overworld/death_mountain_crater.cpp | 12 ++--- .../overworld/death_mountain_trail.cpp | 10 ++--- .../overworld/gerudo_fortress.cpp | 4 +- .../overworld/kokiri_forest.cpp | 45 +++++++++++++------ .../overworld/sacred_forest_meadow.cpp | 1 + .../location_access/overworld/zoras_river.cpp | 13 ------ .../Enhancements/randomizer/randomizerTypes.h | 5 +-- soh/soh/Enhancements/randomizer/settings.cpp | 3 -- 17 files changed, 90 insertions(+), 93 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 13a95f993aa..1347b33c38b 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -413,8 +413,8 @@ void SetAllEntrancesData() { { EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET) } }, { { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET) }, { EntranceType::GrottoGrave, RR_DMT_STORMS_GROTTO, RR_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET) } }, - { { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_AVALANCHE, RR_DMT_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET) }, - { EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_AVALANCHE, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET) } }, + { { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_ROCKFALL, RR_DMT_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET) }, + { EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_ROCKFALL, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET) } }, { { EntranceType::GrottoGrave, RR_KAK_BACKYARD, RR_KAK_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET) }, { EntranceType::GrottoGrave, RR_KAK_OPEN_GROTTO, RR_KAK_BACKYARD, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET) } }, { { EntranceType::GrottoGrave, RR_KAKARIKO_VILLAGE, RR_KAK_REDEAD_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET) }, diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 2e1e46841f3..8e621489aae 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -369,9 +369,9 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "C-Rechts-Taste der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_RIGHT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); - itemTable[RG_CLIMB] = Item(RG_CLIMB, Text{ "Climb", TODO_TRANSLATE, "Grimper" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_CLIMB, RG_CLIMB, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_CLIMB] = Item(RG_CLIMB, Text{ "Climb", TODO_TRANSLATE, "Grimper" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_CLIMB, RG_CLIMB, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_CLIMB].SetCustomDrawFunc(Randomizer_DrawLadder); itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); 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 9caf1db9d56..369e47f7825 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -23,7 +23,7 @@ void RegionTable_Init_DekuTree() { }, { //Locations LOCATION(RC_DEKU_TREE_MAP_CHEST, true), - LOCATION(RC_DEKU_TREE_LOBBY_LOWER_HEART, true), + LOCATION(RC_DEKU_TREE_LOBBY_LOWER_HEART, logic->CanUse(RG_BOOMERANG)), LOCATION(RC_DEKU_TREE_LOBBY_UPPER_HEART, logic->CanPassEnemy(RE_BIG_SKULLTULA)), LOCATION(RC_DEKU_TREE_LOBBY_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_LOBBY_GRASS_2, logic->CanCutShrubs()), @@ -70,10 +70,10 @@ void RegionTable_Init_DekuTree() { //Locations LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), - LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_1, logic->CanCutShrubs() && logic->CanReflectNuts()), - LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_2, logic->CanCutShrubs() && logic->CanReflectNuts()), - LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_3, logic->CanCutShrubs() && logic->CanReflectNuts()), - LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_4, logic->CanCutShrubs() && logic->CanReflectNuts()), + LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_1, logic->CanCutShrubs()), + LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_2, logic->CanCutShrubs()), + LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_3, logic->CanCutShrubs()), + LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_4, logic->CanCutShrubs()), }, { //Exits Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_HOVER_BOOTS);}), @@ -104,12 +104,12 @@ void RegionTable_Init_DekuTree() { //Locations LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, true), 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)), + 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) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_DEKU_TREE_BASEMENT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_BASEMENT_GRASS_2, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEKU_TREE_LOBBY, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_DEKU_TREE_LOBBY, []{return logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT));}), Entrance(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, []{return AnyAgeTime([]{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);});}), Entrance(RR_DEKU_TREE_BASEMENT_UPPER, []{return logic->IsAdult || ctx->GetTrickOption(RT_DEKU_B1_SKIP) || logic->CanGroundJump() || logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK);}), Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return false;}), @@ -123,7 +123,7 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_BASEMENT_SCRUB_ROOM_GRASS_4, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return logic->HasItem(RG_CLIMB);}), + Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return true;}), Entrance(RR_DEKU_TREE_BASEMENT_WATER_ROOM_FRONT, []{return AnyAgeTime([]{return logic->CanHitEyeTargets();});}), }); @@ -202,7 +202,7 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_BEFORE_BOSS_GRASS_3, logic->CanCutShrubs() && logic->HasFireSourceWithTorch()), }, { //Exits - Entrance(RR_DEKU_TREE_BASEMENT_UPPER, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_DEKU_TREE_BASEMENT_UPPER, []{return logic->HasItem(RG_CLIMB) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, []{return AnyAgeTime([]{return logic->CanReflectNuts();});}), }); @@ -216,6 +216,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->HasFireSource();}), }, { //Locations + LOCATION(RC_DEKU_TREE_MQ_LOBBY_HEART, logic->CanUse(RG_BOOMERANG)), LOCATION(RC_DEKU_TREE_MQ_LOBBY_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_LOBBY_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_LOBBY_GRASS_3, logic->CanCutShrubs()), @@ -304,15 +305,15 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_COMPASS_ROOM] = Region("Deku Tree MQ Compass Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_4, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEKU_TREE_MQ_EYE_TARGET_ROOM, []{return logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_HOVER_BOOTS);}), - Entrance(RR_DEKU_TREE_MQ_PAST_BOULDER_VINES, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))) || (logic->CanUse(RG_MEGATON_HAMMER) && (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->HasItem(RG_CLIMB)));});}), + Entrance(RR_DEKU_TREE_MQ_EYE_TARGET_ROOM, []{return true;}), + Entrance(RR_DEKU_TREE_MQ_PAST_BOULDER_VINES, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME))) && AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))) || (logic->CanUse(RG_MEGATON_HAMMER) && (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->HasItem(RG_CLIMB))));});}), }); areaTable[RR_DEKU_TREE_MQ_PAST_BOULDER_VINES] = Region("Deku Tree MQ Past Boulder Vines", SCENE_DEKU_TREE, {}, { 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 5e7230ae50c..43a25566d17 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp @@ -134,7 +134,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_STAIRS_UPPER] = Region("Dodongos Cavern Stairs Upper", SCENE_DODONGOS_CAVERN, {}, { //Locations LOCATION(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, logic->Get(LOGIC_DC_LIFT_PLATFORM) ? ED_BOOMERANG : ED_LONGSHOT)), - LOCATION(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, (logic->HasItem(RG_CLIMB) && (logic->IsAdult || logic->CanAttack())) || logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), + LOCATION(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, (logic->HasItem(RG_CLIMB) /*&& str0*/) || logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), LOCATION(RC_DODONGOS_CAVERN_STAIRCASE_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_STAIRCASE_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_STAIRCASE_POT_3, logic->CanBreakPots()), @@ -367,7 +367,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER] = Region("Dodongos Cavern MQ Stairs Upper", SCENE_DODONGOS_CAVERN, { //Events - EventAccess(LOGIC_DC_MQ_STAIRS_SILVER_RUPEES, []{return true;}), + EventAccess(LOGIC_DC_MQ_STAIRS_SILVER_RUPEES, []{return logic->HasItem(RG_CLIMB);}), }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp index 14e1cec6221..415c6f7cc0b 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -634,12 +634,7 @@ void RegionTable_Init_FireTemple() { Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, []{return true;}), }); - areaTable[RR_FIRE_TEMPLE_MQ_LAVA_GEYSER_1F] = Region("Fire Temple MQ Lava Geyser 1F", SCENE_FIRE_TEMPLE, {}, { - //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_LEFT_HEART, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), - LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_RIGHT_HEART, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), - LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_LOWER_HEART, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), - }, { + areaTable[RR_FIRE_TEMPLE_MQ_LAVA_GEYSER_1F] = Region("Fire Temple MQ Lava Geyser 1F", SCENE_FIRE_TEMPLE, {}, {}, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, []{return true;}), Entrance(RR_FIRE_TEMPLE_MQ_LAVA_GEYSER_GRATE, []{return logic->FireTimer() >= 40 && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}), @@ -662,6 +657,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LAVA_GEYSER_PILLARS] = Region("Fire Temple MQ Lava Geyser Pillars", SCENE_FIRE_TEMPLE, {}, { //Locations //rang can get the other 2 hearts from here but it's an awkward shot so a trick + //similarly rang from 1f can get this lower heart LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_LOWER_HEART, true), }, { //Exits @@ -682,8 +678,8 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_SHORTCUT_ROOM_LOWER] = Region("Fire Temple MQ Shortcut Room Lower", SCENE_FIRE_TEMPLE, {}, {}, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_SHORTCUT_ROOM_MID, []{return (logic->HasFireSource() && (logic->IsAdult || (logic->CanUse(RG_HOOKSHOT)/* && (CanUse(RG_CLIMB)*/))) || - (ctx->GetTrickOption(RT_FIRE_MQ_CLIMB) && logic->CanUse(RG_HOVER_BOOTS)/*&& CanUse(RG_CLIMB)*/);}), + Entrance(RR_FIRE_TEMPLE_MQ_SHORTCUT_ROOM_MID, []{return (logic->HasFireSource() && (logic->IsAdult || (logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_CLIMB)))) || + (ctx->GetTrickOption(RT_FIRE_MQ_CLIMB) && logic->CanUse(RG_HOVER_BOOTS) && logic->HasItem(RG_CLIMB));}), Entrance(RR_FIRE_TEMPLE_MQ_LAVA_GEYSER_2F, []{return true;}), Entrance(RR_FIRE_TEMPLE_MQ_SHORTCUT_CAGE, []{return logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);}), }); @@ -692,7 +688,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_SHORTCUT_ROOM_MID] = Region("Fire Temple MQ Shortcut Room Middle", SCENE_FIRE_TEMPLE, {}, {}, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_SHORTCUT_ROOM_LOWER, []{return true;}), - Entrance(RR_FIRE_TEMPLE_MQ_SHORTCUT_ROOM_3F, []{return true/*(logic->CanUse(RG_HOOKSHOT) || (CanUse(RG_CLIMB))*/;}), + Entrance(RR_FIRE_TEMPLE_MQ_SHORTCUT_ROOM_3F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), }); areaTable[RR_FIRE_TEMPLE_MQ_SHORTCUT_ROOM_3F] = Region("Fire Temple MQ Shortcut Room 3F", SCENE_FIRE_TEMPLE, {}, {}, { @@ -786,7 +782,7 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_MQ_SHORTCUT_CRATE_6, logic->CanBreakCrates()), }, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE, []{return true/*CanUse(RG_CLIMB)*/;}), + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE, []{return logic->HasItem(RG_CLIMB);}), Entrance(RR_FIRE_TEMPLE_MQ_SHORTCUT_CAGE, []{return logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);}), }); @@ -999,7 +995,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB] = Region("Fire Temple MQ Locked Climb", SCENE_FIRE_TEMPLE, {}, {}, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_3F_FLARE_DANCER, []{return true;}), - Entrance(RR_FIRE_TEMPLE_MQ_NARROW_STAIRS_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 4)/* && CanUse(RG_CLIMB)*/;}), + Entrance(RR_FIRE_TEMPLE_MQ_NARROW_STAIRS_ROOM, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 4) && logic->HasItem(RG_CLIMB);}), }); areaTable[RR_FIRE_TEMPLE_MQ_NARROW_STAIRS_ROOM] = Region("Fire Temple MQ Narrow Stairs Room", SCENE_FIRE_TEMPLE, { 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 db27df433ef..b24f093471c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -130,7 +130,7 @@ void RegionTable_Init_ForestTemple() { }, { //Exits Entrance(RR_FOREST_TEMPLE_LOBBY, []{return true;}), - Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_UPPER, []{return logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_VINES) && logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_UPPER, []{return logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_VINES) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_CLIMB));}), Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND, []{return logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_FOREST_TEMPLE_SEWER, []{return (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16;}), Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL);}), @@ -206,8 +206,8 @@ void RegionTable_Init_ForestTemple() { LOCATION(RC_FOREST_TEMPLE_WELL_EAST_HEART, true), }, { //Exits - Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_LOWER, []{return logic->HasItem(RG_CLIMB);}), - Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_LOWER, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, []{return logic->HasItem(RG_CLIMB);}), }); areaTable[RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST] = Region("Forest Temple Below Boss Key Chest", SCENE_FOREST_TEMPLE, {}, {}, { 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 b847c915c1e..fc21d627617 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -49,7 +49,7 @@ void RegionTable_Init_JabuJabusBelly() { LOCATION(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, logic->HookshotOrBoomerang()), }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_HOLES_ROOM, []{return true /* logic->HasItem(RG_CLIMB) */;}), + Entrance(RR_JABU_JABUS_BELLY_HOLES_ROOM, []{return logic->HasItem(RG_CLIMB);}), Entrance(RR_JABU_JABUS_BELLY_B1_JIGGLY, []{return true;}), Entrance(RR_JABU_JABUS_BELLY_HOLES_LOWER_DOOR_LEDGE, []{return logic->IsAdult;}), }); @@ -84,7 +84,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Exits //there's tricks for getting here with bunny-jumps or just side-hops - Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return (logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_CLIMB)) || logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_CLIMB);}), Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), Entrance(RR_JABU_JABUS_BELLY_HOLES_BASEMENT, []{return true;}), }); @@ -95,7 +95,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Exits Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_NORTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), - Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_CLIMB);}), Entrance(RR_JABU_JABUS_BELLY_LIFT_ROOM, []{return logic->CanUseProjectile();}), }); @@ -247,7 +247,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Exits Entrance(RR_JABU_JABUS_BELLY_LIFT_ROOM, []{return true;}), - Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, []{return (logic->HasItem(RG_CLIMB) && logic->CanUse(RG_BOOMERANG)) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_EXPLOSIVES) && (logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_BOMB_BAG))));}), + Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, []{return (logic->HasItem(RG_CLIMB) && logic->CanUse(RG_BOOMERANG)) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_EXPLOSIVES) && (logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_BOMB_BAG) && logic->HasItem(RG_CLIMB))));}), }); #pragma endregion @@ -336,7 +336,7 @@ void RegionTable_Init_JabuJabusBelly() { LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_3, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return true /* logic->HasItem(RG_CLIMB) */;}), + Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->HasItem(RG_CLIMB);}), Entrance(RR_JABU_JABUS_BELLY_MQ_TO_BIGOCTO, []{return logic->Get(LOGIC_JABU_WEST_TENTACLE);}), Entrance(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, []{return true;}), Entrance(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, []{return logic->Get(LOGIC_JABU_NORTH_TENTACLE);}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index 42cf932f0df..d0b884d4654 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -87,7 +87,7 @@ void RegionTable_Init_SpiritTemple() { // these assume SpiritRupeeBridge, silver rupee shuffle & shuffle climb will want to adjust LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->HasFireSourceWithTorch()), // possible to collect without lowering fence, should be a trick - LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)), + LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW) && logic->HasItem(RG_CLIMB)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_SOUTH, []{return logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE);}), @@ -454,9 +454,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BIG_WALL_BASE] = Region("Spirit Temple Big Wall Base", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits Entrance(RR_SPIRIT_TEMPLE_BEAMOS_PITS, []{return true;}), - Entrance(RR_SPIRIT_TEMPLE_BIG_WALL_UPPER, []{return (ctx->GetTrickOption(RT_SPIRIT_WALL) || - (logic->CanAvoidEnemy(RE_BEAMOS, true, 2) && logic->CanPassEnemy(RE_WALLTULA, ED_BOOMERANG))) - /*&& CanClimbHigh()*/;}), + Entrance(RR_SPIRIT_TEMPLE_BIG_WALL_UPPER, []{return (ctx->GetTrickOption(RT_SPIRIT_WALL) || (logic->CanAvoidEnemy(RE_BEAMOS, true, 2) && logic->CanPassEnemy(RE_WALLTULA, ED_BOOMERANG))) && + (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}), }); areaTable[RR_SPIRIT_TEMPLE_BIG_WALL_UPPER] = Region("Spirit Temple Big Wall Upper", SCENE_SPIRIT_TEMPLE, {}, { @@ -678,7 +677,7 @@ void RegionTable_Init_SpiritTemple() { //Exits //This covers adult and reverse access only, as child going forwards arrives here from the other side of this door Entrance(RR_SPIRIT_TEMPLE_MQ_1F_CHEST_SWITCH, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7);}), - Entrance(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return logic->CanHitSwitch()/* && CanClimbHigh()*/;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR] = Region("Spirit Temple MQ Sun on Floor Room", SCENE_SPIRIT_TEMPLE, {}, { @@ -904,7 +903,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_3_SUNS_ROOM_1F] = Region("Spirit Temple MQ 3 Suns Room 1F", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits //It is possible to clip through here with longshot by aiming high enough - Entrance(RR_SPIRIT_TEMPLE_MQ_3_SUNS_ROOM_2F, []{return logic->Get(LOGIC_SPIRIT_MQ_3SUNS_ENEMIES)/* && CanClimbHigh()*/;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_3_SUNS_ROOM_2F, []{return logic->Get(LOGIC_SPIRIT_MQ_3SUNS_ENEMIES) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}), Entrance(RR_SPIRIT_TEMPLE_MQ_BEHIND_GEYSER, []{return true;}), }); @@ -1037,13 +1036,13 @@ void RegionTable_Init_SpiritTemple() { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_BEAMOS_PITS, []{return true;}), //technically we only need to avoid them, but the sheer height and the moving walls makes getting to the top after only stunning them very difficult/impossible - Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER, []{return /*(*/logic->CanKillEnemy(RE_KEESE)/*|| CanUse(RG_SKULL_MASK)) && CanClimbHigh()*/;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER, []{return (logic->CanKillEnemy(RE_KEESE)/*|| CanUse(RG_SKULL_MASK)*/) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER] = Region("Spirit Temple MQ Big Wall Upper", SCENE_SPIRIT_TEMPLE, { //Events //Getting some of these with just climbing downwards is theoretically possible but definitely a trick - EventAccess(LOGIC_SPIRIT_MQ_BIG_WALL_SILVERS, []{return /*(*/logic->CanKillEnemy(RE_KEESE)/*|| CanUse(RG_SKULL_MASK)) && CanClimbHigh()*/;}), + EventAccess(LOGIC_SPIRIT_MQ_BIG_WALL_SILVERS, []{return (logic->CanKillEnemy(RE_KEESE)/*|| CanUse(RG_SKULL_MASK)*/) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}), }, {}, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_BASE, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp index ef562e65045..05688b830f2 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp @@ -22,11 +22,11 @@ void RegionTable_Init_CastleGrounds() { }, { //Locations LOCATION(RC_HC_MALON_EGG, true), - LOCATION(RC_HC_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)), + LOCATION(RC_HC_GS_TREE, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)), }, { //Exits Entrance(RR_CASTLE_GROUNDS, []{return true;}), - Entrance(RR_HYRULE_CASTLE_GROUNDS, []{return logic->HasItem(RG_ZELDAS_LETTER) || logic->HasItem(RG_CLIMB);}), + Entrance(RR_HYRULE_CASTLE_GROUNDS, []{return logic->HasItem(RG_CLIMB);}), // TODO: bribing guard can be logical once permanent }); areaTable[RR_HYRULE_CASTLE_GROUNDS] = Region("Hyrule Castle Grounds", SCENE_HYRULE_CASTLE, { 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 8544f4e47d0..159807c4831 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 @@ -70,7 +70,7 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_SHEIK_IN_CRATER, logic->IsAdult && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), }, { //Exits - Entrance(RR_DMC_CENTRAL_LOCAL, []{return logic->FireTimer() >= 48;}), + Entrance(RR_DMC_CENTRAL_LOCAL, []{return logic->FireTimer() >= 48;}), }); areaTable[RR_DMC_CENTRAL_LOCAL] = Region("DMC Central Local", SCENE_DEATH_MOUNTAIN_CRATER, { @@ -92,11 +92,11 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), }, { //Exits - Entrance(RR_DMC_CENTRAL_NEARBY, []{return true;}), - Entrance(RR_DMC_LOWER_NEARBY, []{return (logic->IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), - Entrance(RR_DMC_UPPER_NEARBY, []{return logic->IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL);}), - Entrance(RR_FIRE_TEMPLE_ENTRYWAY, []{return (logic->IsChild && logic->Hearts() >= 3 && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)) || (logic->IsAdult && logic->FireTimer() >= 24);}), - Entrance(RR_DMC_DISTANT_PLATFORM, []{return logic->FireTimer() >= 48 && logic->IsAdult && logic->ReachDistantScarecrow();}), + Entrance(RR_DMC_CENTRAL_NEARBY, []{return true;}), + Entrance(RR_DMC_LOWER_NEARBY, []{return (logic->IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || (logic->CanUse(RG_HOVER_BOOTS) && (logic->IsAdult || logic->HasItem(RG_CLIMB))) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_DMC_UPPER_NEARBY, []{return logic->IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL);}), + Entrance(RR_DMC_OUTSIDE_FIRE_TEMPLE, []{return (logic->IsChild && logic->Hearts() >= 3 && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)) || (logic->IsAdult && logic->FireTimer() >= 24);}), + Entrance(RR_DMC_DISTANT_PLATFORM, []{return logic->FireTimer() >= 48 && logic->IsAdult && logic->ReachDistantScarecrow();}), }); areaTable[RR_DMC_GREAT_FAIRY_FOUNTAIN] = Region("DMC Great Fairy Fountain", SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp index f8d282553ed..3906288ad77 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp @@ -13,7 +13,7 @@ void RegionTable_Init_DeathMountainTrail() { LOCATION(RC_DMT_CHEST, logic->BlastOrSmash() || (ctx->GetTrickOption(RT_DMT_BOMBABLE) && logic->IsChild && logic->HasItem(RG_GORONS_BRACELET))), LOCATION(RC_DMT_FREESTANDING_POH, logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET)))), LOCATION(RC_DMT_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_DMT_SOIL_GS) && (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_BOOMERANG)))), - LOCATION(RC_DMT_GS_NEAR_KAK, logic->BlastOrSmash()), + LOCATION(RC_DMT_GS_NEAR_KAK, logic->BlastOrSmash() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, logic->IsAdult && logic->CanGetNightTimeGS() && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION) && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL)) || (ctx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && logic->CanUse(RG_HOVER_BOOTS)) || (ctx->GetTrickOption(RT_DMT_JS_LOWER_GS) && logic->CanJumpslash()) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)))), LOCATION(RC_DMT_BLUE_RUPEE, logic->IsChild && logic->BlastOrSmash()), LOCATION(RC_DMT_RED_RUPEE, logic->IsChild && logic->BlastOrSmash()), @@ -25,12 +25,12 @@ void RegionTable_Init_DeathMountainTrail() { //Exits Entrance(RR_KAK_BEHIND_GATE, []{return true;}), Entrance(RR_GORON_CITY, []{return true;}), - Entrance(RR_DEATH_MOUNTAIN_AVALANCHE, []{return AnyAgeTime([]{return logic->BlastOrSmash();}) || (logic->IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->HasItem(RG_GORONS_BRACELET)) || (logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_DMT_CLIMB_HOVERS))));}), + Entrance(RR_DEATH_MOUNTAIN_ROCKFALL, []{return AnyAgeTime([]{return logic->BlastOrSmash();}) || (logic->IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->HasItem(RG_GORONS_BRACELET)) || (logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_DMT_CLIMB_HOVERS))));}), Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, []{return logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET) || logic->IsAdult;}), Entrance(RR_DMT_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), }); - areaTable[RR_DEATH_MOUNTAIN_AVALANCHE] = Region("Death Mountain Avalanche", SCENE_DEATH_MOUNTAIN_TRAIL, {}, { + areaTable[RR_DEATH_MOUNTAIN_ROCKFALL] = Region("Death Mountain Avalanche", SCENE_DEATH_MOUNTAIN_TRAIL, {}, { //Locations LOCATION(RC_DMT_GS_FALLING_ROCKS_PATH, logic->IsAdult && logic->CanGetNightTimeGS() && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DMT_UPPER_GS) && (logic->CanJumpslash() || logic->HasExplosives() || ((ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) || ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))))) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)))), }, { @@ -54,7 +54,7 @@ void RegionTable_Init_DeathMountainTrail() { LOCATION(RC_DMT_GOSSIP_STONE, true), }, { //Exits - Entrance(RR_DEATH_MOUNTAIN_AVALANCHE, []{return true;}), + Entrance(RR_DEATH_MOUNTAIN_ROCKFALL, []{return true;}), Entrance(RR_DMC_UPPER_LOCAL, []{return true;}), Entrance(RR_DMT_OWL_FLIGHT, []{return logic->IsChild;}, false), Entrance(RR_DMT_GREAT_FAIRY_FOUNTAIN, []{return AnyAgeTime([]{return logic->BlastOrSmash();});}), @@ -85,7 +85,7 @@ void RegionTable_Init_DeathMountainTrail() { LOCATION(RC_DMT_COW_GROTTO_GRASS_2, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEATH_MOUNTAIN_AVALANCHE, []{return true;}), + Entrance(RR_DEATH_MOUNTAIN_ROCKFALL, []{return true;}), }); areaTable[RR_DMT_STORMS_GROTTO] = Region("DMT Storms Grotto", SCENE_GROTTOS, grottoEvents, { 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 adb8a9b03d1..5b6f1bcc930 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp @@ -9,7 +9,7 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_OUTSKIRTS] = Region("Gerudo Fortress Outskirts", SCENE_GERUDOS_FORTRESS, { //Events - EventAccess(LOGIC_GF_GATE_OPEN, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CLIMB);}), + EventAccess(LOGIC_GF_GATE_OPEN, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CLIMB);}), // longshot can get up without climb, but jank is hard }, { //Locations LOCATION(RC_GF_OUTSKIRTS_NE_CRATE, (logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)) && logic->CanBreakCrates()), @@ -141,7 +141,7 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_TOP_OF_UPPER_VINES] = Region("GF Top of Upper Vines", SCENE_GERUDOS_FORTRESS, {}, { //Locations //if RR_GF_SLOPED_ROOF > RR_GF_TOP_OF_UPPER_VINES is ever made part of RT_UNINTUITIVE_JUMPS, climb is needed to get back up - LOCATION(RC_GF_GS_TOP_FLOOR, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH) && logic->CanGetNightTimeGS()), + LOCATION(RC_GF_GS_TOP_FLOOR, logic->IsAdult && logic->CanGetNightTimeGS() && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), }, { //Exits Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true;}), 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 6219e4f6f43..a897764ba3c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -20,8 +20,6 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_KOKIRI_FOREST_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_KF_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_KOKIRI_FOREST_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_KF_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_KOKIRI_FOREST_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_KF_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), - LOCATION(RC_KF_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_KF_BRIDGE_RUPEE, logic->IsChild), LOCATION(RC_KF_BEHIND_MIDOS_RUPEE, logic->IsChild), LOCATION(RC_KF_SOUTH_GRASS_WEST_RUPEE, logic->IsChild), @@ -30,17 +28,9 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_NORTH_GRASS_EAST_RUPEE, logic->IsChild), LOCATION(RC_KF_BOULDER_RUPEE_1, logic->IsChild), LOCATION(RC_KF_BOULDER_RUPEE_2, logic->IsChild), - LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_3, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_4, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_5, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_6, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RED_RUPEE, logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_KF_SARIAS_ROOF_WEST_HEART, logic->IsChild), LOCATION(RC_KF_SARIAS_ROOF_EAST_HEART, logic->IsChild), LOCATION(RC_KF_SARIAS_ROOF_NORTH_HEART, logic->IsChild), - LOCATION(RC_KF_GOSSIP_STONE, true), LOCATION(RC_KF_CHILD_GRASS_1, logic->IsChild && logic->CanCutShrubs()), LOCATION(RC_KF_CHILD_GRASS_2, logic->IsChild && logic->CanCutShrubs()), LOCATION(RC_KF_CHILD_GRASS_3, logic->IsChild && logic->CanCutShrubs()), @@ -78,16 +68,16 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_ADULT_GRASS_20, logic->IsAdult && logic->CanCutShrubs()), }, { //Exits - Entrance(RR_KF_LINKS_PORCH, []{return logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_KF_LINKS_PORCH, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_KF_MIDOS_HOUSE, []{return true;}), Entrance(RR_KF_SARIAS_HOUSE, []{return true;}), Entrance(RR_KF_HOUSE_OF_TWINS, []{return true;}), Entrance(RR_KF_KNOW_IT_ALL_HOUSE, []{return true;}), Entrance(RR_KF_KOKIRI_SHOP, []{return true;}), Entrance(RR_KF_OUTSIDE_DEKU_TREE, []{return (logic->IsAdult && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->Get(LOGIC_FOREST_TEMPLE_CLEAR))) || ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_OFF) || logic->Get(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD);}), - Entrance(RR_KF_OUTSIDE_LOST_WOODS, []{return logic->HasItem(RG_CLIMB) || (logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)));}), + Entrance(RR_KF_OUTSIDE_LOST_WOODS, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)));}), + Entrance(RR_KF_RUPEE_ALCOVE, []{return logic->IsAdult && CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL);}), Entrance(RR_LW_BRIDGE_FROM_FOREST, []{return logic->IsAdult || ctx->GetOption(RSK_FOREST).IsNot(RO_CLOSED_FOREST_ON) || logic->Get(LOGIC_DEKU_TREE_CLEAR);}), - Entrance(RR_KF_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), }); areaTable[RR_KF_OUTSIDE_DEKU_TREE] = Region("KF Outside Deku Tree", SCENE_KOKIRI_FOREST, { @@ -179,12 +169,39 @@ void RegionTable_Init_KokiriForest() { Entrance(RR_KOKIRI_FOREST, []{return true;}), }); - areaTable[RR_KF_OUTSIDE_LOST_WOODS] = Region("KF Outside Lost Woods", SCENE_KOKIRI_FOREST, {}, {}, { + areaTable[RR_KF_OUTSIDE_LOST_WOODS] = Region("KF Outside Lost Woods", SCENE_KOKIRI_FOREST, {}, { + //Locations + LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_KF_BEAN_RUPEE_3, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_KF_BEAN_RUPEE_4, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_KF_BEAN_RUPEE_5, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_KF_BEAN_RUPEE_6, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_KF_BEAN_RED_RUPEE, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_KF_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), + LOCATION(RC_KF_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_KF_GOSSIP_STONE, true), + }, { + //Exits Entrance(RR_KOKIRI_FOREST, []{return true;}), Entrance(RR_THE_LOST_WOODS, []{return true;}), + Entrance(RR_KF_RUPEE_ALCOVE, []{return logic->IsAdult && (CanPlantBean(RR_KOKIRI_FOREST, RG_KOKIRI_FOREST_BEAN_SOUL) || logic->CanUse(RG_HOVER_BOOTS));}), Entrance(RR_KF_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), }); + areaTable[RR_KF_RUPEE_ALCOVE] = Region("KF Alcove", SCENE_KOKIRI_FOREST, {}, { + //Locations + LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_KF_BEAN_RUPEE_3, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_KF_BEAN_RUPEE_4, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_KF_BEAN_RUPEE_5, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_KF_BEAN_RUPEE_6, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_KF_BEAN_RED_RUPEE, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), + }, { + Entrance(RR_KOKIRI_FOREST, []{return true;}), + }); + areaTable[RR_KF_STORMS_GROTTO] = Region("KF Storms Grotto", SCENE_GROTTOS, grottoEvents, { //Locations LOCATION(RC_KF_STORMS_GROTTO_CHEST, true), 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 30aac60bc5f..0297fb3e4e5 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 @@ -45,6 +45,7 @@ void RegionTable_Init_SacredForestMeadow() { //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, []{return logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_SFM_ENTRYWAY, []{return 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, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump());}), Entrance(RR_SFM_STORMS_GROTTO, []{return 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 9972c11bade..21154375677 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp @@ -107,19 +107,6 @@ void RegionTable_Init_ZoraRiver() { Entrance(RR_ZORAS_DOMAIN, []{return true;}), }); - areaTable[RR_ZR_UPPER_GROTTOS] = Region("ZR Upper Grottos", SCENE_ZORAS_RIVER, {}, { - //Locations - LOCATION(RC_ZR_GS_NEAR_RAISED_GROTTOS, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), - LOCATION(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), - LOCATION(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, true), - }, { - //Exits - Entrance(RR_ZORAS_RIVER, []{return true;}), - Entrance(RR_ZR_OPEN_GROTTO, []{return true;}), - Entrance(RR_ZR_FAIRY_GROTTO, []{return AnyAgeTime([]{return logic->BlastOrSmash();});}), - }); - areaTable[RR_ZR_OPEN_GROTTO] = Region("ZR Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations LOCATION(RC_ZR_OPEN_GROTTO_CHEST, true), diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index e2e1a8189e7..e326e14471b 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -539,6 +539,7 @@ typedef enum { RR_KF_KOKIRI_SHOP, RR_KF_OUTSIDE_DEKU_TREE, RR_KF_OUTSIDE_LOST_WOODS, + RR_KF_RUPEE_ALCOVE, RR_KF_STORMS_GROTTO, RR_THE_LOST_WOODS, RR_LW_BRIDGE_FROM_FOREST, @@ -681,7 +682,7 @@ typedef enum { RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_GRAVEYARD_WARP_PAD_REGION, RR_DEATH_MOUNTAIN_TRAIL, - RR_DEATH_MOUNTAIN_AVALANCHE, + RR_DEATH_MOUNTAIN_ROCKFALL, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_OWL_FLIGHT, RR_DMT_GREAT_FAIRY_FOUNTAIN, @@ -712,7 +713,6 @@ typedef enum { RR_ZR_PILLAR, RR_ZR_FROM_SHORTCUT, RR_ZR_BEHIND_WATERFALL, - RR_ZR_UPPER_GROTTOS, RR_ZR_OPEN_GROTTO, RR_ZR_FAIRY_GROTTO, RR_ZR_STORMS_GROTTO, @@ -4263,7 +4263,6 @@ typedef enum { RT_SHADOW_UMBRELLA_CLIP, RT_SHADOW_UMBRELLA_GS, RT_SHADOW_FREESTANDING_KEY, - RT_SHADOW_BOAT_JUMP, RT_SHADOW_STATUE, RT_SHADOW_BONGO, RT_LENS_SHADOW_MQ, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 9bbfe43ee09..94d67e985c7 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1982,9 +1982,6 @@ void Settings::CreateOptions() { OPT_TRICK(RT_SHADOW_FREESTANDING_KEY, RCQUEST_VANILLA, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "Shadow Temple Freestanding Key with Bombchu", "Release the Bombchu with good timing so that it explodes near the bottom of the pot."); - OPT_TRICK(RT_SHADOW_BOAT_JUMP, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, - "Shadow Temple Boat Jump", - "Boat can be boarded by jumping on wheel, skipping block and ladder."); OPT_TRICK(RT_SHADOW_STATUE, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "Shadow Temple River Statue with Bombchu", "By sending a Bombchu around the edge of the gorge, you can knock down the statue without needing a Bow. " From 4bab551256b621652cd9af9646803bf1b4c7898e Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Sun, 11 Jan 2026 05:50:28 +0000 Subject: [PATCH 09/18] update logic deku tree falling platform & castle guard bribe also generally refactor castle grounds --- soh/soh/Enhancements/randomizer/entrance.cpp | 4 +- .../location_access/dungeons/deku_tree.cpp | 12 +-- .../overworld/castle_grounds.cpp | 85 +++++++++++++------ .../Enhancements/randomizer/randomizerTypes.h | 5 +- 4 files changed, 69 insertions(+), 37 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 1347b33c38b..9615578d2d8 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -340,8 +340,8 @@ void SetAllEntrancesData() { { EntranceType::Interior, RR_KAK_SHOOTING_GALLERY, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY } }, { { EntranceType::Interior, RR_DESERT_COLOSSUS, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS }, { EntranceType::Interior, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT } }, - { { EntranceType::Interior, RR_HYRULE_CASTLE_GROUNDS, RR_HC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC }, - { EntranceType::Interior, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT } }, + { { EntranceType::Interior, RR_HC_PAST_GATE, RR_HC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC }, + { EntranceType::Interior, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_HC_PAST_GATE, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT } }, { { EntranceType::Interior, RR_GANONS_CASTLE_GROUNDS, RR_OGC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD }, // 0x3E8 is an unused entrance index repurposed to differentiate between the HC and OGC fairy // fountain exits (normally they both use 0x340) 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 369e47f7825..4271578fc18 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -46,7 +46,7 @@ void RegionTable_Init_DekuTree() { }, { //Exits Entrance(RR_DEKU_TREE_LOBBY, []{return true;}), - Entrance(RR_DEKU_TREE_LOBBY_3F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_DEKU_TREE_LOBBY_3F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), // precise hookshot atop chest can make it as adult Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return true;}), }); @@ -68,7 +68,7 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_SLINGSHOT_ROOM] = Region("Deku Tree Slingshot Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, true), LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_2, logic->CanCutShrubs()), @@ -76,7 +76,7 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_4, logic->CanCutShrubs()), }, { //Exits - Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return true;}), }); areaTable[RR_DEKU_TREE_COMPASS_ROOM] = Region("Deku Tree Compass Room", SCENE_DEKU_TREE, { @@ -249,7 +249,7 @@ void RegionTable_Init_DekuTree() { //Exits Entrance(RR_DEKU_TREE_MQ_1F, []{return true;}), //Will need canAvoid logic with enemy shuffle - Entrance(RR_DEKU_TREE_MQ_3F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_DEKU_TREE_MQ_3F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), // precise hookshot atop chest can make it as adult Entrance(RR_DEKU_TREE_MQ_EYE_TARGET_ROOM, []{return logic->Get(LOGIC_DEKU_TREE_MQ_2F_BURNED_WEB);}), }); @@ -305,7 +305,7 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_COMPASS_ROOM] = Region("Deku Tree MQ Compass Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, true), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()), @@ -313,7 +313,7 @@ void RegionTable_Init_DekuTree() { }, { //Exits Entrance(RR_DEKU_TREE_MQ_EYE_TARGET_ROOM, []{return true;}), - Entrance(RR_DEKU_TREE_MQ_PAST_BOULDER_VINES, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME))) && AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))) || (logic->CanUse(RG_MEGATON_HAMMER) && (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->HasItem(RG_CLIMB))));});}), + Entrance(RR_DEKU_TREE_MQ_PAST_BOULDER_VINES, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME))) && AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))) || (logic->CanUse(RG_MEGATON_HAMMER) && ((logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME)) || (ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->HasItem(RG_CLIMB))));});}), }); areaTable[RR_DEKU_TREE_MQ_PAST_BOULDER_VINES] = Region("Deku Tree MQ Past Boulder Vines", SCENE_DEKU_TREE, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp index 05688b830f2..ea6bfe0d225 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp @@ -21,51 +21,80 @@ void RegionTable_Init_CastleGrounds() { EventAccess(LOGIC_BUG_ACCESS, []{return true /*str0*/;}), }, { //Locations - LOCATION(RC_HC_MALON_EGG, true), - LOCATION(RC_HC_GS_TREE, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)), + LOCATION(RC_HC_MALON_EGG, true), + LOCATION(RC_HC_GS_TREE, logic->CanBonkTrees() && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)), + LOCATION(RC_HC_SKULLTULA_TREE, logic->CanBonkTrees()), }, { //Exits - Entrance(RR_CASTLE_GROUNDS, []{return true;}), - Entrance(RR_HYRULE_CASTLE_GROUNDS, []{return logic->HasItem(RG_CLIMB);}), // TODO: bribing guard can be logical once permanent + Entrance(RR_CASTLE_GROUNDS, []{return true;}), + Entrance(RR_HC_ABOVE_VINE, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_HC_PAST_GATE, []{return logic->HasItem(RG_CHILD_WALLET);}), }); - areaTable[RR_HYRULE_CASTLE_GROUNDS] = Region("Hyrule Castle Grounds", SCENE_HYRULE_CASTLE, { + areaTable[RR_HC_ABOVE_VINE] = Region("Hyrule Castle Above Vine", SCENE_HYRULE_CASTLE, { //Events - EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy() || logic->CanUse(RG_STICKS);}), + EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy();}), }, { //Locations LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), - // jumping past guard would be a trick - LOCATION(RC_HC_MALON_GOSSIP_STONE, logic->HasItem(RG_CLIMB)), + LOCATION(RC_HC_MALON_GOSSIP_STONE, true), }, { //Exits - Entrance(RR_HC_MOAT, []{return logic->HasItem(RG_CLIMB);}), - Entrance(RR_HC_GREAT_FAIRY_FOUNTAIN, []{return logic->BlastOrSmash();}), + Entrance(RR_HC_GATE, []{return true;}), + Entrance(RR_HC_PAST_GATE, []{return true;}), }); - areaTable[RR_HC_MOAT] = Region("Hyrule Castle Grounds", SCENE_HYRULE_CASTLE, {}, { + areaTable[RR_HC_PAST_GATE] = Region("Hyrule Castle Past Gate", SCENE_HYRULE_CASTLE, { + //Events + EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanUse(RG_STICKS);}), + }, { + //Locations + LOCATION(RC_HC_NEAR_GUARDS_TREE_1, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_2, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_3, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_4, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_5, logic->CanBonkTrees()), + LOCATION(RC_HC_NEAR_GUARDS_TREE_6, logic->CanBonkTrees()), + LOCATION(RC_HC_NL_TREE_1, false), + LOCATION(RC_HC_NL_TREE_2, false), + }, { + //Exits + Entrance(RR_HC_GATE, []{return true;}), + Entrance(RR_HC_ABOVE_VINE, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_HC_ABOVE_CLIMBABLE_ROCKS, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + }); + + areaTable[RR_HC_ABOVE_CLIMBABLE_ROCKS] = Region("Hyrule Castle Above Climbable Rocks", SCENE_HYRULE_CASTLE, { + //Events + EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy();}), + }, { //Locations LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE, true), LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_HC_GRASS_1, logic->CanCutShrubs()), - LOCATION(RC_HC_GRASS_2, logic->CanCutShrubs()), - LOCATION(RC_HC_GROTTO_TREE, logic->CanBonkTrees()), - LOCATION(RC_HC_NL_TREE_1, false), - LOCATION(RC_HC_NL_TREE_2, false), - LOCATION(RC_HC_SKULLTULA_TREE, logic->CanBonkTrees()), - LOCATION(RC_HC_NEAR_GUARDS_TREE_1, logic->CanBonkTrees()), - LOCATION(RC_HC_NEAR_GUARDS_TREE_2, logic->CanBonkTrees()), - LOCATION(RC_HC_NEAR_GUARDS_TREE_3, logic->CanBonkTrees()), - LOCATION(RC_HC_NEAR_GUARDS_TREE_4, logic->CanBonkTrees()), - LOCATION(RC_HC_NEAR_GUARDS_TREE_5, logic->CanBonkTrees()), - LOCATION(RC_HC_NEAR_GUARDS_TREE_6, logic->CanBonkTrees()), + }, { + //Exits + Entrance(RR_HC_PAST_GATE, []{return true;}), + Entrance(RR_HC_MOAT, []{return true;}), + }); + + areaTable[RR_HC_MOAT] = Region("Hyrule Castle Grounds", SCENE_HYRULE_CASTLE, {}, { + //Locations + LOCATION(RC_HC_GRASS_1, logic->CanCutShrubs()), + LOCATION(RC_HC_GRASS_2, logic->CanCutShrubs()), + LOCATION(RC_HC_GROTTO_TREE, logic->CanBonkTrees()), }, { //Exits Entrance(RR_HC_GATE, []{return true;}), Entrance(RR_HC_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), - Entrance(RR_HC_GARDEN, []{return logic->CanUse(RG_WEIRD_EGG) || !ctx->GetOption(RSK_SHUFFLE_WEIRD_EGG) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}), + Entrance(RR_HC_GARDEN, []{return logic->CanUse(RG_WEIRD_EGG) || !ctx->GetOption(RSK_SHUFFLE_WEIRD_EGG) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->TakeDamage() && logic->HasExplosives() && logic->CanJumpslash());}), + }); + + areaTable[RR_HC_DRAIN_LEDGE] = Region("Hyrule Castle Drain Ledge", SCENE_HYRULE_CASTLE, {}, {}, { + //Exits + Entrance(RR_HC_MOAT, []{return true;}), + Entrance(RR_HC_GARDEN, []{return true /*CanCrawl*/;}), }); areaTable[RR_HC_GARDEN] = Region("HC Garden", SCENE_CASTLE_COURTYARD_ZELDA, {}, { @@ -74,7 +103,7 @@ void RegionTable_Init_CastleGrounds() { LOCATION(RC_SONG_FROM_IMPA, true), }, { //Exits - Entrance(RR_HYRULE_CASTLE_GROUNDS, []{return true;}), + Entrance(RR_HC_DRAIN_LEDGE, []{return true;}), }); areaTable[RR_HC_GREAT_FAIRY_FOUNTAIN] = Region("HC Great Fairy Fountain", SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, {}, { @@ -82,7 +111,7 @@ void RegionTable_Init_CastleGrounds() { LOCATION(RC_HC_GREAT_FAIRY_REWARD, logic->CanUse(RG_ZELDAS_LULLABY)), }, { //Exits - Entrance(RR_CASTLE_GROUNDS, []{return true;}), + Entrance(RR_HC_PAST_GATE, []{return true;}), }); areaTable[RR_HC_STORMS_GROTTO] = Region("HC Storms Grotto", SCENE_GROTTOS, {}, { @@ -137,8 +166,8 @@ void RegionTable_Init_CastleGrounds() { areaTable[RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE] = Region("Castle Grounds From Ganon's Castle", SCENE_OUTSIDE_GANONS_CASTLE, {}, {}, { // Exits - Entrance(RR_HYRULE_CASTLE_GROUNDS, []{return logic->IsChild;}), - Entrance(RR_GANONS_CASTLE_LEDGE, []{return logic->IsAdult;}), + Entrance(RR_HC_DRAIN_LEDGE, []{return logic->IsChild;}), + Entrance(RR_GANONS_CASTLE_LEDGE, []{return logic->IsAdult;}), }); areaTable[RR_GANONS_CASTLE_LEDGE] = Region("Ganon's Castle Ledge", SCENE_OUTSIDE_GANONS_CASTLE, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index e326e14471b..4bdce1c457f 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -643,7 +643,10 @@ typedef enum { RR_CASTLE_GROUNDS, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, RR_HC_GATE, - RR_HYRULE_CASTLE_GROUNDS, + RR_HC_ABOVE_VINE, + RR_HC_PAST_GATE, + RR_HC_ABOVE_CLIMBABLE_ROCKS, + RR_HC_DRAIN_LEDGE, RR_HC_GARDEN, RR_HC_MOAT, RR_HC_GREAT_FAIRY_FOUNTAIN, From cce8a63ae3d774fd81b89c2a934d337264a7703f Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Mon, 12 Jan 2026 05:21:44 +0000 Subject: [PATCH 10/18] vanilla deku tree 1f web event --- .../location_access/dungeons/deku_tree.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) 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 4271578fc18..9aff751ff98 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -18,13 +18,13 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_LOBBY] = Region("Deku Tree Lobby", SCENE_DEKU_TREE, { //Events - EventAccess(LOGIC_STICK_ACCESS, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_STICK_ACCESS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_DEKU_TREE_1F_BROKE_WEB, []{return logic->HasFireSource();}), }, { //Locations LOCATION(RC_DEKU_TREE_MAP_CHEST, true), LOCATION(RC_DEKU_TREE_LOBBY_LOWER_HEART, logic->CanUse(RG_BOOMERANG)), - LOCATION(RC_DEKU_TREE_LOBBY_UPPER_HEART, logic->CanPassEnemy(RE_BIG_SKULLTULA)), LOCATION(RC_DEKU_TREE_LOBBY_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_LOBBY_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_LOBBY_GRASS_3, logic->CanCutShrubs()), @@ -34,7 +34,7 @@ void RegionTable_Init_DekuTree() { //Exits Entrance(RR_DEKU_TREE_ENTRYWAY, []{return true;}), Entrance(RR_DEKU_TREE_LOBBY_2F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), - Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return AnyAgeTime([]{return logic->HasFireSource();});}), + Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return logic->Get(LOGIC_DEKU_TREE_1F_BROKE_WEB);}), Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return false;}), Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, []{return false;}), }); @@ -45,19 +45,21 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_LOBBY_LOWER_HEART, true), }, { //Exits - Entrance(RR_DEKU_TREE_LOBBY, []{return true;}), - Entrance(RR_DEKU_TREE_LOBBY_3F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), // precise hookshot atop chest can make it as adult - Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return true;}), + Entrance(RR_DEKU_TREE_LOBBY, []{return true;}), + Entrance(RR_DEKU_TREE_LOBBY_3F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), // precise hookshot atop chest can make it as adult + Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return true;}), }); - areaTable[RR_DEKU_TREE_LOBBY_3F] = Region("Deku Tree Lobby 3F", SCENE_DEKU_TREE, {}, { + areaTable[RR_DEKU_TREE_LOBBY_3F] = Region("Deku Tree Lobby 3F", SCENE_DEKU_TREE, { + //Events + EventAccess(LOGIC_DEKU_TREE_1F_BROKE_WEB, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), + }, { //Locations LOCATION(RC_DEKU_TREE_LOBBY_UPPER_HEART, logic->CanPassEnemy(RE_BIG_SKULLTULA)), }, { //Exits - Entrance(RR_DEKU_TREE_LOBBY_2F, []{return true;}), - Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return AnyAgeTime([]{return logic->CanPassEnemy(RE_BIG_SKULLTULA);});}), - Entrance(RR_DEKU_TREE_COMPASS_ROOM, []{return true;}), + Entrance(RR_DEKU_TREE_LOBBY_2F, []{return true;}), + Entrance(RR_DEKU_TREE_COMPASS_ROOM, []{return true;}), }); areaTable[RR_DEKU_TREE_2F_MIDDLE_ROOM] = Region("Deku Tree 2F Middle Room", SCENE_DEKU_TREE, {}, {}, { @@ -227,9 +229,7 @@ void RegionTable_Init_DekuTree() { Entrance(RR_DEKU_TREE_ENTRYWAY, []{return true;}), //may need canAvoid logic with enemy shuffle Entrance(RR_DEKU_TREE_MQ_2F, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), - //Swim is not required because you can jump with enough momentum to hit land. - //You even avoid fall damage if you hit the shallow water, though it's obscure knowledge so may be a trick - //if it is, then we need a landing room with (IsAdult || HasItem(RG_BRONZE_SCALE) || TakeDamage() || that trick) to reach basement + //Swim is not required because you can jump with enough momentum to hit land. You even avoid fall damage if you hit the shallow water. Entrance(RR_DEKU_TREE_MQ_BASEMENT, []{return logic->Get(LOGIC_DEKU_TREE_1F_BROKE_WEB);}), //is it possible to recoil from here to the ledge with a trick? }); From a147a44ddafe07783c78eb04e4586a6052948621 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Mon, 12 Jan 2026 06:01:37 +0000 Subject: [PATCH 11/18] jabu fixes --- .../location_access/dungeons/jabujabus_belly.cpp | 8 +++++--- soh/soh/Enhancements/randomizer/settings.cpp | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) 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 fc21d627617..6d7aeb15c43 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -247,7 +247,9 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Exits Entrance(RR_JABU_JABUS_BELLY_LIFT_ROOM, []{return true;}), - Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, []{return (logic->HasItem(RG_CLIMB) && logic->CanUse(RG_BOOMERANG)) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_EXPLOSIVES) && (logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_BOMB_BAG) && logic->HasItem(RG_CLIMB))));}), + Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, []{return (logic->HasItem(RG_CLIMB) && logic->CanUse(RG_BOOMERANG)) || + (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && (logic->CanUse(logic->HasItem(RG_CLIMB) ? RG_HOOKSHOT : RG_LONGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))) || + (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_EXPLOSIVES) && (logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_BOMB_BAG) && logic->HasItem(RG_CLIMB))));}), }); #pragma endregion @@ -460,7 +462,7 @@ void RegionTable_Init_JabuJabusBelly() { && ((logic->IsChild && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS)))))), }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return (logic->Get(LOGIC_JABU_NORTH_TENTACLE) || logic->TakeDamage()) && logic->HasItem(RG_BRONZE_SCALE);}), + Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_BASEMENT, []{return (logic->Get(LOGIC_JABU_NORTH_TENTACLE) || logic->TakeDamage()) && logic->HasItem(RG_BRONZE_SCALE);}), }); // unlike other entrances behind tentacles, Link spawns behind the tentacle. Running into it throws him into main room still @@ -531,7 +533,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), - LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, logic->HasItem(RG_CLIMB) && (logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT)))), + LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, (logic->HasItem(RG_CLIMB) && (logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT)))) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_LONGSHOT))), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_GRASS_2, logic->CanCutShrubs()), diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 94d67e985c7..cbf391a3429 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1701,8 +1701,8 @@ void Settings::CreateOptions() { "room using a precisely-aimed use of the Slingshot, Bow, or Longshot. As well, if you climb to the top of the " "vines you can stand on the right edge of the platform and shoot around the glass. From this distance, even " "the Hookshot can reach the switch. This trick is only relevant if \"Shuffle Boss Entrances\" is enabled. MQ " - "Jabu: A Gold Skulltula Token can be collected with the Hookshot or Longshot using the same methods as hitting " - "the switch in Vanilla. This MQ trick is not currently relevant in logic."); + "Jabu: A Gold Skulltula Token can be collected with Longshot using the same methods as hitting the switch in " + "Vanilla."); OPT_TRICK(RT_JABU_NEAR_BOSS_EXPLOSIVES, RCQUEST_VANILLA, RA_JABU_JABUS_BELLY, { Tricks::Tag::INTERMEDIATE }, "Jabu Near Boss Ceiling Switch with Explosives", "You can hit the switch that opens the door to the boss room using a precisely-aimed Bombchu. Also, " From f6ba484fa1366fb2b5ebc5d627d30e9394e83c2b Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Mon, 12 Jan 2026 14:58:56 +0000 Subject: [PATCH 12/18] spirit fixes --- .../randomizer/location_access.cpp | 2 +- .../location_access/dungeons/spirit_temple.cpp | 18 +++++++++++------- soh/soh/Enhancements/randomizer/logic.cpp | 5 ----- soh/soh/Enhancements/randomizer/logic.h | 1 - .../Enhancements/randomizer/randomizerTypes.h | 1 + 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index 9cc6b39c2b1..5a675954067 100644 --- a/soh/soh/Enhancements/randomizer/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/location_access.cpp @@ -633,7 +633,7 @@ std::map Region::spiritLogicData = { []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, }}, {RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, {5, 0, 3, 0, - []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritSunOnFloorToStatue();}, + []{return false;}, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}, []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, }}, diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index d0b884d4654..67642180f98 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -34,7 +34,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CHILD_SIDE_HUB] = Region("Spirit Temple Child Side Hub", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanBreakSmallCrates();}), + EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanBreakSmallCrates();}), + EventAccess(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE_TORCHES, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_ARMOS);}) && logic->CanUse(RG_STICKS);}), // not usable in doorsanity }, {}, { //Exits Entrance(RR_SPIRIT_TEMPLE_FOYER, []{return logic->IsChild/*CanUse(RG_CRAWL)*/;}), @@ -81,11 +82,11 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_NORTH] = Region("Spirit Temple Rupee Bridge North", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + EventAccess(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), + EventAccess(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE_TORCHES, []{return (logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE) && logic->HasFireSourceWithTorch()) || logic->CanUse(RG_DINS_FIRE);}), }, { //Locations - // these assume SpiritRupeeBridge, silver rupee shuffle & shuffle climb will want to adjust - LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->HasFireSourceWithTorch()), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE_TORCHES)), // possible to collect without lowering fence, should be a trick LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW) && logic->HasItem(RG_CLIMB)), }, { @@ -94,7 +95,10 @@ void RegionTable_Init_SpiritTemple() { Entrance(RR_SPIRIT_TEMPLE_1F_ANUBIS, []{return true;}), }); - areaTable[RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_SOUTH] = Region("Spirit Temple Rupee Bridge South", SCENE_SPIRIT_TEMPLE, {}, { + areaTable[RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_SOUTH] = Region("Spirit Temple Rupee Bridge South", SCENE_SPIRIT_TEMPLE, { + //Events + EventAccess(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE_TORCHES, []{return logic->HasFireSource();}), + }, { //Locations LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { @@ -130,11 +134,11 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanHitSwitch(ED_BOMB_THROW);})), LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->TakeDamage() ? ED_SHORT_JUMPSLASH : ED_BOMB_THROW);}, false, RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG);})), - LOCATION(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash())), + LOCATION(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash())), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, []{return true;}), - Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->SpiritSunOnFloorToStatue();}), + Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}), }); areaTable[RR_SPIRIT_TEMPLE_ADULT_SIDE_HUB] = Region("Spirit Temple Adult Side Hub", SCENE_SPIRIT_TEMPLE, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 7e8043fea7f..7886b1587f2 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -2462,11 +2462,6 @@ bool Logic::IsReverseAccessPossible() { (ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES)))); } -bool Logic::SpiritSunOnFloorToStatue() { - return (HasItem(RG_CLIMB) || CanUse(RG_LONGSHOT)) && - (HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))); -} - bool Logic::SpiritExplosiveKeyLogic() { return SmallKeys(SCENE_SPIRIT_TEMPLE, HasExplosives() ? 1 : 2); } diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index d627bd85137..c5f9273a71d 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -153,7 +153,6 @@ class Logic { static std::map RandoGetToEquipFlag; static std::map RandoGetToRandInf; bool IsReverseAccessPossible(); - bool SpiritSunOnFloorToStatue(); bool SpiritEastToSwitch(); bool SpiritWestToSkull(); bool SpiritSunBlockSouthLedge(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 4bdce1c457f..9c012a1a17b 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -315,6 +315,7 @@ typedef enum { LOGIC_SPIRIT_1F_SILVER_RUPEES, LOGIC_SPIRIT_CHILD_SWITCH_BRIDGE, LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE, + LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE_TORCHES, LOGIC_SPIRIT_SUN_BLOCK_TORCH, LOGIC_SPIRIT_BOUNDERS_SILVERS, LOGIC_SPIRIT_STATUE_SOUTH_DOOR, From 97c4e394d12c8eb349c9c08f264931726da02dfc Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Mon, 12 Jan 2026 15:30:15 +0000 Subject: [PATCH 13/18] some forest fixes --- .../dungeons/forest_temple.cpp | 44 +++++++++++++------ .../Enhancements/randomizer/randomizerTypes.h | 2 + 2 files changed, 32 insertions(+), 14 deletions(-) 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 b24f093471c..28b709e5a5a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -95,12 +95,19 @@ void RegionTable_Init_ForestTemple() { LOCATION(RC_FOREST_TEMPLE_COURTYARD_LEFT_HEART, logic->CanUse(RG_BOOMERANG) && ctx->GetTrickOption(RT_FOREST_COURTYARD_HEARTS_BOOMERANG)), }, { //Exits - Entrance(RR_FOREST_TEMPLE_LOBBY, []{return true;}), - Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()))) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}), - Entrance(RR_FOREST_TEMPLE_MAP_ROOM, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), - Entrance(RR_FOREST_TEMPLE_SEWER, []{return logic->HasItem(RG_GOLDEN_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), - Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL);}), - Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return false;}), + Entrance(RR_FOREST_TEMPLE_LOBBY, []{return true;}), + Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives())) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}), + Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER_ALCOVE, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_FOREST_TEMPLE_SEWER, []{return logic->HasItem(RG_GOLDEN_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), + Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL);}), + Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return false;}), + }); + + areaTable[RR_FOREST_TEMPLE_NW_COURTYARD_UPPER_ALCOVE] = Region("Forest Temple NW Courtyard Upper Alcove", SCENE_FOREST_TEMPLE, {}, {}, { + //Exits + Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_LOWER, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MAP_ROOM, []{return true;}), + Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER, []{return ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_MEGATON_HAMMER);}), }); areaTable[RR_FOREST_TEMPLE_NW_COURTYARD_UPPER] = Region("Forest Temple NW Courtyard Upper", SCENE_FOREST_TEMPLE, { @@ -126,7 +133,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_FOREST_COURTYARD_EAST_GS) && logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_FOREST_COURTYARD_EAST_GS) && logic->CanUse(RG_BOOMERANG))), }, { //Exits Entrance(RR_FOREST_TEMPLE_LOBBY, []{return true;}), @@ -538,10 +545,11 @@ void RegionTable_Init_ForestTemple() { LOCATION(RC_FOREST_TEMPLE_MQ_COURTYARD_LEFT_HEART, true), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_REDEAD_ROOM, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_FLOORMASTER_ROOM, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_WELL_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_FOREST_TEMPLE_MQ_REDEAD_ROOM, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MQ_FLOORMASTER_ROOM, []{return true;}), }); areaTable[RR_FOREST_TEMPLE_MQ_REDEAD_ROOM] = Region("Forest Temple MQ Redead Room", SCENE_FOREST_TEMPLE, {}, { @@ -557,7 +565,6 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_MQ_BURNED_WEB, []{return logic->CanUse(RG_FIRE_ARROWS);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), //the well checks are considered from both areas instead of being a region because the draining is a temp flag and the skull (as well as the chest with hook glitch) has different breath timers from each side LOCATION(RC_FOREST_TEMPLE_MQ_GS_WELL, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && logic->CanUse(RG_HOOKSHOT))), LOCATION(RC_FOREST_TEMPLE_MQ_COURTYARD_RIGHT_HEART, logic->CanUse(RG_BOOMERANG) && ctx->GetTrickOption(RT_FOREST_COURTYARD_HEARTS_BOOMERANG)), @@ -568,9 +575,18 @@ void RegionTable_Init_ForestTemple() { LOCATION(RC_FOREST_TEMPLE_MQ_WELL_EAST_HEART, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), }, { //Exits + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_WELL_LEDGE, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD, []{return logic->HasItem(RG_CLIMB) && (logic->Get(LOGIC_FOREST_DRAINED_WELL) || ((((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16));}), Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->Get(LOGIC_FOREST_MQ_BURNED_WEB) && (logic->CanKillEnemy(RE_BIG_SKULLTULA, ED_LONGSHOT) || logic->CanUse(RG_BOMBCHU_5));}), - Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}), + }); + + areaTable[RR_FOREST_TEMPLE_MQ_NW_COURTYARD_WELL_LEDGE] = Region("Forest Temple MQ NW Courtyard Well Ledge", SCENE_FOREST_TEMPLE, {}, { + //Locations + LOCATION(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), // rang trick could get this from below + }, { + //Exits + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}), }); areaTable[RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE] = Region("Forest Temple MQ NW Courtyard Upper Alcove", SCENE_FOREST_TEMPLE, { @@ -610,7 +626,7 @@ void RegionTable_Init_ForestTemple() { //Exits Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, []{return true;}), Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16;}), - Entrance(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES, []{return logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && ((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanUse(RG_SONG_OF_TIME)));}), + Entrance(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES, []{return logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_VINES) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_CLIMB)) || (logic->CanUse(RG_HOOKSHOT) && ((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->HasItem(RG_CLIMB)) || logic->CanUse(RG_SONG_OF_TIME)));}), Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND, []{return logic->CanUse(RG_LONGSHOT);}), }); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 9c012a1a17b..4254d20d176 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -905,6 +905,7 @@ typedef enum { RR_FOREST_TEMPLE_NORTH_HALLWAY, RR_FOREST_TEMPLE_LOWER_STALFOS, RR_FOREST_TEMPLE_NW_COURTYARD_LOWER, + RR_FOREST_TEMPLE_NW_COURTYARD_UPPER_ALCOVE, RR_FOREST_TEMPLE_NW_COURTYARD_UPPER, RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, RR_FOREST_TEMPLE_NE_COURTYARD_UPPER, @@ -952,6 +953,7 @@ typedef enum { RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, RR_FOREST_TEMPLE_MQ_REDEAD_ROOM, RR_FOREST_TEMPLE_MQ_NW_COURTYARD, + RR_FOREST_TEMPLE_MQ_NW_COURTYARD_WELL_LEDGE, RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE, RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE, RR_FOREST_TEMPLE_MQ_NE_COURTYARD, From b6e4235986a10008646d8bceab8b49cb5ea764ff Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Sun, 18 Jan 2026 14:52:23 +0000 Subject: [PATCH 14/18] cleanup --- soh/soh/Enhancements/randomizer/item_list.cpp | 6 +++--- .../randomizer/location_access/overworld/zoras_river.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 2b78624a528..a2be871777a 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -366,18 +366,18 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_GERUDO_MASK] = Item(RG_GERUDO_MASK, Text{ "Gerudo Mask", "Masque de Gerudo", TODO_TRANSLATE }, ITEMTYPE_ITEM, RG_GERUDO_MASK, true, LOGIC_NONE, RHT_MASK_GERUDO, RG_GERUDO_MASK, OBJECT_GI_GERUDOMASK, GID_MASK_GERUDO, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MASK_OF_TRUTH] = Item(RG_MASK_OF_TRUTH, Text{ "Mask of Truth", "Masque de Vérité", TODO_TRANSLATE }, ITEMTYPE_ITEM, RG_MASK_OF_TRUTH, true, LOGIC_NONE, RHT_MASK_TRUTH, RG_MASK_OF_TRUTH, OBJECT_GI_TRUTH_MASK, GID_MASK_TRUTH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_NONE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "die ", "le "}); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_NONE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "die ", "le "}); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); itemTable[RG_POWER_BRACELET] = Item(RG_POWER_BRACELET, Text{ "Power Bracelet", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_ITEM, GI_BRACELET, true, LOGIC_NONE, RHT_NONE, RG_POWER_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_POWER_BRACELET].SetCustomDrawFunc(Randomizer_DrawPowerBracelet); - itemTable[RG_CLIMB] = Item(RG_CLIMB, Text{ "Climb", TODO_TRANSLATE, "Grimper" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_CLIMB, RG_CLIMB, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_CLIMB] = Item(RG_CLIMB, Text{ "Climb", TODO_TRANSLATE, "Grimper" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_CLIMB, RG_CLIMB, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_CLIMB].SetCustomDrawFunc(Randomizer_DrawLadder); itemTable[RG_CRAWL] = Item(RG_CRAWL, Text{ "Crawl", "Ramper", "Kriechen" }, ITEMTYPE_ITEM, GI_SHIELD_DEKU, true, LOGIC_NONE, RHT_CRAWL, RG_CRAWL, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_CRAWL].SetCustomDrawFunc(Randomizer_DrawKneePads); itemTable[RG_OPEN_CHEST] = Item(RG_OPEN_CHEST, Text{ "Open Chests", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_ITEM, GI_KEY_SMALL, true, LOGIC_NONE, RHT_OPEN_CHEST, RG_OPEN_CHEST, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OPEN_CHEST].SetCustomDrawFunc(Randomizer_DrawOpenChest); - itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "un "}); + itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "un "}); itemTable[RG_PROGRESSIVE_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag); itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "le "}); 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 8b717194de5..5065c78ee23 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, []{return true;}), - Entrance(RR_ZR_ATOP_LADDER, []{return (logic->IsAdult || logic->HasItem(RG_POWER_BRACELET)) && (logic->CanUse(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || CanPlantBean(RR_ZORAS_RIVER, RG_ZORAS_RIVER_BEAN_SOUL));}), + Entrance(RR_ZR_ATOP_LADDER, []{return (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_PILLAR, []{return (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_LOWER));}), Entrance(RR_ZR_FROM_SHORTCUT, []{return logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_ZR_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), From 164c63e09fc6840d93f12f8c69f7cc230e6da19a Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Mon, 19 Jan 2026 15:44:28 +0000 Subject: [PATCH 15/18] fix forest block climb --- .../dungeons/forest_temple.cpp | 89 ++++++++++++++----- .../Enhancements/randomizer/randomizerTypes.h | 4 + 2 files changed, 69 insertions(+), 24 deletions(-) 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 923afdec764..a163468a3ed 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -238,14 +238,21 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_RED_DOORMAT_HALLWAY_DOORMAT] = Region("Forest Temple West Hallway Doormat", SCENE_FOREST_TEMPLE, {}, {}, { //Exits - Entrance(RR_FOREST_TEMPLE_RED_DOORMAT_HALLWAY, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), - Entrance(RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM, []{return true;}), + Entrance(RR_FOREST_TEMPLE_RED_DOORMAT_HALLWAY, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), + Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_FLOOR, []{return true;}), }); - areaTable[RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM] = Region("Forest Temple Lower Block Push Room", SCENE_FOREST_TEMPLE, {}, {}, { + areaTable[RR_FOREST_TEMPLE_BLOCK_PUSH_FLOOR] = Region("Forest Temple Lower Block Push Floor", SCENE_FOREST_TEMPLE, {}, {}, { //Exits Entrance(RR_FOREST_TEMPLE_RED_DOORMAT_HALLWAY_DOORMAT, []{return true;}), + Entrance(RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM, []{return logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanGroundJump());}), + }); + + areaTable[RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM] = Region("Forest Temple Lower Block Push Room", SCENE_FOREST_TEMPLE, {}, {}, { + //Exits + Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_FLOOR, []{return true;}), Entrance(RR_FOREST_TEMPLE_MIDDLE_BLOCK_PUSH_ROOM, []{return logic->HasItem(RG_CLIMB) && logic->HasItem(RG_GORONS_BRACELET);}), + Entrance(RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM, []{return logic->IsAdult && logic->CanGroundJump() && logic->HasItem(RG_GORONS_BRACELET) && logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_COURTYARD_ALCOVE, []{return logic->CanUse(RG_HOVER_BOOTS);}), }); @@ -256,12 +263,18 @@ void RegionTable_Init_ForestTemple() { //Exits Entrance(RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM, []{return true;}), Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_COURTYARD_ALCOVE, []{return ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && logic->CanJumpslashExceptHammer();}), - Entrance(RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM, []{return logic->IsAdult && logic->HasItem(RG_CLIMB) && logic->HasItem(RG_GORONS_BRACELET);}), + Entrance(RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM, []{return logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET);}), }); areaTable[RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM] = Region("Forest Temple Upper Block Push Room", SCENE_FOREST_TEMPLE, {}, {}, { //Exits - Entrance(RR_FOREST_TEMPLE_MIDDLE_BLOCK_PUSH_ROOM, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MIDDLE_BLOCK_PUSH_ROOM, []{return true;}), + Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_TOP, []{return logic->HasItem(RG_CLIMB);}), + }); + + areaTable[RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_TOP] = Region("Forest Temple Block Push Room Top", SCENE_FOREST_TEMPLE, {}, {}, { + //Exits + Entrance(RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM, []{return true;}), Entrance(RR_FOREST_TEMPLE_NW_HALLWAY_TWISTED, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), Entrance(RR_FOREST_TEMPLE_NW_HALLWAY_STRAIGHTENED, []{return logic->CanHitEyeTargets() && logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), }); @@ -274,8 +287,8 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_NW_HALLWAY_TWISTED] = Region("Forest Temple NW Hallway Twisted", SCENE_FOREST_TEMPLE, {}, {}, { //Exits - Entrance(RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), - Entrance(RR_FOREST_TEMPLE_RED_POE_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), + Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_TOP, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), + Entrance(RR_FOREST_TEMPLE_RED_POE_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), }); areaTable[RR_FOREST_TEMPLE_NW_HALLWAY_STRAIGHTENED] = Region("Forest Temple NW Hallway Straightened", SCENE_FOREST_TEMPLE, {}, { @@ -283,8 +296,8 @@ void RegionTable_Init_ForestTemple() { LOCATION(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits - Entrance(RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, []{return true;}), - Entrance(RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), + Entrance(RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, []{return true;}), + Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_TOP, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 2);}), }); areaTable[RR_FOREST_TEMPLE_RED_POE_ROOM] = Region("Forest Temple Red Poe Room", SCENE_FOREST_TEMPLE, { @@ -474,45 +487,73 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_RED_DOORMAT_HALLWAY] = Region("Forest Temple MQ Red Doormat Hallway", SCENE_FOREST_TEMPLE, {}, {}, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS);});}), - Entrance(RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS);});}), + Entrance(RR_FOREST_TEMPLE_MQ_BLOCK_PUZZLE_FLOOR, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS);});}), }); - areaTable[RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE] = Region("Forest Temple MQ Lower Block Puzzle", SCENE_FOREST_TEMPLE, { - //longshot is capable of hitting the switch, but some invisible collision makes the shot harder than you would think, so it may be trickworthy + areaTable[RR_FOREST_TEMPLE_MQ_BLOCK_PUZZLE_FLOOR] = Region("Forest Temple MQ Block Puzzle Floor", SCENE_FOREST_TEMPLE, { + //Events EventAccess(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS, []{return (ctx->GetTrickOption(RT_FOREST_MQ_BLOCK_PUZZLE) && logic->CanUse(RG_BOMBCHU_5));}), //It is barely possible to get this as child with master + hovers, but it's tight without bunny speed - EventAccess(LOGIC_FOREST_CAN_TWIST_HALLWAY, []{return (ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && logic->CanUse(RG_HOVER_BOOTS) && (logic->IsAdult && logic->CanJumpslash()) || (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_MASTER_SWORD)))) || (ctx->GetTrickOption(RT_FOREST_MQ_RANG_HALLWAY_SWITCH) && logic->CanUse(RG_BOOMERANG)) || (ctx->GetTrickOption(RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH) && logic->CanUse(RG_HOOKSHOT));}), + EventAccess(LOGIC_FOREST_CAN_TWIST_HALLWAY, []{return (ctx->GetTrickOption(RT_FOREST_MQ_RANG_HALLWAY_SWITCH) && logic->CanUse(RG_BOOMERANG)) || (ctx->GetTrickOption(RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH) && logic->CanUse(RG_HOOKSHOT));}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_RED_DOORMAT_HALLWAY, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS);});}), - Entrance(RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE, []{return (logic->HasItem(RG_CLIMB) && logic->HasItem(RG_GORONS_BRACELET)) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), - Entrance(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_FOREST_TEMPLE_MQ_RED_DOORMAT_HALLWAY, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE, []{return ((logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanGroundJump())) && + (logic->HasItem(RG_GORONS_BRACELET) || logic->CanUse(RG_HOVER_BOOTS))) || + (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->CanUse(RG_HOOKSHOT);}), + }); + + areaTable[RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE] = Region("Forest Temple MQ Lower Block Puzzle", SCENE_FOREST_TEMPLE, { + //Events + //It is barely possible to get this as child with master + hovers, but it's tight without bunny speed + EventAccess(LOGIC_FOREST_CAN_TWIST_HALLWAY, []{return (ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && logic->CanUse(RG_HOVER_BOOTS) && + (logic->IsAdult && logic->CanJumpslash()) || + (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_MASTER_SWORD))));}), + }, {}, { + //Exits + Entrance(RR_FOREST_TEMPLE_MQ_BLOCK_PUZZLE_FLOOR, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE, []{return (logic->HasItem(RG_GORONS_BRACELET) && (logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanGroundJump()))) || + logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS);}), + Entrance(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->CanUse(RG_HOVER_BOOTS);}), }); areaTable[RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE] = Region("Forest Temple MQ Middle Block Puzzle", SCENE_FOREST_TEMPLE, { - //longshot is capable of hitting the switch, but some invisible collision makes the shot more annoying than you would think, so it may be trickworthy + //Events EventAccess(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS, []{return (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_LONGSHOT));}), - EventAccess(LOGIC_FOREST_CAN_TWIST_HALLWAY, []{return ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && (logic->IsAdult && logic->CanJumpslash()) || (logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MASTER_SWORD)));}), + EventAccess(LOGIC_FOREST_CAN_TWIST_HALLWAY, []{return ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && + (logic->IsAdult && logic->CanJumpslash()) || + (logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MASTER_SWORD)));}), }, {}, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return (logic->IsAdult && logic->HasItem(RG_CLIMB) && logic->HasItem(RG_GORONS_BRACELET)) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), + Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return (logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET)) || + (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT));}), //Hammer cannot recoil from here, but can make the jump forwards with a hammer jumpslash as adult - Entrance(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && (logic->CanJumpslashExceptHammer() || (logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER))));}), + Entrance(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->CanUse(RG_HOVER_BOOTS) || + (ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && (logic->CanJumpslashExceptHammer() || (logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER))));}), }); - areaTable[RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE] = Region("Forest Temple MQ After Block Puzzle", SCENE_FOREST_TEMPLE, {}, {}, { + areaTable[RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE] = Region("Forest Temple MQ Upper Block Puzzle", SCENE_FOREST_TEMPLE, { + //Events + EventAccess(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS, []{return logic->CanHitSwitch();}), + }, {}, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_STRAIGHT_HALLWAY, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), - Entrance(RR_FOREST_TEMPLE_MQ_JOELLE_ROOM, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->SmallKeys(SCENE_FOREST_TEMPLE, 4);}), + Entrance(RR_FOREST_TEMPLE_MQ_BLOCK_PUZZLE_TOP, []{return logic->HasItem(RG_CLIMB);}), + }); + + areaTable[RR_FOREST_TEMPLE_MQ_BLOCK_PUZZLE_TOP] = Region("Forest Temple MQ Block Puzzle Top", SCENE_FOREST_TEMPLE, {}, {}, { + //Exits + Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return true;}), + Entrance(RR_FOREST_TEMPLE_MQ_STRAIGHT_HALLWAY, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), + Entrance(RR_FOREST_TEMPLE_MQ_JOELLE_ROOM, []{return logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->SmallKeys(SCENE_FOREST_TEMPLE, 4);}), //!QUANTUM LOGIC! //As there is no way in default logic to reach the other possible key use without going through RR_FOREST_TEMPLE_MQ_NW_COURTYARD, this is logically safe for now //Breaks if there's any other way to RR_FOREST_TEMPLE_MQ_FALLING_ROOM than going through the eye targets in RR_FOREST_TEMPLE_MQ_LOBBY - //Requires a bow/sling ammo source once ammo logic is done, to avoid edge cases. Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 2) && AnyAgeTime([]{return logic->CanKillEnemy(RE_FLOORMASTER);});}), }); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 7bef1c3180a..86a20b1ee41 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -921,9 +921,11 @@ typedef enum { RR_FOREST_TEMPLE_FLOORMASTER_ROOM, RR_FOREST_TEMPLE_RED_DOORMAT_HALLWAY, RR_FOREST_TEMPLE_RED_DOORMAT_HALLWAY_DOORMAT, + RR_FOREST_TEMPLE_BLOCK_PUSH_FLOOR, RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM, RR_FOREST_TEMPLE_MIDDLE_BLOCK_PUSH_ROOM, RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM, + RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_TOP, RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_COURTYARD_ALCOVE, RR_FOREST_TEMPLE_NW_HALLWAY_TWISTED, RR_FOREST_TEMPLE_NW_HALLWAY_STRAIGHTENED, @@ -946,9 +948,11 @@ typedef enum { RR_FOREST_TEMPLE_MQ_NORTH_HALLWAY, RR_FOREST_TEMPLE_MQ_WOLFOS_ROOM, RR_FOREST_TEMPLE_MQ_RED_DOORMAT_HALLWAY, + RR_FOREST_TEMPLE_MQ_BLOCK_PUZZLE_FLOOR, RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE, RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE, RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, + RR_FOREST_TEMPLE_MQ_BLOCK_PUZZLE_TOP, RR_FOREST_TEMPLE_MQ_STRAIGHT_HALLWAY, RR_FOREST_TEMPLE_MQ_FLOORMASTER_ROOM, RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, From e163f58fec734a24de442181db5068e41d4fc00d Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Mon, 19 Jan 2026 16:01:49 +0000 Subject: [PATCH 16/18] indentation --- .../randomizer/location_access/dungeons/deku_tree.cpp | 2 +- .../randomizer/location_access/dungeons/dodongos_cavern.cpp | 2 +- .../randomizer/location_access/dungeons/forest_temple.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 afc2f1b9b78..2e1dfd7d6d5 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -403,7 +403,7 @@ void RegionTable_Init_DekuTree() { //Locations LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LARVAE_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LARVAE_GRASS_2, logic->CanCutShrubs()), - }, { + }, { //Exits //both imply CanKillEnemy(RE_GOHMA_LARVA) Entrance(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_MAD_SCRUB) && logic->CanKillEnemy(RE_KEESE);});}), 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 8ac01a747f0..46b27b2ba17 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp @@ -533,7 +533,7 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_MQ_POE_ROOM_CRATE_6, logic->HasItem(RG_GORONS_BRACELET) || logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_POE_ROOM_CRATE_7, logic->HasItem(RG_GORONS_BRACELET) || logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_POE_ROOM_CRATE_8, logic->HasItem(RG_GORONS_BRACELET) || logic->CanBreakCrates()), - }, { + }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_OUTSIDE_POES_ROOM, []{return AnyAgeTime([]{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);});}), Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_LIZALFOS, []{return true;}), 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 a163468a3ed..7498652d3be 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -540,7 +540,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE] = Region("Forest Temple MQ Upper Block Puzzle", SCENE_FOREST_TEMPLE, { //Events EventAccess(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS, []{return logic->CanHitSwitch();}), - }, {}, { + }, {}, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE, []{return true;}), Entrance(RR_FOREST_TEMPLE_MQ_BLOCK_PUZZLE_TOP, []{return logic->HasItem(RG_CLIMB);}), From e5cf2394bd8b74fb2b3baa73662654eb2d810dd8 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Mon, 19 Jan 2026 18:35:31 +0000 Subject: [PATCH 17/18] GV fixes --- .../overworld/gerudo_valley.cpp | 89 +++++++++++-------- .../Enhancements/randomizer/randomizerTypes.h | 2 + 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp index e5997f5a0d9..2bdee3085cb 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -11,16 +11,17 @@ void RegionTable_Init_GerudoValley() { }, { //Locations LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), - LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, logic->IsChild || ((logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_CLIMB))), }, { //Exits - Entrance(RR_HYRULE_FIELD, []{return true;}), - Entrance(RR_GV_UPPER_STREAM, []{return (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->HasItem(RG_BRONZE_SCALE) || logic->TakeDamage();}), - Entrance(RR_GV_CRATE_LEDGE, []{return (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_LONGSHOT);}), - Entrance(RR_GV_GROTTO_LEDGE, []{return true;}), - Entrance(RR_GV_FORTRESS_SIDE, []{return (logic->IsAdult && (logic->SummonEpona() || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS))) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOVER_BOOTS)) || - ((logic->IsChild || ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION)) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsChild && ctx->GetTrickOption(RT_GV_CHILD_CUCCO_JUMP) && logic->HasItem(RG_POWER_BRACELET) && logic->CanJumpslash());}), - Entrance(RR_GV_LOWER_STREAM, []{return logic->IsChild && logic->HasItem(RG_POWER_BRACELET);}), + Entrance(RR_HYRULE_FIELD, []{return true;}), + Entrance(RR_GV_UPPER_STREAM, []{return (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->TakeDamage();}), + Entrance(RR_GV_UPPER_STREAM_WATER, []{return true;}), + Entrance(RR_GV_CRATE_LEDGE, []{return (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_GV_GROTTO_LEDGE, []{return true;}), + Entrance(RR_GV_FORTRESS_SIDE, []{return (logic->IsAdult && (logic->SummonEpona() || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS))) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOVER_BOOTS)) || + ((logic->IsChild || ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION)) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsChild && ctx->GetTrickOption(RT_GV_CHILD_CUCCO_JUMP) && logic->HasItem(RG_POWER_BRACELET) && logic->CanJumpslash());}), + Entrance(RR_GV_WATERFALL_ALCOVE, []{return logic->IsChild && logic->HasItem(RG_POWER_BRACELET);}), + Entrance(RR_GV_LOWER_STREAM, []{return logic->IsChild && logic->HasItem(RG_POWER_BRACELET);}), }); areaTable[RR_GV_UPPER_STREAM] = Region("GV Upper Stream", SCENE_GERUDO_VALLEY, { @@ -28,19 +29,26 @@ void RegionTable_Init_GerudoValley() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy() || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS));}), }, { //Locations - LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || (logic->HasItem(RG_CLIMB) && (logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_LONGSHOT))) || CanPlantBean(RR_GV_UPPER_STREAM, RG_GERUDO_VALLEY_BEAN_SOUL)), - LOCATION(RC_GV_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanAttack()), - LOCATION(RC_GV_COW, logic->IsChild && logic->CanUse(RG_EPONAS_SONG)), - LOCATION(RC_GV_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_GV_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_GV_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_GV_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), - LOCATION(RC_GV_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_GV_GOSSIP_STONE, true), - LOCATION(RC_GV_NEAR_COW_CRATE, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_GV_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanAttack()), + LOCATION(RC_GV_COW, logic->IsChild && logic->CanUse(RG_EPONAS_SONG)), + LOCATION(RC_GV_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_GV_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_GV_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_GV_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), + LOCATION(RC_GV_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_GV_GOSSIP_STONE, true), + LOCATION(RC_GV_NEAR_COW_CRATE, logic->IsChild && logic->CanBreakCrates()), }, { //Exits - Entrance(RR_GV_LOWER_STREAM, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), + Entrance(RR_GV_UPPER_STREAM_WATER, []{return true;}), + Entrance(RR_GV_WATERFALL_ALCOVE, []{return (logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_CLIMB)) || logic->CanUse(RG_LONGSHOT) || CanPlantBean(RR_GV_UPPER_STREAM, RG_GERUDO_VALLEY_BEAN_SOUL);}), + }); + + areaTable[RR_GV_UPPER_STREAM_WATER] = Region("GV Upper Stream Water", SCENE_GERUDO_VALLEY, {}, {}, { + //Exits + Entrance(RR_GV_UPPER_STREAM, []{return logic->HasItem(RG_BRONZE_SCALE);}), + Entrance(RR_GV_LOWER_STREAM, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), + Entrance(RR_GV_WATERFALL_ALCOVE, []{return (logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_CLIMB);}), }); // scale/boots logic is outside lower stream, as lower stream combines access to lake hylia for entrance randomizer's sake @@ -49,9 +57,18 @@ void RegionTable_Init_GerudoValley() { Entrance(RR_LAKE_HYLIA, []{return true;}), }); + areaTable[RR_GV_WATERFALL_ALCOVE] = Region("GV Waterfall Alcove", SCENE_GERUDO_VALLEY, {}, { + //Locations + LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, true), + }, { + //Exits + Entrance(RR_GV_UPPER_STREAM, []{return logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_GV_UPPER_STREAM_WATER, []{return true;}), + }); + areaTable[RR_GV_GROTTO_LEDGE] = Region("GV Grotto Ledge", SCENE_GERUDO_VALLEY, {}, {}, { //Exits - Entrance(RR_GV_UPPER_STREAM, []{return ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives();}), + Entrance(RR_GV_UPPER_STREAM, []{return ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->TakeDamage();}), Entrance(RR_GV_LOWER_STREAM, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_GV_OCTOROK_GROTTO, []{return logic->CanUse(RG_SILVER_GAUNTLETS);}), Entrance(RR_GV_CRATE_LEDGE, []{return logic->CanUse(RG_LONGSHOT);}), @@ -63,29 +80,29 @@ void RegionTable_Init_GerudoValley() { LOCATION(RC_GV_FREESTANDING_POH_CRATE, logic->CanBreakCrates()), }, { //Exits - Entrance(RR_GV_UPPER_STREAM, []{return ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives();}), + Entrance(RR_GV_UPPER_STREAM, []{return ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->TakeDamage();}), Entrance(RR_GV_LOWER_STREAM, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), }); areaTable[RR_GV_FORTRESS_SIDE] = Region("GV Fortress Side", SCENE_GERUDO_VALLEY, {}, { //Locations - LOCATION(RC_GV_CHEST, logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT))) && logic->HasItem(RG_OPEN_CHEST)), - LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, (logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_CLIMB)), - LOCATION(RC_GV_TRADE_SAW, logic->IsAdult && logic->CanUse(RG_POACHERS_SAW)), - LOCATION(RC_GV_GS_BEHIND_TENT, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), - LOCATION(RC_GV_GS_PILLAR, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), - LOCATION(RC_GV_CRATE_BRIDGE_1, logic->IsChild && logic->CanBreakCrates()), - LOCATION(RC_GV_CRATE_BRIDGE_2, logic->IsChild && logic->CanBreakCrates()), - LOCATION(RC_GV_CRATE_BRIDGE_3, logic->IsChild && logic->CanBreakCrates()), - LOCATION(RC_GV_CRATE_BRIDGE_4, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_GV_CHEST, logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GV_TRADE_SAW, logic->IsAdult && logic->CanUse(RG_POACHERS_SAW)), + LOCATION(RC_GV_GS_BEHIND_TENT, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), + LOCATION(RC_GV_GS_PILLAR, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), + LOCATION(RC_GV_CRATE_BRIDGE_1, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_GV_CRATE_BRIDGE_2, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_GV_CRATE_BRIDGE_3, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_GV_CRATE_BRIDGE_4, logic->IsChild && logic->CanBreakCrates()), }, { //Exits - Entrance(RR_GF_OUTSKIRTS, []{return true;}), - Entrance(RR_GV_UPPER_STREAM, []{return true;}), - Entrance(RR_GERUDO_VALLEY, []{return logic->IsChild || logic->SummonEpona() || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOVER_BOOTS));}), - Entrance(RR_GV_CARPENTER_TENT, []{return logic->IsAdult || ctx->GetTrickOption(RT_GV_CHILD_TENT);}), - Entrance(RR_GV_STORMS_GROTTO, []{return logic->IsAdult && logic->CanOpenStormsGrotto();}), - Entrance(RR_GV_CRATE_LEDGE, []{return (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GV_CRATE_HOVERS) && logic->TakeDamage() && logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)));}), + Entrance(RR_GF_OUTSKIRTS, []{return true;}), + Entrance(RR_GV_UPPER_STREAM, []{return logic->TakeDamage();}), + Entrance(RR_GV_UPPER_STREAM_WATER, []{return true;}), + Entrance(RR_GERUDO_VALLEY, []{return logic->IsChild || logic->SummonEpona() || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_GV_CARPENTER_TENT, []{return logic->IsAdult || ctx->GetTrickOption(RT_GV_CHILD_TENT);}), + Entrance(RR_GV_STORMS_GROTTO, []{return logic->IsAdult && logic->CanOpenStormsGrotto();}), + Entrance(RR_GV_CRATE_LEDGE, []{return (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GV_CRATE_HOVERS) && logic->TakeDamage() && logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)));}), }); areaTable[RR_GV_CARPENTER_TENT] = Region("GV Carpenter Tent", SCENE_CARPENTERS_TENT, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 86a20b1ee41..b2211cad9c3 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -581,7 +581,9 @@ typedef enum { RR_LH_GROTTO, RR_GERUDO_VALLEY, RR_GV_UPPER_STREAM, + RR_GV_UPPER_STREAM_WATER, RR_GV_LOWER_STREAM, + RR_GV_WATERFALL_ALCOVE, RR_GV_GROTTO_LEDGE, RR_GV_CRATE_LEDGE, RR_GV_OCTOROK_GROTTO, From 18b93592f30cb08aead53b18a6da652194c421b4 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Mon, 19 Jan 2026 19:47:39 +0000 Subject: [PATCH 18/18] 0.25 --- soh/soh/Enhancements/randomizer/draw.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 1a2ee1b6ddf..cfc4a470595 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -24,7 +24,6 @@ extern "C" { #include "objects/object_fish/object_fish.h" #include "objects/object_toki_objects/object_toki_objects.h" #include "objects/object_gi_bomb_2/object_gi_bomb_2.h" -#include "objects/gameplay_field_keep/gameplay_field_keep.h" #include "objects/object_goma/object_goma.h" #include "objects/object_kingdodongo/object_kingdodongo.h" #include "objects/object_bv/object_bv.h" @@ -35,7 +34,6 @@ extern "C" { #include "objects/object_mori_objects/object_mori_objects.h" #include "objects/object_sst/object_sst.h" #include "overlays/actors/ovl_Boss_Goma/z_boss_goma.h" -#include "overlays/ovl_Boss_Sst/ovl_Boss_Sst.h" #include "objects/object_tw/object_tw.h" #include "objects/object_ganon2/object_ganon2.h" #include "objects/object_gi_shield_1/object_gi_shield_1.h" @@ -1162,7 +1160,7 @@ extern "C" void Randomizer_DrawLadder(PlayState* play, GetItemEntry* getItemEntr Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPSegment(POLY_OPA_DISP++, 0x08, (uintptr_t)gMoriHashiraTex); Matrix_Translate(0, -30, 0, MTXMODE_APPLY); - Matrix_Scale(1.0f, 0.375f, 1.0f, MTXMODE_APPLY); + Matrix_Scale(1.0f, 0.25f, 1.0f, MTXMODE_APPLY); gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gMoriHashigoLadderDL);