diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp index 64c572086..671abda83 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp @@ -37,7 +37,7 @@ void RegionTable_Init_BottomOfTheWell() { Entrance(RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, {[]{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}}), Entrance(RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, {[]{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}}), Entrance(RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, {[]{return logic->IsChild && logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}), - Entrance(RR_BOTTOM_OF_THE_WELL_COFFIN_ROOM, {[]{return logic->LoweredWaterInsideBotw || logic->CanUse(RG_BRONZE_SCALE);}}), + Entrance(RR_BOTTOM_OF_THE_WELL_COFFIN_ROOM, {[]{return logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE);}}), Entrance(RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM, {[]{return logic->LoweredWaterInsideBotw && logic->IsChild;}}), //Falling down into basement requires nothing, but falling down somewhere specific requires lens or lens trick //kinda questionable given several drops are blocked by rocks, but that's how it was handled before and on N64 @@ -108,7 +108,7 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), }, { //Exits - Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, {[]{return logic->LoweredWaterInsideBotw || logic->CanUse(RG_BRONZE_SCALE);}}), + Entrance(RR_BOTTOM_OF_THE_WELL_PERIMETER, {[]{return logic->LoweredWaterInsideBotw || logic->HasItem(RG_BRONZE_SCALE);}}), }); areaTable[RR_BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM] = Region("Bottom of the Well Dead Hand Room", "Bottom of the Well", {RA_BOTTOM_OF_THE_WELL}, NO_DAY_NIGHT_CYCLE, {}, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp index ab642b402..bee7f3b40 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp @@ -256,7 +256,7 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT] = Region("Deku Tree MQ Basement Water Room Front", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, { //Events //It's possible to get this with bow if you have move while in first person and one-point skips on, noticeably harder and jankier as child, but that's a trick - EventAccess(&logic->MQDekuWaterRoomTorches, {[]{return logic->CanUse(RG_FIRE_ARROWS) || (logic->IsChild && logic->CanUse(RG_STICKS) && logic->CanShield());}}), + EventAccess(&logic->MQDekuWaterRoomTorches, {[]{return logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_STICKS) && (ctx->GetTrickOption(RT_DEKU_MQ_LOG) || (logic->IsChild && logic->CanShield())));}}), }, { //Locations LOCATION(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, true), @@ -279,7 +279,7 @@ void RegionTable_Init_DekuTree() { //Exits Entrance(RR_DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM, {[]{return logic->MQDekuWaterRoomTorches && logic->CanPassEnemy(RE_BIG_SKULLTULA, logic->CanUse(RG_SONG_OF_TIME) ? ED_CLOSE : ED_HAMMER_JUMPSLASH);}}), Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, {[]{return ctx->GetTrickOption(RT_DEKU_MQ_LOG) || (logic->IsChild && logic->CanShield()) || - logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_BRONZE_SCALE) || + logic->CanUse(RG_LONGSHOT) || logic->HasItem(RG_BRONZE_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && (logic->IsAdult || logic->CanUse(RG_HOOKSHOT)));}}), }); @@ -321,19 +321,19 @@ void RegionTable_Init_DekuTree() { LOCATION(RC_DEKU_TREE_MQ_DEKU_SCRUB, logic->CanStunDeku()), }, { //Exits - Entrance(RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return logic->IsChild;}}), - Entrance(RR_DEKU_TREE_MQ_BASEMENT, {[]{return true;}}), + Entrance(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, {[]{return logic->IsChild;}}), + Entrance(RR_DEKU_TREE_MQ_BASEMENT, {[]{return true;}}), //If strength 0 is shuffled, add hovers or block push to the stick check //recoiling to skip swim is possible, but would be a trick Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, {[]{return Here(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, []{return logic->HasFireSource() || (/*logic->PushedDekuBasementBlock && */logic->CanUse(RG_STICKS));}) - && (logic->CanUse(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS));}}), + && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS));}}), }); areaTable[RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM] = Region("Deku Tree MQ Outside Boss Room", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {}, { // Exits - Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return logic->CanUse(RG_BRONZE_SCALE);}}), + Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return logic->HasItem(RG_BRONZE_SCALE);}}), Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, {[]{return Here(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, []{return logic->CanReflectNuts();});}}), }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp index d81f08152..f894d263d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp @@ -11,7 +11,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_ENTRYWAY] = Region("Fire Temple Entryway", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return ctx->GetDungeon(FIRE_TEMPLE)->IsVanilla();}}), - Entrance(RR_FIRE_TEMPLE_MQ_LOWER, {[]{return ctx->GetDungeon(FIRE_TEMPLE)->IsMQ();}}), + Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, {[]{return ctx->GetDungeon(FIRE_TEMPLE)->IsMQ();}}), Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return true;}}), }); @@ -314,82 +314,309 @@ void RegionTable_Init_FireTemple() { | MASTER QUEST DUNGEON | ---------------------------*/ if (ctx->GetDungeon(FIRE_TEMPLE)->IsMQ()) { - areaTable[RR_FIRE_TEMPLE_MQ_LOWER] = Region("Fire Temple MQ Lower", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { - //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, logic->CanJumpslashExceptHammer() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_BOMB_BAG) || logic->CanUse(RG_DINS_FIRE)), - LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->IsAdult && (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || logic->CanUse(RG_GORON_TUNIC)) && (((logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && logic->CanUse(RG_FAIRY_BOW))) && logic->HasFireSource()) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && ((ctx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO) && ctx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_QUADRUPLE) && ctx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OCTUPLE) && ctx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_SEXDECUPLE)) || logic->CanUse(RG_GORON_TUNIC) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_LONGSHOT)))))), - //Trick: logic->IsAdult && (LogicFewerTunicRequirements || logic->CanUse(RG_GORON_TUNIC)) && (((logic->CanUse(RG_HOVER_BOOTS) || (LogicFireMQNearBoss && logic->CanUse(RG_FAIRY_BOW))) && logic->HasFireSource()) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && ((DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_QUADRUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OCTUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_SEXDECUPLE)) || logic->CanUse(RG_GORON_TUNIC) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_LONGSHOT))))) - }, { + //potentially dangerous temp flag on the first room's torches, should be made parament if possible + areaTable[RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER] = Region("Fire Temple MQ First Room Lower", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return true;}}), - Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return logic->IsAdult && logic->CanUse(RG_GORON_TUNIC) && logic->CanUse(RG_MEGATON_HAMMER) && logic->HasItem(RG_FIRE_TEMPLE_BOSS_KEY) && ((logic->HasFireSource() && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || logic->CanUse(RG_HOVER_BOOTS))) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER));}}), - Entrance(RR_FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 5) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD));}}), - Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, {[]{return logic->IsAdult && logic->FireTimer() >= 24 && logic->CanUse(RG_MEGATON_HAMMER);}}), + Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_SOUTH, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, {[]{return logic->IsAdult || logic->CanUse(RG_HOOKSHOT);}}), + Entrance(RR_FIRE_TEMPLE_MQ_STALFOS_ROOM, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 5);}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER] = Region("Fire Temple MQ First Room Upper", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, {[]{return logic->HasFireSource();}}), + Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, {[]{return Here(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, {[]{return logic->CanUse(RG_MEGATON_HAMMER);}});}}), }); - areaTable[RR_FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR] = Region("Fire Temple MQ Lower Locked Door", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { + areaTable[RR_FIRE_TEMPLE_MQ_MAP_ROOM_SOUTH] = Region("Fire Temple MQ Map Room South", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE)), + }, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, {[]{return Here(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, {[]{return logic->CanKillEnemy(RE_LIKE_LIKE);}});}}), + Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_CAGE, {[]{return logic->OpenedLowestGoronCage;}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_STALFOS_ROOM] = Region("Fire Temple MQ Stalfos Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_IRON_KNUCKLE_ROOM, {[]{return Here(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, {[]{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, 2);}});}}), +}); + + areaTable[RR_FIRE_TEMPLE_MQ_IRON_KNUCKLE_ROOM] = Region("Fire Temple MQ Iron Knuckle Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&logic->FairyPot, {[]{return true;}}), - }, { - //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_HOOKSHOT) || (logic->HasExplosives() && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG))))), - LOCATION(RC_FIRE_TEMPLE_MQ_MAP_CHEST, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), - }, {}); + }, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_STALFOS_ROOM, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER, {[]{return Here(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, {[]{return logic->CanKillEnemy(RE_IRON_KNUCKLE);}});}}), +}); - areaTable[RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM] = Region("Fire Temple MQ Big Lava Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&logic->FairyPot, {[]{return logic->FairyPot || (logic->HasFireSource() && (logic->CanUse(RG_FAIRY_BOW) || ctx->GetTrickOption(RT_FIRE_MQ_BK_CHEST)) && logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || ctx->GetTrickOption(RT_FIRE_SOT)));}}), - //Trick: logic->HasFireSource() && (logic->CanUse(RG_FAIRY_BOW) || LogicFireMQBKChest) && logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || LogicFireSongOfTime) - }, { + areaTable[RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER] = Region("Fire Temple MQ Lower Flare Dancer", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, logic->HasFireSource() && (logic->CanUse(RG_FAIRY_BOW) || ctx->GetTrickOption(RT_FIRE_MQ_BK_CHEST)) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT)), - //Trick: logic->HasFireSource() && (logic->CanUse(RG_FAIRY_BOW) || LogicFireMQBKChest) && logic->IsAdult && logic->CanUse(RG_HOOKSHOT) - LOCATION(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->HasFireSource() && logic->HasExplosives() && logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || ctx->GetTrickOption(RT_FIRE_MQ_BLOCKED_CHEST))), - //Trick: logic->HasFireSource() && logic->HasExplosives() && logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || LogicFireMQBlockedChest) - LOCATION(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, true), + LOCATION(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT)) && Here(RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER, {[]{return logic->CanKillEnemy(RE_FLARE_DANCER);}})), }, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return logic->IsAdult && logic->CanUse(RG_GORON_TUNIC) && logic->SmallKeys(RR_FIRE_TEMPLE, 2) && (logic->HasFireSource() || (ctx->GetTrickOption(RT_FIRE_MQ_CLIMB) && logic->CanUse(RG_HOVER_BOOTS)));}}), - //Trick: logic->IsAdult && logic->CanUse(RG_GORON_TUNIC) && logic->SmallKeys(RR_FIRE_TEMPLE, 2) && (logic->HasFireSource() || (LogicFireMQClimb && logic->CanUse(RG_HOVER_BOOTS))) + Entrance(RR_FIRE_TEMPLE_MQ_IRON_KNUCKLE_ROOM, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_NORTH, {[]{return Here(RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER, {[]{return logic->CanKillEnemy(RE_FLARE_DANCER);}});}}), +}); + + areaTable[RR_FIRE_TEMPLE_MQ_MAP_ROOM_NORTH] = Region("Fire Temple MQ Map Room North", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->OpenedLowestGoronCage, {[]{return logic->CanUse(RG_MEGATON_HAMMER);}}), + }, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_CAGE, {[]{return logic->OpenedLowestGoronCage;}}), +}); + + areaTable[RR_FIRE_TEMPLE_MQ_MAP_ROOM_CAGE] = Region("Fire Temple MQ Map Room Cage", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_FIRE_TEMPLE_MQ_MAP_CHEST, true), + }, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_NORTH, {[]{return logic->OpenedLowestGoronCage;}}), + Entrance(RR_FIRE_TEMPLE_MQ_MAP_ROOM_SOUTH, {[]{return logic->OpenedLowestGoronCage;}}), +}); + + areaTable[RR_FIRE_TEMPLE_NEAR_BOSS_ROOM] = Region("Fire Temple MQ Near Boss Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + //Child cannot make it to the north side torches without a hook without specifically bunny hood speed + hover boots + //The Damage logic here is for crossing to the north torches with hookshot, then using dins there before 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 + //logic->EffectiveHealth() works in half hearts for whatever reason, meaning this needs a deeper refactor to be perfect, but it should be good enough for now + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, //Using the south torch as the initial torch, or using FAs, we first have to sort the crate... + //If we don't go out of the way to break the box it's reasonable to do things in ~25 seconds, otherwise it takes about 40 + (logic->FireTimer() > (ctx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) ? 25 : 40) && + (ctx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) || logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS))) && + //then use FA's, or dins + bow as adult. Child can only do a torch shot from the north side upper torch so will be handled in the lower case to avoid RT_FIRE_MQ_NEAR_BOSS issues + (logic->CanUse(RG_FIRE_ARROWS) || (logic->IsAdult && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW)))) || + //If we're starting with the north torches, we need to get across first, and light them + //Pretty much all these methods take ~20-30 seconds + (logic->FireTimer() > 30 && + (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS))) && logic->CanUse(RG_DINS_FIRE) && + //then we need to either use a bow to shoot back across, or somehow get back to use dins again. Alternatively we can use Sticks as adult and NL + (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->EffectiveHealth() >= 2 || (logic->CanUse(RG_NAYRUS_LOVE) && logic->CanUse(RG_STICKS))))))) + }, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return logic->HasItem(RG_FIRE_TEMPLE_BOSS_KEY) && logic->FireTimer() >= 15 && + (logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || logic->CanUse(RG_HOVER_BOOTS))) || + (logic->IsAdult && logic->HitFireTemplePlatform) || + (logic->HitFireTemplePlatform && logic->CanUse(RG_HOVER_BOOTS)) + ;}}), }); + + areaTable[RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM] = Region("Fire Temple MQ Big Lava Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + //I'm currently assuming the oversight version of RT_FIRE_MQ_BK_CHEST for the fire timer logic + LOCATION(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->FireTimer() >= 40 && logic->HasFireSource() && logic->HasExplosives() && (logic->CanUse(RG_HOOKSHOT) || ctx->GetTrickOption(RT_FIRE_MQ_BLOCKED_CHEST))), + //implies CanGetEnemyDrop(RE_GOLD_SKULLTULA) + LOCATION(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, logic->FireTimer() >= 20 && logic->CanUse(RG_MEGATON_HAMMER)), + }, { + //Exits + // Fewer tunic requirements ends here + Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, {[]{return logic->FireTimer() >= 20;}}), + Entrance(RR_FIRE_TEMPLE_MQ_ELEVATOR_ROOM, {[]{return logic->CanUse(RG_GORON_TUNIC) && logic->SmallKeys(RR_FIRE_TEMPLE, 2);}}), + Entrance(RR_FIRE_TEMPLE_MQ_TORCH_FIREWALL_ROOM, {[]{return logic->HasFireSource() && ((logic->CanUse(RG_FAIRY_BOW) && logic->FireTimer() >= 25) || (ctx->GetTrickOption(RT_FIRE_MQ_BK_CHEST) && logic->FireTimer() >= 50)) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && ctx->GetTrickOption(RT_FIRE_SOT)));}}), +}); + + areaTable[RR_FIRE_TEMPLE_MQ_TORCH_FIREWALL_ROOM] = Region("Fire Temple MQ Torch Firewall Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->FairyPot, {[]{return logic->CanUse(RG_HOOKSHOT);}}), + }, { + //Locations + LOCATION(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_HOOKSHOT)), + }, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, {[]{return true;}}), +}); + +//This room assumes Goron Tunic until looser tunic requirements tricks are made + areaTable[RR_FIRE_TEMPLE_MQ_ELEVATOR_ROOM] = Region("Fire Temple MQ Elevator Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_BIG_TORCH_ROOM, {[]{return true;}}), +}); + + areaTable[RR_FIRE_TEMPLE_MQ_BIG_TORCH_ROOM] = Region("Fire Temple MQ Big Torch Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return (logic->HasFireSource() && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_FIRE_MQ_CLIMB) && logic->CanUse(RG_HOVER_BOOTS));}}), + Entrance(RR_FIRE_TEMPLE_MQ_ELEVATOR_ROOM, {[]{return logic->CanUse(RG_GORON_TUNIC);}}), + Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT_CAGE, {[]{return logic->OpenedUpperFireShortcut;}}), +}); areaTable[RR_FIRE_TEMPLE_MQ_LOWER_MAZE] = Region("Fire Temple MQ Lower Maze", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)), - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_FIRE_MQ_MAZE_SIDE_ROOM) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER_MAZE))), - //Trick: logic->HasExplosives() && (LogicFireMQMazeSideRoom || FIRE_TEMPLE_MQ_UPPER_MAZE.Adult()) + //Check handled on both floors + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, logic->HasExplosives() && ctx->GetTrickOption(RT_FIRE_MQ_MAZE_SIDE_ROOM)), }, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return (logic->IsAdult && ((logic->HasExplosives() && logic->CanUse(RG_HOOKSHOT)) || (ctx->GetTrickOption(RT_FIRE_MQ_MAZE_HOVERS) && logic->CanUse(RG_HOVER_BOOTS)))) || ctx->GetTrickOption(RT_FIRE_MQ_MAZE_JUMP);}}), - //Trick: (logic->IsAdult && ((logic->HasExplosives() && logic->CanUse(RG_HOOKSHOT)) || (LogicFireMQMazeHovers && logic->CanUse(RG_HOVER_BOOTS)))) || LogicFireMQMazeJump + Entrance(RR_FIRE_TEMPLE_MQ_BIG_TORCH_ROOM, {[]{return 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_LOWER_MAZE_CRATE_CAGE, {[]{return Here(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{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_UPPER_MAZE, {[]{return logic->HasExplosives() && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOOKSHOT);}}), }); - areaTable[RR_FIRE_TEMPLE_MQ_UPPER_MAZE] = Region("Fire Temple MQ Upper Maze", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { - //Events - //EventAccess(&WallFairy, {[]{return WallFairy || (logic->IsAdult && (((logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_HOOKSHOT) && logic->HasExplosives()) || logic->CanUse(RG_LONGSHOT))));}}), - EventAccess(&logic->FairyPot, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 3);}}), - }, { + areaTable[RR_FIRE_TEMPLE_MQ_LOWER_MAZE_CRATE_CAGE] = Region("Fire Temple MQ Lower Maze Crate Cage", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, true), - LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, logic->HasExplosives()), - LOCATION(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, logic->IsAdult && ((logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_HOOKSHOT) && logic->HasExplosives()) || logic->CanUse(RG_LONGSHOT))), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, true), + }, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return 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_MAZE, {[]{return logic->IsAdult && ((ctx->GetTrickOption(RT_FIRE_MQ_MAZE_HOVERS) && logic->CanUse(RG_HOVER_BOOTS)) || ctx->GetTrickOption(RT_FIRE_MQ_MAZE_JUMP));}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_UPPER_MAZE] = Region("Fire Temple MQ Upper Maze", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return true;}}), + //this cage is much more lenient than the lower cage as the switch is close to the front. sling, rang and bow all hit the switch easily, though might be too unintuitive for default logic + //This shouldn't come up in most cases anyway as most methods to get here need either a melee weapon or explosives + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE_BOX_CAGE, {[]{return Here(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return logic->CanJumpslash() || logic->HasExplosives();}});}}), + Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT, {[]{return logic->HasExplosives();}}), + //Implies RR_FIRE_TEMPLE_MQ_LOWER_MAZE access + Entrance(RR_FIRE_TEMPLE_MQ_BURNING_BLOCK_CLIMB, {[]{return logic->HasExplosives() && logic->CanUse(RG_MEGATON_HAMMER) && (logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SONG_OF_TIME)));}}), + Entrance(RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 3) && logic->CanUse(RG_GORON_TUNIC);}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_UPPER_MAZE_BOX_CAGE] = Region("Fire Temple MQ Upper Maze Box Cage", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, true), + //Assumes maze access + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, logic->HasExplosives()), }, { //Exits - Entrance(RR_FIRE_TEMPLE_MQ_UPPER, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 3) && logic->IsAdult && ((logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_HOOKSHOT)) || logic->CanUse(RG_FIRE_ARROWS));}}), + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return true;}}), }); - areaTable[RR_FIRE_TEMPLE_MQ_UPPER] = Region("Fire Temple MQ Upper", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + areaTable[RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT] = Region("Fire Temple MQ Maze Shortcut", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->OpenedUpperFireShortcut, {[]{return logic->CanUse(RG_MEGATON_HAMMER);}}), + }, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT_CAGE, {[]{return logic->OpenedUpperFireShortcut;}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT_CAGE] = Region("Fire Temple MQ Maze Shortcut Cage", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, logic->OpenedUpperFireShortcut;), + }, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT, {[]{return logic->OpenedUpperFireShortcut;}}), + Entrance(RR_FIRE_TEMPLE_MQ_BIG_TORCH_ROOM, {[]{return logic->OpenedUpperFireShortcut;}}), + }); + + + areaTable[RR_FIRE_TEMPLE_MQ_BURNING_BLOCK_CLIMB] = Region("Fire Temple MQ Burning Block Climb", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { + //Events + //EventAccess(&WallFairy, {[]{return logic->CanUse(RG_HOOKSHOT);}}), + }, { + //Locations + //There's definitely ways to do this hammerless, but with one points on it's a trick + LOCATION(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_MEGATON_HAMMER)), + }, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_NARROW_PATH_ROOM, {[]{return logic->TakeDamage();}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_NARROW_PATH_ROOM] = Region("Fire Temple MQ Narrow Path Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->FairyPot, {[]{return true;}}), + }, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, {[]{return logic->TakeDamage();}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM] = Region("Fire Temple MQ High Torch Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 3);}}), + Entrance(RR_FIRE_TEMPLE_MQ_NARROW_PATH_ROOM, {[]{return true;}}), + //Child has issues navigating the higher points of this room without an equip swapped hookshot + Entrance(RR_FIRE_TEMPLE_MQ_SOUTH_FIRE_MAZE, {[]{return Here(RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM, {[]{return logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_HOOKSHOT));}}) && + (logic->IsAdult || logic->CanUse(RG_HOOKSHOT));}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_SOUTH_FIRE_MAZE] = Region("Fire Temple MQ South Fire Maze", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, ((logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG)) && logic->CanUse(RG_HOOKSHOT)) || ctx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE)), - //Trick: (logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze - LOCATION(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, ((logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || ctx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE)) && logic->SmallKeys(RR_FIRE_TEMPLE, 4)), - //Trick: ((logic->IsAdult && logic->CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze) && logic->SmallKeys(RR_FIRE_TEMPLE, 4) - LOCATION(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE)), - //Trick: logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_HOVER_BOOTS) || LogicFireMQFlameMaze LOCATION(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, logic->HasExplosives()), - LOCATION(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, (logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_FIRE_TEMPLE, 5)) || (ctx->GetTrickOption(RT_FIRE_MQ_ABOVE_MAZE_GS) && logic->IsAdult && logic->CanUse(RG_LONGSHOT))), - //Trick: (logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && logic->SmallKeys(RR_FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && logic->IsAdult && logic->CanUse(RG_LONGSHOT)) - }, {}); + }, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_DOOR, {[]{return logic->HitFireTemplePlatform;}}), + Entrance(RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS, {[]{return logic->IsAdult || logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_HOVER_BOOTS);}}), + //Hover boots get there via the platforms + Entrance(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_SIDE_ROOM, {[]{return (bool)ctx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}), + Entrance(RR_FIRE_TEMPLE_MQ_NORTH_FIRE_MAZE, {[]{return logic->OpenedFireMQFireMazeDoor;}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS] = Region("Fire Temple MQ Fire Maze Platforms", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->HitFireTemplePlatform, {[]{return logic->CanUse(RG_MEGATON_HAMMER);}}), + EventAccess(&logic->OpenedFireMQFireMazeDoor, {[]{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOOKSHOT);}}), + }, {}, { + Entrance(RR_FIRE_TEMPLE_MQ_SOUTH_FIRE_MAZE, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_SIDE_ROOM, {[]{return logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_HOVER_BOOTS);}}), + //trick to get to RR_FIRE_TEMPLE_MQ_NORTH_FIRE_MAZE with hovers + taking damage is plausible + }); + + areaTable[RR_FIRE_TEMPLE_MQ_FIRE_MAZE_SIDE_ROOM] = Region("Fire Temple MQ Side Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), + }, { + //Exits + Entrance(RR_FIRE_TEMPLE_MQ_SOUTH_FIRE_MAZE, {[]{return logic->IsAdult || ctx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}), + Entrance(RR_FIRE_TEMPLE_MQ_NORTH_FIRE_MAZE, {[]{return (bool)ctx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_NORTH_FIRE_MAZE] = Region("Fire Temple MQ North Fire Maze", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { + Entrance(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PAST_WALL, {[]{return true;}}), + Entrance(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_SIDE_ROOM, {[]{return (bool)ctx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}), + }); + +//this area exists for the pots in case we void warp to the top of fire somehow, because there's no way to get back the way we came + areaTable[RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PAST_WALL] = Region("Fire Temple MQ Fire Maze Past Wall", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, { + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER, {[]{return true;}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER] = Region("Fire Temple MQ North Fire Maze", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, logic->CanKillEnemy(RE_FLARE_DANCER)), + }, { + Entrance(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PAST_WALL, {[]{return logic->CanKillEnemy(RE_FLARE_DANCER);}}), + Entrance(RR_FIRE_TEMPLE_MQ_SCARECROW_ROOM, {[]{return logic->CanKillEnemy(RE_FLARE_DANCER) && logic->SmallKeys(RR_FIRE_TEMPLE, 4);}}), + }); + + areaTable[RR_FIRE_TEMPLE_MQ_SCARECROW_ROOM] = Region("Fire Temple MQ Scarecrow Room", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + //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->CanUse(RG_SCARECROW)), + }, { + //The dropdown here is unusual in that it hits 1 of 3 locations: RR_FIRE_TEMPLE_MQ_SOUTH_FIRE_MAZE, RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS and the section of RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS with the hammer switch + //Using this dropdown is in N64 logic elsewhere, but not here, probably because it requires good foreknowlege to determine where to land + //This would be a logical method to reach the hammer switch without hookshot, but it practically requires access to the area that switch unlocks already. It could also be first child access to PLATFORMS if tricks ever enable that + //If a practical use for this drop is found, it should be made a trick + Entrance(RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER, {[]{return logic->SmallKeys(RR_FIRE_TEMPLE, 4);}}), + Entrance(RR_FIRE_TEMPLE_MQ_COLLAPSED_STAIRS, {[]{return Here(RR_FIRE_TEMPLE_MQ_SCARECROW_ROOM, {[]{return logic->CanUse(RG_MEGATON_HAMMER);}}) && logic->SmallKeys(RR_FIRE_TEMPLE, 5);}}), + }); + + //The peg knocked down from here could have logical implications for child in the fire maze if tricks to gain height like bomb jumps exist + areaTable[RR_FIRE_TEMPLE_MQ_COLLAPSED_STAIRS] = Region("Fire Temple MQ Collapsed Stairs", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + //If someone manages to make a trick to get here from fire maze, this needs to be in a separate room as the door back is barred + LOCATION(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_MAZE, logic->CanUse(RG_HOOKSHOT)), + }, { + Entrance(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS, {[]{return logic->CanUse(RG_HOOKSHOT) && Here(RR_FIRE_TEMPLE_MQ_COLLAPSED_STAIRS, {[]{return logic->CanUse(RG_MEGATON_HAMMER);}});}}), + Entrance(RR_FIRE_TEMPLE_MQ_SCARECROW_ROOM, {[]{return logic->IsAdult && logic->CanUse(RG_HOOKSHOT);}}), + }); } /*--------------------------- @@ -400,7 +627,7 @@ void RegionTable_Init_FireTemple() { { // Exits Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, { [] { return ctx->GetDungeon(FIRE_TEMPLE)->IsVanilla() && false; } }), - Entrance(RR_FIRE_TEMPLE_MQ_LOWER, { [] { return ctx->GetDungeon(FIRE_TEMPLE)->IsMQ() && false; } }), + Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_DOOR, { [] { return ctx->GetDungeon(FIRE_TEMPLE)->IsMQ() && false; } }), Entrance(RR_FIRE_TEMPLE_BOSS_ROOM, { [] { return true; } }), }); diff --git a/soh/soh/Enhancements/randomizer/dungeon.cpp b/soh/soh/Enhancements/randomizer/dungeon.cpp index cbbb39b28..9998e17da 100644 --- a/soh/soh/Enhancements/randomizer/dungeon.cpp +++ b/soh/soh/Enhancements/randomizer/dungeon.cpp @@ -368,7 +368,7 @@ Dungeons::Dungeons() { RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, - RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, + RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_MAZE, RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index d5bea5cf6..bc7eb2702 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -687,7 +687,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_FIRE_TEMPLE_GS_BOULDER_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, RCQUEST_VANILLA, SCENE_FIRE_TEMPLE, 9220, 0x04, "GS Boulder Maze", RHT_FIRE_TEMPLE_GS_BOULDER_MAZE); locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_TOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, RCQUEST_VANILLA, SCENE_FIRE_TEMPLE, 9224, 0x08, "GS Scarecrow Top", RHT_FIRE_TEMPLE_GS_SCARECROW_TOP); locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, RCQUEST_VANILLA, SCENE_FIRE_TEMPLE, 9232, 0x10, "GS Scarecrow Climb", RHT_FIRE_TEMPLE_GS_SCARECROW_CLIMB); - locationTable[RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, RCQUEST_MQ, SCENE_FIRE_TEMPLE, 9218, 0x02, "MQ GS Above Fire Wall Maze", RHT_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_MAZE, RCQUEST_MQ, SCENE_FIRE_TEMPLE, 9218, 0x02, "MQ GS Above Fire Wall Maze", RHT_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE); locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, RCQUEST_MQ, SCENE_FIRE_TEMPLE, 9224, 0x08, "MQ GS Fire Wall Maze Center", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER); locationTable[RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, RCQUEST_MQ, SCENE_FIRE_TEMPLE, 9217, 0x01, "MQ GS Big Lava Room Open Door", RHT_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR); locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, RCQUEST_MQ, SCENE_FIRE_TEMPLE, 9232, 0x10, "MQ GS Fire Wall Maze Side Room", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM); diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 7d2bb308e..514dcad98 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -232,6 +232,7 @@ namespace Rando { } //Can the passed in item be used? + //RANDOTODO catch magic items explicitly and add an assert on miss. bool Logic::CanUse(RandomizerGet itemName) { if (!HasItem(itemName)) return false; @@ -420,7 +421,8 @@ namespace Rando { return false; } - bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance) { +//RANDOTODO quantity is a placeholder for proper ammo use calculation logic. in time will want updating to account for ammo capacity + bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, uint8_t quantity) { bool killed = false; switch(enemy) { case RE_GOLD_SKULLTULA: @@ -465,6 +467,23 @@ namespace Rando { return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || (CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_CHILD_DEADHAND)); case RE_WITHERED_DEKU_BABA: return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_BOOMERANG); + case RE_LIKE_LIKE: + return CanDamage(); + case RE_STALFOS: + //RANDOTODO Add trick to kill stalfos with sticks, and a second one for bombs without stunning. Higher ammo logic for bombs is also plausible + return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_FAIRY_BOW) || CanUse(RG_BOMBCHU_5) || + (quantity <= 2 && (CanUse(RG_NUTS) || HookshotOrBoomerang()) && CanUse(RG_BOMB_BAG)) || (quantity <= 1 && CanUse(RG_STICKS)); + //Needs 16 bombs, but is in default logic in N64, probably because getting the hits is quite easy. + //bow and sling can wake them and damage after they shed their armour, so could reduce ammo requirements for explosives to 10. + //requires 8 sticks to kill so would be a trick unless we apply higher stick bag logic + case RE_IRON_KNUCKLE: + return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MEGATON_HAMMER) || HasExplosives(); + //To stun flare dancer with chus, you have to hit the flame under it while it is spinning. It should eventually return to spinning after dashing for a while if you miss the window + //it is possible to damage the core with explosives, but difficult to get all 4 hits in even with chus, and if it reconstructs the core heals, so it would be a trick. + //the core takes damage from hookshot even if it doesn't show + //Dins killing isn't hard, but is obscure and tight on single magic, so is a trick + case RE_FLARE_DANCER: + return CanUse(RG_MEGATON_HAMMER) || CanUse(RG_HOOKSHOT) || (HasExplosives() && (CanJumpslashExceptHammer() || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG))); default: SPDLOG_ERROR("CanKillEnemy reached `default`."); assert(false); @@ -490,10 +509,16 @@ namespace Rando { case RE_DEAD_HAND: case RE_DEKU_BABA: case RE_WITHERED_DEKU_BABA: + case RE_STALFOS: + case RE_FLARE_DANCER: return true; case RE_BIG_SKULLTULA: //hammer jumpslash can pass, but only on flat land where you can kill with hammer swing return CanUse(RG_NUTS) || CanUse(RG_BOOMERANG); + case RE_LIKE_LIKE: + return CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG); + case RE_IRON_KNUCKLE: + return false; default: SPDLOG_ERROR("CanPassEnemy reached `default`."); assert(false); @@ -514,6 +539,10 @@ namespace Rando { case RE_DEAD_HAND: case RE_DEKU_BABA: case RE_WITHERED_DEKU_BABA: + case RE_LIKE_LIKE: + case RE_STALFOS: + case RE_IRON_KNUCKLE: + case RE_FLARE_DANCER: return true; case RE_MAD_SCRUB: case RE_KEESE: @@ -1843,6 +1872,10 @@ namespace Rando { ClearedMQDekuSERoom = false; MQDekuWaterRoomTorches = false; PushedDekuBasementBlock = false; + OpenedLowestGoronCage = false; + OpenedUpperFireShortcut = false; + HitFireTemplePlatform = false; + OpenedFireMQFireMazeDoor = false; StopPerformanceTimer(PT_LOGIC_RESET); } diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 0e8a98875..3e22d5889 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -140,6 +140,10 @@ class Logic { bool ClearedMQDekuSERoom = false; bool MQDekuWaterRoomTorches = false; bool PushedDekuBasementBlock = false; + bool OpenedLowestGoronCage = false; + bool OpenedUpperFireShortcut = false; + bool HitFireTemplePlatform = false; + bool OpenedFireMQFireMazeDoor = false; /* --- END OF HELPERS AND LOCATION ACCESS --- */ @@ -153,7 +157,7 @@ class Logic { bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched); bool CanDoGlitch(GlitchType glitch); bool CanEquipSwap(RandomizerGet itemName); - bool CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE); + bool CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, uint8_t quantity = 1); bool CanPassEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE); bool CanAvoidEnemy(RandomizerEnemy enemy); bool CanGetEnemyDrop(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool aboveLink = false); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index ee3ae9d52..e5c4dee41 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -672,12 +672,36 @@ typedef enum { RR_FIRE_TEMPLE_HAMMER_RETURN_PATH, RR_FIRE_TEMPLE_ABOVE_FIRE_MAZE, - RR_FIRE_TEMPLE_MQ_LOWER, - RR_FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR, + RR_FIRE_TEMPLE_MQ_FIRST_ROOM_LOWER, + RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, + RR_FIRE_TEMPLE_MQ_MAP_ROOM_SOUTH, + RR_FIRE_TEMPLE_MQ_STALFOS_ROOM, + RR_FIRE_TEMPLE_MQ_IRON_KNUCKLE_ROOM, + RR_FIRE_TEMPLE_MQ_LOWER_FLARE_DANCER, + RR_FIRE_TEMPLE_MQ_MAP_ROOM_NORTH, + RR_FIRE_TEMPLE_MQ_MAP_ROOM_CAGE, + RR_FIRE_TEMPLE_MQ_NEAR_BOSS_DOOR, RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, + RR_FIRE_TEMPLE_MQ_TORCH_FIREWALL_ROOM, + RR_FIRE_TEMPLE_MQ_ELEVATOR_ROOM, + RR_FIRE_TEMPLE_MQ_BIG_TORCH_ROOM, RR_FIRE_TEMPLE_MQ_LOWER_MAZE, + RR_FIRE_TEMPLE_MQ_LOWER_MAZE_CRATE_CAGE, RR_FIRE_TEMPLE_MQ_UPPER_MAZE, - RR_FIRE_TEMPLE_MQ_UPPER, + RR_FIRE_TEMPLE_MQ_UPPER_MAZE_BOX_CAGE, + RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT, + RR_FIRE_TEMPLE_MQ_MAZE_SHORTCUT_CAGE, + RR_FIRE_TEMPLE_MQ_BURNING_BLOCK_CLIMB, + RR_FIRE_TEMPLE_MQ_NARROW_PATH_ROOM, + RR_FIRE_TEMPLE_MQ_HIGH_TORCH_ROOM, + RR_FIRE_TEMPLE_MQ_SOUTH_FIRE_MAZE, + RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PLATFORMS, + RR_FIRE_TEMPLE_MQ_FIRE_MAZE_SIDE_ROOM, + RR_FIRE_TEMPLE_MQ_NORTH_FIRE_MAZE, + RR_FIRE_TEMPLE_MQ_FIRE_MAZE_PAST_WALL, + RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER, + RR_FIRE_TEMPLE_MQ_SCARECROW_ROOM, + RR_FIRE_TEMPLE_MQ_COLLAPSED_STAIRS, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, RR_FIRE_TEMPLE_BOSS_ROOM, @@ -1371,7 +1395,7 @@ typedef enum { RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, - RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, + RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_MAZE, RC_FIRE_TEMPLE_VOLVAGIA_HEART, RC_WATER_TEMPLE_COMPASS_CHEST, RC_WATER_TEMPLE_MAP_CHEST, @@ -4419,6 +4443,10 @@ typedef enum { RE_DEAD_HAND, RE_DEKU_BABA, RE_WITHERED_DEKU_BABA, + RE_LIKE_LIKE, + RE_STALFOS, + RE_IRON_KNUCKLE, + RE_FLARE_DANCER, } RandomizerEnemy; typedef enum { diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 80d09a6d6..38da8936b 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -424,6 +424,7 @@ void Settings::CreateOptions() { // mTrickOptions[RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::INTERMEDIATE}, false, "Forest Temple MQ Twisted Hallway Switch with Hookshot", "There's a very small gap between the glass block and the wall. Through that gap you can hookshot the target on the ceiling."); mTrickOptions[RT_FOREST_MQ_RANG_HALLWAY_SWITCH] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::INTERMEDIATE}, false, "Forest Temple MQ Twisted Hallway Switch with Boomerang", "The Boomerang can return to Link through walls, allowing child to hit the hallway switch. This can be used to allow adult to pass through later, or in conjuction with \"Forest Temple Outside Backdoor with Jump Slash\"."); mTrickOptions[RT_FIRE_BOSS_DOOR_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, false, "Fire Temple Boss Door without Hover Boots or Pillar", "The Fire Temple Boss Door can be reached as adult with a precise jump. You must be touching the side wall of the room so that Link will grab the ledge from farther away than is normally possible."); + //Is also used in MQ logic, but has no practical effect there as of now mTrickOptions[RT_FIRE_SOT] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, false, "Fire Temple Song of Time Room GS without Song of Time", "A precise jump can be used to reach this room."); mTrickOptions[RT_FIRE_STRENGTH] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, false, "Fire Temple Climb without Strength", "A precise jump can be used to skip pushing the block."); mTrickOptions[RT_FIRE_SCARECROW] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::EXPERT}, false, "Fire Temple East Tower without Scarecrow\'s Song", "Also known as \"Pixelshot\". The Longshot can reach the target on the elevator itself, allowing you to skip needing to spawn the scarecrow.");