Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pause Warp Enhancement #3223

Merged
merged 22 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions soh/include/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -2467,6 +2467,10 @@ void Message_DrawText(PlayState* play, Gfx** gfxP);
void Interface_CreateQuadVertexGroup(Vtx* vtxList, s32 xStart, s32 yStart, s32 width, s32 height, u8 flippedH);
void Interface_RandoRestoreSwordless(void);

//Pause Warp
void PauseWarp_HandleSelection();
void PauseWarp_Execute();

// #endregion

#ifdef __cplusplus
Expand Down
1 change: 1 addition & 0 deletions soh/soh/Enhancements/game-interactor/GameInteractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ class GameInteractor {

DEFINE_HOOK(OnFileDropped, void(std::string filePath));
DEFINE_HOOK(OnAssetAltChange, void());
DEFINE_HOOK(OnPauseMenu, void());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this maybe makes more sense as OnKaleidoUpdate

I also assume that this means OnGameFrameUpdate does not run with kaleido open? So you couldn't just also use OnGameFrameUpdate and instead just check some sort of pauseCtx value?

Copy link
Contributor Author

@mckinlee mckinlee Feb 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah, OnGameFrameUpdate does run with Kaleido open. You're right, I could of just checked if pauseCtx->pageIndex == PAUSE_QUEST. However, on my original PR for this @jbodner09 liked the idea of having a hook specific to the pause menu for custom item mods. That comment is here. That's why I kept it in, but it's up to yall. It's not necessary for my use case so I could remove it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, OnGameFrameUpdate is not something we want to use often, so this may be better after all

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I tried to figure out a way around using it for PauseWarp_Execute, but couldn't figure out a easy way to do it. I've made the checks pretty specific so it shouldn't cause any issue anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea should be fine, I still stand by my original rename suggestion though 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine by me and I just changed it in the latest commit.


// Helpers
static bool IsSaveLoaded();
Expand Down
6 changes: 6 additions & 0 deletions soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,9 @@ void GameInteractor_ExecuteOnSetGameLanguage() {
void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)) {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnAssetAltChange>(fn);
}

//MARK: Pause Menu

void GameInteractor_ExecuteOnPauseMenu() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPauseMenu>();
}
3 changes: 3 additions & 0 deletions soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ void GameInteractor_ExecuteOnSetGameLanguage();
// MARK: - System
void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void));

//Mark: - Pause Menu
void GameInteractor_ExecuteOnPauseMenu();

#ifdef __cplusplus
}
#endif
18 changes: 18 additions & 0 deletions soh/soh/Enhancements/mods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,23 @@ void RegisterToTMedallions() {
});
}

void RegisterPauseMenuHooks() {
static bool pauseWarpHooksRegistered = false;
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([&]() {
if (!GameInteractor::IsSaveLoaded() || !CVarGetInteger("gPauseWarp", 0)) {
pauseWarpHooksRegistered = false;
return;
}
if (!pauseWarpHooksRegistered) {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPauseMenu>([]() {PauseWarp_HandleSelection();});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
PauseWarp_Execute();
});
pauseWarpHooksRegistered = true;
}
});
}

void InitMods() {
RegisterTTS();
RegisterInfiniteMoney();
Expand Down Expand Up @@ -1340,4 +1357,5 @@ void InitMods() {
NameTag_RegisterHooks();
RegisterPatchHandHandler();
RegisterHurtContainerModeHandler();
RegisterPauseMenuHooks();
}
92 changes: 92 additions & 0 deletions soh/soh/Enhancements/pausewarp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include "custom-message/CustomMessageTypes.h"
#include "global.h"
#include "z64.h"
#include "game-interactor/GameInteractor.h"

static const int songMessageMap[] = {
TEXT_WARP_MINUET_OF_FOREST,
TEXT_WARP_BOLERO_OF_FIRE,
TEXT_WARP_SERENADE_OF_WATER,
TEXT_WARP_REQUIEM_OF_SPIRIT,
TEXT_WARP_NOCTURNE_OF_SHADOW,
TEXT_WARP_PRELUDE_OF_LIGHT
};

static const int ocarinaSongMap[] = {
OCARINA_SONG_MINUET,
OCARINA_SONG_BOLERO,
OCARINA_SONG_SERENADE,
OCARINA_SONG_REQUIEM,
OCARINA_SONG_NOCTURNE,
OCARINA_SONG_PRELUDE
};

static const int entranceIndexMap[] = {
ENTR_SACRED_FOREST_MEADOW_2, // Minuet
ENTR_DEATH_MOUNTAIN_CRATER_4, // Bolero
ENTR_LAKE_HYLIA_8, // Serenade
ENTR_DESERT_COLOSSUS_5, // Requiem
ENTR_GRAVEYARD_7, // Nocturne
ENTR_TEMPLE_OF_TIME_7 // Prelude
};

static const int songAudioMap[] = {
NA_BGM_OCA_MINUET,
NA_BGM_OCA_BOLERO,
NA_BGM_OCA_SERENADE,
NA_BGM_OCA_REQUIEM,
NA_BGM_OCA_NOCTURNE,
NA_BGM_OCA_LIGHT
};

static bool isWarpActive = false;

void PauseWarp_Execute() {
if (!isWarpActive || gPlayState->msgCtx.msgMode != MSGMODE_NONE) {
return;
}
isWarpActive = false;
GET_PLAYER(gPlayState)->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE;
if (gPlayState->msgCtx.choiceIndex != 0) {
return;
}
if (IS_RANDO) {
Entrance_SetWarpSongEntrance();
return;
}
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_FADE_WHITE_FAST;
for (int i = 0; i < ARRAY_COUNT(ocarinaSongMap); i++) {
if (gPlayState->msgCtx.lastPlayedSong == ocarinaSongMap[i]) {
gPlayState->nextEntranceIndex = entranceIndexMap[i];
return;
}
}
gPlayState->transitionTrigger = TRANS_TRIGGER_OFF;
}

void ActivateWarp(PauseContext* pauseCtx, int song) {
Audio_OcaSetInstrument(0);
Interface_SetDoAction(gPlayState, DO_ACTION_NONE);
pauseCtx->state = 0x12;
WREG(2) = -6240;
func_800F64E0(0);
pauseCtx->unk_1E4 = 0;
int idx = song - QUEST_SONG_MINUET;
gPlayState->msgCtx.lastPlayedSong = ocarinaSongMap[idx];
Audio_SetSoundBanksMute(0x20);
Audio_PlayFanfare(songAudioMap[idx]);
Message_StartTextbox(gPlayState, songMessageMap[idx], NULL);
GET_PLAYER(gPlayState)->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
isWarpActive = true;
}

void PauseWarp_HandleSelection() {
if (gSaveContext.inventory.items[SLOT_OCARINA] != ITEM_NONE) {
int aButtonPressed = CHECK_BTN_ALL(gPlayState->state.input->press.button, BTN_A);
int song = gPlayState->pauseCtx.cursorPoint[PAUSE_QUEST];
if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE) {
ActivateWarp(&gPlayState->pauseCtx, song);
}
}
}
2 changes: 2 additions & 0 deletions soh/soh/SohMenuBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,8 @@ void DrawEnhancementsMenu() {
"- Obtained the Master Sword\n"
"- Not within range of Time Block\n"
"- Not within range of Ocarina playing spots");
UIWidgets::PaddedEnhancementCheckbox("Pause Warp", "gPauseWarp", true, false);
UIWidgets::Tooltip("Selection of warp song in pause menu initiates warp. Disables song playback.");

ImGui::EndTable();
ImGui::EndMenu();
Expand Down
3 changes: 3 additions & 0 deletions soh/src/code/z_kaleido_scope_call.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "global.h"
#include "vt.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"

void (*sKaleidoScopeUpdateFunc)(PlayState* play);
void (*sKaleidoScopeDrawFunc)(PlayState* play);
Expand Down Expand Up @@ -56,6 +57,8 @@ void KaleidoScopeCall_Update(PlayState* play) {
KaleidoMgrOverlay* kaleidoScopeOvl = &gKaleidoMgrOverlayTable[KALEIDO_OVL_KALEIDO_SCOPE];
PauseContext* pauseCtx = &play->pauseCtx;

GameInteractor_ExecuteOnPauseMenu();

if (!gSaveContext.sohStats.gameComplete &&
(!IS_BOSS_RUSH || !gSaveContext.isBossRushPaused)) {
gSaveContext.sohStats.pauseTimer++;
Expand Down
Loading