From eca767dcbfa925cb81ad094fbee9a8d1002a17fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= <159546+serprex@users.noreply.github.com> Date: Thu, 3 Sep 2026 20:05:14 +0000 Subject: [PATCH] Logical bunny hood (#7032) Co-authored-by: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> --- soh/assets/custom/lang/en_US.json | 57 ++- soh/soh/Enhancements/AdultMasks.cpp | 12 +- soh/soh/Enhancements/AdultMasks.h | 1 + soh/soh/Enhancements/BunnyHood.cpp | 7 +- soh/soh/Enhancements/BunnyHood.h | 1 + soh/soh/Enhancements/SpeedModifiers.cpp | 3 +- soh/soh/Enhancements/randomizer/entrance.cpp | 6 +- .../randomizer/location_access.cpp | 34 +- .../location_access/dungeons/deku_tree.cpp | 19 +- .../dungeons/dodongos_cavern.cpp | 132 ++++--- .../location_access/dungeons/fire_temple.cpp | 173 +++++---- .../dungeons/forest_temple.cpp | 87 +++-- .../dungeons/ganons_castle.cpp | 214 +++++++---- .../dungeons/gerudo_training_ground.cpp | 91 +++-- .../location_access/dungeons/ice_cavern.cpp | 24 +- .../dungeons/jabujabus_belly.cpp | 60 ++-- .../dungeons/shadow_temple.cpp | 104 +++--- .../dungeons/spirit_temple.cpp | 152 ++++---- .../location_access/dungeons/water_temple.cpp | 338 ++++++++++++------ .../overworld/castle_grounds.cpp | 2 +- .../overworld/death_mountain_crater.cpp | 2 +- .../overworld/death_mountain_trail.cpp | 30 +- .../overworld/gerudo_fortress.cpp | 17 +- .../overworld/gerudo_valley.cpp | 11 +- .../location_access/overworld/goron_city.cpp | 6 +- .../location_access/overworld/graveyard.cpp | 2 +- .../overworld/haunted_wasteland.cpp | 6 +- .../location_access/overworld/kakariko.cpp | 6 +- .../overworld/kokiri_forest.cpp | 36 +- .../location_access/overworld/lake_hylia.cpp | 12 +- .../location_access/overworld/lost_woods.cpp | 4 +- .../location_access/overworld/market.cpp | 1 - .../overworld/sacred_forest_meadow.cpp | 2 +- .../overworld/thieves_hideout.cpp | 15 +- .../overworld/zoras_domain.cpp | 8 +- .../location_access/overworld/zoras_river.cpp | 9 +- soh/soh/Enhancements/randomizer/logic.cpp | 140 ++++++-- soh/soh/Enhancements/randomizer/logic.h | 8 +- .../randomizer/randomizerEnums/LogicVal.h | 5 +- .../randomizerEnums/RandomizerMiscEnums.h | 16 + .../randomizerEnums/RandomizerRegion.h | 28 +- .../randomizerEnums/RandomizerSettingKey.h | 2 + .../randomizerEnums/RandomizerTrick.h | 5 +- soh/soh/Enhancements/randomizer/settings.cpp | 21 +- .../Enhancements/randomizer/static_data.cpp | 2 +- soh/soh/SohGui/SohMenuEnhancements.cpp | 18 +- 46 files changed, 1257 insertions(+), 672 deletions(-) diff --git a/soh/assets/custom/lang/en_US.json b/soh/assets/custom/lang/en_US.json index d486e92464..21e94bc7af 100644 --- a/soh/assets/custom/lang/en_US.json +++ b/soh/assets/custom/lang/en_US.json @@ -1467,6 +1467,20 @@ "Item placement logic will respect this option, so it might be required to use this to progress." ] }, + "bunny_hood": { + "name": "Bunny Hood Effect", + "description": [ + "Wearing the Bunny Hood makes Link run 1.5x faster and jump 1.5x further, like in Majora's Mask. ", + "Item placement logic will respect this option, so it might be required to use this to progress." + ] + }, + "masks_as_adult": { + "name": "Masks as Adult", + "description": [ + "Masks can be equipped as adult instead of being child only. ", + "Item placement logic will respect this option, so it might be required to use this to progress." + ] + }, "rocs_feather": { "name": "Roc's Feather", "description": [ @@ -1973,10 +1987,6 @@ "letting you interact with some objects inside them such as large chests" ] }, - "bunny_hood_jumps": { - "name": "Bunny Hood Jumps", - "description": "Allows reaching locations using Bunny Hood's extended jumps." - }, "damage_boost_simple": { "name": "Simple damage boosts", "description": "Allows damage boosts in order to reach further locations. Can be combined with \"Simple hover boosts\" for reaching far distances." @@ -2113,7 +2123,7 @@ }, "gy_child_dampe_race_poh": { "name": "Second Dampe Race as Child", - "description": "It is possible to complete the second dampe race as child in under a minute, but it is a strict time limit." + "description": "It is possible to complete the second dampe race as child in under a minute, but it is a strict time limit. This is in default logic with Bunny Hood" }, "gy_shadow_fire_arrows": { "name": "Shadow Temple Entry with Fire Arrows", @@ -2132,7 +2142,7 @@ }, "dmt_bombable": { "name": "Death Mountain Trail Chest with Strength", - "description": "Child Link can blow up the wall using a nearby bomb flower. You must backwalk with the flower and then quickly throw it toward the wall." + "description": "Child Link can blow up the wall using a nearby bomb flower. You must backwalk with the flower and then quickly throw it toward the wall. This is not a trick if you have Bunny Hood." }, "dmt_hovers_lower_gs": { "name": "Death Mountain Trail Lower Red Rock GS with Hover Boots", @@ -2173,7 +2183,7 @@ }, "gc_rolling_strength": { "name": "Rolling Goron (Hot Rodder Goron) as Child with Strength", - "description": "Use the Bomb Flower on the stairs or near Medigoron. Timing is tight, especially without backwalking." + "description": "Use the Bomb Flower on the stairs or near Medigoron. Timing is tight, especially without backwalking.\nThis is in default logic with Bunny Hood." }, "gc_leftmost": { "name": "Goron City Maze Left Chest with Hover Boots", @@ -2205,7 +2215,7 @@ }, "zr_lower": { "name": "Zora's River Lower Freestanding PoH as Adult with Nothing", - "description": "Adult can reach this PoH with a precise jump, no Hover Boots required." + "description": "Adult can reach this PoH and the nearby bush with a precise jump, no Hover Boots or Bunny Hood required." }, "zr_upper": { "name": "Zora's River Upper Freestanding PoH as Adult with Nothing", @@ -2356,11 +2366,11 @@ }, "dc_slingshot_skip": { "name": "Dodongo's Cavern Child Slingshot Skips", - "description": "With precise platforming, child can cross the platforms while the flame circles are there. When enabling this trick, it's recommended that you also enable the Adult variant: \"Dodongo's Cavern Spike Trap Room Jump without Hover Boots\"." + "description": "With precise platforming, child can cross the platforms while the flame circles are there. When enabling this trick, it's recommended that you also enable Unintuitive Jumps, which enables Adult to skip this loop in an easier way." }, "dc_scrub_room": { "name": "Dodongo's Cavern Two Scrub Room with Strength", - "description": "With help from a conveniently-positioned block, Adult can quickly carry a Bomb Flower over to destroy the mud wall blocking the room with two Deku Scrubs." + "description": "With help from a conveniently-positioned block, Adult (or Child with Bunny Hood) can quickly carry a Bomb Flower over to destroy the mud wall blocking the room with two Deku Scrubs." }, "dc_jump": { "name": "Dodongo's Cavern Spike Trap Room Jump without Hover Boots", @@ -2374,13 +2384,17 @@ "name": "Dodongo's Cavern Dodongo with Only Bombchus", "description": "With precise timing you can feed King Dodongo a bombchu during a backflip" }, + "dc_eyes_bunnyhovers": { + "name": "Dodongo's Cavern Dodongo with Goron Bracelet and Bunnyhovers", + "description": "With precisely timed movement using both Bunny Hood and Hover Boots you can use the high-rising platform to carry a Bomb Flower to the Dodongo's Head and quickly throw it close enough to the eyes to trigger them. This requires \"Bunny Hood in Logic\" to function." + }, "dc_mq_stairs_with_only_strength": { "name": "Dodongo's Cavern MQ Stairs With Only Strength", "description": "Taking a bomb from the back can be used to lower stairs without using stick to drop bomb from wall." }, - "dc_mq_child_bombs": { - "name": "Dodongo's Cavern MQ Early Bomb Bag Area as Child", - "description": "With a precise jumpslash from above, you can reach the Bomb Bag area as only child without needing a Slingshot. You will take fall damage." + "dc_child_lobby": { + "name": "Dodongo's Cavern Lobby Recoil to Ledge as Child", + "description": "With a precise jumpslash from above, you can reach the ledge in DC Lobby as Child from the upper area near the tablet. You will take fall damage." }, "dc_mq_child_eyes": { "name": "Dodongo's Cavern MQ Light the Eyes with Strength as Child", @@ -2627,7 +2641,7 @@ }, "water_dragon_jump_dive": { "name": "Water Temple Dragon Statue Jump Dive", - "description": "If you come into the dragon statue room from the serpent river, you can sidehop down from above and get into the tunnel without needing either Iron Boots or a Scale. This trick applies to both Vanilla and Master Quest. In Vanilla, you must shoot the switch from above with the Bow, and then quickly get through the tunnel before the gate closes." + "description": "If you come into the dragon statue room from the serpent river, you can sidehop down from above and get into the tunnel without needing either Iron Boots or a Scale. Alternativly, you can do this while equipping irons in middair to get into the tunnel without swim. This trick applies to both Vanilla and Master Quest. In Vanilla, you must shoot the switch from above with the Bow, and then quickly get through the tunnel before the gate closes." }, "water_adult_dragon": { "name": "Water Temple Dragon Statue Switch from Above the Water as Adult", @@ -2665,7 +2679,7 @@ "description": [ "Invisible hookshot geometry can be used in MQ to get over the gate that blocks you from going to this ", "Skulltula early, skipping a small key as well as needing Hovers or Scarecrow to reach the locked door.\n", - "In vanilla this can be used to get past without bronze scale." + "In vanilla this can be used to leave the water and pass in either direction without Bronze Scale using Iron Boots and Hookshot." ] }, "water_morpha_without_hookshot": { @@ -2737,7 +2751,7 @@ }, "shadow_mq_huge_pit": { "name": "Shadow Temple MQ Lower Huge Pit without Fire Source", - "description": "Normally a frozen eye switch spawns some platforms that you can use to climb down, but there's actually a small piece of ground that you can stand on that you can just jump down to." + "description": "Normally a frozen eye switch spawns some platforms that you can use to climb down, but there's actually a small piece of ground that you can stand on that you can just jump down to. Bunny hood and Hover Boots together can solve this without the trick." }, "shadow_mq_windy_walkway": { "name": "Shadow Temple MQ Windy Walkway Reverse without Hover Boots", @@ -2765,7 +2779,7 @@ }, "spirit_statue_jump": { "name": "Spirit Temple Statue Room Jump from Hands to Upper Ledges", - "description": "A precise jump to obtain the following as adult without needing one of Hover Boots, or Hookshot (in Vanilla) or Song of Time (in MQ): - Spirit Temple Statue Room Northeast Chest - Spirit Temple GS Lobby - Spirit Temple MQ Central Chamber Top Left Pot (Left) - Spirit Temple MQ Central Chamber Top Left Pot (Right)" + "description": "A precise jump to obtain the following as Adult without needing one of Hover Boots, or Hookshot (in Vanilla) or Song of Time (in MQ). Using Bunny Hood puts this trick in default logic.: - Spirit Temple Statue Room Northeast Chest - Spirit Temple GS Lobby - Spirit Temple MQ Central Chamber Top Left Pot (Left) - Spirit Temple MQ Central Chamber Top Left Pot (Right)" }, "spirit_platform_hookshot": { "name": "Spirit Temple Main Room Hookshot to Boss Platform", @@ -2843,7 +2857,7 @@ }, "gtg_fake_wall": { "name": "Reach Gerudo Training Ground Fake Wall Ledge with Hover Boots", - "description": "A precise Hover Boots use from the top of the chest can allow you to grab the ledge without needing the usual requirements. In Master Quest, this always skips a Song of Time requirement. In Vanilla, this skips a Hookshot requirement, but is only relevant if \"Gerudo Training Ground Left Side Silver Rupees without Hookshot\" is enabled." + "description": "A precise Hover Boots use from the top of the chest can allow you to grab the ledge without needing the usual requirements. Logical Bunny Hood allows this to be done in default logic. In Master Quest, this always skips a Song of Time requirement. In Vanilla, this skips a Hookshot requirement, but is only relevant if \"Gerudo Training Ground Left Side Silver Rupees without Hookshot\" is enabled." }, "gtg_lava_jump": { "name": "Gerudo Training Grounds Itemless Lava Room Jump", @@ -2869,6 +2883,13 @@ "This trick supersedes \"Gerudo Training Ground MQ Left Side Silver Rupees with Hookshot\"." ] }, + "gtg_mq_lava_room": { + "name": "Navigate Gerudo Training Ground MQ Lava Room without Fire", + "description": [ + "It's possible to use the edges of the platforms, either with well placed jumps or Hover Boots, to cross sections of MQ GTG Lava Room without having fire to switch off the fire rings.\n", + "This allows you to clear the room using a combination of Din's Fire and either Hover Boots or Bunny Hood instead of Bow and allows you to reach the right of the maze using only Hookshot if the upper switch has been hit, among other things." + ] + }, "lens_ganon": { "name": "Ganon's Castle without Lens of Truth", "description": "Removes the requirements for the Lens of Truth in Ganon's Castle." diff --git a/soh/soh/Enhancements/AdultMasks.cpp b/soh/soh/Enhancements/AdultMasks.cpp index 60d0314224..990f01814c 100644 --- a/soh/soh/Enhancements/AdultMasks.cpp +++ b/soh/soh/Enhancements/AdultMasks.cpp @@ -1,6 +1,7 @@ #include "soh/Enhancements/AdultMasks.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/ShipInit.hpp" +#include "soh/Enhancements/randomizer/SeedContext.h" extern "C" { #include "z64.h" @@ -8,8 +9,13 @@ extern "C" { #include "variables.h" } +// rando's Masks as Adult setting forces the enhancement on, as logic may require it +static bool AdultMasksEnabled() { + return CVarGetInteger(CVAR_ADULT_MASKS_NAME, 0) || (IS_RANDO && RAND_GET_OPTION(RSK_MASKS_AS_ADULT)); +} + bool Ship_MasksEquippableAsAdult() { - return CVarGetInteger(CVAR_ADULT_MASKS_NAME, 0) || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0); + return AdultMasksEnabled() || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0); } static bool IsMask(int item) { @@ -17,7 +23,7 @@ static bool IsMask(int item) { } static void RegisterAdultMasks() { - bool adultMasks = CVarGetInteger(CVAR_ADULT_MASKS_NAME, 0); + bool adultMasks = AdultMasksEnabled(); // Masks drop their child-only age requirement COND_VB_SHOULD(VB_ITEM_MEETS_AGE_REQ, adultMasks, { @@ -34,4 +40,4 @@ static void RegisterAdultMasks() { }); } -static RegisterShipInitFunc initFunc(RegisterAdultMasks, { CVAR_ADULT_MASKS_NAME }); +static RegisterShipInitFunc initFunc(RegisterAdultMasks, { "IS_RANDO", CVAR_ADULT_MASKS_NAME }); diff --git a/soh/soh/Enhancements/AdultMasks.h b/soh/soh/Enhancements/AdultMasks.h index 1417da2834..0b64368c83 100644 --- a/soh/soh/Enhancements/AdultMasks.h +++ b/soh/soh/Enhancements/AdultMasks.h @@ -9,6 +9,7 @@ #ifdef __cplusplus extern "C" { #endif +// Whether adult Link may equip the child masks: the enhancement, the cheat, or whatever rando forces on top of them. bool Ship_MasksEquippableAsAdult(); #ifdef __cplusplus }; diff --git a/soh/soh/Enhancements/BunnyHood.cpp b/soh/soh/Enhancements/BunnyHood.cpp index 05def73f9f..42ae432eb6 100644 --- a/soh/soh/Enhancements/BunnyHood.cpp +++ b/soh/soh/Enhancements/BunnyHood.cpp @@ -2,6 +2,7 @@ #include "soh/ShipInit.hpp" #include "soh/Enhancements/BunnyHood.h" #include "soh/Enhancements/gameplaystats.h" +#include "soh/Enhancements/randomizer/SeedContext.h" extern "C" { #include "z64.h" @@ -10,7 +11,11 @@ extern "C" { extern PlayState* gPlayState; } +// rando's Bunny Hood Effect setting forces the enhancement on, as logic may require it BunnyHoodMode Ship_GetBunnyHoodMode() { + if (IS_RANDO && RAND_GET_OPTION(RSK_BUNNY_HOOD)) { + return BUNNY_HOOD_FAST_AND_JUMP; + } return (BunnyHoodMode)CVarGetInteger(CVAR_BUNNY_HOOD_NAME, BUNNY_HOOD_VANILLA); } @@ -65,4 +70,4 @@ static void RegisterBunnyHood() { }); } -static RegisterShipInitFunc initFunc(RegisterBunnyHood, { CVAR_BUNNY_HOOD_NAME }); +static RegisterShipInitFunc initFunc(RegisterBunnyHood, { "IS_RANDO", CVAR_BUNNY_HOOD_NAME }); diff --git a/soh/soh/Enhancements/BunnyHood.h b/soh/soh/Enhancements/BunnyHood.h index 52724c43f6..1f5515ce03 100644 --- a/soh/soh/Enhancements/BunnyHood.h +++ b/soh/soh/Enhancements/BunnyHood.h @@ -7,6 +7,7 @@ typedef struct Player Player; #define CVAR_BUNNY_HOOD_NAME CVAR_ENHANCEMENT("MMBunnyHood") +// Bunny hood effect in play: the enhancement, or whatever rando forces on top of it. BunnyHoodMode Ship_GetBunnyHoodMode(); // Speed multipliers the effect applies to the player, 1.0f when it doesn't. float Ship_GetBunnyHoodRunFactor(Player* player); diff --git a/soh/soh/Enhancements/SpeedModifiers.cpp b/soh/soh/Enhancements/SpeedModifiers.cpp index b1a87a6aba..e75c5ece8b 100644 --- a/soh/soh/Enhancements/SpeedModifiers.cpp +++ b/soh/soh/Enhancements/SpeedModifiers.cpp @@ -84,4 +84,5 @@ static void RegisterSpeedModifiers() { }); } -static RegisterShipInitFunc initFunc(RegisterSpeedModifiers, { CVAR_SPEED_MODIFIER_VALUE_NAME, CVAR_BUNNY_HOOD_NAME }); +static RegisterShipInitFunc initFunc(RegisterSpeedModifiers, + { "IS_RANDO", CVAR_SPEED_MODIFIER_VALUE_NAME, CVAR_BUNNY_HOOD_NAME }); diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 22186bfeee..4c1160028c 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -276,7 +276,7 @@ void SetAllEntrancesData() { { { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, ENTR_FOREST_TEMPLE_ENTRANCE }, { EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE } }, { { EntranceType::Dungeon, RR_DMC_TEMPLE_EXIT, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE }, - { EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_TEMPLE_EXIT, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } }, + { EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_TEMPLE_ENTRY, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } }, { { EntranceType::Dungeon, RR_LH_FROM_WATER_TEMPLE, RR_WATER_TEMPLE_ENTRYWAY, ENTR_WATER_TEMPLE_ENTRANCE }, { EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE } }, { { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, ENTR_SPIRIT_TEMPLE_ENTRANCE }, @@ -1532,7 +1532,7 @@ int EntranceShuffler::ShuffleAllEntrances() { { EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY), GetEntrance(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW) }, { EntranceNameByRegions(RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY), - GetEntrance(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_TEMPLE_EXIT) }, + GetEntrance(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_TEMPLE_ENTRY) }, { EntranceNameByRegions(RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY), GetEntrance(RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE) }, { EntranceNameByRegions(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY), @@ -1554,7 +1554,7 @@ int EntranceShuffler::ShuffleAllEntrances() { GetEntrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN) }, { EntranceNameByRegions(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW), GetEntrance(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW) }, - { EntranceNameByRegions(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_TEMPLE_EXIT), + { EntranceNameByRegions(RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_TEMPLE_ENTRY), GetEntrance(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_PAD_ENTRY) }, { EntranceNameByRegions(RR_WATER_TEMPLE_ENTRYWAY, RR_LH_FROM_WATER_TEMPLE), GetEntrance(RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA) }, diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index 6242c6404c..6d2f177a5b 100644 --- a/soh/soh/Enhancements/randomizer/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/location_access.cpp @@ -621,32 +621,32 @@ std::map Region::spiritLogicData = { {RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, {5, 0, 3, 0, []{return true;}, []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, - []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult);}, }}, {RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, {5, 0, 3, 0, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}, []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, - []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult);}, }}, {RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, {5, 0, 3, 0, []{return false;}, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT);}, - []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult);}, }}, {RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, - []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult);}, }}, {RR_SPIRIT_TEMPLE_INNER_WEST_HAND, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, []{return logic->SpiritExplosiveKeyLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, - []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult);}, }}, {RR_SPIRIT_TEMPLE_GS_LEDGE, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->SpiritWestToSkull() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, []{return logic->SpiritExplosiveKeyLogic() && logic->SpiritWestToSkull() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, - []{return logic->SpiritWestToSkull() && ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS));}, + []{return logic->SpiritWestToSkull() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult));}, }}, {RR_SPIRIT_TEMPLE_STATUE_ROOM, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic();}, @@ -671,42 +671,42 @@ std::map Region::spiritLogicData = { {RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, - []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult);}, }}, {RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, []{return (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, - []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult);}, }}, {RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, {5, 0, 3, 0, []{return logic->SpiritExplosiveKeyLogic() && logic->CanUse(RG_HOOKSHOT) && logic->SpiritEastToSwitch();}, []{return logic->SpiritEastToSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, - []{return logic->SpiritEastToSwitch() && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}}}, + []{return logic->SpiritEastToSwitch() && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult));}}}, //MQ {RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, {7, 6, 7, 7, []{return logic->StatueRoomMQKeyLogic();}, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6) && logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, - []{return logic->StatueRoomMQKeyLogic() && logic->CanHitSwitch() && ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS));}, + []{return logic->StatueRoomMQKeyLogic() && logic->CanHitSwitch() && ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult));}, }}, {RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, {7, 6, 7, 7, []{return logic->StatueRoomMQKeyLogic() && logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, []{return logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, - []{return logic->StatueRoomMQKeyLogic() && ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS));}, + []{return logic->StatueRoomMQKeyLogic() && ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult));}, }}, {RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_CHILD, {7, 0, 0, 0, []{return logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT);}, - []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);}, + []{return logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult);}, }}, {RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, {7, 0, 0, 0, []{return logic->CanHitSwitch() && logic->MQSpiritWestToPots() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, []{return logic->MQSpiritWestToPots() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, - []{return logic->CanUse(RG_HOVER_BOOTS) || ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->MQSpiritWestToPots());}, + []{return logic->CanUse(RG_HOVER_BOOTS) || ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult)) && logic->MQSpiritWestToPots());}, }}, {RR_SPIRIT_TEMPLE_MQ_INNER_RIGHT_HAND, {7, 0, 0, 0, []{return logic->CanHitSwitch() && logic->MQSpiritWestToPots() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, []{return logic->MQSpiritWestToPots() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, - []{return logic->CanUse(RG_HOVER_BOOTS) || ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->MQSpiritWestToPots());}, + []{return logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult) || ((logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && (logic->IsAdult || logic->CanJumpslash() || logic->BunnyHood()));}, }}, {RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, {7, 0, 0, 0, []{return logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, @@ -716,12 +716,12 @@ std::map Region::spiritLogicData = { {RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, {7, 0, 0, 0, []{return logic->CanHitSwitch() && logic->MQSpiritStatueToSunBlock() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT));}, []{return logic->MQSpiritStatueToSunBlock() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, - []{return logic->MQSpiritStatueToSunBlock() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));}, + []{return logic->MQSpiritStatueToSunBlock() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult));}, }}, {RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, {7, 7, 4, 4, []{return logic->CanHitSwitch() && logic->OuterWestHandMQLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_POWER_BRACELET);}, - []{return logic->OuterWestHandMQLogic();}, - []{return logic->OuterWestHandMQLogic();}, + []{return logic->OuterWestHandMQLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT));}, + []{return logic->OuterWestHandMQLogic() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult));}, }}, {RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR, {7, 0, 0, 0, []{return logic->CanHitSwitch() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR].AnyAgeTime([]{return logic->MQSpiritStatueSouthDoor();});}, 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 f99e628020..77459938be 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -101,7 +101,7 @@ void RegionTable_Init_DekuTree() { //Events EVENT_ACCESS(LOGIC_STICK_ACCESS, logic->CanGetDekuBabaSticks()), EVENT_ACCESS(LOGIC_NUT_ACCESS, logic->CanGetDekuBabaNuts()), - EVENT_ACCESS(LOGIC_DEKU_TREE_B1_BROKE_WEB, (logic->CanUse(RG_STICKS) && (logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))) || + EVENT_ACCESS(LOGIC_DEKU_TREE_B1_BROKE_WEB, (logic->CanUse(RG_STICKS) && (logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())) || (ctx->GetTrickOption(RT_DEKU_B1_BOW_WEBS) && logic->IsAdult && logic->CanUse(RG_FAIRY_BOW))), }, { //Locations @@ -114,7 +114,7 @@ void RegionTable_Init_DekuTree() { //Exits ENTRANCE(RR_DEKU_TREE_LOBBY, logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT))), ENTRANCE(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, AnyAgeTime([]{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);})), - ENTRANCE(RR_DEKU_TREE_BASEMENT_UPPER, logic->IsAdult || ctx->GetTrickOption(RT_DEKU_B1_SKIP) || logic->CanGroundJump() || logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK)), + ENTRANCE(RR_DEKU_TREE_BASEMENT_UPPER, logic->IsAdult || logic->BunnyHood() || ctx->GetTrickOption(RT_DEKU_B1_SKIP) || logic->CanGroundJump() || logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK)), ENTRANCE(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, false), }); @@ -319,16 +319,17 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_4, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BOULDER_1, logic->CanUse(RG_BOOMERANG) && - AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)));})), + AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && ((logic->CanUse(RG_SONG_OF_TIME) || logic->BunnyHood()) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)));})), LOCATION(RC_DEKU_TREE_MQ_BOULDER_2, logic->CanUse(RG_BOOMERANG) && - AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)));})), + AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && ((logic->CanUse(RG_SONG_OF_TIME) || logic->BunnyHood()) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)));})), LOCATION(RC_DEKU_TREE_MQ_BOULDER_3, logic->CanUse(RG_BOOMERANG) && - AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)));})), + AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && ((logic->CanUse(RG_SONG_OF_TIME) || logic->BunnyHood()) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)));})), }, { //Exits ENTRANCE(RR_DEKU_TREE_MQ_EYE_TARGET_ROOM, true), - ENTRANCE(RR_DEKU_TREE_MQ_PAST_BOULDER_VINES, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME))) && - AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && (logic->CanUse(RG_SONG_OF_TIME) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))) || (logic->CanUse(RG_MEGATON_HAMMER) && ((logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME)) || (ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->HasItem(RG_CLIMB))));})), + ENTRANCE(RR_DEKU_TREE_MQ_PAST_BOULDER_VINES, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || ((logic->IsAdult || logic->BunnyHood()) && logic->CanUse(RG_SONG_OF_TIME))) && + AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && ((logic->CanUse(RG_SONG_OF_TIME) || logic->BunnyHood()) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))) || + (logic->CanUse(RG_MEGATON_HAMMER) && (((logic->IsAdult || logic->BunnyHood()) && logic->CanUse(RG_SONG_OF_TIME)) || (ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) && logic->HasItem(RG_CLIMB))));})), }); areaTable[RR_DEKU_TREE_MQ_PAST_BOULDER_VINES] = Region("Deku Tree MQ Past Boulder Vines", SCENE_DEKU_TREE, {}, { @@ -347,7 +348,7 @@ void RegionTable_Init_DekuTree() { //Events EVENT_ACCESS(LOGIC_STICK_ACCESS, logic->CanGetDekuBabaSticks()), EVENT_ACCESS(LOGIC_NUT_ACCESS, logic->CanGetDekuBabaNuts()), - EVENT_ACCESS(LOGIC_DEKU_TREE_B1_BROKE_WEB, logic->CanUse(RG_STICKS) && (logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))), + EVENT_ACCESS(LOGIC_DEKU_TREE_B1_BROKE_WEB, logic->CanUse(RG_STICKS) && (logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) || logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())), }, { //Locations LOCATION(RC_DEKU_TREE_MQ_BASEMENT_CHEST, (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)) && logic->HasItem(RG_OPEN_CHEST)), @@ -361,7 +362,7 @@ void RegionTable_Init_DekuTree() { ENTRANCE(RR_DEKU_TREE_MQ_BASEMENT_SOUTHEAST_ROOM, AnyAgeTime([]{return logic->CanHitEyeTargets();})), //includes RR_DEKU_TREE_MQ_BASEMENT_SOUTHEAST_ROOM Access, other fire sources clear directly from there ENTRANCE(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, AnyAgeTime([]{return logic->CanHitEyeTargets();}) && logic->Get(LOGIC_DEKU_TREE_MQ_CLEARED_SE_ROOM) && AnyAgeTime([]{return logic->CanUse(RG_STICKS);})), - ENTRANCE(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, logic->IsAdult || ctx->GetTrickOption(RT_DEKU_B1_SKIP) || logic->CanGroundJump() || logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, logic->IsAdult || logic->BunnyHood() || ctx->GetTrickOption(RT_DEKU_B1_SKIP) || logic->CanGroundJump() || logic->Get(LOGIC_DEKU_TREE_PUSHED_BASEMENT_BLOCK) || logic->CanUse(RG_HOVER_BOOTS)), }); areaTable[RR_DEKU_TREE_MQ_BASEMENT_SOUTHEAST_ROOM] = Region("Deku Tree MQ Southeast Room", SCENE_DEKU_TREE, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp index 50e38dd5a6..48d1d9acc4 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp @@ -26,7 +26,8 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_LOBBY] = Region("Dodongos Cavern Lobby", SCENE_DODONGOS_CAVERN, { //Events EVENT_ACCESS(LOGIC_FAIRY_ACCESS, (AnyAgeTime([]{return logic->CanBreakMudWalls();}) || logic->HasItem(RG_GORONS_BRACELET)) && logic->CallGossipFairy()), - EVENT_ACCESS(LOGIC_DC_EYES_LIT, ctx->GetTrickOption(RT_DC_EYES_CHU) && logic->CanUse(RG_BOMBCHU_5)), + EVENT_ACCESS(LOGIC_DC_EYES_LIT, (ctx->GetTrickOption(RT_DC_EYES_CHU) && logic->CanUse(RG_BOMBCHU_5)) || + (ctx->GetTrickOption(RT_DC_EYES_BUNNYHOVERS) && logic->HasItem(RG_GORONS_BRACELET) && logic->BunnyHovers())), }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->CanOpenLargeChest();), @@ -56,7 +57,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_SE_CORRIDOR] = Region("Dodongos Cavern SE Corridor", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_GS_SCARECROW, logic->ReachScarecrow() || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_DC_SCARECROW_GS) && logic->HasItem(RG_POWER_BRACELET) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA))), + LOCATION(RC_DODONGOS_CAVERN_GS_SCARECROW, logic->ReachScarecrow() || (logic->IsAdult && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_DC_SCARECROW_GS) && logic->HasItem(RG_POWER_BRACELET) && (logic->IsAdult || logic->CanUse(RG_LONGSHOT)) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA))), LOCATION(RC_DODONGOS_CAVERN_SIDE_ROOM_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_SIDE_ROOM_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_SIDE_ROOM_POT_3, logic->CanBreakPots()), @@ -164,18 +165,34 @@ void RegionTable_Init_DodongosCavern() { ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, logic->IsAdult || (logic->HasItem(RG_POWER_BRACELET) && logic->HasItem(RG_CLIMB)) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->CanUse(RG_HOOKSHOT)), }); + areaTable[RR_DODONGOS_CAVERN_ENTRANCE_SIDE_BRIDGE] = Region("Dodongos Cavern Entrance Side Bridge", SCENE_DODONGOS_CAVERN, {}, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_FIRST_BRIDGE_GRASS, logic->CanCutShrubs()), + LOCATION(RC_DODONGOS_CAVERN_BLADE_POT_1, logic->CanUse(RG_BOOMERANG)), + }, { + //Exits + ENTRANCE(RR_DODONGOS_CAVERN_LOBBY, logic->TakeDamage()), + ENTRANCE(RR_DODONGOS_CAVERN_ARMOS_ROOM, true), + //RANDOTODO where does this damage boost start? + ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, ((logic->IsAdult || logic->BunnyHood()) && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)) || logic->CanUse(RG_HOVER_BOOTS) || + (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash())), + }); + 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, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_BLADE_ROOM_HEART, logic->HasItem(RG_POWER_BRACELET)), - LOCATION(RC_DODONGOS_CAVERN_FIRST_BRIDGE_GRASS, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_BLADE_GRASS, logic->CanCutShrubs()), + //You can get this from the ledge leading to the slingshot loop. breaking the mud wall is not necessary + LOCATION(RC_DODONGOS_CAVERN_BLADE_POT_2, logic->CanUse(RG_BOOMERANG)), }, { //Exits - ENTRANCE(RR_DODONGOS_CAVERN_ARMOS_ROOM, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), - ENTRANCE(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, AnyAgeTime([]{return logic->CanBreakMudWalls() || (ctx->GetTrickOption(RT_DC_SCRUB_ROOM) && logic->HasItem(RG_GORONS_BRACELET));})), + ENTRANCE(RR_DODONGOS_CAVERN_ENTRANCE_SIDE_BRIDGE, logic->CanClimbLadder() || ((logic->IsAdult || logic->CanMiddairGroundJump(true)) && logic->BunnyHovers())), + ENTRANCE(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, AnyAgeTime([]{return logic->CanBreakMudWalls() || (ctx->GetTrickOption(RT_DC_SCRUB_ROOM) && (logic->IsAdult || logic->BunnyHood()) && logic->HasItem(RG_GORONS_BRACELET));})), ENTRANCE(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);})), - ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, (logic->IsAdult && (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->CanGroundJump())) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash())), + ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, (logic->IsAdult && ((ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->BunnyHood()) || logic->CanGroundJump(true) || logic->CanUse(RG_HOVER_BOOTS))) || + logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->CanJumpslash()) || + logic->CanMiddairGroundJump()), }); areaTable[RR_DODONGOS_CAVERN_2F_SIDE_ROOM] = Region("Dodongos Cavern 2F Side Room", SCENE_DODONGOS_CAVERN, {}, { @@ -195,7 +212,7 @@ void RegionTable_Init_DodongosCavern() { }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, true), - ENTRANCE(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, logic->CanHitEyeTargets() || ctx->GetTrickOption(RT_DC_SLINGSHOT_SKIP) || (logic->IsAdult && logic->CanGroundJump()) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_MEGATON_HAMMER) || (logic->CanStandingShield() && logic->CanJumpslash())))), + ENTRANCE(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, logic->CanHitEyeTargets() || ctx->GetTrickOption(RT_DC_SLINGSHOT_SKIP) || (logic->IsAdult && logic->CanGroundJump()) || logic->CanUse(RG_HOVER_BOOTS)), }); areaTable[RR_DODONGOS_CAVERN_UPPER_LIZALFOS] = Region("Dodongos Cavern Upper Lizalfos", SCENE_DODONGOS_CAVERN, {}, { @@ -225,7 +242,9 @@ void RegionTable_Init_DodongosCavern() { }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, true), - ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || ctx->GetTrickOption(RT_DC_SLINGSHOT_SKIP) || (logic->IsAdult && logic->CanGroundJump()) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_MEGATON_HAMMER) || (logic->CanStandingShield() && logic->CanJumpslash())))), + //barely possible as adult with just hover boots and rolls, but hard enough to be a trick + ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, logic->CanHitEyeTargets() || ctx->GetTrickOption(RT_DC_SLINGSHOT_SKIP) || (logic->IsAdult && logic->CanGroundJump()) || + logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD) || logic->BunnyHovers()), }); areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER] = Region("Dodongos Cavern Bomb Room Upper", SCENE_DODONGOS_CAVERN, {}, { @@ -235,6 +254,7 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_BLADE_POT_2, logic->CanBreakPots()), }, { //Exits + ENTRANCE(RR_DODONGOS_CAVERN_ENTRANCE_SIDE_BRIDGE, true), ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, true), ENTRANCE(RR_DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, true), ENTRANCE(RR_DODONGOS_CAVERN_FAR_BRIDGE, true), @@ -251,6 +271,8 @@ void RegionTable_Init_DodongosCavern() { }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_LOBBY, true), + //Bunny hood jump + jumpslash can also make it directly from the raising platform, but it's too tight for unintuitive and overlaps with the recoil trick + ENTRANCE(RR_DODONGOS_CAVERN_LOBBY_SWITCH, logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DC_CHILD_LOBBY) && logic->CanJumpslashExceptHammer() && logic->TakeDamage())), ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, true), }); @@ -291,22 +313,24 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_LOBBY] = Region("Dodongos Cavern MQ Lobby", SCENE_DODONGOS_CAVERN, { //Events - EVENT_ACCESS(LOGIC_DC_EYES_LIT, ctx->GetTrickOption(RT_DC_EYES_CHU) && logic->CanUse(RG_BOMBCHU_5)), + EVENT_ACCESS(LOGIC_DC_EYES_LIT, (ctx->GetTrickOption(RT_DC_EYES_CHU) && logic->CanUse(RG_BOMBCHU_5)) || + (ctx->GetTrickOption(RT_DC_EYES_BUNNYHOVERS) && logic->HasItem(RG_GORONS_BRACELET) && logic->BunnyHovers())), }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->CanOpenLargeChest()), - LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()), - LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()), + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, (logic->CanStunDeku() || (logic->HasItem(RG_GORONS_BRACELET) && logic->BunnyHood())) && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()), + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, (logic->CanStunDeku() || (logic->HasItem(RG_GORONS_BRACELET) && logic->BunnyHood())) && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()), LOCATION(RC_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_1, logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET)), LOCATION(RC_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_2, logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET)), }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_BEGINNING, true), ENTRANCE(RR_DODONGOS_CAVERN_MQ_GOSSIP_STONE, AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);})), - ENTRANCE(RR_DODONGOS_CAVERN_MQ_OUTSIDE_POES_ROOM, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanGroundJump(!!ctx->GetTrickOption(RT_GROUND_JUMP_HARD))), + ENTRANCE(RR_DODONGOS_CAVERN_MQ_OUTSIDE_POES_ROOM, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanGroundJump((ctx->GetTrickOption(RT_GROUND_JUMP_HARD) || logic->BunnyHood()))), ENTRANCE(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, AnyAgeTime([]{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);})), ENTRANCE(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, AnyAgeTime([]{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);})), - ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, AnyAgeTime([]{return logic->CanBreakMudWalls();}) || AnyAgeTime([]{return logic->HasItem(RG_GORONS_BRACELET) && logic->TakeDamage();})), //strength 1 and bunny speed works too + //We can skip bunny here as adult, but it's tight, should probably be a trick + ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, AnyAgeTime([]{return logic->CanBreakMudWalls() || (logic->HasItem(RG_GORONS_BRACELET) && logic->BunnyHood());})), ENTRANCE(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, logic->Get(LOGIC_DC_EYES_LIT)), }); @@ -335,7 +359,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE] = Region("Dodongos Cavern MQ Mouth Side Bridge", SCENE_DODONGOS_CAVERN, { //Events EVENT_ACCESS(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE)), - EVENT_ACCESS(LOGIC_DC_EYES_LIT, logic->HasExplosives() || (logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS) && logic->HasItem(RG_GORONS_BRACELET) && ((logic->IsAdult && ctx->GetTrickOption(RT_DC_MQ_ADULT_EYES)) || (logic->IsChild && ctx->GetTrickOption(RT_DC_MQ_CHILD_EYES))))), + EVENT_ACCESS(LOGIC_DC_EYES_LIT, logic->HasExplosives() || (logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS) && logic->HasItem(RG_GORONS_BRACELET) && (logic->BunnyHood() || (logic->IsAdult && ctx->GetTrickOption(RT_DC_MQ_ADULT_EYES)) || (logic->IsChild && ctx->GetTrickOption(RT_DC_MQ_CHILD_EYES))))), }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_1, logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS)), @@ -344,11 +368,11 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_TOP_FLOOR_PEDESTAL, logic->CanRead()), }, { //Exits - ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOBBY, true), - ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS)), - //Bunny hood jump + jumpslash can also make it directly from the raising platform - ENTRANCE(RR_DODONGOS_CAVERN_MQ_OUTSIDE_POES_ROOM, logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DC_MQ_CHILD_BOMBS) && logic->CanJumpslashExceptHammer() && logic->TakeDamage())), //RANDOTODO is this possible with equip swapped hammer? - //it is possible to use bunny hood speed, hovers and a jumpslash to go between here and the other bridge (included with TORCH_ROOM_LOWER), but this would be a trick + ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOBBY, true), + ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS)), + //Bunny hood jump + jumpslash can also make it directly from the raising platform, but it's too tight for unintuitive and overlaps with the recoil trick + ENTRANCE(RR_DODONGOS_CAVERN_MQ_OUTSIDE_POES_ROOM, logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DC_CHILD_LOBBY) && logic->CanJumpslashExceptHammer() && logic->TakeDamage())), + //ENTRANCE(RR_DODONGOS_CAVERN_MQ_ENTRANCE_SIDE_BRIDGE, ctx->GetTrickOption(RT_UNINTUITIVE_HOVERS) && logic->BunnyHovers() && logic->CanJumpslash()), }); areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER] = Region("Dodongos Cavern MQ Stairs Lower", SCENE_DODONGOS_CAVERN, {}, { @@ -357,10 +381,10 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_3, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_4, logic->CanBreakPots()), - LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_LOWER_CRATE_1, logic->CanBreakCrates()), - LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_LOWER_CRATE_2, logic->CanBreakCrates()), + LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_LOWER_CRATE_1, logic->CanBreakCrates() || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_LOWER_CRATE_2, logic->CanBreakCrates() || logic->HasItem(RG_GORONS_BRACELET)), LOCATION(RC_DODONGOS_CAVERN_MQ_BEAMOS_SILVER, true), - LOCATION(RC_DODONGOS_CAVERN_MQ_1F_CRATE_SILVER, logic->CanBreakCrates() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->IsChild)), + LOCATION(RC_DODONGOS_CAVERN_MQ_1F_CRATE_SILVER, logic->CanBreakCrates()|| logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->IsChild)), }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOBBY, true), @@ -427,15 +451,15 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_ENTRANCE_SIDE_BRIDGE] = Region("Dodongos Cavern MQ Entrance Side Bridge", SCENE_DODONGOS_CAVERN, { //Events - EVENT_ACCESS(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, (((logic->IsAdult /*or bunny hood jump*/) && (logic->HasItem(RG_POWER_BRACELET) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))) || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_STICKS)), + EVENT_ACCESS(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, (((logic->IsAdult || logic->BunnyHood()) && ((logic->HasItem(RG_POWER_BRACELET) && logic->IsAdult) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))) || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_STICKS)), EVENT_ACCESS(LOGIC_DC_MQ_CLEAR_BIG_BLOCK_WEB, logic->CanUse(RG_STICKS) && logic->HasItem(RG_POWER_BRACELET)), }, {}, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOBBY, logic->TakeDamage()), ENTRANCE(RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM, true), + // ENTRANCE(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, ctx->GetTrickOption(RT_UNINTUITIVE_HOVERS) && logic->BunnyHovers() && logic->CanJumpslash()), ENTRANCE(RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM, logic->CanUse(RG_STICKS) && logic->HasItem(RG_POWER_BRACELET)), //assumes RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER access. - //Bunny hood jump can make it as child - ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, (logic->IsAdult && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, ((logic->IsAdult || logic->BunnyHood()) && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)) || logic->CanUse(RG_HOVER_BOOTS)), //Implies access to RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM and RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER from here ENTRANCE(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, logic->CanUse(RG_STICKS) && logic->HasItem(RG_GORONS_BRACELET)), }); @@ -445,16 +469,17 @@ void RegionTable_Init_DodongosCavern() { EVENT_ACCESS(LOGIC_DC_MQ_CLEAR_BIG_BLOCK_WEB, logic->HasFireSource()), }, { //Locations - //on review, RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_MIDDLE_POT from here is indirect as there's a lack of clear line of sight as child. + //on review of the review, RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_MIDDLE_POT has good line of sight from the top of the ladder to big block + LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_MIDDLE_POT, logic->CanUse(RG_BOOMERANG)), LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_HEART, true), }, { //Exits - ENTRANCE(RR_DODONGOS_CAVERN_MQ_ENTRANCE_SIDE_BRIDGE, (logic->IsAdult || logic->HasItem(RG_POWER_BRACELET)) || logic->CanClimbLadder()), + ENTRANCE(RR_DODONGOS_CAVERN_MQ_ENTRANCE_SIDE_BRIDGE, (logic->IsAdult || logic->HasItem(RG_POWER_BRACELET)) || logic->CanClimbLadder() || ((logic->IsAdult || logic->CanMiddairGroundJump(true)) && logic->BunnyHovers())), ENTRANCE(RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM, logic->HasFireSource()), - //you can platform off the blocks to get here without climb + //you can platform off the blocks to get here without climb ENTRANCE(RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM, logic->Get(LOGIC_DC_MQ_CLEAR_BIG_BLOCK_WEB)), //Includes an implied CanPass(RE_BIG_SKULLTULA) - //Bunny hood jump can make it as child - ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, (logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, (logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->CanGroundJump())) || + logic->CanUse(RG_HOOKSHOT) || logic->CanMiddairGroundJump()), }); areaTable[RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM] = Region("Dodongos Cavern MQ Big Block Room", SCENE_DODONGOS_CAVERN, { @@ -467,6 +492,8 @@ void RegionTable_Init_DodongosCavern() { }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, logic->CanPassEnemy(RE_BIG_SKULLTULA)), + // crossing this area with hovers rolless as child requires backwalking, however the gold skulltula prevents this unless the player manages to change the camera angle without changing the facing angle (c-up or freecam) + // it is unclear if this should be considered in logic or not ENTRANCE(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, (logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS)) && ((logic->HasFireSource() && logic->HasItem(RG_GORONS_BRACELET)) || logic->CanBreakMudWalls())), // If you can somehow warp into this room, add logic->CanPassEnemy(RE_BIG_SKULLTULA) }); @@ -492,7 +519,8 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS_POT_3, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS_POT_4, logic->CanBreakPots()), - LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_HEART, logic->BlastOrSmash()), + //bunny hood visibly clears the lower boulders, but even without it you can air drift into a relative gap in the boulders to cross + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_HEART, logic->BlastOrSmash() || logic->BunnyHood() || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)), LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_1, logic->BlastOrSmash() && (logic->TakeDamage() || logic->CanUse(RG_GORON_TUNIC) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_2, logic->BlastOrSmash() && (logic->TakeDamage() || logic->CanUse(RG_GORON_TUNIC) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_3, logic->BlastOrSmash() && (logic->TakeDamage() || logic->CanUse(RG_GORON_TUNIC) || logic->CanUse(RG_BOOMERANG))), @@ -512,18 +540,38 @@ void RegionTable_Init_DodongosCavern() { ENTRANCE(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, AnyAgeTime([]{return logic->CanKillEnemy(RE_LIZALFOS);})), }); - areaTable[RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM] = Region("Dodongos Cavern MQ Before Upper Lizalfos", SCENE_DODONGOS_CAVERN, {}, { + areaTable[RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM] = Region("Dodongos Cavern MQ Two Fires Room", SCENE_DODONGOS_CAVERN, { + //Events + EVENT_ACCESS(LOGIC_DC_MQ_TWO_FIRES_BOULDER, logic->BlastOrSmash()), + }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_CRATE_2, logic->CanBreakCrates()), - LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_BOULDER, logic->BlastOrSmash() || (logic->HasItem(RG_GORONS_BRACELET) && (logic->CanHitSwitch() || ctx->GetTrickOption(RT_DC_SLINGSHOT_SKIP)))), + LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_BOULDER, logic->BlastOrSmash()), }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, true), + ENTRANCE(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_FLOWER, logic->CanHitSwitch() || logic->BunnyHood() || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_DC_SLINGSHOT_SKIP)), //crate platforming skips the puzzle - ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, logic->IsAdult || (AnyAgeTime([]{return logic->BlastOrSmash() || (logic->CanAttack() && logic->HasItem(RG_GORONS_BRACELET));})) || ctx->GetTrickOption(RT_DC_SLINGSHOT_SKIP)), + ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, logic->IsAdult || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || ctx->GetTrickOption(RT_DC_SLINGSHOT_SKIP) || + (logic->Get(LOGIC_DC_MQ_TWO_FIRES_BOULDER) && logic->CanHitSwitch())), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_TWO_FIRES_FLOWER] = Region("Dodongos Cavern MQ Two Fires Nook", SCENE_DODONGOS_CAVERN, { + //Events + EVENT_ACCESS(LOGIC_DC_MQ_TWO_FIRES_BOULDER, logic->HasItem(RG_GORONS_BRACELET)), + }, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_CRATE_1, logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_CRATE_2, logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_BOULDER, logic->HasItem(RG_GORONS_BRACELET)), + }, { + //Exits + ENTRANCE(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, true), + //barely possible as adult with just hover boots and rolls, but hard enough to be a trick + ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, logic->HasItem(RG_GORONS_BRACELET) || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD) || logic->BunnyHovers()), }); areaTable[RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER] = Region("Dodongos Cavern MQ Torch Puzzle Upper", SCENE_DODONGOS_CAVERN, { @@ -540,7 +588,7 @@ void RegionTable_Init_DodongosCavern() { ENTRANCE(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, true), ENTRANCE(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, true), // Implied drop to LOWER_RIGHT_SIDE - ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, logic->HasItem(RG_GORONS_BRACELET) && logic->TakeDamage()), //strength 1 and bunny speed works too + ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, logic->HasItem(RG_GORONS_BRACELET) && logic->TakeDamage()), }); areaTable[RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE] = Region("Dodongos Cavern MQ Lower Right Side", SCENE_DODONGOS_CAVERN, {}, { @@ -611,11 +659,11 @@ void RegionTable_Init_DodongosCavern() { //Locations //This can be gotten with only str0 as adult by using 1 pot to kill the skull from the top of a nearby grave, //then another to hit the switch to turn of the fire then running up the ledge to grab it. This assumes RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE access - //Alternatively, the grave can be pulled and roll jumped off of. + //Alternatively, the grave can be pulled and roll jumped off of, or bunny hood can be used. //This may be trickworthy, but it can only come up with doorsanity or decoupled boss door rando, making it too niche to be it's own trick LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (logic->IsAdult && logic->HasItem(RG_POWER_BRACELET) && - (logic->CanPassEnemy(RE_ARMOS) || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)/* && Roll*/)/* || bunny jumps*/))), + (logic->CanPassEnemy(RE_ARMOS) || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)/* && Roll*/) || logic->BunnyHood()))), LOCATION(RC_DODONGOS_CAVERN_MQ_BEFORE_BOSS_SW_POT, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_BEFORE_BOSS_NE_POT, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_ROOM_SE_POT, logic->CanBreakPots()), @@ -624,7 +672,7 @@ void RegionTable_Init_DodongosCavern() { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOBBY, true), ENTRANCE(RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE, logic->HasItem(RG_POWER_BRACELET) || logic->HasExplosives() || - (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)/* && Roll*/)/* || bunny jumps*/))), + (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)/* && Roll*/) || logic->BunnyHood()))), ENTRANCE(RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE, logic->IsAdult), }); @@ -634,6 +682,7 @@ void RegionTable_Init_DodongosCavern() { }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), + LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_GRASS, logic->CanCutShrubs()), }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, logic->CanHitSwitch()), @@ -655,13 +704,12 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE] = Region("Dodongos Cavern MQ Back Switch Grave", SCENE_DODONGOS_CAVERN, { //Events EVENT_ACCESS(LOGIC_DC_MQ_BEHIND_FIRE_SWITCH, logic->HasItem(RG_POWER_BRACELET) || logic->CanHitSwitch() || logic->CanDetonateBombFlowers()), - EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CanBreakPots()), + EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CanBreakPots() || logic->HasItem(RG_GORONS_BRACELET)), }, { //Locations LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) || logic->HasItem(RG_GORONS_BRACELET)), - LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_ROOM_NW_POT, logic->CanBreakPots()), - LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_ROOM_NE_POT, logic->CanBreakPots()), - LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_GRASS, logic->CanCutShrubs()), + LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_ROOM_NW_POT, logic->CanBreakPots() || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_ARMOS_ROOM_NE_POT, logic->CanBreakPots() || logic->HasItem(RG_GORONS_BRACELET)), }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp index 592f6b4668..cb1046c1df 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -11,7 +11,7 @@ void RegionTable_Init_FireTemple() { //Exits ENTRANCE(RR_FIRE_TEMPLE_FOYER, ctx->GetDungeon(FIRE_TEMPLE)->IsVanilla()), ENTRANCE(RR_FIRE_TEMPLE_MQ_FOYER_LOWER, ctx->GetDungeon(FIRE_TEMPLE)->IsMQ()), - ENTRANCE(RR_DMC_TEMPLE_EXIT, true), + ENTRANCE(RR_DMC_TEMPLE_ENTRY, true), }); #pragma region Vanilla @@ -22,7 +22,7 @@ void RegionTable_Init_FireTemple() { ENTRANCE(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, true), ENTRANCE(RR_FIRE_TEMPLE_LOOP_HEXAGON_ROOM, AnyAgeTime([]{return logic->CanUse(RG_MEGATON_HAMMER);}) && (logic->SmallKeys(SCENE_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked())), ENTRANCE(RR_FIRE_TEMPLE_LOOP_CAGE_FOYER_SIDE, true), - ENTRANCE(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, logic->SmallKeys(SCENE_FIRE_TEMPLE, 2) && logic->FireTimer() >= 24), + ENTRANCE(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, logic->SmallKeys(SCENE_FIRE_TEMPLE, 2)), }); areaTable[RR_FIRE_TEMPLE_NEAR_BOSS_ROOM] = Region("Fire Temple Near Boss Room", SCENE_FIRE_TEMPLE, {}, { @@ -32,9 +32,9 @@ void RegionTable_Init_FireTemple() { //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 }, { //Exits - ENTRANCE(RR_FIRE_TEMPLE_FOYER, (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)) && (logic->FireTimer() >= 16 || (logic->Get(LOGIC_FIRE_HIT_PLATFORM) && logic->FireTimer() >= 8))), + ENTRANCE(RR_FIRE_TEMPLE_FOYER, (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->Get(LOGIC_FIRE_HIT_PLATFORM))) && (logic->FireTimer() >= 16 || (logic->Get(LOGIC_FIRE_HIT_PLATFORM) && logic->FireTimer() >= 8))), ENTRANCE(RR_FIRE_TEMPLE_NEAR_BOSS_UPPER, logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)) && logic->FireTimer() >= 16), - ENTRANCE(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, logic->FireTimer() >= 16 && (logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->Get(LOGIC_FIRE_HIT_PLATFORM))))), + ENTRANCE(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, logic->FireTimer() >= 16 && (logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->Get(LOGIC_FIRE_HIT_PLATFORM)) || (logic->IsAdult && (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->Get(LOGIC_FIRE_HIT_PLATFORM))))), }); //This region assumes tunic logic is handled on entry. @@ -174,9 +174,16 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_SHORTCUT_ROOM] = Region("Fire Temple Shortcut Room", SCENE_FIRE_TEMPLE, {}, { }, { //Exits - ENTRANCE(RR_FIRE_TEMPLE_LAVA_GEYSER_2F, logic->SmallKeys(SCENE_FIRE_TEMPLE, 4)), - ENTRANCE(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT)), - ENTRANCE(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, logic->IsAdult && logic->HasItem(RG_CLIMB) && ((logic->HasItem(RG_GORONS_BRACELET) || ctx->GetTrickOption(RT_FIRE_STRENGTH)) || logic->CanGroundJump()) && logic->CanHitSwitch(ED_BOMB_THROW)), + ENTRANCE(RR_FIRE_TEMPLE_LAVA_GEYSER_2F, logic->SmallKeys(SCENE_FIRE_TEMPLE, 4)), + ENTRANCE(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT)), + ENTRANCE(RR_FIRE_TEMPLE_SHORTCUT_ROOM_3F, logic->IsAdult && logic->HasItem(RG_CLIMB) && ((logic->HasItem(RG_GORONS_BRACELET) || ctx->GetTrickOption(RT_FIRE_STRENGTH)) || logic->CanGroundJump()) && logic->CanHitSwitch(ED_BOMB_THROW)), + }); + + areaTable[RR_FIRE_TEMPLE_SHORTCUT_ROOM_3F] = Region("Fire Temple Shortcut Room 3F", SCENE_FIRE_TEMPLE, {}, { + }, { + //Exits + ENTRANCE(RR_FIRE_TEMPLE_SHORTCUT_ROOM, true), + ENTRANCE(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, true), }); areaTable[RR_FIRE_TEMPLE_SHORTCUT_CLIMB] = Region("Fire Temple Shortcut Climb", SCENE_FIRE_TEMPLE, { @@ -231,10 +238,27 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_FIRE_WALL_EXIT_HEART, logic->FireTimer() >= 16), }, { //Exits - ENTRANCE(RR_FIRE_TEMPLE_NARROW_PATH_ROOM, logic->FireTimer() >= 24 && logic->SmallKeys(SCENE_FIRE_TEMPLE, 6)), - ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_CAGE, logic->FireTimer() >= 16 && logic->IsAdult), - ENTRANCE(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, logic->FireTimer() >= 24 && logic->IsAdult), - ENTRANCE(RR_FIRE_TEMPLE_CORRIDOR, logic->FireTimer() >= 16 && logic->IsAdult && logic->SmallKeys(SCENE_FIRE_TEMPLE, 7)), + ENTRANCE(RR_FIRE_TEMPLE_NARROW_PATH_ROOM, logic->FireTimer() >= 24 && logic->SmallKeys(SCENE_FIRE_TEMPLE, 6)), + ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_CAGE, logic->FireTimer() >= 16 && logic->IsAdult), + ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_UPPER_DOOR, logic->FireTimer() >= 24 && logic->IsAdult), + ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_SIDE_DOOR, logic->FireTimer() >= 16 && logic->IsAdult), + }); + + areaTable[RR_FIRE_TEMPLE_FIRE_WALL_UPPER_DOOR] = Region("Fire Temple Fire Wall Upper Door", SCENE_FIRE_TEMPLE, {}, {}, { + //Exits + ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_CAGE, logic->FireTimer() >= 8 && logic->IsAdult), + ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, true), + ENTRANCE(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, true), + }); + + areaTable[RR_FIRE_TEMPLE_FIRE_WALL_SIDE_DOOR] = Region("Fire Temple Fire Wall Chase", SCENE_FIRE_TEMPLE, {}, { + //Locations + LOCATION(RC_FIRE_TEMPLE_FIRE_WALL_EAST_HEART, logic->FireTimer() >= 8 && logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_FIRE_TEMPLE_FIRE_WALL_WEST_HEART, logic->FireTimer() >= 8 && logic->CanUse(RG_HOVER_BOOTS)), + }, { + //Exits + ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, true), + ENTRANCE(RR_FIRE_TEMPLE_CORRIDOR, logic->SmallKeys(SCENE_FIRE_TEMPLE, 7)), }); //firetimer for entering this area from RR_FIRE_TEMPLE_FIRE_WALL_CHASE is handled there @@ -252,10 +276,16 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits - ENTRANCE(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, logic->HasExplosives()), - ENTRANCE(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, true), - ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, true), - ENTRANCE(RR_FIRE_TEMPLE_GS_CLIMB_4F, logic->ReachScarecrow() || (ctx->GetTrickOption(RT_FIRE_SCARECROW) && logic->IsAdult && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, logic->HasExplosives()), + ENTRANCE(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, true), + ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_UPPER_DOOR, true), + ENTRANCE(RR_FIRE_TEMPLE_BOULDER_MAZE_4F, logic->ReachScarecrow() || (ctx->GetTrickOption(RT_FIRE_SCARECROW) && logic->IsAdult && logic->CanUse(RG_LONGSHOT))), + }); + + areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_4F] = Region("Fire Temple Boulder Maze 4F", SCENE_FIRE_TEMPLE, {}, {}, { + //Exits + ENTRANCE(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, true), + ENTRANCE(RR_FIRE_TEMPLE_GS_CLIMB_4F, true), }); areaTable[RR_FIRE_TEMPLE_GS_CLIMB_4F] = Region("Fire Temple GS Climb 4F", SCENE_FIRE_TEMPLE, {}, { @@ -263,8 +293,8 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT)), }, { //Exits - ENTRANCE(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, true), - ENTRANCE(RR_FIRE_TEMPLE_GS_CLIMB_5F, logic->HasItem(RG_CLIMB)), + ENTRANCE(RR_FIRE_TEMPLE_BOULDER_MAZE_4F, true), + ENTRANCE(RR_FIRE_TEMPLE_GS_CLIMB_5F, logic->HasItem(RG_CLIMB)), }); areaTable[RR_FIRE_TEMPLE_GS_CLIMB_5F] = Region("Fire Temple GS Climb 5F", SCENE_FIRE_TEMPLE, {}, { @@ -289,8 +319,8 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_CORRIDOR] = Region("Fire Temple Corridor", SCENE_FIRE_TEMPLE, {}, {}, { //Exits - ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, logic->SmallKeys(SCENE_FIRE_TEMPLE, 7)), - ENTRANCE(RR_FIRE_TEMPLE_FIRE_MAZE_MAIN, true), + ENTRANCE(RR_FIRE_TEMPLE_FIRE_WALL_SIDE_DOOR, logic->SmallKeys(SCENE_FIRE_TEMPLE, 7)), + ENTRANCE(RR_FIRE_TEMPLE_FIRE_MAZE_MAIN, true), }); areaTable[RR_FIRE_TEMPLE_FIRE_MAZE_MAIN] = Region("Fire Temple Fire Maze Main", SCENE_FIRE_TEMPLE, {}, { @@ -302,9 +332,9 @@ void RegionTable_Init_FireTemple() { }, { //Exits //Accounting for either air-drifting to the platform you want and taking fall damage or landing on the platform and jumping off - ENTRANCE(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, logic->Get(LOGIC_FIRE_HIT_PLATFORM) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->TakeDamage())), + ENTRANCE(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, logic->Get(LOGIC_FIRE_HIT_PLATFORM) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->TakeDamage() || logic->BunnyHood())), ENTRANCE(RR_FIRE_TEMPLE_CORRIDOR, true), - ENTRANCE(RR_FIRE_TEMPLE_FIRE_MAZE_PLATFORMS, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && (logic->Get(LOGIC_FIRE_HIT_ABOVE_MAZE_PLATFORM) || logic->CanGroundJump()))), + ENTRANCE(RR_FIRE_TEMPLE_FIRE_MAZE_PLATFORMS, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && (logic->Get(LOGIC_FIRE_HIT_ABOVE_MAZE_PLATFORM) || logic->CanGroundJump() || logic->BunnyHood()))), ENTRANCE(RR_FIRE_TEMPLE_CAGELESS_CHEST_ROOM, true), ENTRANCE(RR_FIRE_TEMPLE_SOT_CAGE_LOWER, logic->SmallKeys(SCENE_FIRE_TEMPLE, 8)), ENTRANCE(RR_FIRE_TEMPLE_FIRE_MAZE_SWITCH, (bool)ctx->GetTrickOption(RT_FIRE_SKIP_FLAME_WALLS)), @@ -316,6 +346,7 @@ void RegionTable_Init_FireTemple() { }, {}, { //Exits ENTRANCE(RR_FIRE_TEMPLE_FIRE_MAZE_MAIN, true), + //it's possible to go from here to RR_FIRE_TEMPLE_FIRE_MAZE_SWITCH with bunnyhovers by jumping on a pole and then running over other poles, but it's a hard hovers trick ENTRANCE(RR_FIRE_TEMPLE_SOT_CAGE_UPPER_DOOR, logic->CanUse(RG_MEGATON_HAMMER)), }); @@ -338,7 +369,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_SOT_CAGE_UPPER_DOOR] = Region("Fire Temple Sot Cage Upper Door", SCENE_FIRE_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, false), - ENTRANCE(RR_FIRE_TEMPLE_SOT_CAGE_SWITCH, logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME)), + ENTRANCE(RR_FIRE_TEMPLE_SOT_CAGE_SWITCH, logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->BunnyHood()), ENTRANCE(RR_FIRE_TEMPLE_FIRE_MAZE_PLATFORMS, true), ENTRANCE(RR_FIRE_TEMPLE_SOT_CAGE_LOWER, true), }); @@ -349,7 +380,7 @@ void RegionTable_Init_FireTemple() { }, { //Exits ENTRANCE(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, false), - ENTRANCE(RR_FIRE_TEMPLE_SOT_CAGE_UPPER_DOOR, logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME)), + ENTRANCE(RR_FIRE_TEMPLE_SOT_CAGE_UPPER_DOOR, logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->BunnyHood()), ENTRANCE(RR_FIRE_TEMPLE_SOT_CAGE_LOWER, true), }); @@ -382,13 +413,19 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_ABOVE_3F_FLARE_DANCER] = Region("Fire Temple Above 3F Flare Dancer", SCENE_FIRE_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_FIRE_TEMPLE_3F_FLARE_DANCER, true), - ENTRANCE(RR_FIRE_TEMPLE_SWITCH_CLIMB, true), + ENTRANCE(RR_FIRE_TEMPLE_SWITCH_CLIMB_4F, true), }); - areaTable[RR_FIRE_TEMPLE_SWITCH_CLIMB] = Region("Fire Temple Switch Climb", SCENE_FIRE_TEMPLE, {}, {}, { + areaTable[RR_FIRE_TEMPLE_SWITCH_CLIMB_4F] = Region("Fire Temple Switch Climb 4F", SCENE_FIRE_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_FIRE_TEMPLE_ABOVE_3F_FLARE_DANCER, true), - ENTRANCE(RR_FIRE_TEMPLE_NARROW_STAIRS, logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_CLIMB)), + ENTRANCE(RR_FIRE_TEMPLE_SWITCH_CLIMB_5F, logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_CLIMB)), + }); + + areaTable[RR_FIRE_TEMPLE_SWITCH_CLIMB_5F] = Region("Fire Temple Switch Climb 5F", SCENE_FIRE_TEMPLE, {}, {}, { + //Exits + ENTRANCE(RR_FIRE_TEMPLE_SWITCH_CLIMB_4F, true), + ENTRANCE(RR_FIRE_TEMPLE_NARROW_STAIRS, true), }); areaTable[RR_FIRE_TEMPLE_NARROW_STAIRS] = Region("Fire Temple Narrow Stairs", SCENE_FIRE_TEMPLE, {}, { @@ -398,7 +435,7 @@ void RegionTable_Init_FireTemple() { //Exits ENTRANCE(RR_FIRE_TEMPLE_SOT_CAGE_UPPER_DOOR, logic->TakeDamage()), ENTRANCE(RR_FIRE_TEMPLE_SOT_CAGE_SWITCH, logic->TakeDamage()), - ENTRANCE(RR_FIRE_TEMPLE_SWITCH_CLIMB, true), + ENTRANCE(RR_FIRE_TEMPLE_SWITCH_CLIMB_5F, true), ENTRANCE(RR_FIRE_TEMPLE_NARROW_STAIRS_4F, AnyAgeTime([]{return logic->CanUse(RG_MEGATON_HAMMER);})), }); @@ -436,9 +473,8 @@ void RegionTable_Init_FireTemple() { }, {}, { //Exits ENTRANCE(RR_FIRE_TEMPLE_BASE_OF_COLLAPSING_STAIRS, true), - ENTRANCE(RR_FIRE_TEMPLE_FIRE_MAZE_MAIN, logic->Get(LOGIC_FIRE_HIT_ABOVE_MAZE_PLATFORM)), - //it's possible to land directly on the upper platform as child and even avoid fall damage, but it's not intuitive (you have to ledge grab, drop down and then air drift with enough momentum to roll) - ENTRANCE(RR_FIRE_TEMPLE_FIRE_MAZE_PLATFORMS, logic->Get(LOGIC_FIRE_HIT_ABOVE_MAZE_PLATFORM) && logic->CanJumpslash() && logic->TakeDamage()), + //Pegs prevent fall damage + ENTRANCE(RR_FIRE_TEMPLE_FIRE_MAZE_PLATFORMS, logic->Get(LOGIC_FIRE_HIT_ABOVE_MAZE_PLATFORM)), }); #pragma endregion @@ -539,9 +575,9 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_2, logic->FireTimer() >= 24 && logic->CanBreakCrates()), }, { //Exits - ENTRANCE(RR_FIRE_TEMPLE_MQ_FOYER_UPPER, (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)) && (logic->FireTimer() >= 16 || (logic->Get(LOGIC_FIRE_HIT_PLATFORM) && logic->FireTimer() >= 8))), - ENTRANCE(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_TARGET, logic->FireTimer() >= 32 && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))), - ENTRANCE(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, logic->FireTimer() >= 16 && (logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->Get(LOGIC_FIRE_HIT_PLATFORM))))), + ENTRANCE(RR_FIRE_TEMPLE_MQ_FOYER_UPPER, (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_FIRE_HIT_PLATFORM) && logic->BunnyHood())) && (logic->FireTimer() >= 16 || (logic->Get(LOGIC_FIRE_HIT_PLATFORM) && logic->FireTimer() >= 8))), + ENTRANCE(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_TARGET, logic->FireTimer() >= 32 && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood()))), + ENTRANCE(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, logic->FireTimer() >= 16 && (logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_FIRE_HIT_PLATFORM) && logic->BunnyHood()) || (logic->IsAdult && (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->BunnyHood() || logic->Get(LOGIC_FIRE_HIT_PLATFORM))))), }); //This region assumes tunic logic is handled on entry. @@ -553,7 +589,9 @@ void RegionTable_Init_FireTemple() { //The Damage logic here is for jumping down and running across the lava to get in dins range of the south torch //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 - 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() > 12 || (logic->CanUse(RG_NAYRUS_LOVE) && logic->CanUse(RG_STICKS))))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST) && + (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || + (logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_GORON_TUNIC) || logic->BunnyHood() || logic->EffectiveHealth() > 12 || (logic->CanUse(RG_NAYRUS_LOVE) && logic->CanUse(RG_STICKS)))))), 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()), @@ -561,7 +599,7 @@ void RegionTable_Init_FireTemple() { }, { //Exits ENTRANCE(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM, true), - ENTRANCE(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM_UPPER, logic->IsAdult || logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM_UPPER, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), }); //This region assumes tunic logic is handled on entry. @@ -600,6 +638,7 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_MQ_LAVA_ROOM_SOUTH_POT, logic->CanBreakPots() && logic->FireTimer() >= 8), }, { //Exits + ENTRANCE(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, true), ENTRANCE(RR_FIRE_TEMPLE_MQ_TORCH_LOCKED_CAGE, logic->HasExplosives()), }); @@ -617,7 +656,7 @@ void RegionTable_Init_FireTemple() { 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, true), + ENTRANCE(RR_FIRE_TEMPLE_MQ_BIG_LAVA_BLOCKED_DOOR, true), }); areaTable[RR_FIRE_TEMPLE_MQ_TORCH_FIREWALL_ROOM] = Region("Fire Temple MQ Torch Firewall Room", SCENE_FIRE_TEMPLE, { @@ -684,8 +723,10 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_MQ_WONDER_SHORTCUT_ROOM_3, logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits + //RT_FIRE_MQ_CLIMB is free with bunnyhovers ENTRANCE(RR_FIRE_TEMPLE_MQ_SHORTCUT_ROOM_MID, (logic->HasFireSource() && (logic->IsAdult || (logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_CLIMB)))) || - (ctx->GetTrickOption(RT_FIRE_MQ_CLIMB) && logic->CanUse(RG_HOVER_BOOTS) && logic->HasItem(RG_CLIMB))), + (ctx->GetTrickOption(RT_FIRE_MQ_CLIMB) && logic->CanUse(RG_HOVER_BOOTS) && logic->HasItem(RG_CLIMB)) || + (logic->BunnyHovers() && logic->HasItem(RG_CLIMB))), ENTRANCE(RR_FIRE_TEMPLE_MQ_LAVA_GEYSER_2F, true), ENTRANCE(RR_FIRE_TEMPLE_MQ_SHORTCUT_CAGE, logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT)), }); @@ -710,8 +751,7 @@ void RegionTable_Init_FireTemple() { //Exits ENTRANCE(RR_FIRE_TEMPLE_MQ_SHORTCUT_ROOM_LOWER, true), //Explosives can also reach this room. Chus is relatively simple, they need to detonate on the first horizontal bar up from the floor while horizontally near the switch, but bombs are much harder - ENTRANCE(RR_FIRE_TEMPLE_MQ_MAZE_CRATE_CAGE, AnyAgeTime([]{return logic->CanJumpslash();})), - //it's possible to make the RT_FIRE_MQ_MAZE_HOVERS as child using bunny hood jumps, but not adult as adult bonks + ENTRANCE(RR_FIRE_TEMPLE_MQ_MAZE_CRATE_CAGE, AnyAgeTime([]{return logic->CanJumpslash() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanUse(RG_BOMBCHU_5));})), ENTRANCE(RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE, (logic->HasExplosives() || ctx->GetTrickOption(RT_VISIBLE_COLLISION)) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOOKSHOT)), ENTRANCE(RR_FIRE_TEMPLE_MQ_MAZE_SWITCH_DOOR, logic->HasExplosives() && ctx->GetTrickOption(RT_FIRE_MQ_MAZE_SIDE_ROOM)), ENTRANCE(RR_FIRE_TEMPLE_MQ_NARROW_PATH_ROOM, false), @@ -741,8 +781,9 @@ void RegionTable_Init_FireTemple() { }, { //Exits ENTRANCE(RR_FIRE_TEMPLE_MQ_LOWER_LIZALFOS_MAZE, true), - //it's possible to make the RT_FIRE_MQ_MAZE_HOVERS as child using bunny hood jumps, but not adult as adult bonks - ENTRANCE(RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE, logic->IsAdult && ((ctx->GetTrickOption(RT_FIRE_MQ_MAZE_HOVERS) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_FIRE_MQ_MAZE_JUMP))), + //it's possible to make the RT_FIRE_MQ_MAZE_JUMP as child using bunny hood jumps, but not adult as adult bonks. Might be easy enough to be unintuitive. + ENTRANCE(RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE, (logic->IsAdult && ((ctx->GetTrickOption(RT_FIRE_MQ_MAZE_HOVERS) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_FIRE_MQ_MAZE_JUMP))) || + (logic->IsChild && ctx->GetTrickOption(RT_FIRE_MQ_MAZE_JUMP) && logic->BunnyHood())), }); areaTable[RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE] = Region("Fire Temple MQ Upper Lizalfos Maze", SCENE_FIRE_TEMPLE, {}, {}, { @@ -820,9 +861,10 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_BURNING_BLOCK] = Region("Fire Temple MQ Burning Block", SCENE_FIRE_TEMPLE, {}, { //Locations - //There's definitely ways to do this hammerless, but with one points on it's a trick + //There's definitely other ways to do this hammerless, but with one points on it's a trick //you can just hook through the block while next to it to kill the skull and get the token - LOCATION(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_POWER_BRACELET) || ctx->GetTrickOption(RT_VISIBLE_COLLISION))), + LOCATION(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, ((logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOOKSHOT)) || (logic->BunnyHood() && logic->CanKillEnemy(RE_GOLD_SKULLTULA))) && + (logic->HasItem(RG_POWER_BRACELET) || ctx->GetTrickOption(RT_VISIBLE_COLLISION))), }, { //Exits ENTRANCE(RR_FIRE_TEMPLE_MQ_TORCH_SLUG_CLIMB, true), @@ -860,11 +902,11 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_TEMPLE_MQ_WONDER_TORCH_ROOM, logic->CanUse(RG_HOOKSHOT) && logic->FireTimer() >= 16), }, { //Exits - ENTRANCE(RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM_ABOVE_CAGE, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT)) && logic->FireTimer() >= 24), - ENTRANCE(RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE, logic->SmallKeys(SCENE_FIRE_TEMPLE, 3) && logic->FireTimer() >= 24), - ENTRANCE(RR_FIRE_TEMPLE_MQ_NARROW_PATH_ROOM, logic->FireTimer() >= 24), + ENTRANCE(RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM_ABOVE_CAGE, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT)) && logic->FireTimer() >= 24), + ENTRANCE(RR_FIRE_TEMPLE_MQ_UPPER_LIZALFOS_MAZE, logic->SmallKeys(SCENE_FIRE_TEMPLE, 3) && logic->FireTimer() >= 24), + ENTRANCE(RR_FIRE_TEMPLE_MQ_NARROW_PATH_ROOM, logic->FireTimer() >= 24), //Child has issues navigating the higher points of this room without an equip swapped hookshot - ENTRANCE(RR_FIRE_TEMPLE_MQ_CORRIDOR, logic->Get(LOGIC_FIRE_MQ_HIGH_TORCH_LIT) && (logic->IsAdult || logic->CanUse(RG_HOOKSHOT)) && logic->FireTimer() >= 16), + ENTRANCE(RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM_BARRED_DOOR, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT)) && logic->FireTimer() >= 16), }); areaTable[RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM_BARRED_DOOR] = Region("Fire Temple MQ High Torch Barred Door", SCENE_FIRE_TEMPLE, {}, { @@ -925,10 +967,12 @@ void RegionTable_Init_FireTemple() { }, {}, { //Exits ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_MAIN, true), - ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_MIDDLE, logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_HOVER_BOOTS)), + //child can do the bunny hood + damage strat without a jumpslash, but it's inconsistent + ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_MIDDLE, logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && (logic->IsAdult || logic->CanJumpslash()) && logic->TakeDamage())), ENTRANCE(RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_UPPER_DOOR, true), //This one might be a bit too hard for base logic, but is only relevant in doorsanity or with RT_FIRE_MQ_MAZE_HOVERS - ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_SWITCH, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_HOVER_BOOTS) && (logic->TakeDamage() || logic->CanJumpslash())), + ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_SWITCH, (((logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_HOVER_BOOTS)) || logic->BunnyHovers()) && (logic->TakeDamage() || logic->CanJumpslash())) || + (logic->CanUse(RG_SONG_OF_TIME) && logic->BunnyHovers())), }); areaTable[RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_UPPER_DOOR] = Region("Fire Temple MQ 2 Fire Walls Upper Door", SCENE_FIRE_TEMPLE, {}, {}, { @@ -944,7 +988,7 @@ void RegionTable_Init_FireTemple() { }, {}, { //Exits ENTRANCE(RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_UPPER_DOOR, logic->CanUse(RG_HOOKSHOT)), - ENTRANCE(RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_LOWER, false), + ENTRANCE(RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_LOWER, !!ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)), }); areaTable[RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_LOWER] = Region("Fire Temple MQ 2 Fire Walls Lower", SCENE_FIRE_TEMPLE, {}, { @@ -972,7 +1016,8 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_FIRE_MAZE_SWITCH] = Region("Fire Temple MQ Fire Maze Switch", SCENE_FIRE_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PAST_WALL, true), - ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_MIDDLE, (bool)ctx->GetTrickOption(RT_FIRE_SKIP_FLAME_WALLS)), + //this "middair ground jump" is actually a normal ground jump into a hovers run across the poles + ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_MIDDLE, ctx->GetTrickOption(RT_FIRE_SKIP_FLAME_WALLS) || logic->CanMiddairGroundJump()), ENTRANCE(RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_LOWER, true), }); @@ -1007,16 +1052,23 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_ABOVE_3F_FLARE_DANCER] = Region("Fire Temple MQ Above 3F Flare Dancer", SCENE_FIRE_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_FIRE_TEMPLE_MQ_3F_FLARE_DANCER, true), - ENTRANCE(RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB, true), + ENTRANCE(RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB_4F, true), }); - areaTable[RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB] = Region("Fire Temple MQ Locked Climb", SCENE_FIRE_TEMPLE, {}, { + areaTable[RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB_4F] = Region("Fire Temple MQ Locked Climb 4F", SCENE_FIRE_TEMPLE, {}, { //Locations LOCATION(RC_FIRE_TEMPLE_MQ_WONDER_AFTER_FLARE_DANCER, logic->CanUse(RG_HOOKSHOT)), }, { //Exits - ENTRANCE(RR_FIRE_TEMPLE_MQ_3F_FLARE_DANCER, true), - ENTRANCE(RR_FIRE_TEMPLE_MQ_NARROW_STAIRS_ROOM, logic->SmallKeys(SCENE_FIRE_TEMPLE, 4) && logic->HasItem(RG_CLIMB)), + ENTRANCE(RR_FIRE_TEMPLE_MQ_3F_FLARE_DANCER, true), + ENTRANCE(RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB_5F, logic->HasItem(RG_CLIMB)), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB_5F] = Region("Fire Temple MQ Locked Climb 5F", SCENE_FIRE_TEMPLE, {}, { + }, { + //Exits + ENTRANCE(RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB_4F, true), + ENTRANCE(RR_FIRE_TEMPLE_MQ_NARROW_STAIRS_ROOM, logic->SmallKeys(SCENE_FIRE_TEMPLE, 4)), }); areaTable[RR_FIRE_TEMPLE_MQ_NARROW_STAIRS_ROOM] = Region("Fire Temple MQ Narrow Stairs Room", SCENE_FIRE_TEMPLE, { @@ -1026,7 +1078,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()) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, (logic->IsAdult || logic->BunnyHood() || 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 @@ -1034,7 +1086,7 @@ void RegionTable_Init_FireTemple() { ENTRANCE(RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_LOWER, logic->TakeDamage()), ENTRANCE(RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_UPPER_DOOR, logic->TakeDamage()), ENTRANCE(RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_SWITCH, logic->TakeDamage()), - ENTRANCE(RR_FIRE_TEMPLE_MQ_3F_FLARE_DANCER, logic->SmallKeys(SCENE_FIRE_TEMPLE, 4)), + ENTRANCE(RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB_5F, logic->SmallKeys(SCENE_FIRE_TEMPLE, 4)), ENTRANCE(RR_FIRE_TEMPLE_MQ_NARROW_STAIRS_4F, logic->Get(LOGIC_FIRE_MQ_HIT_SCARECROW_ROOM_PLATFORM)), }); @@ -1068,8 +1120,7 @@ void RegionTable_Init_FireTemple() { }, { //Exits ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_MAIN, AnyAgeTime([]{return logic->CanUse(RG_MEGATON_HAMMER);})), - //it's possible to land directly on the upper platform as child and even avoid fall damage, but it's not intuitive (you have to ledge grab, drop down and then air drift with enough momentum to roll) - ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS, AnyAgeTime([]{return logic->CanUse(RG_MEGATON_HAMMER);}) && logic->CanJumpslash() && logic->TakeDamage()), + ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS, AnyAgeTime([]{return logic->CanUse(RG_MEGATON_HAMMER);})), ENTRANCE(RR_FIRE_TEMPLE_MQ_BASE_OF_COLLAPSING_STAIRS, false), }); @@ -1081,8 +1132,8 @@ void RegionTable_Init_FireTemple() { LOCATION(RC_FIRE_BOSS_KEY_HINT, true), }, { // Exits - ENTRANCE(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, ctx->GetDungeon(FIRE_TEMPLE)->IsVanilla() && false), - ENTRANCE(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM, ctx->GetDungeon(FIRE_TEMPLE)->IsMQ() && false), + ENTRANCE(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, ctx->GetDungeon(FIRE_TEMPLE)->IsVanilla()), + ENTRANCE(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM, ctx->GetDungeon(FIRE_TEMPLE)->IsMQ()), ENTRANCE(RR_FIRE_TEMPLE_BOSS_ROOM, logic->HasItem(RG_FIRE_TEMPLE_BOSS_KEY)), }); 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 5ad8dcd3bc..3190d7fe1c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -140,7 +140,7 @@ void RegionTable_Init_ForestTemple() { }, { //Exits ENTRANCE(RR_FOREST_TEMPLE_LOBBY, true), - ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_UPPER, logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_VINES) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_CLIMB))), + ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_SWITCH, logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_VINES) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_CLIMB))), ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND, logic->CanUse(RG_HOOKSHOT)), ENTRANCE(RR_FOREST_TEMPLE_SEWER, (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16), ENTRANCE(RR_FOREST_TEMPLE_DRAINED_SEWER, logic->Get(LOGIC_FOREST_DRAINED_WELL)), @@ -148,24 +148,35 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_NE_COURTYARD_UPPER] = Region("Forest Temple NE Courtyard Upper", SCENE_FOREST_TEMPLE, { //Events - EVENT_ACCESS(LOGIC_STICK_ACCESS, logic->CanGetDekuBabaSticks()), - EVENT_ACCESS(LOGIC_NUT_ACCESS, logic->CanGetDekuBabaNuts()), - EVENT_ACCESS(LOGIC_FOREST_DRAINED_WELL, true), + EVENT_ACCESS(LOGIC_STICK_ACCESS, logic->CanGetDekuBabaSticks()), + EVENT_ACCESS(LOGIC_NUT_ACCESS, logic->CanGetDekuBabaNuts()), }, {}, { //Exits ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, true), - ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND, logic->IsAdult && ctx->GetTrickOption(RT_FOREST_COURTYARD_LEDGE) && logic->CanUse(RG_HOVER_BOOTS)), - ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_DOORFRAME, logic->CanHammerRecoilHover() || ((ctx->GetTrickOption(RT_FOREST_DOORFRAME) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanJumpslash()))), + ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_SWITCH, logic->BunnyHood() || logic->CanUse(RG_CLIMB) || (logic->IsAdult && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)) || logic->CanUse(RG_HOOKSHOT) ||logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_DOORFRAME, logic->CanRecoilHover(RECOIL_HAMMER) || ((ctx->GetTrickOption(RT_FOREST_DOORFRAME) && logic->CanUse(RG_HOVER_BOOTS) && (logic->BunnyHood() || logic->CanJumpslash())))), ENTRANCE(RR_FOREST_TEMPLE_MAP_ROOM, true), }); + areaTable[RR_FOREST_TEMPLE_NE_COURTYARD_SWITCH] = Region("Forest Temple NE Courtyard Switch", SCENE_FOREST_TEMPLE, { + //Events + EVENT_ACCESS(LOGIC_FOREST_DRAINED_WELL, true), + }, {}, { + //Exits + ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, true), + //child can make the jump bunnyless, but it's more awkward and precise, with a nasty reset. Said reset may be too much for adult too, but it's a much easier jump for them + ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_UPPER, logic->BunnyHood() || (logic->IsAdult && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)) || logic->CanUse(RG_HOOKSHOT) ||logic->CanUse(RG_HOVER_BOOTS)), + //Adult can make this with bunny and a jumpslash, but the jump is too awkward for unintuitive (use the north-most railing, change direction as you jump) + ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND, ((logic->IsAdult && ctx->GetTrickOption(RT_FOREST_COURTYARD_LEDGE)) || logic->BunnyHood()) && logic->CanUse(RG_HOVER_BOOTS)), + }); + areaTable[RR_FOREST_TEMPLE_NE_COURTYARD_DOORFRAME] = Region("Forest Temple NE Courtyard Doorframe", SCENE_FOREST_TEMPLE, { //Events EVENT_ACCESS(LOGIC_FOREST_SUMMON_NE_SCARECROW, logic->ScarecrowsSong()), }, {}, { //Exits ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, true), - ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND, logic->CanHammerRecoilHover()), + ENTRANCE(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND, logic->CanRecoilHover(RECOIL_HAMMER)), }); areaTable[RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND] = Region("Forest Temple NE Courtyard Island", SCENE_FOREST_TEMPLE, {}, { @@ -265,7 +276,8 @@ void RegionTable_Init_ForestTemple() { }, { //Exits ENTRANCE(RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM, true), - ENTRANCE(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_COURTYARD_ALCOVE, ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && logic->CanJumpslashExceptHammer()), + ENTRANCE(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM_COURTYARD_ALCOVE, (ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && logic->CanJumpslashExceptHammer()) || + ((logic->IsAdult || logic->CanJumpslash()) && logic->BunnyHood())), ENTRANCE(RR_FOREST_TEMPLE_UPPER_BLOCK_PUSH_ROOM, logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET)), }); @@ -422,7 +434,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->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && (logic->CanPassEnemy(RE_BIG_SKULLTULA, ED_SHORT_JUMPSLASH, false) || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT)) && (logic->CanPassEnemy(RE_BIG_SKULLTULA, ED_SHORT_JUMPSLASH, false) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits ENTRANCE(RR_FOREST_TEMPLE_ENTRYWAY, true), @@ -512,32 +524,30 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE] = Region("Forest Temple MQ Lower Block Puzzle", SCENE_FOREST_TEMPLE, { //Events - //It is barely possible to get this as child with master + hovers, but it's tight without bunny speed - EVENT_ACCESS(LOGIC_FOREST_CAN_TWIST_HALLWAY, (ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && logic->CanUse(RG_HOVER_BOOTS) && - (logic->IsAdult && logic->CanJumpslash()) || - (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_MASTER_SWORD))))), + //I don't seem able to get master as child, but noted i did before. very precise? + EVENT_ACCESS(LOGIC_FOREST_CAN_TWIST_HALLWAY, (ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->BunnyHood())) && + (logic->IsAdult && logic->CanJumpslash()) || (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD)))), }, {}, { //Exits ENTRANCE(RR_FOREST_TEMPLE_MQ_BLOCK_PUZZLE_FLOOR, true), ENTRANCE(RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE, (logic->HasItem(RG_GORONS_BRACELET) && (logic->HasItem(RG_CLIMB) || (logic->IsAdult && logic->CanGroundJump()))) || logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS)), - ENTRANCE(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS))), }); areaTable[RR_FOREST_TEMPLE_MQ_MIDDLE_BLOCK_PUZZLE] = Region("Forest Temple MQ Middle Block Puzzle", SCENE_FOREST_TEMPLE, { //Events EVENT_ACCESS(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS, (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_LONGSHOT))), - EVENT_ACCESS(LOGIC_FOREST_CAN_TWIST_HALLWAY, ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && - (logic->IsAdult && logic->CanJumpslash()) || - (logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MASTER_SWORD)))), + EVENT_ACCESS(LOGIC_FOREST_CAN_TWIST_HALLWAY, ctx->GetTrickOption(RT_FOREST_MQ_JS_HALLWAY_SWITCH) && (logic->IsAdult && logic->CanJumpslash()) || + ((logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MASTER_SWORD)))), }, {}, { //Exits ENTRANCE(RR_FOREST_TEMPLE_MQ_LOWER_BLOCK_PUZZLE, true), ENTRANCE(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, (logic->IsAdult && logic->HasItem(RG_GORONS_BRACELET)) || (logic->Get(LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS) && logic->CanUse(RG_HOOKSHOT))), //Hammer cannot recoil from here, but can make the jump forwards with a hammer jumpslash as adult - ENTRANCE(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && logic->CanUse(RG_HOVER_BOOTS) || - (ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && (logic->CanJumpslashExceptHammer() || (logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER))))), + ENTRANCE(RR_FOREST_TEMPLE_MQ_INDOOR_LEDGE, logic->Get(LOGIC_FOREST_CAN_TWIST_HALLWAY) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && (logic->IsAdult || logic->CanJumpslash())) || + (ctx->GetTrickOption(RT_FOREST_OUTSIDE_BACKDOOR) && (logic->CanJumpslashExceptHammer() || (logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)))))), }); areaTable[RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE] = Region("Forest Temple MQ Upper Block Puzzle", SCENE_FOREST_TEMPLE, { @@ -649,7 +659,7 @@ void RegionTable_Init_ForestTemple() { }, {}, { //Exits ENTRANCE(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE, logic->Get(LOGIC_FOREST_MQ_BURNED_WEB)), - ENTRANCE(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES, true), + ENTRANCE(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_DOOR, true), }); areaTable[RR_FOREST_TEMPLE_MQ_NE_COURTYARD] = Region("Forest Temple MQ NE Courtyard", SCENE_FOREST_TEMPLE, { @@ -662,16 +672,17 @@ void RegionTable_Init_ForestTemple() { 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))), + LOCATION(RC_FOREST_TEMPLE_MQ_GS_WELL, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->WaterTimer() >= 16)), LOCATION(RC_FOREST_TEMPLE_MQ_WELL_WEST_HEART, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), LOCATION(RC_FOREST_TEMPLE_MQ_WELL_MIDDLE_HEART, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), LOCATION(RC_FOREST_TEMPLE_MQ_WELL_EAST_HEART, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), }, { //Exits - ENTRANCE(RR_FOREST_TEMPLE_MQ_LOBBY, true), - ENTRANCE(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16), - ENTRANCE(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES, logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_VINES) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_CLIMB)) || (logic->CanUse(RG_HOOKSHOT) && ((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->HasItem(RG_CLIMB)) || logic->CanUse(RG_SONG_OF_TIME)))), - ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND, logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_FOREST_TEMPLE_MQ_LOBBY, true), + ENTRANCE(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT)) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16), + ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_DOORFRAME, logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_CHEST, logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_VINES) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_CLIMB))), + ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND, logic->CanUse(RG_LONGSHOT)), }); areaTable[RR_FOREST_TEMPLE_MQ_NE_COURTYARD_DOORFRAME] = Region("Forest Temple MQ NE Courtyard Doorframe", SCENE_FOREST_TEMPLE, {}, { @@ -682,21 +693,29 @@ void RegionTable_Init_ForestTemple() { }, { //Exits ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD, true), - ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND, logic->CanHammerRecoilHover()), + ENTRANCE(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_CHEST, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && ((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->HasItem(RG_CLIMB)/*&& (logic->CanUse(RG_ROLL) || logic->BunnyHood())*/) || logic->CanUse(RG_SONG_OF_TIME)))), + ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND, logic->CanRecoilHover(RECOIL_HAMMER)), }); - areaTable[RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES] = Region("Forest Temple MQ Courtyard Top Ledges", SCENE_FOREST_TEMPLE, {}, { + areaTable[RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_DOOR] = Region("Forest Temple MQ Courtyard Top Door", SCENE_FOREST_TEMPLE, {}, {}, { + //Exits + ENTRANCE(RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE, true), + ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD, true), + ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_DOORFRAME, logic->CanRecoilHover(RECOIL_HAMMER) || (logic->IsAdult && logic->BunnyHovers()) || + ((ctx->GetTrickOption(RT_FOREST_DOORFRAME) && logic->CanUse(RG_HOVER_BOOTS) && (logic->CanJumpslash() || logic->BunnyHood()))) || + (logic->IsChild && (ctx->GetTrickOption(RT_FOREST_MQ_CHILD_DOORFRAME) || logic->CanMiddairGroundJump()))), + ENTRANCE(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_CHEST, logic->BunnyHood() || logic->CanUse(RG_CLIMB) || (logic->IsAdult && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)) || logic->CanUse(RG_HOOKSHOT) ||logic->CanUse(RG_HOVER_BOOTS)), + }); + + areaTable[RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_CHEST] = Region("Forest Temple MQ Courtyard Top Chest", SCENE_FOREST_TEMPLE, {}, { //Locations LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits - ENTRANCE(RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE, true), ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD, true), - ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_DOORFRAME, logic->CanHammerRecoilHover() || - ((ctx->GetTrickOption(RT_FOREST_DOORFRAME) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanJumpslash())) || - (logic->IsChild && (ctx->GetTrickOption(RT_FOREST_MQ_CHILD_DOORFRAME) || logic->CanMiddairGroundJump()))), - //N64 logic doesn't check damage but I always take some so I'm adding it - ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND, ctx->GetTrickOption(RT_FOREST_COURTYARD_LEDGE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanJumpslash() && logic->TakeDamage()), + ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_DOORFRAME, logic->CanRecoilHover(RECOIL_HAMMER)), + ENTRANCE(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_DOOR, logic->BunnyHood() || (logic->IsAdult && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)) || logic->CanUse(RG_HOOKSHOT) ||logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND, ((logic->IsAdult && ctx->GetTrickOption(RT_FOREST_COURTYARD_LEDGE)) || logic->BunnyHood()) && logic->CanUse(RG_HOVER_BOOTS)), }); areaTable[RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND] = Region("Forest Temple MQ NE Courtyard Island", SCENE_FOREST_TEMPLE, {}, { @@ -811,7 +830,7 @@ void RegionTable_Init_ForestTemple() { }, { //Exits ENTRANCE(RR_FOREST_TEMPLE_MQ_LOBBY, true), - ENTRANCE(RR_FOREST_TEMPLE_MQ_BASEMENT_POT_ROOM, logic->HasItem(RG_POWER_BRACELET) && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage())), + ENTRANCE(RR_FOREST_TEMPLE_MQ_BASEMENT_POT_ROOM, logic->HasItem(RG_POWER_BRACELET) && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage())), ENTRANCE(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, logic->Get(LOGIC_FOREST_OPEN_BOSS_HALLWAY)), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp index 5dd98b9d4d..9cbefdb5dc 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp @@ -78,7 +78,7 @@ void RegionTable_Init_GanonsCastle() { //Locations LOCATION(RC_GANONS_CASTLE_SOT_BLOCK_FOREST_SILVER, true), //Assumes RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_END access - LOCATION(RC_GANONS_CASTLE_ON_TARGET_FOREST_SILVER, ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanVoid()), + LOCATION(RC_GANONS_CASTLE_ON_TARGET_FOREST_SILVER, (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanVoid()) || (logic->CanMiddairGroundJump()/*&& (logic->CanUse(RG_ROLL) || logic->BunnyHood())*/)), }, { //Exits ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_WOLFOS_ROOM, true), @@ -89,10 +89,10 @@ void RegionTable_Init_GanonsCastle() { //Locations LOCATION(RC_GANONS_CASTLE_LARGE_PLATFORM_FOREST_SILVER, true), LOCATION(RC_GANONS_CASTLE_UNDER_LEDGE_FOREST_SILVER, true), - LOCATION(RC_GANONS_CASTLE_ON_TARGET_FOREST_SILVER, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || (logic->IsChild && ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanVoid())), + LOCATION(RC_GANONS_CASTLE_ON_TARGET_FOREST_SILVER, logic->IsAdult || logic->CanUse(RG_HOOKSHOT)), }, { //Exits - ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM, logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM, logic->CanUse(RG_LONGSHOT) || ((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)/* && (logic->CanUse(RG_ROLL) || logic->BunnyHood() || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD))*/) || (logic->CanMiddairGroundJump()/*&& (logic->CanUse(RG_ROLL) || logic->BunnyHood())*/))), ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_FINAL_DOOR, logic->IsAdult || logic->CanGroundJump() || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)), }); @@ -123,14 +123,14 @@ void RegionTable_Init_GanonsCastle() { }); areaTable[RR_GANONS_CASTLE_FIRE_TRIAL_FROM_OPEN] = Region("Ganon's Castle Fire Trial From Open Door", SCENE_INSIDE_GANONS_CASTLE, { - // backwalking hoverboots with backflip reaches silver rupee without needing str3 EVENT_ACCESS(LOGIC_GANONS_CASTLE_SILVER_FIRE, logic->FireTimer() >= 48 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), }, { //Locations LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_HEART, logic->FireTimer() >= 16), LOCATION(RC_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER, logic->FireTimer() >= 16), LOCATION(RC_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER, logic->FireTimer() >= 16), - LOCATION(RC_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER, logic->FireTimer() >= 32 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), + // backwalking hoverboots with backflip reaches silver rupee without needing str3 + LOCATION(RC_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER, logic->FireTimer() >= 32 && (logic->CanUse(RG_GOLDEN_GAUNTLETS) || logic->BunnyHovers())), LOCATION(RC_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER, logic->FireTimer() >= 8), LOCATION(RC_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER, logic->FireTimer() >= 24 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), }, { @@ -140,19 +140,18 @@ void RegionTable_Init_GanonsCastle() { }); areaTable[RR_GANONS_CASTLE_FIRE_TRIAL_FROM_BARRED] = Region("Ganon's Castle Fire Trial From Barred Door", SCENE_INSIDE_GANONS_CASTLE, { - // backwalking hoverboots with backflip reaches silver rupee without needing str3 - EVENT_ACCESS(LOGIC_GANONS_CASTLE_SILVER_FIRE, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 56 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), + EVENT_ACCESS(LOGIC_GANONS_CASTLE_SILVER_FIRE, (logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->FireTimer() >= 56 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), }, { //Locations - LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_HEART, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 16), - LOCATION(RC_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 8), - LOCATION(RC_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 16), - LOCATION(RC_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 32 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), - LOCATION(RC_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 16), - LOCATION(RC_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 24 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), + LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_HEART, (logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER, (logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->FireTimer() >= 8), + LOCATION(RC_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER, (logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER, (logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->FireTimer() >= 32 && (logic->CanUse(RG_GOLDEN_GAUNTLETS) || logic->BunnyHovers())), + LOCATION(RC_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER, (logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->FireTimer() >= 16), + LOCATION(RC_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER, (logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->FireTimer() >= 24 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), }, { //Exits - ENTRANCE(RR_GANONS_CASTLE_FIRE_TRIAL_OPEN_DOOR, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 24), + ENTRANCE(RR_GANONS_CASTLE_FIRE_TRIAL_OPEN_DOOR, (logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->FireTimer() >= 24), ENTRANCE(RR_GANONS_CASTLE_FIRE_TRIAL_BARRED_DOOR, true), }); @@ -222,7 +221,9 @@ void RegionTable_Init_GanonsCastle() { //Exits ENTRANCE(RR_GANONS_CASTLE_WATER_TRIAL_BLUE_FIRE_ROOM, true), ENTRANCE(RR_GANONS_CASTLE_WATER_TRIAL_BLOCK_ROOM_SWITCH, logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || logic->CanMiddairGroundJump())), - ENTRANCE(RR_GANONS_CASTLE_WATER_TRIAL_BLOCK_ROOM_END, logic->IsAdult || (logic->HasItem(RG_POWER_BRACELET) && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP)), + ENTRANCE(RR_GANONS_CASTLE_WATER_TRIAL_BLOCK_ROOM_END, logic->IsAdult || +//RANDOTODO when you hover close to the floor, you can pivot out of a backwalk to ledgegrab, should this be in base logic? + (logic->CanUse(RG_HOVER_BOOTS)/* && roll or bunny?*/) || logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP) || ((logic->BunnyHood() || logic->HasItem(RG_POWER_BRACELET)) && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), }); areaTable[RR_GANONS_CASTLE_WATER_TRIAL_BLOCK_ROOM_SWITCH] = Region("Ganon's Castle Water Trial Block Room Switch", SCENE_INSIDE_GANONS_CASTLE, { @@ -255,13 +256,31 @@ 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) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits - ENTRANCE(RR_GANONS_CASTLE_MAIN, true), - ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_POTS_PLATFORM, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT)), - // shortcut for longshot to torch, dins, longshot to like like, run to chest platform - ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM, logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_GANONS_CASTLE_MAIN, true), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_SOT_PLATFORM, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), + //start the recoil away from the wall + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_TORCH, logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && logic->CanRecoilHover(RECOIL_HAMMER)) || (logic->CanUse(RG_FIRE_ARROWS) && ((logic->IsAdult && logic->BunnyHood()) || logic->CanUse(RG_HOVER_BOOTS)))), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_POTS_PLATFORM, logic->CanUse(RG_FIRE_ARROWS)), + }); + + areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL_SOT_PLATFORM] = Region("Ganon's Castle Shadow Trial SoT Platform", SCENE_INSIDE_GANONS_CASTLE, {}, { + //Locations + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + }, { + //Exits + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_START, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOVER_BOOTS)/* && bunny or roll or recoil*/) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_TORCH, logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_POTS_PLATFORM, logic->CanUse(RG_FIRE_ARROWS)), + }); + + areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL_TORCH] = Region("Ganon's Castle Shadow Trial Torch", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { + //Exits + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_START, logic->CanUse(RG_LONGSHOT) || (logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_POTS_PLATFORM, logic->CanUse(RG_LONGSHOT) || (logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM, logic->CanUse(RG_LONGSHOT) || (logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS))), }); areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL_POTS_PLATFORM] = Region("Ganon's Castle Shadow Pots Platform", SCENE_INSIDE_GANONS_CASTLE, {}, { @@ -270,43 +289,61 @@ void RegionTable_Init_GanonsCastle() { LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_POT_2, logic->CanBreakPots()), }, { //Exits - ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_START, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT)), - ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_SHADOW_TRIAL_LOWER_SWITCH) && logic->CanUse(RG_HOOKSHOT))), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_START, logic->CanUse(RG_FIRE_ARROWS)), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_TORCH, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_FIRE_ARROWS) && ((logic->IsAdult && logic->BunnyHood()) || logic->CanUse(RG_HOVER_BOOTS)))), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_SOT_PLATFORM, logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_FIRE_ARROWS)), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->CanUse(RG_HOOKSHOT))), }); - areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM] = Region("Ganon's Castle Shadow Chest Platform", SCENE_INSIDE_GANONS_CASTLE, { - //Events - EVENT_ACCESS(LOGIC_SHADOW_TRIAL_RUSTED_SWITCH, (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_MEGATON_HAMMER)), - }, { + //rename this? + areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM] = Region("Ganon's Castle Shadow Chest Platform", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_LOWER_SWITCH) && logic->CanOpenLargeChest()), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->CanOpenLargeChest()), 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)), }, { //Exits ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_POTS_PLATFORM, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)), - ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_LOWER_SWITCH, logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_LOWER_SWITCH, logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood() && logic->CanJumpslash())), + //bunny barely makes it without the path but it's tight enough to not be trickless or unintuitive + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_RUSTED_SWITCH, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS)), ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_END, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)), }); areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL_LOWER_SWITCH] = Region("Ganon's Castle Shadow Trial Lower Switch", SCENE_INSIDE_GANONS_CASTLE, { //Events - EVENT_ACCESS(LOGIC_SHADOW_TRIAL_LOWER_SWITCH, true), + EVENT_ACCESS(LOGIC_SHADOW_TRIAL_LATE_CHEST, true), }, {}, { //Exits - ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM, logic->CanUse(RG_FIRE_ARROWS) || (logic->Get(LOGIC_SHADOW_TRIAL_LOWER_SWITCH) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM, logic->CanUse(RG_FIRE_ARROWS) || (logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->CanUse(RG_LONGSHOT))), + }); + + areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL_RUSTED_SWITCH] = Region("Ganon's Castle Shadow Trial Rusted Switch", SCENE_INSIDE_GANONS_CASTLE, { + //Events + EVENT_ACCESS(LOGIC_SHADOW_TRIAL_RUSTED_SWITCH, logic->CanUse(RG_MEGATON_HAMMER)), + }, { + //Locations + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_1, logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_2, logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_3, logic->CanUse(RG_BOOMERANG)), + }, { + //Exits + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || (logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->CanUse(RG_LONGSHOT)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_END, logic->CanUse(RG_LONGSHOT)), }); areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL_END] = Region("Ganon's Castle Shadow Trial End", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_2, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG)), - LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_3, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_1, ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->BunnyHovers()), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_2, (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_3, (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && (logic->CanUse(RG_HOVER_BOOTS)|| logic->BunnyHood())) || logic->CanUse(RG_BOOMERANG)), }, { //Exits - ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM, (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)) || (logic->CanUse(RG_HOVER_BOOTS) && logic->HasFireSource()) || (logic->Get(LOGIC_SHADOW_TRIAL_LOWER_SWITCH) && logic->CanUse(RG_LONGSHOT))), - ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_POTS_PLATFORM, logic->CanUse(RG_LONGSHOT) && logic->CanUse(RG_DINS_FIRE) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH))), - ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_LOWER_SWITCH, logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM, (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)) || ((logic->CanUse(RG_HOVER_BOOTS) || ((logic->IsAdult || logic->CanJumpslash()) && logic->BunnyHood())) && logic->HasFireSource()) || (logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->CanUse(RG_LONGSHOT))), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_POTS_PLATFORM, logic->CanUse(RG_DINS_FIRE) && (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || ((logic->IsAdult || logic->CanJumpslash()) && logic->BunnyHood()))), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_LOWER_SWITCH, logic->CanUse(RG_HOVER_BOOTS) || ((logic->IsAdult || logic->CanJumpslash()) && logic->BunnyHood())), + ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_RUSTED_SWITCH, (logic->CanUse(RG_HOVER_BOOTS) && (logic->HasFireSource() || logic->BunnyHood()))), ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_FINAL_ROOM, logic->Get(LOGIC_SHADOW_TRIAL_RUSTED_SWITCH)), }); @@ -511,7 +548,9 @@ void RegionTable_Init_GanonsCastle() { 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, logic->Get(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST) && (logic->CanAvoidEnemy(RE_BEAMOS) || logic->CanKillEnemy(RE_ARMOS)) && logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_GANONS_CASTLE_MQ_FOREST_TRIAL_BEAMOS_ROOM, (logic->CanAvoidEnemy(RE_BEAMOS) || logic->CanKillEnemy(RE_ARMOS)) && + ((logic->Get(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST) && logic->CanUse(RG_LONGSHOT)) || + (((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)/* && (logic->CanUse(RG_ROLL) || logic->BunnyHood() || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD))*/) || (logic->CanMiddairGroundJump()/*&& (logic->CanUse(RG_ROLL) || logic->BunnyHood())*/))))), ENTRANCE(RR_GANONS_CASTLE_MQ_FOREST_TRIAL_BEAMOS_ROOM_END, logic->IsAdult || logic->CanGroundJump() || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)), }); @@ -552,11 +591,19 @@ void RegionTable_Init_GanonsCastle() { //Exits ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_OPEN_DOOR, true), ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR, logic->FireTimer() >= 32 && (logic->CanUse(RG_LONGSHOT) || - (logic->CanUse(RG_GOLDEN_GAUNTLETS) && (logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_GANON_MQ_FIRE_TRIAL) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT)))))), + (logic->CanUse(RG_GOLDEN_GAUNTLETS) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood()) || (ctx->GetTrickOption(RT_GANON_MQ_FIRE_TRIAL) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT)))))), }); - areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_BARRED] = Region("Ganon's Castle MQ Fire Trial From Barred Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { + areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_BARRED] = Region("Ganon's Castle MQ Fire Trial From Barred Door", SCENE_INSIDE_GANONS_CASTLE, {}, { + //Locations + LOCATION(RC_GANONS_CASTLE_MQ_UNDER_PILLAR_FIRE_SILVER, logic->CanRecoilHover(RECOIL_HAMMER) && logic->FireTimer() >= 24), + LOCATION(RC_GANONS_CASTLE_MQ_NEAR_TARGET_FIRE_SILVER, logic->CanRecoilHover(RECOIL_HAMMER) && logic->FireTimer() >= 24), + LOCATION(RC_GANONS_CASTLE_MQ_ON_PILLAR_FIRE_SILVER, logic->CanRecoilHover(RECOIL_HAMMER) && ((logic->FireTimer() >= 32 && logic->CanUse(RG_GOLDEN_GAUNTLETS)) || (logic->FireTimer() >= 8 && ctx->GetTrickOption(RT_VOIDOUT_COLLECTION)))), + LOCATION(RC_GANONS_CASTLE_MQ_LAUNCH_PLATFORM_FIRE_SILVER, logic->CanRecoilHover(RECOIL_HAMMER) && logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_MQ_JET_PLATFORM_FIRE_SILVER, logic->CanRecoilHover(RECOIL_HAMMER) && logic->FireTimer() >= 24), + }, { //Exits + ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_OPEN_DOOR, logic->CanRecoilHover(RECOIL_HAMMER) && logic->FireTimer() >= 32), ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR, true), }); @@ -580,7 +627,9 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM] = Region("Ganon's Castle MQ Water Trial Geyser Room", SCENE_INSIDE_GANONS_CASTLE, { //Events - EVENT_ACCESS(LOGIC_BLUE_FIRE_ACCESS, logic->CanJumpslash() || logic->HasExplosives()), // bow can also hit at right angle + //Hover hoots let you tun in and quickly grab fire, but it's a trick + //rang can barely hit the switch through the icicles, but indirect boomerang would be a better place for it + EVENT_ACCESS(LOGIC_BLUE_FIRE_ACCESS, logic->CanJumpslash() || logic->HasExplosives() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)))), }, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)), @@ -615,7 +664,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM] = Region("Ganon's Castle MQ Water Trial Block Room", SCENE_INSIDE_GANONS_CASTLE, { //Events EVENT_ACCESS(LOGIC_GANONS_CASTLE_MQ_SILVER_WATER, logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || logic->CanMiddairGroundJump()) && (logic->BlueFire() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanJumpslash()))), - EVENT_ACCESS(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE, (ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && logic->CanUse(RG_ICE_ARROWS)) || ((logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)/* && logic->CanUse(RG_ROLL)*/)) && logic->HasItem(RG_POWER_BRACELET) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE))), + EVENT_ACCESS(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE, (ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && logic->CanUse(RG_ICE_ARROWS)) || ((logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)) && logic->HasItem(RG_POWER_BRACELET) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE))), }, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_1, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && logic->CanUse(RG_BOOMERANG)), @@ -624,14 +673,15 @@ void RegionTable_Init_GanonsCastle() { LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_4, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && logic->CanUse(RG_BOOMERANG)), LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_5, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && logic->CanUse(RG_BOOMERANG)), LOCATION(RC_GANONS_CASTLE_MQ_IN_HOLE_WATER_SILVER, true), - LOCATION(RC_GANONS_CASTLE_MQ_AIRBORNE_WATER_SILVER, logic->IsAdult || logic->CanUse(RG_POWER_BRACELET) || (/*CanUse(RG_ROLL) && */ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), + LOCATION(RC_GANONS_CASTLE_MQ_AIRBORNE_WATER_SILVER, logic->IsAdult || logic->CanUse(RG_POWER_BRACELET) || (/*roll or bunny && */ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)) || (logic->CanUse(RG_HOVER_BOOTS)/* && roll or bunny?*/)), LOCATION(RC_GANONS_CASTLE_MQ_OVER_PIT_WATER_SILVER, true), LOCATION(RC_GANONS_CASTLE_MQ_NOOK_WATER_SILVER, true), }, { //Exits ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM, logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 3)), ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_HIGH, logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || logic->CanMiddairGroundJump())), - ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_END, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && (logic->IsAdult || ((logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)/* && logic->CanUse(RG_ROLL)*/)) && logic->HasItem(RG_POWER_BRACELET)) || logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP))), + ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_END, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && + (logic->IsAdult || (logic->CanUse(RG_HOVER_BOOTS)/* && roll or bunny?*/) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->HasItem(RG_POWER_BRACELET)) || logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP))), }); areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_HIGH] = Region("Ganon's Castle MQ Water Trial Block Room High", SCENE_INSIDE_GANONS_CASTLE, {}, { @@ -674,45 +724,60 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE] = Region("Ganon's Castle MQ Shadow Trial Starting Ledge", SCENE_INSIDE_GANONS_CASTLE, { //Events EVENT_ACCESS(LOGIC_SHADOW_TRIAL_FIRST_CHEST, logic->CanUse(RG_FAIRY_BOW)), - EVENT_ACCESS(LOGIC_GANONS_CASTLE_MQ_SILVER_SHADOW, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && - (logic->IsAdult && ctx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL) && logic->CanUse(RG_FAIRY_BOW)) && - (logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS))), + //shortcut route for passage involving the torch. defacto the same as the RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST shortcut as everything else is merely lens locked + EVENT_ACCESS(LOGIC_GANONS_CASTLE_MQ_SILVER_SHADOW, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && ((logic->BunnyHovers() && logic->CanUse(RG_STICKS)) || + (logic->IsAdult && ctx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL) && logic->CanUse(RG_FAIRY_BOW) && + (logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())))), }, {}, { //Exits ENTRANCE(RR_GANONS_CASTLE_MQ_MAIN, true), - ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM, (logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM, (logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())) || logic->BunnyHovers() || logic->CanRecoilHoverFromObject(TRECOIL_SHORT)), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER, (logic->IsAdult && (logic->CanRecoilHover(RECOIL_HAMMER) || logic->CanRecoilHoverFromObject(TRECOIL_LONG_AND_SHIELD)))), + //shortcut route for passage involving the torch + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && ((logic->BunnyHovers() && logic->CanUse(RG_STICKS)) || + (logic->IsAdult && ctx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL) && logic->CanUse(RG_FAIRY_BOW) && + (((logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST) && logic->CanUse(RG_HOOKSHOT))) || (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()))))) }); areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM] = Region("Ganon's Castle MQ Shadow Trial Chest Platform", SCENE_INSIDE_GANONS_CASTLE, { //Events - EVENT_ACCESS(LOGIC_SHADOW_TRIAL_FIRST_CHEST, logic->CanUse(RG_FAIRY_BOW)), + EVENT_ACCESS(LOGIC_SHADOW_TRIAL_FIRST_CHEST, logic->CanUse(RG_FAIRY_BOW) || (logic->BunnyHovers() && logic->CanUse(RG_STICKS) && (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)))), }, { //Locations 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, logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS))), - ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_MOVING_PLATFORM, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE, logic->CanUse(RG_HOOKSHOT) || ((logic->IsAdult || logic->BunnyHood() || logic->CanRecoilHover(RECOIL_SWORD)) && logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_MOVING_PLATFORM, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())), }); - areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_MOVING_PLATFORM] = Region("Ganon's Castle MQ Shadow Trial Moving Platform", SCENE_INSIDE_GANONS_CASTLE, { - //Events - //A torch run from RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE is possible but tight, so would be a trick - EVENT_ACCESS(LOGIC_SHADOW_TRIAL_FIRST_CHEST, logic->CanDetonateUprightBombFlower()), - EVENT_ACCESS(LOGIC_GANONS_CASTLE_MQ_SILVER_SHADOW, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && - (logic->HasFireSource() || logic->CanUse(RG_HOVER_BOOTS))), - }, { + //assumes lens or lens trick is checked on entry + areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_MOVING_PLATFORM] = Region("Ganon's Castle MQ Shadow Trial Moving Platform", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_WONDER_SHADOW_TRIAL, (logic->CanDetonateBombFlowers() || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE))) && (logic->TakeDamage() || logic->CanUse(RG_NAYRUS_LOVE))), - LOCATION(RC_GANONS_CASTLE_MQ_BOMB_FLOWER_SHADOW_SILVER, true), LOCATION(RC_GANONS_CASTLE_MQ_MOVING_PLATFORM_SHADOW_SILVER, true), }, { //Exits ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER, true), ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH, true), }); + areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER] = Region("Ganon's Castle MQ Shadow Trial Moving Platform", SCENE_INSIDE_GANONS_CASTLE, { + //Events + //A torch run from RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE is possible but tight, so would be a trick + EVENT_ACCESS(LOGIC_SHADOW_TRIAL_FIRST_CHEST, logic->CanDetonateUprightBombFlower()), + EVENT_ACCESS(LOGIC_GANONS_CASTLE_MQ_SILVER_SHADOW, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && + (logic->HasFireSource() || logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->CanUse(RG_HOOKSHOT)))), + }, { + //Locations + LOCATION(RC_GANONS_CASTLE_MQ_WONDER_SHADOW_TRIAL, (logic->CanDetonateBombFlowers() || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE))) && logic->TakeDamage()), + LOCATION(RC_GANONS_CASTLE_MQ_BOMB_FLOWER_SHADOW_SILVER, true), + }, { + //Exits + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_MOVING_PLATFORM, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + }); + //the LOGIC_SHADOW_TRIAL_LATE_CHEST eye target can be hit from here by backflipping into the void while drawing the bow and shooting with good timing, but that's a trick areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH] = Region("Ganon's Castle MQ Shadow Trial Beamos Torch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_NEAR_TORCH_SHADOW_SILVER, true), @@ -722,20 +787,36 @@ void RegionTable_Init_GanonsCastle() { //A torch run from RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE is possible but very tight, so would be a trick //The bow trick assumes RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE access, if you can somehow void warp directly here it will need handling properly //Hovers is possible as child but a bit tight, requires good rolls - ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST, logic->HasFireSource() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL) && logic->CanUse(RG_FAIRY_BOW))), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST, logic->HasFireSource() || logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->CanUse(RG_HOOKSHOT))), }); - areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST] = Region("Ganon's Castle MQ Shadow Trial Beamos Chest", SCENE_INSIDE_GANONS_CASTLE, {}, { + areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST] = Region("Ganon's Castle MQ Shadow Trial Beamos Chest", SCENE_INSIDE_GANONS_CASTLE, { + //Events + EVENT_ACCESS(LOGIC_SHADOW_TRIAL_LATE_CHEST, logic->CanHitEyeTargets()), + }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), - LOCATION(RC_GANONS_CASTLE_MQ_BEAMOS_PLATFORM_SHADOW_SILVER, ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || - logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits + //longshot can hit a tiny part of the torch to cross, but it's precise enough to be a trick. ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_BEAMOS, ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || + logic->CanUse(RG_HOVER_BOOTS)), ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FINAL_ROOM, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), }); + areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_BEAMOS] = Region("Ganon's Castle MQ Shadow Trial Far Beamos", SCENE_INSIDE_GANONS_CASTLE, { + //Events + EVENT_ACCESS(LOGIC_SHADOW_TRIAL_LATE_CHEST, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanHitEyeTargets()), + }, { + //Locations + LOCATION(RC_GANONS_CASTLE_MQ_BEAMOS_PLATFORM_SHADOW_SILVER, true), + }, { + //Exits + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST, ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || (logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->CanUse(RG_LONGSHOT)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), + //it's possible to recoil off the beamos, but it's a huge pain and not currently useful. + }); + areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BARRED_DOOR] = Region("Ganon's Castle MQ Shadow Trial Barred Door", SCENE_INSIDE_GANONS_CASTLE, { //Events EVENT_ACCESS(LOGIC_GANONS_CASTLE_MQ_SILVER_SHADOW, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && @@ -743,10 +824,13 @@ void RegionTable_Init_GanonsCastle() { }, { //Locations LOCATION(RC_GANONS_CASTLE_MQ_GUILLOTINE_SHADOW_SILVER, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) || - (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanVoid() && logic->CanUse(RG_HOVER_BOOTS))), + (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanVoid() && logic->CanUse(RG_HOVER_BOOTS)) || + (ctx->GetTrickOption(RT_ITEM_EXTENSION) && logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->CanUse(RG_LONGSHOT))), }, { //Exits - ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) || (logic->Get(LOGIC_SHADOW_TRIAL_LATE_CHEST) && logic->CanUse(RG_LONGSHOT))), + //the beamos makes the recoil annoying, but you can avoid it + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_BEAMOS, (logic->BunnyHovers() || logic->CanRecoilHover(RECOIL_HAMMER)) && (logic->CanAvoidEnemy(RE_BEAMOS, ED_LONGSHOT, true, 1) || logic->CanUse(RG_NUTS))), ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FINAL_ROOM, logic->HasItem(RG_GANONS_CASTLE_MQ_SILVER_SHADOW)), }); 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 178caf5089..72e48f075e 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 @@ -88,7 +88,7 @@ void RegionTable_Init_GerudoTrainingGround() { 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, (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()))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_ROOM_UPPER, (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || ((ctx->GetTrickOption(RT_GTG_FAKE_WALL) || logic->BunnyHood()) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || (logic->IsAdult && logic->CanGroundJump()))), ENTRANCE(RR_GERUDO_TRAINING_GROUND_BEHIND_HEAVY_BLOCK, logic->Get(LOGIC_GTG_PUSHED_HEAVY_BLOCK)), ENTRANCE(RR_GERUDO_TRAINING_GROUND_BOULDER_ROOM, true), }); @@ -121,7 +121,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_EYE_STATUE_UPPER] = Region("Gerudo Training Ground Eye Statue Upper", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_WONDER_EYE_STATUE_ROOM, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_STATUE_JUMP))), // Shuffle roll: Jumpslash doesn't require roll, jump only does + LOCATION(RC_GERUDO_TRAINING_GROUND_WONDER_EYE_STATUE_ROOM, logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_STATUE_JUMP))), // Shuffle roll: Jumpslash doesn't require roll, jump only does }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_EYE_STATUE_LOWER, true), @@ -160,18 +160,18 @@ void RegionTable_Init_GerudoTrainingGround() { }); areaTable[RR_GERUDO_TRAINING_GROUND_LAVA_ROOM] = Region("Gerudo Training Ground Lava Room", SCENE_GERUDO_TRAINING_GROUND, { - EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild)), + EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild)), }, { //Locations LOCATION(RC_GTG_NEAR_SWITCH_LAVA_SILVER, true), LOCATION(RC_GTG_NEAR_BARRED_DOOR_LAVA_SILVER, true), - LOCATION(RC_GTG_FIRE_RING_LAVA_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), - LOCATION(RC_GTG_UNDER_LEDGE_LAVA_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), + LOCATION(RC_GTG_FIRE_RING_LAVA_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), + LOCATION(RC_GTG_UNDER_LEDGE_LAVA_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_DINALFOS, true), ENTRANCE(RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT, logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM_UPPER_LEDGE, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_LAVA_JUMP)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage())))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM_UPPER_LEDGE, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_LAVA_JUMP)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage())))), ENTRANCE(RR_GERUDO_TRAINING_GROUND_UNDERWATER, logic->HasItem(RG_GTG_SILVER_LAVA)), }); @@ -181,7 +181,7 @@ void RegionTable_Init_GerudoTrainingGround() { LOCATION(RC_GTG_UNDER_LEDGE_LAVA_SILVER, true), }, { //Exits - ENTRANCE(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_LAVA_JUMP)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage())), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_LAVA_JUMP)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage())), ENTRANCE(RR_GERUDO_TRAINING_GROUND_HAMMER_ROOM, true), }); @@ -309,7 +309,7 @@ void RegionTable_Init_GerudoTrainingGround() { //Events EVENT_ACCESS(LOGIC_BLUE_FIRE_ACCESS, true), EVENT_ACCESS(LOGIC_GTG_UNLOCKED_DOOR_BEHIND_HEAVY_BLOCK, AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);})), - EVENT_ACCESS(LOGIC_GTG_PUSHED_HEAVY_BLOCK, logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanAvoidEnemy(RE_STALFOS, true, 2)), + EVENT_ACCESS(LOGIC_GTG_PUSHED_HEAVY_BLOCK, logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanAvoidEnemy(RE_STALFOS, ED_CLOSE, true, 2)), }, { //Locations //implies logic->CanKillEnemy(RE_BIG_SKULLTULA) @@ -318,7 +318,8 @@ void RegionTable_Init_GerudoTrainingGround() { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM, true), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_BEHIND_BLOCK, logic->Get(LOGIC_GTG_PUSHED_HEAVY_BLOCK)), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM_ALCOVE, logic->IsAdult && (ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->BlueFire() && (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || (logic->IsAdult && logic->CanGroundJump()))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM_ALCOVE, logic->IsAdult && (ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->BlueFire() && + (logic->CanUse(RG_SONG_OF_TIME) || (logic->Get(LOGIC_GTG_UNLOCKED_DOOR_BEHIND_HEAVY_BLOCK) && (ctx->GetTrickOption(RT_GTG_FAKE_WALL) || logic->BunnyHood()) && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanGroundJump())), }); areaTable[RR_GERUDO_TRAINING_GROUND_MQ_BEHIND_BLOCK] = Region("Gerudo Training Ground MQ Behind Block", SCENE_GERUDO_TRAINING_GROUND, {}, {}, { @@ -344,12 +345,13 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE] = Region("Gerudo Training Ground MQ Statue Room Ledge", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_WONDER_EYE_STATUE, logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_STATUE_JUMP))), // Shuffle roll: Jumpslash doesn't require roll, jump only does + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_WONDER_EYE_STATUE, logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_STATUE_JUMP))), // Shuffle roll: Jumpslash doesn't require roll, jump only does }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM_ALCOVE, true), //implies dropping down to hit the switch. Using swords, especially master, is a bit awkward, may be trick worthy, but is only relevant with other tricks - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAGENTA_FIRE_ROOM, AnyAgeTime([]{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_STICKS) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG);})), + //chus work, but the aim is awkward. + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAGENTA_FIRE_ROOM, AnyAgeTime([]{return logic->CanHitSwitch(ctx->GetTrickOption(RT_VISIBLE_COLLISION) ? ED_MASTER_SWORD_JUMPSLASH : ED_BOOMERANG);})), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM, true), }); @@ -384,24 +386,31 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_SWITCH_LEDGE] = Region("Gerudo Training Ground MQ Switch Ledge", SCENE_GERUDO_TRAINING_GROUND, { //Events EVENT_ACCESS(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH, logic->CanUse(RG_MEGATON_HAMMER)), - EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS)), + EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, logic->CanUse(RG_FIRE_ARROWS) && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())), }, {}, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, logic->CanUse(RG_FIRE_ARROWS)), - //the fire bubble here is a jerk if you are aiming for the nearest hook platform, you have to aim to the right hand side with hook to dodge it - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, logic->CanUse(RG_LONGSHOT) || (logic->HasItem(RG_GTG_SILVER_LAVA) && logic->CanUse(RG_HOOKSHOT)) || (logic->CanUse(RG_FIRE_ARROWS) && logic->HasItem(RG_GTG_SILVER_LAVA) && logic->CanUse(RG_HOVER_BOOTS))), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && logic->CanUse(RG_LONGSHOT)), + //the fire bubble here is a jerk if you are aiming for the nearest hook platform, you have to aim to the right hand side with hook to dodge it. might be an unintuitive trick + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, logic->CanUse(RG_LONGSHOT) || + (logic->HasItem(RG_GTG_SILVER_LAVA) && (logic->CanUse(RG_HOOKSHOT) || logic->BunnyHovers())) || + (ctx->GetTrickOption(RT_GTG_MQ_LAVA_ROOM) && ((logic->IsAdult && logic->BunnyHovers()) || logic->CanUse(RG_HOOKSHOT)))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_GTG_MQ_LAVA_ROOM) && logic->CanUse(RG_HOOKSHOT)))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM, logic->CanUse(RG_FIRE_ARROWS) && ((logic->CanUse(RG_BUNNY_HOOD) && logic->CanJumpslash()) || logic->CanUse(RG_HOVER_BOOTS))), + //You can use roll, silvers and the hover boots to get all the way to lit torch, but it's a trick ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SLUG_ROOM, true), }); //This covers the 2 platforms that can be jumped to directly from RR_GERUDO_TRAINING_GROUND_MQ_SWITCH_LEDGE, without flame circles + //logic for removing fire circles is checked on entry areaTable[RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS] = Region("Gerudo Training Ground MQ Ledge Side Platforms", SCENE_GERUDO_TRAINING_GROUND, {}, { LOCATION(RC_GTG_MQ_NEAR_SWITCH_LAVA_SILVER, true), LOCATION(RC_GTG_MQ_MIDDLE_LAVA_SILVER, true), }, { //Exits - //This is merely to extend this region's logic if you have hovers - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM, logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || ctx->GetTrickOption(RT_GTG_LAVA_JUMP) || (logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && logic->CanUse(RG_HOOKSHOT))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM, logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->HasItem(RG_GTG_SILVER_LAVA)), }); //This covers the platform that needs hover boots or the spawned targets to reach from any starting point other than RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, without flame circles @@ -410,12 +419,13 @@ void RegionTable_Init_GerudoTrainingGround() { }, { //Exits //This is merely to extend this region's logic if you have hovers - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->HasItem(RG_GTG_SILVER_LAVA)), }); areaTable[RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH] = Region("Gerudo Training Ground MQ Platforms Unlit Torch", SCENE_GERUDO_TRAINING_GROUND, { //Events - EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS)), + EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, logic->HasFireSource() && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())), }, { LOCATION(RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER, logic->HasFireSource()), LOCATION(RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER, logic->HasFireSource()), @@ -423,25 +433,38 @@ void RegionTable_Init_GerudoTrainingGround() { }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER, logic->HasItem(RG_GTG_SILVER_LAVA)), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS)), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, logic->HasFireSource() || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && (logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && logic->HasFireSource()))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, logic->HasFireSource() && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->HasItem(RG_GTG_SILVER_LAVA))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, logic->HasFireSource()), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_LIT_TORCH, logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHoverFromObject(TRECOIL_SHORT) || (ctx->GetTrickOption(RT_GTG_MQ_LAVA_ROOM) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && + (((logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && (logic->HasFireSource() || logic->HasItem(RG_GTG_SILVER_LAVA))))) || + (ctx->GetTrickOption(RT_GTG_MQ_LAVA_ROOM) && logic->CanUse(RG_HOOKSHOT) && logic->BunnyHovers()))), }); + //logic for removing fire circles is checked on entry areaTable[RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS] = Region("Gerudo Training Ground MQ Torch Side Platforms", SCENE_GERUDO_TRAINING_GROUND, { //Events //this torch shot is possible as child but tight and obtuse enough to be a trick EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)) && logic->CanUse(RG_HOVER_BOOTS)), }, { //Locations - LOCATION(RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER, (logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)), - LOCATION(RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER, (logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)), - LOCATION(RC_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER, (logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)), + LOCATION(RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER, true), + LOCATION(RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER, true), + LOCATION(RC_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER, true), }, { //Exits - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_LAVA_JUMP)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage()))), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, (logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT))), + //RANDOTODO check this damage boost and apply elsewhere + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_LAVA_JUMP)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage()))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, true), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_LIT_TORCH, true), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && logic->CanUse(RG_HOOKSHOT)), + }); + + areaTable[RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_LIT_TORCH] = Region("Gerudo Training Ground MQ Platforms Lit Torch", SCENE_GERUDO_TRAINING_GROUND, {}, {}, { + //Exits + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHoverFromObject(TRECOIL_SHORT) || (ctx->GetTrickOption(RT_GTG_MQ_LAVA_ROOM) && ((logic->IsAdult && logic->BunnyHood()) || (logic->CanUse(RG_HOVER_BOOTS)/* && roll or bunny*/)))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_GTG_MQ_LAVA_ROOM) && logic->CanUse(RG_HOOKSHOT)))), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_ROOM, true), }); @@ -466,14 +489,12 @@ void RegionTable_Init_GerudoTrainingGround() { //Locations 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)), - LOCATION(RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER, logic->CanUse(RG_FIRE_ARROWS)), - LOCATION(RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER, logic->CanUse(RG_FIRE_ARROWS)), - LOCATION(RC_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER, logic->CanUse(RG_FIRE_ARROWS)), }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, true), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(logic->HasItem(RG_GTG_SILVER_LAVA) ? RG_HOOKSHOT : RG_LONGSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, logic->CanUse(RG_FIRE_ARROWS)), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_LIT_TORCH, logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER) || (ctx->GetTrickOption(RT_GTG_MQ_LAVA_ROOM) && (logic->IsAdult || logic->BunnyHood() || logic->CanUse(RG_HOVER_BOOTS)/* || logic->CanUse(RG_ROLL)*/))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, logic->CanUse(logic->HasItem(RG_GTG_SILVER_LAVA) ? RG_HOOKSHOT : RG_LONGSHOT) || (logic->CanRecoilHover(logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) ? RECOIL_HAMMER : RECOIL_HAMMER_AND_SHIELD))), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, logic->CanUse(RG_FIRE_ARROWS)), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM, logic->CanUse(RG_FIRE_ARROWS)), }); @@ -491,8 +512,8 @@ void RegionTable_Init_GerudoTrainingGround() { LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_WONDER_DINOLFOS_ROOM, logic->CanUse(RG_FAIRY_BOW)), }, { //Exits - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, true), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, AnyAgeTime([]{return 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)));})), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, true), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_LIT_TORCH, AnyAgeTime([]{return 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)));})), }); #pragma endregion 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 9d0a6b3189..10510c7419 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp @@ -20,7 +20,7 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_BEGINNING] = Region("Ice Cavern Beginning", SCENE_ICE_CAVERN, {}, { //Locations LOCATION(RC_ICE_CAVERN_ENTRANCE_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), - LOCATION(RC_ICE_CAVERN_LOBBY_RUPEE, logic->BlueFire()), // can get with rang trick + LOCATION(RC_ICE_CAVERN_LOBBY_RUPEE, logic->BlueFire() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanJumpslash())), // can get with rang trick LOCATION(RC_ICE_CAVERN_ENTRANCE_LEFT_STALAGMITE, logic->CanClearStalagmite()), LOCATION(RC_ICE_CAVERN_ENTRANCE_MIDDLE_STALAGMITE, logic->CanClearStalagmite()), LOCATION(RC_ICE_CAVERN_ENTRANCE_RIGHT_STALAGMITE, logic->CanClearStalagmite()), @@ -83,7 +83,7 @@ void RegionTable_Init_IceCavern() { LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire() && logic->CanOpenLargeChest()), // Bow extension is possible, but very precise: X = 403, Z = 2062-3, Rot = -11475, needs a setup and is its own trick LOCATION(RC_ICE_CAVERN_FROZEN_POT_1, (logic->CanBreakPots() && logic->BlueFire()) || logic->HasExplosives() || - (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanJumpslash()) || + (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && (logic->CanJumpslash())) || (ctx->GetTrickOption(RT_ITEM_EXTENSION) && logic->CanUse(RG_HOOKSHOT))), LOCATION(RC_ICE_CAVERN_MAP_ROOM_LEFT_HEART, true), LOCATION(RC_ICE_CAVERN_MAP_ROOM_MIDDLE_HEART, true), @@ -141,6 +141,7 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_BLOCK_ROOM] = Region("Ice Cavern Block Room", SCENE_ICE_CAVERN, {}, { //Locations // trick involves backflip, could be merged into general trick + // is also possible with bunnyhovers and a jumpslash, but unintuitive LOCATION(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, logic->HookshotOrBoomerang() || (ctx->GetTrickOption(RT_ICE_BLOCK_GS) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH))), LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1, logic->CanUse(RG_BOOMERANG)), LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2, logic->CanUse(RG_BOOMERANG)), @@ -154,8 +155,8 @@ void RegionTable_Init_IceCavern() { LOCATION(RC_ICE_CAVERN_PUSH_BLOCK_HALL_STALACTITE_2, true), LOCATION(RC_ICE_CAVERN_PUSH_BLOCK_HALL_STALACTITE_3, true), LOCATION(RC_ICE_CAVERN_LOWER_BLOCK_SILVER, true), - LOCATION(RC_ICE_CAVERN_NEAR_BLOCK_SILVER, logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS)), - LOCATION(RC_ICE_CAVERN_NEAR_GS_BLOCK_SILVER, logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_ICE_CAVERN_NEAR_BLOCK_SILVER, logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), + LOCATION(RC_ICE_CAVERN_NEAR_GS_BLOCK_SILVER, logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), }, { //Exits ENTRANCE(RR_ICE_CAVERN_HUB, logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP)), @@ -163,10 +164,12 @@ void RegionTable_Init_IceCavern() { ENTRANCE(RR_ICE_CAVERN_AFTER_BLOCK_ROOM, (logic->HasItem(RG_POWER_BRACELET) || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP)))) && logic->HasItem(RG_ICE_CAVERN_SILVER_BLOCK)), }); + //the red ice nook can be reached with bunnyhovers from NEAR_BLOCK_SILVER, but it's unintuitive. + //if implimented, split this region areaTable[RR_ICE_CAVERN_BLOCK_ROOM_NOOKS] = Region("Ice Cavern Block Room Nooks", SCENE_ICE_CAVERN, { //Events EVENT_ACCESS(LOGIC_BLUE_FIRE_ACCESS, true), - EVENT_ACCESS(LOGIC_ICE_CAVERN_SILVER_BLOCK, (logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS)) && + EVENT_ACCESS(LOGIC_ICE_CAVERN_SILVER_BLOCK, (logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()) && (logic->BlueFire() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanJumpslash()))), }, { //Locations @@ -310,9 +313,10 @@ void RegionTable_Init_IceCavern() { LOCATION(RC_ICE_CAVERN_MQ_MAP_RED_ICE, logic->BlueFire()), }, {}); + //RANDOTODO the default state of the toggle switchs in MQ ice are wierd, investigate for doordsanity areaTable[RR_ICE_CAVERN_MQ_SCARECROW_ROOM] = Region("Ice Cavern MQ Scarecrow Room", SCENE_ICE_CAVERN, { //Events - EVENT_ACCESS(LOGIC_BLUE_FIRE_ACCESS, logic->CanUse(RG_SONG_OF_TIME) || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP)))), + EVENT_ACCESS(LOGIC_BLUE_FIRE_ACCESS, logic->CanUse(RG_SONG_OF_TIME) || logic->BunnyHovers() || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP)))), }, { //Locations //Implies being able to kill the skull if you hit the switch @@ -320,14 +324,14 @@ void RegionTable_Init_IceCavern() { LOCATION(RC_ICE_CAVERN_MQ_GS_SCARECROW, logic->ReachScarecrow() || (logic->IsAdult && (logic->CanUse(RG_LONGSHOT) || logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP)))), LOCATION(RC_ICE_CAVERN_MQ_BEFORE_SCARECROW_STALAGMITE, logic->CanClearStalagmite()), LOCATION(RC_ICE_CAVERN_MQ_SCARECROW_ROOM_STALACTITE, true), - LOCATION(RC_ICE_CAVERN_MQ_SCARECROW_LEFT_RED_ICE, logic->IsChild && ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && logic->CanUse(RG_ICE_ARROWS) && logic->CanUse(RG_BOOMERANG)), - LOCATION(RC_ICE_CAVERN_MQ_SCARECROW_MIDDLE_RED_ICE, logic->IsChild && ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && logic->CanUse(RG_ICE_ARROWS) && logic->CanUse(RG_BOOMERANG)), - LOCATION(RC_ICE_CAVERN_MQ_SCARECROW_RIGHT_RED_ICE, logic->IsChild && ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && logic->CanUse(RG_ICE_ARROWS) && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_ICE_CAVERN_MQ_SCARECROW_LEFT_RED_ICE, ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && logic->CanUse(RG_ICE_ARROWS) && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_ICE_CAVERN_MQ_SCARECROW_MIDDLE_RED_ICE, ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && logic->CanUse(RG_ICE_ARROWS) && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_ICE_CAVERN_MQ_SCARECROW_RIGHT_RED_ICE, ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && logic->CanUse(RG_ICE_ARROWS) && logic->CanUse(RG_BOOMERANG)), }, { //Exits ENTRANCE(RR_ICE_CAVERN_MQ_HUB, logic->BlueFire()), //The switch defaults into the state where the block exists, and is a temp flag - ENTRANCE(RR_ICE_CAVERN_MQ_WEST_CORRIDOR, logic->IsAdult && logic->BlueFire()), + ENTRANCE(RR_ICE_CAVERN_MQ_WEST_CORRIDOR, (logic->IsAdult || logic->BunnyHovers()) && logic->BlueFire()), }); areaTable[RR_ICE_CAVERN_MQ_WEST_CORRIDOR] = Region("Ice Cavern MQ West Corridor", SCENE_ICE_CAVERN, {}, { 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 5976869556..e3c6d93ec1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -1,6 +1,7 @@ #include "soh/Enhancements/randomizer/location_access.h" #include "soh/Enhancements/randomizer/entrance.h" #include "soh/Enhancements/randomizer/dungeon.h" +#include "soh/Enhancements/randomizer/randomizerEnums.h" using namespace Rando; @@ -32,10 +33,13 @@ void RegionTable_Init_JabuJabusBelly() { ENTRANCE(RR_JABU_JABUS_BELLY_BEGINNING, true), ENTRANCE(RR_JABU_JABUS_BELLY_HOLES_ROOM, true), ENTRANCE(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, true), - ENTRANCE(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, (logic->Get(LOGIC_JABU_LOWERED_PATH) || (ctx->GetTrickOption(RT_JABU_BOSS_HOVER) && logic->CanUse(RG_HOVER_BOOTS))) && logic->HasItem(RG_POWER_BRACELET)), + ENTRANCE(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, (logic->Get(LOGIC_JABU_LOWERED_PATH) || ((ctx->GetTrickOption(RT_JABU_BOSS_HOVER) || logic->BunnyHood()) && logic->CanUse(RG_HOVER_BOOTS))) && logic->HasItem(RG_POWER_BRACELET)), }); - areaTable[RR_JABU_JABUS_BELLY_HOLES_ROOM] = Region("Jabu Jabus Belly Holes Room", SCENE_JABU_JABU, {}, {}, { + areaTable[RR_JABU_JABUS_BELLY_HOLES_ROOM] = Region("Jabu Jabus Belly Holes Room", SCENE_JABU_JABU, { + //Events + EVENT_ACCESS(LOGIC_JABU_RUTO_IN_B1, true), + }, {}, { //Exits ENTRANCE(RR_JABU_JABUS_BELLY_LIFT_ROOM, true), ENTRANCE(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, true), @@ -65,11 +69,11 @@ void RegionTable_Init_JabuJabusBelly() { EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) && logic->CanUse(RG_HOVER_BOOTS))), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_TWO_OCTOROK_POT_1, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) && logic->CanUse(RG_HOVER_BOOTS))), - LOCATION(RC_JABU_JABUS_BELLY_TWO_OCTOROK_POT_2, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) && logic->CanUse(RG_HOVER_BOOTS))), - LOCATION(RC_JABU_JABUS_BELLY_TWO_OCTOROK_POT_3, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) && logic->CanUse(RG_HOVER_BOOTS))), - LOCATION(RC_JABU_JABUS_BELLY_TWO_OCTOROK_POT_4, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) && logic->CanUse(RG_HOVER_BOOTS))), - LOCATION(RC_JABU_JABUS_BELLY_TWO_OCTOROK_POT_5, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) && logic->CanUse(RG_HOVER_BOOTS))), + LOCATION(RC_JABU_JABUS_BELLY_TWO_OCTOROK_POT_1, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && (ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) || logic->BunnyHood()) && logic->CanUse(RG_HOVER_BOOTS))), + LOCATION(RC_JABU_JABUS_BELLY_TWO_OCTOROK_POT_2, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && (ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) || logic->BunnyHood()) && logic->CanUse(RG_HOVER_BOOTS))), + LOCATION(RC_JABU_JABUS_BELLY_TWO_OCTOROK_POT_3, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && (ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) || logic->BunnyHood()) && logic->CanUse(RG_HOVER_BOOTS))), + LOCATION(RC_JABU_JABUS_BELLY_TWO_OCTOROK_POT_4, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && (ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) || logic->BunnyHood()) && logic->CanUse(RG_HOVER_BOOTS))), + LOCATION(RC_JABU_JABUS_BELLY_TWO_OCTOROK_POT_5, logic->CanUse(RG_BOOMERANG) || (logic->CanBreakPots() && (ctx->GetTrickOption(RT_JABU_B1_CUBE_HOVER) || logic->BunnyHood()) && logic->CanUse(RG_HOVER_BOOTS))), }, { //Exits ENTRANCE(RR_JABU_JABUS_BELLY_HOLES_BASEMENT, true), @@ -77,7 +81,8 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_NORTH] = Region("Jabu Jabus Belly Water Switch Room North", SCENE_JABU_JABU, { //Events - EVENT_ACCESS(LOGIC_JABU_RUTO_IN_1F, (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE)) && logic->HasItem(RG_SPEAK_ZORA) && logic->HasItem(RG_POWER_BRACELET)), + //RANDOTODO check how doorsanity handles ruto + EVENT_ACCESS(LOGIC_JABU_RUTO_IN_1F, logic->Get(LOGIC_JABU_RUTO_IN_B1) && (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE)) && logic->HasItem(RG_SPEAK_ZORA) && logic->HasItem(RG_POWER_BRACELET)), }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), @@ -232,8 +237,14 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_JIGGLIES_ROOM] = Region("Jabu Jabus Belly Jigglies Room", SCENE_JABU_JABU, {}, {}, { //Exits - ENTRANCE(RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO, true), - ENTRANCE(RR_JABU_JABUS_BELLY_LIFT_UPPER, logic->CanUse(RG_BOOMERANG) || (logic->IsAdult && logic->CanGroundJump())), + ENTRANCE(RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO, true), + ENTRANCE(RR_JABU_JABUS_BELLY_JIGGLIES_LEDGE, logic->CanUse(RG_BOOMERANG) || (logic->IsAdult && logic->CanGroundJump())), + }); + + areaTable[RR_JABU_JABUS_BELLY_JIGGLIES_LEDGE] = Region("Jabu Jabus Belly Jigglies Ledge", SCENE_JABU_JABU, {}, {}, { + //Exits + ENTRANCE(RR_JABU_JABUS_BELLY_JIGGLIES_ROOM, true), + ENTRANCE(RR_JABU_JABUS_BELLY_LIFT_UPPER, true), }); areaTable[RR_JABU_JABUS_BELLY_LIFT_UPPER] = Region("Jabu Jabus Belly Lift Upper", SCENE_JABU_JABU, { @@ -298,7 +309,7 @@ void RegionTable_Init_JabuJabusBelly() { ENTRANCE(RR_JABU_JABUS_BELLY_MQ_BEGINNING, true), ENTRANCE(RR_JABU_JABUS_BELLY_MQ_UNDERWATER_ALCOVE, logic->HasItem(RG_SILVER_SCALE) || (logic->HasItem(RG_BRONZE_SCALE) && ((logic->IsChild || logic->CanUse(RG_IRON_BOOTS) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))))), ENTRANCE(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, logic->Get(LOGIC_JABU_MQ_HOLES_ROOM_DOOR)), - ENTRANCE(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE, logic->Get(LOGIC_JABU_LOWERED_PATH) || logic->CanUse(RG_HOVER_BOOTS) || (logic->CanUse(RG_HOOKSHOT) && logic->Get(LOGIC_JABU_MQ_LIFT_ROOM_COW))), + ENTRANCE(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE, logic->Get(LOGIC_JABU_LOWERED_PATH) || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->BunnyHood()) || (logic->CanUse(RG_HOOKSHOT) && logic->Get(LOGIC_JABU_MQ_LIFT_ROOM_COW))), ENTRANCE(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM_PAST_GEYSER, logic->Get(LOGIC_JABU_MQ_WATER_SWITCH_LIFT_ACCESS)), }); @@ -321,6 +332,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM] = Region("Jabu Jabus Belly MQ Holes Room", SCENE_JABU_JABU, { //Events + EVENT_ACCESS(LOGIC_JABU_RUTO_IN_B1, true), EVENT_ACCESS(LOGIC_JABU_MQ_FORKED_ROOM_DOOR, (logic->HasExplosives() || ctx->GetTrickOption(RT_BOULDER_COLLISION)) && logic->CanUse(RG_FAIRY_SLINGSHOT)), }, { //Locations @@ -363,10 +375,10 @@ void RegionTable_Init_JabuJabusBelly() { LOCATION(RC_JABU_JABUS_BELLY_MQ_WONDER_BASEMENT_LEFT_COW_3, logic->CanUse(RG_FAIRY_SLINGSHOT)), }, { //Exits - ENTRANCE(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, logic->HasItem(RG_CLIMB)), - ENTRANCE(RR_JABU_JABUS_BELLY_MQ_TO_BIGOCTO, logic->Get(LOGIC_JABU_WEST_TENTACLE)), - ENTRANCE(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, logic->HasItem(RG_SPEAK_ZORA) && logic->HasItem(RG_POWER_BRACELET)), - ENTRANCE(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, logic->Get(LOGIC_JABU_NORTH_TENTACLE)), + ENTRANCE(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, logic->HasItem(RG_CLIMB)), + ENTRANCE(RR_JABU_JABUS_BELLY_MQ_TO_BIGOCTO, logic->Get(LOGIC_JABU_WEST_TENTACLE)), + ENTRANCE(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, logic->HasItem(RG_SPEAK_ZORA) && logic->HasItem(RG_POWER_BRACELET) && logic->Get(LOGIC_JABU_RUTO_IN_B1)), + ENTRANCE(RR_JABU_JABUS_BELLY_MQ_HOLES_B1_SW_DOOR, true), }); areaTable[RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM] = Region("Jabu Jabus Belly MQ Water Switch Room", SCENE_JABU_JABU, { @@ -383,12 +395,14 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Exits //without swim, jump from rang chest to the other side - ENTRANCE(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM_PAST_GEYSER, AnyAgeTime([]{return logic->CanKillEnemy(RE_LIZALFOS);})), + //you can also bunnyhovers to force your way through but that's a trick + ENTRANCE(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM_PAST_GEYSER, AnyAgeTime([]{return logic->CanKillEnemy(RE_LIZALFOS) && (logic->IsAdult || logic->CanUse(RG_CLIMB) || logic->HasItem(RG_BRONZE_SCALE));})), ENTRANCE(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE)) && AnyAgeTime([]{return logic->CanKillEnemy(RE_LIZALFOS);})), }); areaTable[RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM_PAST_GEYSER] = Region("Jabu Jabus Belly MQ Water Switch Room Past Geyser", SCENE_JABU_JABU, {}, {}, { //Exits + //you can also bunnyhovers to force your way through but that's a trick ENTRANCE(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, logic->Get(LOGIC_JABU_MQ_WATER_SWITCH_LIFT_ACCESS)), ENTRANCE(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, true), }); @@ -432,7 +446,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_FORK_NORTH_WEST] = Region("Jabu Jabus Belly MQ Fork North West", SCENE_JABU_JABU, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, logic->BlastOrSmash() && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, logic->BlastOrSmash() && (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || logic->CanUse(RG_SONG_OF_TIME))), LOCATION(RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_BOULDER, logic->BlastOrSmash()), LOCATION(RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_WALL_BOULDER, logic->BlastOrSmash()), }, { @@ -485,6 +499,12 @@ void RegionTable_Init_JabuJabusBelly() { ENTRANCE(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, true), }); + areaTable[RR_JABU_JABUS_BELLY_MQ_HOLES_B1_SW_DOOR] = Region("Jabu Jabus Belly MQ Holes B1 Southwest Door", SCENE_JABU_JABU, {}, {}, { + //Exits + ENTRANCE(RR_JABU_JABUS_BELLY_MQ_HOLES_BASEMENT, logic->Get(LOGIC_JABU_NORTH_TENTACLE) || logic->TakeDamage()), + ENTRANCE(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, logic->Get(LOGIC_JABU_NORTH_TENTACLE)), + }); + areaTable[RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM] = Region("Jabu Jabus Belly MQ Invisible Keese Room", SCENE_JABU_JABU, {}, { //Locations LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, //firstly, we can just use FAs to clear the web and then longshot the skull @@ -499,10 +519,11 @@ void RegionTable_Init_JabuJabusBelly() { //we can hit the keese farthest from the water with irons and hookshot, but we won't be able to see it while doing so (logic->CanKillEnemy(RE_KEESE, ED_LONGSHOT, false) || (ctx->GetTrickOption(RT_LENS_JABU_MQ) && logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)));})) //If we kill the enemies, we then need to cross the water using the platform. Note that adult cannot do so while swimming because MQ jank. - && ((logic->IsChild && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS)))))), + // we can also reach the platform with bunny to Jumpslash + && ((logic->IsChild && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS)) || (logic->BunnyHood() && logic->CanJumpslash()))))), }, { //Exits - ENTRANCE(RR_JABU_JABUS_BELLY_MQ_HOLES_BASEMENT, (logic->Get(LOGIC_JABU_NORTH_TENTACLE) || logic->TakeDamage()) && logic->HasItem(RG_BRONZE_SCALE)), + ENTRANCE(RR_JABU_JABUS_BELLY_MQ_HOLES_B1_SW_DOOR, logic->HasItem(RG_BRONZE_SCALE)), }); // unlike other entrances behind tentacles, Link spawns behind the tentacle. Running into it throws him into main room still @@ -568,7 +589,6 @@ void RegionTable_Init_JabuJabusBelly() { ENTRANCE(RR_JABU_JABUS_BELLY_MQ_NEAR_BOSS_ROOM, logic->Get(LOGIC_JABU_NORTH_TENTACLE)), }); - areaTable[RR_JABU_JABUS_BELLY_MQ_NEAR_BOSS_ROOM] = Region("Jabu Jabus Belly MQ Near Boss Room", SCENE_JABU_JABU, { //Events EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CanBreakPots()), 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 0d8dd4149d..3782e6df2c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp @@ -24,7 +24,7 @@ void RegionTable_Init_ShadowTemple() { //Exits ENTRANCE(RR_SHADOW_TEMPLE_ENTRYWAY, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))), ENTRANCE(RR_SHADOW_TEMPLE_WHISPERING_WALLS_START, ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)), - ENTRANCE(RR_SHADOW_TEMPLE_FIRST_BEAMOS, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_POWER_BRACELET) && logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_SHADOW_TEMPLE_FIRST_BEAMOS, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_POWER_BRACELET) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood()))), }); areaTable[RR_SHADOW_TEMPLE_WHISPERING_WALLS_START] = Region("Shadow Temple Whispering Walls Start", SCENE_SHADOW_TEMPLE, { @@ -90,7 +90,7 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_BEGINNING, ctx->GetTrickOption(RT_VISIBLE_COLLISION) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))), + ENTRANCE(RR_SHADOW_TEMPLE_BEGINNING, ctx->GetTrickOption(RT_VISIBLE_COLLISION) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->BunnyHood()))), ENTRANCE(RR_SHADOW_TEMPLE_COMPASS_ROOM, true), ENTRANCE(RR_SHADOW_TEMPLE_SPINNING_BLADES, true), ENTRANCE(RR_SHADOW_TEMPLE_B2_TO_B3_CORRIDOR_B2, logic->HasExplosives() && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 1)), @@ -106,12 +106,12 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_SPINNING_BLADES] = Region("Shadow Temple Spinning Blades", SCENE_SHADOW_TEMPLE, { //Events - EVENT_ACCESS(LOGIC_SHADOW_SILVER_BLADES, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT)), + EVENT_ACCESS(LOGIC_SHADOW_SILVER_BLADES, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT) || logic->BunnyHood()), }, { //Locations LOCATION(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, logic->HasItem(RG_SHADOW_SILVER_BLADES) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_N_UNDER_BLADE_SILVER, true), - LOCATION(RC_SHADOW_TALL_BLOCK_BLADE_SILVER, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_TALL_BLOCK_BLADE_SILVER, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT) || logic->BunnyHood()), LOCATION(RC_SHADOW_N_NOOK_BLADE_SILVER, true), LOCATION(RC_SHADOW_W_NOOK_BLADE_SILVER, true), LOCATION(RC_SHADOW_S_UNDER_BLADE_SILVER, true), @@ -141,7 +141,7 @@ void RegionTable_Init_ShadowTemple() { //Exits ENTRANCE(RR_SHADOW_TEMPLE_B2_TO_B3_CORRIDOR_B3, logic->CanUse(RG_LONGSHOT)), ENTRANCE(RR_SHADOW_TEMPLE_UPPER_HUGE_PIT_DOOR_LEDGE, ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)), - ENTRANCE(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT, logic->IsAdult || logic->CanJumpslash() || ctx->GetTrickOption(RT_SHADOW_MQ_HUGE_PIT)), + ENTRANCE(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT, logic->IsAdult || logic->CanJumpslash() || logic->BunnyHood() || ctx->GetTrickOption(RT_SHADOW_MQ_HUGE_PIT)), }); areaTable[RR_SHADOW_TEMPLE_UPPER_HUGE_PIT_DOOR_LEDGE] = Region("Shadow Temple Upper Huge Pit Door Ledge", SCENE_SHADOW_TEMPLE, {}, {}, { @@ -162,7 +162,7 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_W_PIT_SILVER, true), },{ //Exits - ENTRANCE(RR_SHADOW_TEMPLE_UPPER_HUGE_PIT, logic->IsAdult || logic->CanJumpslash()), + ENTRANCE(RR_SHADOW_TEMPLE_UPPER_HUGE_PIT, logic->IsAdult || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), ENTRANCE(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT_DOOR_LEDGE, (ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)), ENTRANCE(RR_SHADOW_TEMPLE_STONE_UMBRELLA, logic->HasItem(RG_SHADOW_SILVER_PIT)), }); @@ -227,7 +227,8 @@ void RegionTable_Init_ShadowTemple() { //Assumes logic for navigating around spikes is checked on entry areaTable[RR_SHADOW_TEMPLE_FLOOR_SPIKES_ROOM] = Region("Shadow Temple Floor Spikes Room", SCENE_SHADOW_TEMPLE, { //Events - EVENT_ACCESS(LOGIC_SHADOW_SILVER_SPIKES, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT))), + EVENT_ACCESS(LOGIC_SHADOW_SILVER_SPIKES, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && + (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanMiddairGroundJump() && ((logic->BunnyHovers() && logic->CanJumpslash()) || logic->CanRecoilHover(RECOIL_HAMMER))))), }, { //Locations LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), @@ -256,6 +257,7 @@ void RegionTable_Init_ShadowTemple() { //Locations LOCATION(RC_SHADOW_PLATFORM_SPIKES_SILVER, true), LOCATION(RC_SHADOW_AIRBORNE_SPIKES_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + LOCATION(RC_SHADOW_W_TARGET_SPIKES_SILVER, (logic->BunnyHovers() && logic->CanJumpslash()) || logic->CanUse(RG_HOOKSHOT) || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD)), }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), @@ -264,10 +266,12 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_SPIKES_DOOR_PLATFORM] = Region("Shadow Temple Spikes Door Platform", SCENE_SHADOW_TEMPLE, {}, { //Locations LOCATION(RC_SHADOW_AIRBORNE_SPIKES_SILVER, true), + LOCATION(RC_SHADOW_E_TARGET_SPIKES_SILVER, (logic->BunnyHovers() && logic->CanJumpslash()) || logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)), + LOCATION(RC_SHADOW_W_TARGET_SPIKES_SILVER, logic->CanUse(RG_LONGSHOT)), }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), - ENTRANCE(RR_SHADOW_TEMPLE_SPIKES_CORNER_PLATFORM, logic->CanUse(RG_HOVER_BOOTS)/* && logic->CanUse(RG_ROLL)*/), + ENTRANCE(RR_SHADOW_TEMPLE_SPIKES_CORNER_PLATFORM, logic->CanUse(RG_HOVER_BOOTS)/* && roll or bunny*/), ENTRANCE(RR_SHADOW_TEMPLE_UPPER_WIND_TUNNEL, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3)), }); @@ -283,7 +287,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_UPPER_WIND_TUNNEL] = Region("Shadow Temple Upper Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_SPIKES_DOOR_PLATFORM, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3)), - ENTRANCE(RR_SHADOW_TEMPLE_LOWER_WIND_TUNNEL, (logic->CanUse(RG_HOVER_BOOTS) && logic->CanPassEnemy(RE_BIG_SKULLTULA)) || logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_SHADOW_TEMPLE_LOWER_WIND_TUNNEL, logic->CanUse(RG_HOOKSHOT) || ((logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()) && logic->CanPassEnemy(RE_BIG_SKULLTULA))), }); areaTable[RR_SHADOW_TEMPLE_LOWER_WIND_TUNNEL] = Region("Shadow Temple Lower Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, {}, { @@ -294,7 +298,7 @@ void RegionTable_Init_ShadowTemple() { }); areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL_ALCOVE] = Region("Shadow Temple Wind Tunnel Alcove", SCENE_SHADOW_TEMPLE, {}, {}, { - ENTRANCE(RR_SHADOW_TEMPLE_LOWER_WIND_TUNNEL, (ctx->GetTrickOption(RT_SHADOW_MQ_WINDY_WALKWAY)) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_SHADOW_TEMPLE_LOWER_WIND_TUNNEL, (ctx->GetTrickOption(RT_SHADOW_MQ_WINDY_WALKWAY)) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), ENTRANCE(RR_SHADOW_TEMPLE_ROOM_TO_BOAT, true), }); @@ -345,8 +349,8 @@ void RegionTable_Init_ShadowTemple() { //Exits ENTRANCE(RR_SHADOW_TEMPLE_MAZE, true), ENTRANCE(RR_SHADOW_TEMPLE_CHASM_SCARECROW, logic->ReachDistantScarecrow()), - // a precise recoil hover back flip can get across too, but isn't a simple hover boost - ENTRANCE(RR_SHADOW_TEMPLE_ACROSS_CHASM, logic->Get(LOGIC_SHADOW_BRIDGE_BEYOND_BOAT_LOWERED)), + // a less precise recoil off the broken statue into a jumpslash works. + ENTRANCE(RR_SHADOW_TEMPLE_ACROSS_CHASM, logic->Get(LOGIC_SHADOW_BRIDGE_BEYOND_BOAT_LOWERED) || logic->CanRecoilHover(RECOIL_HAMMER_AND_SHIELD)), }); areaTable[RR_SHADOW_TEMPLE_CHASM_SCARECROW] = Region("Shadow Temple Chasm Scarecrow", SCENE_SHADOW_TEMPLE, {}, { @@ -356,7 +360,7 @@ void RegionTable_Init_ShadowTemple() { }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_ACROSS_CHASM, true), - ENTRANCE(RR_SHADOW_TEMPLE_BROKEN_PILLAR, logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->IsAdult && logic->CanJumpslash())), + ENTRANCE(RR_SHADOW_TEMPLE_BROKEN_PILLAR, logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash()) || (logic->IsAdult && ((ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->CanJumpslash()) || logic->BunnyHood()))), }); areaTable[RR_SHADOW_TEMPLE_ACROSS_CHASM] = Region("Shadow Temple Across Chasm", SCENE_SHADOW_TEMPLE, { @@ -369,7 +373,8 @@ void RegionTable_Init_ShadowTemple() { //RC_SHADOW_TEMPLE_AFTER_SHIP_LOWER_HEART requires an indirect boomerang from here due to invisible collision }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_BEYOND_BOAT, (logic->Get(LOGIC_SHADOW_BRIDGE_BEYOND_BOAT_LOWERED) && logic->IsAdult) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), + //child can use the statue with hovers, but needs to run around the side so it's unintuitive + ENTRANCE(RR_SHADOW_TEMPLE_BEYOND_BOAT, (logic->Get(LOGIC_SHADOW_BRIDGE_BEYOND_BOAT_LOWERED) && logic->IsAdult) || logic->CanRecoilHover(RECOIL_HAMMER)), ENTRANCE(RR_SHADOW_TEMPLE_BROKEN_PILLAR, logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME)), ENTRANCE(RR_SHADOW_TEMPLE_PRE_BOSS_ROOM, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 5)), }); @@ -423,7 +428,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_PRE_BOSS_ROOM] = Region("Shadow Temple Pre Boss Room", SCENE_SHADOW_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_ACROSS_CHASM, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 5)), - ENTRANCE(RR_SHADOW_TEMPLE_BOSS_DOOR, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_SHADOW_TEMPLE_BOSS_DOOR, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->IsAdult))), }); areaTable[RR_SHADOW_TEMPLE_BOSS_DOOR] = Region("Shadow Temple Boss Door", SCENE_SHADOW_TEMPLE, {}, { @@ -431,7 +436,9 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_BOSS_KEY_HINT, true), }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_PRE_BOSS_ROOM, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOVER_BOOTS)), + //child can make this jump with bunny, and it's not hard, but it's too inconsistent for unintuitive + ENTRANCE(RR_SHADOW_TEMPLE_PRE_BOSS_ROOM, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && + (logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->IsAdult))), ENTRANCE(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, true), }); @@ -455,7 +462,7 @@ void RegionTable_Init_ShadowTemple() { }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_ENTRYWAY, true), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, AnyAgeTime([]{return logic->HasItem(RG_POWER_BRACELET) && (logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)));}) && (logic->CanUse(RG_HOVER_BOOTS) || AnyAgeTime([]{return logic->CanUse(RG_FIRE_ARROWS);}) || (ctx->GetTrickOption(RT_SHADOW_MQ_GAP) && logic->CanUse(RG_LONGSHOT) && logic->CanJumpslashExceptHammer()))), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, AnyAgeTime([]{return logic->HasItem(RG_POWER_BRACELET) && (logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)));}) && ((logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())) || AnyAgeTime([]{return logic->CanUse(RG_FIRE_ARROWS);}) || (ctx->GetTrickOption(RT_SHADOW_MQ_GAP) && logic->CanUse(RG_LONGSHOT) && logic->CanJumpslashExceptHammer()))), ENTRANCE(RR_SHADOW_TEMPLE_MQ_WHISPERING_WALLS_START, AnyAgeTime([]{return logic->HasExplosives();}) && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 6) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), }); @@ -511,7 +518,7 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_STORM_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPINNER_ROOM, ctx->GetTrickOption(RT_VISIBLE_COLLISION) && (logic->CanUse(RG_HOVER_BOOTS) || logic->HasFireSource())), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPINNER_ROOM, ctx->GetTrickOption(RT_VISIBLE_COLLISION) && (logic->CanUse(RG_HOVER_BOOTS) || logic->HasFireSource() || (logic->IsAdult && logic->BunnyHood()))), ENTRANCE(RR_SHADOW_TEMPLE_MQ_B2_GIBDO_ROOM, true), ENTRANCE(RR_SHADOW_TEMPLE_MQ_B2_TO_B3_CORRIDOR_B2, logic->HasExplosives() && logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2)), ENTRANCE(RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM, true), @@ -528,12 +535,12 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM] = Region("Shadow Temple MQ B2 Spinning Blade Room", SCENE_SHADOW_TEMPLE, { //Events - EVENT_ACCESS(LOGIC_SHADOW_SILVER_BLADES, logic->CanKillEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())))), + EVENT_ACCESS(LOGIC_SHADOW_SILVER_BLADES, logic->CanKillEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump() || logic->BunnyHood())))), }, { //Locations LOCATION(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && logic->HasItem(RG_SHADOW_SILVER_BLADES) && logic->CanOpenLargeChest()), LOCATION(RC_SHADOW_MQ_W_NOOK_SILVER, logic->CanPassEnemy(RE_BIG_SKULLTULA)), - LOCATION(RC_SHADOW_MQ_TALL_BLOCK_BLADE_SILVER, logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump()))), + LOCATION(RC_SHADOW_MQ_TALL_BLOCK_BLADE_SILVER, logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump() || logic->BunnyHood()))), LOCATION(RC_SHADOW_MQ_NE_UNDER_BLADE_SILVER, true), LOCATION(RC_SHADOW_MQ_S_UNDER_BLADE_SILVER, true), LOCATION(RC_SHADOW_MQ_N_NOOK_BLADE_SILVER, logic->CanPassEnemy(RE_BIG_SKULLTULA)), @@ -568,14 +575,14 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT] = Region("Shadow Temple MQ Upper Huge Pit", SCENE_SHADOW_TEMPLE, { //Events - EVENT_ACCESS(LOGIC_SHADOW_MQ_PIT_STAIRS, logic->HasFireSource()), + EVENT_ACCESS(LOGIC_SHADOW_MQ_PIT_STAIRS, logic->HasFireSource() && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), }, { //Locations LOCATION(RC_SHADOW_TEMPLE_MQ_PIT_STORM_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT_DOOR_LEDGE, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, (logic->Get(LOGIC_SHADOW_MQ_PIT_STAIRS) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))) || ctx->GetTrickOption(RT_SHADOW_MQ_HUGE_PIT)), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, logic->Get(LOGIC_SHADOW_MQ_PIT_STAIRS) || ctx->GetTrickOption(RT_SHADOW_MQ_HUGE_PIT) || logic->BunnyHovers()), }); areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT_DOOR_LEDGE] = Region("Shadow Temple MQ Upper Huge Pit Door Ledge", SCENE_SHADOW_TEMPLE, {}, {}, { @@ -627,7 +634,7 @@ void RegionTable_Init_ShadowTemple() { //Exits ENTRANCE(RR_SHADOW_TEMPLE_MQ_B2_TO_B3_CORRIDOR_B3, logic->CanUse(RG_LONGSHOT)), ENTRANCE(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, logic->Get(LOGIC_SHADOW_MQ_PIT_STAIRS)), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT_DOOR_LEDGE, logic->CanUse(RG_HOVER_BOOTS) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM) || logic->CanUse(RG_LENS_OF_TRUTH))), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT_DOOR_LEDGE, (logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM) || logic->CanUse(RG_LENS_OF_TRUTH))), ENTRANCE(RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM, AnyAgeTime([]{return logic->CanJumpslash() || logic->HasExplosives() || logic->CanUse(RG_GIANTS_KNIFE) || (ctx->GetTrickOption(RT_ITEM_EXTENSION) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)));})), }); @@ -685,9 +692,9 @@ void RegionTable_Init_ShadowTemple() { //This needs either longshot, middair ground jump or hookshot & adult & defeating the redeads (as any age, as they are perm flags) //hovers can cross from the corner platform with a backflip but that would be a trick. logic->CanUse(RG_LONGSHOT) || ((AnyAgeTime([]{return logic->CanKillEnemy(RE_REDEAD);}) || logic->CanMiddairGroundJump()) && - //East midair rupee needs longshot to reach from the floor, or hover boots or jumpslash to reach from the upper door platform. - (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS))) && - //1 rupee is in spikes, needs hovers or damage + //East midair rupee needs longshot to reach from the floor, or hover boots, bunny hood or jumpslash to reach from the upper door platform. + (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())) && + //1 rupee is in spikes, needs hovers, goron tunic or damage (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC))), }, { //Locations @@ -730,6 +737,7 @@ void RegionTable_Init_ShadowTemple() { // can also get W target silver and get to door platform with hovers backwalk>backflip LOCATION(RC_SHADOW_MQ_PLATFORM_SPIKES_SILVER, true), LOCATION(RC_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER, true), + LOCATION(RC_SHADOW_MQ_W_TARGET_SPIKES_SILVER, (logic->BunnyHovers() && logic->CanJumpslash()) || logic->CanUse(RG_HOOKSHOT) || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD)), }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), @@ -747,30 +755,30 @@ void RegionTable_Init_ShadowTemple() { }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_DOOR_PLATFORM, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanJumpslash())), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_DOOR_PLATFORM, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanJumpslash()) || logic->BunnyHood()), }); areaTable[RR_SHADOW_TEMPLE_MQ_SPIKES_DOOR_PLATFORM] = Region("Shadow Temple MQ Spikes Door Platform", SCENE_SHADOW_TEMPLE, { - //Events //(lens or trick) & (adult & hookshot) or longshot is always required for rupees below hookshot targets and the corner platform. + //Events //(lens or trick) & (adult & hookshot) or longshot is always required for rupees below hookshot targets and lens for the corner platform. EVENT_ACCESS(LOGIC_SHADOW_SILVER_SPIKES, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(logic->IsAdult ? RG_LONGSHOT : RG_HOOKSHOT) && //As we start on the upper door platform, we can get north target rupee with just hook, then jump off to get east middair, after which we do not need to get up here again - //East midair rupee needs longshot to reach from the floor, or hover boots or jumpslash to reach from the upper door platform. - (logic->CanUse(RG_LONGSHOT) || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)) && + //East midair rupee needs longshot to reach from the floor, or hover boots, bunny hood or jumpslash to reach from the upper door platform. + (logic->CanUse(RG_LONGSHOT) || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()) && //1 rupee is in spikes, needs hovers or damage (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC))), }, { //Locations // can also get W_TARGET and E_TARGET with hovers backwalk backflip LOCATION(RC_SHADOW_MQ_W_TARGET_SPIKES_SILVER, logic->CanUse(RG_LONGSHOT)), - LOCATION(RC_SHADOW_MQ_E_TARGET_SPIKES_SILVER, logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_SHADOW_MQ_E_TARGET_SPIKES_SILVER, (logic->BunnyHovers() && logic->CanJumpslash()) || logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)), LOCATION(RC_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER, true), LOCATION(RC_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), - LOCATION(RC_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash()), + LOCATION(RC_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash() || logic->BunnyHood()), }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_CORNER_PLATFORM, logic->CanUse(RG_HOVER_BOOTS)/* && logic->CanUse(RG_ROLL)*/), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_GLASS_PLATFORMS, logic->HasItem(RG_SHADOW_SILVER_SPIKES) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_CORNER_PLATFORM, logic->CanUse(RG_HOVER_BOOTS)/* && roll or bunny*/), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_GLASS_PLATFORMS, logic->HasItem(RG_SHADOW_SILVER_SPIKES) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())), ENTRANCE(RR_SHADOW_TEMPLE_MQ_UPPER_WIND_TUNNEL, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)), }); @@ -785,7 +793,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_WIND_TUNNEL] = Region("Shadow Temple MQ Upper Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_DOOR_PLATFORM, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_WIND_TUNNEL, (logic->CanUse(RG_HOVER_BOOTS) && logic->CanPassEnemy(RE_BIG_SKULLTULA)) || logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_WIND_TUNNEL, ((logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()) && logic->CanPassEnemy(RE_BIG_SKULLTULA)) || logic->CanUse(RG_HOOKSHOT)), }); areaTable[RR_SHADOW_TEMPLE_MQ_LOWER_WIND_TUNNEL] = Region("Shadow Temple MQ Lower Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, {}, { @@ -806,7 +814,9 @@ void RegionTable_Init_ShadowTemple() { }); areaTable[RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL_ALCOVE] = Region("Shadow Temple MQ Wind Tunnel Alcove", SCENE_SHADOW_TEMPLE, {}, {}, { - ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_WIND_TUNNEL, (ctx->GetTrickOption(RT_SHADOW_MQ_WINDY_WALKWAY)) || logic->CanUse(RG_HOVER_BOOTS)), + //Exits + //child can make it using the wind strat + ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_WIND_TUNNEL, ctx->GetTrickOption(RT_SHADOW_MQ_WINDY_WALKWAY) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), ENTRANCE(RR_SHADOW_TEMPLE_MQ_B4_GIBDO_ROOM, true), }); @@ -823,7 +833,6 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_BOAT_POT_2, logic->CanBreakPots()), }, { //Exits - //child can make it using the wind strat ENTRANCE(RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL_ALCOVE, true), ENTRANCE(RR_SHADOW_TEMPLE_MQ_DOCK, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 5)), }); @@ -847,15 +856,14 @@ void RegionTable_Init_ShadowTemple() { EVENT_ACCESS(LOGIC_SHADOW_BRIDGE_BEYOND_BOAT_LOWERED, logic->CanUse(RG_FAIRY_BOW) || (ctx->GetTrickOption(RT_SHADOW_STATUE) && logic->CanUse(RG_BOMBCHU_5))), }, { //Locations - //It's a trick on N64 to kill this and drop down to collect this with normal weapons, as doing so without the statue being dropped voids you to before the boat - //hilariously, you can hit this with a pot before you bring down statue, but there's no great way to reset it without crossing. the statue's collision is very inconvenient afterwards + //hilariously, you can hit this with a pot before you bring down statue, but the statue's collision is very inconvenient afterwards and knocking it down cannot be undone LOCATION(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW) && (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanVoid()))), LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_CHASM_WEST_POT, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_CHASM_EAST_POT, logic->CanBreakPots()), }, { //Exits - // a precise recoil hover back flip can get across too, but isn't a simple hover boost - ENTRANCE(RR_SHADOW_TEMPLE_MQ_ACROSS_CHASM, logic->Get(LOGIC_SHADOW_BRIDGE_BEYOND_BOAT_LOWERED) || (logic->Get(LOGIC_SHADOW_MQ_SWITCH_ACROSS_CHASM) && logic->CanUse(RG_LONGSHOT))), + // a less precise recoil off the broken statue into a jumpslash works. + ENTRANCE(RR_SHADOW_TEMPLE_MQ_ACROSS_CHASM, logic->Get(LOGIC_SHADOW_BRIDGE_BEYOND_BOAT_LOWERED) || (logic->Get(LOGIC_SHADOW_MQ_SWITCH_ACROSS_CHASM) && logic->CanUse(RG_LONGSHOT)) || logic->CanRecoilHover(RECOIL_HAMMER_AND_SHIELD)), ENTRANCE(RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, logic->Get(LOGIC_SHADOW_MQ_SWITCH_ACROSS_CHASM)), }); @@ -871,17 +879,19 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_SHIP_UPPER_LEFT_HEART, logic->Get(LOGIC_SHADOW_MQ_EYE_SWITCH_ACROSS_CHASM) && logic->CanUse(RG_LONGSHOT)), LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_SHIP_UPPER_RIGHT_HEART, logic->Get(LOGIC_SHADOW_MQ_EYE_SWITCH_ACROSS_CHASM) && logic->CanUse(RG_LONGSHOT)), //There's invisible floor collision that makes aiming for the heart with rang harder than it should be, so it's a trick. - LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_SHIP_LOWER_HEART, logic->IsAdult), + LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_SHIP_LOWER_HEART, logic->IsAdult || (logic->Get(LOGIC_SHADOW_MQ_EYE_SWITCH_ACROSS_CHASM) && logic->CanUse(RG_HOOKSHOT))), }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, (logic->Get(LOGIC_SHADOW_BRIDGE_BEYOND_BOAT_LOWERED) && logic->IsAdult) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), + //child can use the statue with hovers, but needs to run around the side so it's unintuitive + ENTRANCE(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, (logic->Get(LOGIC_SHADOW_BRIDGE_BEYOND_BOAT_LOWERED) && logic->IsAdult) || logic->CanRecoilHover(RECOIL_HAMMER)), ENTRANCE(RR_SHADOW_TEMPLE_MQ_PRE_BOSS_ROOM, true), }); areaTable[RR_SHADOW_TEMPLE_MQ_PRE_BOSS_ROOM] = Region("Shadow Temple MQ Pre Boss Room", SCENE_SHADOW_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_MQ_ACROSS_CHASM, true), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_BOSS_DOOR, logic->CanUse(RG_HOVER_BOOTS) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + //child can make this jump with bunny, and it's not hard, but it's too inconsistent for unintuitive + ENTRANCE(RR_SHADOW_TEMPLE_MQ_BOSS_DOOR, (logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->IsAdult)) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), }); areaTable[RR_SHADOW_TEMPLE_MQ_BOSS_DOOR] = Region("Shadow Temple MQ Boss Door", SCENE_SHADOW_TEMPLE, {}, { @@ -890,7 +900,7 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, (logic->HookshotOrBoomerang() || ((logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW) || logic->CanUse(RG_MEGATON_HAMMER)) && (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanVoid()))) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_MQ_PRE_BOSS_ROOM, logic->CanUse(RG_HOVER_BOOTS) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_PRE_BOSS_ROOM, (logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->IsAdult)) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), ENTRANCE(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, true), }); @@ -937,8 +947,8 @@ void RegionTable_Init_ShadowTemple() { // Boss Room areaTable[RR_SHADOW_TEMPLE_BOSS_ENTRYWAY] = Region("Shadow Temple Boss Entryway", SCENE_SHADOW_TEMPLE, {}, {}, { // Exits - ENTRANCE(RR_SHADOW_TEMPLE_BOSS_DOOR, ctx->GetDungeon(SHADOW_TEMPLE)->IsVanilla() && false), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_BOSS_DOOR, ctx->GetDungeon(SHADOW_TEMPLE)->IsMQ() && false), + ENTRANCE(RR_SHADOW_TEMPLE_BOSS_DOOR, ctx->GetDungeon(SHADOW_TEMPLE)->IsVanilla()), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_BOSS_DOOR, ctx->GetDungeon(SHADOW_TEMPLE)->IsMQ()), ENTRANCE(RR_SHADOW_TEMPLE_BOSS_ROOM, logic->HasItem(RG_SHADOW_TEMPLE_BOSS_KEY)), }); 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 387b51f723..b938c1a0da 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -56,7 +56,7 @@ void RegionTable_Init_SpiritTemple() { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_CHILD_SIDE_HUB, true), ENTRANCE(RR_SPIRIT_TEMPLE_SWITCH_BRIDGE_NORTH, (logic->Get(LOGIC_SPIRIT_CHILD_SWITCH_BRIDGE) && logic->CanPassEnemy(RE_GREEN_BUBBLE, ED_CLOSE, false)) || - logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT)/* || (logic->IsAdult && CanBunnyJump())*/), + logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && logic->BunnyHood())), }); areaTable[RR_SPIRIT_TEMPLE_SWITCH_BRIDGE_NORTH] = Region("Spirit Temple Switch Bridge North", SCENE_SPIRIT_TEMPLE, { @@ -67,7 +67,7 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits - ENTRANCE(RR_SPIRIT_TEMPLE_SWITCH_BRIDGE_SOUTH, logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_SPIRIT_CHILD_SWITCH_BRIDGE) && logic->CanPassEnemy(RE_GREEN_BUBBLE, ED_CLOSE, false))), + ENTRANCE(RR_SPIRIT_TEMPLE_SWITCH_BRIDGE_SOUTH, logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_SPIRIT_CHILD_SWITCH_BRIDGE) && logic->CanPassEnemy(RE_GREEN_BUBBLE, ED_CLOSE, false)) || (logic->IsAdult && logic->BunnyHood())), ENTRANCE(RR_SPIRIT_TEMPLE_1F_ANUBIS, true), }); @@ -158,7 +158,8 @@ 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))) && logic->CanOpenLargeChest()), + //bunnyhovers works as adult if you run against the wall, but it's unintuitive + LOCATION(RC_SPIRIT_TEMPLE_COMPASS_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->CanOpenLargeChest()), }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_ADULT_SIDE_HUB, true), @@ -169,10 +170,10 @@ void RegionTable_Init_SpiritTemple() { //Jumpslash is possible as child, but pretty tight. Jumpslash as late as you can //A damage boost off the boulder is also possible, but you need to land on the middle of the boulder //to get enough distance to reach the rupee - EVENT_ACCESS(LOGIC_SPIRIT_SILVER_BOULDERS, logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash() || logic->CanUse(RG_LONGSHOT)/* || CanBunnyHop()*/), + EVENT_ACCESS(LOGIC_SPIRIT_SILVER_BOULDERS, logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash() || logic->CanUse(RG_LONGSHOT) || logic->BunnyHood()), }, { //Locations - LOCATION(RC_SPIRIT_AIRBORNE_BOULDER_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash() || logic->CanUse(RG_LONGSHOT)/* || CanBunnyHop()*/), + LOCATION(RC_SPIRIT_AIRBORNE_BOULDER_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash() || logic->CanUse(RG_LONGSHOT) || logic->BunnyHood()), }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_ADULT_SIDE_HUB, true), @@ -221,27 +222,30 @@ 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_ADULT, []{return logic->HasFireSourceWithTorch();}, RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource();}) && logic->CanOpenLargeChest()), 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);})), }, { //Exits - ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM, true), - ENTRANCE(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, true), - ENTRANCE(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, true), - ENTRANCE(RR_SPIRIT_TEMPLE_GS_LEDGE, logic->CanUse(RG_HOVER_BOOTS) || logic->ReachScarecrow()), + ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM, true), + ENTRANCE(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, true), + ENTRANCE(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, true), + ENTRANCE(RR_SPIRIT_TEMPLE_GS_LEDGE, logic->CanUse(RG_HOVER_BOOTS) || logic->ReachScarecrow()), + //adult requirement is artificial as a way to prevent child logic leaking + ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, logic->CanRecoilHoverFromObject(TRECOIL_SHORT) && logic->IsAdult), // RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled - ENTRANCE(RR_SPIRIT_TEMPLE_PLATFORM, logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && - (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)))), - ENTRANCE(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, logic->HasItem(RG_POWER_BRACELET)), + ENTRANCE(RR_SPIRIT_TEMPLE_PLATFORM, logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && + (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)))), + ENTRANCE(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, logic->HasItem(RG_POWER_BRACELET)), //!QUANTUM LOGIC! //When child enters spirit in reverse, has 4 keys, and dungeon entrance shuffle is off, //Child cannot lock themselves out of desert colossus access as if they save the west hand lock for last //they will be able to exit the dungeon through the intended entrance and vice versa //for needing to open the west hand lock to block the intended child route - ENTRANCE(RR_DESERT_COLOSSUS, ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && logic->HasItem(RG_POWER_BRACELET) && - logic->CanUse(RG_CRAWL) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4) && logic->CanKillEnemy(RE_IRON_KNUCKLE)), + ENTRANCE(RR_DESERT_COLOSSUS, ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && logic->HasItem(RG_POWER_BRACELET) && + logic->CanUse(RG_CRAWL) && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4) && logic->CanKillEnemy(RE_IRON_KNUCKLE)), }); areaTable[RR_SPIRIT_TEMPLE_INNER_WEST_HAND] = Region("Spirit Temple Inner West Hand", SCENE_SPIRIT_TEMPLE, {}, { @@ -252,17 +256,20 @@ void RegionTable_Init_SpiritTemple() { RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT);})), }, { //Exits - ENTRANCE(RR_DESERT_COLOSSUS, (logic->IsChild && logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5)) || (logic->CanUse(RG_SILVER_GAUNTLETS) && ((logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 3) && logic->HasExplosives()) || logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 5)))), + //Adult can barely make it with just a jump, but it's a bit tight with a bad retry if it is relevent, so it would be it's own trick. + ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->CanJumpslash() || logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM, true), + ENTRANCE(RR_SPIRIT_TEMPLE_GS_LEDGE, logic->IsAdult && (ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP) || logic->BunnyHood())), }); areaTable[RR_SPIRIT_TEMPLE_GS_LEDGE] = Region("Spirit Temple GS Ledge", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, SpiritShared(RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA);}, false, + LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, SpiritShared(RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA);}, 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_STATUE_ROOM_CHILD, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT);})), }, { //Exits - ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)/* || CanBunnyJump()*/), + ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || logic->BunnyHood()), ENTRANCE(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, true) }); @@ -279,8 +286,6 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), - ENTRANCE(RR_SPIRIT_TEMPLE_PLATFORM, logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && - (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)))), //explicit adult check here is a precaution against possible child logic leaking, child with a hookshot can do this ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, logic->IsAdult && logic->CanUse(RG_HOOKSHOT)), ENTRANCE(RR_SPIRIT_TEMPLE_SHORTCUT, logic->Get(LOGIC_SPIRIT_STATUE_SOUTH_DOOR)), @@ -370,38 +375,41 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT] = Region("Spirit Temple Statue Room Adult", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits - ENTRANCE(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, true), - ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM, true), - ENTRANCE(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, true), + ENTRANCE(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, true), + ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM, true), + ENTRANCE(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, true), //(IsAdult && ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP)) || CanUse(RG_HOVER_BOOTS) || (CanUse(RG_ZELDAS_LULLABY) && CanUse(RG_HOOKSHOT)); - ENTRANCE(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, logic->SpiritEastToSwitch()), - ENTRANCE(RR_SPIRIT_TEMPLE_POT_STAIRS, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4)), + ENTRANCE(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, logic->SpiritEastToSwitch()), + ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, logic->CanRecoilHoverFromObject(TRECOIL_SHORT)), + ENTRANCE(RR_SPIRIT_TEMPLE_POT_STAIRS, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 4)), //RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled - ENTRANCE(RR_SPIRIT_TEMPLE_PLATFORM, logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && - (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)))), + ENTRANCE(RR_SPIRIT_TEMPLE_PLATFORM, logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && + (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)))), }); areaTable[RR_SPIRIT_TEMPLE_INNER_LEFT_HAND] = Region("Spirit Temple Inner Left Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations //Assumes RR_SPIRIT_TEMPLE_INNER_WEST_HAND access via RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD and RR_SPIRIT_TEMPLE_STATUE_ROOM. - LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, []{return logic->CanUse(RG_ZELDAS_LULLABY) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_OPEN_CHEST);})), - }, { + //If entering via the statue's head, there's a scenario where RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST can be reached without being able to go from 1 hand to the other + //This invovles using limited means to reach the left hand, playing ZL, dieing, then on respawn jumping to the other hand for the chest + //Both reloading a save and using FW reload the temp flags and despawn the chest. + //In addition to being obtuse however there is no reliable, itemless way to die in this room, as the only enemies that can be reached with no items are pots that do 1 hit, break and likely give you a heart to replace it + //because of all of this, it would be a trick + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, []{return logic->CanUse(RG_ZELDAS_LULLABY) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_OPEN_CHEST);})), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, []{return logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST) && + ((logic->IsAdult && (ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP) || logic->BunnyHood())) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));})),}, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM, true), - ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, logic->CanUse(RG_HOVER_BOOTS)/* || CanBunnyJump()*/), + ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->CanUse(RG_HOOKSHOT)), //Assumes RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT access via RR_SPIRIT_TEMPLE_STATUE_ROOM - ENTRANCE(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, (logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP)) || + ENTRANCE(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, (logic->IsAdult && (ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP) || logic->BunnyHood())) || (logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanUse(RG_HOOKSHOT))), }); areaTable[RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH] = Region("Spirit Temple Shortcut Switch", SCENE_SPIRIT_TEMPLE, { //Events EVENT_ACCESS(LOGIC_SPIRIT_STATUE_SOUTH_DOOR, SpiritShared(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return logic->CanUse(RG_MEGATON_HAMMER);})), - }, { - //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) && logic->HasItem(RG_OPEN_CHEST);})), - }, { + }, {}, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, true), ENTRANCE(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, true), @@ -430,7 +438,6 @@ 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() && 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, true), @@ -481,7 +488,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BIG_WALL_BASE] = Region("Spirit Temple Big Wall Base", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_BEAMOS_PITS, true), - ENTRANCE(RR_SPIRIT_TEMPLE_BIG_WALL_UPPER, (ctx->GetTrickOption(RT_SPIRIT_WALL) || (logic->CanAvoidEnemy(RE_BEAMOS, true, 2) && logic->CanPassEnemy(RE_WALLTULA, ED_BOOMERANG))) && + ENTRANCE(RR_SPIRIT_TEMPLE_BIG_WALL_UPPER, (ctx->GetTrickOption(RT_SPIRIT_WALL) || (logic->CanAvoidEnemy(RE_BEAMOS, ED_CLOSE, true, 2) && logic->CanPassEnemy(RE_WALLTULA, ED_BOOMERANG))) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))), }); @@ -506,7 +513,7 @@ 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_FIRE_RINGS)) || - (AnyAgeTime([]{return logic->CanHitEyeTargets() && logic->CanAvoidEnemy(RE_TORCH_SLUG, true, 4);}) + (AnyAgeTime([]{return logic->CanHitEyeTargets() && logic->CanAvoidEnemy(RE_TORCH_SLUG, ED_CLOSE, true, 4);}) && logic->CanUse(RG_HOOKSHOT))) && logic->CanOpenLargeChest()), }, { //Exits @@ -545,9 +552,10 @@ void RegionTable_Init_SpiritTemple() { ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM, true), ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, true), ENTRANCE(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, true), + //if we are here as child, it's either doorsanity or we have 5 logical keys, so we don't care about leaks ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, true), ENTRANCE(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, true), - ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_HEAD, logic->Get(LOGIC_SPIRIT_PUSHED_4F_MIRRORS) && logic->CanUse(RG_MIRROR_SHIELD) && logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_HEAD, logic->Get(LOGIC_SPIRIT_PUSHED_4F_MIRRORS) && AnyAgeTime([]{return logic->CanUse(RG_MIRROR_SHIELD);}) && logic->CanUse(RG_HOOKSHOT)), }); areaTable[RR_SPIRIT_TEMPLE_STATUE_HEAD] = Region("Spirit Temple Statue Head", SCENE_SPIRIT_TEMPLE, { @@ -561,11 +569,12 @@ void RegionTable_Init_SpiritTemple() { }, { // Exits ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_ROOM, true), - //CanBunnyJump with a jumpslash can reach either hand and with good timing the platform as child. the latter is definitely a trick, the former may not be + //Bunny hood jumps with a jumpslash can reach either hand and with good timing the platform as child. + //The latter is definitely a trick, the former may not be but I am dissalowing it because I would have to spend a week writing a new branch of spirit key logic. //If this interaction with the hands is added, SpiritSharedLogic needs updating for it - ENTRANCE(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, logic->CanUse(RG_HOVER_BOOTS)), - ENTRANCE(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, logic->CanUse(RG_HOVER_BOOTS)), - ENTRANCE(RR_SPIRIT_TEMPLE_PLATFORM, logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)/* || (IsAdult && CanBunnyJump())*/)), + ENTRANCE(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult)), + ENTRANCE(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && logic->CanJumpslash() && logic->IsAdult)), + ENTRANCE(RR_SPIRIT_TEMPLE_PLATFORM, logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->BunnyHood()))), ENTRANCE(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, true), }); @@ -601,7 +610,8 @@ void RegionTable_Init_SpiritTemple() { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_ENTRYWAY, true), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_CHILD_SIDE_HUB, (logic->IsAdult || logic->HasItem(RG_SPEAK_GERUDO) || logic->Get(LOGIC_SPIRIT_NABOORU_KIDNAPPED)) && logic->CanUse(RG_CRAWL) /*&& logic->HasSoul(RG_NABOORU_SOUL)*/), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_BEHIND_GEYSER, ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_MEGATON_HAMMER) || (logic->CanStandingShield() && (logic->CanUseSword() || logic->CanUse(RG_STICKS))))), + //You can use the boulder over the eye target to do this with just sword, but it cannot be logical as the boulder is a perm flag + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_BEHIND_GEYSER, logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD)), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_HOLE, logic->CanUse(RG_LONGSHOT) && logic->CanUse(RG_BOMBCHU_5)), }); @@ -628,7 +638,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_GIBDO_GRAVES] = Region("Spirit Temple MQ Gibdo Graves", SCENE_SPIRIT_TEMPLE, { //Events EVENT_ACCESS(LOGIC_SPIRIT_MQ_GIBDOS_CLEARED, logic->HasItem(RG_POWER_BRACELET) && - ((logic->CanUse(RG_BOMBCHU_5) && logic->CanHitEyeTargets()) || logic->CanUse(RG_HOVER_BOOTS)/* || (IsAdult && CanBunnyJump())*/) + ((logic->CanUse(RG_BOMBCHU_5) && logic->CanHitEyeTargets()) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())) && logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 3)), }, { //Location @@ -639,7 +649,7 @@ void RegionTable_Init_SpiritTemple() { ENTRANCE(RR_SPIRIT_TEMPLE_MQ_CHILD_SIDE_HUB, true), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_GIBDO_POTS, logic->HasItem(RG_POWER_BRACELET) && (logic->CanUse(RG_BOMBCHU_5) && logic->CanHitEyeTargets()) || - logic->CanUse(RG_HOVER_BOOTS)/* || (IsAdult && CanBunnyJump())*/), + logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), }); areaTable[RR_SPIRIT_TEMPLE_MQ_GIBDO_POTS] = Region("Spirit Temple MQ Gibdo Pots", SCENE_SPIRIT_TEMPLE, {}, { @@ -649,6 +659,7 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_MQ_GIBDO_BOULDER, logic->BlastOrSmash()), }, { //Exits + //climbing the grate through the celing allows you to go backwards here, but that's a clip not visible collision ENTRANCE(RR_SPIRIT_TEMPLE_MQ_TURNTABLE, logic->Get(LOGIC_SPIRIT_MQ_GIBDOS_CLEARED)), }); @@ -677,7 +688,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_ANUBIS_BRIDGE_GRAVE] = Region("Spirit Temple MQ Anubis Bridge Grave", SCENE_SPIRIT_TEMPLE, { //Events - EVENT_ACCESS(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, (logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE)) && (logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) /*|| (logic->IsAdult && CanBunnyJump())*/) || + EVENT_ACCESS(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, (logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE)) && (logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->BunnyHood())) || (logic->CanKillEnemy(RE_ANUBIS, ED_BOOMERANG) && logic->CanKillEnemy(RE_KEESE, ED_FAR))), }, { //Locations @@ -685,7 +696,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_MQ_TURNTABLE, true), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_ANUBIS_BRIDGE_CHEST, logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) /*|| (logic->IsAdult && CanBunnyJump())*/), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_ANUBIS_BRIDGE_CHEST, logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->BunnyHood())), }); areaTable[RR_SPIRIT_TEMPLE_MQ_ANUBIS_BRIDGE_CHEST] = Region("Spirit Temple MQ Anubis Bridge Chest", SCENE_SPIRIT_TEMPLE, { @@ -698,7 +709,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits //The bridge is a temp flag, so not a way to cross south to north in logic - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_ANUBIS_BRIDGE_GRAVE, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)/* || (logic->IsAdult && CanBunnyJump())*/), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_ANUBIS_BRIDGE_GRAVE, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_CHILD_SIDE_HUB, true), }); @@ -756,10 +767,10 @@ void RegionTable_Init_SpiritTemple() { (logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && AnyAgeTime([]{return logic->CanUse(RG_MEGATON_HAMMER);})))), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6)), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME)), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_INNER_RIGHT_HAND, logic->IsAdult || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)/* || CanBunnyJump()*/), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_INNER_RIGHT_HAND, logic->IsAdult || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_FLAMETHROWER_STAIRS, logic->MQSpiritStatueToSunBlock()), //explicit adult check here is a precaution against possible child logic leaking, child with a hookshot can do this - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_ADULT, logic->IsAdult && logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_ADULT, logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || logic->CanRecoilHover(RECOIL_HAMMER_AND_SHIELD))), }); areaTable[RR_SPIRIT_TEMPLE_MQ_POT_LEDGE] = Region("Spirit Temple MQ Pot Ledge", SCENE_SPIRIT_TEMPLE, { @@ -790,10 +801,7 @@ void RegionTable_Init_SpiritTemple() { //Land on the SoT block ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_CHILD, true), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, true), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP)), - // RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_PLATFORM, logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && - (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)))), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, logic->IsAdult && (ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP) || logic->BunnyHood())), }); areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM] = Region("Spirit Temple MQ Statue Room", SCENE_SPIRIT_TEMPLE, { @@ -816,6 +824,7 @@ void RegionTable_Init_SpiritTemple() { (logic->CanUse(RG_BOOMERANG) && logic->HasExplosives());})), }, { //Exits + //Adult can use bunnyhovers to reach the SoT block from the statues legs, but that's unintuitive ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_CHILD, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR, logic->Get(LOGIC_SPIRIT_STATUE_SOUTH_DOOR)), //explicit adult check here is a precaution against possible Child logic leaking, Child with a hookshot can do this @@ -833,7 +842,7 @@ void RegionTable_Init_SpiritTemple() { //Locations LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->HasItem(RG_POWER_BRACELET) && logic->HasItem(RG_OPEN_CHEST);})), //RT_SPIRIT_MQ_SUN_BLOCK_GS should probably be expanded to cover all ground based methods, as it can be hit with longshot because the skull hitbox is larger than the model - LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return (logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows())) || + LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) && (logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows())) || (ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->CanUse(RG_BOOMERANG));})), LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_1, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_2, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanBreakPots();})), @@ -896,7 +905,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_ADULT] = Region("Spirit Temple MQ Statue Room Adult", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, true), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_INNER_LEFT_HAND, logic->IsAdult || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)/* || CanBunnyJump()*/), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_CHILD, logic->CanUse(RG_HOOKSHOT) || logic->CanRecoilHover(RECOIL_HAMMER_AND_SHIELD)), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_INNER_LEFT_HAND, logic->IsAdult || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_CHEST_LEDGE, logic->CanUse(RG_HOVER_BOOTS) || ((ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_LONGSHOT))), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_3_SUNS_ROOM_2F, logic->Get(LOGIC_SPIRIT_MQ_STATUE_ROOM_TORCHES)), @@ -914,9 +924,9 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, true), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_ADULT, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_ADULT, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || logic->BunnyHood()), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_CHEST_LEDGE, ((logic->IsAdult || ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE)) && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT)) - || (logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP))), + || (logic->IsAdult && (ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP) || logic->BunnyHood()))), }); areaTable[RR_SPIRIT_TEMPLE_MQ_CHEST_LEDGE] = Region("Spirit Temple MQ Chest Ledge", SCENE_SPIRIT_TEMPLE, {}, { @@ -925,7 +935,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, true), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_ADULT, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT)/* || CanBunnyJump()*/), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_ADULT, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || logic->BunnyHood()), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_INNER_LEFT_HAND, true), }); @@ -960,7 +970,7 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_MQ_JET_LOBBY_SILVER, logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_FOYER, logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && (logic->CanUseSword() || logic->CanUse(RG_STICKS)))), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_FOYER, logic->CanUse(RG_MEGATON_HAMMER) || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD)), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_3_SUNS_ROOM_1F, true), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_SAND_PIT, true), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_UPPER, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 7)), @@ -968,7 +978,8 @@ 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))) && logic->HasItem(RG_OPEN_CHEST)), + //bunnyhovers works as adult if you run against the wall, but it's unintuitive + LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, logic->CanKillEnemy(RE_PURPLE_LEEVER) && (logic->CanUse(RG_HOOKSHOT) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits @@ -1017,11 +1028,11 @@ 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) && 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()), + LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, logic->CanAvoidEnemy(RE_BEAMOS, ED_CLOSE, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanBreakSmallCrates()), }, { //Exits - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_UPPER, logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->HasItem(RG_POWER_BRACELET)), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->HasItem(RG_POWER_BRACELET)), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_UPPER, logic->CanAvoidEnemy(RE_BEAMOS, ED_CLOSE, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->HasItem(RG_POWER_BRACELET)), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, logic->CanAvoidEnemy(RE_BEAMOS, ED_CLOSE, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->HasItem(RG_POWER_BRACELET)), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_BASE, logic->SmallKeys(SCENE_SPIRIT_TEMPLE, 6)), }); @@ -1161,7 +1172,7 @@ void RegionTable_Init_SpiritTemple() { //Assumes SpiritPlatformLowered is checked on entry areaTable[RR_SPIRIT_TEMPLE_MQ_PLATFORM] = Region("Spirit Temple MQ Platform", SCENE_SPIRIT_TEMPLE, {}, {}, { //Exits - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD, logic->Get(LOGIC_SPIRIT_PUSHED_4F_MIRRORS) && logic->CanUse(RG_MIRROR_SHIELD) && logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD, logic->Get(LOGIC_SPIRIT_PUSHED_4F_MIRRORS) && AnyAgeTime([]{return logic->CanUse(RG_MIRROR_SHIELD);}) && logic->CanUse(RG_HOOKSHOT)), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_CHILD, true), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_INNER_RIGHT_HAND, true), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, true), @@ -1180,11 +1191,12 @@ void RegionTable_Init_SpiritTemple() { }, { // Exits ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, true), - //CanBunnyJump with a jumpslash can reach either hand and with good timing the platform as child. the latter is definitely a trick, the former may not be + //Bunny hood jumps with a jumpslash can reach either hand and with good timing the platform as child. + //The latter is definitely a trick, the former may not be but I am dissalowing it because I would have to spend a week writing a new branch of spirit key logic. //If this interaction with the hands is added, SpiritSharedLogic needs updating for it ENTRANCE(RR_SPIRIT_TEMPLE_MQ_INNER_RIGHT_HAND, logic->CanUse(RG_HOVER_BOOTS)), ENTRANCE(RR_SPIRIT_TEMPLE_MQ_INNER_LEFT_HAND, logic->CanUse(RG_HOVER_BOOTS)), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_PLATFORM, logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)/* || (IsAdult && CanBunnyJump())*/)), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_PLATFORM, logic->Get(LOGIC_SPIRIT_PLATFORM_LOWERED) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->BunnyHood()))), ENTRANCE(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, true), }); @@ -1193,8 +1205,8 @@ void RegionTable_Init_SpiritTemple() { // Boss Room areaTable[RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY] = Region("Spirit Temple Boss Entryway", SCENE_SPIRIT_TEMPLE, {}, {}, { // Exits - ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_HEAD, ctx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla() && false), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD, ctx->GetDungeon(SPIRIT_TEMPLE)->IsMQ() && false), + ENTRANCE(RR_SPIRIT_TEMPLE_STATUE_HEAD, ctx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla()), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD, ctx->GetDungeon(SPIRIT_TEMPLE)->IsMQ()), ENTRANCE(RR_SPIRIT_TEMPLE_BOSS_ROOM, logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY)), }); 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 9ef5221f39..b4ffa4b26d 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp @@ -1,6 +1,7 @@ #include "soh/Enhancements/randomizer/location_access.h" #include "soh/Enhancements/randomizer/entrance.h" #include "soh/Enhancements/randomizer/dungeon.h" +#include "soh/Enhancements/randomizer/randomizerEnums.h" using namespace Rando; @@ -20,13 +21,17 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_ENTRANCE_LEDGE] = Region("Water Temple Entrance Ledge", SCENE_WATER_TEMPLE, { //Events EVENT_ACCESS(LOGIC_WATER_COULD_MIDDLE, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), + //Assumes RR_WATER_TEMPLE_JET_LIFT and RR_WATER_TEMPLE_HIGH_EMBLEM access + EVENT_ACCESS(LOGIC_WATER_COULD_HIGH_FROM_MID, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->HasItem(RG_BRONZE_SCALE) || logic->BunnyHood()) && + logic->CanHitSwitch(ED_BOMB_THROW)), }, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_ENTRYWAY, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS)), ENTRANCE(RR_WATER_TEMPLE_MAIN, true), - ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_A, (logic->WaterLevel(WL_HIGH) && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS)), - ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))), - ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_LM, logic->CanUse(RG_HOVER_BOOTS) && logic->WaterLevel(WL_LOW_OR_MID)), + //child can just barely make it with bunny hood if the water is not high and they are perfectly straight, but this probably isn't unintuitive due to unreliability + ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_A, (logic->WaterLevel(WL_HIGH) && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), + ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood()))), + ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_LM, (logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood()) )&& logic->WaterLevel(WL_LOW_OR_MID)), ENTRANCE(RR_WATER_TEMPLE_2F_CENTRAL_LM, logic->WaterLevel(WL_LOW_OR_MID)), }); @@ -41,28 +46,28 @@ void RegionTable_Init_WaterTemple() { EVENT_ACCESS(LOGIC_WATER_COULD_MIDDLE, (logic->CanUse(RG_LONGSHOT) && (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW))) || (logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(SCENE_WATER_TEMPLE, 5))), //Assumes RR_WATER_TEMPLE_JET_LIFT and RR_WATER_TEMPLE_HIGH_EMBLEM access - EVENT_ACCESS(LOGIC_WATER_COULD_HIGH_FROM_MID, (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->HasItem(RG_BRONZE_SCALE)) && - logic->CanHitSwitch(ED_BOMB_THROW)), + EVENT_ACCESS(LOGIC_WATER_COULD_HIGH_FROM_MID, logic->HasItem(RG_BRONZE_SCALE) && logic->CanHitSwitch(ED_BOMB_THROW)), }, {}, { //Exits - ENTRANCE(RR_WATER_TEMPLE_ENTRANCE_LEDGE, logic->HasItem(RG_BRONZE_SCALE) && logic->WaterLevel(WL_HIGH)), - ENTRANCE(RR_WATER_TEMPLE_SIDE_TOWER_1F, (logic->WaterTimer() >= 24 && logic->CanUse(RG_IRON_BOOTS)) || - (logic->WaterLevel(WL_MID) && logic->HasItem(RG_GOLDEN_SCALE) && logic->WaterTimer() >= 16) || - logic->WaterLevel(WL_LOW) || - (logic->CanUse(RG_LONGSHOT) && ctx->GetTrickOption(RT_WATER_LONGSHOT_TORCH) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 8)), - ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_A, logic->WaterLevel(WL_HIGH) && logic->HasItem(RG_BRONZE_SCALE)), - ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && logic->HasItem(RG_BRONZE_SCALE)), - ENTRANCE(RR_WATER_TEMPLE_2F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && logic->CanUse(RG_IRON_BOOTS) && ((logic->WaterTimer() >= 8 && logic->HasItem(RG_BRONZE_SCALE)) || (logic->WaterTimer() >= 40 && logic->CanUse(RG_LONGSHOT)))), - ENTRANCE(RR_WATER_TEMPLE_2F_CENTRAL_LM, logic->WaterLevel(WL_LOW_OR_MID) && ((logic->WaterLevel(WL_MID) && logic->HasItem(RG_BRONZE_SCALE)) || - ((logic->WaterLevel(WL_LOW) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40)) && logic->CanUse(RG_LONGSHOT)))), - ENTRANCE(RR_WATER_TEMPLE_PILLAR_1F, logic->WaterLevel(WL_LOW) && logic->SmallKeys(SCENE_WATER_TEMPLE, 5)), - ENTRANCE(RR_WATER_TEMPLE_SPIKE_MOAT, ((logic->WaterLevel(WL_LOW) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE))))), - ENTRANCE(RR_WATER_TEMPLE_BLOCK_U_BEND, logic->Get(LOGIC_WATER_PUSHED_1F_BLOCK) && - ((logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 16) || - (logic->WaterLevel(WL_LOW) && logic->HasItem(RG_SILVER_SCALE)))), - ENTRANCE(RR_WATER_TEMPLE_NEAR_CAGE, AnyAgeTime([]{return logic->WaterLevel(WL_LOW) && logic->HasExplosives();}) && - (logic->WaterLevel(WL_LOW) && logic->HasItem(RG_SILVER_SCALE) || - (logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 16))), + ENTRANCE(RR_WATER_TEMPLE_ENTRANCE_LEDGE, logic->HasItem(RG_BRONZE_SCALE) && logic->WaterLevel(WL_HIGH)), + ENTRANCE(RR_WATER_TEMPLE_SIDE_TOWER_1F, (logic->WaterTimer() >= 24 && logic->CanUse(RG_IRON_BOOTS)) || + (logic->WaterLevel(WL_MID) && logic->HasItem(RG_GOLDEN_SCALE) && logic->WaterTimer() >= 16) || + logic->WaterLevel(WL_LOW) || + (logic->CanUse(RG_LONGSHOT) && ctx->GetTrickOption(RT_WATER_LONGSHOT_TORCH) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 8)), + ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_A, logic->WaterLevel(WL_HIGH) && logic->HasItem(RG_BRONZE_SCALE)), + ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && logic->HasItem(RG_BRONZE_SCALE)), + ENTRANCE(RR_WATER_TEMPLE_2F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && logic->CanUse(RG_IRON_BOOTS) && ((logic->WaterTimer() >= 8 && logic->HasItem(RG_BRONZE_SCALE)) || (logic->WaterTimer() >= 40 && logic->CanUse(RG_LONGSHOT)))), + ENTRANCE(RR_WATER_TEMPLE_2F_CENTRAL_LM, logic->WaterLevel(WL_LOW_OR_MID) && ((logic->WaterLevel(WL_MID) && logic->HasItem(RG_BRONZE_SCALE)) || + ((logic->WaterLevel(WL_LOW) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40)) && logic->CanUse(RG_LONGSHOT)))), + ENTRANCE(RR_WATER_TEMPLE_PILLAR_1F, logic->WaterLevel(WL_LOW) && logic->SmallKeys(SCENE_WATER_TEMPLE, 5)), + ENTRANCE(RR_WATER_TEMPLE_SPIKE_MOAT, ((logic->WaterLevel(WL_LOW) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE))))), + ENTRANCE(RR_WATER_TEMPLE_BLOCK_U_BEND, logic->Get(LOGIC_WATER_PUSHED_1F_BLOCK) && + ((logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 16) || + (logic->WaterLevel(WL_LOW) && logic->HasItem(RG_SILVER_SCALE)))), + ENTRANCE(RR_WATER_TEMPLE_NEAR_CAGE, AnyAgeTime([]{return logic->WaterLevel(WL_LOW) && logic->HasExplosives();}) && + (logic->WaterLevel(WL_LOW) && logic->HasItem(RG_SILVER_SCALE) || + (logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 16))), + ENTRANCE(RR_WATER_TEMPLE_RISING_TARGET_LEDGE, logic->WaterLevel(WL_HIGH) && ctx->GetTrickOption(RT_WATER_IRON_BOOTS_LEDGE_GRAB) && logic->IsAdult && logic->HasItem(RG_BRONZE_SCALE) && logic->CanUse(RG_IRON_BOOTS)), }); areaTable[RR_WATER_TEMPLE_3F_CENTRAL_A] = Region("Water Temple 3F Central Any Water", SCENE_WATER_TEMPLE, {}, { @@ -72,7 +77,7 @@ void RegionTable_Init_WaterTemple() { }, { //Exits ENTRANCE(RR_WATER_TEMPLE_MAIN, true), - ENTRANCE(RR_WATER_TEMPLE_ENTRANCE_LEDGE, logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_WATER_TEMPLE_ENTRANCE_LEDGE, logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), ENTRANCE(RR_WATER_TEMPLE_HIGH_EMBLEM, logic->Water3FCentralToHighEmblem()), ENTRANCE(RR_WATER_TEMPLE_JET_CHEST_ROOM, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16), ENTRANCE(RR_WATER_TEMPLE_RISING_TARGET_LEDGE, ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()))), @@ -123,7 +128,7 @@ void RegionTable_Init_WaterTemple() { //Implies CanAvoid(RE_STINGERS) ENTRANCE(RR_WATER_TEMPLE_JET_CHEST_ROOM, logic->CanUse(RG_HOOKSHOT)), ENTRANCE(RR_WATER_TEMPLE_OUTSIDE_JET_LIFT_2F, logic->WaterLevel(WL_MID) && - (logic->IsAdult && logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->HasItem(RG_BRONZE_SCALE))), + (logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->HasItem(RG_BRONZE_SCALE) || logic->BunnyHood())), //Child can jumpslash with the lit stick to light the torch ENTRANCE(RR_WATER_TEMPLE_PILLAR_2F, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), //assumes RR_WATER_TEMPLE_3F_CENTRAL_LM and RR_WATER_TEMPLE_HIGH_EMBLEM access @@ -133,7 +138,7 @@ void RegionTable_Init_WaterTemple() { logic->Water3FCentralToHighEmblem()), //hookshot + jumpslash can make it up through the platform slit as adult, is easier with WL_MID but still possible on WL_LOW, but it's a trick ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_LM, logic->CanUse(RG_LONGSHOT)), - ENTRANCE(RR_WATER_TEMPLE_BLOCK_LOOP, logic->CanHitEyeTargets() && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_WATER_TEMPLE_BLOCK_LOOP, logic->CanHitEyeTargets() && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood()))), }); areaTable[RR_WATER_TEMPLE_SIDE_TOWER_1F] = Region("Water Temple Side Tower 1F", SCENE_WATER_TEMPLE, { @@ -217,7 +222,7 @@ void RegionTable_Init_WaterTemple() { //Exits ENTRANCE(RR_WATER_TEMPLE_BEHIND_SPIKE_MOAT, logic->SmallKeys(SCENE_WATER_TEMPLE, 4)), ENTRANCE(RR_WATER_TEMPLE_BOULDERS_NORTH, logic->HasItem(RG_BRONZE_SCALE) || (ctx->GetTrickOption(RT_WATER_INVISIBLE_HOOKSHOT_TARGET) && logic->CanUse(logic->IsAdult ? RG_HOOKSHOT : RG_LONGSHOT) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), - ENTRANCE(RR_WATER_TEMPLE_BOULDER_CANAL, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP))) || + ENTRANCE(RR_WATER_TEMPLE_BOULDER_CANAL, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || ctx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP))) || // A midair ground jump gets child onto the ledge, but they can't reasonably do anything without irons, and this may need TakeDamage due to the boulders // swim can be skipped by boots changing during the ledge climb (logic->CanMiddairGroundJump() && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), @@ -225,7 +230,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BOULDERS_NORTH] = Region("Water Temple Boulders North", SCENE_WATER_TEMPLE, {}, {}, { //Exits - ENTRANCE(RR_WATER_TEMPLE_BOULDERS_SOUTH, logic->HasItem(RG_BRONZE_SCALE)), + ENTRANCE(RR_WATER_TEMPLE_BOULDERS_SOUTH, logic->HasItem(RG_BRONZE_SCALE) || (ctx->GetTrickOption(RT_WATER_INVISIBLE_HOOKSHOT_TARGET) && logic->CanUse(logic->IsAdult ? RG_HOOKSHOT : RG_LONGSHOT) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), ENTRANCE(RR_WATER_TEMPLE_BLOCK_ROOM_TARGET, true), }); @@ -247,9 +252,9 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BLOCK_ROOM] = Region("Water Temple Block Room", SCENE_WATER_TEMPLE, { //Events //Implies CanAvoid(RE_STINGER) - //the full logic for the puzzle, as it is cut down here for optimisation + //the full logic for the puzzle, as it is cut down here for optimisation because of how the water rising starts requiring scale //EVENT_ACCESS(LOGIC_WATER_PUSHED_B1_BLOCK, logic->HasItem(RG_GORONS_BRACELET) && logic->HasExplosives() && - // (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS))), + // (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logiic->BunnyHood()))), }, { //Locations //we can always get the pots by shooting them from afar and diving for the item... LOCATION(RC_WATER_TEMPLE_BASEMENT_BLOCK_PUZZLE_POT_1, (logic->CanBreakPots(ED_LONGSHOT, true, true) && logic->HasItem(RG_BRONZE_SCALE)) || @@ -278,31 +283,42 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_3_JETS_NO_SWITCH] = Region("Water Temple 3 Jets Room No Switch", SCENE_WATER_TEMPLE, {}, {}, { //Exits - ENTRANCE(RR_WATER_TEMPLE_3_JETS_SWITCH, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanStandingShield())), + ENTRANCE(RR_WATER_TEMPLE_3_JETS_SWITCH, logic->CanUse(RG_HOOKSHOT) || logic->CanRecoilHover(RECOIL_HAMMER_AND_SHIELD)), ENTRANCE(RR_WATER_TEMPLE_CANAL_ALCOVE, true), }); areaTable[RR_WATER_TEMPLE_CANAL_ALCOVE] = Region("Water Temple Canal Alcove", SCENE_WATER_TEMPLE, {}, { //Locations + //Can we grab the token at range? LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || + //Otherwise we need to be able to reach it... //child can also do a hovers backwalk backflip to reach the token after killing the skull - (((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanMiddairGroundJump()) && + (((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || logic->BunnyHovers() || logic->CanMiddairGroundJump()) && + //survive the landing, or don't care if we void + (logic->HasItem(RG_BRONZE_SCALE) || (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanVoid())) && + //and of course kill the skulltula to spawn the token + //Adult can kill with a bomb from the canal, and climb back up, handled here for simplicity //killing with bombchu from here is hard due to the terrain, but adult can do it much easier from the river so it's only relevant for child - logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->HasItem(RG_BRONZE_SCALE) && logic->IsAdult ? ED_SHORT_JUMPSLASH : ED_BOOMERANG))), + (logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->HasItem(RG_BRONZE_SCALE) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()) ? ED_SHORT_JUMPSLASH : logic->IsAdult ? ED_BOMB_THROW : ED_BOOMERANG)))), }, { //Exits ENTRANCE(RR_WATER_TEMPLE_3_JETS_NO_SWITCH, true), - ENTRANCE(RR_WATER_TEMPLE_BOULDER_CANAL, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), + //It's possible to longshot directly to BOULDERS_SOUTH as a Child using the invisible target, but it's very precise + ENTRANCE(RR_WATER_TEMPLE_BOULDER_CANAL, (logic->IsAdult && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())) || + logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), ENTRANCE(RR_WATER_TEMPLE_BEHIND_CANAL, logic->IsAdult && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->HasItem(RG_BRONZE_SCALE)), }); areaTable[RR_WATER_TEMPLE_BOULDER_CANAL] = Region("Water Temple Boulder Canal", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, (logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)) || (((logic->IsAdult && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)) || (logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOOMERANG))) && (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanVoid()) && logic->CanUse(RG_HOVER_BOOTS))), + LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, (logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)) || + (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))), }, { //Exits //making the jump as adult without jumpslash is possible, but hard enough to be a trick - ENTRANCE(RR_WATER_TEMPLE_BOULDERS_SOUTH, logic->HasItem(RG_BRONZE_SCALE) || (logic->IsAdult && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)))), + ENTRANCE(RR_WATER_TEMPLE_BOULDERS_SOUTH, logic->HasItem(RG_BRONZE_SCALE) || + (ctx->GetTrickOption(RT_WATER_INVISIBLE_HOOKSHOT_TARGET) && logic->CanUse((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) ? RG_HOOKSHOT : RG_LONGSHOT)) || + (logic->IsAdult && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)))), ENTRANCE(RR_WATER_TEMPLE_BOULDERS_NORTH, logic->HasItem(RG_BRONZE_SCALE) || (ctx->GetTrickOption(RT_WATER_INVISIBLE_HOOKSHOT_TARGET) && logic->CanUse(logic->IsAdult ? RG_HOOKSHOT : RG_LONGSHOT) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), ENTRANCE(RR_WATER_TEMPLE_CANAL_ALCOVE, logic->IsAdult), ENTRANCE(RR_WATER_TEMPLE_BEHIND_CANAL, logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 8), @@ -334,7 +350,7 @@ void RegionTable_Init_WaterTemple() { //Exits ENTRANCE(RR_WATER_TEMPLE_MAIN, logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 16), ENTRANCE(RR_WATER_TEMPLE_NEAR_CAGE, logic->CanUse(RG_HOOKSHOT) || - ((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanMiddairGroundJump())), + (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())) || logic->CanMiddairGroundJump()), }); areaTable[RR_WATER_TEMPLE_NEAR_CAGE] = Region("Water Temple Near Cage", SCENE_WATER_TEMPLE, {}, {}, { @@ -362,12 +378,12 @@ void RegionTable_Init_WaterTemple() { //Exits ENTRANCE(RR_WATER_TEMPLE_MAIN, logic->Get(LOGIC_WATER_PUSHED_1F_BLOCK) && ((logic->CanUse(RG_IRON_BOOTS) && ((logic->CanUse(RG_HOOKSHOT) && logic->WaterLevel(WL_LOW)) || logic->HasItem(RG_BRONZE_SCALE))) || (logic->WaterLevel(WL_HIGH_OR_MID) && logic->CanUse(RG_SILVER_SCALE))) && logic->WaterTimer() >= 8), - ENTRANCE(RR_WATER_TEMPLE_OUTSIDE_DRAGON_ROOM, logic->CanHitSwitch()), + ENTRANCE(RR_WATER_TEMPLE_OUTSIDE_DRAGON_ROOM, logic->CanHitSwitch() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), }); areaTable[RR_WATER_TEMPLE_OUTSIDE_DRAGON_ROOM] = Region("Water Temple Outside Dragon Room", SCENE_WATER_TEMPLE, {}, {}, { //Exits - ENTRANCE(RR_WATER_TEMPLE_BLOCK_U_BEND, logic->CanHitSwitch(ED_BOOMERANG) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_WATER_TEMPLE_BLOCK_U_BEND, logic->CanHitSwitch(ED_BOOMERANG) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->BunnyHood())), ENTRANCE(RR_WATER_TEMPLE_DRAGON_ROOM, true), }); @@ -439,7 +455,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_OUTSIDE_JET_LIFT_2F] = Region("Water Temple Outside Jet Lift 2F", SCENE_WATER_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_MAIN, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS)), - ENTRANCE(RR_WATER_TEMPLE_2F_CENTRAL_LM, logic->WaterLevel(WL_MID) && (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_WATER_TEMPLE_2F_CENTRAL_LM, logic->WaterLevel(WL_MID) && (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())), ENTRANCE(RR_WATER_TEMPLE_JET_LIFT_2F, logic->WaterLevel(WL_MID)), }); @@ -490,7 +506,7 @@ void RegionTable_Init_WaterTemple() { }, { //Exits ENTRANCE(RR_WATER_TEMPLE_MAIN, true), - ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_A, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_A, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), }); //This region is not able to finish pushing the block out of the way to reach the chest @@ -498,7 +514,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BLOCK_LOOP_3F_H] = Region("Water Temple Block Loop 3F High Water", SCENE_WATER_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_BLOCK_LOOP_3F_A, true), - ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_H, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_H, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), }); //This region is not able to finish pushing the block out of the way to reach the chest @@ -506,7 +522,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BLOCK_LOOP_3F_LM] = Region("Water Temple Block Loop 3F Low or Mid Water", SCENE_WATER_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_BLOCK_LOOP_3F_A, true), - ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_LM, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_LM, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), ENTRANCE(RR_WATER_TEMPLE_2F_CENTRAL_LM, true), }); @@ -515,7 +531,7 @@ void RegionTable_Init_WaterTemple() { ENTRANCE(RR_WATER_TEMPLE_MAIN, true), ENTRANCE(RR_WATER_TEMPLE_OUTSIDE_JET_LIFT_2F, logic->WaterLevel(WL_MID)), ENTRANCE(RR_WATER_TEMPLE_WATERFALL, logic->WaterLevel(WL_HIGH) && logic->SmallKeys(SCENE_WATER_TEMPLE, 4)), - ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE))), + ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE) || logic->BunnyHood())), ENTRANCE(RR_WATER_TEMPLE_2F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)), }); @@ -539,7 +555,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_TOGGLE_SWITCH] = Region("Water Temple Toggle Switch", SCENE_WATER_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_WATERFALL_TOP, logic->SmallKeys(SCENE_WATER_TEMPLE, 5)), - //you can reach the spikes with hovers + CanHitSwitch(ED_BOMB_THROW) but can't cross them + //you can reach the spikes with (hovers or (adult and bunny)) + CanHitSwitch(ED_BOMB_THROW) but can't cross them ENTRANCE(RR_WATER_TEMPLE_LIKE_LIKE_SPIKES, logic->CanUse(RG_HOOKSHOT)), }); @@ -552,7 +568,7 @@ void RegionTable_Init_WaterTemple() { //swim can be skipped here as adult if you have hookshot and a melee weapon, as you can use the side of the snouts of the pillars to just barely reach the next platform, //and get a glitchy ledge grab by jumping from it while it is raised for the final one, which can be escaped with a jumpslash. //this is a trick separate from glitch ledge grabs however as the snouts are very wonky collision to climb on. - ENTRANCE(RR_WATER_TEMPLE_TOGGLE_SWITCH, (logic->HasItem(RG_BRONZE_SCALE) && logic->CanHitSwitch(ED_BOMB_THROW)) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_WATER_TEMPLE_TOGGLE_SWITCH, (logic->HasItem(RG_BRONZE_SCALE) && logic->CanHitSwitch(ED_BOMB_THROW)) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), ENTRANCE(RR_WATER_TEMPLE_DARK_LINK_ROOM, true), }); @@ -573,30 +589,46 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_RIVER] = Region("Water Temple River", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_GS_RIVER, (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->WaterTimer() >= 16)), - LOCATION(RC_WATER_TEMPLE_RIVER_HEART_1, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->HasItem(RG_BRONZE_SCALE)), - LOCATION(RC_WATER_TEMPLE_RIVER_HEART_2, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->HasItem(RG_BRONZE_SCALE)), - LOCATION(RC_WATER_TEMPLE_RIVER_HEART_3, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->HasItem(RG_BRONZE_SCALE)), - LOCATION(RC_WATER_TEMPLE_RIVER_HEART_4, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->HasItem(RG_BRONZE_SCALE)), + //You can use backflips to surface and reset the timer without taking off irons. + //this is simple as Adult, but Child has a corner they can do this roo + LOCATION(RC_WATER_TEMPLE_GS_RIVER, (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->WaterTimer() >= 8)), + LOCATION(RC_WATER_TEMPLE_RIVER_HEART_1, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->HasItem(RG_BRONZE_SCALE)), + LOCATION(RC_WATER_TEMPLE_RIVER_HEART_2, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->HasItem(RG_BRONZE_SCALE)), + LOCATION(RC_WATER_TEMPLE_RIVER_HEART_3, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->HasItem(RG_BRONZE_SCALE)), + LOCATION(RC_WATER_TEMPLE_RIVER_HEART_4, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->HasItem(RG_BRONZE_SCALE)), }, { //Exits //it is possible with persistence for adult to make it past the final whirlpool with only irons and climb to the pots, //but the collision around there is very janky and loves making you slide back down. //combined with the drowning time pressure this is a trick. //For best results walk to the right of the seam pointing to the pots, then move left to try and cross it at the very top. - ENTRANCE(RR_WATER_TEMPLE_RIVER_POTS, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 32 && logic->CanUse(RG_LONGSHOT)) || logic->HasItem(RG_BRONZE_SCALE)), + //Bunny hood makes this trivial, even for child, though they need hookshot to get out of the water. + ENTRANCE(RR_WATER_TEMPLE_RIVER_PLATFORM, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && ((logic->CanUse(logic->BunnyHood() ? RG_HOOKSHOT: RG_LONGSHOT)) || (logic->IsAdult && logic->BunnyHood()))) || logic->HasItem(RG_BRONZE_SCALE)), + }); + + areaTable[RR_WATER_TEMPLE_RIVER_PLATFORM] = Region("Water Temple River Platform", SCENE_WATER_TEMPLE, {}, { + //Locations + LOCATION(RC_WATER_TEMPLE_GS_RIVER, ctx->GetTrickOption(RT_WATER_RIVER_GS) && logic->IsAdult && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_FAR) && logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_WATER_TEMPLE_RIVER_POT_1, logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_WATER_TEMPLE_RIVER_POT_2, logic->CanUse(RG_BOOMERANG)), + }, { + //Exits + //Child can enter the water without jumping to have just enough time to make it with just swim, but it's a trick + ENTRANCE(RR_WATER_TEMPLE_ABOVE_DRAGON, logic->CanHitEyeTargets() && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || logic->BunnyHood())), + //This ledge is bad: Child can make this with bunnyhovers, but it's inconsistent and has a bad retry time, adult can't and needs a jumpslash + //regardless, this is annoying enough to be a trick. + ENTRANCE(RR_WATER_TEMPLE_RIVER_POTS, logic->HasItem(RG_BRONZE_SCALE) || (logic->IsAdult && (logic->CanUse(RG_IRON_BOOTS) || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD)))), + ENTRANCE(RR_WATER_TEMPLE_RIVER, logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE)), }); areaTable[RR_WATER_TEMPLE_RIVER_POTS] = Region("Water Temple River Pots", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_GS_RIVER, ctx->GetTrickOption(RT_WATER_RIVER_GS) && logic->CanUse(RG_LONGSHOT)), LOCATION(RC_WATER_TEMPLE_RIVER_POT_1, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_RIVER_POT_2, logic->CanBreakPots()), }, { //Exits - //Child can enter the water without jumping to have just enough time to make it with just swim, but it's a trick - ENTRANCE(RR_WATER_TEMPLE_ABOVE_DRAGON, logic->CanHitEyeTargets() && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))), - ENTRANCE(RR_WATER_TEMPLE_RIVER, logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE)), + ENTRANCE(RR_WATER_TEMPLE_RIVER_PLATFORM, logic->HasItem(RG_BRONZE_SCALE) || (logic->IsAdult && (logic->CanUse(RG_IRON_BOOTS) || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD) || logic->BunnyHovers()))), + ENTRANCE(RR_WATER_TEMPLE_RIVER, logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE)), }); areaTable[RR_WATER_TEMPLE_ABOVE_DRAGON] = Region("Water Temple Above Dragon", SCENE_WATER_TEMPLE, {}, { @@ -607,13 +639,18 @@ void RegionTable_Init_WaterTemple() { ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE))), }, { //Exits - ENTRANCE(RR_WATER_TEMPLE_DRAGON_ROOM, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanJumpslash())), + ENTRANCE(RR_WATER_TEMPLE_DRAGON_ROOM, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOVER_BOOTS) && (logic->CanJumpslash() || logic->BunnyHood()))), }); areaTable[RR_WATER_TEMPLE_RISING_TARGET_LEDGE] = Region("Water Temple Rising Target Ledge", SCENE_WATER_TEMPLE, { //Events - EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CanBreakPots()), - EVENT_ACCESS(LOGIC_WATER_COULD_MIDDLE, logic->WaterRisingTargetTo3FCentral() && (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW))), + EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CanBreakPots()), + EVENT_ACCESS(LOGIC_WATER_COULD_MIDDLE, (logic->WaterRisingTargetTo3FCentral() || logic->BunnyHovers() || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD) || logic->CanUse(RG_LONGSHOT)) && + (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW))), + //Assumes RR_WATER_TEMPLE_JET_LIFT and RR_WATER_TEMPLE_HIGH_EMBLEM access + EVENT_ACCESS(LOGIC_WATER_COULD_HIGH_FROM_MID, (logic->BunnyHovers() || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD) || logic->CanUse(RG_LONGSHOT)) && + logic->CanHitSwitch(ED_BOMB_THROW)), + EVENT_ACCESS(LOGIC_WATER_COULD_LOW, logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE)), }, { // Locations LOCATION(RC_WATER_TEMPLE_MAIN_LEVEL_1_POT_1, logic->CanBreakPots()), @@ -627,6 +664,7 @@ void RegionTable_Init_WaterTemple() { ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_A, logic->WaterRisingTargetTo3FCentral()), ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_H, logic->WaterRisingTargetTo3FCentral() && logic->WaterLevel(WL_HIGH)), ENTRANCE(RR_WATER_TEMPLE_3F_CENTRAL_LM, logic->WaterRisingTargetTo3FCentral() && logic->WaterLevel(WL_LOW_OR_MID)), + ENTRANCE(RR_WATER_TEMPLE_2F_CENTRAL_LM, (logic->BunnyHovers() || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD)) && logic->WaterLevel(WL_LOW_OR_MID)), //Assumes RR_WATER_TEMPLE_3F_CENTRAL, RR_WATER_TEMPLE_HIGH_EMBLEM and RR_WATER_TEMPLE_2F_CENTRAL access ENTRANCE(RR_WATER_TEMPLE_PILLAR_H, logic->WaterLevel(WL_LOW_OR_MID) && ctx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && logic->CanUse(RG_FIRE_ARROWS) && logic->WaterRisingTargetTo3FCentral()), ENTRANCE(RR_WATER_TEMPLE_TRAPPED_SLOPE, true), @@ -652,9 +690,9 @@ void RegionTable_Init_WaterTemple() { ENTRANCE(RR_WATER_TEMPLE_ENTRYWAY, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS)), ENTRANCE(RR_WATER_TEMPLE_MQ_MAIN, true), //If we are not on WL_HIGH, we reach RR_WATER_TEMPLE_MQ_3F_MAIN with hookshot via 2F, otherwise we can reach the platform - ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_A, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)), - ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_H, (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)) && logic->WaterLevel(WL_HIGH)), - ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_LM, (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)) && logic->WaterLevel(WL_LOW_OR_MID)), + ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_A, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), + ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_H, (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())) && logic->WaterLevel(WL_HIGH)), + ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_LM, (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())) && logic->WaterLevel(WL_LOW_OR_MID)), ENTRANCE(RR_WATER_TEMPLE_MQ_2F_CENTRAL_LM, logic->WaterLevel(WL_LOW_OR_MID)), }); @@ -664,7 +702,9 @@ void RegionTable_Init_WaterTemple() { //remember that any solution that works for any level doesn't need to be given a level, even if that solution is overkill for a lower level areaTable[RR_WATER_TEMPLE_MQ_MAIN] = Region("Water Temple MQ Main", SCENE_WATER_TEMPLE, { //Events - EVENT_ACCESS(LOGIC_WATER_COULD_MIDDLE, logic->CanUse(RG_HOOKSHOT)), + EVENT_ACCESS(LOGIC_WATER_COULD_MIDDLE, logic->CanUse(RG_HOOKSHOT)), + //we can't fully extend from the above letting you leave the pillar at MID in case the player saveloads at mid, but we rely on it to let the player go from LOW to HIGH if they can solve at MID. + EVENT_ACCESS(LOGIC_WATER_HIGH, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE)), }, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_ENTRANCE_LEDGE, logic->HasItem(RG_BRONZE_SCALE) && logic->WaterLevel(WL_HIGH)), @@ -689,19 +729,20 @@ void RegionTable_Init_WaterTemple() { ENTRANCE(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM, logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && ((logic->WaterLevel(WL_LOW) && logic->HasItem(RG_SILVER_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT))))), //Adult needs to jump in instead of dive for swim access, but you just hold forward. RT_WATER_BK_REGION Isn't relevant unless the Dark Link loop can be done without longshot with other tricks ENTRANCE(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_ROOM, logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && ((logic->WaterLevel(WL_LOW) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE))) && (logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_WATER_BK_REGION) && logic->CanUse(RG_HOVER_BOOTS)))), + ENTRANCE(RR_WATER_TEMPLE_MQ_RISING_TARGET_LEDGE, logic->WaterLevel(WL_HIGH) && ctx->GetTrickOption(RT_WATER_IRON_BOOTS_LEDGE_GRAB) && logic->IsAdult && logic->HasItem(RG_BRONZE_SCALE) && logic->CanUse(RG_IRON_BOOTS)), }); //This region specifically covers the topmost platform around central pillar areaTable[RR_WATER_TEMPLE_MQ_3F_CENTRAL_A] = Region("Water Temple MQ 3F Central Any Water", SCENE_WATER_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_MAIN, true), - ENTRANCE(RR_WATER_TEMPLE_MQ_ENTRANCE_LEDGE, logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_WATER_TEMPLE_MQ_ENTRANCE_LEDGE, logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), ENTRANCE(RR_WATER_TEMPLE_MQ_2F_CENTRAL_A, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanUse(RG_HOOKSHOT)), ENTRANCE(RR_WATER_TEMPLE_MQ_RISING_TARGET_LEDGE, ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()))), //this swimless jump with irons may be a trick as you have to put irons on quite late. ENTRANCE(RR_WATER_TEMPLE_MQ_LIZALFOS_LOOP_A, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16), //Jumping across is possible but a trick due to the janky ledge - ENTRANCE(RR_WATER_TEMPLE_MQ_HIGH_EMBLEM, logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_WATER_TEMPLE_MQ_HIGH_EMBLEM, logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || (logic->BunnyHood() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), }); //This region specifically covers the topmost platform around central pillar @@ -709,8 +750,8 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_3F_CENTRAL_H] = Region("Water Temple MQ 3F Central High Water", SCENE_WATER_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_2F_CENTRAL_H, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanUse(RG_HOOKSHOT)), - ENTRANCE(RR_WATER_TEMPLE_MQ_RISING_TARGET_LEDGE, logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_WATER_IRON_BOOTS_LEDGE_GRAB) && logic->IsAdult && logic->HasItem(RG_BRONZE_SCALE) && logic->CanUse(RG_IRON_BOOTS))), - ENTRANCE(RR_WATER_TEMPLE_MQ_OUTSIDE_WATERFALL, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_WATER_TEMPLE_MQ_RISING_TARGET_LEDGE, logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_WATER_TEMPLE_MQ_OUTSIDE_WATERFALL, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || logic->BunnyHood()), }); //This region specifically covers the topmost platform around central pillar @@ -726,21 +767,22 @@ void RegionTable_Init_WaterTemple() { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_MAIN, true), ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_A, logic->CanUse(RG_HOOKSHOT)), - ENTRANCE(RR_WATER_TEMPLE_MQ_STORAGE_ROOM, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_WATER_IRON_BOOTS_LEDGE_GRAB) && logic->HasItem(RG_BRONZE_SCALE))), + ENTRANCE(RR_WATER_TEMPLE_MQ_STORAGE_ROOM, logic->CanUse(RG_HOOKSHOT)), }); areaTable[RR_WATER_TEMPLE_MQ_2F_CENTRAL_H] = Region("Water Temple MQ 2F Central High Water", SCENE_WATER_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_2F_CENTRAL_A, true), ENTRANCE(RR_WATER_TEMPLE_MQ_PILLAR_H, true), + ENTRANCE(RR_WATER_TEMPLE_MQ_STORAGE_ROOM, (ctx->GetTrickOption(RT_WATER_IRON_BOOTS_LEDGE_GRAB) && logic->HasItem(RG_BRONZE_SCALE))), }); areaTable[RR_WATER_TEMPLE_MQ_2F_CENTRAL_LM] = Region("Water Temple MQ 2F Central Low or Mid Water", SCENE_WATER_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_2F_CENTRAL_A, true), ENTRANCE(RR_WATER_TEMPLE_MQ_PILLAR_2F, true), - ENTRANCE(RR_WATER_TEMPLE_MQ_HIDDEN_SWITCH_2F, (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_POWER_BRACELET)), - ENTRANCE(RR_WATER_TEMPLE_MQ_LIZALFOS_LOOP_LM, logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_WATER_TEMPLE_MQ_HIDDEN_SWITCH_2F, (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_POWER_BRACELET)), + ENTRANCE(RR_WATER_TEMPLE_MQ_LIZALFOS_LOOP_LM, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), }); areaTable[RR_WATER_TEMPLE_MQ_HIGH_EMBLEM] = Region("Water Temple MQ High Emblem", SCENE_WATER_TEMPLE, { @@ -753,7 +795,12 @@ void RegionTable_Init_WaterTemple() { ENTRANCE(RR_WATER_TEMPLE_MQ_MAIN, true), }); - areaTable[RR_WATER_TEMPLE_MQ_RISING_TARGET_LEDGE] = Region("Water Temple MQ Rising Target Ledge", SCENE_WATER_TEMPLE, {}, {}, { + areaTable[RR_WATER_TEMPLE_MQ_RISING_TARGET_LEDGE] = Region("Water Temple MQ Rising Target Ledge", SCENE_WATER_TEMPLE, { + //Events + EVENT_ACCESS(LOGIC_WATER_COULD_MIDDLE, logic->BunnyHovers() || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD) || logic->WaterRisingTargetTo3FCentral()), + //if we can lower the water, we can re-raise it with just this + EVENT_ACCESS(LOGIC_WATER_HIGH, (logic->BunnyHovers() || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD)) && logic->CanUse(RG_HOOKSHOT)), + }, {}, { //Exits //As you cannot change the water level from here, we must be able to make the drop on any water level //Bronze scale does this alone thanks to the nearby pond cancelling fall damage @@ -762,6 +809,7 @@ void RegionTable_Init_WaterTemple() { ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_A, logic->WaterRisingTargetTo3FCentral()), ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_H, logic->WaterRisingTargetTo3FCentral() && logic->WaterLevel(WL_HIGH)), ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_LM, logic->WaterRisingTargetTo3FCentral() && logic->WaterLevel(WL_LOW_OR_MID)), + ENTRANCE(RR_WATER_TEMPLE_MQ_2F_CENTRAL_LM, (logic->BunnyHovers() || logic->CanRecoilHover(RECOIL_SWORD_AND_SHIELD)) && logic->WaterLevel(WL_LOW_OR_MID)), ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_DOOR_RAMP, true), }); @@ -944,7 +992,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_OUTSIDE_HIDDEN_SWITCH_2F] = Region("Water Temple MQ Outside Hidden Switch 2F", SCENE_WATER_TEMPLE, {}, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_MAIN, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS)), - ENTRANCE(RR_WATER_TEMPLE_MQ_2F_CENTRAL_LM, logic->WaterLevel(WL_MID) && (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_WATER_TEMPLE_MQ_2F_CENTRAL_LM, logic->WaterLevel(WL_MID) && (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())), ENTRANCE(RR_WATER_TEMPLE_MQ_HIDDEN_SWITCH_2F, logic->WaterLevel(WL_MID)), }); @@ -1038,7 +1086,7 @@ void RegionTable_Init_WaterTemple() { ENTRANCE(RR_WATER_TEMPLE_MQ_MAIN, true), ENTRANCE(RR_WATER_TEMPLE_MQ_OUTSIDE_HIDDEN_SWITCH_2F, logic->WaterLevel(WL_MID)), ENTRANCE(RR_WATER_TEMPLE_MQ_WATERFALL, logic->WaterLevel(WL_HIGH) && logic->SmallKeys(SCENE_WATER_TEMPLE, 1)), - ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE))), + ENTRANCE(RR_WATER_TEMPLE_MQ_3F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE) || logic->BunnyHood())), ENTRANCE(RR_WATER_TEMPLE_MQ_2F_CENTRAL_H, logic->WaterLevel(WL_HIGH) && logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)), }); @@ -1066,6 +1114,7 @@ void RegionTable_Init_WaterTemple() { LOCATION(RC_WATER_TEMPLE_MQ_WONDER_HOOKSHOT_STAIRCASE_LEFT_3, logic->CanUse(RG_HOOKSHOT)), }, { //Exits + //you can also make it with hover boots and good timing, using the momentom of the slope, but it's a trick ENTRANCE(RR_WATER_TEMPLE_MQ_WATERFALL, logic->CanUse(RG_LONGSHOT) && logic->CanHitSwitch(ED_FAR)), ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT, true), }); @@ -1074,7 +1123,7 @@ void RegionTable_Init_WaterTemple() { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_WATERFALL_TOP, logic->Get(LOGIC_WATER_MQ_STALFOS_PIT)), ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT_LOWER, true), - ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS, (logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS, (logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && (logic->IsAdult || logic->BunnyHood()) && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && logic->CanUse(RG_LONGSHOT)), }); @@ -1084,6 +1133,8 @@ void RegionTable_Init_WaterTemple() { }, {}, { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT, logic->CanUse(RG_HOOKSHOT) && (logic->IsAdult || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8))), + //Child can use the second method (going via the wall target near the half raised target) with bunny hood, but while the first jump is just wall assisted, the second is inconsistent + //It is also possible for them to jump around the statue with bunny, or even climb up sometimes. This needs more investigation before catagorisation as they also seem inconsistent without a setup ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT_POTS, (logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || (logic->CanUse(RG_HOOKSHOT) && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) && (logic->CanUse(RG_HOVER_BOOTS) || logic->Get(LOGIC_WATER_MQ_STALFOS_PIT)))), ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && (logic->IsAdult || logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) && logic->CanUse(RG_HOOKSHOT)), }); @@ -1101,7 +1152,8 @@ void RegionTable_Init_WaterTemple() { LOCATION(RC_WATER_TEMPLE_MQ_DARK_LINK_PILAR_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits - ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT)), + //possible as child with bunny, but inconsistent + ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && logic->BunnyHood())), ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT_LOWER, true), ENTRANCE(RR_WATER_TEMPLE_MQ_STALFOS_PIT_UPPER, logic->Get(LOGIC_WATER_MQ_STALFOS_PIT) && logic->CanUse(RG_HOOKSHOT)), }); @@ -1140,12 +1192,14 @@ void RegionTable_Init_WaterTemple() { ENTRANCE(RR_WATER_TEMPLE_MQ_RIVER_SKULL, logic->CanUse(RG_HOOKSHOT) && (logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->CanUse(RG_LONGSHOT))), }); - //if we can use hookshot, we are standing on the targets, otherwise assume we're in the water + //if we can use hookshot, we are standing on the targets, otherwise assume we're in the water and need to pull up onto the target areaTable[RR_WATER_TEMPLE_MQ_RIVER_SKULL] = Region("Water Temple MQ River Skull", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_GS_RIVER, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))), + LOCATION(RC_WATER_TEMPLE_MQ_GS_RIVER, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT)) || + (logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG))), }, { //Exits + //if entering with irons, hookshot + bunnyhovers also solves, but it's unintuitive ENTRANCE(RR_WATER_TEMPLE_MQ_RIVER_POTS, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT)), }); @@ -1158,11 +1212,27 @@ void RegionTable_Init_WaterTemple() { LOCATION(RC_WATER_TEMPLE_MQ_RIVER_POT_2, logic->CanBreakPots()), }, { //Exits - ENTRANCE(RR_WATER_TEMPLE_MQ_RIVER_SKULL, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && logic->CanUse(RG_HOOKSHOT))), - //You don't need to swim for this if you put irons on in midair and hold forward while aiming for the tunnel with a tight angle, but if you miss you have to void unless you have a hook. It's only relevant with glitches anyway - ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16), + ENTRANCE(RR_WATER_TEMPLE_MQ_RIVER_SKULL, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && (logic->CanUse(RG_HOOKSHOT) || logic->BunnyHovers()))), + ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_BOTTOM, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), + //You don't need to swim for this if you put irons on in midair and hold forward while aiming for the tunnel with a tight angle, but if you miss you have to void unless you have a hook. + //Including in jump dive as it's too long a retry for unintuitive + ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE)), ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE, logic->HasItem(RG_SILVER_SCALE) || (logic->IsAdult && logic->HasItem(RG_BRONZE_SCALE) && ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE))), - ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanJumpslash())), + ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOVER_BOOTS) && (logic->CanJumpslash() || logic->BunnyHood()))), + }); + + //This region assumes Iron boots to access + areaTable[RR_WATER_TEMPLE_MQ_DRAGON_ROOM_BOTTOM] = Region("Water Temple MQ Dragon Room Bottom", SCENE_WATER_TEMPLE, {}, + { + //Locations + LOCATION(RC_WATER_TEMPLE_MQ_WONDER_DRAGON_ROOM_LEFT_EYE, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_WATER_TEMPLE_MQ_WONDER_DRAGON_ROOM_RIGHT_EYE, logic->CanUse(RG_HOOKSHOT)), + }, { + //Exits + ENTRANCE(RR_WATER_TEMPLE_MQ_RIVER_POTS, logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL, logic->CanUse(RG_HOOKSHOT) && logic->WaterTimer() >= 16), + ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE, logic->HasItem(RG_BRONZE_SCALE)), }); //This region assumes Iron boots to access @@ -1173,11 +1243,10 @@ void RegionTable_Init_WaterTemple() { LOCATION(RC_WATER_TEMPLE_MQ_DRAGON_ROOM_SUBMERGED_CRATE_2, logic->CanBreakCrates()), LOCATION(RC_WATER_TEMPLE_MQ_DRAGON_ROOM_SUBMERGED_CRATE_3, logic->CanBreakCrates()), LOCATION(RC_WATER_TEMPLE_MQ_DRAGON_ROOM_SUBMERGED_CRATE_4, logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WONDER_DRAGON_ROOM_LEFT_EYE, logic->CanUse(RG_HOOKSHOT)), - LOCATION(RC_WATER_TEMPLE_MQ_WONDER_DRAGON_ROOM_RIGHT_EYE, logic->CanUse(RG_HOOKSHOT)), }, { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_RIVER_POTS, logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_BOTTOM, logic->WaterTimer() >= 16), ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT)), ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT)), }); @@ -1196,25 +1265,28 @@ void RegionTable_Init_WaterTemple() { }, { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16), - ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, logic->HasItem(RG_SILVER_SCALE)), + ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, logic->HasItem(RG_SILVER_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE))), }); areaTable[RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR] = Region("Water Temple MQ Dragon Room Door", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR_CRATE_1, logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR_CRATE_2, logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WONDER_DRAGON_ROOM_LEFT_EYE, logic->CanUse(RG_HOOKSHOT) && logic->WaterTimer() >= 8), - LOCATION(RC_WATER_TEMPLE_MQ_WONDER_DRAGON_ROOM_RIGHT_EYE, logic->CanUse(RG_HOOKSHOT) && logic->WaterTimer() >= 8), + LOCATION(RC_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR_CRATE_1, logic->CanBreakCrates()), + LOCATION(RC_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR_CRATE_2, logic->CanBreakCrates()), + //The wonder items in the eyes can be triggered from here with RT_WATER_ADULT_DRAGON, but even gold scale does not reach the bottom, so an additional dive trick is needed to skip irons }, { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_RIVER_POTS, logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_BOTTOM, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanUse(RG_HOOKSHOT)), - ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE, logic->HasItem(RG_SILVER_SCALE)), + ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE, logic->HasItem(RG_SILVER_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE))), ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, logic->Get(LOGIC_WATER_MQ_DRAGON_TORCHES)), }); - areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH] = Region("Water Temple MQ Boss Key Room Switch", SCENE_WATER_TEMPLE, {}, { + areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH] = Region("Water Temple MQ Boss Key Room Switch", SCENE_WATER_TEMPLE, { + //Events + EVENT_ACCESS(LOGIC_WATER_MQ_BOSS_KEY_CHEST_TORCHES, (logic->CanHitSwitch() || logic->HasItem(RG_POWER_BRACELET)) && logic->CanUse(RG_DINS_FIRE)), + }, { //Locations LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_POT, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_MQ_BK_ROOM_UPPER_CRATE, logic->CanBreakCrates()), @@ -1222,7 +1294,7 @@ void RegionTable_Init_WaterTemple() { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, true), ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_PIT, true), - ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, logic->CanHitSwitch() && AnyAgeTime([]{return logic->CanUse(RG_DINS_FIRE);}) && logic->HasItem(RG_OPEN_CHEST)), + ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, logic->Get(LOGIC_WATER_MQ_BOSS_KEY_CHEST_TORCHES) && (logic->CanHitSwitch() || logic->CanUse(RG_HOVER_BOOTS) || logic->HasItem(RG_POWER_BRACELET) || (logic->IsAdult && logic->BunnyHood()))), }); //this exists for the crates in preparation for clips through the grate @@ -1238,12 +1310,15 @@ void RegionTable_Init_WaterTemple() { ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, logic->CanHitSwitch(ED_BOOMERANG)), }); - areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST] = Region("Water Temple MQ Boss Key Room Chest", SCENE_WATER_TEMPLE, {}, { + areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST] = Region("Water Temple MQ Boss Key Room Chest", SCENE_WATER_TEMPLE, { + //Events + EVENT_ACCESS(LOGIC_WATER_MQ_BOSS_KEY_CHEST_TORCHES, logic->HasFireSource()), + }, { //Locations LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanOpenLargeChest()), }, { //Exits - ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, logic->CanHitSwitch(ED_BOMB_THROW) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, logic->Get(LOGIC_WATER_MQ_BOSS_KEY_CHEST_TORCHES) && (logic->CanHitSwitch(ED_BOMB_THROW) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood()))), ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_PIT, true), ENTRANCE(RR_WATER_TEMPLE_MQ_B1_GATE_SWITCH, logic->HasItem(RG_SILVER_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && (logic->HasItem(RG_BRONZE_SCALE) || (logic->WaterTimer() >= 24 && logic->CanUse(RG_LONGSHOT))))), }); @@ -1287,7 +1362,7 @@ void RegionTable_Init_WaterTemple() { //Exits ENTRANCE(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM, true), ENTRANCE(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_CAGE, logic->CanUse(RG_FIRE_ARROWS) && - ((logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanMiddairGroundJump() || + ((logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())) || logic->CanMiddairGroundJump() || (logic->CanUse(RG_LONGSHOT) && AnyAgeTime([]{return logic->ScarecrowsSong();})))) }); @@ -1323,27 +1398,61 @@ void RegionTable_Init_WaterTemple() { //Locations LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_FRONT_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_FRONT_CRATE_2, logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_1, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_2, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_3, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_4, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_5, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_6, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_1, logic->CanUse(RG_BOMBCHU_5) && + ((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->IsAdult && logic->BunnyHood()))), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_2, logic->CanUse(RG_BOMBCHU_5) && + ((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && (logic->IsAdult || logic->CanUse(RG_HOOKSHOT))) || logic->HasItem(RG_BRONZE_SCALE))), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_3, logic->CanUse(RG_BOMBCHU_5) && + ((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && (logic->IsAdult || logic->CanUse(RG_HOOKSHOT))) || logic->HasItem(RG_BRONZE_SCALE))), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_4, logic->CanUse(RG_BOMBCHU_5) && + ((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && (logic->IsAdult || logic->CanUse(RG_HOOKSHOT))) || logic->HasItem(RG_BRONZE_SCALE))), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_5, logic->CanUse(RG_BOMBCHU_5) && + ((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->IsAdult && logic->BunnyHood()))), + //This can spawn in or outside of rang range depending on random spread, should be a trick + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_6, logic->CanUse(RG_BOMBCHU_5) && + ((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->HasItem(RG_BRONZE_SCALE))), }, { //Exits - ENTRANCE(RR_WATER_TEMPLE_MQ_BEHIND_SPIKE_MOAT, true), - //Child can use the crate to get the height to make it with hovers, but it's annoyingly tight so would be a trick - ENTRANCE(RR_WATER_TEMPLE_MQ_SCARECROW_CANAL, ((logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP))) || - (AnyAgeTime([]{return logic->ScarecrowsSong();}) && logic->CanUse(RG_HOOKSHOT))) && - (logic->IsAdult || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8))), - ENTRANCE(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_CAGE, ctx->GetTrickOption(RT_WATER_INVISIBLE_HOOKSHOT_TARGET) && logic->CanUse(logic->IsAdult ? RG_HOOKSHOT : RG_LONGSHOT) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), + ENTRANCE(RR_WATER_TEMPLE_MQ_BEHIND_SPIKE_MOAT, true), + //Child can use the crate to get the height to make it with hovers, but it's annoyingly tight so would be a trick unless bunny. + ENTRANCE(RR_WATER_TEMPLE_MQ_SCARECROW_CANAL, (logic->BunnyHovers() || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || ctx->GetTrickOption(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP))) || + (AnyAgeTime([]{return logic->ScarecrowsSong();}) && logic->CanUse(RG_HOOKSHOT))) && + (logic->IsAdult || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8))), + ENTRANCE(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_BED_S, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), + }); + + //Assumes Iron Boots are checked on entry + areaTable[RR_WATER_TEMPLE_MQ_CRATE_VORTEX_BED_S] = Region("Water Temple MQ Crate Vortex Bed South", SCENE_WATER_TEMPLE, {}, + { + //Locations + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_1, true/*logic->CanUse(RG_ROLL)*/), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_5, true/*logic->CanUse(RG_ROLL)*/), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_6, true/*logic->CanUse(RG_ROLL)*/), + }, { + //Exits + ENTRANCE(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_ROOM, logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE)), + //Child can use the crate to get the height to make it with hovers, but it's annoyingly tight so would be a trick unless bunny. + ENTRANCE(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_BED_N, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE)), + }); + + //Assumes Iron Boots are checked on entry + areaTable[RR_WATER_TEMPLE_MQ_CRATE_VORTEX_BED_N] = Region("Water Temple MQ Crate Vortex Bed North", SCENE_WATER_TEMPLE, {}, + { + //Locations + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_2, true/*logic->CanUse(RG_ROLL)*/), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_3, true/*logic->CanUse(RG_ROLL)*/), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_4, true/*logic->CanUse(RG_ROLL)*/), + }, { + //Exits + ENTRANCE(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_BED_S, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE)), + ENTRANCE(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_CAGE, ctx->GetTrickOption(RT_WATER_INVISIBLE_HOOKSHOT_TARGET) && logic->CanUse(RG_HOOKSHOT)), }); areaTable[RR_WATER_TEMPLE_MQ_SCARECROW_CANAL] = Region("Water Temple MQ Scarecrow Canal", SCENE_WATER_TEMPLE, {}, {}, { //Exits //making the jump as adult without jumpslash is possible, but hard enough to be a trick ENTRANCE(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_ROOM, logic->HasItem(RG_BRONZE_SCALE) || - (logic->IsAdult && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS))) || + (logic->IsAdult && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8 && logic->CanUse(RG_HOOKSHOT))), ENTRANCE(RR_WATER_TEMPLE_MQ_CANAL_ALCOVE, logic->IsAdult), ENTRANCE(RR_WATER_TEMPLE_MQ_BEHIND_CANAL, logic->CanUse(RG_IRON_BOOTS) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT)) && logic->WaterTimer() >= 8), @@ -1351,6 +1460,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_CANAL_ALCOVE] = Region("Water Temple MQ Canal Alcove", SCENE_WATER_TEMPLE, {}, {}, { //Exits + //It's possible to longshot directly to RR_WATER_TEMPLE_MQ_CRATE_VORTEX_ROOM as a Child using the invisible target, but it's very precise ENTRANCE(RR_WATER_TEMPLE_MQ_3_JETS_ROOM_SWITCH_SIDE, logic->SmallKeys(SCENE_WATER_TEMPLE, 2)), ENTRANCE(RR_WATER_TEMPLE_MQ_SCARECROW_CANAL, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), ENTRANCE(RR_WATER_TEMPLE_MQ_BEHIND_CANAL, logic->IsAdult && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->HasItem(RG_BRONZE_SCALE)), @@ -1387,15 +1497,16 @@ void RegionTable_Init_WaterTemple() { ENTRANCE(RR_WATER_TEMPLE_MQ_CANAL_ALCOVE, logic->SmallKeys(SCENE_WATER_TEMPLE, 2)), ENTRANCE(RR_WATER_TEMPLE_MQ_3_JETS_ROOM_NO_SWITCH_SIDE, logic->CanHitSwitch()), // No Switch Side requires CanHitSwitch(ED_BOOMERANG) to get to this entrance. This is covered by No Switch -> Switch entrance. - ENTRANCE(RR_WATER_TEMPLE_MQ_DODONGO_ROOM, logic->CanHitSwitch(ED_BOOMERANG) && logic->HasFireSource()), + //Fire arrows works but is unintuitive as the hitboxes are not on the torch but in the wall, so is probably a trick. + ENTRANCE(RR_WATER_TEMPLE_MQ_DODONGO_ROOM, logic->CanHitSwitch(ED_BOOMERANG) && logic->CanUse(RG_DINS_FIRE)), }); areaTable[RR_WATER_TEMPLE_MQ_3_JETS_ROOM_NO_SWITCH_SIDE] = Region("Water Temple MQ 3 Jets Room No Switch Side", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_WONDER_WATER_SPROUTS_2, logic->IsAdult), + LOCATION(RC_WATER_TEMPLE_MQ_WONDER_WATER_SPROUTS_2, logic->IsAdult || logic->BunnyHood()), }, { //Exits - ENTRANCE(RR_WATER_TEMPLE_MQ_3_JETS_ROOM_SWITCH_SIDE, logic->CanHitSwitch(ED_BOOMERANG) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanHammerRecoilHover())), + ENTRANCE(RR_WATER_TEMPLE_MQ_3_JETS_ROOM_SWITCH_SIDE, logic->CanHitSwitch(ED_BOOMERANG) || logic->CanRecoilHover(RECOIL_HAMMER)), }); areaTable[RR_WATER_TEMPLE_MQ_DODONGO_ROOM] = Region("Water Temple MQ Dodongo Room", SCENE_WATER_TEMPLE, {}, { @@ -1409,7 +1520,8 @@ void RegionTable_Init_WaterTemple() { LOCATION(RC_WATER_TEMPLE_MQ_DODONGO_ROOM_LOWER_CRATE_3, logic->CanBreakCrates()), }, { //Exits - ENTRANCE(RR_WATER_TEMPLE_MQ_3_JETS_ROOM_NO_SWITCH_SIDE, (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)) && AnyAgeTime([]{return logic->CanKillEnemy(RE_DODONGO, ED_CLOSE, true, 5);})), + ENTRANCE(RR_WATER_TEMPLE_MQ_3_JETS_ROOM_NO_SWITCH_SIDE, (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->IsAdult)) && AnyAgeTime([]{return logic->CanKillEnemy(RE_DODONGO, ED_CLOSE, true, 5);})), + //it's possible to do this jump as Adult with bunny hood, but it's a tight jump ENTRANCE(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_CAGE, (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)) && AnyAgeTime([]{return logic->CanKillEnemy(RE_DODONGO, ED_CLOSE, true, 5);})), }); @@ -1431,8 +1543,8 @@ void RegionTable_Init_WaterTemple() { // Boss Room areaTable[RR_WATER_TEMPLE_BOSS_ENTRYWAY] = Region("Water Temple Boss Entryway", SCENE_WATER_TEMPLE, {}, {}, { // Exits - ENTRANCE(RR_WATER_TEMPLE_TRAPPED_SLOPE, ctx->GetDungeon(WATER_TEMPLE)->IsVanilla() && false), - ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_DOOR, ctx->GetDungeon(WATER_TEMPLE)->IsMQ() && false), + ENTRANCE(RR_WATER_TEMPLE_TRAPPED_SLOPE, ctx->GetDungeon(WATER_TEMPLE)->IsVanilla()), + ENTRANCE(RR_WATER_TEMPLE_MQ_BOSS_DOOR, ctx->GetDungeon(WATER_TEMPLE)->IsMQ()), ENTRANCE(RR_WATER_TEMPLE_BOSS_ROOM, logic->HasItem(RG_WATER_TEMPLE_BOSS_KEY)), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp index 17f13a47b3..009a50ca35 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp @@ -120,7 +120,7 @@ void RegionTable_Init_CastleGrounds() { //Exits ENTRANCE(RR_HC_GATE, true), ENTRANCE(RR_HC_STORMS_GROTTO, logic->CanOpenStormsGrotto()), - ENTRANCE(RR_HC_DRAIN_LEDGE, (logic->Get(LOGIC_TALON_RETURNED_FROM_CASTLE) && logic->HasItem(RG_POWER_BRACELET)) || + ENTRANCE(RR_HC_DRAIN_LEDGE, (logic->Get(LOGIC_TALON_RETURNED_FROM_CASTLE) && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->TakeDamage() && logic->HasExplosives() && logic->CanJumpslash())), }); 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 b9588df7f1..105cd9c336 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 @@ -368,7 +368,7 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_DMC_ROCK_BY_FIRE_TEMPLE_3, logic->IsAdult), LOCATION(RC_DMC_ROCK_BY_FIRE_TEMPLE_4, logic->IsAdult), LOCATION(RC_DMC_ROCK_BY_FIRE_TEMPLE_5, logic->IsAdult), - // RANDOTODO: A number of tricks to reach this: sidehop jumpslash or hookshot + jumpslash from bridge platform, chu+shield damage boost + // RANDOTODO: A number of tricks to reach this: sidehop jumpslash or hookshot + jumpslash from bridge platform, chu+shield damage boost. Also does hover need roll/bunny LOCATION(RC_DMC_WONDER_BENEATH_BRIDGE_PLATFORM, logic->IsAdult && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_HOVER_BOOTS))), }, {}); 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 160990cc6e..974091e815 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 @@ -11,20 +11,21 @@ void RegionTable_Init_DeathMountainTrail() { EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_DEATH_MOUNTAIN_TRAIL_BEAN) && 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))) && logic->HasItem(RG_OPEN_CHEST)), - LOCATION(RC_DMT_FREESTANDING_POH, logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BeanPlanted(LOGIC_PLANT_DEATH_MOUNTAIN_TRAIL_BEAN) && (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() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, logic->IsAdult && logic->CanGetNightTimeGS() && - ((logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_ITEM_EXTENSION) && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_DMT_JS_LOWER_GS) && logic->CanJumpslash())) || - ((ctx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && logic->BeanPlanted(LOGIC_PLANT_DEATH_MOUNTAIN_TRAIL_BEAN)) || (ctx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && logic->CanUse(RG_HOVER_BOOTS)) && - (logic->HasExplosives() || logic->CanUse(RG_DINS_FIRE) || ((ctx->GetTrickOption(RT_BOULDER_COLLISION) || ctx->GetTrickOption(RT_ITEM_EXTENSION)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))) || logic->CanJumpslash())))), - LOCATION(RC_DMT_BLUE_RUPEE, logic->IsChild && logic->BlastOrSmash()), - LOCATION(RC_DMT_RED_RUPEE, logic->IsChild && logic->BlastOrSmash()), - LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_DEATH_MOUNTAIN_TRAIL_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), - LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_DEATH_MOUNTAIN_TRAIL_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), - LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_DEATH_MOUNTAIN_TRAIL_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), - LOCATION(RC_DMT_FLAG_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), + LOCATION(RC_DMT_CHEST, (logic->BlastOrSmash() || (logic->IsChild && (ctx->GetTrickOption(RT_DMT_BOMBABLE) || logic->BunnyHood()) && logic->HasItem(RG_GORONS_BRACELET))) && logic->HasItem(RG_OPEN_CHEST)), + //adult and bunny jumps off the nearby ledge and over the fence + LOCATION(RC_DMT_FREESTANDING_POH, logic->IsAdult || logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), + 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() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, logic->IsAdult && logic->CanGetNightTimeGS() && + ((logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_ITEM_EXTENSION) && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_DMT_JS_LOWER_GS) && logic->CanJumpslash())) || + ((ctx->GetTrickOption(RT_DMT_BEAN_LOWER_GS) && logic->BeanPlanted(LOGIC_PLANT_DEATH_MOUNTAIN_TRAIL_BEAN)) || (ctx->GetTrickOption(RT_DMT_HOVERS_LOWER_GS) && logic->CanUse(RG_HOVER_BOOTS)) && + (logic->HasExplosives() || logic->CanUse(RG_DINS_FIRE) || ((ctx->GetTrickOption(RT_BOULDER_COLLISION) || ctx->GetTrickOption(RT_ITEM_EXTENSION)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))) || logic->CanJumpslash())))), + LOCATION(RC_DMT_BLUE_RUPEE, logic->IsChild && logic->BlastOrSmash()), + LOCATION(RC_DMT_RED_RUPEE, logic->IsChild && logic->BlastOrSmash()), + LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_DEATH_MOUNTAIN_TRAIL_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_DEATH_MOUNTAIN_TRAIL_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_DEATH_MOUNTAIN_TRAIL_BEAN) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_DMT_FLAG_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), LOCATION(RC_DMT_ROCK_1, logic->CanBreakRocks()), LOCATION(RC_DMT_ROCK_2, logic->CanBreakRocks()), LOCATION(RC_DMT_ROCK_3, logic->CanBreakRocks()), @@ -79,6 +80,7 @@ void RegionTable_Init_DeathMountainTrail() { }, { //Exits ENTRANCE(RR_DEATH_MOUNTAIN_TRAIL, true), + //bunny keeps you ahead of the aimed boulders, but random boulders ahead become unavoidable because the aimed boulders catch you if you change course ENTRANCE(RR_DEATH_MOUNTAIN_SUMMIT, logic->HasItem(RG_CLIMB) && (logic->IsAdult || ctx->GetTrickOption(RT_DMT_SHIELDLESS_CLIMB) || logic->HasItem(RG_HYLIAN_SHIELD) || logic->CanUse(RG_NAYRUS_LOVE))), ENTRANCE(RR_DMT_COW_GROTTO, AnyAgeTime([]{return logic->BlastOrSmash();})), 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 bddb3617ae..39a561e394 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp @@ -20,8 +20,8 @@ void RegionTable_Init_GerudoFortress() { ENTRANCE(RR_GF_OUTSIDE_GATE, logic->Get(LOGIC_GF_GATE_OPEN)), ENTRANCE(RR_GF_NEAR_GROTTO, logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)), ENTRANCE(RR_GF_OUTSIDE_GTG, logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)), - //You can talk to the guards to get yourself thrown in jail, so long as you have a hookshot to actually end up there ENTRANCE(RR_GF_TOWER, (logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD)) && logic->CanClimbHighLadder()), + //You can talk to the guards to get yourself thrown in jail, so long as you have a hookshot to actually end up there ENTRANCE(RR_GF_JAIL_WINDOW, logic->CanUse(RG_HOOKSHOT)), }); @@ -108,6 +108,7 @@ void RegionTable_Init_GerudoFortress() { ENTRANCE(RR_GF_BOTTOM_OF_LOWER_VINES, true), // need to explicitly convert it into a bool ENTRANCE(RR_GF_BOTTOM_OF_UPPER_VINES, logic->IsAdult && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS).Get()), + ENTRANCE(RR_GF_BELOW_GS, logic->BunnyHovers()), }); areaTable[RR_GF_NEAR_GS] = Region("GF Near GS", SCENE_GERUDOS_FORTRESS, {}, { @@ -119,7 +120,7 @@ void RegionTable_Init_GerudoFortress() { ENTRANCE(RR_GF_BOTTOM_OF_LOWER_VINES, true), ENTRANCE(RR_GF_TOP_OF_LOWER_VINES, true), ENTRANCE(RR_GF_SLOPED_ROOF, logic->IsAdult || logic->CanGroundJump()), - ENTRANCE(RR_GF_LONG_ROOF, logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_GF_LONG_ROOF, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->BunnyHood())), ENTRANCE(RR_GF_NEAR_CHEST, logic->CanUse(RG_LONGSHOT)), ENTRANCE(RR_GF_BELOW_GS, true), }); @@ -136,7 +137,7 @@ void RegionTable_Init_GerudoFortress() { //Exits ENTRANCE(RR_GF_OUTSIDE_GTG, true), ENTRANCE(RR_GF_TOP_OF_LOWER_VINES, true), - ENTRANCE(RR_GF_SLOPED_ROOF, logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), + ENTRANCE(RR_GF_SLOPED_ROOF, logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)/* && roll*/))), ENTRANCE(RR_GF_TOP_OF_UPPER_VINES, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), ENTRANCE(RR_GF_TO_GTG, logic->IsAdult && ctx->GetTrickOption(RT_GF_LEDGE_CLIP_INTO_GTG).Get()), }); @@ -150,7 +151,7 @@ void RegionTable_Init_GerudoFortress() { ENTRANCE(RR_GF_TOP_OF_LOWER_VINES, true), ENTRANCE(RR_GF_SLOPED_ROOF, true), ENTRANCE(RR_GF_BOTTOM_OF_UPPER_VINES, true), - ENTRANCE(RR_GF_NEAR_CHEST, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->ReachScarecrow()) || logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_GF_NEAR_CHEST, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && (logic->ReachScarecrow() || logic->BunnyHood())) || logic->CanUse(RG_LONGSHOT)), }); areaTable[RR_GF_NEAR_CHEST] = Region("GF Near Chest", SCENE_GERUDOS_FORTRESS, {}, { @@ -166,7 +167,7 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_LONG_ROOF] = Region("GF Long Roof", SCENE_GERUDOS_FORTRESS, {}, {}, { //Exits ENTRANCE(RR_GF_BOTTOM_OF_LOWER_VINES, true), - ENTRANCE(RR_GF_NEAR_GS, (logic->IsAdult && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_GF_NEAR_GS, (logic->IsAdult && (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->BunnyHood())) || logic->CanUse(RG_HOVER_BOOTS)), ENTRANCE(RR_GF_BELOW_GS, true), ENTRANCE(RR_GF_NEAR_CHEST, logic->CanUse(RG_LONGSHOT)), ENTRANCE(RR_GF_BELOW_CHEST, true), @@ -206,9 +207,7 @@ void RegionTable_Init_GerudoFortress() { }, { //Exits //there's a trick to reach RR_GF_LONG_ROOF - //For some reason, you take fall damage if you backflip onto the fortress but not onto the sand - //It's unintuitive to avoid being caught on landing, but that sends you to the same place anyway... - ENTRANCE(RR_GF_OUTSKIRTS, ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->TakeDamage()), + ENTRANCE(RR_GF_OUTSKIRTS, true), ENTRANCE(RR_GF_NEAR_CHEST, logic->CanUse(RG_LONGSHOT)), ENTRANCE(RR_GF_BELOW_CHEST, logic->TakeDamage()), ENTRANCE(RR_GF_JAIL_WINDOW, logic->CanUse(RG_HOOKSHOT)), @@ -219,7 +218,7 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_JAIL_WINDOW] = Region("GF Jail Window", SCENE_GERUDOS_FORTRESS, {}, {}, { //Exits - ENTRANCE(RR_GF_LONG_ROOF, ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER)), // can also get it with hovers backwalk into backflip + ENTRANCE(RR_GF_LONG_ROOF, logic->CanRecoilHover(RECOIL_HAMMER)), // can also get it with hovers backwalk into backflip ENTRANCE(RR_GF_OUTSKIRTS, true), ENTRANCE(RR_GF_BELOW_CHEST, true), ENTRANCE(RR_GF_ABOVE_JAIL, ctx->GetTrickOption(RT_HOOKSHOT_CLIP) && logic->CanUse(RG_HOOKSHOT)), 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 e051ef839b..924ba841bc 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -11,7 +11,6 @@ void RegionTable_Init_GerudoValley() { }, { //Locations LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), - LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_GV_ROCK_1, logic->CanBreakRocks()), LOCATION(RC_GV_ROCK_2, logic->CanBreakRocks()), LOCATION(RC_GV_ROCK_3, logic->CanBreakRocks()), @@ -34,7 +33,8 @@ void RegionTable_Init_GerudoValley() { ENTRANCE(RR_GV_UPPER_STREAM_WATER, true), ENTRANCE(RR_GV_CRATE_LEDGE, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_LONGSHOT)), ENTRANCE(RR_GV_GROTTO_LEDGE, true), - ENTRANCE(RR_GV_FORTRESS_SIDE, (logic->IsAdult && (logic->SummonEpona() || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS))) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOVER_BOOTS)) || + //Bunnyhovers needs to aim for the sides of the bridge + ENTRANCE(RR_GV_FORTRESS_SIDE, (logic->IsAdult && (logic->SummonEpona() || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS))) || logic->CanRecoilHover(RECOIL_HAMMER) || (logic->BunnyHovers() && logic->HasItem(RG_CLIMB)) || ((logic->IsChild || ctx->GetTrickOption(RT_GV_HOOKSHOT_BRIDGE)) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsChild && ctx->GetTrickOption(RT_GV_CHILD_CUCCO_JUMP) && logic->HasItem(RG_POWER_BRACELET) && logic->CanJumpslash())), ENTRANCE(RR_GV_WATERFALL_ALCOVE, logic->IsChild && logic->HasItem(RG_POWER_BRACELET)), ENTRANCE(RR_GV_LOWER_STREAM, logic->IsChild && logic->HasItem(RG_POWER_BRACELET)), @@ -91,10 +91,11 @@ void RegionTable_Init_GerudoValley() { LOCATION(RC_GV_SILVER_BOULDER, logic->CanUse(RG_SILVER_GAUNTLETS)), }, { //Exits - ENTRANCE(RR_GV_UPPER_STREAM, ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives() && logic->TakeDamage()), + ENTRANCE(RR_GV_UPPER_STREAM, ((ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || + (logic->BunnyHovers() && logic->CanJumpslash()) || logic->CanRecoilHover(RECOIL_HAMMER)) && logic->TakeDamage()), ENTRANCE(RR_GV_LOWER_STREAM, logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS)), ENTRANCE(RR_GV_OCTOROK_GROTTO, logic->CanUse(RG_SILVER_GAUNTLETS)), - ENTRANCE(RR_GV_CRATE_LEDGE, logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_GV_CRATE_LEDGE, logic->CanUse(RG_LONGSHOT) || logic->CanRecoilHoverFromObject(TRECOIL_SHORT)), }); areaTable[RR_GV_CRATE_LEDGE] = Region("GV Crate Ledge", SCENE_GERUDO_VALLEY, {}, { @@ -133,7 +134,7 @@ void RegionTable_Init_GerudoValley() { ENTRANCE(RR_GF_OUTSKIRTS, true), ENTRANCE(RR_GV_UPPER_STREAM, logic->TakeDamage()), ENTRANCE(RR_GV_UPPER_STREAM_WATER, true), - ENTRANCE(RR_GERUDO_VALLEY, logic->IsChild || logic->SummonEpona() || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_GERUDO_VALLEY, logic->IsChild || logic->SummonEpona() || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS) || logic->CanRecoilHover(RECOIL_HAMMER) || (logic->BunnyHovers() && logic->CanUse(RG_CLIMB))), ENTRANCE(RR_GV_CARPENTER_TENT, logic->IsAdult || ctx->GetTrickOption(RT_GV_CHILD_TENT)), ENTRANCE(RR_GV_STORMS_GROTTO, logic->IsAdult && logic->CanOpenStormsGrotto()), ENTRANCE(RR_GV_CRATE_LEDGE, (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GV_CRATE_HOVERS) && logic->TakeDamage() && logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)))), 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 f6f1ff69f9..5832d6b4c8 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp @@ -11,9 +11,11 @@ void RegionTable_Init_GoronCity() { EVENT_ACCESS(LOGIC_STICK_ACCESS, logic->IsChild && logic->CanBreakPots()), EVENT_ACCESS(LOGIC_BUG_ACCESS, (logic->BlastOrSmash() && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_SILVER_GAUNTLETS)), EVENT_ACCESS(LOGIC_GORON_CITY_CHILD_FIRE, logic->IsChild && logic->CanUse(RG_DINS_FIRE)), - EVENT_ACCESS(LOGIC_GORON_CITY_WOODS_WARP_OPEN, logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER) || logic->Get(LOGIC_GORON_CITY_CHILD_FIRE)), + EVENT_ACCESS(LOGIC_GORON_CITY_WOODS_WARP_OPEN, logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER) || + (logic->IsChild && logic->Get(LOGIC_GORON_CITY_CHILD_FIRE) && logic->CanUse(RG_STICKS))), EVENT_ACCESS(LOGIC_GORON_CITY_DARUNIAS_DOOR_OPEN_CHILD, logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY)), // bottle animation causes similar complications as stopping goron with Din's Fire, only put in logic when both din's & blue fire tricks enabled + // RANDOTODO Strength for this is a trick in N64, should it be here? Should bunny put it in default logic? EVENT_ACCESS(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT, logic->IsAdult && logic->HasItem(RG_SPEAK_GORON) && (logic->HasItem(RG_GORONS_BRACELET) || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) || (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)))))), }, { @@ -34,7 +36,7 @@ void RegionTable_Init_GoronCity() { LOCATION(RC_GC_UPPER_STAIRCASE_POT_1, logic->CanBreakPots()), LOCATION(RC_GC_UPPER_STAIRCASE_POT_2, logic->CanBreakPots()), LOCATION(RC_GC_UPPER_STAIRCASE_POT_3, logic->CanBreakPots()), - LOCATION(RC_GC_MAZE_CRATE, logic->BlastOrSmash() || (logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanBreakCrates())), + LOCATION(RC_GC_MAZE_CRATE, logic->BlastOrSmash() || (logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanBreakCrates())), LOCATION(RC_GC_ENTRANCE_BOULDER_1, logic->BlastOrSmash()), LOCATION(RC_GC_ENTRANCE_BOULDER_2, logic->BlastOrSmash()), LOCATION(RC_GC_ENTRANCE_BOULDER_3, logic->BlastOrSmash()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp index aa42b38dba..898347ed37 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp @@ -99,7 +99,7 @@ void RegionTable_Init_Graveyard() { }, { //Locations LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, logic->HasItem(RG_SPEAK_HYLIAN) && logic->CanOpenLargeChest()), - LOCATION(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, (logic->IsAdult || ctx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH)) && logic->HasItem(RG_SPEAK_HYLIAN)), + LOCATION(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, (logic->IsAdult || ctx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH) || logic->BunnyHood()) && logic->HasItem(RG_SPEAK_HYLIAN)), LOCATION(RC_GY_DAMPES_GRAVE_POT_1, logic->CanBreakPots()), LOCATION(RC_GY_DAMPES_GRAVE_POT_2, logic->CanBreakPots()), LOCATION(RC_GY_DAMPES_GRAVE_POT_3, 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 8766b6db66..86a43fe214 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp @@ -12,14 +12,14 @@ void RegionTable_Init_HauntedWasteland() { }, { //Exits ENTRANCE(RR_GF_OUTSIDE_GATE, true), - ENTRANCE(RR_HAUNTED_WASTELAND, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || ctx->GetTrickOption(RT_HW_CROSSING)), + ENTRANCE(RR_HAUNTED_WASTELAND, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || ctx->GetTrickOption(RT_HW_CROSSING) || (ctx->GetTrickOption(RT_HW_BUNNY_CROSSING) && logic->BunnyHood())), }); areaTable[RR_HAUNTED_WASTELAND] = Region("Haunted Wasteland", SCENE_HAUNTED_WASTELAND, { //Events EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CanBreakPots()), EVENT_ACCESS(LOGIC_NUT_ACCESS, logic->CanBreakPots()), - EVENT_ACCESS(LOGIC_CARPET_MERCHANT, logic->HasItem(RG_ADULT_WALLET) && GetCheckPrice(RC_WASTELAND_BOMBCHU_SALESMAN) <= GetWalletCapacity() && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS))), + EVENT_ACCESS(LOGIC_CARPET_MERCHANT, logic->HasItem(RG_ADULT_WALLET) && GetCheckPrice(RC_WASTELAND_BOMBCHU_SALESMAN) <= GetWalletCapacity() && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood())), }, { //Locations LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), @@ -37,7 +37,7 @@ void RegionTable_Init_HauntedWasteland() { }, { //Exits ENTRANCE(RR_WASTELAND_NEAR_COLOSSUS, ctx->GetTrickOption(RT_LENS_HW) || logic->CanUse(RG_LENS_OF_TRUTH)), - ENTRANCE(RR_WASTELAND_NEAR_FORTRESS, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || ctx->GetTrickOption(RT_HW_CROSSING)), + ENTRANCE(RR_WASTELAND_NEAR_FORTRESS, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || ctx->GetTrickOption(RT_HW_CROSSING) || (ctx->GetTrickOption(RT_HW_BUNNY_CROSSING) && logic->BunnyHood())), }); areaTable[RR_WASTELAND_NEAR_COLOSSUS] = Region("Wasteland Near Colossus", SCENE_HAUNTED_WASTELAND, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index f50aedfa9f..55ac819eac 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -84,14 +84,14 @@ void RegionTable_Init_Kakariko() { ENTRANCE(RR_KAK_WELL, logic->IsAdult || logic->Get(LOGIC_DRAIN_WELL) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_BOTTOM_OF_THE_WELL_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash())), ENTRANCE(RR_KAK_POTION_SHOP, (logic->AtDay || logic->IsChild) && logic->HasItem(RG_KAK_POTION_SHOP_KEY)), ENTRANCE(RR_KAK_REDEAD_GROTTO, logic->CanOpenBombGrotto()), - ENTRANCE(RR_KAK_IMPAS_LEDGE, (logic->IsChild && logic->AtDay && logic->HasItem(RG_POWER_BRACELET)) || (logic->IsAdult && ctx->GetTrickOption(RT_VISIBLE_COLLISION))), + ENTRANCE(RR_KAK_IMPAS_LEDGE, (logic->IsChild && ((logic->AtDay && logic->HasItem(RG_POWER_BRACELET)) || (logic->BunnyHovers() && logic->CanJumpslash()))) || (logic->IsAdult && ctx->GetTrickOption(RT_VISIBLE_COLLISION))), ENTRANCE(RR_KAK_WATCHTOWER, logic->HasItem(RG_CLIMB) && (logic->IsAdult || logic->AtDay || logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT) || (ctx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslashExceptHammer()))), ENTRANCE(RR_KAK_ROOFTOP, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->IsAdult)), ENTRANCE(RR_KAK_IMPAS_ROOFTOP, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_KAK_ROOFTOP_GS) && logic->CanUse(RG_HOVER_BOOTS))), ENTRANCE(RR_THE_GRAVEYARD, true), ENTRANCE(RR_KAK_BEHIND_GATE, logic->IsAdult || logic->Get(LOGIC_KAKARIKO_GATE_OPEN)), - //adult can jump from the fence near the windmill to ledgegrab the fence near granny's shop. is in logic on N64 - ENTRANCE(RR_KAK_BACKYARD, logic->IsAdult || (logic->AtDay && logic->HasItem(RG_POWER_BRACELET))), + //adult or bunny can jump from the fence near the windmill to ledgegrab the fence near granny's shop. is in logic on N64 + ENTRANCE(RR_KAK_BACKYARD, logic->IsAdult || logic->BunnyHood() || (logic->AtDay && logic->HasItem(RG_POWER_BRACELET))), ENTRANCE(RR_KAK_BEHIND_POTION_SHOP, logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->IsAdult)), }); 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 1cc32caaf3..b0a316ab96 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -8,7 +8,7 @@ void RegionTable_Init_KokiriForest() { areaTable[RR_KOKIRI_FOREST] = Region("Kokiri Forest", SCENE_KOKIRI_FOREST, { //Events EVENT_ACCESS(LOGIC_PLANT_KOKIRI_FOREST_BEAN, CanPlantBean(RG_KOKIRI_FOREST_BEAN_SOUL)), - EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairyExceptSuns() || (logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_KOKIRI_FOREST_BEAN) && logic->CanUse(RG_SONG_OF_STORMS))), + EVENT_ACCESS(LOGIC_FAIRY_ACCESS, (logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_KOKIRI_FOREST_BEAN) && logic->CanUse(RG_SONG_OF_STORMS))), EVENT_ACCESS(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD, logic->IsChild && logic->HasItem(RG_SPEAK_KOKIRI) && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD)), }, { //Locations @@ -26,13 +26,9 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_SOUTH_GRASS_EAST_RUPEE, logic->IsChild), LOCATION(RC_KF_NORTH_GRASS_WEST_RUPEE, logic->IsChild), LOCATION(RC_KF_NORTH_GRASS_EAST_RUPEE, logic->IsChild), - LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult && (logic->BeanPlanted(LOGIC_PLANT_KOKIRI_FOREST_BEAN) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult && (logic->BeanPlanted(LOGIC_PLANT_KOKIRI_FOREST_BEAN) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_3, logic->IsAdult && (logic->BeanPlanted(LOGIC_PLANT_KOKIRI_FOREST_BEAN) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_4, logic->IsAdult && (logic->BeanPlanted(LOGIC_PLANT_KOKIRI_FOREST_BEAN) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_5, logic->IsAdult && (logic->BeanPlanted(LOGIC_PLANT_KOKIRI_FOREST_BEAN) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RUPEE_6, logic->IsAdult && (logic->BeanPlanted(LOGIC_PLANT_KOKIRI_FOREST_BEAN) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_KF_BEAN_RED_RUPEE, logic->IsAdult && (logic->BeanPlanted(LOGIC_PLANT_KOKIRI_FOREST_BEAN) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_KF_BEAN_RUPEE_6, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), LOCATION(RC_KF_SARIAS_ROOF_WEST_HEART, logic->IsChild), LOCATION(RC_KF_SARIAS_ROOF_EAST_HEART, logic->IsChild), LOCATION(RC_KF_SARIAS_ROOF_NORTH_HEART, logic->IsChild), @@ -119,7 +115,9 @@ void RegionTable_Init_KokiriForest() { ENTRANCE(RR_LW_BRIDGE_FROM_FOREST, logic->IsAdult || ctx->GetOption(RSK_FOREST).IsNot(RO_CLOSED_FOREST_ON) || logic->Get(LOGIC_DEKU_TREE_CLEAR)), }); - areaTable[RR_KF_OUTSIDE_LOST_WOODS] = Region("KF Outside Lost Woods", SCENE_KOKIRI_FOREST, {}, { + areaTable[RR_KF_OUTSIDE_LOST_WOODS] = Region("KF Outside Lost Woods", SCENE_KOKIRI_FOREST, { + EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairyExceptSuns()), + }, { //Locations LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult && logic->CanUse(RG_BOOMERANG)), @@ -136,19 +134,19 @@ void RegionTable_Init_KokiriForest() { //Exits ENTRANCE(RR_KOKIRI_FOREST, true), ENTRANCE(RR_THE_LOST_WOODS, true), - ENTRANCE(RR_KF_RUPEE_ALCOVE, logic->IsAdult && (logic->BeanPlanted(LOGIC_PLANT_KOKIRI_FOREST_BEAN) || logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_KF_RUPEE_ALCOVE, (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || logic->CanMiddairGroundJump()), ENTRANCE(RR_KF_STORMS_GROTTO, logic->CanOpenStormsGrotto()), }); areaTable[RR_KF_RUPEE_ALCOVE] = Region("KF Alcove", SCENE_KOKIRI_FOREST, {}, { //Locations - LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), - LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), - LOCATION(RC_KF_BEAN_RUPEE_3, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), - LOCATION(RC_KF_BEAN_RUPEE_4, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), - LOCATION(RC_KF_BEAN_RUPEE_5, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), - LOCATION(RC_KF_BEAN_RUPEE_6, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), - LOCATION(RC_KF_BEAN_RED_RUPEE, logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_KF_BEAN_RUPEE_1, logic->IsAdult), + LOCATION(RC_KF_BEAN_RUPEE_2, logic->IsAdult), + LOCATION(RC_KF_BEAN_RUPEE_3, logic->IsAdult), + LOCATION(RC_KF_BEAN_RUPEE_4, logic->IsAdult), + LOCATION(RC_KF_BEAN_RUPEE_5, logic->IsAdult), + LOCATION(RC_KF_BEAN_RUPEE_6, logic->IsAdult), + LOCATION(RC_KF_BEAN_RED_RUPEE, logic->IsAdult), }, { ENTRANCE(RR_KOKIRI_FOREST, true), }); @@ -163,8 +161,8 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_CHILD_GRASS_MAZE_3, logic->IsChild && logic->CanCutShrubs()), LOCATION(RC_KF_AFTER_CRAWLSPACE_RECTANGLE_SIGN, logic->IsChild && logic->CanRead()), LOCATION(RC_KF_BOULDER_MAZE_RECTANGLE_SIGN, logic->IsChild && logic->CanRead()), - LOCATION(RC_KF_WONDER_CRAWL_GRASS_1, logic->IsChild), - LOCATION(RC_KF_WONDER_CRAWL_GRASS_2, logic->IsChild), + LOCATION(RC_KF_WONDER_CRAWL_GRASS_1, logic->IsChild), + LOCATION(RC_KF_WONDER_CRAWL_GRASS_2, logic->IsChild), }, { //Exits ENTRANCE(RR_KOKIRI_FOREST, logic->CanUse(RG_CRAWL)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp index d80a2004bc..29d102aca2 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp @@ -11,17 +11,17 @@ void RegionTable_Init_LakeHylia() { EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairy() || logic->CanUse(RG_STICKS) || (logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_LAKE_HYLIA_BEAN) && logic->CanUse(RG_SONG_OF_STORMS))), EVENT_ACCESS(LOGIC_BUG_ACCESS, logic->IsChild && logic->CanCutShrubs()), EVENT_ACCESS(LOGIC_CHILD_SCARECROW, logic->IsChild && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2), - EVENT_ACCESS(LOGIC_ADULT_SCARECROW, logic->IsAdult && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2), + EVENT_ACCESS(LOGIC_ADULT_SCARECROW, logic->IsAdult && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 2), }, { //Locations LOCATION(RC_LH_UNDERWATER_ITEM, logic->IsChild && logic->HasItem(RG_SILVER_SCALE)), LOCATION(RC_LH_SUN, logic->IsAdult && ((logic->Get(LOGIC_WATER_TEMPLE_CLEAR) && logic->HasItem(RG_BRONZE_SCALE)) || logic->ReachDistantScarecrow()) && logic->CanUse(RG_FAIRY_BOW)), - LOCATION(RC_LH_FREESTANDING_POH, logic->IsAdult && (logic->ReachScarecrow() || logic->BeanPlanted(LOGIC_PLANT_LAKE_HYLIA_BEAN)) && logic->CanAvoidEnemy(RE_GUAY, false) && logic->HasItem(RG_CLIMB)), + LOCATION(RC_LH_FREESTANDING_POH, logic->IsAdult && (logic->ReachScarecrow() || logic->BeanPlanted(LOGIC_PLANT_LAKE_HYLIA_BEAN)) && logic->CanAvoidEnemy(RE_GUAY, ED_CLOSE, false) && logic->HasItem(RG_CLIMB)), LOCATION(RC_LH_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_LAKE_HYLIA_BEAN_SOUL) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_LH_GS_LAB_WALL, logic->IsChild && (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (ctx->GetTrickOption(RT_LH_LAB_WALL_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), LOCATION(RC_LH_GS_SMALL_ISLAND, logic->IsChild && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) && logic->CanGetNightTimeGS() && logic->HasItem(RG_BRONZE_SCALE)), LOCATION(RC_LH_GS_TREE, logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->CanGetNightTimeGS()), - LOCATION(RC_LH_FRONT_RUPEE, logic->IsChild && logic->HasItem(RG_BRONZE_SCALE)), + LOCATION(RC_LH_FRONT_RUPEE, logic->IsChild && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS))), LOCATION(RC_LH_MIDDLE_RUPEE, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))), LOCATION(RC_LH_BACK_RUPEE, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS))), LOCATION(RC_LH_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_LAKE_HYLIA_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), @@ -110,12 +110,12 @@ void RegionTable_Init_LakeHylia() { areaTable[RR_LH_FISHING_ISLAND] = Region("LH Fishing Island", SCENE_LAKE_HYLIA, {}, { //Locations - LOCATION(RC_LH_ROCK, logic->CanBreakRocks()), - LOCATION(RC_LH_FISHING_SIGN, logic->CanRead()), + LOCATION(RC_LH_ROCK, logic->CanBreakRocks()), + LOCATION(RC_LH_FISHING_SIGN, logic->CanRead()), LOCATION(RC_LH_FISHING_ISLAND_WATER_SWITCH_SIGN, logic->IsAdult && logic->CanRead()), }, { //Exits - ENTRANCE(RR_LAKE_HYLIA, logic->HasItem(RG_BRONZE_SCALE)), + ENTRANCE(RR_LAKE_HYLIA, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE)), ENTRANCE(RR_LH_FISHING_POND, logic->HasItem(RG_FISHING_HOLE_KEY)), }); 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 fc327ff5b4..1dc911b90a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -58,7 +58,7 @@ void RegionTable_Init_LostWoods() { ENTRANCE(RR_LW_FOREST_EXIT, true), ENTRANCE(RR_LW_UNDER_BRIDGE, true), ENTRANCE(RR_GC_WOODS_WARP, true), - ENTRANCE(RR_LW_BRIDGE, (logic->IsAdult && (logic->BeanPlanted(LOGIC_PLANT_LOST_WOODS_BRIDGE_BEAN) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT)), + ENTRANCE(RR_LW_BRIDGE, (logic->IsAdult && (logic->BeanPlanted(LOGIC_PLANT_LOST_WOODS_BRIDGE_BEAN) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || logic->CanUse(RG_LONGSHOT)), ENTRANCE(RR_ZR_FROM_SHORTCUT, logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LOST_WOOD_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash())), ENTRANCE(RR_LW_BEYOND_MIDO, logic->IsChild || logic->CanUse(RG_SARIAS_SONG) || ctx->GetTrickOption(RT_LW_MIDO_BACKFLIP)), ENTRANCE(RR_LW_NEAR_SHORTCUTS_GROTTO, AnyAgeTime([]{return logic->BlastOrSmash();})), @@ -66,7 +66,7 @@ void RegionTable_Init_LostWoods() { areaTable[RR_LW_UNDER_BRIDGE] = Region("Lost Woods Under the Bridge", SCENE_LOST_WOODS, { //Events - EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairyExceptSuns()), + EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairyExceptSuns()), }, { //Locations LOCATION(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index 248669cbef..bda66f584b 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -14,7 +14,6 @@ void RegionTable_Init_Market() { areaTable[RR_THE_MARKET] = Region("Market", SCENE_MARKET_DAY, {}, { //Locations - //RANDOTODO add item avalibility to regions to remove need to hardcode logic in limited item use situations LOCATION(RC_MARKET_GRASS_1, logic->IsChild && logic->CanCutShrubs()), LOCATION(RC_MARKET_GRASS_2, logic->IsChild && logic->CanCutShrubs()), LOCATION(RC_MARKET_GRASS_3, logic->IsChild && logic->CanCutShrubs()), 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 eb7d375c35..71fbfb6f84 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() { ENTRANCE(RR_FOREST_TEMPLE_ENTRYWAY, logic->CanUse(RG_HOOKSHOT)), ENTRANCE(RR_SFM_ENTRYWAY, logic->IsAdult || logic->Get(LOGIC_OPEN_SFM_GATE)), // adult can jump up, but it's a trick. being hit directly by club moblin while wearing hover boots also works, but relies on coming from LW - ENTRANCE(RR_SFM_ABOVE_MAZE, logic->CanClimbLadder() || (logic->IsAdult && logic->CanGroundJump())), + ENTRANCE(RR_SFM_ABOVE_MAZE, logic->CanClimbLadder() || (logic->IsAdult && (logic->CanGroundJump() || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) && logic->BunnyHood())))), ENTRANCE(RR_SFM_STORMS_GROTTO, logic->CanOpenStormsGrotto()), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp index 4814dee000..114068c730 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp @@ -116,25 +116,28 @@ void RegionTable_Init_ThievesHideout() { areaTable[RR_TH_KITCHEN_BY_CORRIDOR] = Region("Thieves Hideout Kitchen Top By Corridor", SCENE_THIEVES_HIDEOUT, {}, { //Locations - LOCATION(RC_TH_KITCHEN_POT_1, logic->CanUse(RG_BOOMERANG)), - LOCATION(RC_TH_KITCHEN_POT_2, logic->CanUse(RG_BOOMERANG)), + //"Voidout" here means getting caught by guards + LOCATION(RC_TH_KITCHEN_POT_1, logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanBreakPots(ED_BOMB_THROW))), + LOCATION(RC_TH_KITCHEN_POT_2, logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_TH_WONDER_KITCHEN_SOUP, ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->BunnyHovers()), }, { //Exits ENTRANCE(RR_TH_KITCHEN_MAIN, true), //hookshot to cross using rafters implied by logic->CanPassEnemy(RE_GERUDO_GUARD) - ENTRANCE(RR_TH_KITCHEN_OPPOSITE_CORRIDOR, logic->CanPassEnemy(RE_GERUDO_GUARD) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_TH_KITCHEN_OPPOSITE_CORRIDOR, logic->CanPassEnemy(RE_GERUDO_GUARD) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), ENTRANCE(RR_GF_TOP_OF_LOWER_VINES, true), }); areaTable[RR_TH_KITCHEN_OPPOSITE_CORRIDOR] = Region("Thieves Hideout Kitchen Top Across From Corridor", SCENE_THIEVES_HIDEOUT, {}, { //Locations - LOCATION(RC_TH_KITCHEN_POT_1, logic->CanUse(RG_BOOMERANG)), - LOCATION(RC_TH_KITCHEN_POT_2, logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_TH_KITCHEN_POT_1, logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_TH_KITCHEN_POT_2, logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanBreakPots(ED_BOMB_THROW))), + LOCATION(RC_TH_WONDER_KITCHEN_SOUP, ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->BunnyHovers()), }, { //Exits ENTRANCE(RR_TH_KITCHEN_MAIN, true), //hookshot to cross using rafters implied by logic->CanPassEnemy(RE_GERUDO_GUARD) - ENTRANCE(RR_TH_KITCHEN_BY_CORRIDOR, logic->CanPassEnemy(RE_GERUDO_GUARD) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_TH_KITCHEN_BY_CORRIDOR, logic->CanPassEnemy(RE_GERUDO_GUARD) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()), ENTRANCE(RR_GF_NEAR_GS, 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 5f528b531d..eee9752ca8 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp @@ -19,7 +19,9 @@ void RegionTable_Init_ZorasDomain() { LOCATION(RC_ZD_CHEST, logic->IsChild && logic->CanUse(RG_STICKS) && logic->CanOpenLargeChest()), LOCATION(RC_ZD_KING_ZORA_THAWED, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED) && logic->HasItem(RG_SPEAK_ZORA)), 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()), + //bad terrain blocks bomb throws, so "inWater" is enabled to simulate that. Chus are also awkward to aim, so might want to be removed as well + //You normally need spin attack or RT_ZD_GS to kill with melee weapons, simulated by ED_SHORT_JUMPSLASH when that condition is met, as that prohibits hammer like those 2 do + LOCATION(RC_ZD_GS_FROZEN_WATERFALL, logic->IsAdult && logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->CanUse(RG_MAGIC_SINGLE) || ctx->GetTrickOption(RT_ZD_GS) ? ED_SHORT_JUMPSLASH : ED_BOOMERANG, true, 1, false, true) && logic->CanGetNightTimeGS()), LOCATION(RC_ZD_FISH_1, logic->IsChild && logic->HasBottle()), LOCATION(RC_ZD_FISH_2, logic->IsChild && logic->HasBottle()), LOCATION(RC_ZD_FISH_3, logic->IsChild && logic->HasBottle()), @@ -61,7 +63,9 @@ void RegionTable_Init_ZorasDomain() { areaTable[RR_ZORAS_DOMAIN_ISLAND] = Region("Zoras Domain Island", SCENE_ZORAS_DOMAIN, {}, {}, { //Exits - ENTRANCE(RR_ZORAS_DOMAIN, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && ctx->GetTrickOption(RT_HOOKSHOT_LADDERS))), + ENTRANCE(RR_ZORAS_DOMAIN, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT) || + (logic->CanUse(RG_HOOKSHOT) && ctx->GetTrickOption(RT_HOOKSHOT_LADDERS)) || logic->CanUse(RG_IRON_BOOTS) || + ((logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood()) && logic->HasItem(RG_CLIMB))), ENTRANCE(RR_ZD_STORMS_GROTTO, logic->CanOpenStormsGrotto()), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp index 5301b7f08f..114e9f15fc 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp @@ -51,7 +51,7 @@ void RegionTable_Init_ZoraRiver() { LOCATION(RC_ZR_FROGS_SUNS_SONG, logic->IsChild && logic->CanUse(RG_SUNS_SONG)), LOCATION(RC_ZR_FROGS_SONG_OF_TIME, logic->IsChild && logic->CanUse(RG_SONG_OF_TIME)), LOCATION(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, logic->CanUse(RG_BOOMERANG)), - LOCATION(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_UPPER))), + LOCATION(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_HOVER_BOOTS) || logic->BunnyHood() || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_UPPER))), LOCATION(RC_ZR_GS_LADDER, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH) && logic->CanGetNightTimeGS()), LOCATION(RC_ZR_GS_NEAR_RAISED_GROTTOS, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT) && logic->CanGetNightTimeGS()), LOCATION(RC_ZR_GS_ABOVE_BRIDGE, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_HOOKSHOT) && logic->CanGetNightTimeGS()), @@ -116,10 +116,11 @@ void RegionTable_Init_ZoraRiver() { }, { //Exits ENTRANCE(RR_ZR_FRONT, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_POWER_BRACELET) || logic->BlastOrSmash() || logic->HasItem(RG_HOVER_BOOTS)), - ENTRANCE(RR_ZR_ATOP_LADDER, ((logic->IsAdult || logic->HasItem(RG_POWER_BRACELET)) && logic->CanClimbLadder()) || (logic->IsAdult && logic->BeanPlanted(LOGIC_PLANT_ZORAS_RIVER_BEAN))), - ENTRANCE(RR_ZR_PILLAR, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_LOWER))), + ENTRANCE(RR_ZR_ATOP_LADDER, ((logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanClimbLadder()) || (logic->IsAdult && logic->BeanPlanted(LOGIC_PLANT_ZORAS_RIVER_BEAN))), + ENTRANCE(RR_ZR_PILLAR, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && (ctx->GetTrickOption(RT_ZR_LOWER) || logic->BunnyHood()))), ENTRANCE(RR_ZR_FROM_SHORTCUT, logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)), ENTRANCE(RR_ZR_STORMS_GROTTO, logic->CanOpenStormsGrotto()), + //possible with adult + bunny, but too precise for unintuitive ENTRANCE(RR_ZR_BEHIND_WATERFALL, ctx->GetOption(RSK_SLEEPING_WATERFALL).Is(RO_WATERFALL_OPEN) || AnyAgeTime([]{return logic->CanUse(RG_ZELDAS_LULLABY);}) || (logic->IsChild && ctx->GetTrickOption(RT_ZR_CUCCO) && logic->HasItem(RG_POWER_BRACELET)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_ZR_HOVERS))), }); @@ -144,7 +145,7 @@ void RegionTable_Init_ZoraRiver() { }, { //Exits ENTRANCE(RR_ZORAS_RIVER, true), - ENTRANCE(RR_ZR_PILLAR, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOVER_BOOTS)), + ENTRANCE(RR_ZR_PILLAR, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->BunnyHood() && (logic->IsAdult || logic->CanJumpslash()))), ENTRANCE(RR_ZR_OPEN_GROTTO, true), ENTRANCE(RR_ZR_FAIRY_GROTTO, AnyAgeTime([]{return logic->BlastOrSmash();})), }); diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 13ced6261c..d9e27ff434 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -624,7 +624,8 @@ bool Logic::CanUse(RandomizerGet itemName) { return IsChild; case RG_SKULL_MASK: case RG_MASK_OF_TRUTH: - return IsChild; + case RG_BUNNY_HOOD: + return IsChild || ctx->GetOption(RSK_MASKS_AS_ADULT); // Songs case RG_ZELDAS_LULLABY: @@ -1177,11 +1178,12 @@ bool Logic::CanPassEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal // Can we avoid this enemy while climbing up a wall, or doing a difficult platforming challenge? // use grounded if the challenge is such that the enemy interfears even if it cannot hit link out of the air -bool Logic::CanAvoidEnemy(RandomizerEnemy enemy, bool grounded, uint8_t quantity) { +bool Logic::CanAvoidEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool grounded, uint8_t quantity) { // DISTANCE AND WALL ASSUMED, add more arguments later if needed - if (CanKillEnemy(enemy, ED_CLOSE, true, quantity)) { + if (CanKillEnemy(enemy, distance, true, quantity)) { return true; } + bool avoided = false; switch (enemy) { case RE_GOLD_SKULLTULA: case RE_GOHMA_LARVA: @@ -1214,8 +1216,32 @@ bool Logic::CanAvoidEnemy(RandomizerEnemy enemy, bool grounded, uint8_t quantity case RE_WALLTULA: return true; case RE_BEAMOS: - return !grounded || CanUse(RG_NUTS) || CanUse(RG_DINS_FIRE) || - (quantity == 1 && (CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT))); + if (!grounded) { + return true; + } + switch (distance) { + // melee can stun, but doing so means getting close anyway + case ED_CLOSE: + case ED_SHORT_JUMPSLASH: + case ED_MASTER_SWORD_JUMPSLASH: + case ED_LONG_JUMPSLASH: + case ED_BOMB_THROW: + avoided = CanUse(RG_DINS_FIRE) || CanUse(RG_NUTS); + [[fallthrough]]; + case ED_BOOMERANG: + avoided = avoided || CanUse(RG_BOOMERANG); + [[fallthrough]]; + case ED_HOOKSHOT: + avoided = avoided || CanUse(RG_HOOKSHOT); + [[fallthrough]]; + case ED_LONGSHOT: + avoided = avoided || CanUse(RG_LONGSHOT); + [[fallthrough]]; + case ED_FAR: + avoided = avoided || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW); + break; + } + return avoided; case RE_MAD_SCRUB: return !grounded || CanUse(RG_NUTS); case RE_KEESE: @@ -1325,15 +1351,71 @@ bool Logic::BeanPlanted(LogicVal beanEvent) { return swch >> patch->swchFlag & 1; } -bool Logic::CanHammerRecoilHover(bool needShield) { - return CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && CanUse(RG_MEGATON_HAMMER) && - (!needShield || CanStandingShield()); +bool Logic::CanRecoilHover(RecoilRequirements req) { + if (!(CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE))) { + return false; + } + bool can = false; + switch (req) { + case RECOIL_SWORD: + can = CanJumpslash(); + break; + case RECOIL_SWORD_AND_SHIELD: + // hammer without shield gives better recoils than sword and shield + can = (CanJumpslash() && CanStandingShield()); + [[fallthrough]]; + case RECOIL_HAMMER: + can = can || CanUse(RG_MEGATON_HAMMER); + break; + case RECOIL_HAMMER_AND_SHIELD: + can = (CanUse(RG_MEGATON_HAMMER) && CanStandingShield()); + default: + break; + } + return can; +} + +// some actors seem to normalise recoil distance, so the only thing that can matter is attack range +bool Logic::CanRecoilHoverFromObject(TorchRecoilRequirements req) { + if (!(CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE))) { + return false; + } + bool can = false; + switch (req) { + case TRECOIL_LONG_AND_SHIELD: + can = (CanUse(RG_STICKS) || CanUse(RG_BIGGORON_SWORD)) && CanStandingShield(); + break; + case TRECOIL_SHORT: + can = CanUse(RG_MEGATON_HAMMER) || CanUse(RG_KOKIRI_SWORD); + [[fallthrough]]; + case TRECOIL_MASTER: + can = can || CanUse(RG_MASTER_SWORD); + [[fallthrough]]; + case TRECOIL_LONG: + can = can || CanUse(RG_STICKS) || CanUse(RG_BIGGORON_SWORD); + break; + default: + break; + } + return can; } bool Logic::Water3FCentralToHighEmblem() { + //"Just jumping" to this ledge is complicated, as the nearest part of the ledge is janky + // Adult without bunny hood can airdrift left to get a clean ledge grab, however if the scarecrow has spawned (which + // is a perm flag that with skip scarecrow inevitably activates while setting water to high) the usable ledge area + // is much smaller. Unlike most jumps like this, Bunny hood does not solve the jump, at least for Adult. For child + // it makes this not only possible but much less prone to issues than either Adult jump. Adult can instead aim even + // further left to get a good ledge climb, but will almost always be blocked by the scarecrow if that exists. + // otherwise Adult with bunny will result in worse ledge bugging than not using bunny. You can climb up even if you + // start doing weird ledge things with a well timed jumpslash. Hovers are similarly unintuitive, needing the player + // aim for the far side of the ledge, but the scarecrow is less annoying as even if you get pushed off, hovers will + // save you and push you slightly right, eventually giving you a good ledge grab return (IsAdult && (CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && CanUse(RG_BOMB_BAG) && TakeDamage()))) || - CanMiddairGroundJump() || (Get(LOGIC_WATER_SCARECROW) && CanUse(RG_HOOKSHOT)); + CanMiddairGroundJump() || + (Get(LOGIC_WATER_SCARECROW) && CanUse(RG_HOOKSHOT) || + (logic->IsChild && logic->BunnyHood() && ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))); } bool Logic::WaterRisingTargetTo3FCentral() { @@ -1743,6 +1825,16 @@ bool Logic::SunlightArrows() { return ctx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS); } +// Bunny Hood grants the Majora's Mask run speed and jump distance boost +bool Logic::BunnyHood() { + return ctx->GetOption(RSK_BUNNY_HOOD) && CanUse(RG_BUNNY_HOOD); +} + +// Hovering with the extra speed the hood gives +bool Logic::BunnyHovers() { + return CanUse(RG_HOVER_BOOTS) && BunnyHood(); +} + bool Logic::CanStandingShield() { return CanUse(RG_MIRROR_SHIELD) || (IsAdult && HasItem(RG_HYLIAN_SHIELD)) || CanUse(RG_DEKU_SHIELD); } @@ -2903,17 +2995,19 @@ bool Logic::IsReverseAccessPossible() { } bool Logic::DMCUpperToPots() { - return CanUse(RG_HOVER_BOOTS) || (IsAdult && ((Get(LOGIC_DMC_BOULDER)) || - (ctx->GetTrickOption(RT_DMC_BOULDER_SKIP) /* && CanUse(RG_ROLL)*/))); + return CanUse(RG_HOVER_BOOTS) || BunnyHood() || + (IsAdult && + ((Get(LOGIC_DMC_BOULDER)) || (ctx->GetTrickOption(RT_DMC_BOULDER_SKIP) /* && CanUse(RG_ROLL)*/))); } bool Logic::DMCPotsToPad() { - return (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT) || - (IsAdult && CanShield() && ctx->GetTrickOption(RT_DMC_BOLERO_JUMP) && CanUse(RG_POWER_BRACELET))); + return CanUse(RG_HOVER_BOOTS) || (BunnyHood() && (IsAdult || HasItem(RG_CLIMB))) || CanUse(RG_HOOKSHOT) || + (IsAdult && CanShield() && ctx->GetTrickOption(RT_DMC_BOLERO_JUMP) && CanUse(RG_POWER_BRACELET)); } bool Logic::DMCPadToPots() { - return ((CanUse(RG_HOVER_BOOTS) && (IsAdult || (HasItem(RG_CLIMB) /*&& CanUse(RG_ROLL)*/))) || CanUse(RG_HOOKSHOT)); + return (CanUse(RG_HOVER_BOOTS) && (IsAdult || (HasItem(RG_CLIMB) /*&& can roll or bunny*/))) || + CanUse(RG_HOOKSHOT) || (IsAdult && BunnyHood() && HasItem(RG_CLIMB)); } // via scarecrow @@ -2926,12 +3020,13 @@ bool Logic::SpiritExplosiveKeyLogic() { } bool Logic::SpiritWestToSkull() { - return (IsAdult && ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP)) || CanUse(RG_HOVER_BOOTS) || ReachScarecrow(); + return (IsAdult && (ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP) || logic->BunnyHood())) || CanUse(RG_HOVER_BOOTS) || + ReachScarecrow(); } bool Logic::SpiritSunBlockSouthLedge() { // also possible to do a backwalk hover + backflip if you equip hovers as you start backwalk to accelerate faster - return HasItem(RG_POWER_BRACELET) || IsAdult || CanKillEnemy(RE_BEAMOS) /*|| BunnyHovers()*/ || + return HasItem(RG_POWER_BRACELET) || IsAdult || CanKillEnemy(RE_BEAMOS) || BunnyHovers() || (CanUse(RG_HOOKSHOT) && (HasFireSource() || (Get(LOGIC_SPIRIT_SUN_BLOCK_TORCH) && @@ -2939,18 +3034,19 @@ bool Logic::SpiritSunBlockSouthLedge() { } bool Logic::SpiritEastToSwitch() { - return (IsAdult && ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP)) || CanUse(RG_HOVER_BOOTS) || + return (IsAdult && (ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP) || logic->BunnyHood())) || CanUse(RG_HOVER_BOOTS) || (CanUse(RG_ZELDAS_LULLABY) && CanUse(RG_HOOKSHOT)); } // Combines crossing the ledge directly and the jump from the hand bool Logic::MQSpiritWestToPots() { - return (IsAdult && ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP)) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_SONG_OF_TIME); + return (IsAdult && (ctx->GetTrickOption(RT_SPIRIT_STATUE_JUMP) || logic->BunnyHood())) || CanUse(RG_HOVER_BOOTS) || + CanUse(RG_SONG_OF_TIME); } bool Logic::MQSpiritStatueToSunBlock() { - return (IsAdult || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || - CanUse(RG_SONG_OF_TIME) /* || CanBunnyJump()*/) && + return (IsAdult || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || CanUse(RG_SONG_OF_TIME) || + CanUse(RG_HOVER_BOOTS) || BunnyHood()) && HasItem(RG_POWER_BRACELET); } @@ -2965,7 +3061,7 @@ bool Logic::MQSpirit4KeyColossus() { // Colossus This is because there are only 3 keys that can be wasted without opening up either this lock to East // hand, or the West Hand lock through Sun Block Room and both directions allow you to drop onto colossus // logic->CanKillEnemy(RE_FLOORMASTER) is implied - return CanAvoidEnemy(RE_BEAMOS, true, 4) && CanUse(RG_SONG_OF_TIME) && CanJumpslash() && + return CanAvoidEnemy(RE_BEAMOS, ED_CLOSE, true, 4) && CanUse(RG_SONG_OF_TIME) && CanJumpslash() && (HasItem(RG_POWER_BRACELET) || SunlightArrows()) && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)) && CanKillEnemy(RE_IRON_KNUCKLE) && CanUse(RG_HOOKSHOT); @@ -2979,7 +3075,7 @@ bool Logic::MQSpirit4KeyWestHand() { } // This version of the function handles Shared Access for child, based on what adult could do if they existed bool Logic::CouldMQSpirit4KeyWestHand() { - return CanAvoidEnemy(RE_BEAMOS, true, 4) && CanUse(RG_SONG_OF_TIME) && + return CanAvoidEnemy(RE_BEAMOS, ED_CLOSE, true, 4) && CanUse(RG_SONG_OF_TIME) && (HasItem(RG_MASTER_SWORD) || HasItem(RG_BIGGORON_SWORD) || HasItem(RG_MEGATON_HAMMER)) && (HasItem(RG_POWER_BRACELET) || SunlightArrows()) && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)) && HasItem(RG_LONGSHOT); diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 87ddef994a..214b7f3ce0 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -52,7 +52,8 @@ class Logic { bool CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool wallOrFloor = true, uint8_t quantity = 1, bool timer = false, bool inWater = false); bool CanPassEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool wallOrFloor = true); - bool CanAvoidEnemy(RandomizerEnemy enemy, bool grounded = false, uint8_t quantity = 1); + bool CanAvoidEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool grounded = false, + uint8_t quantity = 1); bool CanGetEnemyDrop(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool aboveLink = false); bool CanBreakMudWalls(); bool CanGetDekuBabaSticks(); @@ -61,7 +62,8 @@ class Logic { bool CanDetonateBombFlowers(); bool CanDetonateUprightBombFlower(); bool BeanPlanted(LogicVal beanEvent); - bool CanHammerRecoilHover(bool needShield = false); + bool CanRecoilHover(RecoilRequirements req); + bool CanRecoilHoverFromObject(TorchRecoilRequirements req); bool Water3FCentralToHighEmblem(); bool WaterRisingTargetTo3FCentral(); bool WaterLevel(RandoWaterLevel level); @@ -112,6 +114,8 @@ class Logic { bool HasFireSource(); bool HasFireSourceWithTorch(); bool SunlightArrows(); + bool BunnyHood(); + bool BunnyHovers(); bool CanStandingShield(); bool CanShield(); bool CanUseProjectile(); diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h b/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h index fde3575865..83f43343c2 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h @@ -263,9 +263,11 @@ RANDO_ENUM_ITEM(LOGIC_DC_EYES_LIT) RANDO_ENUM_ITEM(LOGIC_DC_STAIRS_ROOM_DOOR) RANDO_ENUM_ITEM(LOGIC_DC_LIFT_PLATFORM) RANDO_ENUM_ITEM(LOGIC_DC_KILLED_LOWER_LIZALFOS) +RANDO_ENUM_ITEM(LOGIC_DC_MQ_TWO_FIRES_BOULDER) RANDO_ENUM_ITEM(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS) RANDO_ENUM_ITEM(LOGIC_DC_MQ_CLEAR_BIG_BLOCK_WEB) RANDO_ENUM_ITEM(LOGIC_DC_MQ_BEHIND_FIRE_SWITCH) +RANDO_ENUM_ITEM(LOGIC_JABU_RUTO_IN_B1) RANDO_ENUM_ITEM(LOGIC_JABU_RUTO_IN_1F) RANDO_ENUM_ITEM(LOGIC_JABU_WEST_TENTACLE) RANDO_ENUM_ITEM(LOGIC_JABU_EAST_TENTACLE) @@ -308,6 +310,7 @@ RANDO_ENUM_ITEM(LOGIC_WATER_PUSHED_1F_BLOCK) RANDO_ENUM_ITEM(LOGIC_WATER_SCARECROW) RANDO_ENUM_ITEM(LOGIC_WATER_MQ_STALFOS_PIT) RANDO_ENUM_ITEM(LOGIC_WATER_MQ_DRAGON_TORCHES) +RANDO_ENUM_ITEM(LOGIC_WATER_MQ_BOSS_KEY_CHEST_TORCHES) RANDO_ENUM_ITEM(LOGIC_WATER_MQ_B1_SWITCH) RANDO_ENUM_ITEM(LOGIC_WATER_MQ_B1_OPENED_PILLAR) RANDO_ENUM_ITEM(LOGIC_WATER_MQ_PILLAR_SOT_BLOCK) @@ -359,7 +362,7 @@ RANDO_ENUM_ITEM(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST) RANDO_ENUM_ITEM(LOGIC_WATER_TRIAL_RUSTED_SWITCH) RANDO_ENUM_ITEM(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) RANDO_ENUM_ITEM(LOGIC_SHADOW_TRIAL_FIRST_CHEST) -RANDO_ENUM_ITEM(LOGIC_SHADOW_TRIAL_LOWER_SWITCH) +RANDO_ENUM_ITEM(LOGIC_SHADOW_TRIAL_LATE_CHEST) RANDO_ENUM_ITEM(LOGIC_SHADOW_TRIAL_RUSTED_SWITCH) RANDO_ENUM_ITEM(LOGIC_MAX) RANDO_ENUM_END(LogicVal) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h index ca712fa455..82cb8eac6e 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h @@ -524,6 +524,22 @@ RANDO_ENUM_BEGIN(GrottoEntranceOffsets) /* 0x21 */ RANDO_ENUM_ITEM(GROTTO_OFFSET_MAX) RANDO_ENUM_END(GrottoEntranceOffsets) +RANDO_ENUM_BEGIN(RecoilRequirements) +/* 0x00 */ RANDO_ENUM_ITEM(RECOIL_SWORD) +/* 0x01 */ RANDO_ENUM_ITEM(RECOIL_SWORD_AND_SHIELD) +/* 0x02 */ RANDO_ENUM_ITEM(RECOIL_HAMMER) +/* 0x03 */ RANDO_ENUM_ITEM(RECOIL_HAMMER_AND_SHIELD) +/* 0x04 */ RANDO_ENUM_ITEM(RECOIL_MAX) +RANDO_ENUM_END(RecoilRequirements) + +RANDO_ENUM_BEGIN(TorchRecoilRequirements) +/* 0x00 */ RANDO_ENUM_ITEM(TRECOIL_SHORT) +/* 0x01 */ RANDO_ENUM_ITEM(TRECOIL_MASTER) +/* 0x02 */ RANDO_ENUM_ITEM(TRECOIL_LONG) +/* 0x03 */ RANDO_ENUM_ITEM(TRECOIL_LONG_AND_SHIELD) +/* 0x04 */ RANDO_ENUM_ITEM(TRECOIL_MAX) +RANDO_ENUM_END(TorchRecoilRequirements) + #ifdef RANDO_ENUM_BEGIN_CLEANUP #undef RANDO_ENUM_BEGIN #undef RANDO_ENUM_BEGIN_CLEANUP diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h index 65331ad241..f0bd6aa85d 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h @@ -312,6 +312,7 @@ RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_STAIRS_LOWER) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_STAIRS_UPPER) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_COMPASS_ROOM) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_ARMOS_ROOM) +RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_ENTRANCE_SIDE_BRIDGE) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_2F_SIDE_ROOM) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM) @@ -338,6 +339,7 @@ RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM) +RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_FLOWER) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE) RANDO_ENUM_ITEM(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE_SCRUB) @@ -375,6 +377,7 @@ RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_BIGOCTO_LEDGE) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_BIGOCTO) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_JIGGLIES_ROOM) +RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_JIGGLIES_LEDGE) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_LIFT_UPPER) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM) @@ -396,6 +399,7 @@ RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_MQ_TO_FORK_NORTH) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_MQ_FORK_NORTH) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_MQ_FORK_NORTH_EAST) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_MQ_FORK_EAST) +RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_MQ_HOLES_B1_SW_DOOR) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_MQ_TO_BIGOCTO) RANDO_ENUM_ITEM(RR_JABU_JABUS_BELLY_MQ_BIGOCTO) @@ -420,6 +424,7 @@ RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER_ALCOVE) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_NE_COURTYARD_UPPER) +RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_NE_COURTYARD_SWITCH) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_NE_COURTYARD_DOORFRAME) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_NE_COURTYARD_SCARECROW_LEDGE) @@ -472,7 +477,8 @@ RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_WELL_LEDGE) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_MQ_NE_COURTYARD) -RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES) +RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_DOOR) +RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_CHEST) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_DOORFRAME) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND) RANDO_ENUM_ITEM(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_LEDGE_ABOVE_ISLAND) @@ -507,13 +513,17 @@ RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_LAVA_GEYSER_GRATE) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_LAVA_GEYSER_TORCH) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_LAVA_GEYSER_2F) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_SHORTCUT_ROOM) +RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_SHORTCUT_ROOM_3F) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_SHORTCUT_CLIMB) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_3F_CURVED_CAGE) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_NARROW_PATH_ROOM) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_FIRE_WALL_CHASE) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_FIRE_WALL_CAGE) +RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_FIRE_WALL_UPPER_DOOR) +RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_FIRE_WALL_SIDE_DOOR) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER) +RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_BOULDER_MAZE_4F) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_GS_CLIMB_4F) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_GS_CLIMB_5F) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_5F_RUINS) @@ -528,7 +538,8 @@ RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_FIRE_MAZE_SWITCH) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_FIRE_MAZE_PAST_WALL) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_3F_FLARE_DANCER) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_ABOVE_3F_FLARE_DANCER) -RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_SWITCH_CLIMB) +RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_SWITCH_CLIMB_4F) +RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_SWITCH_CLIMB_5F) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_NARROW_STAIRS) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_NARROW_STAIRS_4F) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_TOP_OF_COLLAPSING_STAIRS) @@ -586,7 +597,8 @@ RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_MQ_GS_LIZALFOS_ROOM) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PAST_WALL) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_MQ_3F_FLARE_DANCER) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_MQ_ABOVE_3F_FLARE_DANCER) -RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB) +RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB_4F) +RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_MQ_LOCKED_CLIMB_5F) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_MQ_NARROW_STAIRS_ROOM) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_MQ_NARROW_STAIRS_4F) RANDO_ENUM_ITEM(RR_FIRE_TEMPLE_MQ_TOP_OF_COLLAPSING_STAIRS) @@ -650,6 +662,7 @@ RANDO_ENUM_ITEM(RR_WATER_TEMPLE_LIKE_LIKE_SPIKES) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_DARK_LINK_ROOM) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_SOT_PIT_ROOM) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_RIVER) +RANDO_ENUM_ITEM(RR_WATER_TEMPLE_RIVER_PLATFORM) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_RIVER_POTS) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_ABOVE_DRAGON) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_RISING_TARGET_LEDGE) @@ -696,6 +709,7 @@ RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_DARK_LINK_ROOM) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_GATED_PIT) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_RIVER_SKULL) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_RIVER_POTS) +RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_BOTTOM) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_TUNNEL) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE) @@ -709,6 +723,8 @@ RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_CAGE) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_SPIKE_MOAT) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_BEHIND_SPIKE_MOAT) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_ROOM) +RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_BED_S) +RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_CRATE_VORTEX_BED_N) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_SCARECROW_CANAL) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_CANAL_ALCOVE) RANDO_ENUM_ITEM(RR_WATER_TEMPLE_MQ_BEHIND_CANAL) @@ -1008,6 +1024,7 @@ RANDO_ENUM_ITEM(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS) RANDO_ENUM_ITEM(RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM) RANDO_ENUM_ITEM(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS) RANDO_ENUM_ITEM(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH) +RANDO_ENUM_ITEM(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_LIT_TORCH) RANDO_ENUM_ITEM(RR_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_ROOM) RANDO_ENUM_ITEM(RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER) RANDO_ENUM_ITEM(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT) @@ -1032,9 +1049,12 @@ RANDO_ENUM_ITEM(RR_GANONS_CASTLE_WATER_TRIAL_BLOCK_ROOM_SWITCH) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_WATER_TRIAL_BLOCK_ROOM_END) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_WATER_TRIAL_FINAL_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_SHADOW_TRIAL_START) +RANDO_ENUM_ITEM(RR_GANONS_CASTLE_SHADOW_TRIAL_SOT_PLATFORM) +RANDO_ENUM_ITEM(RR_GANONS_CASTLE_SHADOW_TRIAL_TORCH) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_SHADOW_TRIAL_POTS_PLATFORM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_SHADOW_TRIAL_CHEST_PLATFORM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_SHADOW_TRIAL_LOWER_SWITCH) +RANDO_ENUM_ITEM(RR_GANONS_CASTLE_SHADOW_TRIAL_RUSTED_SWITCH) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_SHADOW_TRIAL_END) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_SHADOW_TRIAL_FINAL_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_SPIRIT_TRIAL_BEAMOS_ROOM) @@ -1068,8 +1088,10 @@ RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_WATER_TRIAL_FINAL_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_MOVING_PLATFORM) +RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST) +RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_BEAMOS) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BARRED_DOOR) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FINAL_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h index 4b85ab349a..6d7d7e9690 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h @@ -203,6 +203,8 @@ RANDO_ENUM_ITEM(RSK_MERCHANT_PRICES_AFFORDABLE) RANDO_ENUM_ITEM(RSK_SHUFFLE_BEGGAR) RANDO_ENUM_ITEM(RSK_BLUE_FIRE_ARROWS) RANDO_ENUM_ITEM(RSK_SUNLIGHT_ARROWS) +RANDO_ENUM_ITEM(RSK_BUNNY_HOOD) +RANDO_ENUM_ITEM(RSK_MASKS_AS_ADULT) RANDO_ENUM_ITEM(RSK_SLINGBOW_BREAK_BEEHIVES) RANDO_ENUM_ITEM(RSK_ENABLE_BOMBCHU_DROPS) RANDO_ENUM_ITEM(RSK_BOMBCHU_BAG) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h index 4996a888e8..88925da0fe 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h @@ -22,7 +22,6 @@ RANDO_ENUM_ITEM(RT_GROTTOS_WITHOUT_AGONY) RANDO_ENUM_ITEM(RT_FEWER_TUNIC_REQUIREMENTS) RANDO_ENUM_ITEM(RT_UNINTUITIVE_JUMPS) RANDO_ENUM_ITEM(RT_FIRE_RINGS) -RANDO_ENUM_ITEM(RT_BUNNY_HOOD_JUMPS) RANDO_ENUM_ITEM(RT_DAMAGE_BOOST_SIMPLE) RANDO_ENUM_ITEM(RT_HOVER_BOOST_SIMPLE) RANDO_ENUM_ITEM(RT_BOMBCHU_BEEHIVES) @@ -103,11 +102,12 @@ RANDO_ENUM_ITEM(RT_DC_SLINGSHOT_SKIP) RANDO_ENUM_ITEM(RT_DC_SCRUB_ROOM) RANDO_ENUM_ITEM(RT_DC_HAMMER_FLOOR) RANDO_ENUM_ITEM(RT_DC_MQ_STAIRS_WITH_ONLY_STRENGTH) -RANDO_ENUM_ITEM(RT_DC_MQ_CHILD_BOMBS) +RANDO_ENUM_ITEM(RT_DC_CHILD_LOBBY) RANDO_ENUM_ITEM(RT_DC_MQ_CHILD_EYES) RANDO_ENUM_ITEM(RT_DC_MQ_ADULT_EYES) RANDO_ENUM_ITEM(RT_DC_DODONGO_CHU) RANDO_ENUM_ITEM(RT_DC_EYES_CHU) +RANDO_ENUM_ITEM(RT_DC_EYES_BUNNYHOVERS) RANDO_ENUM_ITEM(RT_JABU_BOSS_HOVER) RANDO_ENUM_ITEM(RT_JABU_NEAR_BOSS_RANGED) RANDO_ENUM_ITEM(RT_JABU_NEAR_BOSS_EXPLOSIVES) @@ -208,6 +208,7 @@ RANDO_ENUM_ITEM(RT_GTG_STATUE_JUMP) RANDO_ENUM_ITEM(RT_LENS_GTG_MQ) RANDO_ENUM_ITEM(RT_GTG_MQ_WITH_HOOKSHOT) RANDO_ENUM_ITEM(RT_GTG_MQ_WITHOUT_HOOKSHOT) +RANDO_ENUM_ITEM(RT_GTG_MQ_LAVA_ROOM) RANDO_ENUM_ITEM(RT_LENS_GANON) RANDO_ENUM_ITEM(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) RANDO_ENUM_ITEM(RT_LENS_GANON_MQ) diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index b78ca88e05..df72aa88c8 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1396,6 +1396,8 @@ void Settings::CreateOptions() { // TODO: Compasses show rewards/woth, maps show dungeon mode OPT_BOOL(RSK_BLUE_FIRE_ARROWS, CVAR_RANDOMIZER_SETTING("BlueFireArrows")); OPT_BOOL(RSK_SUNLIGHT_ARROWS, CVAR_RANDOMIZER_SETTING("SunlightArrows")); + OPT_BOOL(RSK_BUNNY_HOOD, CVAR_RANDOMIZER_SETTING("BunnyHood")); + OPT_BOOL(RSK_MASKS_AS_ADULT, CVAR_RANDOMIZER_SETTING("MasksAsAdult")); OPT_BOOL(RSK_ROCS_FEATHER, CVAR_RANDOMIZER_SETTING("RocsFeather")); OPT_U8(RSK_INFINITE_UPGRADES, {"Off", "Progressive", "Condensed Progressive"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("InfiniteUpgrades")); OPT_BOOL(RSK_SKELETON_KEY, CVAR_RANDOMIZER_SETTING("SkeletonKey")); @@ -1594,11 +1596,6 @@ void Settings::CreateOptions() { OPT_TRICK(RT_UNINTUITIVE_JUMPS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "UnJmp"); OPT_TRICK(RT_FIRE_RINGS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::INTERMEDIATE }, "FlaChst"); - // disabled for now, can't check for being able to use bunny hood & bunny hood speedup is currently completely - // decoupled from rando - - // OPT_TRICK(RT_BUNNY_HOOD_JUMPS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED }); - OPT_TRICK(RT_DAMAGE_BOOST_SIMPLE, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL }, "SDmgBoo"); OPT_TRICK(RT_HOVER_BOOST_SIMPLE, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::GLITCH }, "SHovBoo"); @@ -1677,10 +1674,8 @@ void Settings::CreateOptions() { OPT_TRICK(RT_GF_LEDGE_CLIP_INTO_GTG, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, "GTGLdgClp"); - // disabled for now, can't check for being able to use bunny hood & bunny hood speedup is currently completely - // decoupled from rando - - // OPT_TRICK(RT_HW_BUNNY_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, { Tricks::Tag::NOVICE }); + // only does anything with the Bunny Hood Effect setting on + OPT_TRICK(RT_HW_BUNNY_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, { Tricks::Tag::NOVICE }, "HWBun"); OPT_TRICK(RT_HW_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, { Tricks::Tag::INTERMEDIATE }, "RvrSand"); OPT_TRICK(RT_LENS_HW, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, { Tricks::Tag::INTERMEDIATE }, "HWNoLoT"); @@ -1701,10 +1696,11 @@ void Settings::CreateOptions() { OPT_TRICK(RT_DC_HAMMER_FLOOR, RCQUEST_BOTH, RA_DODONGOS_CAVERN, { Tricks::Tag::NOVICE }, "KDHamFl"); OPT_TRICK(RT_DC_DODONGO_CHU, RCQUEST_BOTH, RA_DODONGOS_CAVERN, { Tricks::Tag::ADVANCED }, "KDChu"); OPT_TRICK(RT_DC_MQ_STAIRS_WITH_ONLY_STRENGTH, RCQUEST_MQ, RA_DODONGOS_CAVERN, { Tricks::Tag::NOVICE }, "DCStaStr"); - OPT_TRICK(RT_DC_MQ_CHILD_BOMBS, RCQUEST_MQ, RA_DODONGOS_CAVERN, { Tricks::Tag::ADVANCED }, "DCLobyJS"); + OPT_TRICK(RT_DC_CHILD_LOBBY, RCQUEST_BOTH, RA_DODONGOS_CAVERN, { Tricks::Tag::ADVANCED }, "DCLobyJS"); OPT_TRICK(RT_DC_MQ_CHILD_EYES, RCQUEST_MQ, RA_DODONGOS_CAVERN, { Tricks::Tag::EXPERT }, "DCEyeStrC"); OPT_TRICK(RT_DC_MQ_ADULT_EYES, RCQUEST_MQ, RA_DODONGOS_CAVERN, { Tricks::Tag::ADVANCED }, "DCEyeStrA"); OPT_TRICK(RT_DC_EYES_CHU, RCQUEST_BOTH, RA_DODONGOS_CAVERN, { Tricks::Tag::ADVANCED }, "DCEyeChu"); + OPT_TRICK(RT_DC_EYES_BUNNYHOVERS, RCQUEST_BOTH, RA_DODONGOS_CAVERN, { Tricks::Tag::ADVANCED }, "DCEyeBun"); OPT_TRICK(RT_JABU_BOSS_HOVER, RCQUEST_VANILLA, RA_JABU_JABUS_BELLY, { Tricks::Tag::INTERMEDIATE }, "JbuBoxHB"); OPT_TRICK(RT_JABU_NEAR_BOSS_RANGED, RCQUEST_BOTH, RA_JABU_JABUS_BELLY, { Tricks::Tag::NOVICE }, "JbuBosPrj"); OPT_TRICK(RT_JABU_NEAR_BOSS_EXPLOSIVES, RCQUEST_VANILLA, RA_JABU_JABUS_BELLY, { Tricks::Tag::INTERMEDIATE }, @@ -1828,6 +1824,7 @@ void Settings::CreateOptions() { OPT_TRICK(RT_GTG_MQ_WITH_HOOKSHOT, RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::NOVICE }, "GTGMQHS"); OPT_TRICK(RT_GTG_MQ_WITHOUT_HOOKSHOT, RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::INTERMEDIATE }, "GTGMQNoHS"); + OPT_TRICK(RT_GTG_MQ_LAVA_ROOM, RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::INTERMEDIATE }, "GTGMQLava"); OPT_TRICK(RT_LENS_GANON, RCQUEST_VANILLA, RA_GANONS_CASTLE, { Tricks::Tag::NOVICE }, "GCLoT"); OPT_TRICK(RT_GANON_SPIRIT_TRIAL_HOOKSHOT, RCQUEST_VANILLA, RA_GANONS_CASTLE, { Tricks::Tag::NOVICE }, "GCNoHS"); OPT_TRICK(RT_LENS_GANON_MQ, RCQUEST_MQ, RA_GANONS_CASTLE, { Tricks::Tag::NOVICE }, "GCMQLoT"); @@ -1874,6 +1871,8 @@ void Settings::CreateOptions() { &mOptions[RSK_BIG_POE_COUNT], &mOptions[RSK_BLUE_FIRE_ARROWS], &mOptions[RSK_SUNLIGHT_ARROWS], + &mOptions[RSK_BUNNY_HOOD], + &mOptions[RSK_MASKS_AS_ADULT], &mOptions[RSK_FULL_WALLETS], &mOptions[RSK_SLINGBOW_BREAK_BEEHIVES], &mOptions[RSK_SWORDLESS_EPONA_ITEMS], @@ -2443,6 +2442,8 @@ void Settings::CreateOptions() { &mOptions[RSK_DAMAGE_MULTIPLIER], &mOptions[RSK_BLUE_FIRE_ARROWS], &mOptions[RSK_SUNLIGHT_ARROWS], + &mOptions[RSK_BUNNY_HOOD], + &mOptions[RSK_MASKS_AS_ADULT], &mOptions[RSK_INFINITE_UPGRADES], &mOptions[RSK_SKELETON_KEY], &mOptions[RSK_SLINGBOW_BREAK_BEEHIVES], diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp index 79f157e98b..ec7482eb0c 100644 --- a/soh/soh/Enhancements/randomizer/static_data.cpp +++ b/soh/soh/Enhancements/randomizer/static_data.cpp @@ -377,7 +377,7 @@ std::unordered_map StaticData::trickToEnum = { { "74", RT_DC_SCRUB_ROOM }, { "76", RT_DC_HAMMER_FLOOR }, { "77", RT_DC_MQ_STAIRS_WITH_ONLY_STRENGTH }, - { "78", RT_DC_MQ_CHILD_BOMBS }, + { "78", RT_DC_CHILD_LOBBY }, { "79", RT_DC_MQ_CHILD_EYES }, { "80", RT_DC_MQ_ADULT_EYES }, { "81", RT_DC_DODONGO_CHU }, diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 84db38733c..52a93c2777 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -990,15 +990,29 @@ void SohMenu::AddMenuEnhancements() { AddWidget(path, "Masks", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Bunny Hood Effect", WIDGET_CVAR_COMBOBOX) .CVar(CVAR_BUNNY_HOOD_NAME) + .PreFunc([](WidgetInfo& info) { + info.options->disabled = OTRGlobals::Instance->gRandoContext->GetOption(RSK_BUNNY_HOOD).Is(RO_GENERIC_ON); + info.options->disabledTooltip = "This setting is forcefully enabled because a randomized savefile with " + "\"Bunny Hood Effect\" is currently loaded."; + }) .Options(ComboboxOptions() .ComboMap(bunnyHoodEffectMap) .Tooltip("Wearing the Bunny Hood grants a speed and jump boost like in Majora's Mask.\n" "Can also be limited to only the speed boost.\n" - "The effects of either option are not accounted for in Randomizer logic.\n" + "Randomizer logic only accounts for this when the seed's own \"Bunny Hood Effect\" " + "setting is on.\n" "Also disables NPC's reactions to wearing the Bunny Hood.")); AddWidget(path, "Masks Equippable as Adult", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ADULT_MASKS_NAME) - .Options(CheckboxOptions().Tooltip("Allows masks to be equipped normally from the pause menu as adult.")); + .PreFunc([](WidgetInfo& info) { + info.options->disabled = + OTRGlobals::Instance->gRandoContext->GetOption(RSK_MASKS_AS_ADULT).Is(RO_GENERIC_ON); + info.options->disabledTooltip = "This setting is forcefully enabled because a randomized savefile with " + "\"Masks as Adult\" is currently loaded."; + }) + .Options(CheckboxOptions().Tooltip("Allows masks to be equipped normally from the pause menu as adult.\n" + "Randomizer logic only accounts for this when the seed's own " + "\"Masks as Adult\" setting is on.")); AddWidget(path, "Persistent Masks", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("PersistentMasks")) .Options(