Fix grotto handling with the skip intro timesaver (#4252)

This commit is contained in:
Archez 2024-07-23 21:31:01 -04:00 committed by GitHub
parent c68cecec71
commit e66dada09d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 78 additions and 29 deletions

View File

@ -3,11 +3,11 @@
#include "soh/OTRGlobals.h"
extern "C" {
#include "z64save.h"
#include "functions.h"
#include "soh/Enhancements/randomizer/randomizer_grotto.h"
extern PlayState* gPlayState;
extern SaveContext gSaveContext;
#include "z64save.h"
#include "functions.h"
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
void SkipIntro_Register() {
@ -15,8 +15,10 @@ void SkipIntro_Register() {
// If we're playing rando and if starting age is adult and/or overworld spawns are shuffled we need to skip
// the cutscene regardless of the enhancement being on.
bool adultStart = gSaveContext.linkAge == LINK_AGE_ADULT;
bool shuffleOverworldSpawns = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_OVERWORLD_SPAWNS).Is(true);
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) || (IS_RANDO && (adultStart || shuffleOverworldSpawns))) {
bool shuffleOverworldSpawns =
OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_OVERWORLD_SPAWNS).Is(true);
if ((CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) ||
(IS_RANDO && (adultStart || shuffleOverworldSpawns)) && gSaveContext.cutsceneIndex == 0xFFF1)) {
// Calculate spawn location. Start with vanilla, Link's house.
int32_t spawnEntrance = ENTR_LINKS_HOUSE_0;
// If we're not in rando, we can skip all of the below.
@ -29,10 +31,10 @@ void SkipIntro_Register() {
if (shuffleOverworldSpawns) {
// If we're shuffling overworld spawns the adult spawn is ENTR_HYRULE_FIELD_10 instead of
// ENTR_TEMPLE_OF_TIME_7, so that spawn and Prelude don't share an entrance.
if (adultStart){
if (adultStart) {
spawnEntrance = ENTR_HYRULE_FIELD_10;
}
spawnEntrance = Grotto_OverrideSpecialEntrance(Entrance_GetOverride(spawnEntrance));
spawnEntrance = Entrance_PeekNextIndexOverride(spawnEntrance);
}
}
// Skip the intro cutscene for whatever the spawnEntrance is calculated to be.

View File

@ -260,6 +260,10 @@ s16 Entrance_GetOverride(s16 index) {
return entranceOverrideTable[index];
}
s16 Entrance_PeekNextIndexOverride(int16_t nextEntranceIndex) {
return Grotto_GetEntranceValueHandlingGrottoRando(Entrance_GetOverride(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_0 && Entrance_GetOverride(nextEntranceIndex) != nextEntranceIndex &&

View File

@ -81,6 +81,7 @@ void Entrance_ResetEntranceTable(void);
uint8_t Entrance_EntranceIsNull(EntranceOverride* entranceOverride);
int16_t Entrance_GetOverride(int16_t index);
int16_t Entrance_OverrideNextIndex(int16_t nextEntranceIndex);
int16_t Entrance_PeekNextIndexOverride(int16_t nextEntranceIndex);
int16_t Entrance_OverrideDynamicExit(int16_t dynamicExitIndex);
uint32_t Entrance_SceneAndSpawnAre(uint8_t scene, uint8_t spawn);
void Entrance_SetGameOverEntrance(void);

View File

@ -128,8 +128,49 @@ static void Grotto_SetupReturnInfo(GrottoReturnInfo grotto, RespawnMode respawnM
}
}
// Get the next entrance value while handling conversion of grotto rando IDs to real entrance values.
// This method doesn't change player respawn data, so only use this if you are querying an entrance index.
s16 Grotto_GetEntranceValueHandlingGrottoRando(s16 nextEntranceIndex) {
// Don't change anything unless grotto shuffle has been enabled
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) && !Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) && !Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS)) {
return nextEntranceIndex;
}
// If Link hits a grotto exit, load the entrance index from the grotto exit list
// based on the current grotto ID
if (nextEntranceIndex == ENTR_RETURN_GROTTO) {
nextEntranceIndex = grottoExitList[grottoId];
}
// Get the new grotto id from the next entrance
grottoId = nextEntranceIndex & 0x00FF;
// Grotto Returns
if (nextEntranceIndex >= ENTRANCE_RANDO_GROTTO_EXIT_START && nextEntranceIndex < ENTRANCE_RANDO_GROTTO_EXIT_START + NUM_GROTTOS) {
GrottoReturnInfo grotto = grottoReturnTable[grottoId];
// When the nextEntranceIndex is determined by a dynamic exit,
// or set by Entrance_OverrideBlueWarp to mark a blue warp entrance,
// we have to set the respawn information and nextEntranceIndex manually
if (gPlayState != NULL && gPlayState->nextEntranceIndex != ENTR_LOAD_OPENING) {
nextEntranceIndex = grotto.entranceIndex;
} else if (gPlayState == NULL) { // Handle spawn position when loading from a save file
nextEntranceIndex = grotto.entranceIndex;
// Otherwise return 0x7FFF (ENTR_RETURN_GROTTO) and let the game handle it
} else {
nextEntranceIndex = ENTR_RETURN_GROTTO;
}
// Grotto Loads
} else if (nextEntranceIndex >= ENTRANCE_RANDO_GROTTO_LOAD_START && nextEntranceIndex < ENTRANCE_RANDO_GROTTO_EXIT_START) {
GrottoLoadInfo grotto = grottoLoadTable[grottoId];
nextEntranceIndex = grotto.entranceIndex;
}
return nextEntranceIndex;
}
// Translates and overrides the passed in entrance index if it corresponds to a
// special grotto entrance (grotto load or returnpoint)
// special grotto entrance (grotto load or returnpoint) and updates player respawn data correctly.
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
// Don't change anything unless grotto shuffle has been enabled

View File

@ -24,6 +24,7 @@ typedef struct {
void Grotto_InitExitAndLoadLists(void);
void Grotto_SetExitOverride(s16 originalIndex, s16 overrideIndex);
void Grotto_SetLoadOverride(s16 originalIndex, s16 overrideIndex);
s16 Grotto_GetEntranceValueHandlingGrottoRando(s16 nextEntranceIndex);
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex);
void Grotto_ForceGrottoReturnOnSpecialEntrance(void);
void Grotto_ForceGrottoReturn(void);