diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 8aa37a580..f91e3491e 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -281,6 +281,9 @@ typedef enum { VB_SPAWN_BLUE_WARP, // Vanilla condition: this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF VB_BLUE_WARP_APPLY_ENTRANCE_AND_CUTSCENE, + // Vanilla condition: SurfaceType_GetSlope(&play->colCtx, poly, bgId) == 2 + // Opt: int (original next entrance index) + VB_SET_VOIDOUT_FROM_SURFACE, // Vanilla condition: this->collider.base.acFlags & 2 VB_BG_BREAKWALL_BREAK, // Vanilla condition: true diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 000081cec..fa313d763 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -1558,6 +1558,40 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l *should = !Flags_GetInfTable(INFTABLE_145) || Flags_GetInfTable(INFTABLE_146); break; } + case VB_SET_VOIDOUT_FROM_SURFACE: { + // ENTRTODO: Move all entrance rando handling to a dedicated file + std::vector entrPersistTempFlags = { + ENTR_DEKU_TREE_BOSS_ENTRANCE, ENTR_DEKU_TREE_BOSS_DOOR, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, + ENTR_DODONGOS_CAVERN_BOSS_DOOR, ENTR_JABU_JABU_BOSS_ENTRANCE, ENTR_JABU_JABU_BOSS_DOOR, + ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, ENTR_FOREST_TEMPLE_BOSS_DOOR, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE, + ENTR_FIRE_TEMPLE_BOSS_DOOR, ENTR_WATER_TEMPLE_BOSS_ENTRANCE, ENTR_WATER_TEMPLE_BOSS_DOOR, + ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE, ENTR_SPIRIT_TEMPLE_BOSS_DOOR, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE, + ENTR_SHADOW_TEMPLE_BOSS_DOOR, ENTR_SPIRIT_TEMPLE_ENTRANCE, + }; + + s16 originalEntrance = (s16)va_arg(args, int); + + // In Entrance rando, if our respawnFlag is set for a grotto return, we don't want the void out to happen + if (*should == true && RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES)) { + // Check for dungeon special entrances that are randomized to a new location + if (std::find(entrPersistTempFlags.begin(), entrPersistTempFlags.end(), originalEntrance) != + entrPersistTempFlags.end() && originalEntrance != gPlayState->nextEntranceIndex) { + // Normally dungeons use a special voidout between scenes so that entering/exiting a boss room, + // or leaving via Spirit Hands and going back in persist temp flags across scenes. + // For ER, the temp flags should be wiped out so that they aren't transferred to the new location. + gPlayState->actorCtx.flags.tempSwch = 0; + gPlayState->actorCtx.flags.tempCollect = 0; + + // If the respawnFlag is set for a grotto return, we don't want the void out to happen. + // Set the data flag to one to prevent the respawn point from being overriden by dungeon doors. + if (gSaveContext.respawnFlag == 2) { + gSaveContext.respawn[RESPAWN_MODE_DOWN].data = 1; + *should = false; + } + } + } + break; + } case VB_FREEZE_ON_SKULL_TOKEN: case VB_TRADE_TIMER_ODD_MUSHROOM: case VB_TRADE_TIMER_FROG: @@ -1623,6 +1657,7 @@ void RandomizerOnSceneInitHandler(int16_t sceneNum) { CheckTracker::RecalculateAllAreaTotals(); } + // ENTRTODO: Move all entrance rando handling to a dedicated file if (RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES)) { // In ER, override roomNum to load based on scene and spawn during scene init if (gSaveContext.respawnFlag <= 0) { @@ -2336,6 +2371,7 @@ void RandomizerRegisterHooks() { if (!IS_RANDO) return; + // ENTRTODO: Move all entrance rando handling to a dedicated file // Setup the modified entrance table and entrance shuffle table for rando Entrance_Init(); diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index 8f4a1668c..7a492fe9c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -267,13 +267,6 @@ s16 Entrance_PeekNextIndexOverride(int16_t nextEntranceIndex) { } s16 Entrance_OverrideNextIndex(s16 nextEntranceIndex) { - // When entering Spirit Temple, clear temp flags so they don't carry over to the randomized dungeon - if (nextEntranceIndex == ENTR_SPIRIT_TEMPLE_ENTRANCE && Entrance_GetOverride(nextEntranceIndex) != nextEntranceIndex && - gPlayState != NULL) { - gPlayState->actorCtx.flags.tempSwch = 0; - gPlayState->actorCtx.flags.tempCollect = 0; - } - // Exiting through the crawl space from Hyrule Castle courtyard is the same exit as leaving Ganon's castle // Don't override the entrance if we came from the Castle courtyard (day and night scenes) if (gPlayState != NULL && (gPlayState->sceneNum == SCENE_CASTLE_COURTYARD_GUARDS_DAY || gPlayState->sceneNum == SCENE_CASTLE_COURTYARD_GUARDS_NIGHT) && diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 16abaf568..ade67d576 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -5145,9 +5145,9 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol Scene_SetTransitionForNextEntrance(play); } else { - // In Entrance rando, if our respawnFlag is set for a grotto return, we don't want the void out to happen - if (SurfaceType_GetSlope(&play->colCtx, poly, bgId) == 2 && - (!IS_RANDO || (Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES) && gSaveContext.respawnFlag != 2))) { + if (GameInteractor_Should(VB_SET_VOIDOUT_FROM_SURFACE, + SurfaceType_GetSlope(&play->colCtx, poly, bgId) == 2, + play->setupExitList[exitIndex - 1])) { gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = play->nextEntranceIndex; Play_TriggerVoidOut(play); gSaveContext.respawnFlag = -2;