diff --git a/soh/soh/Enhancements/SkipAmyPuzzle.cpp b/soh/soh/Enhancements/SkipAmyPuzzle.cpp index 27486e04cde..8409390efa3 100644 --- a/soh/soh/Enhancements/SkipAmyPuzzle.cpp +++ b/soh/soh/Enhancements/SkipAmyPuzzle.cpp @@ -1,8 +1,14 @@ #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/ShipInit.hpp" +extern "C" { +#include "functions.h" +extern SaveContext gSaveContext; +} + void RegisterSkipAmyPuzzle() { - COND_VB_SHOULD(VB_AMY_SOLVE, CVarGetInteger(CVAR_ENHANCEMENT("SkipAmyPuzzle"), 0), { *should = true; }); + COND_VB_SHOULD(VB_AMY_SOLVE, CVarGetInteger(CVAR_ENHANCEMENT("SkipAmyPuzzle"), 0), + { *should = !IS_RANDO || Flags_GetRandomizerInf(RAND_INF_CAN_GRAB); }); } static RegisterShipInitFunc initFunc(RegisterSkipAmyPuzzle, { CVAR_ENHANCEMENT("SkipAmyPuzzle") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index b561985edd1..5140c1dfbcf 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -1838,6 +1838,14 @@ typedef enum { // - None VB_PREVENT_ADULT_STICK, + // #### `result` + // ```c + // varies + // ``` + // #### `args` + // - None + VB_PREVENT_STRENGTH, + // #### `result` // ```c // true diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 710869d8128..2492fed1121 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -173,7 +173,6 @@ void GenerateItemPool() { AddItemToPool(RG_GREG_RUPEE, 1, 1, 1, 1); AddItemToPool(RG_PROGRESSIVE_HOOKSHOT, 2, 2, 2, 2); AddItemToPool(RG_HYLIAN_SHIELD, 1, 1, 1, 1); - AddItemToPool(RG_PROGRESSIVE_STRENGTH, 4, 3, 3, 3); AddItemToPool(RG_DOUBLE_DEFENSE, 2, 1, 0, 0); bool isScrubs = ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_ALL); AddFixedItemToPool(RG_DEKU_SHIELD, isScrubs ? 1 : 2); @@ -387,6 +386,9 @@ 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_BEEHIVES)) { PlaceItemsForType(RCTYPE_BEEHIVE, true, true); } diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 7774125bccd..b0dd0a71d9b 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -14,6 +14,7 @@ extern "C" { #include "dungeon.h" #include "objects/object_gi_key/object_gi_key.h" #include "objects/object_gi_bosskey/object_gi_bosskey.h" +#include "objects/object_gi_bracelet/object_gi_bracelet.h" #include "objects/object_gi_compass/object_gi_compass.h" #include "objects/object_gi_map/object_gi_map.h" #include "objects/object_gi_hearts/object_gi_hearts.h" @@ -1121,6 +1122,22 @@ extern "C" void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getIte CLOSE_DISPS(play->state.gfxCtx); } +extern "C" void Randomizer_DrawPowerBracelet(PlayState* play, GetItemEntry* getItemEntry) { + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + 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_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry) { Vec3f pos; OPEN_DISPS(play->state.gfxCtx); diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index 3830fdcebf4..4b74e2be150 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -22,6 +22,7 @@ void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawPowerBracelet(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry* getItemEntry); diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 8f73310266a..5f42b3aa096 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -1045,6 +1045,13 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l *should = false; break; } + case VB_PREVENT_STRENGTH: { + if (!Flags_GetRandomizerInf(RAND_INF_CAN_GRAB)) { + GET_PLAYER(gPlayState)->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY; + *should = true; + } + break; + } case VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED: { *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); break; diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 08539f9ffc7..c11c995fab5 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -270,6 +270,10 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio } break; case RG_PROGRESSIVE_STRENGTH: + if (!logic->CheckRandoInf(RAND_INF_CAN_GRAB)) { + actual = RG_POWER_BRACELET; + break; + } switch (logic->CurrentUpgrade(UPG_STRENGTH)) { case 0: actual = RG_GORONS_BRACELET; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index bfd487ed658..daffaf13eb2 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -369,10 +369,13 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "C-Rechts-Taste der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_RIGHT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_NONE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); - itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_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_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_PROGRESSIVE_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag); 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); diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index 05f3851ddc2..f3481eacab1 100644 --- a/soh/soh/Enhancements/randomizer/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/location_access.cpp @@ -626,20 +626,20 @@ std::array areaTable; // clang-format off std::map Region::spiritLogicData = { //Vanilla Child uses ExplosiveKeyLogic here because they need to exist for shared adult checks - {RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, {5, 0, 3, 0, []{return true;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;}}}, - {RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, {5, 0, 3, 0, []{return true/*logic->CanClimbHigh()*/;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;}}}, - {RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, {5, 0, 3, 0, []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritSunOnFloorToStatue();}, []{return true/*logic->CanClimbHigh()*/;}, []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}}}, - {RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh()*/;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;}}}, - {RR_SPIRIT_TEMPLE_INNER_WEST_HAND, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh()*/;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;}}}, - {RR_SPIRIT_TEMPLE_GS_LEDGE, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->SpiritWestToSkull()/* && logic->CanClimbHigh()*/;}, []{return logic->SpiritExplosiveKeyLogic() && logic->SpiritWestToSkull()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SpiritWestToSkull()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;}}}, - {RR_SPIRIT_TEMPLE_STATUE_ROOM, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic();}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true;}}}, + {RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, {5, 0, 3, 0, []{return true;}, []{return logic->SpiritExplosiveKeyLogic() && logic->HasItem(RG_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->CanClimbHigh() && str0*/;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*((logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)) && str0) || (logic->CanKillEnemy(RE_BEAMOS) && logic->CanUse(RG_LONGSHOT))*/;}}}, - {RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SpiritExplosiveKeyLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return true/*((logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)) && str0) || (logic->CanKillEnemy(RE_BEAMOS) && logic->CanUse(RG_LONGSHOT))*/;}}}, + {RR_SPIRIT_TEMPLE_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 true/*logic->CanClimbHigh() && str0*/;}, []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}}}, - {RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT)/* && logic->CanClimbHigh()*/;}, []{return true/*logic->CanClimbHigh() && str0*/;}, []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}}}, - {RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT) && logic->SpiritEastToSwitch();}, []{return logic->SpiritEastToSwitch()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SpiritEastToSwitch() && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}}}, + {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))*/;}}}, @@ -648,7 +648,7 @@ std::map Region::spiritLogicData = { {RR_SPIRIT_TEMPLE_MQ_INNER_RIGHT_HAND, {7, 0, 0, 0, []{return logic->CanHitSwitch() && logic->MQSpiritWestToPots()/* && logic->CanClimbHigh()*/;}, []{return logic->MQSpiritWestToPots()/* && logic->Climb*/;}, []{return /*logic->CanUse(RG_HOVER_BOOTS) || (logic->CanClimb() && */logic->MQSpiritWestToPots()/*)*/;}}}, {RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, {7, 0, 0, 0, []{return logic->CanHitSwitch()/* && logic->CanClimbHigh()*/;}, []{return true;}, []{return true;}}}, {RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, {7, 0, 0, 0, []{return logic->CanHitSwitch() && logic->MQSpiritStatueToSunBlock()/* && logic->CanClimbHigh()*/;}, []{return logic->MQSpiritStatueToSunBlock()/* && logic->Climb*/;}, []{return logic->MQSpiritStatueToSunBlock()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;}}}, - {RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, {7, 7, 4, 4, []{return logic->CanHitSwitch() && logic->OuterWestHandMQLogic()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->OuterWestHandMQLogic();}, []{return logic->OuterWestHandMQLogic();}}}, + {RR_SPIRIT_TEMPLE_MQ_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();});}}}, }; 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 2c3f17e77e5..ea9f7a76ef2 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 @@ -288,7 +288,7 @@ void RegionTable_Init_BottomOfTheWell() { (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))/*&& CanClimb()*/);}), Entrance(RR_BOTW_MQ_CORNER_CRAWLSPACE, []{return logic->IsChild/*CanCrawl()*/;}), Entrance(RR_BOTW_MQ_NEAR_BOSS_LOWER, []{return logic->IsChild/*CanCrawl()*/ && logic->Get(LOGIC_BOTW_LOWERED_WATER);}), - Entrance(RR_BOTW_MQ_B3, []{return true;}), + Entrance(RR_BOTW_MQ_B3, []{return true;}), }); areaTable[RR_BOTW_MQ_MIDDLE] = Region("Bottom of the Well MQ Middle", SCENE_BOTTOM_OF_THE_WELL, {}, { @@ -303,8 +303,8 @@ void RegionTable_Init_BottomOfTheWell() { Entrance(RR_BOTW_MQ_PERIMETER, []{return logic->Get(LOGIC_BOTW_MQ_OPENED_GATES);}), Entrance(RR_BOTW_MQ_PIT_CAGE, []{return (bool)ctx->GetTrickOption(RT_BOTW_PITS);}), Entrance(RR_BOTW_MQ_B3_PLATFORM, []{return logic->Get(LOGIC_BOTW_MQ_OPENED_MIDDLE_HOLE);}), - Entrance(RR_BOTW_MQ_B3, []{return true;}), - Entrance(RR_BOTW_MQ_INVISIBLE_PATH, []{return true/*str0 or CanHitSwitch(ED_BOMB_THROW)*/;}), + Entrance(RR_BOTW_MQ_B3, []{return true;}), + Entrance(RR_BOTW_MQ_INVISIBLE_PATH, []{return logic->HasItem(RG_POWER_BRACELET) || logic->CanHitSwitch(ED_BOMB_THROW);}), Entrance(RR_BOTW_MQ_GRAVE_ROOM, []{return logic->Get(LOGIC_BOTW_MQ_OPENED_WEST_ROOM);}), }); @@ -317,8 +317,8 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_POT_3, logic->CanBreakPots()), }, { //Exits - Entrance(RR_BOTW_MQ_MIDDLE, []{return true;}), - Entrance(RR_BOTW_MQ_B3, []{return true;}), + Entrance(RR_BOTW_MQ_MIDDLE, []{return true;}), + Entrance(RR_BOTW_MQ_B3, []{return true;}), }); areaTable[RR_BOTW_MQ_GRAVE_ROOM] = Region("Bottom of the Well Grave Room", 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 0ea102d6632..73471a045d8 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -120,7 +120,7 @@ void RegionTable_Init_DekuTree() { }, { //Exits Entrance(RR_DEKU_TREE_BASEMENT_WATER_ROOM_FRONT, []{return logic->HasItem(RG_BRONZE_SCALE) || ctx->GetTrickOption(RT_DEKU_B1_BACKFLIP_OVER_SPIKED_LOG);}), - Entrance(RR_DEKU_TREE_BASEMENT_TORCH_ROOM, []{return true;}), + Entrance(RR_DEKU_TREE_BASEMENT_TORCH_ROOM, []{return logic->IsAdult || logic->HasItem(RG_POWER_BRACELET);}), }); areaTable[RR_DEKU_TREE_BASEMENT_TORCH_ROOM] = Region("Deku Tree Basement Torch Room", SCENE_DEKU_TREE, { @@ -164,7 +164,7 @@ void RegionTable_Init_DekuTree() { //Events EventAccess(LOGIC_STICK_ACCESS, []{return logic->CanGetDekuBabaSticks();}), EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), - EventAccess(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK, []{return true;}), + EventAccess(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK, []{return logic->HasItem(RG_POWER_BRACELET);}), }, {}, { //Exits Entrance(RR_DEKU_TREE_BASEMENT_LOWER, []{return true;}), @@ -416,7 +416,7 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_BASEMENT_LEDGE] = Region("Deku Tree MQ Basement Ledge", SCENE_DEKU_TREE, { //Events - EventAccess(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK, []{return true;}), + EventAccess(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK, []{return logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations LOCATION(RC_DEKU_TREE_MQ_DEKU_SCRUB, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()), @@ -427,9 +427,8 @@ void RegionTable_Init_DekuTree() { //Exits Entrance(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, []{return logic->IsChild;}), Entrance(RR_DEKU_TREE_MQ_BASEMENT, []{return true;}), - //If strength 0 is shuffled, add hovers or block push to the stick check //recoiling to skip swim is possible, but would be a trick - Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, []{return AnyAgeTime([]{return logic->HasFireSource() || (/*logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) && */logic->CanUse(RG_STICKS));}) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS));}), + Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, []{return AnyAgeTime([]{return logic->HasFireSource() || ((logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_STICKS));}) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS));}), }); areaTable[RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM] = Region("Deku Tree MQ Outside Boss Room", SCENE_DEKU_TREE, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp index 9e3f3efe25a..5c5c8ed1c70 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp @@ -55,7 +55,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_SE_CORRIDOR] = Region("Dodongos Cavern SE Corridor", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_GS_SCARECROW, logic->ReachScarecrow() || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_DC_SCARECROW_GS) && logic->CanKillEnemy(RE_GOLD_SKULLTULA))), + LOCATION(RC_DODONGOS_CAVERN_GS_SCARECROW, logic->ReachScarecrow() || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_DC_SCARECROW_GS) && logic->HasItem(RG_POWER_BRACELET) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA))), LOCATION(RC_DODONGOS_CAVERN_SIDE_ROOM_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_SIDE_ROOM_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_SIDE_ROOM_POT_3, logic->CanBreakPots()), @@ -66,8 +66,8 @@ void RegionTable_Init_DodongosCavern() { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, []{return true;}), //Shield seems to be in logic to drop a pot on their head as they hit you to blow up the wall - Entrance(RR_DODONGOS_CAVERN_SE_ROOM, []{return AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->CanAttack() || (logic->TakeDamage() && logic->CanShield());});}), - Entrance(RR_DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, []{return true;}), + Entrance(RR_DODONGOS_CAVERN_SE_ROOM, []{return AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->CanAttack() || (logic->TakeDamage() && logic->CanShield() && logic->HasItem(RG_POWER_BRACELET));});}), + Entrance(RR_DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, []{return logic->HasItem(RG_POWER_BRACELET);}), }); areaTable[RR_DODONGOS_CAVERN_SE_ROOM] = Region("Dodongos Cavern SE Room", SCENE_DODONGOS_CAVERN, {}, { @@ -156,13 +156,14 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_ARMOS_ROOM] = Region("Dodongos Cavern Armos Room", SCENE_DODONGOS_CAVERN, {}, {}, { //Exits Entrance(RR_DODONGOS_CAVERN_STAIRS_UPPER, []{return true;}), - Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return true;}), + Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return logic->IsAdult || (logic->HasItem(RG_POWER_BRACELET) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS));}), }); + // TODO split into 2 areas, need adult or power bracelet to reach lower area by bomb chest areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER] = Region("Dodongos Cavern Bomb Room Lower", SCENE_DODONGOS_CAVERN, {}, { //Locations LOCATION(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, true), - LOCATION(RC_DODONGOS_CAVERN_BLADE_ROOM_HEART, true), + LOCATION(RC_DODONGOS_CAVERN_BLADE_ROOM_HEART, logic->HasItem(RG_POWER_BRACELET)), LOCATION(RC_DODONGOS_CAVERN_FIRST_BRIDGE_GRASS, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_BLADE_GRASS, logic->CanCutShrubs()), }, { @@ -258,7 +259,7 @@ void RegionTable_Init_DodongosCavern() { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, []{return true;}), Entrance(RR_DODONGOS_CAVERN_BACK_ROOM, []{return AnyAgeTime([]{return logic->CanBreakMudWalls();});}), - Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, []{return true;}), + Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, []{return logic->HasItem(RG_POWER_BRACELET);}), }); areaTable[RR_DODONGOS_CAVERN_BACK_ROOM] = Region("Dodongos Cavern Back Room", SCENE_DODONGOS_CAVERN, {}, { @@ -412,10 +413,10 @@ void RegionTable_Init_DodongosCavern() { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->TakeDamage();}), Entrance(RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM, []{return true;}), - Entrance(RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM, []{return logic->HasFireSourceWithTorch();}),//torch checks here need strength 0 with sticks when that is implemented + Entrance(RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM, []{return logic->HasFireSource() || (logic->CanUse(RG_STICKS) && logic->HasItem(RG_POWER_BRACELET));}), Entrance(RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM, []{return AnyAgeTime([]{return logic->HasFireSourceWithTorch();});}), //Includes an implied CanPass(RE_BIG_SKULLTULA) //Bunny hood jump can make it as child - Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, []{return (logic->IsAdult && (true /* str0 */ || ctx->GetTrickOption(RT_DC_JUMP) || logic->CanGroundJump())) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, []{return (logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || ctx->GetTrickOption(RT_DC_JUMP) || logic->CanGroundJump())) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return logic->CanUse(RG_STICKS) && logic->HasItem(RG_GORONS_BRACELET);}), //Implies access to RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM from here }); @@ -426,7 +427,7 @@ void RegionTable_Init_DodongosCavern() { }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), - Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return (logic->HasFireSource() && logic->HasItem(RG_GORONS_BRACELET)) || logic->CanBreakMudWalls();}), //Requires str0, If you can somehow warp into this room, add logic->CanPassEnemy(RE_BIG_SKULLTULA) + Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return (logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS)) && ((logic->HasFireSource() && logic->HasItem(RG_GORONS_BRACELET)) || logic->CanBreakMudWalls());}), // If you can somehow warp into this room, add logic->CanPassEnemy(RE_BIG_SKULLTULA) }); areaTable[RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM] = Region("Dodongos Cavern MQ Larvae Room", SCENE_DODONGOS_CAVERN, {}, { @@ -560,9 +561,7 @@ void RegionTable_Init_DodongosCavern() { }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return true;}), - //using pots to get past the fire is in default logic. if str0 gets added, this will need to be: - //str0 || explosives, or projectiles if str0 isn't needed to pull graves (it's a narrow shot though, may be trick worthy) - Entrance(RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE, []{return true;}), + Entrance(RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE, []{return logic->HasItem(RG_POWER_BRACELET) || logic->HasExplosives();}), Entrance(RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE, []{return logic->IsAdult;}), }); @@ -592,7 +591,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE] = Region("Dodongos Cavern MQ Back Switch Grave", SCENE_DODONGOS_CAVERN, { //Events - EventAccess(LOGIC_DC_MQ_BEHIND_FIRE_SWITCH, []{return true/*str0 || logic->CanHitSwitch() || logic->CanDetonateBombFlowers()*/;}), + EventAccess(LOGIC_DC_MQ_BEHIND_FIRE_SWITCH, []{return logic->HasItem(RG_POWER_BRACELET) || logic->CanHitSwitch() || logic->CanDetonateBombFlowers();}), EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations @@ -603,7 +602,7 @@ void RegionTable_Init_DodongosCavern() { }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE, []{return true;}), - Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, []{return true;}), //if strength 0 prevents grave pulls, add it here + Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, []{return logic->HasItem(RG_POWER_BRACELET);}), }); #pragma endregion 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 82a7c7987b4..a662e09d270 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -155,7 +155,7 @@ void RegionTable_Init_FireTemple() { }, { //Exits Entrance(RR_FIRE_TEMPLE_LAVA_GEYSER_1F, []{return logic->TakeDamage();}), - Entrance(RR_FIRE_TEMPLE_LAVA_GEYSER_2F, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 4) && logic->FireTimer() >= 48/* && str0*/;}), + Entrance(RR_FIRE_TEMPLE_LAVA_GEYSER_2F, []{return logic->FireTimer() >= 48 && logic->HasItem(RG_POWER_BRACELET);}), }); //you can get the hearts with an indirect boomerang from here, but it's a trick @@ -423,7 +423,7 @@ void RegionTable_Init_FireTemple() { //Exits Entrance(RR_FIRE_TEMPLE_TOP_OF_COLLAPSING_STAIRS, []{return logic->Get(LOGIC_FIRE_HIT_STAIRS) && logic->IsAdult;}), // this is here to maintain 1:1 door entrances between regions - Entrance(RR_FIRE_TEMPLE_ABOVE_FIRE_MAZE, []{return logic->Get(LOGIC_FIRE_HIT_STAIRS) && (logic->IsAdult || logic->Get(LOGIC_FIRE_CHILD_AT_TOP_OF_STAIRS))/* && str0*/;}), + Entrance(RR_FIRE_TEMPLE_ABOVE_FIRE_MAZE, []{return logic->Get(LOGIC_FIRE_HIT_STAIRS) && (logic->IsAdult || logic->Get(LOGIC_FIRE_CHILD_AT_TOP_OF_STAIRS)) && logic->HasItem(RG_POWER_BRACELET);}), }); areaTable[RR_FIRE_TEMPLE_ABOVE_FIRE_MAZE] = Region("Fire Temple Above Fire Maze", SCENE_FIRE_TEMPLE, { @@ -761,7 +761,7 @@ void RegionTable_Init_FireTemple() { //Exits Entrance(RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE, []{return true;}), //Assumes maze access - Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SWITCH_DOOR, []{return logic->HasExplosives()/* && str0*/;}), + Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SWITCH_DOOR, []{return logic->HasExplosives() && logic->HasItem(RG_POWER_BRACELET);}), }); areaTable[RR_FIRE_TEMPLE_MQ_ABOVE_MAZE] = Region("Fire Temple MQ Above Maze", SCENE_FIRE_TEMPLE, {}, {}, { @@ -808,7 +808,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_BURNING_BLOCK] = Region("Fire Temple MQ Burning Block", SCENE_FIRE_TEMPLE, {}, { //Locations //There's definitely ways to do this hammerless, but with one points on it's a trick - LOCATION(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOOKSHOT)/* && (str0 || ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION))*/), + LOCATION(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_POWER_BRACELET) || ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION))), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_TORCH_SLUG_CLIMB, []{return true;}), @@ -864,7 +864,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM_ABOVE_CAGE] = Region("Fire Temple MQ High Torch Room Above Cage", SCENE_FIRE_TEMPLE, { //Events - EventAccess(LOGIC_FIRE_MQ_HIGH_TORCH_LIT, []{return ((logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_HOOKSHOT)/*&& str0*/) && logic->FireTimer() >= 48);}), + EventAccess(LOGIC_FIRE_MQ_HIGH_TORCH_LIT, []{return ((logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_POWER_BRACELET)) && logic->FireTimer() >= 48);}), }, { //Locations //Tunic logic for these checks is handled on entry 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 45d7e372bb4..e318d9afaa2 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -347,7 +347,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_GREEN_POE_ROOM] = Region("Forest Temple Green Poe Room", SCENE_FOREST_TEMPLE, { //Events - EventAccess(LOGIC_FOREST_AMY, []{return logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_FOREST_AMY, []{return logic->CanUse(RG_FAIRY_BOW) && logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_GREEN_POE_POT_1, logic->CanBreakPots()), @@ -372,11 +372,11 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_BASEMENT] = Region("Forest Temple Boss Region", SCENE_FOREST_TEMPLE, { //Events - EventAccess(LOGIC_FOREST_OPEN_BOSS_HALLWAY, []{return true;}), + EventAccess(LOGIC_FOREST_OPEN_BOSS_HALLWAY, []{return logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_BASEMENT_CHEST, true), - LOCATION(RC_FOREST_TEMPLE_GS_BASEMENT, logic->HookshotOrBoomerang()), + LOCATION(RC_FOREST_TEMPLE_BASEMENT_CHEST, logic->HasItem(RG_POWER_BRACELET)), + LOCATION(RC_FOREST_TEMPLE_GS_BASEMENT, logic->HasItem(RG_POWER_BRACELET) && logic->HookshotOrBoomerang()), }, { //Exits Entrance(RR_FOREST_TEMPLE_LOBBY, []{return true;}), @@ -687,7 +687,7 @@ void RegionTable_Init_ForestTemple() { LOCATION(RC_FOREST_TEMPLE_MQ_FROZEN_EYE_SWITCH_SMALL_CRATE_3, logic->CanBreakSmallCrates()), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, []{return logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DINS_FIRE);}), + Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, []{return logic->CanUse(logic->HasItem(RG_POWER_BRACELET) ? RG_FAIRY_BOW : RG_FIRE_ARROWS) || logic->CanUse(RG_DINS_FIRE);}), Entrance(RR_FOREST_TEMPLE_MQ_BETH_ROOM, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 6);}), }); @@ -702,7 +702,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_AMY_ROOM] = Region("Forest Temple MQ Amy Room", SCENE_FOREST_TEMPLE, { //Events - EventAccess(LOGIC_FOREST_AMY, []{return logic->CanUse(RG_FAIRY_BOW);}), + EventAccess(LOGIC_FOREST_AMY, []{return logic->CanUse(RG_FAIRY_BOW) && logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations LOCATION(RC_FOREST_TEMPLE_MQ_GREEN_POE_POT_1, logic->CanBreakPots()), @@ -722,14 +722,14 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_BASEMENT] = Region("Forest Temple MQ Basement", SCENE_FOREST_TEMPLE, { //Events //Implies CanHitSwitch() - EventAccess(LOGIC_FOREST_OPEN_BOSS_HALLWAY, []{return logic->CanHitEyeTargets();}), + EventAccess(LOGIC_FOREST_OPEN_BOSS_HALLWAY, []{return logic->HasItem(RG_POWER_BRACELET) && logic->CanHitEyeTargets();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, logic->HasItem(RG_POWER_BRACELET)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, []{return true;}), - Entrance(RR_FOREST_TEMPLE_MQ_BASEMENT_POT_ROOM, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage();}), + Entrance(RR_FOREST_TEMPLE_MQ_BASEMENT_POT_ROOM, []{return logic->HasItem(RG_POWER_BRACELET) && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage());}), Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return logic->Get(LOGIC_FOREST_OPEN_BOSS_HALLWAY);}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp index b96441b31a6..f2e3dabb849 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp @@ -148,14 +148,14 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_WATER_TRIAL_BLOCK_ROOM] = Region("Ganon's Castle Water Trial Block Room", SCENE_INSIDE_GANONS_CASTLE, { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanBreakPots();}), - EventAccess(LOGIC_WATER_TRIAL_RUSTED_SWITCH, []{return (logic->BlueFire() || ctx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_WATER_TRIAL_RUSTED_SWITCH, []{return logic->HasItem(RG_POWER_BRACELET) && (logic->BlueFire() || ctx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER);}), }, { //Locations LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_POT_3, logic->CanBreakPots()), }, { //Exits Entrance(RR_GANONS_CASTLE_WATER_TRIAL_BLUE_FIRE_ROOM, []{return true;}), - Entrance(RR_GANONS_CASTLE_WATER_TRIAL_BLOCK_ROOM_END, []{return logic->IsAdult || logic->CanGroundJump();}), + Entrance(RR_GANONS_CASTLE_WATER_TRIAL_BLOCK_ROOM_END, []{return logic->IsAdult || (logic->HasItem(RG_POWER_BRACELET) && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanGroundJump();}), }); areaTable[RR_GANONS_CASTLE_WATER_TRIAL_BLOCK_ROOM_END] = Region("Ganon's Castle Water Trial Block Room End", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { @@ -472,12 +472,12 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM] = Region("Ganon's Castle MQ Water Trial Block Room", SCENE_INSIDE_GANONS_CASTLE, { //Events - EventAccess(LOGIC_WATER_TRIAL_MQ_SILVER_RUPEES, []{return logic->IsAdult && logic->BlueFire();}), - EventAccess(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE, []{return logic->IsAdult && logic->BlueFire();}), + EventAccess(LOGIC_WATER_TRIAL_MQ_SILVER_RUPEES, []{return logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump() && logic->CanUse(RG_HOVER_BOOTS))) && logic->BlueFire();}), + EventAccess(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE, []{return (ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && logic->CanUse(RG_ICE_ARROWS)) || (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_POWER_BRACELET) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE);}), }, {}, { //Exits Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM, []{return logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 3);}), - Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_END, []{return logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && (logic->IsAdult || logic->CanGroundJump());}), + Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_END, []{return logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && (logic->IsAdult || (logic->CanUse(RG_HOVER_BOOTS) && logic->HasItem(RG_POWER_BRACELET)) || logic->CanGroundJump());}), }); areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_END] = Region("Ganon's Castle MQ Water Trial Block Room End", SCENE_INSIDE_GANONS_CASTLE, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp index 9def5685084..aed0219499b 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp @@ -74,21 +74,31 @@ void RegionTable_Init_IceCavern() { Entrance(RR_ICE_CAVERN_HUB, []{return true;}), }); - // heavily relies on str0 - areaTable[RR_ICE_CAVERN_BLOCK_ROOM] = Region("Ice Cavern Block Room", SCENE_ICE_CAVERN, { + areaTable[RR_ICE_CAVERN_BLOCK_ROOM] = Region("Ice Cavern Block Room", SCENE_ICE_CAVERN, {}, { + //Locations + // trick involves backflip, could be merged into general trick + LOCATION(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, logic->HookshotOrBoomerang() || (ctx->GetTrickOption(RT_ICE_BLOCK_GS) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH))), + LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1, logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2, logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3, logic->CanUse(RG_BOOMERANG)), + }, { + //Exits + Entrance(RR_ICE_CAVERN_HUB, []{return logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP);}), + Entrance(RR_ICE_CAVERN_BLOCK_ROOM_BLUE_FIRE, []{return logic->HasItem(RG_POWER_BRACELET) || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_ICE_SLIDING_JUMP)));}), + Entrance(RR_ICE_CAVERN_BEFORE_FINAL_ROOM, []{return (logic->HasItem(RG_POWER_BRACELET) || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_ICE_SLIDING_JUMP)))) && AnyAgeTime([]{return logic->BlueFire();});}), + }); + + areaTable[RR_ICE_CAVERN_BLOCK_ROOM_BLUE_FIRE] = Region("Ice Cavern Block Room Blue Fire", SCENE_ICE_CAVERN, { //Events EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), }, { //Locations - // trick involves backflip, could be merged into general trick - LOCATION(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, logic->HookshotOrBoomerang() || (ctx->GetTrickOption(RT_ICE_BLOCK_GS) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH))), - LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1, logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_BOOMERANG)), - LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2, logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_BOOMERANG)), - LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3, logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1, logic->CanUse(RG_SONG_OF_TIME)), + LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2, logic->CanUse(RG_SONG_OF_TIME)), + LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3, logic->CanUse(RG_SONG_OF_TIME)), }, { //Exits - Entrance(RR_ICE_CAVERN_HUB, []{return logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP);}), - Entrance(RR_ICE_CAVERN_BEFORE_FINAL_ROOM, []{return AnyAgeTime([]{return logic->BlueFire();});}), + Entrance(RR_ICE_CAVERN_BLOCK_ROOM, []{return true;}), }); // this represents being past the red ice barricade, not just past the silver rupee door @@ -170,11 +180,11 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_MQ_SCARECROW_ROOM] = Region("Ice Cavern MQ Scarecrow Room", SCENE_ICE_CAVERN, { //Events - EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->IsAdult && logic->CanGroundJump();}), + EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->CanUse(RG_SONG_OF_TIME) || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_ICE_SLIDING_JUMP)));}), }, { //Locations LOCATION(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, (logic->BlueFire() && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)) || (logic->IsAdult && logic->CanHitSwitch(ED_LONG_JUMPSLASH))), - LOCATION(RC_ICE_CAVERN_MQ_GS_SCARECROW, logic->ReachScarecrow() || (logic->IsAdult && (logic->CanUse(RG_LONGSHOT) || logic->CanGroundJump() || ctx->GetTrickOption(RT_ICE_MQ_SCARECROW)))), + LOCATION(RC_ICE_CAVERN_MQ_GS_SCARECROW, logic->ReachScarecrow() || (logic->IsAdult && (logic->CanUse(RG_LONGSHOT) || logic->CanGroundJump() || ctx->GetTrickOption(RT_ICE_SLIDING_JUMP)))), }, { //Exits Entrance(RR_ICE_CAVERN_MQ_HUB, []{return logic->BlueFire();}), 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 4d80779bcc8..818cbc4490d 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -32,7 +32,7 @@ void RegionTable_Init_JabuJabusBelly() { Entrance(RR_JABU_JABUS_BELLY_BEGINNING, []{return true;}), Entrance(RR_JABU_JABUS_BELLY_HOLES_ROOM, []{return true;}), Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, []{return true;}), - Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, []{return logic->Get(LOGIC_JABU_LOWERED_PATH) || (ctx->GetTrickOption(RT_JABU_BOSS_HOVER) && logic->CanUse(RG_HOVER_BOOTS));}), + Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, []{return (logic->Get(LOGIC_JABU_LOWERED_PATH) || (ctx->GetTrickOption(RT_JABU_BOSS_HOVER) && logic->CanUse(RG_HOVER_BOOTS))) && logic->HasItem(RG_POWER_BRACELET);}), }); areaTable[RR_JABU_JABUS_BELLY_HOLES_ROOM] = Region("Jabu Jabus Belly Holes Room", SCENE_JABU_JABU, {}, {}, { @@ -77,7 +77,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_NORTH] = Region("Jabu Jabus Belly Water Switch Room North", SCENE_JABU_JABU, { //Events - EventAccess(LOGIC_JABU_RUTO_IN_1F, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), + EventAccess(LOGIC_JABU_RUTO_IN_1F, []{return (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE)) && logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, logic->HookshotOrBoomerang()), @@ -338,7 +338,7 @@ void RegionTable_Init_JabuJabusBelly() { //Exits Entrance(RR_JABU_JABUS_BELLY_HOLES_ROOM, []{return true /* logic->HasItem(RG_CLIMB) */;}), Entrance(RR_JABU_JABUS_BELLY_MQ_TO_BIGOCTO, []{return logic->Get(LOGIC_JABU_WEST_TENTACLE);}), - Entrance(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, []{return true;}), + Entrance(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, []{return logic->CanUse(RG_POWER_BRACELET);}), Entrance(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, []{return logic->Get(LOGIC_JABU_NORTH_TENTACLE);}), }); @@ -410,7 +410,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_TO_FORK_NORTH] = Region("Jabu Jabus Belly MQ To Fork North", SCENE_JABU_JABU, {}, {}, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, []{return logic->BlastOrSmash();}), - Entrance(RR_JABU_JABUS_BELLY_MQ_FORK_NORTH, []{return logic->BlastOrSmash() /*&& str0*/;}), + Entrance(RR_JABU_JABUS_BELLY_MQ_FORK_NORTH, []{return logic->BlastOrSmash() && logic->HasItem(RG_POWER_BRACELET);}), }); areaTable[RR_JABU_JABUS_BELLY_MQ_FORK_NORTH] = Region("Jabu Jabus Belly MQ Fork North", SCENE_JABU_JABU, { @@ -473,8 +473,8 @@ void RegionTable_Init_JabuJabusBelly() { // Need Ruto here areaTable[RR_JABU_JABUS_BELLY_MQ_BIGOCTO] = Region("Jabu Jabus Belly MQ Big Octo", SCENE_JABU_JABU, {}, {}, { //Exits - Entrance(RR_JABU_JABUS_BELLY_MQ_TO_BIGOCTO, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_BIG_OCTO);});}), - Entrance(RR_JABU_JABUS_BELLY_MQ_ABOVE_BIGOCTO, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_BIG_OCTO);});}), + Entrance(RR_JABU_JABUS_BELLY_MQ_TO_BIGOCTO, []{return AnyAgeTime([]{return logic->HasItem(RG_POWER_BRACELET) && logic->CanKillEnemy(RE_BIG_OCTO);});}), + Entrance(RR_JABU_JABUS_BELLY_MQ_ABOVE_BIGOCTO, []{return AnyAgeTime([]{return logic->HasItem(RG_POWER_BRACELET) && logic->CanKillEnemy(RE_BIG_OCTO);});}), }); areaTable[RR_JABU_JABUS_BELLY_MQ_ABOVE_BIGOCTO] = Region("Jabu Jabus Belly MQ Above Big Octo", SCENE_JABU_JABU, {}, { @@ -496,7 +496,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_ABOVE_BIGOCTO, []{return true;}), - Entrance(RR_JABU_JABUS_BELLY_MQ_ABOVE_LIFT_ROOM, []{return logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_FAIRY_SLINGSHOT);}), + Entrance(RR_JABU_JABUS_BELLY_MQ_ABOVE_LIFT_ROOM, []{return logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_POWER_BRACELET);}), }); areaTable[RR_JABU_JABUS_BELLY_MQ_ABOVE_LIFT_ROOM] = Region("Jabu Jabus Belly MQ Above Lift Room", SCENE_JABU_JABU, { 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 46772fdb446..705f3f001a7 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp @@ -20,7 +20,7 @@ void RegionTable_Init_ShadowTemple() { //Exits Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, []{return (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_SHADOW_TEMPLE_WHISPERING_WALLS_START, []{return ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH);}), - Entrance(RR_SHADOW_TEMPLE_FIRST_BEAMOS, []{return (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_SHADOW_TEMPLE_FIRST_BEAMOS, []{return (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_POWER_BRACELET) && logic->CanUse(RG_HOVER_BOOTS);}), }); areaTable[RR_SHADOW_TEMPLE_WHISPERING_WALLS_START] = Region("Shadow Temple Whispering Walls Start", SCENE_SHADOW_TEMPLE, { @@ -83,7 +83,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_FIRST_BEAMOS] = Region("Shadow Temple First Beamos", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_BEGINNING, []{return ctx->GetTrickOption(RT_VISIBLE_COLLISION) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}), @@ -371,7 +371,7 @@ void RegionTable_Init_ShadowTemple() { }, { //Exits Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, []{return true;}), - Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return AnyAgeTime([]{return logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}) && (logic->CanUse(RG_HOVER_BOOTS) || AnyAgeTime([]{return logic->CanUse(RG_FIRE_ARROWS);}) || (ctx->GetTrickOption(RT_SHADOW_MQ_GAP) && logic->CanUse(RG_LONGSHOT) && logic->CanJumpslashExceptHammer()));}), + Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return AnyAgeTime([]{return logic->HasItem(RG_POWER_BRACELET) && (logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)));}) && (logic->CanUse(RG_HOVER_BOOTS) || AnyAgeTime([]{return logic->CanUse(RG_FIRE_ARROWS);}) || (ctx->GetTrickOption(RT_SHADOW_MQ_GAP) && logic->CanUse(RG_LONGSHOT) && logic->CanJumpslashExceptHammer()));}), Entrance(RR_SHADOW_TEMPLE_MQ_WHISPERING_WALLS_START, []{return AnyAgeTime([]{return logic->HasExplosives();}) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 6) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index 75a8163060a..442be07fc63 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -192,12 +192,12 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM] = Region("Spirit Temple 2F Mirror Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return true/*str0 || SunlightArrows()*/;})), - LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return true/*str0 || SunlightArrows()*/;})), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows();})), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows();})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_1F_MIRROR_ROOM, []{return true;}), - Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, []{return true/*str0 || SunlightArrows()*/;}), + Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, []{return logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows();}), }); areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD] = Region("Spirit Temple Statue Rooom Child", SCENE_SPIRIT_TEMPLE, {}, { @@ -216,13 +216,13 @@ void RegionTable_Init_SpiritTemple() { // RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled 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)));}), - Entrance(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, []{return true/*str0*/;}), + Entrance(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, []{return logic->HasItem(RG_POWER_BRACELET);}), //!QUANTUM LOGIC! //When child enters spirit in reverse, has 4 keys, and dungeon entrance shuffle is off, //Child cannot lock themselves out of desert colossus access as if they save the west hand lock for last //they will be able to exit the dungeon through the intended entrance and vice versa //for needing to open the west hand lock to block the intended child route - Entrance(RR_DESERT_COLOSSUS, []{return ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && /*str0 &&*/ + Entrance(RR_DESERT_COLOSSUS, []{return ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && logic->HasItem(RG_POWER_BRACELET) && logic->IsChild/*CanUse(RG_CRAWL)*/ && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4) && logic->CanKillEnemy(RE_IRON_KNUCKLE);}), }); @@ -274,8 +274,8 @@ void RegionTable_Init_SpiritTemple() { //If you do not have explosives to kill Beamos, but do have a way to defeat Iron Knuckles, this becomes possible with 4 keys instead. Entrance(RR_SPIRIT_TEMPLE_ADULT_SIDE_HUB, []{return ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->IsAdult && - ((logic->CanKillEnemy(RE_BEAMOS) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, /*CanClimb() && str0 ?*/ 2 /*: 3*/)) || - (/*CanClimb() && str0 && */logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4)));}), + ((logic->CanKillEnemy(RE_BEAMOS) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, /*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)));}), }); areaTable[RR_SPIRIT_TEMPLE_EMPTY_STAIRS] = Region("Spirit Temple Empty Stairs", SCENE_SPIRIT_TEMPLE, {}, {}, { @@ -286,12 +286,10 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM] = Region("Spirit Temple Sun Block Room", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits - Entrance(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, []{return true/*str0 || SunlightArrows*/;}), + Entrance(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, []{return logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows();}), //The blocks can be used to get onto this ledge itemless - //true/*str0 || IsAdult || CanKillEnemy(RE_BEAMOS) || BunnyHovers() || - //((HasFireSource() || (SpiritSunBlockTorch && (logic->CanUse(STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))))) && CanUse(RG_HOOKSHOT))*/ Entrance(RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, []{return logic->SpiritSunBlockSouthLedge();}), - Entrance(RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, []{return true/*str0 || SunlightArrows*/;}), + Entrance(RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, []{return logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows();}), }); areaTable[RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE] = Region("Spirit Temple Sun Block Chest ledge", SCENE_SPIRIT_TEMPLE, { @@ -303,8 +301,8 @@ void RegionTable_Init_SpiritTemple() { //Spawning the chest to get here is accounted for in movement logic, so we only need to confirm it can be spawned here LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, []{return logic->HasFireSource() || - (logic->Get(LOGIC_SPIRIT_SUN_BLOCK_TORCH) && //Possible without str0 by timing a shot during a backflip from the ledge, but it's probably a separate trick - (logic->CanUse(RG_STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW)/* && str0*/)));})), + (logic->Get(LOGIC_SPIRIT_SUN_BLOCK_TORCH) && + (logic->CanUse(RG_STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))));})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM, []{return true;}), @@ -504,9 +502,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BIG_MIRROR_CAVE] = Region("Spirit Temple Big Mirror Cave", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(LOGIC_SPIRIT_4F_SWITCH, []{return logic->HasExplosives();}), - //WARNING: not currently a permanent flag, needs to be one for doorsanity - EventAccess(LOGIC_SPIRIT_PUSHED_4F_MIRRORS, []{return logic->HasExplosives()/*&& str0*/;}), + EventAccess(LOGIC_SPIRIT_4F_SWITCH, []{return logic->HasExplosives();}), + EventAccess(LOGIC_SPIRIT_PUSHED_4F_MIRRORS, []{return logic->HasExplosives() && logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, (logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows()), @@ -590,14 +587,13 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_GIBDO_GRAVES] = Region("Spirit Temple MQ Gibdo Graves", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(LOGIC_SPIRIT_MQ_GIBDOS_CLEARED, []{return /*str0 && */ - (logic->CanUse(RG_BOMBCHU_5) && logic->CanHitEyeTargets()) || - logic->CanUse(RG_HOVER_BOOTS)/* || (IsAdult && CanBunnyJump())*/ - && logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 3) /* && str0*/;}), + EventAccess(LOGIC_SPIRIT_MQ_GIBDOS_CLEARED, []{return logic->HasItem(RG_POWER_BRACELET) && + ((logic->CanUse(RG_BOMBCHU_5) && logic->CanHitEyeTargets()) || logic->CanUse(RG_HOVER_BOOTS)/* || (IsAdult && CanBunnyJump())*/) + && logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 3);}), }, {}, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_CHILD_SIDE_HUB, []{return true;}), - Entrance(RR_SPIRIT_TEMPLE_MQ_GIBDO_POTS, []{return /*str0 && */ + Entrance(RR_SPIRIT_TEMPLE_MQ_GIBDO_POTS, []{return logic->HasItem(RG_POWER_BRACELET) && (logic->CanUse(RG_BOMBCHU_5) && logic->CanHitEyeTargets()) || logic->CanUse(RG_HOVER_BOOTS)/* || (IsAdult && CanBunnyJump())*/;}), }); @@ -636,15 +632,15 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_ANUBIS_BRIDGE_GRAVE] = Region("Spirit Temple MQ Anubis Bridge Grave", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, []{return /*(*/logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE)/*) && (str0 || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT) || (logic->IsAdult && CanBunnyJump())) || - logic->CanKillEnemy(RE_ANUBIS, ED_BOOMERANG) && logic->CanKillEnemy(RE_KEESE, ED_FAR)*/;}), + EventAccess(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, []{return (logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE)) && (logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) /*|| (logic->IsAdult && CanBunnyJump())*/) || + (logic->CanKillEnemy(RE_ANUBIS, ED_BOOMERANG) && logic->CanKillEnemy(RE_KEESE, ED_FAR));}), }, { //Locations LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->Get(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_TURNTABLE, []{return true;}), - Entrance(RR_SPIRIT_TEMPLE_MQ_ANUBIS_BRIDGE_CHEST, []{return true/*str0 || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT) || (logic->IsAdult && CanBunnyJump())*/;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_ANUBIS_BRIDGE_CHEST, []{return logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) /*|| (logic->IsAdult && CanBunnyJump())*/;}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_ANUBIS_BRIDGE_CHEST] = Region("Spirit Temple MQ Anubis Bridge Chest", SCENE_SPIRIT_TEMPLE, { @@ -712,7 +708,6 @@ void RegionTable_Init_SpiritTemple() { Entrance(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6);}), Entrance(RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME);}), Entrance(RR_SPIRIT_TEMPLE_MQ_INNER_RIGHT_HAND, []{return logic->IsAdult || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)/* || CanBunnyJump()*/;}), - //(IsAdult || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || CanUse(RG_SONG_OF_TIME) || CanBunnyJump()) && str0 Entrance(RR_SPIRIT_TEMPLE_MQ_FLAMETHROWER_STAIRS, []{return logic->MQSpiritStatueToSunBlock();}), //explicit adult check here is a precaution against possible child logic leaking, child with a hookshot can do this Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_ADULT, []{return logic->IsAdult && logic->CanUse(RG_HOOKSHOT);}), @@ -787,16 +782,16 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM] = Region("Spirit Temple MQ Sun Block Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return true/*str0*/;})), - //RT_SPIRIT_MQ_SUN_BLOCK_GS should probably be expanded to cover all ground based methods when str0 is added, as it can be hit with longshot because the skull hitbox is larger than the model - LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return (logic->CanUse(RG_HOOKSHOT)/* && (str0 || SunlightArrows())*/) || + LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->HasItem(RG_POWER_BRACELET);})), + //RT_SPIRIT_MQ_SUN_BLOCK_GS should probably be expanded to cover all ground based methods, as it can be hit with longshot because the skull hitbox is larger than the model + LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return (logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows())) || (ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->CanUse(RG_BOOMERANG));})), LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_1, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_2, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanBreakPots();})), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_FLAMETHROWER_STAIRS, []{return true/*str0 || SunlightArrows()*/;}), - Entrance(RR_SPIRIT_TEMPLE_MQ_SKULLTULA_STAIRS, []{return true/*str0 || SunlightArrows()*/;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_FLAMETHROWER_STAIRS, []{return logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows();}), + Entrance(RR_SPIRIT_TEMPLE_MQ_SKULLTULA_STAIRS, []{return logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows();}), }); areaTable[RR_SPIRIT_TEMPLE_MQ_SKULLTULA_STAIRS] = Region("Spirit Temple MQ Skulltula Stairs", SCENE_SPIRIT_TEMPLE, {}, {}, { @@ -853,17 +848,7 @@ void RegionTable_Init_SpiritTemple() { Entrance(RR_SPIRIT_TEMPLE_MQ_CHEST_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) || ((ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_LONGSHOT));}), Entrance(RR_SPIRIT_TEMPLE_MQ_3_SUNS_ROOM_2F, []{return logic->Get(LOGIC_SPIRIT_MQ_STATUE_ROOM_TORCHES);}), - /* logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && - logic->CanJumpslash() && (str0 || SunlightArrows) && - (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && - logic->CanKillEnemy(RE_IRON_KNUCKLE) && - logic->CanUse(RG_HOOKSHOT)*/ Entrance(RR_DESERT_COLOSSUS, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4) && logic->MQSpirit4KeyColossus();}), - /* logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && - logic->CanJumpslash() && (str0 || SunlightArrows) && - (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && - logic->CanKillEnemy(RE_IRON_KNUCKLE) && - logic->CanUse(RG_LONGSHOT) */ Entrance(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4) && logic->MQSpirit4KeyWestHand();}), Entrance(RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_LOWER, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5);}), // RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled @@ -979,8 +964,8 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanBreakSmallCrates()), }, { //Exits - Entrance(RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_UPPER, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME)/* && str0*/;}), - Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME)/* && str0*/;}), + Entrance(RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_UPPER, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->HasItem(RG_POWER_BRACELET);}), + Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->HasItem(RG_POWER_BRACELET);}), Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_BASE, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6);}), }); @@ -1095,8 +1080,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE] = Region("Spirit Temple MQ Big Mirror Cave", SCENE_SPIRIT_TEMPLE, { //Events - //WARNING: Not currently a permanent flag, needs to be one for doorsanity - EventAccess(LOGIC_SPIRIT_PUSHED_4F_MIRRORS, []{return ((logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows())/* && str0*/;}), + EventAccess(LOGIC_SPIRIT_PUSHED_4F_MIRRORS, []{return ((logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows()) && logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp index e03026bae40..02f6a4d9bed 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp @@ -736,7 +736,7 @@ void RegionTable_Init_WaterTemple() { //Exits Entrance(RR_WATER_TEMPLE_MQ_2F_CENTRAL_A, []{return true;}), Entrance(RR_WATER_TEMPLE_MQ_PILLAR_2F, []{return true;}), - Entrance(RR_WATER_TEMPLE_MQ_HIDDEN_SWITCH_2F, []{return (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_WATER_TEMPLE_MQ_HIDDEN_SWITCH_2F, []{return (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_POWER_BRACELET);}), Entrance(RR_WATER_TEMPLE_MQ_LIZALFOS_LOOP_LM, []{return logic->CanUse(RG_HOVER_BOOTS);}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp index 6ec8114a094..b72d248049b 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp @@ -19,7 +19,7 @@ void RegionTable_Init_CastleGrounds() { areaTable[RR_HYRULE_CASTLE_GROUNDS] = Region("Hyrule Castle Grounds", SCENE_HYRULE_CASTLE, { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy() || logic->CanUse(RG_STICKS);}), - EventAccess(LOGIC_BUG_ACCESS, []{return true;}), + EventAccess(LOGIC_BUG_ACCESS, []{return logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations LOCATION(RC_HC_MALON_EGG, true), @@ -45,7 +45,7 @@ void RegionTable_Init_CastleGrounds() { }, { //Exits Entrance(RR_CASTLE_GROUNDS, []{return true;}), - Entrance(RR_HC_GARDEN, []{return logic->CanUse(RG_WEIRD_EGG) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash());}), + Entrance(RR_HC_GARDEN, []{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->BlastOrSmash();}), Entrance(RR_HC_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), }); 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 d2d23b4a04a..84636646d50 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 @@ -33,7 +33,7 @@ void RegionTable_Init_DeathMountainTrail() { areaTable[RR_DEATH_MOUNTAIN_SUMMIT] = Region("Death Mountain Summit", SCENE_DEATH_MOUNTAIN_TRAIL, { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy();}), - EventAccess(LOGIC_BUG_ACCESS, []{return logic->IsChild;}), + EventAccess(LOGIC_BUG_ACCESS, []{return logic->IsChild && logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations LOCATION(RC_DMT_TRADE_BROKEN_SWORD, logic->IsAdult && logic->CanUse(RG_BROKEN_SWORD)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp index 428281602fc..4afeb119fd8 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp @@ -7,7 +7,7 @@ void RegionTable_Init_DesertColossus() { // clang-format off areaTable[RR_DESERT_COLOSSUS] = Region("Desert Colossus", SCENE_DESERT_COLOSSUS, { //Events - EventAccess(LOGIC_BUG_ACCESS, []{return true;}), + EventAccess(LOGIC_BUG_ACCESS, []{return logic->HasItem(RG_POWER_BRACELET);}), }, { //Locations LOCATION(RC_COLOSSUS_FREESTANDING_POH, logic->IsAdult && CanPlantBean(RR_DESERT_COLOSSUS, RG_DESERT_COLOSSUS_BEAN_SOUL)), 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 7dd796e466e..1e99e1f65fd 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -7,19 +7,19 @@ void RegionTable_Init_GerudoValley() { // clang-format off areaTable[RR_GERUDO_VALLEY] = Region("Gerudo Valley", SCENE_GERUDO_VALLEY, { //Events - EventAccess(LOGIC_BUG_ACCESS, []{return logic->IsChild;}), + 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()), }, { //Exits Entrance(RR_HYRULE_FIELD, []{return true;}), - Entrance(RR_GV_UPPER_STREAM, []{return logic->IsChild || logic->HasItem(RG_BRONZE_SCALE) || logic->TakeDamage();}), - Entrance(RR_GV_CRATE_LEDGE, []{return logic->IsChild || logic->CanUse(RG_LONGSHOT);}), + 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->CanJumpslash());}), - Entrance(RR_GV_LOWER_STREAM, []{return logic->IsChild;}), //can use cucco as child + ((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);}), }); areaTable[RR_GV_UPPER_STREAM] = Region("GV Upper Stream", SCENE_GERUDO_VALLEY, { @@ -27,7 +27,7 @@ void RegionTable_Init_GerudoValley() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairy() || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GERUDO_VALLEY_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS));}), }, { //Locations - LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, logic->IsChild || logic->HasItem(RG_BRONZE_SCALE) || CanPlantBean(RR_GV_UPPER_STREAM, RG_GERUDO_VALLEY_BEAN_SOUL)),//can use cucco as child + LOCATION(RC_GV_WATERFALL_FREESTANDING_POH, (logic->IsChild && logic->HasItem(RG_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)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp index 9641da2fae3..7af1c2ced4d 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp @@ -9,7 +9,7 @@ void RegionTable_Init_GoronCity() { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairyExceptSuns();}), EventAccess(LOGIC_STICK_ACCESS, []{return logic->IsChild && logic->CanBreakPots();}), - EventAccess(LOGIC_BUG_ACCESS, []{return logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS);}), + EventAccess(LOGIC_BUG_ACCESS, []{return (logic->BlastOrSmash() && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_SILVER_GAUNTLETS);}), EventAccess(LOGIC_GORON_CITY_CHILD_FIRE, []{return logic->IsChild && logic->CanUse(RG_DINS_FIRE);}), EventAccess(LOGIC_GORON_CITY_WOODS_WARP_OPEN, []{return logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER) || logic->Get(LOGIC_GORON_CITY_CHILD_FIRE);}), EventAccess(LOGIC_GORON_CITY_DARUNIAS_DOOR_OPEN_CHILD, []{return logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY);}), @@ -82,7 +82,7 @@ void RegionTable_Init_GoronCity() { }, { //Exits Entrance(RR_GORON_CITY, []{return true;}), - Entrance(RR_DMC_LOWER_LOCAL, []{return logic->IsAdult;}), + Entrance(RR_DMC_LOWER_LOCAL, []{return logic->IsAdult && logic->HasItem(RG_POWER_BRACELET);}), }); areaTable[RR_GC_GROTTO_PLATFORM] = Region("GC Grotto Platform", SCENE_GORON_CITY, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp index fc5ff2cc647..d3c9d6dd468 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp @@ -8,7 +8,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_THE_GRAVEYARD] = Region("The Graveyard", SCENE_GRAVEYARD, { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return (logic->AtDay && logic->CanUse(RG_STICKS)) || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS));}), - EventAccess(LOGIC_BUG_ACCESS, []{return true;}), + EventAccess(LOGIC_BUG_ACCESS, []{return logic->HasItem(RG_POWER_BRACELET);}), EventAccess(LOGIC_BORROW_BUNNY_HOOD, []{return logic->IsChild && logic->AtDay && logic->Get(LOGIC_BORROW_SPOOKY_MASK) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations @@ -34,10 +34,10 @@ void RegionTable_Init_Graveyard() { LOCATION(RC_GRAVEYARD_CRATE, ((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD, RG_GRAVEYARD_BEAN_SOUL)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()), }, { //Exits - Entrance(RR_GRAVEYARD_SHIELD_GRAVE, []{return logic->IsAdult || logic->AtNight;}), + Entrance(RR_GRAVEYARD_SHIELD_GRAVE, []{return (logic->IsAdult || logic->AtNight) && logic->HasItem(RG_POWER_BRACELET);}), Entrance(RR_GRAVEYARD_COMPOSERS_GRAVE, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), - Entrance(RR_GRAVEYARD_HEART_PIECE_GRAVE, []{return logic->IsAdult || logic->AtNight;}), - Entrance(RR_GRAVEYARD_DAMPES_GRAVE, []{return logic->IsAdult;}), + Entrance(RR_GRAVEYARD_HEART_PIECE_GRAVE, []{return (logic->IsAdult || logic->AtNight) && logic->HasItem(RG_POWER_BRACELET);}), + Entrance(RR_GRAVEYARD_DAMPES_GRAVE, []{return logic->IsAdult && logic->HasItem(RG_POWER_BRACELET);}), Entrance(RR_GRAVEYARD_DAMPES_HOUSE, []{return logic->IsAdult && logic->CanOpenOverworldDoor(RG_DAMPES_HUT_KEY) /*|| logic->AtDampeTime*/;}), //TODO: This needs to be handled in ToD rework Entrance(RR_KAKARIKO_VILLAGE, []{return true;}), Entrance(RR_GRAVEYARD_WARP_PAD_REGION, []{return false;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index 77444333a78..45129833fe7 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -7,7 +7,7 @@ void RegionTable_Init_Kakariko() { // clang-format off areaTable[RR_KAKARIKO_VILLAGE] = Region("Kakariko Village", SCENE_KAKARIKO_VILLAGE, { //Events - EventAccess(LOGIC_BUG_ACCESS, []{return true;}), + EventAccess(LOGIC_BUG_ACCESS, []{return logic->HasItem(RG_POWER_BRACELET);}), //Open Gate setting is applied in RR_ROOT EventAccess(LOGIC_KAKARIKO_GATE_OPEN, []{return logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER);}), //Needs wallet to be able to get another mask after selling Keaton @@ -15,14 +15,14 @@ void RegionTable_Init_Kakariko() { }, { //Locations LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->HasItem(RG_FOREST_MEDALLION) && logic->HasItem(RG_FIRE_MEDALLION) && logic->HasItem(RG_WATER_MEDALLION)), - LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay), + LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay && logic->HasItem(RG_POWER_BRACELET)), 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 - LOCATION(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, logic->IsChild && logic->CanGetNightTimeGS()), - LOCATION(RC_KAK_GS_SKULLTULA_HOUSE, logic->IsChild && logic->CanGetNightTimeGS()), - LOCATION(RC_KAK_GS_GUARDS_HOUSE, logic->IsChild && logic->CanGetNightTimeGS()), - LOCATION(RC_KAK_GS_TREE, logic->IsChild && logic->CanGetNightTimeGS() && logic->CanBonkTrees()), + LOCATION(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, logic->IsChild && logic->CanGetNightTimeGS() && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))), + 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_NEAR_POTION_SHOP_POT_1, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_KAK_NEAR_POTION_SHOP_POT_2, logic->IsChild && logic->CanBreakPots()), @@ -72,14 +72,14 @@ void RegionTable_Init_Kakariko() { Entrance(RR_KAK_WELL, []{return logic->IsAdult || logic->Get(LOGIC_DRAIN_WELL) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_BOTTOM_OF_THE_WELL_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash());}), Entrance(RR_KAK_POTION_SHOP_FRONT, []{return (logic->AtDay || logic->IsChild) && logic->CanOpenOverworldDoor(RG_KAK_POTION_SHOP_KEY);}), Entrance(RR_KAK_REDEAD_GROTTO, []{return logic->CanOpenBombGrotto();}), - Entrance(RR_KAK_IMPAS_LEDGE, []{return (logic->IsChild && logic->AtDay) || (logic->IsAdult && ctx->GetTrickOption(RT_VISIBLE_COLLISION));}), + Entrance(RR_KAK_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_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;}), Entrance(RR_KAK_BEHIND_GATE, []{return logic->IsAdult || logic->Get(LOGIC_KAKARIKO_GATE_OPEN);}), //adult can jump from the fence near the windmill to ledgegrab the fence near granny's shop. is in logic on N64 - Entrance(RR_KAK_BACKYARD, []{return logic->IsAdult || logic->AtDay;}), + Entrance(RR_KAK_BACKYARD, []{return logic->IsAdult || (logic->AtDay && logic->HasItem(RG_POWER_BRACELET));}), }); areaTable[RR_KAK_IMPAS_LEDGE] = Region("Kak Impas Ledge", SCENE_KAKARIKO_VILLAGE, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp index e40f514face..64e398752ad 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp @@ -12,8 +12,8 @@ void RegionTable_Init_LonLonRanch() { }, { //Locations LOCATION(RC_SONG_FROM_MALON, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER) && logic->HasItem(RG_FAIRY_OCARINA) && logic->AtDay), - LOCATION(RC_LLR_GS_TREE, logic->IsChild && logic->CanBonkTrees()), - LOCATION(RC_LLR_GS_RAIN_SHED, logic->IsChild && logic->CanGetNightTimeGS()), + LOCATION(RC_LLR_GS_TREE, logic->IsChild && logic->CanBonkTrees() && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))), + LOCATION(RC_LLR_GS_RAIN_SHED, logic->IsChild && logic->CanGetNightTimeGS() && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))), LOCATION(RC_LLR_GS_HOUSE_WINDOW, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_LLR_GS_BACK_WALL, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_LLR_FRONT_POT_1, logic->IsChild && logic->CanBreakPots()), @@ -56,7 +56,7 @@ void RegionTable_Init_LonLonRanch() { areaTable[RR_LLR_TOWER] = Region("LLR Tower", SCENE_LON_LON_BUILDINGS, {}, { //Locations - LOCATION(RC_LLR_FREESTANDING_POH, logic->IsChild), + LOCATION(RC_LLR_FREESTANDING_POH, logic->IsChild && logic->HasItem(RG_POWER_BRACELET)), LOCATION(RC_LLR_TOWER_LEFT_COW, logic->CanUse(RG_EPONAS_SONG)), LOCATION(RC_LLR_TOWER_RIGHT_COW, logic->CanUse(RG_EPONAS_SONG)), }, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index f6cdecde11e..35a7ab91176 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -56,7 +56,7 @@ void RegionTable_Init_Market() { }, { //Locations LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->Get(LOGIC_BIG_POE_KILL) || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())), - LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild), + LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))), LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_1, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_2, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_3, logic->IsChild && logic->CanBreakPots()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp index b1ad49080c1..827d7e56480 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp @@ -8,7 +8,7 @@ void RegionTable_Init_ZorasDomain() { areaTable[RR_ZORAS_DOMAIN] = Region("Zoras Domain", SCENE_ZORAS_DOMAIN, { //Events EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(LOGIC_NUT_ACCESS, []{return true;}), + EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanBreakPots();}), EventAccess(LOGIC_STICK_ACCESS, []{return logic->IsChild;}), EventAccess(LOGIC_FISH_ACCESS, []{return logic->IsChild;}), EventAccess(LOGIC_KING_ZORA_THAWED, []{return logic->IsAdult && logic->BlueFire();}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp index 83ce7061fa9..d1399d86ec6 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp @@ -10,7 +10,7 @@ void RegionTable_Init_ZorasFountain() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairyExceptSuns() || (logic->CanUse(RG_STICKS) && logic->AtDay);}), }, { //Locations - LOCATION(RC_ZF_GS_TREE, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_ZF_GS_TREE, logic->IsChild && logic->CanBonkTrees() && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))), LOCATION(RC_ZF_GS_ABOVE_THE_LOG, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_ZF_FAIRY_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), LOCATION(RC_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp index 883a3f8a749..f3d0e5c9483 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp @@ -41,7 +41,7 @@ void RegionTable_Init_ZoraRiver() { LOCATION(RC_ZR_FROGS_SUNS_SONG, logic->IsChild && logic->CanUse(RG_SUNS_SONG)), LOCATION(RC_ZR_FROGS_SONG_OF_TIME, logic->IsChild && logic->CanUse(RG_SONG_OF_TIME)), LOCATION(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, logic->CanUse(RG_BOOMERANG)), - LOCATION(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, (logic->IsChild /*&& str0*/) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_UPPER))), + LOCATION(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_UPPER))), LOCATION(RC_ZR_GS_LADDER, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH) && logic->CanGetNightTimeGS()), LOCATION(RC_ZR_GS_NEAR_RAISED_GROTTOS, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT) && logic->CanGetNightTimeGS()), LOCATION(RC_ZR_GS_ABOVE_BRIDGE, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_HOOKSHOT) && logic->CanGetNightTimeGS()), @@ -59,11 +59,11 @@ void RegionTable_Init_ZoraRiver() { }, { //Exits Entrance(RR_ZR_FRONT, []{return true;}), - Entrance(RR_ZR_ATOP_LADDER, []{return true/*(logic->IsAdult || str0) && (logic->CanUse(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)))*/;}), - Entrance(RR_ZR_PILLAR, []{return (logic->IsChild/* && str0*/) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_LOWER));}), + 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_PILLAR, []{return (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_LOWER));}), Entrance(RR_THE_LOST_WOODS, []{return logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_ZR_STORMS_GROTTO, []{return logic->CanOpenStormsGrotto();}), - Entrance(RR_ZR_BEHIND_WATERFALL, []{return ctx->GetOption(RSK_SLEEPING_WATERFALL).Is(RO_WATERFALL_OPEN) || AnyAgeTime([]{return logic->CanUse(RG_ZELDAS_LULLABY);}) || (logic->IsChild && ctx->GetTrickOption(RT_ZR_CUCCO)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_ZR_HOVERS));}), + Entrance(RR_ZR_BEHIND_WATERFALL, []{return ctx->GetOption(RSK_SLEEPING_WATERFALL).Is(RO_WATERFALL_OPEN) || AnyAgeTime([]{return logic->CanUse(RG_ZELDAS_LULLABY);}) || (logic->IsChild && ctx->GetTrickOption(RT_ZR_CUCCO) && logic->HasItem(RG_POWER_BRACELET)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_ZR_HOVERS));}), }); areaTable[RR_ZR_ATOP_LADDER] = Region("ZR Atop Ladder", SCENE_ZORAS_RIVER, { @@ -78,7 +78,7 @@ void RegionTable_Init_ZoraRiver() { }, { //Exits Entrance(RR_ZORAS_RIVER, []{return true;}), - Entrance(RR_ZR_PILLAR, []{return (logic->IsChild/* && str0*/) || logic->CanUse(RG_HOVER_BOOTS);}), + Entrance(RR_ZR_PILLAR, []{return (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_ZR_OPEN_GROTTO, []{return true;}), Entrance(RR_ZR_FAIRY_GROTTO, []{return AnyAgeTime([]{return logic->BlastOrSmash();});}), }); diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index a79d45444ab..9a1b2211a92 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -1,7 +1,6 @@ #include "logic.h" #include "../debugger/performanceTimer.h" -#include #include #include @@ -80,6 +79,8 @@ bool Logic::HasItem(RandomizerGet itemName) { return CheckEquipment(RandoGetToEquipFlag.at(itemName)) || Get(LOGIC_MEDIGORON); case RG_BIGGORON_SWORD: return CheckEquipment(RandoGetToEquipFlag.at(itemName)) && mSaveContext->bgsFlag; + case RG_POWER_BRACELET: + return CheckRandoInf(RAND_INF_CAN_GRAB); case RG_GORONS_BRACELET: return CurrentUpgrade(UPG_STRENGTH); case RG_SILVER_GAUNTLETS: @@ -752,7 +753,8 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal (ctx->GetTrickOption(RT_DC_DODONGO_CHU) && IsAdult && CanUse(RG_BOMBCHU_5))); case RE_BARINADE: return HasBossSoul(RG_BARINADE_SOUL) && CanUse(RG_BOOMERANG) && - (CanJumpslashExceptHammer() || ctx->GetTrickOption(RT_JABU_BARINADE_POTS)); + (CanJumpslashExceptHammer() || + (ctx->GetTrickOption(RT_JABU_BARINADE_POTS) && HasItem(RG_POWER_BRACELET))); case RE_PHANTOM_GANON: return HasBossSoul(RG_PHANTOM_GANON_SOUL) && CanUseSword() && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT)); @@ -1238,10 +1240,10 @@ bool Logic::CanBreakPots(EnemyDistance distance, bool wallOrFloor, bool inWater) bool hit = false; switch (distance) { case ED_CLOSE: - hit = true; // str0 + hit = HasItem(RG_POWER_BRACELET); [[fallthrough]]; case ED_SHORT_JUMPSLASH: - hit = hit || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MEGATON_HAMMER); + hit = hit || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_GIANTS_KNIFE); [[fallthrough]]; case ED_MASTER_SWORD_JUMPSLASH: hit = hit || CanUse(RG_MASTER_SWORD); @@ -1273,7 +1275,7 @@ bool Logic::CanBreakCrates() { } bool Logic::CanBreakSmallCrates() { - return true; + return CanUseSword() || BlastOrSmash() || HasItem(RG_POWER_BRACELET); } bool Logic::CanBonkTrees() { @@ -1720,8 +1722,14 @@ void Logic::ApplyItemEffect(Item& item, bool state) { } break; case RG_PROGRESSIVE_STRENGTH: { auto currentLevel = CurrentUpgrade(UPG_STRENGTH); - auto newLevel = currentLevel + (!state ? -1 : 1); - SetUpgrade(UPG_STRENGTH, newLevel); + if (!CheckRandoInf(RAND_INF_CAN_GRAB) && state) { + SetRandoInf(RAND_INF_CAN_GRAB, true); + } else if (currentLevel == 0 && !state) { + SetRandoInf(RAND_INF_CAN_GRAB, false); + } else { + auto newLevel = currentLevel + (!state ? -1 : 1); + SetUpgrade(UPG_STRENGTH, newLevel); + } } break; case RG_PROGRESSIVE_BOMB_BAG: { auto realGI = item.GetGIEntry(); @@ -2461,13 +2469,12 @@ bool Logic::SpiritWestToSkull() { } bool Logic::SpiritSunBlockSouthLedge() { - // It's also possible to do a backwalk hover + backflip if you equip hovers as you start the backwalk to accelerate - // faster - return true /*str0 || IsAdult || CanKillEnemy(RE_BEAMOS) || BunnyHovers() || - (CanUse(RG_HOOKSHOT) && (HasFireSource() || - (SpiritSunBlockTorch && (logic->CanUse(STICKS) || - (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))))))*/ - ; + // also possible to do a backwalk hover + backflip if you equip hovers as you start backwalk to accelerate faster + return HasItem(RG_POWER_BRACELET) || IsAdult || CanKillEnemy(RE_BEAMOS) /*|| BunnyHovers()*/ || + (CanUse(RG_HOOKSHOT) && + (HasFireSource() || + (Get(LOGIC_SPIRIT_SUN_BLOCK_TORCH) && + (CanUse(RG_STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && CanUse(RG_FAIRY_BOW)))))); } bool Logic::SpiritEastToSwitch() { @@ -2482,7 +2489,8 @@ bool Logic::MQSpiritWestToPots() { bool Logic::MQSpiritStatueToSunBlock() { return (IsAdult || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || - CanUse(RG_SONG_OF_TIME) /* || CanBunnyJump()*/) /* && str0*/; + CanUse(RG_SONG_OF_TIME) /* || CanBunnyJump()*/) && + HasItem(RG_POWER_BRACELET); } bool Logic::MQSpiritStatueSouthDoor() { @@ -2496,8 +2504,8 @@ bool Logic::MQSpirit4KeyColossus() { // Colossus This is because there are only 3 keys that can be wasted without opening up either this lock to East // hand, or the West Hand lock through Sun Block Room and both directions allow you to drop onto colossus // logic->CanKillEnemy(RE_FLOORMASTER) is implied - return CanAvoidEnemy(RE_BEAMOS, true, 4) && CanUse(RG_SONG_OF_TIME) && - CanJumpslash() && /*(str0 || SunlightArrows) &&*/ + return CanAvoidEnemy(RE_BEAMOS, true, 4) && CanUse(RG_SONG_OF_TIME) && CanJumpslash() && + (HasItem(RG_POWER_BRACELET) || SunlightArrows()) && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)) && CanKillEnemy(RE_IRON_KNUCKLE) && CanUse(RG_HOOKSHOT); } @@ -2512,7 +2520,7 @@ bool Logic::MQSpirit4KeyWestHand() { bool Logic::CouldMQSpirit4KeyWestHand() { return CanAvoidEnemy(RE_BEAMOS, true, 4) && CanUse(RG_SONG_OF_TIME) && (HasItem(RG_MASTER_SWORD) || HasItem(RG_BIGGORON_SWORD) || HasItem(RG_MEGATON_HAMMER)) && - /*(str0 || SunlightArrows) &&*/ + (HasItem(RG_POWER_BRACELET) || SunlightArrows()) && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)) && HasItem(RG_LONGSHOT); } @@ -2523,7 +2531,7 @@ bool Logic::CouldMQSpirit4KeyWestHand() { // If we have the longshot, we can also guarantee access to the outer west hand as you can longshot from the east hand // to the west Implies CanKillEnemy(RE_IRON_KNUCKLE) bool Logic::OuterWestHandLogic() { - return HasExplosives() /* && CanClimbHigh() && str0*/ && + return HasExplosives() /*&& CanClimbHigh()*/ && HasItem(RG_POWER_BRACELET) && SmallKeys(SCENE_SPIRIT_TEMPLE, HasItem(RG_LONGSHOT) ? 3 : 5); } @@ -2566,6 +2574,11 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { SetRandoInf(RAND_INF_CAN_SWIM, 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 child's wallet, we start with it if (ctx->GetOption(RSK_SHUFFLE_CHILD_WALLET).Is(false)) { SetRandoInf(RAND_INF_HAS_WALLET, true); diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index ea559f7a83e..7a70aff8036 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -251,11 +251,13 @@ void Settings::CreateOptionDescriptions() { "This will require finding the buttons before being able to use them in songs."; mOptionDescriptions[RSK_SHUFFLE_SWIM] = - "Shuffles the ability to Swim into the item pool.\n" - "The ability to swim has to be found as an item (you can still be underwater if you use iron boots).\n" + "Shuffles the ability to Swim into the item pool as a progressive upgrade before Silver Scale.\n" + "The ability to swim has to be found as an item (you can still be underwater with iron boots).\n" "\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_GRAB] = + "Shuffle the ability to grab as a progressive upgrade before Goron Bracelet."; mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG] = "Shuffles the Weird Egg from Malon in to the item pool. Enabling " "\"Skip Child Zelda\" disables this feature.\n" "\n" diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index bca464444bd..90ddc59c389 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -5267,6 +5267,8 @@ void Randomizer::CreateCustomMessages() { GIMESSAGE(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!", "Du hast die %rBronzene Schuppe%w&erhalten! Die Fähigkeit zu&Schwimmen ist nun dein!", "Vous obtenez l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est&à vous!"), + GIMESSAGE(RG_POWER_BRACELET, ITEM_BRACELET, "You got the %rPower Bracelet%w!&Wimp no more!", TODO_TRANSLATE, + TODO_TRANSLATE), GIMESSAGE(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!", "Du hast eine verlorene %rAngelrute%w&gefunden!&Zeit, im Teich&zu angeln!", "Vous obtenez une %rCanne à pêche%w&perdue!&Il est temps d'aller à %gl'étang%w!"), @@ -5430,6 +5432,7 @@ extern "C" u8 Return_Item_Entry(GetItemEntry itemEntry, u8 returnItem); std::map randomizerGetToRandInf = { { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }, { RG_BRONZE_SCALE, RAND_INF_CAN_SWIM }, + { RG_POWER_BRACELET, RAND_INF_CAN_GRAB }, { RG_QUIVER_INF, RAND_INF_HAS_INFINITE_QUIVER }, { RG_BOMB_BAG_INF, RAND_INF_HAS_INFINITE_BOMB_BAG }, { RG_BULLET_BAG_INF, RAND_INF_HAS_INFINITE_BULLET_BAG }, diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 72e24367620..20d44f22b88 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1406,6 +1406,7 @@ typedef enum { RR_ICE_CAVERN_MAP_ROOM, RR_ICE_CAVERN_COMPASS_ROOM, RR_ICE_CAVERN_BLOCK_ROOM, + RR_ICE_CAVERN_BLOCK_ROOM_BLUE_FIRE, RR_ICE_CAVERN_BEFORE_FINAL_ROOM, RR_ICE_CAVERN_FINAL_ROOM, RR_ICE_CAVERN_FINAL_ROOM_UNDERWATER, @@ -4272,6 +4273,7 @@ typedef enum { RT_SPIRIT_MQ_FROZEN_EYE, RT_ICE_STALAGMITE_CLIP, RT_ICE_STALAGMITE_HOOKSHOT, + RT_ICE_SLIDING_JUMP, RT_ICE_BLOCK_GS, RT_ICE_MQ_RED_ICE_GS, RT_ICE_MQ_SCARECROW, @@ -4599,6 +4601,7 @@ typedef enum { RG_HINT, RG_TYCOON_WALLET, RG_BRONZE_SCALE, + RG_POWER_BRACELET, RG_CHILD_WALLET, RG_PROGRESSIVE_BOMBCHU_BAG, RG_QUIVER_INF, @@ -5799,7 +5802,6 @@ typedef enum { RHT_OCARINA_C_DOWN_BUTTON, RHT_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, - RHT_BRONZE_SCALE, RHT_FISHING_POLE, RHT_SKELETON_KEY, RHT_EPONA, @@ -6396,6 +6398,7 @@ typedef enum { RSK_SHUFFLE_OCARINA, RSK_SHUFFLE_OCARINA_BUTTONS, RSK_SHUFFLE_SWIM, + RSK_SHUFFLE_GRAB, RSK_STARTING_DEKU_SHIELD, RSK_STARTING_KOKIRI_SWORD, RSK_STARTING_MASTER_SWORD, diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 7017ec73867..aed11c1220f 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_GRAB) DEFINE_RAND_INF(RAND_INF_HAS_WALLET) diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index f130f10a3bc..7c55209d6f3 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -313,6 +313,10 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetRandomizerInf(RAND_INF_CAN_SWIM); } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_GRAB) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_GRAB); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHILD_WALLET) == RO_GENERIC_OFF) { Flags_SetRandomizerInf(RAND_INF_HAS_WALLET); } diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index c8a54da8405..1e09c5c16f9 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -780,6 +780,7 @@ void Settings::CreateOptions() { }); OPT_BOOL(RSK_SHUFFLE_OCARINA_BUTTONS, "Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]); OPT_BOOL(RSK_SHUFFLE_SWIM, "Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]); + OPT_BOOL(RSK_SHUFFLE_GRAB, "Shuffle Grab", CVAR_RANDOMIZER_SETTING("ShuffleGrab"), mOptionDescriptions[RSK_SHUFFLE_GRAB]); OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]); OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_POTS_OFF); @@ -2049,7 +2050,8 @@ void Settings::CreateOptions() { OPT_TRICK(RT_SPIRIT_SUN_CHEST, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, { Tricks::Tag::ADVANCED }, "Spirit Temple Sun Block Room Chest with Bow", "Using the blocks in the room as platforms you can get lines of sight to all three torches. The timer on " - "the torches is quite short so you must move quickly in order to light all three."); + "the torches is quite short so you must move quickly in order to light all three.\n" + "A backflip can be used instead to light torches without pushing blocks."); OPT_TRICK( RT_SPIRIT_WALL, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "Spirit Temple Shifting Wall with No Additional Items", @@ -2082,6 +2084,8 @@ void Settings::CreateOptions() { OPT_TRICK(RT_ICE_STALAGMITE_HOOKSHOT, RCQUEST_BOTH, RA_ICE_CAVERN, { Tricks::Tag::NOVICE }, "Ice Cavern Stalagmites with Hookshot", "Shooting stalagmites with hookshot in the right way also breaks them. Also applies to Water Trial."); + OPT_TRICK(RT_ICE_SLIDING_JUMP, RCQUEST_BOTH, RA_ICE_CAVERN, { Tricks::Tag::NOVICE }, "Ice Cavern Sliding Jumps", + "Running forward while sliding sideways on ice can be used to jump on platforms."); OPT_TRICK(RT_ICE_BLOCK_GS, RCQUEST_VANILLA, RA_ICE_CAVERN, { Tricks::Tag::INTERMEDIATE }, "Ice Cavern Block Room GS with Hover Boots", "The Hover Boots can be used to get in front of the Skulltula to kill it with a jump slash. Then, the " @@ -2090,9 +2094,6 @@ void Settings::CreateOptions() { "Ice Cavern MQ Red Ice GS without Song of Time", "If you side-hop into the perfect position, you can briefly stand on the platform with the red ice just " "long enough to dump some blue fire."); - OPT_TRICK(RT_ICE_MQ_SCARECROW, RCQUEST_MQ, RA_ICE_CAVERN, { Tricks::Tag::INTERMEDIATE }, - "Ice Cavern MQ Scarecrow GS with No Additional Items", - "As adult a precise jump can be used to reach this alcove."); OPT_TRICK(RT_LENS_GTG, RCQUEST_VANILLA, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::NOVICE }, "Gerudo Training Ground without Lens of Truth", "Removes the requirements for the Lens of Truth in Gerudo Training Ground."); @@ -2377,6 +2378,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_DEKU_NUT_BAG], &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], + &mOptions[RSK_SHUFFLE_GRAB], &mOptions[RSK_SHUFFLE_BEAN_SOULS], &mOptions[RSK_BOMBCHU_BAG], &mOptions[RSK_ENABLE_BOMBCHU_DROPS], @@ -2593,6 +2595,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_OCARINA], &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], + &mOptions[RSK_SHUFFLE_GRAB], &mOptions[RSK_SHUFFLE_WEIRD_EGG], &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD], &mOptions[RSK_SHUFFLE_MERCHANTS], diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 2c70b2c36c9..a3a5c696e26 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -5578,8 +5578,9 @@ void func_8083A0F4(PlayState* play, Player* this) { } else if ((interactActorId == ACTOR_EN_ISHI) && ((interactRangeActor->params & 0xF) == 1)) { Player_SetupAction(play, this, Player_Action_80846260, 0); anim = &gPlayerAnim_link_silver_carry; - } else if (((interactActorId == ACTOR_EN_BOMBF) || (interactActorId == ACTOR_EN_KUSA)) && - (Player_GetStrength() <= PLAYER_STR_NONE)) { + } else if (GameInteractor_Should(VB_PREVENT_STRENGTH, ((interactActorId == ACTOR_EN_BOMBF) || + (interactActorId == ACTOR_EN_KUSA)) && + (Player_GetStrength() <= PLAYER_STR_NONE))) { Player_SetupAction(play, this, Player_Action_80846408, 0); this->actor.world.pos.x = (Math_SinS(interactRangeActor->yawTowardsPlayer) * 20.0f) + interactRangeActor->world.pos.x; @@ -13162,7 +13163,7 @@ void Player_Action_8084B78C(Player* this, PlayState* play) { } void func_8084B840(PlayState* play, Player* this, f32 arg2) { - if (this->actor.wallBgId != BGCHECK_SCENE) { + if (!GameInteractor_Should(VB_PREVENT_STRENGTH, false) && this->actor.wallBgId != BGCHECK_SCENE) { DynaPolyActor* dynaPolyActor = DynaPoly_GetActor(&play->colCtx, this->actor.wallBgId); if (dynaPolyActor != NULL) {