diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp index e94556aac..0bb65a8de 100644 --- a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp @@ -3,35 +3,43 @@ #include "soh/OTRGlobals.h" extern "C" { - #include "macros.h" - #include "src/overlays/actors/ovl_En_Ko/z_en_ko.h" - #include "z64save.h" - #include "functions.h" - #include "variables.h" +#include "macros.h" +#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h" +#include "z64save.h" +#include "functions.h" +#include "variables.h" } #define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() +static bool sEnteredBlueWarp = false; + /** * This will override the transitions into the blue warp cutscenes, set any appropriate flags, and * set the entrance index to where you would normally end up after the blue warp cutscene. This * should also account for the difference between your first and following visits to the blue warp. */ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) { - if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) { - uint8_t isBlueWarpCutscene = 0; + bool overrideBlueWarpDestinations = + IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || + RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); + + // Force blue warp skip on when ER needs to place Link somewhere else. + // This is preferred over having story cutscenes play in the overworld and then reloading Link somewhere else after. + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) || overrideBlueWarpDestinations) { + bool isBlueWarpCutscene = false; // Deku Tree Blue warp if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) { gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP; - isBlueWarpCutscene = 1; + isBlueWarpCutscene = true; // Dodongo's Cavern Blue warp } else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT && gSaveContext.cutsceneIndex == 0xFFF1) { gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP; - isBlueWarpCutscene = 1; + isBlueWarpCutscene = true; // Jabu Jabu's Blue warp } else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP && gSaveContext.cutsceneIndex == 0xFFF0) { gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP; - isBlueWarpCutscene = 1; + isBlueWarpCutscene = true; // Forest Temple Blue warp } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) { // Normally set in the blue warp cutscene @@ -43,14 +51,14 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_12; } - isBlueWarpCutscene = 1; + isBlueWarpCutscene = true; // Fire Temple Blue warp } else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE && gSaveContext.cutsceneIndex == 0xFFF3) { // Normally set in the blue warp cutscene Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED); gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP; - isBlueWarpCutscene = 1; + isBlueWarpCutscene = true; // Water Temple Blue warp } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) { // Normally set in the blue warp cutscene @@ -58,15 +66,15 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP; - isBlueWarpCutscene = 1; + isBlueWarpCutscene = true; // Spirit Temple Blue warp } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) { gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP; - isBlueWarpCutscene = 1; + isBlueWarpCutscene = true; // Shadow Temple Blue warp } else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) { gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP; - isBlueWarpCutscene = 1; + isBlueWarpCutscene = true; } if (isBlueWarpCutscene) { @@ -80,10 +88,20 @@ void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_l } // This is outside the above condition because we want to handle both first and following visits to the blue warp - if (IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) { + if (sEnteredBlueWarp && overrideBlueWarpDestinations) { Entrance_OverrideBlueWarp(); } } + + sEnteredBlueWarp = false; +} + +/** + * Using this hook to simply observe that Link has entered a bluewarp + * This way we know to allow entrance rando overrides to be processed on the next tranisition hook + */ +void SkipBlueWarp_ShouldPlayBlueWarpCS(GIVanillaBehavior _, bool* should, va_list originalArgs) { + sEnteredBlueWarp = true; } /** @@ -143,6 +161,7 @@ void SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished(GIVanillaBehavior _, void SkipBlueWarp_Register() { GameInteractor::Instance->RegisterGameHookForID(ACTOR_EN_KO, SkipBlueWarp_OnActorUpdate); GameInteractor::Instance->RegisterGameHookForID(VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS); + GameInteractor::Instance->RegisterGameHookForID(VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS); GameInteractor::Instance->RegisterGameHookForID(VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished); GameInteractor::Instance->RegisterGameHookForID(VB_GIVE_ITEM_FROM_BLUE_WARP, SkipBlueWarp_ShouldGiveItem); } diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index e441f3aa5..5c0f8971f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -198,7 +198,7 @@ void Entrance_Init(void) { bossSceneSaveDeathWarps[bossScene - SCENE_DEKU_TREE_BOSS] = saveWarpEntrance; } - //Overwrite grotto related indices + // Overwrite grotto related indices if (originalIndex >= ENTRANCE_GROTTO_EXIT_START) { Grotto_SetExitOverride(originalIndex, overrideIndex); continue; @@ -226,7 +226,7 @@ void Entrance_Init(void) { s16 indicesToSilenceBackgroundMusic[2] = { // The lost woods music playing near the GC Woods Warp keeps playing - // in the next area if the bvackground music is allowed to keep playing + // in the next area if the background music is allowed to keep playing entranceOverrideTable[ENTR_LOST_WOODS_TUNNEL_SHORTCUT], // Goron City -> Lost Woods override // If Malon is singing at night, then her singing will be transferred @@ -452,7 +452,19 @@ void Entrance_SetWarpSongEntrance(void) { } void Entrance_OverrideBlueWarp(void) { - // Handles first time entering bluewarp (with item give) + // Remap child 2nd visits in adult dungeons for warp pad -> bluewarp + if (gSaveContext.entranceIndex == ENTR_SACRED_FOREST_MEADOW_WARP_PAD) { + gSaveContext.entranceIndex = ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP; + } else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD) { + gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP; + } else if (gSaveContext.entranceIndex == ENTR_LAKE_HYLIA_WARP_PAD) { + gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP; + } else if (gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_WARP_PAD) { + gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP; + } else if (gSaveContext.entranceIndex == ENTR_GRAVEYARD_WARP_PAD) { + gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP; + } + switch (gSaveContext.entranceIndex) { case ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP: // Gohma blue warp case ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP: // KD blue warp @@ -465,20 +477,6 @@ void Entrance_OverrideBlueWarp(void) { gSaveContext.entranceIndex = Entrance_OverrideNextIndex(gSaveContext.entranceIndex); return; } - - // Handles second+ times entering bluewarp - switch (gPlayState->nextEntranceIndex) { - case ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP: // Gohma blue warp - case ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP: // KD blue warp - case ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP: // Barinade blue warp - case ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP: // Phantom Ganon blue warp - case ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP: // Volvagia blue warp - case ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP: // Morpha blue warp - case ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP: // Bongo-Bongo blue warp - case ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP: // Twinrova blue warp - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(gPlayState->nextEntranceIndex); - return; - } } void Entrance_EnableFW(void) { diff --git a/soh/soh/Enhancements/randomizer/randomizer_grotto.c b/soh/soh/Enhancements/randomizer/randomizer_grotto.c index be10e5ec4..cb8eacb1a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_grotto.c +++ b/soh/soh/Enhancements/randomizer/randomizer_grotto.c @@ -99,6 +99,10 @@ void Grotto_InitExitAndLoadLists(void) { grottoLoadList[i] = ENTRANCE_GROTTO_LOAD_START + i; grottoExitList[i] = ENTRANCE_GROTTO_EXIT_START + i; } + + grottoId = 0xFF; + lastEntranceType = NOT_GROTTO; + overridingNextEntrance = false; } void Grotto_SetExitOverride(s16 originalIndex, s16 overrideIndex) {