diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index e378b3b22f3..7a260ccd6ad 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 01e015ed308..4b347417f28 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 @@ -2117,10 +2117,11 @@ 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 obscure and ambiguous hints + hintTextTable[RHT_CLIMB] = HintText(CustomMessage("the ability to climb", /*german*/TODO_TRANSLATE, /*french*/"la capacité de grimper")); hintTextTable[RHT_CRAWL] = HintText(CustomMessage("the ability to crawl", /*german*/TODO_TRANSLATE, /*french*/"la capacité de ramper")); hintTextTable[RHT_OPEN_CHEST] = HintText(CustomMessage("the ability to open chests", /*german*/TODO_TRANSLATE, /*french*/TODO_TRANSLATE)); - //RANDOTODO if these are ever used for anything other than name, they want abscure and ambiguous hints 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 b1678fa885b..6b842de1d88 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -401,7 +401,12 @@ void GenerateItemPool() { int bronzeScale = ctx->GetOption(RSK_SHUFFLE_SWIM) ? 1 : 0; AddItemToPool(RG_PROGRESSIVE_SCALE, 3 + bronzeScale, 2 + bronzeScale, 2 + bronzeScale, 2 + bronzeScale); + int powerBracelet = ctx->GetOption(RSK_SHUFFLE_GRAB) ? 1 : 0; + AddItemToPool(RG_PROGRESSIVE_STRENGTH, 4 + powerBracelet, 3 + powerBracelet, 3 + powerBracelet, 3 + powerBracelet); + if (ctx->GetOption(RSK_SHUFFLE_CLIMB)) { + AddItemToPool(RG_CLIMB, 2, 1, 1, 1); + } if (ctx->GetOption(RSK_SHUFFLE_CRAWL)) { AddItemToPool(RG_CRAWL, 2, 1, 1, 1); } @@ -409,9 +414,6 @@ void GenerateItemPool() { AddItemToPool(RG_OPEN_CHEST, 2, 1, 1, 1); } - int powerBracelet = ctx->GetOption(RSK_SHUFFLE_GRAB) ? 1 : 0; - AddItemToPool(RG_PROGRESSIVE_STRENGTH, 4 + powerBracelet, 3 + powerBracelet, 3 + powerBracelet, 3 + powerBracelet); - if (ctx->GetOption(RSK_SHUFFLE_BEEHIVES)) { PlaceItemsForType(RCTYPE_BEEHIVE, true, true); } diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp index 834aea3da00..10b1a6a7df4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp @@ -997,6 +997,10 @@ 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_CRAWL] = { // TODO_TRANSLATE Text{ "Crouch" }, diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 2ec7d2219bc..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" @@ -32,9 +31,9 @@ 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" #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" @@ -1139,35 +1138,53 @@ extern "C" void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getIte CLOSE_DISPS(play->state.gfxCtx); } -extern "C" void Randomizer_DrawKneePads(PlayState* play, GetItemEntry* getItemEntry) { +extern "C" void Randomizer_DrawPowerBracelet(PlayState* play, GetItemEntry* getItemEntry) { OPEN_DISPS(play->state.gfxCtx); Gfx_SetupDL_25Opa(play->state.gfxCtx); - Matrix_Translate(-35, -5, 0, MTXMODE_APPLY); - Matrix_Scale(0.4f, 0.8f, 1.2f, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiDekuShieldDL); - Gfx_SetupDL_25Opa(play->state.gfxCtx); - Matrix_Translate(35, -7, 4, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiDekuShieldDL); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + + gSPGrayscale(POLY_OPA_DISP++, true); + gDPSetGrayscaleColor(POLY_OPA_DISP++, 80, 80, 80, 255); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiGoronBraceletDL); + gSPGrayscale(POLY_OPA_DISP++, false); CLOSE_DISPS(play->state.gfxCtx); } -extern "C" void Randomizer_DrawPowerBracelet(PlayState* play, GetItemEntry* getItemEntry) { +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.25f, 1.0f, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), - G_MTX_MODELVIEW | G_MTX_LOAD); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gMoriHashigoLadderDL); - gSPGrayscale(POLY_OPA_DISP++, true); - gDPSetGrayscaleColor(POLY_OPA_DISP++, 80, 80, 80, 255); - gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiGoronBraceletDL); - gSPGrayscale(POLY_OPA_DISP++, false); + 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_DrawKneePads(PlayState* play, GetItemEntry* getItemEntry) { + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + Matrix_Translate(-35, -5, 0, MTXMODE_APPLY); + Matrix_Scale(0.4f, 0.8f, 1.2f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiDekuShieldDL); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + Matrix_Translate(35, -7, 4, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiDekuShieldDL); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index 8ba0f93456d..ce3a4564d0d 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -23,6 +23,7 @@ void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawPowerBracelet(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawLadder(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawKneePads(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawOpenChest(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry); diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 9cb2137ef05..7d13537e741 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 }, @@ -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) @@ -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_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) }, { 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 }, @@ -1544,7 +1544,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), @@ -1566,7 +1566,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 e0ad1c256de..5f6d7861776 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_CRAWL: *should = *should && Flags_GetRandomizerInf(RAND_INF_CAN_CRAWL); break; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 582d738015c..ce29f260d86 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -366,17 +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_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_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].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.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index 25a8f2ecdd6..696f5ebb7df 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,116 @@ 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->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh() */;}, []{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->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh() */;}, []{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->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{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->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{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->HasItem(RG_POWER_BRACELET) && logic->SpiritWestToSkull()/* && logic->CanClimbHigh()*/;}, []{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->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{return true;}}}, - //Assumes SpiritSunBlockSouthLedge() for all access - {RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{return logic->SpiritExplosiveKeyLogic() && logic->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{return logic->HasItem(RG_POWER_BRACELET)/*((logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_POWER_BRACELET)) || (logic->CanKillEnemy(RE_BEAMOS) && logic->CanUse(RG_LONGSHOT))*/;}}}, - {RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{return logic->SpiritExplosiveKeyLogic() && logic->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{return logic->HasItem(RG_POWER_BRACELET)/*((logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_POWER_BRACELET)) || (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 logic->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{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 logic->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{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_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{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->HasItem(RG_POWER_BRACELET)/* && logic->CanClimbHigh()*/;}, []{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_ON_FLOOR_1F, {5, 0, 3, 0, + []{return true;}, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, + []{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)) && logic->HasItem(RG_POWER_BRACELET);}, + []{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 false;}, + []{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)) && logic->HasItem(RG_POWER_BRACELET);}, + []{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)) && logic->HasItem(RG_POWER_BRACELET);}, + []{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)) && logic->HasItem(RG_POWER_BRACELET);}, + []{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)) && logic->HasItem(RG_POWER_BRACELET);}, + []{return true;}, + }}, + {RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, {5, 0, 3, 0, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, + []{return (((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_POWER_BRACELET)) || (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)) && logic->HasItem(RG_POWER_BRACELET);}, + []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, + []{return (((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_POWER_BRACELET)) || (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)) && logic->HasItem(RG_POWER_BRACELET);}, + []{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)) && logic->HasItem(RG_POWER_BRACELET);}, + []{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)) && logic->HasItem(RG_POWER_BRACELET);}, + []{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)) && logic->HasItem(RG_POWER_BRACELET);}, + []{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 e290bf26363..f0c5b1af162 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->CanUse(RG_CRAWL) /* && CanClimb*/;}), + Entrance(RR_BOTW_ENTRYWAY, []{return logic->CanUse(RG_CRAWL) && logic->HasItem(RG_CLIMB);}), Entrance(RR_BOTW_PERIMETER, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), }); @@ -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->CanUse(RG_CRAWL);}), //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->CanUse(RG_CRAWL);}), //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;}), }); @@ -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->CanUse(RG_CRAWL) && (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->CanUse(RG_CRAWL) && (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, {}, {}, { @@ -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->CanUse(RG_CRAWL) /* && CanClimb()*/;}), + Entrance(RR_BOTW_ENTRYWAY, []{return logic->CanUse(RG_CRAWL) && (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->CanUse(RG_CRAWL);}), Entrance(RR_BOTW_MQ_NEAR_BOSS_LOWER, []{return logic->CanUse(RG_CRAWL) && logic->Get(LOGIC_BOTW_LOWERED_WATER);}), Entrance(RR_BOTW_MQ_B3, []{return true;}), @@ -354,8 +354,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);}), }); @@ -391,8 +391,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->CanUse(RG_CRAWL) && (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->CanUse(RG_CRAWL) && (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, {}, {}, { @@ -424,7 +424,7 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits - Entrance(RR_BOTW_MQ_PERIMETER, []{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 3b50c4ee902..2e1dfd7d6d5 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, logic->HasItem(RG_OPEN_CHEST)), - LOCATION(RC_DEKU_TREE_LOBBY_LOWER_HEART, true), - LOCATION(RC_DEKU_TREE_LOBBY_UPPER_HEART, logic->CanPassEnemy(RE_BIG_SKULLTULA)), + LOCATION(RC_DEKU_TREE_LOBBY_LOWER_HEART, logic->CanUse(RG_BOOMERANG)), 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()), @@ -33,13 +33,35 @@ 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 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;}), }); + 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);}), // 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, { + //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_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);});}), @@ -49,14 +71,14 @@ 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_OPEN_CHEST)), - LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), - 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_ROOM_SIDE_CHEST, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_OPEN_CHEST)), + 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);}), + Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return true;}), }); areaTable[RR_DEKU_TREE_COMPASS_ROOM] = Region("Deku Tree Compass Room", SCENE_DEKU_TREE, { @@ -86,12 +108,12 @@ void RegionTable_Init_DekuTree() { //Locations LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, logic->HasItem(RG_OPEN_CHEST)), 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 true;}), + 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;}), @@ -187,7 +209,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();});}), }); @@ -201,6 +223,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()), @@ -210,10 +233,8 @@ 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;}), - //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 + 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. 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? }); @@ -233,7 +254,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);}), // 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);}), }); @@ -296,8 +317,8 @@ void RegionTable_Init_DekuTree() { 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 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_EYE_TARGET_ROOM, []{return true;}), + 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, {}, { @@ -323,7 +344,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);});}), @@ -382,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);});}), @@ -449,7 +470,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 c63f14fa48b..46b27b2ba17 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_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->IsAdult ? ED_LONG_JUMPSLASH : ED_BOMB_THROW)), + LOCATION(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, (logic->HasItem(RG_CLIMB) && logic->HasItem(RG_POWER_BRACELET)) || 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());}), @@ -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()), @@ -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/fire_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp index 1d920817a9e..557ddb180f1 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 @@ -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->HasItem(RG_CLIMB);}), }); areaTable[RR_FIRE_TEMPLE_NARROW_STAIRS] = Region("Fire Temple Narrow Stairs", SCENE_FIRE_TEMPLE, {}, { @@ -630,15 +633,10 @@ 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, true), - LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_RIGHT_HEART, true), - LOCATION(RC_FIRE_TEMPLE_MQ_FIRE_PILLAR_LOWER_HEART, true), - }, { + 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/* && 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);}), }); @@ -658,6 +656,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 @@ -678,8 +677,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);}), }); @@ -688,7 +687,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, {}, {}, { @@ -782,7 +781,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);}), }); @@ -801,7 +800,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, {}, { @@ -996,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 cbdd6896483..7498652d3be 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, logic->HasItem(RG_OPEN_CHEST)), - 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)) && logic->HasItem(RG_OPEN_CHEST)), + 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;}), @@ -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->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_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_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_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,11 +133,11 @@ 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;}), - 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 +213,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) || 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, {}, {}, { @@ -231,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_MIDDLE_BLOCK_PUSH_ROOM, []{return logic->HasItem(RG_GORONS_BRACELET);}), + 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);}), }); @@ -254,7 +268,13 @@ void RegionTable_Init_ForestTemple() { 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);}), }); @@ -267,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, {}, { @@ -276,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, { @@ -399,7 +419,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)) && logic->HasItem(RG_OPEN_CHEST)), + 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)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, []{return true;}), @@ -467,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_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_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);});}), }); @@ -538,10 +586,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 +606,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 +616,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_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_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()));}), + 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));}), + }); + + 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, { @@ -609,8 +666,8 @@ 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_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_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) || (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/location_access/dungeons/gerudo_training_ground.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp index 6c3b3fdbdbf..46cff241abf 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)) && logic->HasItem(RG_OPEN_CHEST)), + 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)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 4) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 6) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 7) && logic->HasItem(RG_OPEN_CHEST)), @@ -203,7 +203,7 @@ void RegionTable_Init_GerudoTrainingGround() { //Locations LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, logic->HasItem(RG_OPEN_CHEST)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, (ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + 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)) && logic->HasItem(RG_OPEN_CHEST)), }, { //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 9b6853518f2..32b888d8749 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->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);}), //Adult can barely reach it with BGS, but it's finnicky enough to be a trick, and too niche to be worth adding yet (only relevant in doorsanity) Entrance(RR_JABU_JABUS_BELLY_LIFT_ROOM, []{return logic->CanHitSwitch(ED_BOMB_THROW);}), }); @@ -248,11 +248,13 @@ 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(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 @@ -342,7 +344,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 logic->HasItem(RG_POWER_BRACELET);}), Entrance(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, []{return logic->Get(LOGIC_JABU_NORTH_TENTACLE);}), @@ -354,8 +356,8 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, logic->HasItem(RG_OPEN_CHEST)), - LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanKillEnemy(RE_LIZALFOS) && logic->HasItem(RG_OPEN_CHEST)), - LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, (logic->CanUse(RG_SONG_OF_TIME) && (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) || logic->HasItem(RG_POWER_BRACELET))) || (ctx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, (logic->IsAdult || logic->HasItem(RG_CLIMB)) && logic->CanKillEnemy(RE_LIZALFOS) && logic->HasItem(RG_OPEN_CHEST)), + 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()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_BOOMERANG_GRASS, logic->CanCutShrubs()), @@ -466,7 +468,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 @@ -536,8 +538,8 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), - 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_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)))) || (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/location_access/dungeons/shadow_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp index 8675d091dd1..6d583a8d9de 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/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index 4c9221eff65..703c21a3162 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->CanUse(RG_CRAWL);}), @@ -81,20 +82,23 @@ 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);}), + 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() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE_TORCHES) && logic->HasItem(RG_OPEN_CHEST)), // 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);}), 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)), }, { @@ -121,7 +125,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, {}, { @@ -130,12 +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) && logic->HasItem(RG_OPEN_CHEST);})), 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;}), - ///*CanClimbHigh() &&*/ (HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))) - 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, {}, {}, { @@ -171,7 +174,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);}), }); @@ -187,7 +190,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, {}, { @@ -260,7 +263,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 @@ -274,8 +277,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() &&*/ logic->HasItem(RG_POWER_BRACELET) ? 2 : 3)) || - (/*CanClimb() &&*/ logic->HasItem(RG_POWER_BRACELET) && 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)) && logic->HasItem(RG_POWER_BRACELET) ? 2 : 3)) || + ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_POWER_BRACELET) && 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, {}, {}, { @@ -356,7 +359,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) && logic->HasItem(RG_OPEN_CHEST)/* && 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)) && logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}), @@ -453,9 +456,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, {}, { @@ -675,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, {}, { @@ -767,7 +769,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 @@ -890,7 +892,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;}), }); @@ -932,7 +934,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);}), }); @@ -1023,13 +1025,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) || logic->CanUse(RG_SKULL_MASK)/*) && CanClimbHigh()*/;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER, []{return (logic->CanKillEnemy(RE_KEESE) || logic->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) || logic->CanUse(RG_SKULL_MASK)) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}), }, {}, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_BASE, []{return true;}), @@ -1128,7 +1130,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)), 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 60880e2013e..d707aa8c817 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp @@ -12,48 +12,91 @@ 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_HYRULE_CASTLE_GROUNDS] = Region("Hyrule Castle Grounds", SCENE_HYRULE_CASTLE, { + areaTable[RR_HC_GATE] = Region("Hyrule Castle Gate", SCENE_HYRULE_CASTLE, { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy() || logic->CanUse(RG_STICKS);}), EventAccess(LOGIC_BUG_ACCESS, []{return logic->HasItem(RG_POWER_BRACELET);}), }, { //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_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_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_HC_ABOVE_VINE] = Region("Hyrule Castle Above Vine", SCENE_HYRULE_CASTLE, { + //Events + 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)), + LOCATION(RC_HC_MALON_GOSSIP_STONE, true), + }, { + //Exits + Entrance(RR_HC_GATE, []{return true;}), + Entrance(RR_HC_PAST_GATE, []{return true;}), + }); + + 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);}), + Entrance(RR_HC_GREAT_FAIRY_FOUNTAIN, []{return logic->BlastOrSmash() && logic->CanUse(RG_CRAWL);}), + }); + + 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_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()), - 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_CASTLE_GROUNDS, []{return true;}), - Entrance(RR_HC_LEDGE, []{return (logic->CanUse(RG_WEIRD_EGG) && logic->HasItem(RG_POWER_BRACELET)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}), - Entrance(RR_HC_GREAT_FAIRY_FOUNTAIN, []{return logic->CanUse(RG_CRAWL) && logic->BlastOrSmash();}), - Entrance(RR_HC_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), + 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) && logic->HasItem(RG_POWER_BRACELET)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->TakeDamage() && logic->HasExplosives() && logic->CanJumpslash());}), }); - areaTable[RR_HC_LEDGE] = Region("HC Ledge", SCENE_HYRULE_CASTLE, {}, {}, { + areaTable[RR_HC_DRAIN_LEDGE] = Region("Hyrule Castle Drain Ledge", SCENE_HYRULE_CASTLE, {}, {}, { //Exits - Entrance(RR_HYRULE_CASTLE_GROUNDS, []{return true;}), - Entrance(RR_HC_GARDEN, []{return logic->CanUse(RG_CRAWL);}), + Entrance(RR_HC_MOAT, []{return true;}), + Entrance(RR_HC_GARDEN, []{return logic->CanUse(RG_CRAWL);}), }); areaTable[RR_HC_GARDEN] = Region("HC Garden", SCENE_CASTLE_COURTYARD_ZELDA, {}, { @@ -62,7 +105,7 @@ void RegionTable_Init_CastleGrounds() { LOCATION(RC_SONG_FROM_IMPA, true), }, { //Exits - Entrance(RR_HC_LEDGE, []{return true;}), // if this ever gets shuffled leaving garden area should come out crawlspace + Entrance(RR_HC_DRAIN_LEDGE, []{return true;}), // if this ever gets shuffled leaving garden area should come out crawlspace }); areaTable[RR_HC_GREAT_FAIRY_FOUNTAIN] = Region("HC Great Fairy Fountain", SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, {}, { @@ -70,7 +113,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, {}, { @@ -78,7 +121,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();}), }); @@ -125,8 +168,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/location_access/overworld/death_mountain_crater.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp index 6b19d2342a0..7c54b069fbd 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));}), }); @@ -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, {}, { @@ -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 07169798528..baecc3b6cf5 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))) && logic->HasItem(RG_OPEN_CHEST)), 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,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_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_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)))), + }, { + //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_ROCKFALL, []{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_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 e5a6b0cd25b..c31b533522c 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->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()), @@ -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->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,14 +134,14 @@ 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->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_GF_TO_GTG, []{return logic->IsAdult && ctx->GetTrickOption(RT_GF_LEDGE_CLIP_INTO_GTG).Get();}), }); 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/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp index c299eb51f7a..2bdee3085cb 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -10,16 +10,18 @@ void RegionTable_Init_GerudoValley() { EventAccess(LOGIC_BUG_ACCESS, []{return logic->IsChild && logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations - LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), + LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), }, { //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, { @@ -27,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_BRONZE_SCALE) || 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 @@ -48,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);}), @@ -62,7 +80,7 @@ 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);}), }); @@ -78,12 +96,13 @@ void RegionTable_Init_GerudoValley() { 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/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp index 845188fd50a..7de7da9c872 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, logic->HasItem(RG_OPEN_CHEST)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index 7b24a6e12b0..d0b14b85577 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -15,8 +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)), - // RANDOTODO Readd chickens to rando settings - LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay && logic->HasItem(RG_POWER_BRACELET) && logic->CanBreakCrates()), + LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay && logic->HasItem(RG_CLIMB) && logic->HasItem(RG_POWER_BRACELET) && logic->CanBreakCrates()), // RANDOTODO adjust requirements to cucco settings 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 @@ -24,7 +23,7 @@ void RegionTable_Init_Kakariko() { LOCATION(RC_KAK_GS_SKULLTULA_HOUSE, logic->IsChild && logic->CanGetNightTimeGS() && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))), LOCATION(RC_KAK_GS_GUARDS_HOUSE, logic->IsChild && logic->CanGetNightTimeGS() && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))), LOCATION(RC_KAK_GS_TREE, logic->IsChild && logic->CanGetNightTimeGS() && logic->CanBonkTrees() && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))), - 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()), @@ -74,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->HasItem(RG_POWER_BRACELET)) || (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;}), @@ -280,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 b20e7b4fbbd..f35f60d1925 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -19,8 +19,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), @@ -37,7 +35,6 @@ void RegionTable_Init_KokiriForest() { 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()), @@ -73,16 +70,16 @@ void RegionTable_Init_KokiriForest() { }, { //Exits Entrance(RR_KF_BOULDER_LOOP, []{return logic->CanUse(RG_CRAWL);}), - Entrance(RR_KF_LINKS_HOUSE, []{return true;}), + 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_THE_LOST_WOODS, []{return true;}), + 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_BOULDER_LOOP] = Region("KF Boulder Loop", SCENE_KOKIRI_FOREST, {}, { @@ -118,13 +115,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, {}, { @@ -182,6 +184,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, {}, { + //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, logic->HasItem(RG_OPEN_CHEST)), @@ -197,7 +232,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 12eaa832091..f7b8802daeb 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 cfeeff380cc..e54642e7544 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 b838e890c5e..3d5c12f9115 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,50 @@ 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;}), + // 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();}), }); + 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 +71,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 d1399d86ec6..7f7d543f135 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 1a99063ea69..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)))*/;}), + 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();}), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 7efa98aeb88..9935d9f63a4 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -253,6 +253,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_CRAWL: return CheckRandoInf(RAND_INF_CAN_CRAWL); case RG_OPEN_CHEST: @@ -1758,6 +1760,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_CRAWL: SetRandoInf(RAND_INF_CAN_CRAWL, state); break; @@ -2539,10 +2544,6 @@ bool Logic::IsReverseAccessPossible() { (ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES)))); } -bool Logic::SpiritSunOnFloorToStatue() { - return /*CanClimbHigh() &&*/ (HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS))); -} - bool Logic::SpiritExplosiveKeyLogic() { return SmallKeys(SCENE_SPIRIT_TEMPLE, HasExplosives() ? 1 : 2); } @@ -2578,7 +2579,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() { @@ -2614,7 +2615,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()*/ && HasItem(RG_POWER_BRACELET) && + return HasExplosives() && (HasItem(RG_CLIMB) || CanUse(RG_LONGSHOT)) && HasItem(RG_POWER_BRACELET) && SmallKeys(SCENE_SPIRIT_TEMPLE, HasItem(RG_LONGSHOT) ? 3 : 5); } @@ -2628,8 +2629,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*/) { @@ -2657,16 +2660,21 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { SetRandoInf(RAND_INF_CAN_SWIM, true); } - // If we're not shuffling crawl, we start with it - if (ctx->GetOption(RSK_SHUFFLE_CRAWL).Is(false)) { - SetRandoInf(RAND_INF_CAN_CRAWL, true); - } - // If we're not shuffling grab, we start with it if (ctx->GetOption(RSK_SHUFFLE_GRAB).Is(false)) { SetRandoInf(RAND_INF_CAN_GRAB, 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 crawl, we start with it + if (ctx->GetOption(RSK_SHUFFLE_CRAWL).Is(false)) { + SetRandoInf(RAND_INF_CAN_CRAWL, true); + } + // If we're not shuffling open chest, we start with it if (ctx->GetOption(RSK_SHUFFLE_OPEN_CHEST).Is(false)) { SetRandoInf(RAND_INF_CAN_OPEN_CHEST, true); 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/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 1b5d7166bdf..f9146bf8b36 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -258,9 +258,10 @@ 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_CRAWL] = "Shuffles the ability to use crawlspaces into the item pool."; mOptionDescriptions[RSK_SHUFFLE_GRAB] = "Shuffle the ability to grab as a progressive upgrade before Goron Bracelet."; + mOptionDescriptions[RSK_SHUFFLE_CLIMB] = "Shuffle the ability to climb ladders into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_CRAWL] = "Shuffles the ability to use crawlspaces into the item pool."; mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST] = "Shuffles the ability to open chests 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" diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index d07704566c3..affc1c4978f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -12,7 +12,6 @@ #include "3drando/random.hpp" #include "soh/ResourceManagerHelpers.h" #include "soh/SohGui/SohGui.hpp" -#include "3drando/custom_messages.hpp" #include #include #include "../custom-message/CustomMessageTypes.h" @@ -125,6 +124,7 @@ std::map randomizerGetToRandInf = { { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }, { RG_BRONZE_SCALE, RAND_INF_CAN_SWIM }, { RG_POWER_BRACELET, RAND_INF_CAN_GRAB }, + { RG_CLIMB, RAND_INF_CAN_CLIMB }, { RG_CRAWL, RAND_INF_CAN_CRAWL }, { RG_OPEN_CHEST, RAND_INF_CAN_OPEN_CHEST }, { RG_QUIVER_INF, RAND_INF_HAS_INFINITE_QUIVER }, diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 67c1956026c..b2211cad9c3 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -316,6 +316,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, @@ -531,6 +532,7 @@ typedef enum { RR_NOCTURNE_OF_SHADOW_WARP, RR_PRELUDE_OF_LIGHT_WARP, RR_KOKIRI_FOREST, + RR_KF_LINKS_PORCH, RR_KF_BOULDER_LOOP, RR_KF_LINKS_HOUSE, RR_KF_MIDOS_HOUSE, @@ -539,6 +541,8 @@ typedef enum { RR_KF_KNOW_IT_ALL_HOUSE, 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, @@ -549,11 +553,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, @@ -573,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, @@ -637,9 +647,13 @@ typedef enum { RR_TOT_BEYOND_DOOR_OF_TIME, RR_CASTLE_GROUNDS, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, - RR_HYRULE_CASTLE_GROUNDS, - RR_HC_LEDGE, + RR_HC_GATE, + 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, RR_HC_STORMS_GROTTO, RR_HC_STORMS_GROTTO_BEHIND_WALLS, @@ -676,6 +690,7 @@ typedef enum { RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_GRAVEYARD_WARP_PAD_REGION, RR_DEATH_MOUNTAIN_TRAIL, + RR_DEATH_MOUNTAIN_ROCKFALL, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_OWL_FLIGHT, RR_DMT_GREAT_FAIRY_FOUNTAIN, @@ -699,6 +714,7 @@ 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, @@ -741,6 +757,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, @@ -891,6 +909,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, @@ -904,9 +923,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, @@ -929,15 +950,18 @@ 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, 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, @@ -4608,8 +4632,9 @@ typedef enum { RG_HINT, RG_TYCOON_WALLET, RG_BRONZE_SCALE, - RG_CRAWL, RG_POWER_BRACELET, + RG_CLIMB, + RG_CRAWL, RG_OPEN_CHEST, RG_CHILD_WALLET, RG_PROGRESSIVE_BOMBCHU_BAG, @@ -5826,6 +5851,7 @@ typedef enum { RHT_MASK_ZORA, RHT_MASK_GERUDO, RHT_MASK_TRUTH, + RHT_CLIMB, RHT_CRAWL, RHT_OPEN_CHEST, RHT_FISHING_POLE, @@ -6423,8 +6449,9 @@ typedef enum { RSK_SHUFFLE_OCARINA, RSK_SHUFFLE_OCARINA_BUTTONS, RSK_SHUFFLE_SWIM, - RSK_SHUFFLE_CRAWL, RSK_SHUFFLE_GRAB, + RSK_SHUFFLE_CLIMB, + RSK_SHUFFLE_CRAWL, RSK_SHUFFLE_OPEN_CHEST, RSK_STARTING_DEKU_SHIELD, RSK_STARTING_KOKIRI_SWORD, diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 92f0929087b..de7b8750c29 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_CAN_CRAWL) DEFINE_RAND_INF(RAND_INF_CAN_GRAB) DEFINE_RAND_INF(RAND_INF_CAN_OPEN_CHEST) diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index bd449227517..665ffedfe6c 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -313,14 +313,18 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetRandomizerInf(RAND_INF_CAN_SWIM); } - if (Randomizer_GetSettingValue(RSK_SHUFFLE_CRAWL) == RO_GENERIC_OFF) { - Flags_SetRandomizerInf(RAND_INF_CAN_CRAWL); - } - if (Randomizer_GetSettingValue(RSK_SHUFFLE_GRAB) == RO_GENERIC_OFF) { Flags_SetRandomizerInf(RAND_INF_CAN_GRAB); } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CLIMB) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_CLIMB); + } + + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CRAWL) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_CRAWL); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_OPEN_CHEST) == RO_GENERIC_OFF) { Flags_SetRandomizerInf(RAND_INF_CAN_OPEN_CHEST); } diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index b89eed82e8a..51571b56c9f 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -785,8 +785,9 @@ 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_GRAB, "Shuffle Grab", CVAR_RANDOMIZER_SETTING("ShuffleGrab"), mOptionDescriptions[RSK_SHUFFLE_GRAB]); + OPT_BOOL(RSK_SHUFFLE_CLIMB, "Shuffle Climb", CVAR_RANDOMIZER_SETTING("ShuffleClimb"), mOptionDescriptions[RSK_SHUFFLE_CLIMB]); OPT_BOOL(RSK_SHUFFLE_CRAWL, "Shuffle Crawl", CVAR_RANDOMIZER_SETTING("ShuffleCrawl"), mOptionDescriptions[RSK_SHUFFLE_CRAWL]); + OPT_BOOL(RSK_SHUFFLE_GRAB, "Shuffle Grab", CVAR_RANDOMIZER_SETTING("ShuffleGrab"), mOptionDescriptions[RSK_SHUFFLE_GRAB]); OPT_BOOL(RSK_SHUFFLE_OPEN_CHEST, "Shuffle Open Chest", CVAR_RANDOMIZER_SETTING("ShuffleOpenChest"), mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST]); 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]); @@ -1712,8 +1713,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, " @@ -2400,6 +2401,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], &mOptions[RSK_SHUFFLE_GRAB], + &mOptions[RSK_SHUFFLE_CLIMB], &mOptions[RSK_SHUFFLE_CRAWL], &mOptions[RSK_SHUFFLE_OPEN_CHEST], &mOptions[RSK_SHUFFLE_BEAN_SOULS], @@ -2621,6 +2623,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], &mOptions[RSK_SHUFFLE_GRAB], + &mOptions[RSK_SHUFFLE_CLIMB], &mOptions[RSK_SHUFFLE_CRAWL], &mOptions[RSK_SHUFFLE_OPEN_CHEST], &mOptions[RSK_SHUFFLE_WEIRD_EGG], 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 8324ee83ad2..5a027c32386 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -13401,6 +13401,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;