From 04df48944a753cf2468cd2d7d100c01f011c7c95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= Date: Fri, 16 Jan 2026 18:34:14 +0000 Subject: [PATCH] Shuffle Open Chest (#5946) --- .../vanilla-behavior/GIVanillaBehavior.h | 8 ++ .../3drando/hint_list/hint_list_item.cpp | 2 + .../randomizer/3drando/item_pool.cpp | 5 +- .../Enhancements/randomizer/3drando/shops.cpp | 4 + soh/soh/Enhancements/randomizer/draw.cpp | 54 +++++++++++ soh/soh/Enhancements/randomizer/draw.h | 1 + .../Enhancements/randomizer/hook_handlers.cpp | 5 +- soh/soh/Enhancements/randomizer/item_list.cpp | 6 +- .../dungeons/bottom_of_the_well.cpp | 34 +++---- .../location_access/dungeons/deku_tree.cpp | 26 +++--- .../dungeons/dodongos_cavern.cpp | 24 ++--- .../location_access/dungeons/fire_temple.cpp | 65 +++++++------ .../dungeons/forest_temple.cpp | 50 +++++----- .../dungeons/ganons_castle.cpp | 58 ++++++------ .../dungeons/gerudo_training_ground.cpp | 76 +++++++-------- .../location_access/dungeons/ice_cavern.cpp | 16 ++-- .../dungeons/jabujabus_belly.cpp | 38 ++++---- .../dungeons/shadow_temple.cpp | 74 +++++++-------- .../dungeons/spirit_temple.cpp | 92 +++++++++---------- .../location_access/dungeons/water_temple.cpp | 34 +++---- .../overworld/death_mountain_crater.cpp | 2 +- .../overworld/death_mountain_trail.cpp | 4 +- .../overworld/gerudo_fortress.cpp | 2 +- .../overworld/gerudo_valley.cpp | 2 +- .../location_access/overworld/goron_city.cpp | 6 +- .../location_access/overworld/graveyard.cpp | 8 +- .../overworld/haunted_wasteland.cpp | 2 +- .../overworld/hyrule_field.cpp | 6 +- .../location_access/overworld/kakariko.cpp | 4 +- .../overworld/kokiri_forest.cpp | 12 +-- .../location_access/overworld/lost_woods.cpp | 2 +- .../location_access/overworld/market.cpp | 22 ++--- .../overworld/sacred_forest_meadow.cpp | 2 +- .../overworld/zoras_domain.cpp | 2 +- .../location_access/overworld/zoras_river.cpp | 2 +- soh/soh/Enhancements/randomizer/logic.cpp | 13 ++- .../randomizer/option_descriptions.cpp | 1 + .../Enhancements/randomizer/randomizer.cpp | 1 + .../Enhancements/randomizer/randomizerTypes.h | 3 + .../Enhancements/randomizer/randomizer_inf.h | 1 + soh/soh/Enhancements/randomizer/savefile.cpp | 4 + soh/soh/Enhancements/randomizer/settings.cpp | 3 + .../actors/ovl_player_actor/z_player.c | 72 ++++++++------- 43 files changed, 475 insertions(+), 373 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index c16fb6fc86..5400afeeae 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -1469,6 +1469,14 @@ typedef enum { // - `*EnOkarinaTag` VB_OKARINA_TAG_COMPLETED, + // #### `result` + // ```c + // this->getItemId != GI_NONE + // ``` + // #### `args` + // - `None` + VB_OPEN_CHEST, + // #### `result` // ```c // CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index dacd6a28ad..b77b5b26e3 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -2107,7 +2107,9 @@ void StaticData::HintTable_Init_Item() { }, { CustomMessage("a master unlocker", /*german*/ "ein Meisterentsperrer", /*french*/ "un Kit de Déverrouillage") }); // /*spanish*/un desbloqueador maestro + hintTextTable[RHT_CRAWL] = HintText(CustomMessage("the ability to crawl", /*german*/TODO_TRANSLATE, /*french*/"la capacité de ramper")); + hintTextTable[RHT_OPEN_CHEST] = HintText(CustomMessage("the ability to open chests", /*german*/TODO_TRANSLATE, /*french*/TODO_TRANSLATE)); //RANDOTODO if these are ever used for anything other than name, they want abscure and ambiguous hints hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("an infinite Quiver", /*german*/"der unendliche Köcher", /*french*/"un Carquois Infini")); diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index ec5a646d79..2baa64e3c0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -395,6 +395,9 @@ void GenerateItemPool() { if (ctx->GetOption(RSK_SHUFFLE_CRAWL)) { AddItemToPool(RG_CRAWL, 2, 1, 1, 1); } + if (ctx->GetOption(RSK_SHUFFLE_OPEN_CHEST)) { + AddItemToPool(RG_OPEN_CHEST, 2, 1, 1, 1); + } if (ctx->GetOption(RSK_SHUFFLE_BEEHIVES)) { PlaceItemsForType(RCTYPE_BEEHIVE, true, true); @@ -897,7 +900,7 @@ void GenerateItemPool() { if (ctx->GetOption(RSK_ICE_TRAP_PERCENT).Is(100)) { iceTrapstoAdd = junkToAdd; } else if (ctx->GetOption(RSK_ICE_TRAP_PERCENT).Get() >= 0) { - for (int count = 0; count < junkToAdd; count++) { + for (size_t count = 0; count < junkToAdd; count++) { if (Random(0, 101) < ctx->GetOption(RSK_ICE_TRAP_PERCENT).Get()) { iceTrapstoAdd++; } diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp index 1da898fa75..1f34968db4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp @@ -1001,6 +1001,10 @@ void InitTrickNames() { // TODO_TRANSLATE Text{ "Crouch" }, }; + trickNameTable[RG_OPEN_CHEST] = { + // TODO_TRANSLATE + Text{ "Open Cheats" }, + }; trickNameTable[RG_OCARINA_A_BUTTON] = { Text{ "Ocarina J Button", "Touche Ha de l'Ocarina", "J-Taste der Okarina" }, diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 62971a2841..75fc14fed8 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -3,6 +3,7 @@ #include "soh/cvar_prefixes.h" #include "randomizerTypes.h" #include "soh_assets.h" +#include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" extern "C" { @@ -11,6 +12,7 @@ extern "C" { #include "functions.h" #include "variables.h" #include "dungeon.h" +#include "objects/object_box/object_box.h" #include "objects/object_gi_key/object_gi_key.h" #include "objects/object_gi_bosskey/object_gi_bosskey.h" #include "objects/object_gi_compass/object_gi_compass.h" @@ -1153,6 +1155,58 @@ extern "C" void Randomizer_DrawKneePads(PlayState* play, GetItemEntry* getItemEn CLOSE_DISPS(play->state.gfxCtx); } +static Gfx* boxLidDL; +static Gfx* boxBodyDL; +extern "C" void EnBox_PostLimbDrawOverride(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + Gfx** gfx = (Gfx**)thisx; + if (limbIndex == 1) { + gSPMatrix((*gfx)++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList((*gfx)++, boxBodyDL); + } else if (limbIndex == 3) { + gSPMatrix((*gfx)++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList((*gfx)++, boxLidDL); + } +} + +extern "C" Gfx* EnBox_EmptyDList(GraphicsContext* gfxCtx); +#define LIMB_COUNT_CHEST 5 +extern "C" void Randomizer_DrawOpenChest(PlayState* play, GetItemEntry* getItemEntry) { + static bool initialized = false; + static SkelAnime skelAnime; + static Vec3s jointTable[LIMB_COUNT_CHEST]; + static Vec3s otherTable[LIMB_COUNT_CHEST]; + static u32 lastUpdate = 0; + + if (!initialized) { + initialized = true; + boxBodyDL = ResourceMgr_LoadGfxByName((const char*)gTreasureChestChestFrontDL); + boxLidDL = ResourceMgr_LoadGfxByName((const char*)gTreasureChestChestSideAndLidDL); + SkelAnime_Init(play, &skelAnime, (SkeletonHeader*)&gTreasureChestSkel, + (AnimationHeader*)&gTreasureChestAnim_00024C, jointTable, otherTable, LIMB_COUNT_CHEST); + + // no closing animation to loop, so play animation back & forth for smooth loop + Animation_PlayOnce(&skelAnime, (AnimationHeader*)&gTreasureChestAnim_00043C); + } + + if (lastUpdate != play->state.frames) { + lastUpdate = play->state.frames; + if (SkelAnime_Update(&skelAnime)) { + Animation_Reverse(&skelAnime); + } + } + + OPEN_DISPS(play->state.gfxCtx); + Matrix_Scale(0.01f, 0.01f, 0.01f, MTXMODE_APPLY); + + gDPPipeSync(POLY_OPA_DISP++); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); + gSPSegment(POLY_OPA_DISP++, 0x08, (uintptr_t)EnBox_EmptyDList(play->state.gfxCtx)); + Gfx_SetupDL_25Opa(play->state.gfxCtx); + SkelAnime_DrawSkeletonOpa(play, &skelAnime, nullptr, (PostLimbDrawOpa)EnBox_PostLimbDrawOverride, &POLY_OPA_DISP); + + 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 e00678f9bf..82f9255ebc 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -23,6 +23,7 @@ void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawKneePads(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawOpenChest(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 3d6e6d73f0..902eb71dcb 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -851,7 +851,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l switch (id) { case VB_CRAWL: - *should = !RAND_GET_OPTION(RSK_SHUFFLE_CRAWL) || Flags_GetRandomizerInf(RAND_INF_CAN_CRAWL); + *should = *should && Flags_GetRandomizerInf(RAND_INF_CAN_CRAWL); break; case VB_ALLOW_ENTRANCE_CS_FOR_EITHER_AGE: { s32 entranceIndex = va_arg(args, s32); @@ -921,6 +921,9 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l case VB_MIDO_CONSIDER_DEKU_TREE_DEAD: *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); break; + case VB_OPEN_CHEST: + *should = *should && Flags_GetRandomizerInf(RAND_INF_CAN_OPEN_CHEST); + break; case VB_OPEN_KOKIRI_FOREST: *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || RAND_GET_OPTION(RSK_FOREST) != RO_CLOSED_FOREST_ON; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 693eb89e24..b433d44798 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -337,13 +337,15 @@ 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", "Taste C-Rechts 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, {"the ", "den ", "le "}); 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, {"the ", "die ", "le "}); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "die ", "le "}); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); itemTable[RG_CRAWL] = Item(RG_CRAWL, Text{ "Crawl", "Ramper", "Kriechen" }, ITEMTYPE_ITEM, GI_SHIELD_DEKU, true, LOGIC_NONE, RHT_CRAWL, RG_CRAWL, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_CRAWL].SetCustomDrawFunc(Randomizer_DrawKneePads); + itemTable[RG_OPEN_CHEST] = Item(RG_OPEN_CHEST, Text{ "Open Chests", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_ITEM, GI_KEY_SMALL, true, LOGIC_NONE, RHT_OPEN_CHEST, RG_OPEN_CHEST, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OPEN_CHEST].SetCustomDrawFunc(Randomizer_DrawOpenChest); - itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "un "}); + itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "un "}); itemTable[RG_PROGRESSIVE_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag); itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "le "}); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp index b2d51eeb65..bda9307c0b 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 @@ -31,12 +31,12 @@ void RegionTable_Init_BottomOfTheWell() { EventAccess(LOGIC_BOTW_LOWERED_WATER, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), - LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), - LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()), - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()), + LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, (logic->Get(LOGIC_BOTW_LOWERED_WATER) && logic->HasItem(RG_OPEN_CHEST)) || logic->CanOpenUnderwaterChest()), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, (logic->Get(LOGIC_BOTW_LOWERED_WATER) && logic->HasItem(RG_OPEN_CHEST)) || logic->CanOpenUnderwaterChest()), LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_POT, (logic->CanBreakPots() && logic->Get(LOGIC_BOTW_LOWERED_WATER)) || logic->CanUse(RG_BOOMERANG)), @@ -61,7 +61,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_MIDDLE] = Region("Bottom of the Well Middle", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations //You can just barely pass the spider on the right side without damage or items, but it's probably tight enough to count as as a trick - LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()), + LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTW_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), @@ -91,7 +91,7 @@ void RegionTable_Init_BottomOfTheWell() { //Passing through this area needs lens, but entering doesn't, so that the fire keese can be killed without crossing the pits if enemy drops are ever shuffled areaTable[RR_BOTW_HIDDEN_PITS_ROOM] = Region("Bottom of the Well Hidden Pits Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_POT_1, logic->CanBreakPots() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), }, { //Exits @@ -103,7 +103,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_LOCKED_CAGE] = Region("Bottom of the Well Locked Cage", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits @@ -112,7 +112,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_PIT_CAGE] = Region("Bottom of the Well Pit Cage", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTW_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), @@ -143,7 +143,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_BEHIND_MOAT] = Region("Bottom of the Well Behind Moat", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, (logic->Get(LOGIC_BOTW_LOWERED_WATER) && logic->HasItem(RG_OPEN_CHEST)) || logic->CanOpenUnderwaterChest()), }, { //Exits //Climb always needed in case water is lowered out of logic @@ -178,8 +178,8 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_DEAD_HAND_ROOM] = Region("Bottom of the Well Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), - LOCATION(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTW_NEAR_BOSS_UPPER, []{return logic->CanKillEnemy(RE_DEAD_HAND);}), @@ -238,7 +238,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_B3_CHEST_AREA] = Region("Bottom of the Well B3 Chest Area", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTW_B3_OOZE, []{return AnyAgeTime([]{return logic->BlastOrSmash();});}), @@ -293,7 +293,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_MQ_MIDDLE] = Region("Bottom of the Well MQ Middle", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_1, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_2, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_3, logic->CanBreakPots()), @@ -398,7 +398,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_MQ_DEAD_HAND_ROOM] = Region("Bottom of the Well MQ Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, logic->HasExplosives() || (ctx->GetTrickOption(RT_BOTW_MQ_DEADHAND_KEY) && logic->CanUse(RG_BOOMERANG))), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_GRASS_2, logic->CanCutShrubs()), @@ -425,7 +425,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_MQ_B3_PLATFORM] = Region("Bottom of the Well MQ B3 Platform", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations //Assumes RR_BOTW_MQ_B3 access - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, logic->CanPassEnemy(RE_REDEAD)), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, logic->CanPassEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTW_MQ_B3, []{return true;}), 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 b2be1d7fcd..01a191d2a3 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -22,7 +22,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_MAP_CHEST, true), + LOCATION(RC_DEKU_TREE_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_LOBBY_LOWER_HEART, true), LOCATION(RC_DEKU_TREE_LOBBY_UPPER_HEART, logic->CanPassEnemy(RE_BIG_SKULLTULA)), LOCATION(RC_DEKU_TREE_LOBBY_GRASS_1, logic->CanCutShrubs()), @@ -48,8 +48,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_SLINGSHOT_ROOM] = Region("Deku Tree Slingshot Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, true), - LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, true), + LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_1, logic->CanCutShrubs() && logic->CanReflectNuts()), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_2, logic->CanCutShrubs() && logic->CanReflectNuts()), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_3, logic->CanCutShrubs() && logic->CanReflectNuts()), @@ -65,8 +65,8 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_COMPASS_CHEST, true), - LOCATION(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, true), + LOCATION(RC_DEKU_TREE_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_GS_COMPASS_ROOM, logic->CanAttack()), LOCATION(RC_DEKU_TREE_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_COMPASS_GRASS_2, logic->CanCutShrubs()), @@ -82,7 +82,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, true), + LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_GS_BASEMENT_GATE, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH)), LOCATION(RC_DEKU_TREE_GS_BASEMENT_VINES, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) ? ED_SHORT_JUMPSLASH : ED_BOMB_THROW)), LOCATION(RC_DEKU_TREE_BASEMENT_GRASS_1, logic->CanCutShrubs()), @@ -218,7 +218,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_DEKU_TREE_MQ_2F_BURNED_WEB, []{return logic->HasFireSource();}), }, { //Locations - LOCATION(RC_DEKU_TREE_MQ_MAP_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_GS_LOBBY, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_DEKU_TREE_MQ_LOBBY_HEART, true), LOCATION(RC_DEKU_TREE_MQ_LOBBY_GRASS_6, logic->CanCutShrubs()), @@ -252,8 +252,8 @@ void RegionTable_Init_DekuTree() { }, { //Locations //Implies CanKillEnemy(RE_GOHMA_LARVA) - LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, logic->CanKillEnemy(RE_DEKU_BABA)), - LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, logic->HasFireSourceWithTorch() || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW))), + LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, logic->CanKillEnemy(RE_DEKU_BABA) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, (logic->HasFireSourceWithTorch() || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_HEART, true), LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_GRASS_2, logic->CanCutShrubs()), @@ -284,7 +284,7 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_COMPASS_ROOM] = Region("Deku Tree MQ Compass Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()), @@ -310,7 +310,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_MQ_BASEMENT_CHEST, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_DEKU_TREE_MQ_BASEMENT_CHEST, (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LOWER_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LOWER_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LOWER_GRASS_3, logic->CanCutShrubs()), @@ -346,7 +346,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_DEKU_TREE_MQ_WATER_ROOM_TORCHES, []{return logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_STICKS) && (ctx->GetTrickOption(RT_DEKU_MQ_LOG) || (logic->IsChild && logic->CanShield())));}), }, { //Locations - LOCATION(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_FRONT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_FRONT_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_FRONT_GRASS_3, logic->CanCutShrubs()), @@ -363,7 +363,7 @@ void RegionTable_Init_DekuTree() { }, { //Locations //it blocks the chest while stunned unless you stun it from afar while it's slightly off the ground - LOCATION(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanPassEnemy(RE_BIG_SKULLTULA)), + LOCATION(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanPassEnemy(RE_BIG_SKULLTULA) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_BACK_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_BACK_GRASS_2, logic->CanCutShrubs()), }, { 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 a0f380fd5a..8a68677175 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp @@ -28,7 +28,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_EYES_LIT, []{return ctx->GetTrickOption(RT_DC_EYES_CHU) && logic->CanUse(RG_BOMBCHU_5);}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);), + LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST);), LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, (logic->CanStunDeku() || logic->HasItem(RG_GORONS_BRACELET)) && GetCheckPrice() <= GetWalletCapacity()), LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET); }) && logic->CallGossipFairy()), LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET); }) && logic->CanUse(RG_SONG_OF_STORMS)), @@ -147,7 +147,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_COMPASS_ROOM] = Region("Dodongos Cavern Compass Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_COMPASS_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, []{return logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET);}), @@ -161,7 +161,7 @@ void RegionTable_Init_DodongosCavern() { 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_BOMB_FLOWER_PLATFORM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_BLADE_ROOM_HEART, true), LOCATION(RC_DODONGOS_CAVERN_FIRST_BRIDGE_GRASS, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_BLADE_GRASS, logic->CanCutShrubs()), @@ -225,7 +225,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER] = Region("Dodongos Cavern Bomb Room Upper", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_BLADE_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_BLADE_POT_2, logic->CanBreakPots()), }, { @@ -241,7 +241,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_LIFT_PLATFORM, []{return true;}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, logic->CanBreakMudWalls()), + LOCATION(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, logic->CanBreakMudWalls() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, []{return true;}), @@ -288,7 +288,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_EYES_LIT, []{return ctx->GetTrickOption(RT_DC_EYES_CHU) && logic->CanUse(RG_BOMBCHU_5);}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()), LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()), }, { @@ -317,7 +317,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_OUTSIDE_POES_ROOM] = Region("Dodongos Cavern MQ Outside Poes Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Events Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return true;}), @@ -390,7 +390,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM] = Region("Dodongos Cavern MQ Dodongo Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DODONGO) || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, (logic->CanKillEnemy(RE_DODONGO) || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()), @@ -431,7 +431,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM] = Region("Dodongos Cavern MQ Larvae Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, true), //implied logic->CanKillEnemy(RE_GOHMA_LARVA) based on entry reqs with a trick to kill with nuts + LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), //implied logic->CanKillEnemy(RE_GOHMA_LARVA) based on entry reqs with a trick to kill with nuts LOCATION(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, logic->CanBreakCrates()), //implied logic->CanKillEnemy(RE_GOLD_SKULTULLA) based on entry reqs. Add crate logic when BONKO is added LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CRATE_2, logic->CanBreakCrates()), @@ -476,7 +476,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, []{return logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER);}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_CORNER_POT, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_MIDDLE_POT, logic->CanBreakPots()), }, { @@ -582,7 +582,7 @@ void RegionTable_Init_DodongosCavern() { }); areaTable[RR_DODONGOS_CAVERN_MQ_BACK_POE_ROOM] = Region("Dodongos Cavern MQ Back Poe Room", SCENE_DODONGOS_CAVERN, {}, { - LOCATION(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, true), //pulling the grave isn't required, as you can open the chest through it + LOCATION(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, logic->HasItem(RG_OPEN_CHEST)), //pulling the grave isn't required, as you can open the chest through it LOCATION(RC_DODONGOS_CAVERN_MQ_BACKROOM_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_BACKROOM_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_BACK_POE_GRASS, logic->CanCutShrubs()), @@ -629,7 +629,7 @@ void RegionTable_Init_DodongosCavern() { && logic->CanKillEnemy(RE_KING_DODONGO);}), }, { // Locations - LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, logic->Get(LOGIC_DODONGOS_CAVERN_CLEAR)), LOCATION(RC_KING_DODONGO, logic->Get(LOGIC_DODONGOS_CAVERN_CLEAR)), }, { 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 a0d39399c3..a3c4be4336 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -27,7 +27,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_NEAR_BOSS_ROOM] = Region("Fire Temple Near Boss Room", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, logic->FireTimer() >= 16), + LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, logic->FireTimer() >= 16 && logic->HasItem(RG_OPEN_CHEST)), //It's plausible to get the pots with rang from the larger square platform, but it's a blind shot that likely needs a setup //and I've only been able to get the nearest 2, regardless it's a trick and probably a specific one like GY crate freestanding with rang }, { @@ -68,7 +68,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_FLARE_DANCER] = Region("Fire Temple Loop Flare Dancer", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_FLARE_DANCER);}) && (logic->IsAdult || logic->CanGroundJump() || logic->CanUse(RG_HOOKSHOT))), + LOCATION(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_FLARE_DANCER);}) && (logic->IsAdult || logic->CanGroundJump() || logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_5_TILE_ROOM, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_FLARE_DANCER);});}), @@ -86,7 +86,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_GORON_CAGE] = Region("Fire Temple Loop Goron Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_CAGE_SWITCH, []{return logic->Get(LOGIC_FIRE_LOOP_SWITCH);}), @@ -116,7 +116,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_1F_CURVED_CAGE] = Region("Fire Temple 1F Curved Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return true;}), @@ -134,7 +134,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_STRAIGHTFORWARD_CAGE] = Region("Fire Temple Straightforward Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return true;}), @@ -184,7 +184,7 @@ void RegionTable_Init_FireTemple() { EventAccess(LOGIC_FIRE_OPENED_UPPER_SHORTCUT, []{return true;}), }, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, []{return true;}), @@ -193,7 +193,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER] = Region("Fire Temple Boulder Maze Lower", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, logic->HasExplosives() && (logic->IsAdult || logic->HookshotOrBoomerang() || logic->CanGroundJumpJumpSlash())), }, { //Exits @@ -205,7 +205,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_3F_CURVED_CAGE] = Region("Fire Temple 3F Curved Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, []{return true;}), @@ -240,7 +240,7 @@ void RegionTable_Init_FireTemple() { //firetimer for entering this area from RR_FIRE_TEMPLE_FIRE_WALL_CHASE is handled there areaTable[RR_FIRE_TEMPLE_FIRE_WALL_CAGE] = Region("Fire Temple Fire Wall Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MAP_CHEST, logic->FireTimer() >= 8), + LOCATION(RC_FIRE_TEMPLE_MAP_CHEST, logic->FireTimer() >= 8 && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_NARROW_PATH_ROOM, []{return true;}), @@ -249,7 +249,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER] = Region("Fire Temple Boulder Maze Upper", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return logic->HasExplosives();}), @@ -276,7 +276,7 @@ void RegionTable_Init_FireTemple() { //RANDOTODO find a better name areaTable[RR_FIRE_TEMPLE_5F_RUINS] = Region("Fire Temple 5F Ruins", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_SCARECROW_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_SCARECROW_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)), }, { //Exits @@ -318,7 +318,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_CAGELESS_CHEST_ROOM] = Region("Fire Temple Cageless Chest Room", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_COMPASS_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_MAIN, []{return true;}), @@ -342,7 +342,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_SOT_CAGE_SWITCH] = Region("Fire Temple Sot Cage Switch", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return false;}), @@ -389,7 +389,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_NARROW_STAIRS] = Region("Fire Temple Narrow Stairs", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_SOT_CAGE_UPPER_DOOR, []{return logic->TakeDamage();}), @@ -464,7 +464,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOOP_CAGE_FOYER_SIDE] = Region("Fire Temple MQ Loop Cage Foyer Side", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE)), + LOCATION(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_FOYER_LOWER, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_LIKE_LIKE);});}), @@ -502,7 +502,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOOP_FLARE_DANCER] = Region("Fire Temple MQ Loop Flare Dancer", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanGroundJump()) && AnyAgeTime([]{return logic->CanKillEnemy(RE_FLARE_DANCER);})), + LOCATION(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanGroundJump()) && AnyAgeTime([]{return logic->CanKillEnemy(RE_FLARE_DANCER);}) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_LOOP_5_TILE_ROOM, []{return true;}), @@ -520,7 +520,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOOP_GORON_CAGE] = Region("Fire Temple MQ Loop Goron Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MAP_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_LOOP_CAGE_SWITCH, []{return logic->Get(LOGIC_FIRE_OPENED_LOWEST_GORON_CAGE);}), @@ -530,10 +530,9 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM] = Region("Fire Temple MQ Near Boss Room", SCENE_FIRE_TEMPLE, {}, { //Locations //If we're using the south torch as the initial torch, or using FAs, we either have to cross to the north to remove the crate, or use a trick to ignore it - LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->FireTimer() >= 24 && ctx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && (logic->CanUse(RG_FIRE_ARROWS) || (logic->IsAdult && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW)))), + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->FireTimer() >= 24 && ctx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && (logic->CanUse(RG_FIRE_ARROWS) || (logic->IsAdult && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_1, logic->FireTimer() >= 24 && logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_2, logic->FireTimer() >= 24 && logic->CanBreakCrates()), - }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_FOYER_UPPER, []{return (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)) && (logic->FireTimer() >= 16 || (logic->Get(LOGIC_FIRE_HIT_PLATFORM) && logic->FireTimer() >= 8));}), @@ -551,7 +550,7 @@ void RegionTable_Init_FireTemple() { //Fairies cannot be used for this as it is time sensetive, and NL is only useful with sticks as it disables other magic while in use, so it's tunic or raw damage taking ability. //testing tells me you take 3 ticks of lava damage, which is 12 internal damage or 3/4 of a heart at x1 damage multiplier, performing this run //logic->EffectiveHealth() works in half hearts for whatever reason, meaning this needs a deeper refactor to be perfect, but it should be good enough for now - LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_DINS_FIRE) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_GORON_TUNIC) || logic->EffectiveHealth() >= 2 || (logic->CanUse(RG_NAYRUS_LOVE) && logic->CanUse(RG_STICKS)))))), + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_DINS_FIRE) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_GORON_TUNIC) || logic->EffectiveHealth() >= 2 || (logic->CanUse(RG_NAYRUS_LOVE) && logic->CanUse(RG_STICKS))))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_POT_1, logic->CanBreakPots()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_POT_2, logic->CanBreakPots()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_5, logic->CanBreakCrates()), @@ -567,7 +566,7 @@ void RegionTable_Init_FireTemple() { //Locations //If we have FAs, we can just remove the crate and use those to light the torches. //otherwise, with Dins, we first light them with dins and then use a bow shot - LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW))), + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, (logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_3, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_4, logic->CanBreakCrates()), }, { @@ -612,7 +611,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_TORCH_LOCKED_CAGE] = Region("Fire Temple MQ Torch Locked Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->HasFireSource()), + LOCATION(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, []{return true;}), @@ -623,7 +622,7 @@ void RegionTable_Init_FireTemple() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanUse(RG_HOOKSHOT);}), }, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_LAVA_TORCH_POT_1, logic->HookshotOrBoomerang()), LOCATION(RC_FIRE_TEMPLE_MQ_LAVA_TORCH_POT_2, logic->HookshotOrBoomerang()), }, { @@ -718,7 +717,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_3F_CURVED_CAGE] = Region("Fire Temple MQ 3F Curved Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SWITCH_DOOR, []{return true;}), @@ -726,7 +725,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_MAZE_CRATE_CAGE] = Region("Fire Temple MQ Maze Crate Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_2, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_3, logic->CanBreakCrates()), @@ -751,12 +750,12 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_MAZE_BOX_CAGE] = Region("Fire Temple MQ Maze Box Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, true), - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_1, logic->CanBreakCrates()), - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_2, logic->CanBreakCrates()), - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_3, logic->CanBreakCrates()), - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_SMALL_CRATE_1, logic->CanBreakSmallCrates()), - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_SMALL_CRATE_2, logic->CanBreakSmallCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_1, logic->CanBreakCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_2, logic->CanBreakCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_3, logic->CanBreakCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_SMALL_CRATE_1, logic->CanBreakSmallCrates()), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_SMALL_CRATE_2, logic->CanBreakSmallCrates()), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE, []{return true;}), @@ -789,7 +788,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_SHORTCUT_CAGE] = Region("Fire Temple MQ Shortcut Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_SHORTCUT_CLIMB, []{return logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);}), @@ -1006,7 +1005,7 @@ void RegionTable_Init_FireTemple() { //Locations //This requires nothing in N64 logic, but is tight enough to need rollspam with the one-point on which is stricter than I would normally consider in logic //Child basically needs the scarecrow or a bunny hood though due to a worse ledge grab. - LOCATION(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, logic->IsAdult || logic->ReachScarecrow()), + LOCATION(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, (logic->IsAdult || logic->ReachScarecrow()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //The dropdown here is unusual in that it hits 1 of 3 locations: RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_LOWER, RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_UPPER_DOOR, and RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_SWITCH 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 05253e5b2e..48a49f82d1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -20,7 +20,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_TREES] = Region("Forest Temple Trees", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_GS_FIRST_ROOM, (logic->IsAdult && logic->CanUse(RG_BOMB_BAG)) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOMBCHU_5) || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_FOREST_FIRST_GS) && (logic->CanJumpslashExceptHammer() || (logic->IsChild && logic->CanUse(RG_BOMB_BAG))))), }, { //Exits @@ -76,7 +76,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH)), + LOCATION(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_LOWER_STALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_LOWER_STALFOS_POT_2, logic->CanBreakPots()), }, { @@ -160,7 +160,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND] = Region("Forest Temple NE Courtyard Island", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, []{return true;}), @@ -181,7 +181,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MAP_ROOM] = Region("Forest Temple Map Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_BLUE_BUBBLE)), + LOCATION(RC_FOREST_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_BLUE_BUBBLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_LOWER, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_BLUE_BUBBLE);});}), @@ -201,7 +201,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_DRAINED_SEWER] = Region("Forest Temple Drained Well", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_WELL_WEST_HEART, true), LOCATION(RC_FOREST_TEMPLE_WELL_EAST_HEART, true), }, { @@ -217,7 +217,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_FLOORMASTER_ROOM] = Region("Forest Temple Floormaster Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, logic->CanDamage()), + LOCATION(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, logic->CanDamage() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER, []{return true;}), @@ -244,7 +244,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MIDDLE_BLOCK_PUSH_ROOM] = Region("Forest Temple Middle Block Push Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, logic->CanHitEyeTargets()), + LOCATION(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM, []{return true;}), @@ -273,7 +273,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_NW_HALLWAY_STRAIGHTENED] = Region("Forest Temple NW Hallway Straightened", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, []{return true;}), @@ -285,7 +285,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_JOELLE, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->Get(LOGIC_FOREST_JOELLE)), + LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->Get(LOGIC_FOREST_JOELLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_HALLWAY_TWISTED, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), @@ -298,7 +298,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3)), + LOCATION(RC_FOREST_TEMPLE_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_UPPER_STALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_UPPER_STALFOS_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_UPPER_STALFOS_POT_3, logic->CanBreakPots()), @@ -314,7 +314,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_BETH, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->Get(LOGIC_FOREST_BETH)), + LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->Get(LOGIC_FOREST_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_3, logic->CanBreakPots()), @@ -348,7 +348,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_FALLING_ROOM] = Region("Forest Temple Falling Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_SCARECROW_LEDGE, []{return true;}), @@ -385,7 +385,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_OPEN_BOSS_HALLWAY, []{return true;}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_BASEMENT_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_BASEMENT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_GS_BASEMENT, logic->HookshotOrBoomerang()), }, { //Exits @@ -399,7 +399,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_TREES] = Region("Forest Temple MQ Trees", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA, ED_SHORT_JUMPSLASH, false) || logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, (logic->CanPassEnemy(RE_BIG_SKULLTULA, ED_SHORT_JUMPSLASH, false) || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, []{return true;}), @@ -456,7 +456,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_WOLFOS);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH)), + LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_POT_2, logic->CanBreakPots()), }, { @@ -511,7 +511,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_STRAIGHT_HALLWAY] = Region("Forest Temple MQ Straight Hallway", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(SCENE_FOREST_TEMPLE, 3)), + LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(SCENE_FOREST_TEMPLE, 3) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_FLOORMASTER_ROOM, []{return true;}), @@ -546,7 +546,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_REDEAD_ROOM] = Region("Forest Temple MQ Redead Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, logic->CanKillEnemy(RE_REDEAD)), + LOCATION(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_REDEAD);});}), @@ -599,7 +599,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_DRAINED_WELL, []{return logic->CanHitEyeTargets();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)), + LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, (logic->Get(LOGIC_FOREST_DRAINED_WELL) && logic->HasItem(RG_OPEN_CHEST)) || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)), LOCATION(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), //implies logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) LOCATION(RC_FOREST_TEMPLE_MQ_GS_WELL, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))), @@ -627,7 +627,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES] = Region("Forest Temple MQ Courtyard Top Ledges", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE, []{return true;}), @@ -641,7 +641,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND] = Region("Forest Temple MQ NE Courtyard Island", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //Skipping swim here is non-trival, needs a roll-jump. If a swim lock is added it's probably wise to copy deku baba events here @@ -659,7 +659,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_JOELLE, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_MAP_CHEST, logic->Get(LOGIC_FOREST_JOELLE)), + LOCATION(RC_FOREST_TEMPLE_MQ_MAP_CHEST, logic->Get(LOGIC_FOREST_JOELLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 4);}), @@ -672,7 +672,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_WOLFOS);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3)), + LOCATION(RC_FOREST_TEMPLE_MQ_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_3, logic->CanBreakPots()), @@ -688,7 +688,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_BETH, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_FOREST_BETH)), + LOCATION(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_FOREST_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_3, logic->CanBreakPots()), @@ -715,7 +715,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_FALLING_ROOM] = Region("Forest Temple MQ Falling Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_LEDGE_ABOVE_ISLAND, []{return true;}), @@ -747,7 +747,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_OPEN_BOSS_HALLWAY, []{return logic->CanHitEyeTargets();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, []{return true;}), 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 b96441b31a..72c83d475a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp @@ -63,7 +63,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_FOREST_TRIAL_WOLFOS_ROOM] = Region("Ganon's Castle Forest Trial Wolfos Room", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanKillEnemy(RE_WOLFOS)), + LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanKillEnemy(RE_WOLFOS) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MAIN, []{return true;}), @@ -137,8 +137,8 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP);}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, true), + LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MAIN, []{return true;}), @@ -177,7 +177,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL_START] = Region("Ganon's Castle Shadow Trial Start", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MAIN, []{return true;}), @@ -201,7 +201,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_SHADOW_TRIAL_RUSTED_SWITCH, []{return (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_MEGATON_HAMMER);}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_LOWER_SWITCH)), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_LOWER_SWITCH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_1, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_BOOMERANG)), LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_2, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_BOOMERANG)), LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_3, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_BOOMERANG)), @@ -256,7 +256,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL_BEFORE_SWITCH] = Region("Ganon's Castle Spirit Trial Before Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, logic->CanJumpslash() || logic->HasExplosives() || logic->CanUse(RG_GIANTS_KNIFE)), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (logic->CanJumpslash() || logic->HasExplosives() || logic->CanUse(RG_GIANTS_KNIFE)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL_BEAMOS_ROOM, []{return true;}), @@ -265,8 +265,8 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL_AFTER_SWITCH] = Region("Ganon's Castle Spirit Trial After Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, logic->CanHitSwitch()), - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, logic->CanHitSwitch() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL_BEFORE_SWITCH, []{return true;}), @@ -288,13 +288,13 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL_CHESTS_ROOM] = Region("Ganon's Castle Light Trial Chests Room", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanKillEnemy(RE_BIG_SKULLTULA) && logic->CanKillEnemy(RE_KEESE, ED_CLOSE, true, 3))), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanKillEnemy(RE_BIG_SKULLTULA) && logic->CanKillEnemy(RE_KEESE, ED_CLOSE, true, 3)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MAIN, []{return true;}), @@ -303,7 +303,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL_TRIFORCE_ROOM] = Region("Ganon's Castle Light Trial Triforce Room", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL_CHESTS_ROOM, []{return true;}), @@ -400,7 +400,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST, []{return logic->CanHitEyeTargets();}) }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, logic->Get(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, logic->Get(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_FOREST_TRIAL_STALFOS_ROOM, []{return true;}), @@ -412,7 +412,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST, []{return logic->CanHitEyeTargets();}) }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, logic->HasFireSource()), + LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_FOREST_TRIAL_BEAMOS_ROOM, []{return logic->Get(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST) && (logic->CanAvoidEnemy(RE_BEAMOS) || logic->CanKillEnemy(RE_ARMOS)) && logic->CanUse(RG_LONGSHOT);}), @@ -462,7 +462,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->CanJumpslash() || logic->HasExplosives();}), // bow can also hit at right angle }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, logic->BlueFire()), + LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_HEART, logic->BlueFire()), }, { //Exits @@ -513,7 +513,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_SHADOW_TRIAL_FIRST_CHEST, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE, []{return logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS));}), @@ -542,7 +542,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_SIDE] = Region("Ganon's Castle MQ Shadow Trial Far Side", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets()), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH, []{return logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOVER_BOOTS);}), @@ -574,7 +574,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_BEFORE_SWITCH] = Region("Ganon's Castle MQ Spirit Trial Before Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, logic->CanPassEnemy(RE_GREEN_BUBBLE)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, logic->CanPassEnemy(RE_GREEN_BUBBLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM, []{return true;}), @@ -583,12 +583,12 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_AFTER_SWITCH] = Region("Ganon's Castle MQ Spirit Trial After Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), //better names for these would be nice. - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_BEFORE_SWITCH, []{return AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5);});}), @@ -617,7 +617,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_TRIFORCE_ROOM] = Region("Ganon's Castle MQ Light Trial Triforce Room", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_DINOLFOS_ROOM, []{return true;}), @@ -690,7 +690,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_TOWER_FLOOR_2] = Region("Ganon's Tower Floor 2", SCENE_GANONS_TOWER, {}, { //Locations - LOCATION(RC_GANONS_TOWER_BOSS_KEY_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)), + LOCATION(RC_GANONS_TOWER_BOSS_KEY_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_TOWER_STAIRS_2, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);});}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp index 6cf954250c..6c3b3fdbdb 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp @@ -18,8 +18,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_LOBBY] = Region("Gerudo Training Ground Lobby", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, logic->CanHitEyeTargets()), - LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, logic->CanHitEyeTargets()), + LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { //Exits @@ -31,7 +31,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_SAND_ROOM] = Region("Gerudo Training Ground Sand Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_LOBBY, []{return true;}), @@ -45,11 +45,11 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE] = Region("Gerudo Training Ground Central Maze", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3) && (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 4)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 6)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 7)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 9)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3) && (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 4) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 6) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 7) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 9) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_LOBBY, []{return true;}), @@ -58,8 +58,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT] = Region("Gerudo Training Ground Central Maze Right", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, true), }, { //Exits @@ -73,7 +73,7 @@ void RegionTable_Init_GerudoTrainingGround() { EventAccess(LOGIC_GTG_PUSHED_HEAVY_BLOCK, []{return logic->CanUse(RG_SILVER_GAUNTLETS);}), }, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 4, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 4, true) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_ROOM_UPPER, []{return (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || (logic->IsAdult && logic->CanGroundJump()));}), @@ -98,10 +98,10 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_LIKE_LIKE_ROOM] = Region("Gerudo Training Ground Like Like Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE)), - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE)), - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanPassEnemy(RE_LIKE_LIKE)), - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanPassEnemy(RE_LIKE_LIKE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_BEHIND_HEAVY_BLOCK, []{return true;}), @@ -116,7 +116,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_ABOVE_MAZE] = Region("Gerudo Training Ground Above Eye", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_EYE_STATUE_UPPER, []{return true;}), @@ -127,7 +127,7 @@ void RegionTable_Init_GerudoTrainingGround() { EventAccess(LOGIC_GTG_CLEARED_EYE_STATUE, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, logic->Get(LOGIC_GTG_CLEARED_EYE_STATUE)), + LOCATION(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, logic->Get(LOGIC_GTG_CLEARED_EYE_STATUE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_HAMMER_ROOM, []{return true;}), @@ -135,8 +135,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_HAMMER_ROOM] = Region("Gerudo Training Ground Hammer Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, logic->CanAttack()), - LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || (logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS))), + LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, logic->CanAttack() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, (logic->CanUse(RG_MEGATON_HAMMER) || (logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_EYE_STATUE_LOWER, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_FAIRY_BOW);}), @@ -161,7 +161,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_UNDERWATER] = Region("Gerudo Training Ground Underwater", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 24), + LOCATION(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 24 && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM, []{return true;}), @@ -169,7 +169,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_DINALFOS] = Region("Gerudo Training Dinalfos", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, logic->CanKillEnemy(RE_BEAMOS) && logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, logic->CanKillEnemy(RE_BEAMOS) && logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_SOUTH_HEART, true), LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_EAST_HEART, true), }, { @@ -184,8 +184,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_LOBBY] = Region("Gerudo Training Ground MQ Lobby", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_1, logic->CanBreakPots()), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_2, logic->CanBreakPots()), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_1, logic->CanBreakPots()), @@ -201,9 +201,9 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_BY_LOBBY] = Region("Gerudo Training Ground MQ Maze By Lobby", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, (ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), @@ -212,7 +212,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_FIRST_LOCK] = Region("Gerudo Training Ground MQ Maze First Lock", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 1);}), @@ -233,7 +233,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_SAND_ROOM] = Region("Gerudo Training Ground MQ Sand Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), @@ -254,7 +254,7 @@ void RegionTable_Init_GerudoTrainingGround() { }, { //Locations //implies logic->CanKillEnemy(RE_BIG_SKULLTULA) - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM, []{return true;}), @@ -270,7 +270,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_ROOM_BEHIND_BLOCK] = Region("Gerudo Training Ground MQ Room Behind Block", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations //implies logic->CanKillEnemy(RE_SPIKE) - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_FREEZARD)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_FREEZARD) && logic->HasItem(RG_OPEN_CHEST)), }, { Entrance(RR_GERUDO_TRAINING_GROUND_MQ_BEHIND_BLOCK, []{return true;}), }); @@ -285,7 +285,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAGENTA_FIRE_ROOM] = Region("Gerudo Training Ground MQ Magenta Fire Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, logic->Get(LOGIC_GTG_MQ_MAZE_SWITCH)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, logic->Get(LOGIC_GTG_MQ_MAZE_SWITCH) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE, []{return true;}), @@ -293,7 +293,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM] = Region("Gerudo Training Ground MQ Statue Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE, []{return logic->CanUse(RG_LONGSHOT);}), @@ -303,8 +303,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SLUG_ROOM] = Region("Gerudo Training Ground MQ Torch Slug Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations //implies logic->CanKillEnemy(RE_TORCH_SLUG) - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanHitSwitch(ED_BOMB_THROW)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}), @@ -368,7 +368,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER] = Region("Gerudo Training Ground MQ Underwater", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations //it is possible to snipe the stingers with bow or sling before dropping in, or just get really lucky, and avoid needing to take damage, but that might be trick worthy - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, logic->HasFireSource() && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->HasItem(RG_BRONZE_SCALE) && logic->TakeDamage()), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, (logic->HasFireSource() && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->HasItem(RG_BRONZE_SCALE) && logic->TakeDamage()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, []{return true;}), @@ -380,8 +380,8 @@ void RegionTable_Init_GerudoTrainingGround() { EventAccess(LOGIC_GTG_PLATFORM_SILVER_RUPEES, []{return logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS);}), }, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), @@ -400,7 +400,7 @@ void RegionTable_Init_GerudoTrainingGround() { //is logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true) && logic->CanKillEnemy(RE_ARMOS, ED_CLOSE, true, 1, true) broken down to exclude sticks, as it takes too many to clear the room //Proper enemy kill room ammo logic is needed to handle this room //some combinations may be impossible without taking damage, keep an eye out for issues here - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_BOW) || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT)))), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_BOW) || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp index 9def568508..a8afc9004e 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp @@ -48,7 +48,7 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), }, { //Locations - LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire()), + LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)), // very easy to break pot through ice LOCATION(RC_ICE_CAVERN_FROZEN_POT_1, (logic->CanBreakPots() && logic->BlueFire()) || logic->HasExplosives() || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && ((logic->CanStandingShield() && logic->CanUse(RG_KOKIRI_SWORD)) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER))) || @@ -66,7 +66,7 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), }, { //Locations - LOCATION(RC_ICE_CAVERN_COMPASS_CHEST, (logic->IsChild || logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP)) && logic->BlueFire()), + LOCATION(RC_ICE_CAVERN_COMPASS_CHEST, (logic->IsChild || logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP)) && logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_ICE_CAVERN_FREESTANDING_POH, (logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP)) && logic->BlueFire()), // can skip blue fire with rang trick LOCATION(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, logic->HookshotOrBoomerang()), }, { @@ -104,8 +104,8 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_FINAL_ROOM] = Region("Ice Cavern Final Room", SCENE_ICE_CAVERN, {}, { //Locations - LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_WOLFOS);})), - LOCATION(RC_SHEIK_IN_ICE_CAVERN, AnyAgeTime([]{return logic->CanKillEnemy(RE_WOLFOS);})), // rando enables this for child + LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_WOLFOS);}) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHEIK_IN_ICE_CAVERN, AnyAgeTime([]{return logic->CanKillEnemy(RE_WOLFOS);}) && logic->HasItem(RG_OPEN_CHEST)), // rando enables this for child }, { //Exits Entrance(RR_ICE_CAVERN_BEFORE_FINAL_ROOM, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_WOLFOS);});}), @@ -165,7 +165,7 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->IsChild || logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP);}), }, { //Locations - LOCATION(RC_ICE_CAVERN_MQ_MAP_CHEST, logic->BlueFire() && AnyAgeTime([]{return logic->CanHitSwitch();})), + LOCATION(RC_ICE_CAVERN_MQ_MAP_CHEST, logic->BlueFire() && AnyAgeTime([]{return logic->CanHitSwitch();}) && logic->HasItem(RG_OPEN_CHEST)), }, {}); areaTable[RR_ICE_CAVERN_MQ_SCARECROW_ROOM] = Region("Ice Cavern MQ Scarecrow Room", SCENE_ICE_CAVERN, { @@ -197,7 +197,7 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), }, { //Locations - LOCATION(RC_ICE_CAVERN_MQ_COMPASS_CHEST, true), + LOCATION(RC_ICE_CAVERN_MQ_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), //It is possible for child with master, BGS or sticks, or adult with BGS, to hit this switch through the ice with a crouchstab, but it's precise and unintuitive for a trick LOCATION(RC_ICE_CAVERN_MQ_FREESTANDING_POH, logic->HasExplosives()), // can get with rang trick //doing RT_ICE_MQ_RED_ICE_GS as child is untested, as I could not perform the trick reliably even as adult @@ -209,8 +209,8 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_MQ_STALFOS_ROOM] = Region("Ice Cavern MQ Stalfos Room", SCENE_ICE_CAVERN, {}, { //Locations - LOCATION(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, logic->CanKillEnemy(RE_STALFOS)), - LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->CanKillEnemy(RE_STALFOS)), // rando enables this for child + LOCATION(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, logic->CanKillEnemy(RE_STALFOS) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->CanKillEnemy(RE_STALFOS) && logic->HasItem(RG_OPEN_CHEST)), // rando enables this for child }, { //Exits Entrance(RR_ICE_CAVERN_MQ_WEST_CORRIDOR, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS);});}), 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 ec0d324575..79d971e4d1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -130,7 +130,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_JABU_WEST_TENTACLE, []{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->Get(LOGIC_JABU_WEST_TENTACLE)), + LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->Get(LOGIC_JABU_WEST_TENTACLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, []{return true;}), @@ -146,7 +146,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_FORK_NORTH_WEST] = Region("Jabu Jabus Belly Fork North West", SCENE_JABU_JABU, {}, { //Locations //ruto could theoretically clear this room, but it's hard because of the timer and she doesn't appear with you when you respawn after failing, which would force a savewarp - LOCATION(RC_JABU_JABUS_BELLY_COMPASS_CHEST, logic->CanKillEnemy(RE_SHABOM, ED_CLOSE, false, 9)), + LOCATION(RC_JABU_JABUS_BELLY_COMPASS_CHEST, logic->CanKillEnemy(RE_SHABOM, ED_CLOSE, false, 9) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_TO_FORK_NORTH_WEST, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_SHABOM, ED_CLOSE, false, 9);});}), @@ -186,7 +186,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_FORK_EAST] = Region("Jabu Jabus Belly Fork East", SCENE_JABU_JABU, {}, { //Locations //We can kill the Stingers with ruto - LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, logic->Get(LOGIC_JABU_RUTO_IN_1F) || logic->CanKillEnemy(RE_STINGER, ED_CLOSE, true, 4)), + LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, (logic->Get(LOGIC_JABU_RUTO_IN_1F) || logic->CanKillEnemy(RE_STINGER, ED_CLOSE, true, 4)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, []{return true;}), @@ -259,8 +259,8 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, logic->BlastOrSmash()), - LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, logic->BlastOrSmash() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_GRASS_1, logic->CanCutShrubs()), @@ -276,7 +276,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_JABU_MQ_LIFT_ROOM_COW, []{return logic->CanUse(RG_FAIRY_SLINGSHOT);}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, true), + LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIFT_HEART_1, true), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIFT_HEART_2, true), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIFT_RUPEE_1, logic->CanUse(RG_IRON_BOOTS)), @@ -296,7 +296,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_JABU_MQ_HOLES_ROOM_DOOR, []{return true;}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, logic->CanHitSwitch(ED_HOOKSHOT, true) || (ctx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG) && logic->HasItem(RG_BRONZE_SCALE))), + LOCATION(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, (logic->CanHitSwitch(ED_HOOKSHOT, true) || (ctx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG) && logic->HasItem(RG_BRONZE_SCALE))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_GEYSER_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_GEYSER_POT_2, logic->CanBreakPots()), //Getting the ones closest to the ledge with rang may be a trick due to the awkward angle without blind shooting through the flesh @@ -329,8 +329,8 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_HOLES_BASEMENT] = Region("Jabu Jabus Belly MQ Holes Basement", SCENE_JABU_JABU, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), - LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_3, logic->CanCutShrubs()), @@ -347,12 +347,12 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_JABU_MQ_WATER_SWITCH_LIFT_ACCESS, []{return logic->CanKillEnemy(RE_LIZALFOS);}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, true), - LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanKillEnemy(RE_LIZALFOS)), - LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, (logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)) || (ctx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_JABU_JABUS_BELLY_MQ_TIME_BLOCK_POT_1, logic->CanBreakPots()), - LOCATION(RC_JABU_JABUS_BELLY_MQ_TIME_BLOCK_POT_2, logic->CanBreakPots()), - LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_BOOMERANG_GRASS, logic->CanCutShrubs()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanKillEnemy(RE_LIZALFOS) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, (logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)) || (ctx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_JABU_JABUS_BELLY_MQ_TIME_BLOCK_POT_1, logic->CanBreakPots()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_TIME_BLOCK_POT_2, logic->CanBreakPots()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_BOOMERANG_GRASS, logic->CanCutShrubs()), }, { //Exits //without swim, jump from rang chest to the other side @@ -368,7 +368,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR] = Region("Jabu Jabus Belly MQ Forked Corridor", SCENE_JABU_JABU, {}, {}, { //Exits - Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->CanUse(RG_BOOMERANG);}), + Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->CanUse(RG_BOOMERANG);}), //If some mode lets an age use sticks and not sling, and other use sling and not sticks, this needs changing Entrance(RR_JABU_JABUS_BELLY_MQ_TO_FORK_WEST, []{return true;}), Entrance(RR_JABU_JABUS_BELLY_MQ_TO_FORK_NORTH_WEST, []{return true;}), @@ -424,7 +424,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_FORK_NORTH_EAST] = Region("Jabu Jabus Belly MQ Fork North East", SCENE_JABU_JABU, {}, { //Locations //Implies CanKillEnemy(RE_LIKE_LIKE) - LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIKE_LIKES_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIKE_LIKES_POT_2, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_GRASS, logic->CanCutShrubs()), @@ -510,7 +510,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE] = Region("Jabu Jabus Belly MQ Lift Room East Ledge", SCENE_JABU_JABU, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, logic->Get(LOGIC_JABU_MQ_LIFT_ROOM_COW)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, logic->Get(LOGIC_JABU_MQ_LIFT_ROOM_COW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, []{return true;}), @@ -530,7 +530,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT))), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_GRASS_1, logic->CanCutShrubs()), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp index 45973796d6..44ae8080a9 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp @@ -65,7 +65,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_WHISPERING_WALLS_SIDE_ROOM] = Region("Shadow Temple Whispering Walls Side Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->CanKillEnemy(RE_KEESE)), + LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->CanKillEnemy(RE_KEESE) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST_POT_2, logic->CanBreakPots()), }, { @@ -75,7 +75,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_DEAD_HAND] = Region("Shadow Temple Dead Hand", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), + LOCATION(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_WHISPERING_WALLS_END, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_DEAD_HAND);});}), @@ -94,7 +94,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_COMPASS_ROOM] = Region("Shadow Temple Compass Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_COMPASS_CHEST, logic->CanKillEnemy(RE_GIBDO)), + LOCATION(RC_SHADOW_TEMPLE_COMPASS_CHEST, logic->CanKillEnemy(RE_GIBDO) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_FIRST_BEAMOS, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_GIBDO);});}), @@ -102,7 +102,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_SPINNING_BLADES] = Region("Shadow Temple Spinning Blades", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, ((logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_FIRST_BEAMOS, []{return true;}), @@ -148,7 +148,7 @@ void RegionTable_Init_ShadowTemple() { // See MQ for comments areaTable[RR_SHADOW_TEMPLE_STONE_UMBRELLA] = Region("Shadow Temple Stone Umbrella", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (logic->IsAdult && ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump() && logic->CanJumpslash())), LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_2, logic->CanBreakPots()), @@ -161,8 +161,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_STONE_UMBRELLA_UPPER] = Region("Shadow Temple Stone Umbrella Upper", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, true), - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, logic->HasItem(RG_OPEN_CHEST)), //Assuming the known setup for RT_SHADOW_UMBRELLA_HOVER and RT_SHADOW_UMBRELLA_GS, probably possible without sword + shield. LOCATION(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, ctx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD)), LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_3, logic->CanBreakPots()), @@ -180,8 +180,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_INVISIBLE_SPINNING_BLADES] = Region("Shadow Temple Invisible Spinning Blades", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_KEESE)), - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_KEESE) && (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_KEESE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_KEESE) && (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, AnyAgeTime([]{return logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_KEESE);}) && ((logic->IsAdult && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH)) || logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG))), //We cannot repeat the MQ invisible blades trick for these hearts as the like-like does not respawn if the room is cleared LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_LEFT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || logic->CanUse(RG_BOOMERANG)), @@ -193,7 +193,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_INVISIBLE_SPIKES] = Region("Shadow Temple Invisible Spikes", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->TakeDamage() || logic->CanUse(RG_GORON_TUNIC))), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->TakeDamage() || logic->CanUse(RG_GORON_TUNIC)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT_DOOR_LEDGE, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2);}), @@ -237,7 +237,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL_HINT_ROOM] = Region("Shadow Temple Wind Tunnel Hint Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, logic->CanKillEnemy(RE_REDEAD)), + LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits @@ -246,8 +246,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_ROOM_TO_BOAT] = Region("Shadow Temple Room to Boat", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 2)), - LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives()), + LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_POT_2, logic->CanBreakPots()), }, { @@ -313,7 +313,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_X_CROSS] = Region("Shadow Temple X-Cross", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanKillEnemy(RE_FLOORMASTER)), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanKillEnemy(RE_FLOORMASTER) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_FLOORMASTER_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_FLOORMASTER_POT_2, logic->CanBreakPots()), }, { @@ -331,8 +331,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_WOODEN_SPIKES] = Region("Shadow Temple Wooden Spikes", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE)), - LOCATION(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_POT_1, logic->CanBreakPots()), }, { //Exits @@ -406,7 +406,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_WHISPERING_WALLS_SIDE_ROOM] = Region("Shadow Temple MQ Whispering Walls Redeads", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_REDEAD)), + LOCATION(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_ENTRANCE_REDEAD_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_ENTRANCE_REDEAD_POT_2, logic->CanBreakPots()), }, { @@ -416,7 +416,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_WHISPERING_WALLS_DEAD_HAND] = Region("Shadow Temple MQ Whispering Walls Dead Hand", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), + LOCATION(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_WHISPERING_WALLS_END, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_DEAD_HAND);});}), @@ -436,7 +436,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_B2_GIBDO_ROOM] = Region("Shadow Temple MQ B2 Gibdo Room", SCENE_SHADOW_TEMPLE, {}, { //Locations //Doing this sets the shared flag for the glass in RR_SHADOW_TEMPLE_MQ_WHISPERING_WALLS, but doesn't seem to affect the chest - LOCATION(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, logic->CanKillEnemy(RE_GIBDO) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, logic->CanKillEnemy(RE_GIBDO) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_GIBDO);});}), @@ -444,7 +444,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM] = Region("Shadow Temple MQ B2 Spinning Blade Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())))), + LOCATION(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump()))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));});}), @@ -453,7 +453,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_SHORTCUT_PATH] = Region("Shadow Temple MQ Shortcut Path", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), @@ -497,9 +497,9 @@ void RegionTable_Init_ShadowTemple() { //you take half a heart base from a spit out, double check EffectiveHealth when damage logic gets reworked //Child is too small to get hit by the blades doesn't need the trick or lens for dodging them LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && - (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && - ((ctx->GetTrickOption(RT_LENS_SHADOW_MQ) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE))) || logic->CanUse(RG_LENS_OF_TRUTH))), + (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && + ((ctx->GetTrickOption(RT_LENS_SHADOW_MQ) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE))) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_LEFT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1) || logic->CanUse(RG_BOOMERANG)), LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_RIGHT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1) || logic->CanUse(RG_BOOMERANG)), }, { @@ -509,7 +509,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT] = Region("Shadow Temple MQ Lower Huge Pit", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, logic->CanUse(RG_LONGSHOT) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_B2_TO_B3_CORRIDOR_B3, []{return logic->CanUse(RG_LONGSHOT);}), @@ -525,7 +525,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM] = Region("Shadow Temple MQ Stone Umbrella Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (logic->IsAdult && ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump() && logic->CanJumpslash())), LOCATION(RC_SHADOW_TEMPLE_MQ_LOWER_UMBRELLA_WEST_POT, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_LOWER_UMBRELLA_EAST_POT, logic->CanBreakPots()), @@ -539,8 +539,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_STONE_UMBRELLA] = Region("Shadow Temple MQ Upper Stone Umbrella", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, true), - LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, logic->HasItem(RG_OPEN_CHEST)), //Assuming the known setup for RT_SHADOW_UMBRELLA_HOVER and RT_SHADOW_UMBRELLA_GS, probably possible without sword + shield. LOCATION(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, ctx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD)), LOCATION(RC_SHADOW_TEMPLE_MQ_UPPER_UMBRELLA_NORTH_POT, logic->CanBreakPots()), @@ -562,7 +562,7 @@ void RegionTable_Init_ShadowTemple() { (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC));}), }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->TakeDamage() || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_GORON_TUNIC))), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->TakeDamage() || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_GORON_TUNIC)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3);}), @@ -580,7 +580,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM] = Region("Shadow Temple MQ Stalfos Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)), + LOCATION(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);});}), @@ -601,7 +601,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_WIND_HINT_ROOM] = Region("Shadow Temple MQ Wind Hint Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanPassEnemy(RE_REDEAD)), + LOCATION(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanPassEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), LOCATION(RC_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { @@ -619,8 +619,8 @@ void RegionTable_Init_ShadowTemple() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO)), - LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, logic->HasExplosives()), LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_BOAT_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_BOAT_POT_2, logic->CanBreakPots()), @@ -708,7 +708,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_X_CROSS] = Region("Shadow Temple MQ X-Cross", SCENE_SHADOW_TEMPLE, {}, { //Locations //don't use CanDetonateUprightBombFlower as blue fire logic would need to account for player having multiple bottles & taking damage multiple times - LOCATION(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, (logic->CanUse(RG_LENS_OF_TRUTH) || ctx->GetTrickOption(RT_LENS_SHADOW_MQ_DEADHAND)) && logic->CanKillEnemy(RE_DEAD_HAND) && (logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, (logic->CanUse(RG_LENS_OF_TRUTH) || ctx->GetTrickOption(RT_LENS_SHADOW_MQ_DEADHAND)) && logic->CanKillEnemy(RE_DEAD_HAND) && (logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_DEAD_HAND_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_DEAD_HAND_POT_2, logic->CanBreakPots()), }, { @@ -718,7 +718,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_THREE_SKULL_JARS] = Region("Shadow Temple MQ Three Skull Jars", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, true), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, []{return true;}), @@ -726,8 +726,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_SPIKE_WALLS_ROOM] = Region("Shadow Temple MQ Spike Walls Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE)), - LOCATION(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_BARICADE_POT, logic->CanBreakPots()), }, { //Exits 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 4f37e3346c..cb3a97cfed 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -60,7 +60,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_CHILD_SWITCH_BRIDGE, []{return logic->CanHitSwitch();}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_SWITCH_BRIDGE_SOUTH, []{return logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_SPIRIT_CHILD_SWITCH_BRIDGE) && logic->CanPassEnemy(RE_GREEN_BUBBLE, ED_CLOSE, false));}), @@ -85,7 +85,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Locations // these assume SpiritRupeeBridge, silver rupee shuffle & shuffle climb will want to adjust - LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->HasFireSourceWithTorch()), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->HasFireSourceWithTorch() && logic->HasItem(RG_OPEN_CHEST)), // possible to collect without lowering fence, should be a trick LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)), }, { @@ -126,8 +126,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F] = Region("Spirit Temple Sun On Floor 2F", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanHitSwitch(ED_BOMB_THROW);})), - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanHitSwitch(ED_BOMB_THROW);})), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_OPEN_CHEST);})), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_OPEN_CHEST);})), LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->TakeDamage() ? ED_SHORT_JUMPSLASH : ED_BOMB_THROW);}, false, RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG);})), LOCATION(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash())), @@ -148,7 +148,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_SAND_PIT] = Region("Spirit Temple Sand Pit", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_COMPASS_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER)))), + LOCATION(RC_SPIRIT_TEMPLE_COMPASS_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_ADULT_SIDE_HUB, []{return true;}), @@ -177,7 +177,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_PAST_BOULDERS] = Region("Spirit Temple Past Boulders", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits @@ -192,8 +192,8 @@ 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_OPEN_CHEST)/*&& (str0 || SunlightArrows())*/;})), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return logic->HasItem(RG_OPEN_CHEST)/*&& (str0 || SunlightArrows())*/;})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_1F_MIRROR_ROOM, []{return true;}), @@ -204,7 +204,7 @@ void RegionTable_Init_SpiritTemple() { //Locations //Assumes RR_SPIRIT_TEMPLE_STATUE_ROOM access LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW));}, false, - RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource();})), + RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource();}) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT);}, false, RR_SPIRIT_TEMPLE_INNER_WEST_HAND, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE) ? ED_BOOMERANG : ED_HOOKSHOT);}, RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA);})), @@ -251,7 +251,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM] = Region("Spirit Temple Statue Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource();}, false, - RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW));})), + RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW));}) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->CanBreakPots();})), @@ -304,7 +304,7 @@ void RegionTable_Init_SpiritTemple() { 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->CanUse(RG_STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW)/* && str0*/)));}) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM, []{return true;}), @@ -335,7 +335,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND] = Region("Spirit Temple Outer Right Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND, []{return true;})), + LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND, []{return logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_RIGHT_HAND_EXIT, []{return true;}), @@ -358,7 +358,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_INNER_LEFT_HAND] = Region("Spirit Temple Inner Left Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations //Assumes RR_SPIRIT_TEMPLE_INNER_WEST_HAND access via RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD and RR_SPIRIT_TEMPLE_STATUE_ROOM. - LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, []{return logic->CanUse(RG_ZELDAS_LULLABY)/* && CanClimb()*/;})), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, []{return logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST)/* && CanClimb()*/;})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}), @@ -374,7 +374,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Locations //Assumes RR_SPIRIT_TEMPLE_INNER_LEFT_HAND access - LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return logic->CanUse(RG_ZELDAS_LULLABY);})), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, []{return true;}), @@ -404,7 +404,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_4_ARMOS] = Region("Spirit Temple 4 Armos", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, (logic->CanUse(RG_MIRROR_SHIELD) || logic->SunlightArrows()) && logic->HasExplosives()), + LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, (logic->CanUse(RG_MIRROR_SHIELD) || logic->SunlightArrows()) && logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, logic->HasExplosives() && logic->CanUse(RG_SUNS_SONG)), }, { Entrance(RR_SPIRIT_TEMPLE_BEAMOS_PITS, []{return true;}), @@ -414,7 +414,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_4_ARMOS_SIDE_ROOM] = Region("Spirit Temple 4 Armos Side Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_4_ARMOS, []{return true;}), @@ -422,8 +422,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CHEST_STAIRS] = Region("Spirit Temple Chest Stairs", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)), - LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_4_ARMOS, []{return true;}), @@ -444,7 +444,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_OUTER_LEFT_HAND] = Region("Spirit Temple Outer Left Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_LEFT_HAND_EXIT, []{return true;}), @@ -480,9 +480,9 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_FAKE_DOORS_ROOM] = Region("Spirit Temple Fake Doors Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, (logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS)) || + LOCATION(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, ((logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS)) || (AnyAgeTime([]{return logic->CanHitEyeTargets() && logic->CanAvoidEnemy(RE_TORCH_SLUG, true, 4);}) - && logic->CanUse(RG_HOOKSHOT))), + && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_4F_CENTRAL, []{return true;}), @@ -509,7 +509,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_PUSHED_4F_MIRRORS, []{return logic->HasExplosives()/*&& str0*/;}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, (logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows()), + LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, ((logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_BIG_MIRROR_ROOM, []{return true;}), @@ -553,10 +553,10 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_FORWARDS_SPIRIT_ADULT, []{return logic->IsAdult;}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, true), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, AnyAgeTime([]{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->CanHitSwitch(ED_BOOMERANG)), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Get(LOGIC_SPIRIT_1F_SILVER_RUPEES)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, AnyAgeTime([]{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->CanHitSwitch(ED_BOOMERANG) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Get(LOGIC_SPIRIT_1F_SILVER_RUPEES) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_3, logic->CanBreakPots()), @@ -575,7 +575,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_MQ_CRAWL_BOULDER, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, logic->Get(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, logic->Get(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_SLUGMA_POT, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_LEFT_HEART, logic->CanHitEyeTargets()), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_RIGHT_HEART, logic->CanHitEyeTargets()), @@ -640,7 +640,7 @@ void RegionTable_Init_SpiritTemple() { 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)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->Get(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_TURNTABLE, []{return true;}), @@ -653,7 +653,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, []{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE, ED_BOOMERANG);}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //The bridge is a temp flag, so not a way to cross south to north in logic @@ -663,7 +663,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_1F_CHEST_SWITCH] = Region("Spirit Temple MQ West 1F Rusted Switch", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->HasItem(RG_OPEN_CHEST);}), EventAccess(LOGIC_SPIRIT_MQ_CRAWL_BOULDER, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}), }, {}, { //Exits @@ -685,9 +685,9 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR] = Region("Spirit Temple MQ Sun on Floor Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations //Implies CanKillEnemy(RE_LIKE_LIKE) - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return logic->CanKillEnemy(RE_BEAMOS);})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return logic->CanKillEnemy(RE_BEAMOS) && logic->HasItem(RG_OPEN_CHEST);})), //Sunlights only temp spawn this chest, which is unintuitive/a bug. - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return (logic->HasExplosives() || logic->SunlightArrows()) && logic->CanUse(RG_HOOKSHOT);})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return (logic->HasExplosives() || logic->SunlightArrows()) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->CanHitSwitch();}), @@ -760,7 +760,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_MQ_STATUE_ROOM_TORCHES, []{return logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && logic->CanUse(RG_DINS_FIRE));}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanHitEyeTargets();})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST);})), LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_2F_CENTER_EAST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_2F_WEST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_2F_EASTMOST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanBreakPots();})), @@ -787,7 +787,7 @@ 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*/;})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->HasItem(RG_OPEN_CHEST)/*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())*/) || (ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->CanUse(RG_BOOMERANG));})), @@ -819,7 +819,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND] = Region("Spirit Temple MQ Outer Right Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, []{return true;})), + LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, []{return logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits //If it is ever relevent for 1 age to spawn the mirror shield chest for the other can longshot across, it needs an eventAccess @@ -839,7 +839,7 @@ void RegionTable_Init_SpiritTemple() { //Locations //Hard child locked because pushing the block is a permanent flag that blocks the eye target and cannot be undone //but it resets as Child as a rando QoL feature - LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR, []{return logic->IsChild && logic->CanHitEyeTargets();})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR, []{return logic->IsChild && logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits //if going to RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_HOLE from here is ever relevant, there needs to be an event to handle the block @@ -873,8 +873,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_INNER_LEFT_HAND] = Region("Spirit Temple MQ Inner East Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanBreakCrates()), - }, { + LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanBreakCrates() && logic->HasItem(RG_OPEN_CHEST)), + }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_ADULT, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}), @@ -884,7 +884,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_CHEST_LEDGE] = Region("Spirit Temple MQ Chest Ledge", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}), @@ -927,7 +927,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SAND_PIT] = Region("Spirit Temple MQ Sand Pit", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, logic->CanKillEnemy(RE_PURPLE_LEEVER) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER)))), + LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, logic->CanKillEnemy(RE_PURPLE_LEEVER) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits @@ -954,7 +954,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SKULLTULA_ROOM] = Region("Spirit Temple MQ Skulltula Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits @@ -975,7 +975,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_BEAMOS_PITS] = Region("Spirit Temple MQ Beamos Pits", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->CanKillEnemy(RE_BEAMOS)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->CanKillEnemy(RE_BEAMOS) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanBreakSmallCrates()), }, { //Exits @@ -986,7 +986,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM] = Region("Spirit Temple MQ SoT Sun Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits @@ -1014,7 +1014,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_OUTER_LEFT_HAND] = Region("Spirit Temple MQ Outer Left Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, []{return logic->CanUse(RG_LONGSHOT);}), @@ -1024,7 +1024,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM] = Region("Spirit Temple MQ 3F Gibdo Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return true;}), @@ -1099,7 +1099,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_PUSHED_4F_MIRRORS, []{return ((logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows())/* && str0*/;}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return true;}), 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 e03026bae4..ec6d0c483e 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp @@ -175,7 +175,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_4_SPIKES_ROOM] = Region("Water Temple 4 Spikes Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MAP_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_SPIKE, ED_CLOSE, true, 4);})), + LOCATION(RC_WATER_TEMPLE_MAP_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_SPIKE, ED_CLOSE, true, 4);}) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_SIDE_TOWER_1F, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_SPIKE, ED_CLOSE, true, 4);});}), @@ -183,7 +183,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_CRACKED_WALL] = Region("Water Temple Cracked Wall", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, logic->WaterLevel(WL_LOW_OR_MID) || logic->CanOpenUnderwaterChest()), + LOCATION(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, (logic->WaterLevel(WL_LOW_OR_MID) && logic->HasItem(RG_OPEN_CHEST)) || logic->CanOpenUnderwaterChest()), }, { //Exits Entrance(RR_WATER_TEMPLE_SIDE_TOWER_2F, []{return true;}), @@ -191,7 +191,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_TORCH_ROOM] = Region("Water Temple Torch Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_TORCHES_CHEST, AnyAgeTime([]{return (logic->WaterLevel(WL_LOW) && logic->CanKillEnemy(RE_SHELL_BLADE, ED_CLOSE, true, 3)) || + LOCATION(RC_WATER_TEMPLE_TORCHES_CHEST, AnyAgeTime([]{return (logic->WaterLevel(WL_LOW) && logic->CanKillEnemy(RE_SHELL_BLADE, ED_CLOSE, true, 3) && logic->HasItem(RG_OPEN_CHEST)) || logic->CanOpenUnderwaterChest();})), }, { //Exits @@ -323,7 +323,7 @@ void RegionTable_Init_WaterTemple() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_WATER_TEMPLE_BOSS_KEY_CHEST, true), + LOCATION(RC_WATER_TEMPLE_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_BOSS_KEY_POT_1, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_BOSS_KEY_POT_2, logic->CanBreakPots()), }, { @@ -373,7 +373,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_DRAGON_ROOM] = Region("Water Temple Dragon Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, logic->HasItem(RG_BRONZE_SCALE) && + LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_OPEN_CHEST) && ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)) || (((logic->IsAdult && ctx->GetTrickOption(RT_WATER_ADULT_DRAGON)) || (logic->IsChild && ctx->GetTrickOption(RT_WATER_CHILD_DRAGON))) && logic->CanHitSwitch(ED_BOOMERANG, true) && (logic->HasItem(RG_SILVER_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8))))), @@ -418,7 +418,7 @@ void RegionTable_Init_WaterTemple() { //Assuming tunic and irons was checked on entry areaTable[RR_WATER_TEMPLE_PILLAR_B1] = Region("Water Temple Pillar B1", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE)), + LOCATION(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //Can't know water level, so we'll just assume any possibility and skip to MAIN @@ -427,7 +427,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_JET_CHEST_ROOM] = Region("Water Temple Jet Chest Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_COMPASS_CHEST, logic->CanUseProjectile()), + LOCATION(RC_WATER_TEMPLE_COMPASS_CHEST, logic->CanUseProjectile() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_NEAR_COMPASS_POT_1, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_NEAR_COMPASS_POT_2, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_NEAR_COMPASS_POT_3, logic->CanBreakPots()), @@ -477,7 +477,7 @@ void RegionTable_Init_WaterTemple() { //Currently assumes WL_LOW_OR_MID as there's no way to reach it on WL_HIGH in logic, this will need splitting if one is added areaTable[RR_WATER_TEMPLE_BLOCK_LOOP_BACK] = Region("Water Temple Block Loop Back", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, true), + LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_POT_1, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_POT_2, logic->CanBreakPots()), }, {}); @@ -564,7 +564,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_SOT_PIT_ROOM] = Region("Water Temple Song Of Time Pit Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_LONGSHOT_CHEST, true), + LOCATION(RC_WATER_TEMPLE_LONGSHOT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_DARK_LINK_ROOM, []{return true;}), @@ -601,8 +601,8 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_ABOVE_DRAGON] = Region("Water Temple Above Dragon", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_RIVER_CHEST, true), - LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, logic->IsAdult && logic->CanHitSwitch(ED_LONGSHOT) && logic->HasItem(RG_BRONZE_SCALE) && + LOCATION(RC_WATER_TEMPLE_RIVER_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, logic->IsAdult && logic->CanHitSwitch(ED_LONGSHOT) && logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->HasItem(RG_SILVER_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8))) || ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE))), }, { @@ -791,7 +791,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_SIDE_TOWER_2F] = Region("Water Temple MQ Side Tower 2F", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, logic->CanUse(RG_HOOKSHOT) && (logic->WaterLevel(WL_MID) || logic->CanOpenUnderwaterChest())), + LOCATION(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, logic->CanUse(RG_HOOKSHOT) && ((logic->WaterLevel(WL_MID) && logic->HasItem(RG_OPEN_CHEST)) || logic->CanOpenUnderwaterChest())), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_SIDE_TOWER_1F, []{return logic->WaterLevel(WL_LOW) || logic->CanUse(RG_IRON_BOOTS);}), @@ -812,7 +812,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_3_STALFOS_ROOM] = Region("Water Temple MQ 3 Stalfos Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_MAP_CHEST, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_WATER_TEMPLE_MQ_MAP_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_LOW_EMBLEM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 4);}), @@ -823,7 +823,7 @@ void RegionTable_Init_WaterTemple() { EventAccess(LOGIC_WATER_MQ_SIDE_TOWER_TARGETS, []{return logic->CanKillEnemy(RE_LIZALFOS) && logic->CanKillEnemy(RE_SPIKE);}), }, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_WATER_MQ_SIDE_TOWER_TARGETS)), + LOCATION(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_WATER_MQ_SIDE_TOWER_TARGETS) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_SIDE_TOWER_1F, []{return true;}), @@ -903,7 +903,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_PILLAR_B1_FINAL] = Region("Water Temple MQ Central Pillar B1 Final", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), }, {}); areaTable[RR_WATER_TEMPLE_MQ_STORAGE_ROOM] = Region("Water Temple MQ Storage Room", SCENE_WATER_TEMPLE, {}, { @@ -1181,7 +1181,7 @@ void RegionTable_Init_WaterTemple() { //Exits Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, []{return true;}), Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_PIT, []{return true;}), - Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, []{return logic->CanHitSwitch() && AnyAgeTime([]{return logic->CanUse(RG_DINS_FIRE);});}), + Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, []{return logic->CanHitSwitch() && AnyAgeTime([]{return logic->CanUse(RG_DINS_FIRE);}) && logic->HasItem(RG_OPEN_CHEST);}), }); //this exists for the crates in preparation for clips through the grate @@ -1199,7 +1199,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST] = Region("Water Temple MQ Boss Key Room Chest", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, true), + LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, []{return logic->CanHitSwitch(ED_BOMB_THROW) || logic->CanUse(RG_HOVER_BOOTS);}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp index 5d33722235..6b19d2342a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp @@ -109,7 +109,7 @@ void RegionTable_Init_DeathMountainCrater() { areaTable[RR_DMC_UPPER_GROTTO] = Region("DMC Upper Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_DMC_UPPER_GROTTO_CHEST, true), + LOCATION(RC_DMC_UPPER_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DMC_UPPER_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), 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 d59043ab48..51044348bb 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 @@ -10,7 +10,7 @@ void RegionTable_Init_DeathMountainTrail() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET));}), }, { //Locations - LOCATION(RC_DMT_CHEST, logic->BlastOrSmash() || (ctx->GetTrickOption(RT_DMT_BOMBABLE) && logic->IsChild && logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_DMT_CHEST, (logic->BlastOrSmash() || (ctx->GetTrickOption(RT_DMT_BOMBABLE) && logic->IsChild && logic->HasItem(RG_GORONS_BRACELET))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DMT_FREESTANDING_POH, logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET)))), LOCATION(RC_DMT_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_DMT_SOIL_GS) && (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_BOOMERANG)))), LOCATION(RC_DMT_GS_NEAR_KAK, logic->BlastOrSmash()), @@ -83,7 +83,7 @@ void RegionTable_Init_DeathMountainTrail() { areaTable[RR_DMT_STORMS_GROTTO] = Region("DMT Storms Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_DMT_STORMS_GROTTO_CHEST, true), + LOCATION(RC_DMT_STORMS_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DMT_STORMS_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp index f921c5483c..e5a6b0cd25 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp @@ -152,7 +152,7 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_NEAR_CHEST] = Region("GF Near Chest", SCENE_GERUDOS_FORTRESS, {}, { //Locations - LOCATION(RC_GF_CHEST, true), + LOCATION(RC_GF_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GF_GS_TOP_FLOOR, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) && logic->CanGetNightTimeGS()), }, { //Exits 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 370fdf0b1a..a1e3555bdb 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -68,7 +68,7 @@ void RegionTable_Init_GerudoValley() { areaTable[RR_GV_FORTRESS_SIDE] = Region("GV Fortress Side", SCENE_GERUDO_VALLEY, {}, { //Locations - LOCATION(RC_GV_CHEST, logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)))), + LOCATION(RC_GV_CHEST, logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GV_TRADE_SAW, logic->IsAdult && logic->CanUse(RG_POACHERS_SAW)), LOCATION(RC_GV_GS_BEHIND_TENT, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_GV_GS_PILLAR, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), 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 9641da2fae..57017f1a1d 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp @@ -18,9 +18,9 @@ void RegionTable_Init_GoronCity() { (ctx->GetTrickOption(RT_GC_LINK_GORON_DINS) && (logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE)))));}), }, { //Locations - LOCATION(RC_GC_MAZE_LEFT_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (ctx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS))), - LOCATION(RC_GC_MAZE_CENTER_CHEST, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)), - LOCATION(RC_GC_MAZE_RIGHT_CHEST, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_LEFT_CHEST, (logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (ctx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GC_MAZE_CENTER_CHEST, (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GC_MAZE_RIGHT_CHEST, (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GC_POT_FREESTANDING_POH, logic->IsChild && logic->Get(LOGIC_GORON_CITY_CHILD_FIRE) && (logic->CanUse(RG_BOMB_BAG) || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_POT_STRENGTH)) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_GC_POT)))), LOCATION(RC_GC_ROLLING_GORON_AS_CHILD, logic->IsChild && (logic->HasExplosives() || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_ROLLING_STRENGTH)))), LOCATION(RC_GC_ROLLING_GORON_AS_ADULT, logic->Get(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp index fc5ff2cc64..a393eb2e86 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp @@ -45,7 +45,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_SHIELD_GRAVE] = Region("Graveyard Shield Grave", SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, {}, { //Locations - LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, true), + LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_THE_GRAVEYARD, []{return true;}), @@ -69,7 +69,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_HEART_PIECE_GRAVE] = Region("Graveyard Heart Piece Grave", SCENE_REDEAD_GRAVE, {}, { //Locations - LOCATION(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, logic->CanUse(RG_SUNS_SONG)), + LOCATION(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, logic->CanUse(RG_SUNS_SONG) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_THE_GRAVEYARD, []{return true;}), @@ -77,7 +77,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_COMPOSERS_GRAVE] = Region("Graveyard Composers Grave", SCENE_ROYAL_FAMILYS_TOMB, {}, { //Locations - LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource()), + LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, logic->CanUseProjectile() || logic->CanJumpslash()), LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { @@ -90,7 +90,7 @@ void RegionTable_Init_Graveyard() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, true), + LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, logic->IsAdult || ctx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH)), LOCATION(RC_GY_DAMPES_GRAVE_POT_1, logic->CanBreakPots()), LOCATION(RC_GY_DAMPES_GRAVE_POT_2, logic->CanBreakPots()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp index b3730c982e..991a6eaa9a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp @@ -22,7 +22,7 @@ void RegionTable_Init_HauntedWasteland() { EventAccess(LOGIC_CARPET_MERCHANT, []{return logic->HasItem(RG_ADULT_WALLET) && GetCheckPrice(RC_WASTELAND_BOMBCHU_SALESMAN) <= GetWalletCapacity() && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS));}), }, { //Locations - LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource()), + LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) && GetCheckPrice() <= GetWalletCapacity()), LOCATION(RC_WASTELAND_GS, logic->HookshotOrBoomerang() || (logic->IsAdult && ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump() && logic->CanJumpslash())), // need to jumpslash immediately with two handed weapons LOCATION(RC_WASTELAND_NEAR_GS_POT_1, logic->CanBreakPots()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp index 83bbfcff7e..845188fd50 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp @@ -189,7 +189,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_SOUTHEAST_GROTTO] = Region("HF Southeast Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_HF_SOUTHEAST_GROTTO_CHEST, true), + LOCATION(RC_HF_SOUTHEAST_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_HF_SOUTHEAST_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), @@ -207,7 +207,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_OPEN_GROTTO] = Region("HF Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_HF_OPEN_GROTTO_CHEST, true), + LOCATION(RC_HF_OPEN_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_HF_OPEN_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), @@ -261,7 +261,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_NEAR_MARKET_GROTTO] = Region("HF Near Market Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_HF_NEAR_MARKET_GROTTO_CHEST, true), + LOCATION(RC_HF_NEAR_MARKET_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_HF_NEAR_MARKET_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index 77444333a7..04007ead25 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -247,7 +247,7 @@ void RegionTable_Init_Kakariko() { areaTable[RR_KAK_REDEAD_GROTTO] = Region("Kak Redead Grotto", SCENE_GROTTOS, {}, { //Locations - LOCATION(RC_KAK_REDEAD_GROTTO_CHEST, logic->CanKillEnemy(RE_REDEAD, ED_CLOSE, true, 2)), + LOCATION(RC_KAK_REDEAD_GROTTO_CHEST, logic->CanKillEnemy(RE_REDEAD, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_KAKARIKO_VILLAGE, []{return true;}), @@ -255,7 +255,7 @@ void RegionTable_Init_Kakariko() { areaTable[RR_KAK_OPEN_GROTTO] = Region("Kak Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_KAK_OPEN_GROTTO_CHEST, true), + LOCATION(RC_KAK_OPEN_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_KAK_OPEN_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp index 0588ea0c25..b20e7b4fbb 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -87,7 +87,7 @@ void RegionTable_Init_KokiriForest() { areaTable[RR_KF_BOULDER_LOOP] = Region("KF Boulder Loop", SCENE_KOKIRI_FOREST, {}, { //Locations - LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild), + LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_KF_BOULDER_RUPEE_1, logic->IsChild), LOCATION(RC_KF_BOULDER_RUPEE_2, logic->IsChild), LOCATION(RC_KF_CHILD_GRASS_MAZE_1, logic->IsChild && logic->CanCutShrubs()), @@ -129,10 +129,10 @@ void RegionTable_Init_KokiriForest() { areaTable[RR_KF_MIDOS_HOUSE] = Region("KF Mido's House", SCENE_MIDOS_HOUSE, {}, { //Locations - LOCATION(RC_KF_MIDOS_TOP_LEFT_CHEST, true), - LOCATION(RC_KF_MIDOS_TOP_RIGHT_CHEST, true), - LOCATION(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, true), - LOCATION(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, true), + LOCATION(RC_KF_MIDOS_TOP_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_KF_MIDOS_TOP_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_KOKIRI_FOREST, []{return true;}), @@ -184,7 +184,7 @@ void RegionTable_Init_KokiriForest() { areaTable[RR_KF_STORMS_GROTTO] = Region("KF Storms Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_KF_STORMS_GROTTO_CHEST, true), + LOCATION(RC_KF_STORMS_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_KF_STORMS_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp index 0dc3080961..186a3895e1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -92,7 +92,7 @@ void RegionTable_Init_LostWoods() { areaTable[RR_LW_NEAR_SHORTCUTS_GROTTO] = Region("LW Near Shortcuts Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, true), + LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index f6cdecde11..f06a830740 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -193,17 +193,17 @@ void RegionTable_Init_Market() { areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Region("Market Treasure Chest Game", SCENE_TREASURE_BOX_SHOP, {}, { //Locations LOCATION(RC_GREG_HINT, logic->HasItem(RG_CHILD_WALLET)), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->HasItem(RG_CHILD_WALLET) && ((logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), }, { //Exits Entrance(RR_THE_MARKET, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp index c813a81215..b838e890c5 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp @@ -57,7 +57,7 @@ void RegionTable_Init_SacredForestMeadow() { areaTable[RR_SFM_WOLFOS_GROTTO] = Region("SFM Wolfos Grotto", SCENE_GROTTOS, {}, { //Locations - LOCATION(RC_SFM_WOLFOS_GROTTO_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 2)), + LOCATION(RC_SFM_WOLFOS_GROTTO_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SFM_ENTRYWAY, []{return true;}), 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 b1ad49080c..bf931f5ae6 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp @@ -16,7 +16,7 @@ void RegionTable_Init_ZorasDomain() { }, { //Locations LOCATION(RC_ZD_DIVING_MINIGAME, logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_CHILD_WALLET) && logic->IsChild), - LOCATION(RC_ZD_CHEST, logic->IsChild && logic->CanUse(RG_STICKS)), + LOCATION(RC_ZD_CHEST, logic->IsChild && logic->CanUse(RG_STICKS) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_ZD_KING_ZORA_THAWED, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED)), LOCATION(RC_ZD_TRADE_PRESCRIPTION, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED) && logic->CanUse(RG_PRESCRIPTION)), LOCATION(RC_ZD_GS_FROZEN_WATERFALL, logic->IsAdult && (logic->HookshotOrBoomerang() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || (logic->CanUse(RG_MAGIC_SINGLE) && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))) || (ctx->GetTrickOption(RT_ZD_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), 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 883a3f8a74..911d1630ec 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp @@ -109,7 +109,7 @@ void RegionTable_Init_ZoraRiver() { areaTable[RR_ZR_OPEN_GROTTO] = Region("ZR Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_ZR_OPEN_GROTTO_CHEST, true), + LOCATION(RC_ZR_OPEN_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_ZR_OPEN_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index c27918aec1..00f65a7d6f 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -229,6 +229,8 @@ bool Logic::HasItem(RandomizerGet itemName) { return CurrentUpgrade(UPG_SCALE) >= 2; case RG_CRAWL: return CheckRandoInf(RAND_INF_CAN_CRAWL); + case RG_OPEN_CHEST: + return CheckRandoInf(RAND_INF_CAN_OPEN_CHEST); case RG_POCKET_EGG: return CheckRandoInf(RAND_INF_ADULT_TRADES_HAS_POCKET_EGG); case RG_COJIRO: @@ -462,7 +464,8 @@ bool Logic::CanMiddairGroundJump(bool hasBombflower) { } bool Logic::CanOpenUnderwaterChest() { - return ctx->GetTrickOption(RT_OPEN_UNDERWATER_CHEST) && CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT); + return ctx->GetTrickOption(RT_OPEN_UNDERWATER_CHEST) && CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT) && + HasItem(RG_OPEN_CHEST); } uint8_t GetDifficultyValueFromString(Rando::Option& glitchOption) { @@ -1720,6 +1723,9 @@ void Logic::ApplyItemEffect(Item& item, bool state) { case RG_CRAWL: SetRandoInf(RAND_INF_CAN_CRAWL, state); break; + case RG_OPEN_CHEST: + SetRandoInf(RAND_INF_CAN_OPEN_CHEST, state); + break; case RG_PROGRESSIVE_HOOKSHOT: { uint8_t i; for (i = 0; i < 3; i++) { @@ -2588,6 +2594,11 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { SetRandoInf(RAND_INF_CAN_CRAWL, true); } + // If we're not shuffling open chest, we start with it + if (ctx->GetOption(RSK_SHUFFLE_OPEN_CHEST).Is(false)) { + SetRandoInf(RAND_INF_CAN_OPEN_CHEST, true); + } + // 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 c200135a58..3e5e76c196 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -257,6 +257,7 @@ void Settings::CreateOptionDescriptions() { "If you enter a water entrance without swim you will be respawned on land to prevent infinite death loops.\n" "If you void out in Water Temple you will immediately be kicked out to prevent a softlock."; mOptionDescriptions[RSK_SHUFFLE_CRAWL] = "Shuffles the ability to use crawlspaces into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST] = "Shuffles the ability to open chests into the item pool."; mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG] = "Shuffles the Weird Egg from Malon in to the item pool. Enabling " "\"Skip Child Zelda\" disables this feature.\n" "\n" diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 88a4fddd96..140c3e38f6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3649,6 +3649,7 @@ std::map randomizerGetToRandInf = { { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }, { RG_BRONZE_SCALE, RAND_INF_CAN_SWIM }, { RG_CRAWL, RAND_INF_CAN_CRAWL }, + { RG_OPEN_CHEST, RAND_INF_CAN_OPEN_CHEST }, { 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 1cbc2bb162..8e6dbefbdd 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -4606,6 +4606,7 @@ typedef enum { RG_TYCOON_WALLET, RG_BRONZE_SCALE, RG_CRAWL, + RG_OPEN_CHEST, RG_CHILD_WALLET, RG_PROGRESSIVE_BOMBCHU_BAG, RG_QUIVER_INF, @@ -5807,6 +5808,7 @@ typedef enum { RHT_OCARINA_C_RIGHT_BUTTON, RHT_BRONZE_SCALE, RHT_CRAWL, + RHT_OPEN_CHEST, RHT_FISHING_POLE, RHT_SKELETON_KEY, RHT_EPONA, @@ -6403,6 +6405,7 @@ typedef enum { RSK_SHUFFLE_OCARINA_BUTTONS, RSK_SHUFFLE_SWIM, RSK_SHUFFLE_CRAWL, + RSK_SHUFFLE_OPEN_CHEST, 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 b0eae93427..c81bff8187 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -1140,6 +1140,7 @@ DEFINE_RAND_INF(RAND_INF_CAUGHT_LOACH) DEFINE_RAND_INF(RAND_INF_CAN_SWIM) DEFINE_RAND_INF(RAND_INF_CAN_CRAWL) +DEFINE_RAND_INF(RAND_INF_CAN_OPEN_CHEST) DEFINE_RAND_INF(RAND_INF_HAS_WALLET) diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index dc35afdfa1..34a46a5f40 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -317,6 +317,10 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetRandomizerInf(RAND_INF_CAN_CRAWL); } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_OPEN_CHEST) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_OPEN_CHEST); + } + 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 8652bb5ef8..7ab293b90e 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -779,6 +779,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_CRAWL, "Shuffle Crawl", CVAR_RANDOMIZER_SETTING("ShuffleCrawl"), mOptionDescriptions[RSK_SHUFFLE_CRAWL]); + OPT_BOOL(RSK_SHUFFLE_OPEN_CHEST, "Shuffle Open Chest", CVAR_RANDOMIZER_SETTING("ShuffleOpenChest"), mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST]); OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]); OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); 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); @@ -2390,6 +2391,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], &mOptions[RSK_SHUFFLE_CRAWL], + &mOptions[RSK_SHUFFLE_OPEN_CHEST], &mOptions[RSK_SHUFFLE_BEAN_SOULS], &mOptions[RSK_ROCS_FEATHER], &mOptions[RSK_BOMBCHU_BAG], @@ -2608,6 +2610,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], &mOptions[RSK_SHUFFLE_CRAWL], + &mOptions[RSK_SHUFFLE_OPEN_CHEST], &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 025aeb9765..e47af88aae 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -7387,46 +7387,48 @@ s32 Player_ActionHandler_2(Player* this, PlayState* play) { !(this->stateFlags1 & PLAYER_STATE1_CARRYING_ACTOR) && !(this->stateFlags2 & PLAYER_STATE2_UNDERWATER)) { if (this->getItemId != GI_NONE) { - GetItemEntry giEntry; - if (this->getItemEntry.objectId == OBJECT_INVALID) { - giEntry = ItemTable_Retrieve(-this->getItemId); - } else { - giEntry = this->getItemEntry; - } - EnBox* chest = (EnBox*)interactedActor; - if (giEntry.itemId != ITEM_NONE) { - if (((Item_CheckObtainability(giEntry.itemId) == ITEM_NONE) && (giEntry.field & 0x40)) || - ((Item_CheckObtainability(giEntry.itemId) != ITEM_NONE) && (giEntry.field & 0x20))) { - this->getItemId = -GI_RUPEE_BLUE; - giEntry = ItemTable_Retrieve(GI_RUPEE_BLUE); + if (GameInteractor_Should(VB_OPEN_CHEST, true)) { + GetItemEntry giEntry; + if (this->getItemEntry.objectId == OBJECT_INVALID) { + giEntry = ItemTable_Retrieve(-this->getItemId); + } else { + giEntry = this->getItemEntry; + } + EnBox* chest = (EnBox*)interactedActor; + if (giEntry.itemId != ITEM_NONE) { + if (((Item_CheckObtainability(giEntry.itemId) == ITEM_NONE) && (giEntry.field & 0x40)) || + ((Item_CheckObtainability(giEntry.itemId) != ITEM_NONE) && (giEntry.field & 0x20))) { + this->getItemId = -GI_RUPEE_BLUE; + giEntry = ItemTable_Retrieve(GI_RUPEE_BLUE); + } } - } - if (GameInteractor_Should(VB_GIVE_ITEM_FROM_CHEST, true, chest)) { - Player_SetupWaitForPutAway(play, this, func_8083A434); - } - this->stateFlags1 |= - PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_CARRYING_ACTOR | PLAYER_STATE1_IN_CUTSCENE; - func_8083AE40(this, giEntry.objectId); + if (GameInteractor_Should(VB_GIVE_ITEM_FROM_CHEST, true, chest)) { + Player_SetupWaitForPutAway(play, this, func_8083A434); + } + this->stateFlags1 |= + PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_CARRYING_ACTOR | PLAYER_STATE1_IN_CUTSCENE; + func_8083AE40(this, giEntry.objectId); - this->actor.world.pos.x = - chest->dyna.actor.world.pos.x - (Math_SinS(chest->dyna.actor.shape.rot.y) * 29.4343f); - this->actor.world.pos.z = - chest->dyna.actor.world.pos.z - (Math_CosS(chest->dyna.actor.shape.rot.y) * 29.4343f); - this->yaw = this->actor.shape.rot.y = chest->dyna.actor.shape.rot.y; - func_80832224(this); + this->actor.world.pos.x = + chest->dyna.actor.world.pos.x - (Math_SinS(chest->dyna.actor.shape.rot.y) * 29.4343f); + this->actor.world.pos.z = + chest->dyna.actor.world.pos.z - (Math_CosS(chest->dyna.actor.shape.rot.y) * 29.4343f); + this->yaw = this->actor.shape.rot.y = chest->dyna.actor.shape.rot.y; + func_80832224(this); - bool vanillaPlaySlowChestCS = (giEntry.itemId != ITEM_NONE) && (giEntry.gi >= 0) && - (Item_CheckObtainability(giEntry.itemId) == ITEM_NONE); + bool vanillaPlaySlowChestCS = (giEntry.itemId != ITEM_NONE) && (giEntry.gi >= 0) && + (Item_CheckObtainability(giEntry.itemId) == ITEM_NONE); - if (GameInteractor_Should(VB_PLAY_SLOW_CHEST_CS, vanillaPlaySlowChestCS, chest)) { - Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_98); - Player_StartAnimMovement(play, this, 0x28F); - chest->unk_1F4 = 1; - Camera_ChangeSetting(Play_GetCamera(play, 0), CAM_SET_SLOW_CHEST_CS); - } else { - Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_box_kick); - chest->unk_1F4 = -1; + if (GameInteractor_Should(VB_PLAY_SLOW_CHEST_CS, vanillaPlaySlowChestCS, chest)) { + Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_98); + Player_StartAnimMovement(play, this, 0x28F); + chest->unk_1F4 = 1; + Camera_ChangeSetting(Play_GetCamera(play, 0), CAM_SET_SLOW_CHEST_CS); + } else { + Player_AnimPlayOnce(play, this, &gPlayerAnim_link_normal_box_kick); + chest->unk_1F4 = -1; + } } return 1;