diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 23f938d79..196a3254e 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -263,16 +263,58 @@ void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) { } void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t flag) { - if (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF && - sceneNum == SCENE_GERUDOS_FORTRESS && flagType == FLAG_SCENE_SWITCH && flag == 0x3A) { - Flags_SetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN); - } + if (flagType == FLAG_SCENE_SWITCH) { + auto dungeonInfo = Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(sceneNum); + bool isVanilla = dungeonInfo == nullptr || dungeonInfo->IsVanilla(); - if (sceneNum == SCENE_SPIRIT_TEMPLE && flagType == FLAG_SCENE_SWITCH) { - bool isVanilla = - Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla(); - if (isVanilla && flag == 0x23) { - Flags_SetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON); + switch (sceneNum) { + case SCENE_GERUDOS_FORTRESS: + if (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF && flag == 0x3A) { + Flags_SetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN); + } + break; + case SCENE_DEKU_TREE: + if (!isVanilla && flag == 0x27) { + Flags_SetRandomizerInf(RAND_INF_DEKU_TREE_MQ_TORCH_SWITCH); + } + break; + case SCENE_DODONGOS_CAVERN: + if (!isVanilla && flag == 0x25) { + Flags_SetRandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEES); + } + break; + case SCENE_JABU_JABU: + if (isVanilla && flag == 0x3b) { + Flags_SetRandomizerInf(RAND_INF_JABU_JABUS_BELLY_FIRST_SWITCH); + } + break; + case SCENE_FOREST_TEMPLE: + if (flag == 0x26) { + Flags_SetRandomizerInf(RAND_INF_FOREST_DRAINED_WELL); + } else if (flag == 0x25) { + Flags_SetRandomizerInf(RAND_INF_FOREST_LOBBY_EYES); + if (!isVanilla) { + Flags_SetSwitch(gPlayState, 0x2a); + } + } else if (!isVanilla && flag == 0x2a) { + Flags_SetRandomizerInf(RAND_INF_FOREST_LOBBY_EYES); + Flags_SetSwitch(gPlayState, 0x25); + } else if (!isVanilla && flag == 0x21) { + Flags_SetRandomizerInf(RAND_INF_FOREST_MQ_COURTYARD_WEB_BURNT); + } + break; + case SCENE_FIRE_TEMPLE: + if (!isVanilla && flag == 0x28) { + Flags_SetRandomizerInf(RAND_INF_FIRE_MQ_LOBBY_TORCHES); + } + break; + case SCENE_SPIRIT_TEMPLE: + if (isVanilla && flag == 0x23) { + Flags_SetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON); + } else if (!isVanilla && flag == 0x37) { + Flags_SetRandomizerInf(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEES); + } + break; } } @@ -1931,12 +1973,51 @@ void RandomizerOnActorInitHandler(void* actorRef) { Actor* actor = static_cast(actorRef); if (actor->id == ACTOR_PLAYER) { - if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE) { - bool isVanilla = - Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla(); - if (isVanilla && Flags_GetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON)) { - Flags_SetSwitch(gPlayState, 0x23); - } + auto dungeonInfo = Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(gPlayState->sceneNum); + bool isVanilla = dungeonInfo == nullptr || dungeonInfo->IsVanilla(); + switch (gPlayState->sceneNum) { + case SCENE_DEKU_TREE: + if (!isVanilla && Flags_GetRandomizerInf(RAND_INF_DEKU_TREE_MQ_TORCH_SWITCH)) { + Flags_SetSwitch(gPlayState, 0x27); + } + break; + case SCENE_DODONGOS_CAVERN: + if (!isVanilla && Flags_GetRandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEES)) { + Flags_SetSwitch(gPlayState, 0x25); + } + break; + case SCENE_JABU_JABU: + if (isVanilla && Flags_GetRandomizerInf(RAND_INF_JABU_JABUS_BELLY_FIRST_SWITCH)) { + Flags_SetSwitch(gPlayState, 0x3b); + } + break; + case SCENE_FOREST_TEMPLE: + if (Flags_GetRandomizerInf(RAND_INF_FOREST_DRAINED_WELL)) { + Flags_SetSwitch(gPlayState, 0x26); + } + if (Flags_GetRandomizerInf(RAND_INF_FOREST_LOBBY_EYES)) { + Flags_SetSwitch(gPlayState, 0x25); + if (!isVanilla) { + Flags_SetSwitch(gPlayState, 0x2a); + } + } + if (!isVanilla && Flags_GetRandomizerInf(RAND_INF_FOREST_MQ_COURTYARD_WEB_BURNT)) { + Flags_SetSwitch(gPlayState, 0x21); + } + break; + case SCENE_FIRE_TEMPLE: + if (!isVanilla && Flags_GetRandomizerInf(RAND_INF_FIRE_MQ_LOBBY_TORCHES)) { + Flags_SetSwitch(gPlayState, 0x28); + } + break; + case SCENE_SPIRIT_TEMPLE: + if (isVanilla && Flags_GetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON)) { + Flags_SetSwitch(gPlayState, 0x23); + } + if (!isVanilla && Flags_GetRandomizerInf(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEES)) { + Flags_SetSwitch(gPlayState, 0x37); + } + break; } } diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp index 4ad0cf482..ff50b368c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -99,6 +99,7 @@ void RegionTable_Init_ForestTemple() { Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}), Entrance(RR_FOREST_TEMPLE_MAP_ROOM, []{return true;}), Entrance(RR_FOREST_TEMPLE_SEWER, []{return logic->HasItem(RG_GOLDEN_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), + Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL);}), Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return false;}), }); @@ -132,6 +133,7 @@ void RegionTable_Init_ForestTemple() { Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_UPPER, []{return logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_VINES) && logic->CanUse(RG_HOOKSHOT));}), Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND, []{return logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_FOREST_TEMPLE_SEWER, []{return (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16;}), + Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL);}), }); areaTable[RR_FOREST_TEMPLE_NE_COURTYARD_UPPER] = Region("Forest Temple NE Courtyard Upper", SCENE_FOREST_TEMPLE, { @@ -139,12 +141,12 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_STICK_ACCESS, []{return logic->CanGetDekuBabaSticks();}), EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), EventAccess(LOGIC_FOREST_SUMMON_NE_SCARECROW, []{return ctx->GetTrickOption(RT_FOREST_DOORFRAME) && logic->CanJumpslash() && logic->CanUse(RG_HOVER_BOOTS) && logic->ScarecrowsSong();}), + EventAccess(LOGIC_FOREST_DRAINED_WELL, []{return true;}), }, {}, { //Exits Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, []{return true;}), Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND, []{return logic->IsAdult && ctx->GetTrickOption(RT_FOREST_COURTYARD_LEDGE) && logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_FOREST_TEMPLE_MAP_ROOM, []{return true;}), - Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return true;}), }); areaTable[RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND] = Region("Forest Temple NE Courtyard Island", SCENE_FOREST_TEMPLE, { @@ -540,7 +542,10 @@ void RegionTable_Init_ForestTemple() { Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return Here(RR_FOREST_TEMPLE_MQ_REDEAD_ROOM, []{return logic->CanKillEnemy(RE_REDEAD);});}), }); - areaTable[RR_FOREST_TEMPLE_MQ_NW_COURTYARD] = Region("Forest Temple MQ NW Courtyard", SCENE_FOREST_TEMPLE, {}, { + areaTable[RR_FOREST_TEMPLE_MQ_NW_COURTYARD] = Region("Forest Temple MQ NW Courtyard", SCENE_FOREST_TEMPLE, { + //Events + EventAccess(LOGIC_FOREST_MQ_BURNED_WEB, []{return logic->CanUse(RG_FIRE_ARROWS);}), + }, { //Locations LOCATION(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), //the well checks are considered from both areas instead of being a region because the draining is a temp flag and the skull (as well as the chest with hook glitch) has different breath timers from each side @@ -553,30 +558,43 @@ void RegionTable_Init_ForestTemple() { LOCATION(RC_FOREST_TEMPLE_MQ_WELL_EAST_HEART, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), }, { //Exits - Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD, []{return (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16;}), - Entrance(RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE, []{return logic->CanUse(RG_FIRE_ARROWS);}), // temp flag, can't be event - Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}), + Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL) || ((((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16);}), + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE, []{return logic->Get(LOGIC_FOREST_MQ_BURNED_WEB) && (logic->CanKillEnemy(RE_BIG_SKULLTULA, ED_LONGSHOT) || logic->CanUse(RG_BOMBCHU_5));}), + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}), }); - areaTable[RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE] = Region("Forest Temple MQ North Passage", SCENE_FOREST_TEMPLE, {}, {}, { - Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return logic->HasFireSourceWithTorch();}), - Entrance(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES, []{return true;}), + areaTable[RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE] = Region("Forest Temple MQ NW Courtyard Upper Alcove", SCENE_FOREST_TEMPLE, { + //Events + EventAccess(LOGIC_FOREST_MQ_BURNED_WEB, []{return logic->HasFireSource();}), + }, {}, { + //Exits + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage();}), + Entrance(RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE, []{return true;}), + }); + + areaTable[RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE] = Region("Forest Temple MQ North Passage", SCENE_FOREST_TEMPLE, { + //Events + EventAccess(LOGIC_FOREST_MQ_BURNED_WEB, []{return logic->HasFireSourceWithTorch();}), + }, {}, { + //Exits + Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE, []{return logic->Get(LOGIC_FOREST_MQ_BURNED_WEB);}), + Entrance(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES, []{return true;}), }); - //The well only considers the eye target here because the eye target is a temp flag, making it unwieldy to use as an EventAccess to make it it's own room areaTable[RR_FOREST_TEMPLE_MQ_NE_COURTYARD] = Region("Forest Temple MQ NE Courtyard", SCENE_FOREST_TEMPLE, { //Events - EventAccess(LOGIC_STICK_ACCESS, []{return logic->CanGetDekuBabaSticks();}), - EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_STICK_ACCESS, []{return logic->CanGetDekuBabaSticks();}), + EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), + EventAccess(LOGIC_FOREST_DRAINED_WELL, []{return logic->CanHitEyeTargets();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, logic->CanHitEyeTargets() || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)), + LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)), LOCATION(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), //implies logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) - LOCATION(RC_FOREST_TEMPLE_MQ_GS_WELL, logic->CanHitEyeTargets() || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))), - LOCATION(RC_FOREST_TEMPLE_MQ_WELL_WEST_HEART, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->CanHitEyeTargets()), - LOCATION(RC_FOREST_TEMPLE_MQ_WELL_MIDDLE_HEART, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->CanHitEyeTargets()), - LOCATION(RC_FOREST_TEMPLE_MQ_WELL_EAST_HEART, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->CanHitEyeTargets()), + LOCATION(RC_FOREST_TEMPLE_MQ_GS_WELL, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))), + LOCATION(RC_FOREST_TEMPLE_MQ_WELL_WEST_HEART, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), + LOCATION(RC_FOREST_TEMPLE_MQ_WELL_MIDDLE_HEART, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), + LOCATION(RC_FOREST_TEMPLE_MQ_WELL_EAST_HEART, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 571cc621f..6dc0ffdd9 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -269,8 +269,10 @@ typedef enum { LOGIC_JABU_LOWERED_PATH, LOGIC_JABU_MQ_HOLES_ROOM_DOOR, LOGIC_JABU_MQ_LIFT_ROOM_COW, + LOGIC_FOREST_DRAINED_WELL, LOGIC_FOREST_SUMMON_NE_SCARECROW, LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS, + LOGIC_FOREST_MQ_BURNED_WEB, LOGIC_FOREST_CAN_TWIST_HALLWAY, LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, LOGIC_FOREST_OPEN_BOSS_HALLWAY, @@ -870,6 +872,7 @@ typedef enum { RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, RR_FOREST_TEMPLE_MQ_REDEAD_ROOM, RR_FOREST_TEMPLE_MQ_NW_COURTYARD, + RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE, RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE, RR_FOREST_TEMPLE_MQ_NE_COURTYARD, RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES, diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index b7d37725d..ad928e855 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -1218,8 +1218,16 @@ DEFINE_RAND_INF(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5) DEFINE_RAND_INF(RAND_INF_TH_ITEM_FROM_LEADER_OF_FORTRESS) DEFINE_RAND_INF(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN) +DEFINE_RAND_INF(RAND_INF_DEKU_TREE_MQ_TORCH_SWITCH) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEES) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_FIRST_SWITCH) +DEFINE_RAND_INF(RAND_INF_FOREST_LOBBY_EYES) +DEFINE_RAND_INF(RAND_INF_FOREST_DRAINED_WELL) +DEFINE_RAND_INF(RAND_INF_FOREST_MQ_COURTYARD_WEB_BURNT) +DEFINE_RAND_INF(RAND_INF_FIRE_MQ_LOBBY_TORCHES) DEFINE_RAND_INF(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON) DEFINE_RAND_INF(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED) +DEFINE_RAND_INF(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEES) DEFINE_RAND_INF(RAND_INF_ZELDAS_LETTER) DEFINE_RAND_INF(RAND_INF_WEIRD_EGG)