Change CanUse to include an assert, fix some bad uses of CanUse (#4444)

This commit is contained in:
Pepper0ni 2024-10-20 09:03:09 +01:00 committed by GitHub
parent 81db6e3996
commit 323c67b47c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 49 additions and 64 deletions

View File

@ -166,7 +166,7 @@ void RegionTable_Init_DekuTree() {
Entrance(RR_DEKU_TREE_MQ_2F, {[]{return true;}}), Entrance(RR_DEKU_TREE_MQ_2F, {[]{return true;}}),
//Swim is not required because you can jump with enough momentum to hit land. //Swim is not required because you can jump with enough momentum to hit land.
//You even avoid fall damage if you hit the shallow water, though it's obscure knowledge so may be a trick //You even avoid fall damage if you hit the shallow water, though it's obscure knowledge so may be a trick
//if it is, then we need a landing room with (IsAdult || CanUse(RG_BRONZE_SCALE) || TakeDamage() || that trick) to reach basement //if it is, then we need a landing room with (IsAdult || HasItem(RG_BRONZE_SCALE) || TakeDamage() || that trick) to reach basement
Entrance(RR_DEKU_TREE_MQ_BASEMENT, {[]{return logic->BrokeDeku1FWeb;}}), Entrance(RR_DEKU_TREE_MQ_BASEMENT, {[]{return logic->BrokeDeku1FWeb;}}),
//is it possible to recoil from here to the ledge with a trick? //is it possible to recoil from here to the ledge with a trick?
}); });

View File

@ -219,17 +219,17 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_MQ_LOBBY] = Region("Dodongos Cavern MQ Lobby", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_DODONGOS_CAVERN_MQ_LOBBY] = Region("Dodongos Cavern MQ Lobby", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->GossipStoneFairy, {[]{return (Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls();}) || logic->CanUse(RG_GORONS_BRACELET)) && logic->CallGossipFairy();}}), EventAccess(&logic->GossipStoneFairy, {[]{return (Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls();}) || logic->HasItem(RG_GORONS_BRACELET)) && logic->CallGossipFairy();}}),
}, { }, {
//Locations //Locations
LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, logic->CanBreakMudWalls() || logic->CanUse(RG_GORONS_BRACELET)), LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)),
LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku()), 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_LOBBY_FRONT, logic->CanStunDeku()),
LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls() || logic->CanUse(RG_GORONS_BRACELET);})), LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);})),
}, { }, {
//Exits //Exits
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_MOUTH_SIDE_BRIDGE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(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_STAIRS_LOWER, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}}),
Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls();}) || 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 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_POES_ROOM, {[]{return logic->IsAdult;}}),
@ -264,13 +264,13 @@ void RegionTable_Init_DodongosCavern() {
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, { 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 //Events
EventAccess(&logic->DekuBabaSticks, {[]{return logic->CanGetDekuBabaSticks();}}), EventAccess(&logic->DekuBabaSticks, {[]{return logic->CanGetDekuBabaSticks();}}),
//EventAccess(&logic->CanClimbDCStairs, {[]{return logic->CanUse(RG_GORONS_BRACELET) && (logic->CanUse(RG_STICKS));}}), //EventAccess(&logic->CanClimbDCStairs, {[]{return logic->HasItem(RG_GORONS_BRACELET) && (logic->CanUse(RG_STICKS));}}),
}, { }, {
//Locations //Locations
LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)),
}, { }, {
//Exits //Exits
Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER, {[]{return logic->CanUse(RG_GORONS_BRACELET) && (logic->CanUse(RG_STICKS));}}), Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER, {[]{return logic->HasItem(RG_GORONS_BRACELET) && (logic->CanUse(RG_STICKS));}}),
Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, {[]{return true;}}), Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, {[]{return true;}}),
}); });

View File

@ -15,18 +15,6 @@
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
namespace Rando { namespace Rando {
bool Logic::IsMagicItem(RandomizerGet item) {
return item == RG_DINS_FIRE ||
item == RG_FARORES_WIND ||
item == RG_NAYRUS_LOVE ||
item == RG_LENS_OF_TRUTH;
}
bool Logic::IsMagicArrow(RandomizerGet item) {
return item == RG_FIRE_ARROWS ||
item == RG_ICE_ARROWS ||
item == RG_LIGHT_ARROWS;
}
bool Logic::HasItem(RandomizerGet itemName) { bool Logic::HasItem(RandomizerGet itemName) {
switch (itemName) { switch (itemName) {
@ -238,6 +226,19 @@ namespace Rando {
return false; return false;
switch (itemName) { switch (itemName) {
// Magic items
case RG_MAGIC_SINGLE:
return AmmoCanDrop || (HasBottle() && GetInLogic(LOGIC_BUY_MAGIC_POTION));
case RG_DINS_FIRE:
case RG_FARORES_WIND:
case RG_NAYRUS_LOVE:
case RG_LENS_OF_TRUTH:
return CanUse(RG_MAGIC_SINGLE);
case RG_FIRE_ARROWS:
case RG_ICE_ARROWS:
case RG_LIGHT_ARROWS:
return CanUse(RG_MAGIC_SINGLE) && CanUse(RG_FAIRY_BOW);
// Adult items // Adult items
// TODO: Uncomment those if we ever implement more item usability settings // TODO: Uncomment those if we ever implement more item usability settings
case RG_FAIRY_BOW: case RG_FAIRY_BOW:
@ -249,28 +250,34 @@ namespace Rando {
case RG_HOVER_BOOTS: case RG_HOVER_BOOTS:
return IsAdult;// || HoverBootsAsChild; return IsAdult;// || HoverBootsAsChild;
case RG_HOOKSHOT: case RG_HOOKSHOT:
return IsAdult;// || HookshotAsChild;
case RG_LONGSHOT: case RG_LONGSHOT:
case RG_SCARECROW:
case RG_DISTANT_SCARECROW:
return IsAdult;// || HookshotAsChild; return IsAdult;// || HookshotAsChild;
case RG_SILVER_GAUNTLETS:
case RG_GOLDEN_GAUNTLETS:
return IsAdult;
case RG_GORON_TUNIC: case RG_GORON_TUNIC:
return IsAdult;// || GoronTunicAsChild; return IsAdult;// || GoronTunicAsChild;
case RG_ZORA_TUNIC: case RG_ZORA_TUNIC:
return IsAdult;// || ZoraTunicAsChild; return IsAdult;// || ZoraTunicAsChild;
case RG_SCARECROW:
return IsAdult;// || HookshotAsChild;
case RG_DISTANT_SCARECROW:
return IsAdult;// || HookshotAsChild;
case RG_HYLIAN_SHIELD:
return true;
case RG_MIRROR_SHIELD: case RG_MIRROR_SHIELD:
return IsAdult;// || MirrorShieldAsChild; return IsAdult;// || MirrorShieldAsChild;
case RG_MASTER_SWORD: case RG_MASTER_SWORD:
return IsAdult;// || MasterSwordAsChild; return IsAdult;// || MasterSwordAsChild;
case RG_BIGGORON_SWORD: case RG_BIGGORON_SWORD:
return IsAdult;// || BiggoronSwordAsChild; return IsAdult;// || BiggoronSwordAsChild;
case RG_SILVER_GAUNTLETS:
case RG_GOLDEN_GAUNTLETS:
// Adult Trade
case RG_POCKET_EGG:
case RG_COJIRO:
case RG_ODD_MUSHROOM:
case RG_ODD_POTION:
case RG_POACHERS_SAW:
case RG_BROKEN_SWORD:
case RG_PRESCRIPTION:
case RG_EYEBALL_FROG:
case RG_EYEDROPS:
case RG_CLAIM_CHECK:
return IsAdult;
// Child items // Child items
case RG_FAIRY_SLINGSHOT: case RG_FAIRY_SLINGSHOT:
@ -285,8 +292,6 @@ namespace Rando {
return IsChild /* || StickAsAdult;*/&& (StickPot || DekuBabaSticks); return IsChild /* || StickAsAdult;*/&& (StickPot || DekuBabaSticks);
case RG_DEKU_SHIELD: case RG_DEKU_SHIELD:
return IsChild;// || DekuShieldAsAdult; return IsChild;// || DekuShieldAsAdult;
case RG_WEIRD_EGG:
return IsChild;
case RG_PROGRESSIVE_BOMB_BAG: case RG_PROGRESSIVE_BOMB_BAG:
case RG_BOMB_BAG: case RG_BOMB_BAG:
return AmmoCanDrop || GetInLogic(LOGIC_BUY_BOMB); return AmmoCanDrop || GetInLogic(LOGIC_BUY_BOMB);
@ -295,47 +300,30 @@ namespace Rando {
case RG_BOMBCHU_10: case RG_BOMBCHU_10:
case RG_BOMBCHU_20: case RG_BOMBCHU_20:
return BombchuRefill() && BombchusEnabled(); return BombchuRefill() && BombchusEnabled();
case RG_WEIRD_EGG:
case RG_RUTOS_LETTER: case RG_RUTOS_LETTER:
return IsChild; return IsChild;
// Adult Trade
case RG_POCKET_EGG:
case RG_COJIRO:
case RG_ODD_MUSHROOM:
case RG_ODD_POTION:
case RG_POACHERS_SAW:
case RG_BROKEN_SWORD:
case RG_PRESCRIPTION:
case RG_EYEBALL_FROG:
case RG_EYEDROPS:
case RG_CLAIM_CHECK:
return IsAdult;
// Songs // Songs
case RG_ZELDAS_LULLABY: case RG_ZELDAS_LULLABY:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON);
case RG_EPONAS_SONG: case RG_EPONAS_SONG:
case RG_PRELUDE_OF_LIGHT:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON); return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON);
case RG_SARIAS_SONG: case RG_SARIAS_SONG:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON);
case RG_SUNS_SONG: case RG_SUNS_SONG:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON);
case RG_SONG_OF_TIME: case RG_SONG_OF_TIME:
case RG_BOLERO_OF_FIRE:
case RG_REQUIEM_OF_SPIRIT:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON);
case RG_SONG_OF_STORMS: case RG_SONG_OF_STORMS:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON);
case RG_MINUET_OF_FOREST: case RG_MINUET_OF_FOREST:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON); return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON);
case RG_BOLERO_OF_FIRE:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON);
case RG_SERENADE_OF_WATER: case RG_SERENADE_OF_WATER:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON);
case RG_REQUIEM_OF_SPIRIT:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON);
case RG_NOCTURNE_OF_SHADOW: case RG_NOCTURNE_OF_SHADOW:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON); return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_A_BUTTON) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_DOWN_BUTTON);
case RG_PRELUDE_OF_LIGHT:
return HasItem(RG_FAIRY_OCARINA) && HasItem(RG_OCARINA_C_LEFT_BUTTON) && HasItem(RG_OCARINA_C_RIGHT_BUTTON) && HasItem(RG_OCARINA_C_UP_BUTTON);
// Misc. Items // Misc. Items
case RG_FISHING_POLE: case RG_FISHING_POLE:
@ -353,11 +341,10 @@ namespace Rando {
case RG_BOTTLE_WITH_FAIRY: case RG_BOTTLE_WITH_FAIRY:
return FairyPot || GossipStoneFairy || BeanPlantFairy || ButterflyFairy || FreeFairies || FairyPond || GetInLogic(LOGIC_FAIRY_ACCESS); return FairyPot || GossipStoneFairy || BeanPlantFairy || ButterflyFairy || FreeFairies || FairyPond || GetInLogic(LOGIC_FAIRY_ACCESS);
// Magic items
case RG_MAGIC_SINGLE:
return AmmoCanDrop || (HasBottle() && GetInLogic(LOGIC_BUY_MAGIC_POTION));
default: default:
return CanUse(RG_MAGIC_SINGLE) && (IsMagicItem(itemName) || (IsMagicArrow(itemName) && CanUse(RG_FAIRY_BOW))); SPDLOG_ERROR("CanUse reached `default` for {}. Assuming intention is no extra requirements for use so returning true, but HasItem should be used instead.", static_cast<uint32_t>(itemName));
assert(false);
return true;
} }
} }
@ -599,7 +586,7 @@ namespace Rando {
} }
bool Logic::CanDetonateUprightBombFlower() { bool Logic::CanDetonateUprightBombFlower() {
return CanDetonateBombFlowers() || CanUse(RG_GORONS_BRACELET); return CanDetonateBombFlowers() || HasItem(RG_GORONS_BRACELET);
} }
Logic::Logic() { Logic::Logic() {
@ -681,7 +668,7 @@ namespace Rando {
} }
bool Logic::CanReflectNuts(){ bool Logic::CanReflectNuts(){
return CanUse(RG_DEKU_SHIELD) || (IsAdult && CanUse(RG_HYLIAN_SHIELD)); return CanUse(RG_DEKU_SHIELD) || (IsAdult && HasItem(RG_HYLIAN_SHIELD));
} }
bool Logic::CanCutShrubs(){ bool Logic::CanCutShrubs(){
@ -832,11 +819,11 @@ namespace Rando {
} }
bool Logic::CanStandingShield(){ bool Logic::CanStandingShield(){
return CanUse(RG_MIRROR_SHIELD) || (IsAdult && CanUse(RG_HYLIAN_SHIELD)) || CanUse(RG_DEKU_SHIELD); return CanUse(RG_MIRROR_SHIELD) || (IsAdult && HasItem(RG_HYLIAN_SHIELD)) || CanUse(RG_DEKU_SHIELD);
} }
bool Logic::CanShield(){ bool Logic::CanShield(){
return CanUse(RG_MIRROR_SHIELD) || CanUse(RG_HYLIAN_SHIELD) || CanUse(RG_DEKU_SHIELD); return CanUse(RG_MIRROR_SHIELD) || HasItem(RG_HYLIAN_SHIELD) || CanUse(RG_DEKU_SHIELD);
} }
bool Logic::CanUseProjectile(){ bool Logic::CanUseProjectile(){

View File

@ -247,8 +247,6 @@ class Logic {
static std::map<RandomizerGet, uint32_t> RandoGetToRandInf; static std::map<RandomizerGet, uint32_t> RandoGetToRandInf;
private: private:
static bool IsMagicItem(RandomizerGet item);
static bool IsMagicArrow(RandomizerGet item);
std::shared_ptr<Context> ctx; std::shared_ptr<Context> ctx;
bool inLogic[LOGIC_MAX]; bool inLogic[LOGIC_MAX];
}; // class Logic }; // class Logic