From 88154d78c813bab30a7a4af51ce9b24cfee1f00e Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Tue, 8 Apr 2025 16:26:04 +0100 Subject: [PATCH] Fix Market Grass and Crate logic (#5340) * fix market grass and crate logic * apply clang --- .../dungeons/bottom_of_the_well.cpp | 4 +- .../location_access/overworld/market.cpp | 25 +++++----- soh/soh/Enhancements/randomizer/logic.cpp | 46 ++++++++----------- soh/soh/Enhancements/randomizer/logic.h | 1 + 4 files changed, 35 insertions(+), 41 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp index 4ec6b6773..44c3fa817 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp @@ -50,7 +50,7 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, true), LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, true), LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, true), - //N64 has no extra check here, but I can't get past without dealing with the spider or taking a hit, they probably assume sticks + //You can just barely pass the spider on the right side without damage or items, but it's probably tight enough to count as as a trick LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()), //Not technically behind a wall, but still logically needs lens due to pits LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives()), @@ -160,7 +160,7 @@ void RegionTable_Init_BottomOfTheWell() { }, { //Exits Entrance(RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, []{return logic->IsChild && logic->CanPassEnemy(RE_BIG_SKULLTULA);}), - //It's possible top abuse boulder's limited range of collision detection to detonate the flowers through the boulder with bow, but this is a glitch + //It's possible to abuse boulder's limited range of collision detection to detonate the flowers through the boulder with bow, but this is a glitch //the exact range is just past the furthest away plank in the green goo section Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS, []{return Here(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || (logic->CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_BASEMENT));});}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index 2016b24cd..0314bfde0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -14,18 +14,19 @@ void RegionTable_Init_Market() { areaTable[RR_THE_MARKET] = Region("Market", "Market", {RA_THE_MARKET}, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_MARKET_GRASS_1, logic->IsChild && logic->CanCutShrubs()), - LOCATION(RC_MARKET_GRASS_2, logic->IsChild && logic->CanCutShrubs()), - LOCATION(RC_MARKET_GRASS_3, logic->IsChild && logic->CanCutShrubs()), - LOCATION(RC_MARKET_GRASS_4, logic->IsChild && logic->CanCutShrubs()), - LOCATION(RC_MARKET_GRASS_5, logic->IsChild && logic->CanCutShrubs()), - LOCATION(RC_MARKET_GRASS_6, logic->IsChild && logic->CanCutShrubs()), - LOCATION(RC_MARKET_GRASS_7, logic->IsChild && logic->CanCutShrubs()), - LOCATION(RC_MARKET_GRASS_8, logic->IsChild && logic->CanCutShrubs()), - LOCATION(RC_MK_NEAR_BAZAAR_CRATE_1, logic->IsChild && logic->CanBreakCrates()), - LOCATION(RC_MK_NEAR_BAZAAR_CRATE_2, logic->IsChild && logic->CanBreakCrates()), - LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_1, logic->IsChild && logic->CanBreakCrates()), - LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_2, logic->IsChild && logic->CanBreakCrates()), + //RANDOTODO add item avalibility to regions to remove need to hardcode logic in limited item use situations + LOCATION(RC_MARKET_GRASS_1, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_MARKET_GRASS_2, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_MARKET_GRASS_3, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_MARKET_GRASS_4, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_MARKET_GRASS_5, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_MARKET_GRASS_6, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_MARKET_GRASS_7, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_MARKET_GRASS_8, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_MK_NEAR_BAZAAR_CRATE_1, logic->IsChild /*&& logic->CanRoll()*/), + LOCATION(RC_MK_NEAR_BAZAAR_CRATE_2, logic->IsChild /*&& logic->CanRoll()*/), + LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_1, logic->IsChild /*&& logic->CanRoll()*/), + LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_2, logic->IsChild /*&& logic->CanRoll()*/), }, { //Exits Entrance(RR_MARKET_ENTRANCE, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index b2856391f..ed91b21b8 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -558,9 +558,8 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal } return killed; case RE_DODONGO: - return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || - CanUse(RG_MEGATON_HAMMER) || (quantity <= 5 && CanUse(RG_STICKS)) || HasExplosives() || - CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW); + return CanUseSword() || CanUse(RG_MEGATON_HAMMER) || (quantity <= 5 && CanUse(RG_STICKS)) || + HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW); case RE_LIZALFOS: return CanJumpslash() || HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW); case RE_KEESE: @@ -604,11 +603,9 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal (CanUse(RG_NUTS) || HookshotOrBoomerang() || CanStandingShield())); case RE_DEAD_HAND: // RANDOTODO change Dead Hand trick to be sticks Dead Hand - return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || - (CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_CHILD_DEADHAND)); + return CanUseSword() || (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); + return CanUseSword() || CanUse(RG_BOOMERANG); case RE_LIKE_LIKE: case RE_FLOORMASTER: return CanDamage(); @@ -645,8 +642,7 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal // 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(); + return CanUseSword() || 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 @@ -695,9 +691,8 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal CanUse(RG_STICKS) || HasExplosives() || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE) || CanUse(RG_FIRE_ARROWS); case RE_SHELL_BLADE: - return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || - CanUse(RG_MEGATON_HAMMER) || CanUse(RG_STICKS) || HasExplosives() || CanUse(RG_HOOKSHOT) || - CanUse(RG_FAIRY_BOW) || CanUse(RG_DINS_FIRE); + return CanJumpslash() || HasExplosives() || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || + CanUse(RG_DINS_FIRE); case RE_SPIKE: return CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_STICKS) || HasExplosives() || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || @@ -744,25 +739,20 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal case RE_BARINADE: return HasBossSoul(RG_BARINADE_SOUL) && CanUse(RG_BOOMERANG) && CanJumpslashExceptHammer(); case RE_PHANTOM_GANON: - return HasBossSoul(RG_PHANTOM_GANON_SOUL) && - (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && + return HasBossSoul(RG_PHANTOM_GANON_SOUL) && CanUseSword() && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT)); case RE_VOLVAGIA: return HasBossSoul(RG_VOLVAGIA_SOUL) && CanUse(RG_MEGATON_HAMMER); case RE_MORPHA: - return HasBossSoul(RG_MORPHA_SOUL) && CanUse(RG_HOOKSHOT) && - (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || - CanUse(RG_MEGATON_HAMMER)); + return HasBossSoul(RG_MORPHA_SOUL) && CanUse(RG_HOOKSHOT) && (CanUseSword() || CanUse(RG_MEGATON_HAMMER)); case RE_BONGO_BONGO: return HasBossSoul(RG_BONGO_BONGO_SOUL) && - (CanUse(RG_LENS_OF_TRUTH) || ctx->GetTrickOption(RT_LENS_BONGO)) && - (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && + (CanUse(RG_LENS_OF_TRUTH) || ctx->GetTrickOption(RT_LENS_BONGO)) && CanUseSword() && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || ctx->GetTrickOption(RT_SHADOW_BONGO)); case RE_TWINROVA: return HasBossSoul(RG_TWINROVA_SOUL) && CanUse(RG_MIRROR_SHIELD) && - (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || - CanUse(RG_MEGATON_HAMMER)); + (CanUseSword() || CanUse(RG_MEGATON_HAMMER)); case RE_GANONDORF: // RANDOTODO: Trick to use hammer (no jumpslash) or stick (only jumpslash) instead of a sword to reflect the // energy ball and either of them regardless of jumpslashing to damage and kill ganondorf @@ -771,8 +761,7 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal // for killing ganondorf and all of those can reflect the energy ball // This will not be the case once ammo logic in taken into account as // sticks are limited and using a bottle might become a requirement in that case - return HasBossSoul(RG_GANON_SOUL) && CanUse(RG_LIGHT_ARROWS) && - (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)); + return HasBossSoul(RG_GANON_SOUL) && CanUse(RG_LIGHT_ARROWS) && CanUseSword(); case RE_GANON: return HasBossSoul(RG_GANON_SOUL) && CanUse(RG_MASTER_SWORD); case RE_DARK_LINK: @@ -792,8 +781,7 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal return CanUse(RG_BOOMERANG); case RE_BARI: return HookshotOrBoomerang() || CanUse(RG_FAIRY_BOW) || HasExplosives() || CanUse(RG_MEGATON_HAMMER) || - CanUse(RG_STICKS) || CanUse(RG_DINS_FIRE) || - (TakeDamage() && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))); + CanUse(RG_STICKS) || CanUse(RG_DINS_FIRE) || (TakeDamage() && CanUseSword()); case RE_SHABOM: // RANDOTODO when you add better damage logic, you can kill this by taking hits return CanUse(RG_BOOMERANG) || CanUse(RG_NUTS) || CanJumpslash() || CanUse(RG_DINS_FIRE) || @@ -962,7 +950,7 @@ bool Logic::CanBreakMudWalls() { } bool Logic::CanGetDekuBabaSticks() { - return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_BOOMERANG)); + return CanUseSword() || CanUse(RG_BOOMERANG); } bool Logic::CanGetDekuBabaNuts() { @@ -1060,9 +1048,13 @@ bool Logic::HasBottle() { return BottleCount() >= 1; } +bool Logic::CanUseSword() { + return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD); +} + bool Logic::CanJumpslashExceptHammer() { // Not including hammer as hammer jump attacks can be weird; - return CanUse(RG_STICKS) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD); + return CanUse(RG_STICKS) || CanUseSword(); } bool Logic::CanJumpslash() { diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 7e0daac90..4f966f5de 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -209,6 +209,7 @@ class Logic { uint8_t BottleCount(); uint8_t OcarinaButtons(); bool HasBottle(); + bool CanUseSword(); bool CanJumpslashExceptHammer(); bool CanJumpslash(); bool CanHitSwitch(EnemyDistance distance = ED_CLOSE, bool inWater = false);