Rewrite MQ Jabu Logic (#4493)

* rewrite MQ Jabu Logic

* Add swim requirement to the rang jump trick as link hints the water first
This commit is contained in:
Pepper0ni 2024-10-29 21:05:09 +00:00 committed by GitHub
parent 6bd3b1d160
commit 71e9e616b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 255 additions and 58 deletions

View File

@ -83,7 +83,7 @@ void RegionTable_Init_BottomOfTheWell() {
areaTable[RR_BOTTOM_OF_THE_WELL_LIKE_LIKE_CAGE] = Region("Bottom of the Well Like-Like Cage", "Bottom of the Well", {RA_BOTTOM_OF_THE_WELL}, NO_DAY_NIGHT_CYCLE, {}, { areaTable[RR_BOTTOM_OF_THE_WELL_LIKE_LIKE_CAGE] = Region("Bottom of the Well Like-Like Cage", "Bottom of the Well", {RA_BOTTOM_OF_THE_WELL}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations //Locations
LOCATION(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, true), LOCATION(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, true),
LOCATION(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_RANG_OR_HOOKSHOT)), LOCATION(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
}, { }, {
//Exits //Exits
Entrance(RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, {[]{return true;}}), Entrance(RR_BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, {[]{return true;}}),
@ -96,8 +96,8 @@ void RegionTable_Init_BottomOfTheWell() {
EventAccess(&logic->DekuBabaNuts, {[]{return logic->CanGetDekuBabaNuts();}}), EventAccess(&logic->DekuBabaNuts, {[]{return logic->CanGetDekuBabaNuts();}}),
}, { }, {
//Locations //Locations
LOCATION(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_RANG_OR_HOOKSHOT)), LOCATION(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
LOCATION(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_RANG_OR_HOOKSHOT)), LOCATION(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
}, { }, {
//Exits //Exits
Entrance(RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, {[]{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}), Entrance(RR_BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, {[]{return logic->SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}),

View File

@ -220,7 +220,7 @@ void RegionTable_Init_DekuTree() {
areaTable[RR_DEKU_TREE_MQ_PAST_BOULDER_VINES] = Region("Deku Tree MQ Past Boulder Vines", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, { areaTable[RR_DEKU_TREE_MQ_PAST_BOULDER_VINES] = Region("Deku Tree MQ Past Boulder Vines", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations //Locations
LOCATION(RC_DEKU_TREE_MQ_GS_PAST_BOULDER_VINES, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_RANG_OR_HOOKSHOT)), LOCATION(RC_DEKU_TREE_MQ_GS_PAST_BOULDER_VINES, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
}, { }, {
//Exits //Exits
Entrance(RR_DEKU_TREE_MQ_COMPASS_ROOM, {[]{return logic->BlastOrSmash();}}), Entrance(RR_DEKU_TREE_MQ_COMPASS_ROOM, {[]{return logic->BlastOrSmash();}}),
@ -296,7 +296,7 @@ void RegionTable_Init_DekuTree() {
EventAccess(&logic->DekuBabaNuts, {[]{return logic->CanGetDekuBabaNuts();}}) EventAccess(&logic->DekuBabaNuts, {[]{return logic->CanGetDekuBabaNuts();}})
}, { }, {
//Locations //Locations
LOCATION(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_RANG_OR_HOOKSHOT))), LOCATION(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG))),
}, { }, {
//Exits //Exits
Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return logic->IsChild && Here(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, []{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);});}}), Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return logic->IsChild && Here(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, []{return logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW);});}}),
@ -307,7 +307,7 @@ void RegionTable_Init_DekuTree() {
areaTable[RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM] = Region("Deku Tree MQ Basement Back Room", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, { areaTable[RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM] = Region("Deku Tree MQ Basement Back Room", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations //Locations
LOCATION(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_RANG_OR_HOOKSHOT)), LOCATION(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
}, { }, {
//Exits //Exits
Entrance(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, {[]{return true;}}), Entrance(RR_DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, {[]{return true;}}),

View File

@ -380,7 +380,7 @@ void RegionTable_Init_DodongosCavern() {
//Locations //Locations
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_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 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 logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG, 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))) //&& (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 //Exits
@ -391,7 +391,7 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_MQ_MAD_SCRUB_ROOM] = Region("Dodongos Cavern Mad Scrub Room", "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 //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 LOCATION(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG, 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))) //&& (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 //Exits
@ -424,7 +424,7 @@ void RegionTable_Init_DodongosCavern() {
}, { }, {
//Locations //Locations
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 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)) || Here(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, []{return (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)) ||
(logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) /* || bunny jumps*/);})), (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) /* || bunny jumps*/);})),
}, { }, {
//Exits //Exits

View File

@ -180,9 +180,8 @@ void RegionTable_Init_GerudoTrainingGrounds() {
LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true)), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true)),
}, { }, {
//Exits //Exits
//The here check needs to be before the age check here
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_BEHIND_BLOCK, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);}) && logic->CanUse(RG_SILVER_GAUNTLETS);}}), Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_BEHIND_BLOCK, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);}) && logic->CanUse(RG_SILVER_GAUNTLETS);}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STATUE_ROOM_LEDGE, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);}) && logic->IsAdult && Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STATUE_ROOM_LEDGE, {[]{return logic->IsAdult && Here(RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);}) &&
(ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->BlueFire() && (ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->BlueFire() &&
(logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->CanUse(RG_HOVER_BOOTS)));}}), (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->CanUse(RG_HOVER_BOOTS)));}}),
}); });
@ -221,7 +220,7 @@ void RegionTable_Init_GerudoTrainingGrounds() {
//Locations //Locations
//implies logic->CanKillEnemy(RE_TORCH_SLUG) //implies logic->CanKillEnemy(RE_TORCH_SLUG)
LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE)), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE)),
LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanHitSwitch(ED_RANG_OR_HOOKSHOT)), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanHitSwitch(ED_BOOMERANG)),
}, { }, {
//Exits //Exits
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STATUE_ROOM, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_MQ_TORCH_SLUG_ROOM, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}}), Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STATUE_ROOM, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_MQ_TORCH_SLUG_ROOM, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}}),

View File

@ -123,7 +123,7 @@ void RegionTable_Init_HyruleField() {
LOCATION(RC_LH_SUN, logic->IsAdult && ((logic->WaterTempleClear && logic->HasItem(RG_BRONZE_SCALE)) || logic->CanUse(RG_DISTANT_SCARECROW)) && logic->CanUse(RG_FAIRY_BOW)), LOCATION(RC_LH_SUN, logic->IsAdult && ((logic->WaterTempleClear && logic->HasItem(RG_BRONZE_SCALE)) || logic->CanUse(RG_DISTANT_SCARECROW)) && logic->CanUse(RG_FAIRY_BOW)),
LOCATION(RC_LH_FREESTANDING_POH, logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA))), LOCATION(RC_LH_FREESTANDING_POH, logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA))),
LOCATION(RC_LH_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_LH_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)),
LOCATION(RC_LH_GS_LAB_WALL, logic->IsChild && (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_RANG_OR_HOOKSHOT) || (ctx->GetTrickOption(RT_LH_LAB_WALL_GS) && logic->CanJumpslashExceptHammer())) && logic->AtNight && logic->CanGetNightTimeGS()), LOCATION(RC_LH_GS_LAB_WALL, logic->IsChild && (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (ctx->GetTrickOption(RT_LH_LAB_WALL_GS) && logic->CanJumpslashExceptHammer())) && logic->AtNight && logic->CanGetNightTimeGS()),
LOCATION(RC_LH_GS_SMALL_ISLAND, logic->IsChild && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) && logic->AtNight && logic->CanGetNightTimeGS() && logic->HasItem(RG_BRONZE_SCALE)), LOCATION(RC_LH_GS_SMALL_ISLAND, logic->IsChild && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) && logic->AtNight && logic->CanGetNightTimeGS() && logic->HasItem(RG_BRONZE_SCALE)),
LOCATION(RC_LH_GS_TREE, logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->AtNight && logic->CanGetNightTimeGS()), LOCATION(RC_LH_GS_TREE, logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->AtNight && logic->CanGetNightTimeGS()),
LOCATION(RC_LH_LAB_GOSSIP_STONE, true), LOCATION(RC_LH_LAB_GOSSIP_STONE, true),

View File

@ -166,54 +166,147 @@ void RegionTable_Init_JabuJabusBelly() {
}, { }, {
//Locations //Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, logic->BlastOrSmash()), LOCATION(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, logic->BlastOrSmash()),
LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)), LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)),
}, { }, {
//Exits //Exits
Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}), Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return Here(RR_JABU_JABUS_BELLY_MQ_BEGINNING, []{return logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT);});}}), Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, {[]{return Here(RR_JABU_JABUS_BELLY_MQ_BEGINNING, []{return logic->CanUse(RG_FAIRY_SLINGSHOT);});}}),
}); });
areaTable[RR_JABU_JABUS_BELLY_MQ_MAIN] = Region("Jabu Jabus Belly MQ Main", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, { areaTable[RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM] = Region("Jabu Jabus Belly MQ Lift Room", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->MQJabuLiftRoomCow, {[]{return logic->CanUse(RG_FAIRY_SLINGSHOT);}}),
}, {
//Locations //Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, true), LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, true),
LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))) || ChildCanAccess(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA)),
LOCATION(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) ||
ctx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE)) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG)))),
LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)),
LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)),
LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, true),
LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_STICKS) || logic->CanUse(RG_BOMB_BAG)),
LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->IsChild && logic->CanUse(RG_BOOMERANG))),
//Trick: logic->CanUse(RG_SONG_OF_TIME) || (LogicJabuMQSoTGS && logic->IsChild && logic->CanUse(RG_BOOMERANG))
}, { }, {
//Exits //Exits
Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}), Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_DEPTHS, {[]{return logic->HasExplosives() && logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->CanUse(RG_BOOMERANG);}}), Entrance(RR_JABU_JABUS_BELLY_MQ_UNDERWATER_ALCOVE, {[]{return logic->HasItem(RG_SILVER_SCALE) || (logic->HasItem(RG_BRONZE_SCALE) && ((logic->IsChild || logic->CanUse(RG_IRON_BOOTS) || ctx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE))));}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, {[]{return logic->MQJabuHolesRoomDoor;}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE, {[]{return logic->LoweredJabuPath || logic->CanUse(RG_HOVER_BOOTS) || (logic->CanUse(RG_HOOKSHOT) && logic->MQJabuLiftRoomCow);}}),
//If opening RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM by lowering the geyser as 1 age is to let the other through is relevant, it needs an eventAccess
}); });
areaTable[RR_JABU_JABUS_BELLY_MQ_DEPTHS] = Region("Jabu Jabus Belly MQ Depths", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, { areaTable[RR_JABU_JABUS_BELLY_MQ_UNDERWATER_ALCOVE] = Region("Jabu Jabus Belly MQ Underwater Alcove", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->MQJabuHolesRoomDoor, {[]{return true;}}),
}, {
//Locations //Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, true), LOCATION(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, logic->CanHitSwitch(ED_HOOKSHOT, true) || (ctx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG) && logic->HasItem(RG_BRONZE_SCALE))),
LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, logic->HasItem(RG_BRONZE_SCALE) && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_DINS_FIRE))),
LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, (ctx->GetTrickOption(RT_LENS_JABU_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) || Here(RR_JABU_JABUS_BELLY_MQ_MAIN, []{return logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_HOOKSHOT);})),
}, { }, {
//Exits //Exits
Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}), Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, {[]{return logic->HasItem(RG_BRONZE_SCALE);}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA, {[]{return logic->CanUse(RG_STICKS) || (logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_KOKIRI_SWORD));}}),
}); });
areaTable[RR_JABU_JABUS_BELLY_MQ_BOSS_AREA] = Region("Jabu Jabus Belly MQ Boss Region", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM] = Region("Jabu Jabus Belly MQ Holes Room", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)),
LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)),
}, {
//Exits
Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, {[]{return logic->CanUse(RG_BOOMERANG) && logic->HasExplosives() && Here(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->CanUse(RG_FAIRY_SLINGSHOT);});}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, {[]{return logic->JabuNorthTentacle;}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_PAST_OCTO, {[]{return logic->JabuWestTentacle && Here(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->CanKillEnemy(RE_BIG_OCTO);}) && logic->CanUse(RG_FAIRY_SLINGSHOT);}}),
});
areaTable[RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM] = Region("Jabu Jabus Belly MQ Water Switch Room", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, true),
//Implies logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_STINGER). Without swim, jump from the song of time block to the vines.
LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanKillEnemy(RE_LIZALFOS)),
LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, (logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)) || (ctx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->CanUse(RG_BOOMERANG))),
}, {
//Exits
//without swim, jump from rang chest to the other side
Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return Here(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, []{return logic->CanKillEnemy(RE_LIZALFOS);});}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, {[]{return (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE)) && Here(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, []{return logic->CanKillEnemy(RE_LIZALFOS);});}}),
});
//Includes Like Like room
areaTable[RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR] = Region("Jabu Jabus Belly MQ Forked Corridor", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->JabuNorthTentacle, {[]{return Here(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, []{return logic->BlastOrSmash();}) && logic->CanUse(RG_BOOMERANG);}}),
}, {
//Locations
//Implies CanKillEnemy(RE_LIKE_LIKE)
LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)),
}, {
//Exits
Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, {[]{return logic->CanUse(RG_BOOMERANG);}}),
//If some mode lets an age use sticks and not sling, and other use sling and not sticks, this needs changing
Entrance(RR_JABU_JABUS_BELLY_MQ_WEST_FORKED_ROOMS, {[]{return Here(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, []{return logic->CanUse(RG_BOOMERANG);}) &&
(Here(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, []{return logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->CanUse(RG_STICKS);}) ||
Here(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, []{return logic->HasFireSource();}));}}),
});
areaTable[RR_JABU_JABUS_BELLY_MQ_WEST_FORKED_ROOMS] = Region("Jabu Jabus Belly MQ West Forked Rooms", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->JabuWestTentacle, {[]{return logic->CanUse(RG_BOOMERANG);}}),
}, {
//Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, Here(RR_JABU_JABUS_BELLY_MQ_WEST_FORKED_ROOMS, []{return logic->HasExplosives();}) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
}, {
//Exits
Entrance(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, {[]{return true;}}),
});
areaTable[RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM] = Region("Jabu Jabus Belly MQ Depths", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, //firstly, we can just use FAs to clear the web and then longshot the skull
logic->CanUse(RG_FIRE_ARROWS) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT) ||
//Otherwise, we we have to cross the gap and kill the skull.
(logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) &&
//We can cheese the gap with hovers
((logic->CanUse(RG_HOVER_BOOTS) ||
//Otherwise we have to kill the enemies to raise the platform. This persists so we can do it as the other age.
Here(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, []{return (ctx->GetTrickOption(RT_LENS_JABU_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) &&
logic->CanKillEnemy(RE_STINGER, ED_BOOMERANG, false, 2, false, true) &&
//we can hit the keese farthest from the water with irons and hookshot, but we won't be able to see it while doing so
(logic->CanKillEnemy(RE_KEESE, ED_LONGSHOT, false) || (ctx->GetTrickOption(RT_LENS_JABU_MQ) && logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)));}))
//If we kill the enemies, we then need to cross the water using the platform. Note that adult cannot do so while swimming because MQ jank.
&& ((logic->IsChild && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && logic->CanUse(RG_IRON_BOOTS)))))),
}, {
//Exits
Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, {[]{return (logic->JabuNorthTentacle || logic->TakeDamage()) && logic->HasItem(RG_BRONZE_SCALE);}}),
});
areaTable[RR_JABU_JABUS_BELLY_MQ_PAST_OCTO] = Region("Jabu Jabus Belly MQ Past Octo", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
//Events
//if a hover up to the path is added, this will want it's own room
EventAccess(&logic->LoweredJabuPath, {[]{return logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_FAIRY_SLINGSHOT);}}),
}, {
//Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_COW, logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_FAIRY_SLINGSHOT)),
}, {
//Exits
Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, {[]{return logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_FAIRY_SLINGSHOT);}}),
//you take both fall damage and tentacle damage, unless the tentacle is down. need better damage logic
Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, {[]{return logic->TakeDamage() && Here(RR_JABU_JABUS_BELLY_MQ_PAST_OCTO, []{return logic->CanKillEnemy(RE_BIG_OCTO);});}}),
});
areaTable[RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE] = Region("Jabu Jabus Belly MQ Lift Room East Ledge", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, logic->MQJabuLiftRoomCow),
}, {
//Exits
Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_EAST_ROOM, {[]{return logic->JabuNorthTentacle;}}),
});
areaTable[RR_JABU_JABUS_BELLY_MQ_EAST_ROOM] = Region("Jabu Jabus Belly MQ Boss Region", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->FairyPot, {[]{return true;}}), EventAccess(&logic->FairyPot, {[]{return true;}}),
}, { }, {
//Locations //Locations
LOCATION(RC_JABU_JABUS_BELLY_MQ_COW, logic->CanUse(RG_EPONAS_SONG)),
LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)),
LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT))), LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT))),
}, { }, {
//Exits //Exits
Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}), Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return logic->CanUse(RG_FAIRY_SLINGSHOT);}}), Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return Here(RR_JABU_JABUS_BELLY_MQ_EAST_ROOM, []{return logic->CanUse(RG_FAIRY_SLINGSHOT);});}}),
}); });
} }
@ -225,7 +318,7 @@ void RegionTable_Init_JabuJabusBelly() {
{ {
// Exits // Exits
Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, { [] { return ctx->GetDungeon(JABU_JABUS_BELLY)->IsVanilla(); } }), Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, { [] { return ctx->GetDungeon(JABU_JABUS_BELLY)->IsVanilla(); } }),
Entrance(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA, { [] { return ctx->GetDungeon(JABU_JABUS_BELLY)->IsMQ(); } }), Entrance(RR_JABU_JABUS_BELLY_MQ_EAST_ROOM, { [] { return ctx->GetDungeon(JABU_JABUS_BELLY)->IsMQ(); } }),
Entrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, { [] { return true; } }), Entrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, { [] { return true; } }),
}); });

View File

@ -410,7 +410,7 @@ namespace Rando {
//RANDOTODO quantity is a placeholder for proper ammo use calculation logic. in time will want updating to account for ammo capacity //RANDOTODO quantity is a placeholder for proper ammo use calculation logic. in time will want updating to account for ammo capacity
//Can we kill this enemy //Can we kill this enemy
bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wallOrFloor, uint8_t quantity, bool timer) { bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wallOrFloor, uint8_t quantity, bool timer, bool inWater) {
bool killed = false; bool killed = false;
switch(enemy) { switch(enemy) {
case RE_GOLD_SKULLTULA: case RE_GOLD_SKULLTULA:
@ -422,10 +422,10 @@ namespace Rando {
switch (distance){ switch (distance){
case ED_CLOSE: case ED_CLOSE:
//hammer jumpslash cannot damage these, but hammer swing can //hammer jumpslash cannot damage these, but hammer swing can
killed = killed || CanUse(RG_MEGATON_HAMMER); killed = CanUse(RG_MEGATON_HAMMER);
[[fallthrough]]; [[fallthrough]];
case ED_SHORT_JUMPSLASH: case ED_SHORT_JUMPSLASH:
killed = killed || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_KOKIRI_SWORD); killed = killed || CanUse(RG_KOKIRI_SWORD);
[[fallthrough]]; [[fallthrough]];
case ED_MASTER_SWORD_JUMPSLASH: case ED_MASTER_SWORD_JUMPSLASH:
killed = killed || CanUse(RG_MASTER_SWORD); killed = killed || CanUse(RG_MASTER_SWORD);
@ -433,15 +433,19 @@ namespace Rando {
case ED_LONG_JUMPSLASH: case ED_LONG_JUMPSLASH:
killed = killed || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS); killed = killed || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS);
[[fallthrough]]; [[fallthrough]];
case ED_RANG_OR_HOOKSHOT: case ED_BOOMERANG:
//RANDOTODO test dins, bomb and chu range in a practical example //RANDOTODO test dins, bomb and chu range in a practical example
killed = killed || CanUse(RG_HOOKSHOT) || CanUse(RG_BOMB_BAG) || (wallOrFloor && CanUse(RG_BOMBCHU_5)) || CanUse(RG_DINS_FIRE); killed = killed || CanUse(RG_BOMB_BAG) || CanUse(RG_DINS_FIRE);
[[fallthrough]];
case ED_HOOKSHOT:
//RANDOTODO test dins, bomb and chu range in a practical example
killed = killed || CanUse(RG_HOOKSHOT) || (wallOrFloor && CanUse(RG_BOMBCHU_5));
[[fallthrough]]; [[fallthrough]];
case ED_LONGSHOT: case ED_LONGSHOT:
killed = killed || CanUse(RG_LONGSHOT); killed = killed || CanUse(RG_LONGSHOT);
[[fallthrough]]; [[fallthrough]];
case ED_FAR: case ED_FAR:
killed = CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW); killed = killed || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
break; break;
} }
return killed; return killed;
@ -450,7 +454,33 @@ namespace Rando {
return CanJumpslash() || HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW); return CanJumpslash() || HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
case RE_KEESE: case RE_KEESE:
case RE_FIRE_KEESE: case RE_FIRE_KEESE:
return CanJumpslash() || HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG); switch (distance){
case ED_CLOSE:
case ED_SHORT_JUMPSLASH:
killed = CanUse(RG_MEGATON_HAMMER) || CanUse(RG_KOKIRI_SWORD);
[[fallthrough]];
case ED_MASTER_SWORD_JUMPSLASH:
killed = killed || CanUse(RG_MASTER_SWORD);
[[fallthrough]];
case ED_LONG_JUMPSLASH:
killed = killed || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS);
[[fallthrough]];
case ED_BOOMERANG:
//RANDOTODO test dins, bomb and chu range in a practical example
killed = killed || CanUse(RG_BOOMERANG) || (!inWater && CanUse(RG_BOMB_BAG));
[[fallthrough]];
case ED_HOOKSHOT:
//RANDOTODO test dins, bomb and chu range in a practical example
killed = killed || CanUse(RG_HOOKSHOT) || (wallOrFloor && CanUse(RG_BOMBCHU_5));
[[fallthrough]];
case ED_LONGSHOT:
killed = killed || CanUse(RG_LONGSHOT);
[[fallthrough]];
case ED_FAR:
killed = killed || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
break;
}
return killed;
case RE_BLUE_BUBBLE: case RE_BLUE_BUBBLE:
//RANDOTODO Trick to use shield hylian shield as child to stun these guys //RANDOTODO Trick to use shield hylian shield as child to stun these guys
//RANDOTODO check hammer damage //RANDOTODO check hammer damage
@ -500,6 +530,37 @@ namespace Rando {
return CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_STICKS) || HasExplosives() || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE) || CanUse(RG_FIRE_ARROWS); return CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_STICKS) || HasExplosives() || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE) || CanUse(RG_FIRE_ARROWS);
case RE_SPIKE: 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) || CanUse(RG_DINS_FIRE); return 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);
case RE_STINGER:
switch (distance){
case ED_CLOSE:
case ED_SHORT_JUMPSLASH:
killed = CanUse(RG_MEGATON_HAMMER) || CanUse(RG_KOKIRI_SWORD);
[[fallthrough]];
case ED_MASTER_SWORD_JUMPSLASH:
killed = killed || CanUse(RG_MASTER_SWORD);
[[fallthrough]];
case ED_LONG_JUMPSLASH:
killed = killed || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS);
[[fallthrough]];
case ED_BOOMERANG:
//RANDOTODO test dins, bomb and chu range in a practical example
killed = killed || (!inWater && CanUse(RG_BOMB_BAG));
[[fallthrough]];
case ED_HOOKSHOT:
//RANDOTODO test dins, bomb and chu range in a practical example
killed = killed || CanUse(RG_HOOKSHOT) || (wallOrFloor && CanUse(RG_BOMBCHU_5));
[[fallthrough]];
case ED_LONGSHOT:
killed = killed || CanUse(RG_LONGSHOT);
[[fallthrough]];
case ED_FAR:
killed = killed || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
break;
}
return killed;
case RE_BIG_OCTO:
//If chasing octo is annoying but with rolls you can catch him, and you need rang to get into this room without shenanigains anyway. Bunny makes it free
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_STICKS) || CanUse(RG_MASTER_SWORD);
default: default:
SPDLOG_ERROR("CanKillEnemy reached `default`."); SPDLOG_ERROR("CanKillEnemy reached `default`.");
assert(false); assert(false);
@ -545,6 +606,7 @@ namespace Rando {
// we need a way to check if suns won't force a reload // we need a way to check if suns won't force a reload
return CanUse(RG_HOOKSHOT) || CanUse(RG_SUNS_SONG); return CanUse(RG_HOOKSHOT) || CanUse(RG_SUNS_SONG);
case RE_IRON_KNUCKLE: case RE_IRON_KNUCKLE:
case RE_BIG_OCTO:
return false; return false;
case RE_GREEN_BUBBLE: case RE_GREEN_BUBBLE:
return TakeDamage() || CanUse(RG_NUTS) || CanUse(RG_BOOMERANG) || CanUse(RG_HOOKSHOT); return TakeDamage() || CanUse(RG_NUTS) || CanUse(RG_BOOMERANG) || CanUse(RG_HOOKSHOT);
@ -582,6 +644,7 @@ namespace Rando {
case RE_GREEN_BUBBLE: case RE_GREEN_BUBBLE:
case RE_FREEZARD: case RE_FREEZARD:
case RE_SPIKE: case RE_SPIKE:
case RE_BIG_OCTO:
return true; return true;
case RE_MAD_SCRUB: case RE_MAD_SCRUB:
case RE_KEESE: case RE_KEESE:
@ -604,15 +667,33 @@ namespace Rando {
if (distance <= ED_MASTER_SWORD_JUMPSLASH){ if (distance <= ED_MASTER_SWORD_JUMPSLASH){
return true; return true;
} }
bool drop = false;
switch(enemy) { switch(enemy) {
case RE_GOLD_SKULLTULA: case RE_GOLD_SKULLTULA:
switch(distance){
case ED_CLOSE:
case ED_SHORT_JUMPSLASH:
case ED_MASTER_SWORD_JUMPSLASH:
case ED_LONG_JUMPSLASH:
case ED_BOOMERANG:
drop = drop || CanUse(RG_BOOMERANG);
[[fallthrough]];
case ED_HOOKSHOT:
drop = drop || CanUse(RG_HOOKSHOT);
[[fallthrough]];
case ED_LONGSHOT:
drop = drop || CanUse(RG_LONGSHOT);
[[fallthrough]];
case ED_FAR:
return drop;
//RANDOTODO double check all jumpslash kills that might be out of jump/backflip range //RANDOTODO double check all jumpslash kills that might be out of jump/backflip range
return distance <= ED_SHORT_JUMPSLASH || (distance <= ED_RANG_OR_HOOKSHOT && (CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG))) || (distance == ED_LONGSHOT && CanUse(RG_LONGSHOT)); }
break;
case RE_KEESE: case RE_KEESE:
case RE_FIRE_KEESE: case RE_FIRE_KEESE:
return true; return true;
default: default:
return aboveLink || (distance <= ED_RANG_OR_HOOKSHOT && CanUse(RG_BOOMERANG)); return aboveLink || (distance <= ED_BOOMERANG && CanUse(RG_BOOMERANG));
} }
} }
@ -676,12 +757,12 @@ namespace Rando {
return CanJumpslashExceptHammer() || CanUse(RG_MEGATON_HAMMER); return CanJumpslashExceptHammer() || CanUse(RG_MEGATON_HAMMER);
} }
bool Logic::CanHitSwitch(EnemyDistance distance) { bool Logic::CanHitSwitch(EnemyDistance distance, bool inWater) {
bool hit = false; bool hit = false;
switch (distance){ switch (distance){
case ED_CLOSE: case ED_CLOSE:
case ED_SHORT_JUMPSLASH: case ED_SHORT_JUMPSLASH:
hit = hit || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MEGATON_HAMMER); hit = CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MEGATON_HAMMER);
[[fallthrough]]; [[fallthrough]];
case ED_MASTER_SWORD_JUMPSLASH: case ED_MASTER_SWORD_JUMPSLASH:
hit = hit || CanUse(RG_MASTER_SWORD); hit = hit || CanUse(RG_MASTER_SWORD);
@ -689,15 +770,19 @@ namespace Rando {
case ED_LONG_JUMPSLASH: case ED_LONG_JUMPSLASH:
hit = hit || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS); hit = hit || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS);
[[fallthrough]]; [[fallthrough]];
case ED_RANG_OR_HOOKSHOT: case ED_BOOMERANG:
//RANDOTODO test bomb and chu range in a practical example //RANDOTODO test bomb and chu range in a practical example
hit = hit || HookshotOrBoomerang() || HasExplosives() ; hit = hit || CanUse(RG_BOOMERANG) || (!inWater && CanUse(RG_BOMB_BAG)) ;
[[fallthrough]];
case ED_HOOKSHOT:
//RANDOTODO test bomb and chu range in a practical example
hit = hit || CanUse(RG_HOOKSHOT) || CanUse(RG_BOMBCHU_5) ;
[[fallthrough]]; [[fallthrough]];
case ED_LONGSHOT: case ED_LONGSHOT:
hit = hit || CanUse(RG_LONGSHOT); hit = hit || CanUse(RG_LONGSHOT);
[[fallthrough]]; [[fallthrough]];
case ED_FAR: case ED_FAR:
hit = CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW); hit = hit || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
break; break;
} }
return hit; return hit;
@ -1946,6 +2031,11 @@ namespace Rando {
ShadowTrialFirstChest = false; ShadowTrialFirstChest = false;
MQGTGMazeSwitch = false; MQGTGMazeSwitch = false;
GTGPlatformSilverRupees = false; GTGPlatformSilverRupees = false;
MQJabuHolesRoomDoor = false;
JabuWestTentacle = false;
JabuNorthTentacle = false;
LoweredJabuPath = false;
MQJabuLiftRoomCow = false;
StopPerformanceTimer(PT_LOGIC_RESET); StopPerformanceTimer(PT_LOGIC_RESET);
} }

View File

@ -150,6 +150,11 @@ class Logic {
bool MQGTGMazeSwitch = false; bool MQGTGMazeSwitch = false;
bool MQGTGRightSideSwitch = false; bool MQGTGRightSideSwitch = false;
bool GTGPlatformSilverRupees = false; bool GTGPlatformSilverRupees = false;
bool MQJabuHolesRoomDoor = false;
bool JabuWestTentacle = false;
bool JabuNorthTentacle = false;
bool LoweredJabuPath = false;
bool MQJabuLiftRoomCow = false;
/* --- END OF HELPERS AND LOCATION ACCESS --- */ /* --- END OF HELPERS AND LOCATION ACCESS --- */
@ -163,7 +168,7 @@ class Logic {
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched); bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched);
bool CanDoGlitch(GlitchType glitch); bool CanDoGlitch(GlitchType glitch);
bool CanEquipSwap(RandomizerGet itemName); bool CanEquipSwap(RandomizerGet itemName);
bool CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool wallOrFloor = true, uint8_t quantity = 1, bool timer = false); bool CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool wallOrFloor = true, uint8_t quantity = 1, bool timer = false, bool inWater = false);
bool CanPassEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool wallOrFloor = true); bool CanPassEnemy(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool wallOrFloor = true);
bool CanAvoidEnemy(RandomizerEnemy enemy); bool CanAvoidEnemy(RandomizerEnemy enemy);
bool CanGetEnemyDrop(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool aboveLink = false); bool CanGetEnemyDrop(RandomizerEnemy enemy, EnemyDistance distance = ED_CLOSE, bool aboveLink = false);
@ -178,7 +183,7 @@ class Logic {
bool HasBottle(); bool HasBottle();
bool CanJumpslashExceptHammer(); bool CanJumpslashExceptHammer();
bool CanJumpslash(); bool CanJumpslash();
bool CanHitSwitch(EnemyDistance distance = ED_CLOSE); bool CanHitSwitch(EnemyDistance distance = ED_CLOSE, bool inWater = false);
bool CanDamage(); bool CanDamage();
bool CanAttack(); bool CanAttack();
bool BombchusEnabled(); bool BombchusEnabled();

View File

@ -586,9 +586,16 @@ typedef enum {
RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM,
RR_JABU_JABUS_BELLY_MQ_BEGINNING, RR_JABU_JABUS_BELLY_MQ_BEGINNING,
RR_JABU_JABUS_BELLY_MQ_MAIN, RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM,
RR_JABU_JABUS_BELLY_MQ_DEPTHS, RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE,
RR_JABU_JABUS_BELLY_MQ_BOSS_AREA, RR_JABU_JABUS_BELLY_MQ_UNDERWATER_ALCOVE,
RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM,
RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM,
RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR,
RR_JABU_JABUS_BELLY_MQ_WEST_FORKED_ROOMS,
RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM,
RR_JABU_JABUS_BELLY_MQ_PAST_OCTO,
RR_JABU_JABUS_BELLY_MQ_EAST_ROOM,
RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY,
RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ROOM,
@ -4500,6 +4507,8 @@ typedef enum {
RE_FREEZARD, RE_FREEZARD,
RE_SPIKE, RE_SPIKE,
RE_WHITE_WOLFOS, RE_WHITE_WOLFOS,
RE_STINGER,
RE_BIG_OCTO,
} RandomizerEnemy; } RandomizerEnemy;
//RANDOTODO compare child long jumpslash range with adult short //RANDOTODO compare child long jumpslash range with adult short
@ -4510,7 +4519,8 @@ typedef enum {
ED_MASTER_SWORD_JUMPSLASH, ED_MASTER_SWORD_JUMPSLASH,
//sticks or BGS //sticks or BGS
ED_LONG_JUMPSLASH, ED_LONG_JUMPSLASH,
ED_RANG_OR_HOOKSHOT, ED_BOOMERANG,
ED_HOOKSHOT,
ED_LONGSHOT, ED_LONGSHOT,
ED_FAR, ED_FAR,
} EnemyDistance; } EnemyDistance;