Skip to content

Commit

Permalink
[Enhancement] Add Skip Song of Time Cutscenes (#971)
Browse files Browse the repository at this point in the history
* skip song of time cutscenes

* cleanup better sodt respawn data
  • Loading branch information
Archez authored Jan 30, 2025
1 parent 41ebe7e commit 192118f
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 9 deletions.
3 changes: 3 additions & 0 deletions mm/2s2h/BenGui/BenMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,9 @@ void BenMenu::AddEnhancements() {
AddWidget(path, "Faster Song Playback", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.Songs.FasterSongPlayback")
.Options(CheckboxOptions().Tooltip("Speeds up the playback of songs."));
AddWidget(path, "Skip Song of Time cutscenes", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.Songs.SkipSoTCutscenes")
.Options(CheckboxOptions().Tooltip("Skips the cutscenes when playing any of the Song of Time songs"));

// Time Savers
path = { "Enhancements", "Time Savers", 1 };
Expand Down
19 changes: 10 additions & 9 deletions mm/2s2h/Enhancements/Songs/BetterSongOfDoubleTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,16 @@ void OnPlayerUpdate(Actor* actor) {

gPlayState->nextEntrance = gSaveContext.save.entrance;
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_INSTANT;

gSaveContext.respawn[RESPAWN_MODE_DOWN].entrance = gSaveContext.save.entrance;
gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex = gPlayState->roomCtx.curRoom.num;
gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = player->actor.world.pos;
gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = player->actor.shape.rot.y;
gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = PLAYER_PARAMS(0xFF, PLAYER_INITMODE_D);
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST;
gSaveContext.respawnFlag = -8;
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK_FAST;

Play_SetRespawnData(&gPlayState->state, RESPAWN_MODE_RETURN, gSaveContext.save.entrance,
gPlayState->roomCtx.curRoom.num, PLAYER_PARAMS(0xFF, PLAYER_INITMODE_B),
&player->actor.world.pos, player->actor.world.rot.y);
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK;
gSaveContext.respawnFlag = 2;

// Stop BGM so that new day sequences can play
gSaveContext.seqId = (u8)NA_BGM_DISABLED;

GameInteractor::Instance->UnregisterGameHookForID<GameInteractor::OnActorKill>(onEnTest6KillHookId);
onEnTest6KillHookId = 0;
Expand Down
68 changes: 68 additions & 0 deletions mm/2s2h/Enhancements/Songs/SkipSoTCutscenes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <libultraship/bridge.h>
#include "2s2h/GameInteractor/GameInteractor.h"
#include "2s2h/ShipInit.hpp"

extern "C" {
#include "variables.h"
#include "overlays/actors/ovl_En_Test6/z_en_test6.h"

void EnTest6_DoubleSoTCutscene(EnTest6* thisx, PlayState* play);
void EnTest6_InvertedSoTCutscene(EnTest6* thisx, PlayState* play);
void EnTest6_StopDoubleSoTCutscene(EnTest6* thisx, PlayState* play);
void EnTest6_StopInvertedSoTCutscene(EnTest6* thisx, PlayState* play);
}

#define CVAR_NAME "gEnhancements.Songs.SkipSoTCutscenes"
#define CVAR CVarGetInteger(CVAR_NAME, 0)

void RegisterSkipSoTCutscenes() {
// Song of Time cutscene plays as part of an entrance, so set the time and
// hijack the entrance to the destination
COND_VB_SHOULD(VB_PLAY_TRANSITION_CS, CVAR, {
if ((gSaveContext.save.entrance == ENTRANCE(CUTSCENE, 0) ||
gSaveContext.save.entrance == ENTRANCE(CUTSCENE, 1)) &&
gSaveContext.save.cutsceneIndex == 0xFFF7) {
gSaveContext.save.eventDayCount = 0;
gSaveContext.save.day = 0;
gSaveContext.save.time = CLOCK_TIME(6, 0) - 1;

if (gSaveContext.save.entrance == ENTRANCE(CUTSCENE, 1)) {
// Loads to flash back montage before going to Dawn of... in clock town
// Use ENTRANCE(SOUTH_CLOCK_TOWN, 10) if we ever add a story cutscene skip for the flash backs
gSaveContext.save.entrance = ENTRANCE(LOST_WOODS, 1);
} else {
// Directly to Dawn of... in clock town
gSaveContext.save.entrance = ENTRANCE(SOUTH_CLOCK_TOWN, 0);
}

gSaveContext.save.cutsceneIndex = 0;
}
});

// Skips inverted/double time cutscenes by forcing the actor to stop
COND_ID_HOOK(OnActorUpdate, ACTOR_EN_TEST6, CVAR, [](Actor* actor) {
EnTest6* enTest6 = (EnTest6*)actor;

if (enTest6->actionFunc == EnTest6_DoubleSoTCutscene) {
enTest6->actionFunc = EnTest6_StopDoubleSoTCutscene;
Player* player = GET_PLAYER(gPlayState);

// Respawns the player out when going from day -> night
// copied from last cutscene cue SOTCS_CUEID_DOUBLE_END in EnTest6_SharedSoTCutscene
if (gSaveContext.save.time > CLOCK_TIME(12, 0)) {
Play_SetRespawnData(&gPlayState->state, RESPAWN_MODE_RETURN, gSaveContext.save.entrance,
player->unk_3CE, PLAYER_PARAMS(0xFF, PLAYER_INITMODE_B), &player->unk_3C0,
player->unk_3CC);
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->nextEntrance = gSaveContext.respawn[RESPAWN_MODE_RETURN].entrance;
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;
gSaveContext.respawnFlag = 2;
gPlayState->msgCtx.ocarinaMode = OCARINA_MODE_END;
}
} else if (enTest6->actionFunc == EnTest6_InvertedSoTCutscene) {
enTest6->actionFunc = EnTest6_StopInvertedSoTCutscene;
}
});
}

static RegisterShipInitFunc initFunc(RegisterSkipSoTCutscenes, { CVAR_NAME });

0 comments on commit 192118f

Please sign in to comment.