From 0a3eeb8339243aa8f173e679d513c97949df45e7 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Sat, 5 Oct 2024 21:29:38 +0100 Subject: [PATCH] Rewrite DC MQ Logic (#4355) * Doodongs Cavern * rewrite MQ DC Logic * forgot some cleanup * remove an unused region * post-merge cleanups * change CanUse for HasITem on gorons braclet * git ate half the rewrite * more small error fixes --------- Co-authored-by: aMannus --- .../randomizer/3drando/location_access.cpp | 4 +- .../randomizer/3drando/location_access.hpp | 4 +- .../location_access/locacc_castle_town.cpp | 6 +- .../location_access/locacc_death_mountain.cpp | 4 +- .../locacc_dodongos_cavern.cpp | 231 +++++++++++++++--- .../location_access/locacc_gerudo_valley.cpp | 2 +- .../location_access/locacc_hyrule_field.cpp | 2 +- .../location_access/locacc_kakariko.cpp | 2 +- .../location_access/locacc_lost_woods.cpp | 10 +- .../location_access/locacc_zoras_domain.cpp | 6 +- soh/soh/Enhancements/randomizer/logic.cpp | 113 +++++++-- soh/soh/Enhancements/randomizer/logic.h | 14 +- .../Enhancements/randomizer/randomizerTypes.h | 39 ++- 13 files changed, 361 insertions(+), 76 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp index a22383386..e15245d13 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp @@ -215,7 +215,7 @@ void Region::ResetVariables() { std::array areaTable; bool Here(const RandomizerRegion region, ConditionFn condition) { - return areaTable[region].HereCheck(condition); + return areaTable[region].Here(condition); } bool CanPlantBean(const RandomizerRegion region) { @@ -246,7 +246,7 @@ void RegionTable_Init() { ctx = Context::GetInstance().get(); logic = ctx->GetLogic(); //RANDOTODO do not hardcode, instead allow accepting a Logic class somehow grottoEvents = { - EventAccess(&logic->GossipStoneFairy, { [] { return logic->GossipStoneFairy || logic->CallGossipFairy(); } }), + EventAccess(&logic->GossipStoneFairy, { [] { return logic->CallGossipFairy(); } }), EventAccess(&logic->ButterflyFairy, { [] { return logic->ButterflyFairy || (logic->CanUse(RG_STICKS)); } }), EventAccess(&logic->BugShrub, { [] { return logic->CanCutShrubs(); } }), EventAccess(&logic->LoneFish, { [] { return true; } }), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp index 3a257ca0f..2b18ab029 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.hpp @@ -210,7 +210,7 @@ public: //access to this area. For example: if there are rocks that block a path //which both child and adult can access, adult having hammer can give //both child and adult access to the path. - bool HereCheck(ConditionFn condition) { + bool Here(ConditionFn condition) { //store current age variables bool pastAdult = logic->IsAdult; @@ -246,7 +246,7 @@ public: extern std::array areaTable; extern std::vector grottoEvents; -bool Here(const RandomizerRegion region, ConditionFn condition); +bool Here(const RandomizerRegion region, ConditionFn condition); //RANDOTODO make a less stupid way to check own at either age than self referncing with this bool CanPlantBean(const RandomizerRegion region); bool BothAges(const RandomizerRegion region); bool ChildCanAccess(const RandomizerRegion region); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp index 868e231ae..74059abc8 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp @@ -35,7 +35,7 @@ void RegionTable_Init_CastleTown() { areaTable[RR_TOT_ENTRANCE] = Region("ToT Entrance", "ToT Entrance", RA_THE_MARKET, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairyExceptSuns();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairyExceptSuns();}}), }, { //Locations LOCATION(RC_TOT_LEFTMOST_GOSSIP_STONE, true), @@ -82,7 +82,7 @@ void RegionTable_Init_CastleTown() { areaTable[RR_HYRULE_CASTLE_GROUNDS] = Region("Hyrule Castle Grounds", "Castle Grounds", RA_HYRULE_CASTLE, DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairy();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairy();}}), EventAccess(&logic->ButterflyFairy, {[]{return logic->ButterflyFairy || logic->CanUse(RG_STICKS);}}), EventAccess(&logic->BugRock, {[]{return true;}}), }, { @@ -121,7 +121,7 @@ void RegionTable_Init_CastleTown() { areaTable[RR_HC_STORMS_GROTTO] = Region("HC Storms Grotto", "HC Storms Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&logic->NutPot, {[]{return logic->NutPot || logic->BlastOrSmash();}}), - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || (logic->BlastOrSmash() && logic->CallGossipFairy());}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CanBreakMudWalls() && logic->CallGossipFairy();}}), EventAccess(&logic->WanderingBugs, {[]{return logic->WanderingBugs || logic->BlastOrSmash();}}), }, { //Locations diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp index 630017585..b61687d3d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp @@ -26,7 +26,7 @@ void RegionTable_Init_DeathMountain() { areaTable[RR_DEATH_MOUNTAIN_SUMMIT] = Region("Death Mountain Summit", "Death Mountain", RA_DEATH_MOUNTAIN_TRAIL, DAY_NIGHT_CYCLE, { //Events EventAccess(&logic->PrescriptionAccess, {[]{return logic->PrescriptionAccess || (logic->IsAdult && (logic->BrokenSwordAccess || logic->CanUse(RG_BROKEN_SWORD)));}}), - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairy();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairy();}}), EventAccess(&logic->BugRock, {[]{return logic->BugRock || logic->IsChild;}}), }, { //Locations @@ -81,7 +81,7 @@ void RegionTable_Init_DeathMountain() { areaTable[RR_GORON_CITY] = Region("Goron City", "Goron City", RA_GORON_CITY, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairyExceptSuns();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairyExceptSuns();}}), EventAccess(&logic->StickPot, {[]{return logic->StickPot || logic->IsChild;}}), EventAccess(&logic->BugRock, {[]{return logic->BugRock || (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS));}}), EventAccess(&logic->GoronCityChildFire, {[]{return logic->GoronCityChildFire || (logic->IsChild && logic->CanUse(RG_DINS_FIRE));}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp index 5274ea2e3..3826dc7a0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp @@ -22,17 +22,17 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BEGINNING] = Region("Dodongos Cavern Beginning", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, {[]{return true;}}), - Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return Here(RR_DODONGOS_CAVERN_BEGINNING, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}}), + Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return Here(RR_DODONGOS_CAVERN_BEGINNING, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);});}}), }); areaTable[RR_DODONGOS_CAVERN_LOBBY] = Region("Dodongos Cavern Lobby", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || (logic->CallGossipFairy() && Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);}));}}), + EventAccess(&logic->GossipStoneFairy, {[]{return (Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls();}) || logic->HasItem(RG_GORONS_BRACELET)) && logic->CallGossipFairy();}}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);})), + LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);})), LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, logic->CanStunDeku() || logic->HasItem(RG_GORONS_BRACELET)), - LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);})), + LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);})), }, { //Exits Entrance(RR_DODONGOS_CAVERN_BEGINNING, {[]{return true;}}), @@ -219,60 +219,219 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_LOBBY] = Region("Dodongos Cavern MQ Lobby", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->DekuBabaSticks, {[]{return logic->DekuBabaSticks || (logic->IsAdult || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BOOMERANG));}}), - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairy();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return (Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls();}) || logic->CanUse(RG_GORONS_BRACELET)) && logic->CallGossipFairy();}}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, true), - LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, logic->CanAttack() || logic->CanUse(RG_NUTS)), - LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, (logic->IsChild && logic->CanUse(RG_STICKS)) || logic->HasFireSource()), - LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, logic->BlastOrSmash() || (logic->IsChild && logic->CanUse(RG_STICKS)) || logic->CanUse(RG_DINS_FIRE) || (logic->IsAdult && (ctx->GetTrickOption(RT_DC_JUMP) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)))), - LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, logic->CanUse(RG_SONG_OF_TIME) && logic->CanAttack()), - LOCATION(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, (logic->IsChild && logic->CanUse(RG_STICKS)) || logic->HasFireSource()), - LOCATION(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, logic->BlastOrSmash()), - LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku()), - LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku()), - LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, logic->CanStunDeku()), - LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, logic->CanBreakMudWalls() || logic->CanUse(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku()), + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku()), + LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls() || logic->CanUse(RG_GORONS_BRACELET);})), }, { //Exits - Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || (((logic->IsChild && logic->CanUse(RG_STICKS)) || logic->CanUse(RG_DINS_FIRE)) && logic->TakeDamage());});}}), - Entrance(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return logic->IsAdult || (Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->IsAdult;}) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_DC_MQ_CHILD_BOMBS) && logic->CanJumpslash() && logic->TakeDamage());}}), - //Trick: logic->IsAdult || logic->HasExplosives() || (LogicDCMQChildBombs && (logic->CanUse(RG_KOKIRI_SWORD) || logic->Sticks) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO)) - Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, {[]{return logic->HasExplosives() || (logic->HasItem(RG_GORONS_BRACELET) && ((logic->IsAdult && ctx->GetTrickOption(RT_DC_MQ_ADULT_EYES)) || (logic->IsChild && ctx->GetTrickOption(RT_DC_MQ_CHILD_EYES))) && ((logic->IsChild && (logic->CanUse(RG_STICKS))) || logic->CanUse(RG_DINS_FIRE) || (logic->IsAdult && (ctx->GetTrickOption(RT_DC_JUMP) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT)))));}}), - //Trick: logic->HasExplosives() || (LogicDCMQEyes && logic->HasItem(RG_GORONS_BRACELET) && (logic->IsAdult || LogicDCMQChildBack) && ((logic->IsChild && logic->CanUse(RG_STICKS)) || logic->CanUse(RG_DINS_FIRE) || (logic->IsAdult && (LogicDCJump || logic->Hammer || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))))) + Entrance(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->CanUse(RG_GORONS_BRACELET);});}}), + Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->CanUse(RG_GORONS_BRACELET);});}}), + Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls();}) || + Here(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, []{return logic->HasItem(RG_GORONS_BRACELET) && logic->TakeDamage();});}}), //strength 1 and bunny speed works too + Entrance(RR_DODONGOS_CAVERN_MQ_POES_ROOM, {[]{return logic->IsAdult;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, {[]{return Here(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, []{return logic->HasExplosives() || (logic->ClearMQDCUpperLobbyRocks && logic->HasItem(RG_GORONS_BRACELET) && + ((logic->IsAdult && ctx->GetTrickOption(RT_DC_MQ_ADULT_EYES)) || + (logic->IsChild && ctx->GetTrickOption(RT_DC_MQ_CHILD_EYES))));});}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE] = Region("Dodongos Cavern MQ Mouth Side Bridge", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->ClearMQDCUpperLobbyRocks, {[]{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}}), + }, {}, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, {[]{return logic->ClearMQDCUpperLobbyRocks;}}), + //Bunny hood jump + jumpslash can also make it directly from the raising platform + Entrance(RR_DODONGOS_CAVERN_MQ_POES_ROOM, {[]{return logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_DC_MQ_CHILD_BOMBS) && logic->CanJumpslash() && 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 + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER] = Region("Dodongos Cavern MQ Stairs Lower", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { + //Events + //EventAccess(&logic->CanClimbDCStairs, {[]{return logic->HasExplosives || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_DC_STAIRCASE) && logic->CanUse(RG_FAIRY_BOW));}}), + }, {}, { + //Exits + //This is possible with sticks and shield, igniting a first flower by "touch" then very quickly crouch stabbing in a way that cuts the corner to light the 3rd bomb on the other side, but that's a trick + Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER, {[]{return Here(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return logic->HasExplosives() || logic->CanUse(RG_DINS_FIRE) || + (ctx->GetTrickOption(RT_DC_STAIRCASE) && logic->CanUse(RG_FAIRY_BOW));});}}), + Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_MUD_WALL, {[]{return Here(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return logic->CanBreakMudWalls();});}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_MUD_WALL] = Region("Dodongos Cavern MQ Stairs Past Mud Wall", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->DekuBabaSticks, {[]{return logic->CanGetDekuBabaSticks();}}), + //EventAccess(&logic->CanClimbDCStairs, {[]{return logic->CanUse(RG_GORONS_BRACELET) && (logic->CanUse(RG_STICKS));}}), + }, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), + }, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER, {[]{return logic->CanUse(RG_GORONS_BRACELET) && (logic->CanUse(RG_STICKS));}}), + Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, {[]{return true;}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER] = Region("Dodongos Cavern MQ Stairs Upper", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, logic->CanStunDeku()), + }, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_BIG_SKULLTULAS, {[]{return logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->CanUse(RG_HOVER_BOOTS);}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_BIG_SKULLTULAS] = Region("Dodongos Cavern MQ Past Big Skulltulas", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER, {[]{return logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->CanUse(RG_HOVER_BOOTS);}}), + Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, {[]{return logic->TakeDamage();}}), + //If some case comes up where you can directly (void?)warp here without going through Dodongo room or climbing up from below, + //the commented out logic is to handle going down and reclimbing to get silver rupees. A new eventVar will need decalring to handle this. + /*(logic->CanPassEnemy(RE_BIG_SKULLTULA) || CanUse(RG_HOVER_BOOTS)) && logic->CanClimbDCStairs;*/ + Entrance(RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM, {[]{return true;}}),//if we add BONKO or other crate logic, logic for silver rupees goes here + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM] = Region("Dodongos Cavern MQ Dodongo Room", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DODONGO) || logic->HasItem(RG_GORONS_BRACELET)), + }, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_BIG_SKULLTULAS, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, {[]{return Here(RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM, []{return logic->CanKillEnemy(RE_DODONGO) || logic->HasItem(RG_GORONS_BRACELET);});}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER] = Region("Dodongos Cavern MQ Torch Puzzle Lower", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->ClearMQDCUpperLobbyRocks, {[]{return (((logic->IsAdult /*or bunny hood jump*/) && ctx->GetTrickOption(RT_DC_JUMP)) || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_STICKS);}}), + }, {}, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, {[]{return logic->TakeDamage();}}), + Entrance(RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM, {[]{return logic->HasFireSourceWithTorch();}}),//torch checks here need strength 0 with sticks when that is implemented + Entrance(RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, []{return logic->HasFireSourceWithTorch();});}}), //Includes an implied CanPass(RE_BIG_SKULLTULA) + Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, {[]{return ((logic->IsAdult /*or bunny hood jump*/) && ctx->GetTrickOption(RT_DC_JUMP)) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}}), + Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, {[]{return logic->CanUse(RG_STICKS) && logic->HasItem(RG_GORONS_BRACELET);}}), //Implies access to RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM from here + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM] = Region("Dodongos Cavern MQ Torch Puzzle Lower", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, {[]{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}}), + Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, {[]{return (logic->HasFireSource() && logic->HasItem(RG_GORONS_BRACELET)) || logic->CanBreakMudWalls();}}), //Requires stregnth 0, If you can somehow warp into this room, add logic->CanPassEnemy(RE_BIG_SKULLTULA) + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM] = Region("Dodongos Cavern MQ Larvae Room", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, true), //implied logic->CanKillEnemy(RE_GOHMA_LARVA) based on entry reqs with a trick to kill with nuts + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, true), //implied logic->CanKillEnemy(RE_GOLD_SKULTULLA) based on entry reqs. Add crate logic when BONKO is added + }, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, {[]{return true;}}), //implied logic->CanKillEnemy(RE_GOHMA_LARVA) based on entry reqs with a trick to kill with nuts + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS] = Region("Dodongos Cavern MQ Before Upper Lizalfos", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, logic->BlastOrSmash()), //Implied CanGetEnemyDrop(RE_GOLD_SKULLTULA) + }, { + //Exits + //Falling down gets you stuck with nothing there, not a useful exit for logic + Entrance(RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS);});}}), + Entrance(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS);});}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM] = Region("Dodongos Cavern MQ Before Upper Lizalfos", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, {[]{return logic->IsAdult || (Here(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, []{return logic->BlastOrSmash() || (logic->CanAttack() && logic->HasItem(RG_GORONS_BRACELET));}));}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER] = Region("Dodongos Cavern MQ Torch Puzzle Upper", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->ClearMQDCUpperLobbyRocks, {[]{return logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER);}}), + }, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, true), + }, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, {[]{return logic->ClearMQDCUpperLobbyRocks;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, {[]{return true;}}), }); areaTable[RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE] = Region("Dodongos Cavern MQ Lower Right Side", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, logic->CanStunDeku()), + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->CanStunDeku()), }, { //Exits - Entrance(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return (Here(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, []{return logic->IsAdult && logic->CanUse(RG_FAIRY_BOW);}) || logic->HasItem(RG_GORONS_BRACELET) || - logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives()) && - logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT);}}), + Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_LIZALFOS, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);}) && logic->CanHitEyeTargets();}}), }); - areaTable[RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA] = Region("Dodongos Cavern MQ Bomb Bag Region", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { + areaTable[RR_DODONGOS_CAVERN_MQ_LOWER_LIZALFOS] = Region("Dodongos Cavern MQ Lower Lizalfos", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { + //When you add wonder item logic for behind the lavafall, use Here(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS) to account for jumping down instead of an exit + //because the doors are sealed when entering from the top and you can't spawn the lower lizalfos + }, {}, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOWER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS);});}}), + Entrance(RR_DODONGOS_CAVERN_MQ_POES_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOWER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS);});}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_POES_ROOM] = Region("Dodongos Cavern MQ Poes Room", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, true), - LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, (Here(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, []{return logic->IsAdult && logic->CanUse(RG_FAIRY_BOW);}) || logic->HasItem(RG_GORONS_BRACELET) || logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives()) && logic->HookshotOrBoomerang()), + LOCATION(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, true), //If you can get to the locked part of POES_ROOM without a way to open it or passing the chest, this will need it's own room + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, (Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);}) && //could be a seperate room if it gets busy + logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_RANG_OR_HOOKSHOT, true))), //Implies you can avoid/kill the enemies with what you use on the skull, if this assumption is broken, add + //&& (Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanKillEnemy(RE_FIRE_KEESE) && logic->CanKillEnemy(RE_MAD_SCRUB);}) || (logic->CanAvoidEnemy(RE_FIRE_KEESE) && logic->CanAvoidEnemy(RE_MAD_SCRUB))) }, { //Exits - Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);});}}), + Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_LIZALFOS, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET);});}}), }); - areaTable[RR_DODONGOS_CAVERN_MQ_BOSS_AREA] = Region("Dodongos Cavern MQ BossArea", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { + areaTable[RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM] = Region("Dodongos Cavern Mad Scrub Room", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_RANG_OR_HOOKSHOT, true))), //Implies you can avoid/kill the enemies with what you use on the skull, if this assumption is broken, add + //&& (Here(RR_DODONGOS_CAVERN_MQ_POES_ROOM, []{return logic->CanKillEnemy(RE_FIRE_KEESE) && logic->CanKillEnemy(RE_MAD_SCRUB);}) || (logic->CanAvoidEnemy(RE_FIRE_KEESE) && logic->CanAvoidEnemy(RE_MAD_SCRUB))) + }, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_POES_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM, []{return logic->CanKillEnemy(RE_FIRE_KEESE) && logic->CanKillEnemy(RE_MAD_SCRUB);});}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH] = Region("Dodongos Cavern MQ Behind Mouth", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, {[]{return true;}}), + //using pots to get past the fire is in default logic. if stregnth 0 gets added, this will need to be: + //stregnth 0 || explosives, or projectiles if str0 isn't needed to pull graves (it's a narrow shot though, may be trick worthy) + Entrance(RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE, {[]{return logic->IsAdult;}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE] = Region("Dodongos Cavern MQ Back Behind Fire", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, true), //pulling the grave isn't required, as you can open the chest through it + }, { + //Exits + Entrance(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, {[]{return logic->CanAttack();}}), + //There's a trick N64 rolls into the child eyes trick for using armos blow up the bomb flowers when dieing, which would be killing an armos + Entrance(RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE, []{return logic->CanDetonateBombFlowers();}) || + Here(RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE, []{return logic->CanAttack();});}}), + }); + + areaTable[RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE] = Region("Dodongos Cavern MQ BossArea", "Dodongos Cavern", RA_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->FairyPot, {[]{return true;}}), + EventAccess(&logic->FairyPot, {[]{return true;}}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, true), - LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) || logic->HasItem(RG_GORONS_BRACELET) || //even if you somehow warp to BACK_BEHIND_FIRE, if you can kill the skull at range, you can get to BEHIND_MOUTH + Here(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, []{return (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_RANG_OR_HOOKSHOT)) || + (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) /* || bunny jumps*/);})), }, { //Exits - Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE, {[]{return true;}}), + Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, {[]{return true;}}), //if strength 0 prevents grave pulls, add it here }); + } /*--------------------------- @@ -283,7 +442,7 @@ void RegionTable_Init_DodongosCavern() { { // Exits Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, { [] { return ctx->GetDungeon(DODONGOS_CAVERN)->IsVanilla(); } }), - Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, { [] { return ctx->GetDungeon(DODONGOS_CAVERN)->IsMQ(); } }), + Entrance(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, { [] { return ctx->GetDungeon(DODONGOS_CAVERN)->IsMQ(); } }), Entrance(RR_DODONGOS_CAVERN_BOSS_ROOM, { [] { return true; } }), }); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp index 601ca03d0..ec9790ed1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp @@ -21,7 +21,7 @@ void RegionTable_Init_GerudoValley() { areaTable[RR_GV_UPPER_STREAM] = Region("GV Upper Stream", "Gerudo Valley", RA_GERUDO_VALLEY, DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairy();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairy();}}), EventAccess(&logic->BeanPlantFairy, {[]{return logic->BeanPlantFairy || (CanPlantBean(RR_GV_UPPER_STREAM) && logic->CanUse(RG_SONG_OF_STORMS));}}), }, { //Locations diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp index 772a7fad2..2e906c7aa 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp @@ -111,7 +111,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_LAKE_HYLIA] = Region("Lake Hylia", "Lake Hylia", RA_LAKE_HYLIA, DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairy();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairy();}}), EventAccess(&logic->BeanPlantFairy, {[]{return logic->BeanPlantFairy || (CanPlantBean(RR_LAKE_HYLIA) && logic->CanUse(RG_SONG_OF_STORMS));}}), EventAccess(&logic->ButterflyFairy, {[]{return logic->ButterflyFairy || logic->CanUse(RG_STICKS);}}), EventAccess(&logic->BugShrub, {[]{return logic->BugShrub || (logic->IsChild && logic->CanCutShrubs());}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp index bec90d866..9475547f7 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp @@ -278,7 +278,7 @@ void RegionTable_Init_Kakariko() { areaTable[RR_GRAVEYARD_WARP_PAD_REGION] = Region("Graveyard Warp Pad Region", "Graveyard", RA_THE_GRAVEYARD, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairyExceptSuns();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairyExceptSuns();}}), }, { //Locations LOCATION(RC_GRAVEYARD_GOSSIP_STONE, true), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp index 72aebe634..39316eea2 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp @@ -7,7 +7,7 @@ void RegionTable_Init_LostWoods() { areaTable[RR_KOKIRI_FOREST] = Region("Kokiri Forest", "Kokiri Forest", RA_KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&logic->BeanPlantFairy, {[]{return logic->BeanPlantFairy || (CanPlantBean(RR_KOKIRI_FOREST) && logic->CanUse(RG_SONG_OF_STORMS));}}), - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairyExceptSuns();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairyExceptSuns();}}), EventAccess(&logic->ShowedMidoSwordAndShield, {[]{return logic->ShowedMidoSwordAndShield || (logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD));}}), }, { //Locations @@ -24,7 +24,7 @@ void RegionTable_Init_LostWoods() { Entrance(RR_KF_HOUSE_OF_TWINS, {[]{return true;}}), Entrance(RR_KF_KNOW_IT_ALL_HOUSE, {[]{return true;}}), Entrance(RR_KF_KOKIRI_SHOP, {[]{return true;}}), - Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return (logic->IsAdult && (logic->CanPassEnemy("Big Skulltula") || logic->ForestTempleClear)) || ctx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield;}}), + Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return (logic->IsAdult && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->ForestTempleClear)) || ctx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield;}}), Entrance(RR_THE_LOST_WOODS, {[]{return true;}}), Entrance(RR_LW_BRIDGE_FROM_FOREST, {[]{return logic->IsAdult || ctx->GetOption(RSK_FOREST).IsNot(RO_FOREST_CLOSED) || logic->DekuTreeClear;}}), Entrance(RR_KF_STORMS_GROTTO, {[]{return logic->CanOpenStormsGrotto();}}), @@ -42,7 +42,7 @@ void RegionTable_Init_LostWoods() { }, { //Exits Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return logic->IsChild || (ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && (ctx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield));}}), - Entrance(RR_KOKIRI_FOREST, {[]{return (logic->IsAdult && (logic->CanPassEnemy("Big Skulltula") || logic->ForestTempleClear)) || ctx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield;}}), + Entrance(RR_KOKIRI_FOREST, {[]{return (logic->IsAdult && (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->ForestTempleClear)) || ctx->GetOption(RSK_FOREST).Is(RO_FOREST_OPEN) || logic->ShowedMidoSwordAndShield;}}), }); areaTable[RR_KF_LINKS_HOUSE] = Region("KF Link's House", "KF Link's House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, { @@ -115,7 +115,7 @@ void RegionTable_Init_LostWoods() { //Events EventAccess(&logic->OddMushroomAccess, {[]{return logic->OddMushroomAccess || (logic->IsAdult && (logic->CojiroAccess || logic->CanUse(RG_COJIRO)));}}), EventAccess(&logic->PoachersSawAccess, {[]{return logic->PoachersSawAccess || (logic->IsAdult && logic->OddPoulticeAccess);}}), - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairyExceptSuns();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairyExceptSuns();}}), EventAccess(&logic->BeanPlantFairy, {[]{return logic->BeanPlantFairy || logic->CanUse(RG_SONG_OF_STORMS);}}), EventAccess(&logic->BugShrub, {[]{return logic->IsChild && logic->CanCutShrubs();}}), }, { @@ -204,7 +204,7 @@ void RegionTable_Init_LostWoods() { areaTable[RR_SACRED_FOREST_MEADOW] = Region("Sacred Forest Meadow", "Sacred Forest Meadow", RA_SACRED_FOREST_MEADOW, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairyExceptSuns();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairyExceptSuns();}}), }, { //Locations LOCATION(RC_SONG_FROM_SARIA, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER)), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp index 40768ffff..07a768fbd 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp @@ -15,7 +15,7 @@ void RegionTable_Init_ZorasDomain() { areaTable[RR_ZORAS_RIVER] = Region("Zora River", "Zora River", RA_ZORAS_RIVER, DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairy();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairy();}}), EventAccess(&logic->BeanPlantFairy, {[]{return logic->BeanPlantFairy || (CanPlantBean(RR_ZORAS_RIVER) && logic->CanUse(RG_SONG_OF_STORMS));}}), EventAccess(&logic->ButterflyFairy, {[]{return logic->ButterflyFairy || logic->CanUse(RG_STICKS);}}), EventAccess(&logic->BugShrub, {[]{return logic->BugShrub || logic->CanCutShrubs();}}), @@ -85,7 +85,7 @@ void RegionTable_Init_ZorasDomain() { areaTable[RR_ZORAS_DOMAIN] = Region("Zoras Domain", "Zoras Domain", RA_ZORAS_DOMAIN, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&logic->EyeballFrogAccess, {[]{return logic->EyeballFrogAccess || (logic->IsAdult && logic->KingZoraThawed && (logic->CanUse(RG_EYEDROPS) || logic->CanUse(RG_EYEBALL_FROG) || logic->CanUse(RG_PRESCRIPTION) || logic->PrescriptionAccess));}}), - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairyExceptSuns();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairyExceptSuns();}}), EventAccess(&logic->NutPot, {[]{return true;}}), EventAccess(&logic->StickPot, {[]{return logic->StickPot || logic->IsChild;}}), EventAccess(&logic->FishGroup, {[]{return logic->FishGroup || logic->IsChild;}}), @@ -149,7 +149,7 @@ void RegionTable_Init_ZorasDomain() { areaTable[RR_ZORAS_FOUNTAIN] = Region("Zoras Fountain", "Zoras Fountain", RA_ZORAS_FOUNTAIN, NO_DAY_NIGHT_CYCLE, { //Events - EventAccess(&logic->GossipStoneFairy, {[]{return logic->GossipStoneFairy || logic->CallGossipFairyExceptSuns();}}), + EventAccess(&logic->GossipStoneFairy, {[]{return logic->CallGossipFairyExceptSuns();}}), EventAccess(&logic->ButterflyFairy, {[]{return logic->ButterflyFairy || (logic->CanUse(RG_STICKS) && logic->AtDay);}}), }, { //Locations diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 3f22f3b0f..07215307f 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -428,25 +428,109 @@ namespace Rando { return false; } - //NOTE, when adding dark link,add Hearts() > 0 - bool Logic::CanKillEnemy(std::string enemy) { - //switch(enemy) {} RANDOTODO implement enemies enum - if (enemy == "Big Skulltula"){ - return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || CanJumpslash() || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE) || HasExplosives(); + bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance) { + switch(enemy) { + case RE_GOLD_SKULLTULA: + case RE_GOHMA_LARVA: + case RE_MAD_SCRUB: + return CanAttack(); + case RE_BIG_SKULLTULA: + return CanDamage() || CanUse(RG_HOOKSHOT); + case RE_DODONGO: + case RE_LIZALFOS: + return CanJumpslash() || HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_MEGATON_HAMMER); + case RE_KEESE: + case RE_FIRE_KEESE: + return CanJumpslash() || HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG); + default: + SPDLOG_ERROR("CanKillEnemy reached `default`."); + assert(false); + return false; } - //Shouldn't be reached - return false; } - bool Logic::CanPassEnemy(std::string enemy) { - //switch(enemy) {} RANDOTODO implement enemies enum + bool Logic::CanPassEnemy(RandomizerEnemy enemy) { if (CanKillEnemy(enemy)){ return true; } - if (enemy == "Big Skulltula"){ - return CanUse(RG_NUTS) || CanUse(RG_BOOMERANG); + switch(enemy) { + case RE_GOLD_SKULLTULA: + case RE_GOHMA_LARVA: + case RE_LIZALFOS: + case RE_DODONGO: //RANDOTODO do dodongos block the way in tight corridors? + case RE_MAD_SCRUB: + case RE_KEESE: + case RE_FIRE_KEESE: + return true; + case RE_BIG_SKULLTULA: + return CanUse(RG_NUTS) || CanUse(RG_BOOMERANG); + default: + SPDLOG_ERROR("CanPassEnemy reached `default`."); + assert(false); + return false; } - return false; + } + + bool Logic::CanAvoidEnemy(RandomizerEnemy enemy) { + if (CanKillEnemy(enemy)){ + return true; + } + switch(enemy) { + case RE_GOLD_SKULLTULA: + case RE_GOHMA_LARVA: + case RE_LIZALFOS: + case RE_DODONGO: //RANDOTODO do dodongos block the way in tight corridors? + case RE_BIG_SKULLTULA: + return true; + case RE_MAD_SCRUB: + case RE_KEESE: + case RE_FIRE_KEESE: + return CanUse(RG_NUTS); + default: + SPDLOG_ERROR("CanPassEnemy reached `default`."); + assert(false); + return false; + } + } + + bool Logic::CanGetEnemyDrop(RandomizerEnemy enemy, EnemyDistance distance, bool aboveLink) { + if (!CanKillEnemy(enemy, distance)){ + return false; + } + if (distance <= ED_MASTER_SWORD_JUMPSLASH){ + return true; + } + switch(enemy) { + case RE_GOLD_SKULLTULA: + //RANDOTODO double check all jumpslash kills that might be out of jump/backflip range + return distance <= ED_HAMMER_JUMPSLASH || (distance <= ED_RANG_OR_HOOKSHOT && (CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG))) || (distance == ED_LONGSHOT && CanUse(RG_LONGSHOT)); + case RE_KEESE: + case RE_FIRE_KEESE: + return true; + default: + return aboveLink || (distance <= ED_RANG_OR_HOOKSHOT && CanUse(RG_BOOMERANG)); + } + } + + bool Logic::CanBreakMudWalls() { + //RANDOTODO blue fire tricks + return BlastOrSmash(); + } + + bool Logic::CanGetDekuBabaSticks() { + return DekuBabaSticks || (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_BOOMERANG)); + } + + bool Logic::CanHitEyeTargets() { + return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT); + } + + bool Logic::CanDetonateBombFlowers() { + return CanUse(RG_FAIRY_BOW) || HasExplosives() || CanUse(RG_DINS_FIRE); + } + + bool Logic::CanDetonateUprightBombFlower() { + return CanDetonateBombFlowers() || CanUse(RG_GORONS_BRACELET); } Logic::Logic() { @@ -546,8 +630,9 @@ namespace Rando { return CallGossipFairyExceptSuns() || CanUse(RG_SUNS_SONG); } - bool Logic::EffectiveHealth(){ - return CallGossipFairyExceptSuns() || CanUse(RG_SUNS_SONG); + uint8_t Logic::EffectiveHealth(){ + uint8_t Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Value() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Value() : 10; + return ((Hearts() << (2 + HasItem(RG_DOUBLE_DEFENSE))) >> Multiplier) + ((Hearts() << (2 + HasItem(RG_DOUBLE_DEFENSE))) % (1 << Multiplier) > 0); } uint8_t Logic::Hearts(){ diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 3efae4d1d..dee521425 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -141,6 +141,7 @@ class Logic { bool FireLoopSwitch = false; bool LinksCow = false; bool DeliverLetter = false; + bool ClearMQDCUpperLobbyRocks = false; /* --- END OF HELPERS AND LOCATION ACCESS --- */ @@ -154,8 +155,15 @@ class Logic { bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched); bool CanDoGlitch(GlitchType glitch); bool CanEquipSwap(RandomizerGet itemName); - bool CanKillEnemy(std::string enemy); - bool CanPassEnemy(std::string enemy); + bool CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE); + bool CanPassEnemy(RandomizerEnemy enemy); + bool CanAvoidEnemy(RandomizerEnemy enemy); + bool CanGetEnemyDrop(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool aboveLink = false); + bool CanBreakMudWalls(); + bool CanGetDekuBabaSticks(); + bool CanHitEyeTargets(); + bool CanDetonateBombFlowers(); + bool CanDetonateUprightBombFlower(); uint8_t BottleCount(); uint8_t OcarinaButtons(); bool HasBottle(); @@ -176,7 +184,7 @@ class Logic { bool CanLeaveForest(); bool CallGossipFairy(); bool CallGossipFairyExceptSuns(); - bool EffectiveHealth(); + uint8_t EffectiveHealth(); uint8_t Hearts(); uint8_t StoneCount(); uint8_t MedallionCount(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 324e90149..3476d4fa7 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -539,10 +539,25 @@ typedef enum { RR_DODONGOS_CAVERN_MQ_BEGINNING, RR_DODONGOS_CAVERN_MQ_LOBBY, + RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, + RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_MUD_WALL, + RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, + RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER, + RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_BIG_SKULLTULAS, + RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM, + RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_LOWER, + RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM, + RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM, + RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, + RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, + RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, - RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, - RR_DODONGOS_CAVERN_MQ_BOSS_AREA, - + RR_DODONGOS_CAVERN_MQ_LOWER_LIZALFOS, + RR_DODONGOS_CAVERN_MQ_POES_ROOM, + RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM, + RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, + RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE, + RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, RR_DODONGOS_CAVERN_BOSS_ROOM, @@ -4345,4 +4360,22 @@ typedef enum { TH_MESSAGE_SURPLUS, } TriforceHuntMessages; +typedef enum { + RE_GOLD_SKULLTULA, + RE_BIG_SKULLTULA, + RE_DODONGO, + RE_LIZALFOS, + RE_GOHMA_LARVA, + RE_KEESE, + RE_FIRE_KEESE, + RE_MAD_SCRUB, +} RandomizerEnemy; +typedef enum { + ED_CLOSE, + ED_HAMMER_JUMPSLASH, + ED_MASTER_SWORD_JUMPSLASH, + ED_RANG_OR_HOOKSHOT, + ED_LONGSHOT, + ED_FAR, +} EnemyDistance;