mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-02-15 23:00:21 -05:00
Feedback Update #2
-Introduced new function 'PauseWarp_Idle' now that 'PauseWarp_Main' is no longer called every frame -Added C wrapper to access 'GameInteractor::IsSaveLoaded' and scrapped the 'IsStateValid' function -Added 'PauseWarp_Idle' to the the 'RegisterPauseWarp' function -Refactored the code some
This commit is contained in:
parent
b1e621b375
commit
362f6426ec
@ -45,6 +45,11 @@ bool GameInteractor::IsSaveLoaded() {
|
||||
return (gPlayState == NULL || player == NULL || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) ? false : true;
|
||||
}
|
||||
|
||||
extern "C" bool IsSaveLoadedWrapper() {
|
||||
GameInteractor* gameInteractor = GameInteractor::Instance;
|
||||
return gameInteractor->IsSaveLoaded();
|
||||
}
|
||||
|
||||
bool GameInteractor::IsGameplayPaused() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
return (Player_InBlockingCsMode(gPlayState, player) || gPlayState->pauseCtx.state != 0 || gPlayState->msgCtx.msgMode != 0) ? true : false;
|
||||
|
@ -33,6 +33,7 @@ extern PlayState* gPlayState;
|
||||
extern void Overlay_DisplayText(float duration, const char* text);
|
||||
uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum);
|
||||
void PauseWarp_Main();
|
||||
void PauseWarp_Idle();
|
||||
}
|
||||
bool performDelayedSave = false;
|
||||
bool performSave = false;
|
||||
@ -979,6 +980,10 @@ void RegisterPauseWarp() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPauseMenu>([]() {
|
||||
PauseWarp_Main();
|
||||
});
|
||||
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
PauseWarp_Idle();
|
||||
});
|
||||
}
|
||||
|
||||
void InitMods() {
|
||||
|
@ -1,110 +1,83 @@
|
||||
// Importing necessary libraries and headers
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "soh/Enhancements/gameconsole.h"
|
||||
#include "global.h"
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
#include "soh/Enhancements/custom-message/CustomMessageTypes.h"
|
||||
|
||||
#include "luslog.h"
|
||||
|
||||
// Defining the structure for the pause warp state, which holds different flags and cooldowns
|
||||
typedef struct {
|
||||
bool warpInitiated, textboxInitiated, inChoosingState, textboxIsOpen, isTextboxClosing;
|
||||
int aButtonCooldown, textboxCheckCooldown, textboxOpenCooldown;
|
||||
} PauseWarpState;
|
||||
|
||||
// Mapping the song messages. Each song corresponds to a specific text message.
|
||||
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 };
|
||||
|
||||
// Mapping the song audio. Each song corresponds to a specific audio ID.
|
||||
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 };
|
||||
|
||||
// Forward declaring the functions used in this file
|
||||
bool IsStateValid(PlayState* play, Player* player, PauseWarpState* state);
|
||||
void ResetStateFlags(PauseWarpState* state);
|
||||
void InitiateWarp(PlayState* play, Player* player, int song, PauseWarpState* state);
|
||||
void HandleWarpConfirmation(PlayState* play, Player* player, PauseWarpState* state);
|
||||
void HandleCooldowns(PauseWarpState* state);
|
||||
extern bool IsSaveLoadedWrapper();
|
||||
|
||||
// Checking if the state is valid. This is a sanity check to ensure we're not operating on null pointers.
|
||||
bool IsStateValid(PlayState* play, Player* player, PauseWarpState* state) {
|
||||
return play && player && state;
|
||||
static PauseWarpState state;
|
||||
|
||||
bool IsPauseWarpEnabled() {
|
||||
return CVarGetInteger("gPauseWarpEnabled", 0) && IsSaveLoadedWrapper();
|
||||
}
|
||||
|
||||
// Resetting all the flags in the state to their default values (which is mostly 'false' for booleans and '0' for integers)
|
||||
void ResetStateFlags(PauseWarpState* state) {
|
||||
*state = (PauseWarpState){0};
|
||||
}
|
||||
|
||||
// Initiating the warp process. Here we set all the required flags and disable player input.
|
||||
void InitiateWarp(PlayState* play, Player* player, int song, PauseWarpState* state) {
|
||||
int idx = song - QUEST_SONG_MINUET; // Calculating the song index
|
||||
Audio_SetSoundBanksMute(0x20); //Mute current BGM
|
||||
Audio_PlayFanfare(songAudioMap[idx]); // Play the corresponding fanfare
|
||||
play->msgCtx.lastPlayedSong = idx; // Storing the last played song
|
||||
play->pauseCtx.state = 0x12; // Setting the pause state
|
||||
Message_StartTextbox(play, songMessageMap[idx], NULL); // Starting the textbox with the appropriate message
|
||||
player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; // Disabling player input
|
||||
*state = (PauseWarpState){.warpInitiated = true, .textboxOpenCooldown = 10, .aButtonCooldown = 10, .textboxCheckCooldown = 5, .textboxIsOpen = true}; // Setting the flags for warp
|
||||
play->msgCtx.choiceIndex = 0; // Resetting the choice index
|
||||
void InitiateWarp(PlayState* play, Player* player, int song) {
|
||||
int idx = song - QUEST_SONG_MINUET;
|
||||
Audio_SetSoundBanksMute(0x20);
|
||||
Audio_PlayFanfare(songAudioMap[idx]);
|
||||
play->msgCtx.lastPlayedSong = idx;
|
||||
play->pauseCtx.state = 0x12;
|
||||
Message_StartTextbox(play, songMessageMap[idx], NULL);
|
||||
player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
|
||||
state = (PauseWarpState){.warpInitiated = true, .textboxOpenCooldown = 10, .aButtonCooldown = 10, .textboxCheckCooldown = 5, .textboxIsOpen = true};
|
||||
play->msgCtx.choiceIndex = 0;
|
||||
}
|
||||
|
||||
// Handling the warp confirmation. This is the part where the player actually gets teleported if they confirmed.
|
||||
void HandleWarpConfirmation(PlayState* play, Player* player, PauseWarpState* state) {
|
||||
if (play->msgCtx.choiceIndex == 0) Entrance_SetWarpSongEntrance(); // Teleporting the player if 'ok' was selected
|
||||
player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; // Re-enabling player input
|
||||
ResetStateFlags(state); // Resetting the state flags
|
||||
void HandleWarpConfirmation(PlayState* play, Player* player) {
|
||||
if (play->msgCtx.choiceIndex == 0) Entrance_SetWarpSongEntrance();
|
||||
player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE;
|
||||
ResetStateFlags(&state);
|
||||
}
|
||||
|
||||
// Managing the cooldowns for different actions and transitions
|
||||
void HandleCooldowns(PauseWarpState* state) {
|
||||
// Decreasing the cooldowns if they're greater than zero
|
||||
if (state->aButtonCooldown > 0) state->aButtonCooldown--;
|
||||
if (state->textboxCheckCooldown > 0) state->textboxCheckCooldown--;
|
||||
if (state->textboxOpenCooldown > 0) state->textboxOpenCooldown--;
|
||||
|
||||
// If the textbox is closing, reset the flag
|
||||
if (state->isTextboxClosing) *state = (PauseWarpState){.isTextboxClosing = false};
|
||||
void HandleCooldowns() {
|
||||
if (state.aButtonCooldown > 0) state.aButtonCooldown--;
|
||||
if (state.textboxCheckCooldown > 0) state.textboxCheckCooldown--;
|
||||
if (state.textboxOpenCooldown > 0) state.textboxOpenCooldown--;
|
||||
if (state.isTextboxClosing) ResetStateFlags(&state);
|
||||
}
|
||||
|
||||
// The main function that gets called every frame
|
||||
void PauseWarp_Main() {
|
||||
LUSLOG_CRITICAL("PauseWarp_Main Called");
|
||||
static PauseWarpState state; // The state is static so it retains its value between function calls
|
||||
|
||||
// Checking if the pause warp feature is enabled
|
||||
int pauseWarpEnabled = CVarGetInteger("gPauseWarpEnabled", 0);
|
||||
if (!IsPauseWarpEnabled()) return;
|
||||
|
||||
PlayState* play = gPlayState;
|
||||
Player* player = play ? GET_PLAYER(play) : NULL;
|
||||
|
||||
// If pause warp is not enabled or the state is invalid, reset the state and exit
|
||||
if (!pauseWarpEnabled || !IsStateValid(play, player, &state)) return ResetStateFlags(&state);
|
||||
|
||||
// Check if a Ocarina in the Ocarina slot
|
||||
if (gSaveContext.inventory.items[SLOT_OCARINA] == ITEM_NONE) return ResetStateFlags(&state);
|
||||
|
||||
// Checking if the 'A' button is pressed
|
||||
Player* player = GET_PLAYER(play);
|
||||
int aButtonPressed = CHECK_BTN_ALL(play->state.input->press.button, BTN_A);
|
||||
|
||||
// If 'A' is pressed and the cooldowns are zero, and we're not already warping, initiate the warp
|
||||
if (aButtonPressed && !state.aButtonCooldown && !(state.warpInitiated || state.textboxInitiated || state.inChoosingState)) {
|
||||
int song = play->pauseCtx.cursorPoint[PAUSE_QUEST];
|
||||
|
||||
// Check if the player has the selected warp song
|
||||
if (!CHECK_QUEST_ITEM(song)) return;
|
||||
|
||||
// Initiate warp if the song is within the valid range
|
||||
if (song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE) InitiateWarp(play, player, song, &state);
|
||||
if (CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE) {
|
||||
InitiateWarp(play, player, song);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PauseWarp_Idle() {
|
||||
if (!IsPauseWarpEnabled()) return;
|
||||
|
||||
PlayState* play = gPlayState;
|
||||
Player* player = GET_PLAYER(play);
|
||||
|
||||
if (gSaveContext.inventory.items[SLOT_OCARINA] == ITEM_NONE) return ResetStateFlags(&state);
|
||||
|
||||
// Depending on the message mode, update the state flags
|
||||
switch (play->msgCtx.msgMode) {
|
||||
case 6: if (state.warpInitiated) state.textboxInitiated = true; break;
|
||||
case 53: if (state.warpInitiated && state.textboxInitiated) state.inChoosingState = true; break;
|
||||
case 54: if (state.warpInitiated && state.textboxInitiated && state.inChoosingState) HandleWarpConfirmation(play, player, &state); break;
|
||||
case 54: if (state.warpInitiated && state.textboxInitiated && state.inChoosingState) HandleWarpConfirmation(play, player); break;
|
||||
case 0: ResetStateFlags(&state); break;
|
||||
}
|
||||
|
||||
// Finally, handle any cooldowns for the next frame
|
||||
HandleCooldowns(&state);
|
||||
HandleCooldowns();
|
||||
}
|
Loading…
Reference in New Issue
Block a user