[Enhancement] Pause Owl Warp (#620)

* Add Pause Owl Warp Enhancement

- **mm/2s2h/BenGui/BenMenuBar.cpp**: Updated menu to include new enhancement options.
- **mm/2s2h/Enhancements/Enhancements.cpp**: Registered the new Pause Owl Warp enhancement.
- **mm/2s2h/Enhancements/Enhancements.h**: Declared functions for the new enhancement.
- **mm/2s2h/Enhancements/Songs/PauseOwlWarp.cpp**: Implemented the Pause Owl Warp functionality.
- **mm/2s2h/Enhancements/Songs/PauseOwlWarp.h**: Header file for the Pause Owl Warp implementation.
- **mm/include/functions.h**: Added function declarations related to the new enhancement.
- **mm/src/overlays/kaleido_scope/ovl_kaleido_map.c**: Modified to support the new enhancement.
- **mm/src/overlays/kaleido_scope/ovl_kaleido_scope_NES.c**: Modified to support the new enhancement.

* ran clang-format script

* Additional logic and bug fixes

* Fix PauseOwlWarp cursor logic triggering on dungeon map
-Added a check to ensure PauseOwlWarp's cursor logic is only triggered when not in a dungeon.

* Add Song of Soaring check
- To make it more in line with vanilla, you are now required to have the Song of Soaring to use this enhancement.

* bug fix and ran clang-format script
-My previous commit had a extra condition that wasn't needed that caused a bug where the world map points locations pointed to activated owl statues.

* added more checks

* Simplified complex conditional statements

* possibly fix macos build issue?

* index warping logic added

* implement feedback from Archez

* shot in the dark macos build fix?

* how bout now?

* revert back to previous commit

* if this fixed the macos build issue it'll be thanks to cclark25... let's pray

* add debugeditor check - thanks archez!

* Moved debugEditor check to prevent triggering ALL pauseOwlWarp logic. wtf was I thinking earlier
This commit is contained in:
mckinlee
2024-08-05 15:18:52 -04:00
committed by GitHub
parent d0caa0f78c
commit 0ec23b34ba
9 changed files with 252 additions and 3 deletions
+3
View File
@@ -653,6 +653,9 @@ void DrawEnhancementsMenu() {
{ .tooltip = "Enables using the Dpad for Ocarina playback." });
UIWidgets::CVarCheckbox("Prevent Dropped Ocarina Inputs", "gEnhancements.Playback.NoDropOcarinaInput",
{ .tooltip = "Prevent dropping inputs when playing the ocarina quickly" });
UIWidgets::CVarCheckbox("Pause Owl Warp", "gEnhancements.Songs.PauseOwlWarp",
{ .tooltip = "Allows the player to use the pause menu map to owl warp instead of "
"having to play the Song of Soaring." });
ImGui::EndMenu();
}
+1
View File
@@ -48,6 +48,7 @@ void InitEnhancements() {
// Songs
RegisterEnableSunsSong();
RegisterPauseOwlWarp();
// Restorations
RegisterPowerCrouchStab();
+1
View File
@@ -28,6 +28,7 @@
#include "Graphics/PlayAsKafei.h"
#include "Player/Player.h"
#include "Songs/EnableSunsSong.h"
#include "Songs/PauseOwlWarp.h"
#include "Saving/SavingEnhancements.h"
#include "Graphics/DisableBlackBars.h"
#include "Modes/TimeMovesWhenYouMove.h"
+222
View File
@@ -0,0 +1,222 @@
#include "PauseOwlWarp.h"
#include <libultraship/libultraship.h>
#include "Enhancements/GameInteractor/GameInteractor.h"
extern "C" {
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
extern f32 sPauseMenuVerticalOffset;
extern u16 sCursorPointsToOcarinaModes[];
extern u16 sOwlWarpPauseItems[];
extern u16 D_80AF343C[];
extern s16 sInDungeonScene;
}
extern "C" bool PauseOwlWarp_IsOwlWarpEnabled() {
return CVarGetInteger("gEnhancements.Songs.PauseOwlWarp", 0) && CHECK_QUEST_ITEM(QUEST_SONG_SOARING) &&
gSaveContext.save.saveInfo.playerData.owlActivationFlags != 0 &&
gPlayState->pauseCtx.debugEditor == DEBUG_EDITOR_NONE;
}
static bool sIsConfirming = false;
static u16 sStickAdjTimer = 0;
void ResetMessageContext() {
gPlayState->msgCtx.msgLength = 0;
gPlayState->msgCtx.msgMode = MSGMODE_NONE;
}
void ClosePauseMenu(PauseContext* pauseCtx) {
Interface_SetAButtonDoAction(gPlayState, DO_ACTION_NONE);
Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
gPlayState->msgCtx.ocarinaMode = OCARINA_MODE_END;
gSaveContext.prevHudVisibility = HUD_VISIBILITY_ALL;
sIsConfirming = false;
Message_CloseTextbox(gPlayState);
pauseCtx->state = PAUSE_STATE_UNPAUSE_SETUP;
}
void HandleConfirmingState(PauseContext* pauseCtx, Input* input) {
if (Message_ShouldAdvance(gPlayState)) {
ResetMessageContext();
sIsConfirming = false;
if (gPlayState->msgCtx.choiceIndex == 0) { // Yes
Interface_SetAButtonDoAction(gPlayState, DO_ACTION_NONE);
Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
gPlayState->msgCtx.ocarinaMode = sCursorPointsToOcarinaModes[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]];
Audio_PlaySfx(NA_SE_SY_DECIDE);
Message_CloseTextbox(gPlayState);
sPauseMenuVerticalOffset = -6240.0f;
pauseCtx->state = PAUSE_STATE_UNPAUSE_SETUP;
gPlayState->nextEntrance = D_80AF343C[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]];
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_FADE_WHITE;
} else { // No
Interface_SetAButtonDoAction(gPlayState, DO_ACTION_WARP);
Audio_PlaySfx(NA_SE_SY_MESSAGE_PASS);
Message_CloseTextbox(gPlayState);
}
} else if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
ResetMessageContext();
sIsConfirming = false;
Audio_PlaySfx(NA_SE_SY_MESSAGE_PASS);
Message_CloseTextbox(gPlayState);
} else if (CHECK_BTN_ALL(input->press.button, BTN_START)) {
ClosePauseMenu(pauseCtx);
}
}
void UpdateCursorForOwlWarpPoints(PauseContext* pauseCtx) {
if (pauseCtx->cursorSpecialPos == 0) {
if (pauseCtx->stickAdjX > 30) {
pauseCtx->cursorShrinkRate = 4.0f;
sStickAdjTimer = 0;
do {
pauseCtx->cursorPoint[PAUSE_WORLD_MAP]++;
if (pauseCtx->cursorPoint[PAUSE_WORLD_MAP] > OWL_WARP_STONE_TOWER) {
KaleidoScope_MoveCursorToSpecialPos(gPlayState, PAUSE_CURSOR_PAGE_RIGHT);
return;
}
} while (!pauseCtx->worldMapPoints[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]]);
if (pauseCtx->worldMapPoints[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]]) {
pauseCtx->cursorItem[PAUSE_MAP] =
sOwlWarpPauseItems[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]] - ITEM_MAP_POINT_GREAT_BAY;
pauseCtx->cursorSlot[PAUSE_MAP] = 31 + pauseCtx->cursorPoint[PAUSE_WORLD_MAP];
Audio_PlaySfx(NA_SE_SY_CURSOR);
}
} else if (pauseCtx->stickAdjX < -30) {
pauseCtx->cursorShrinkRate = 4.0f;
sStickAdjTimer = 0;
do {
pauseCtx->cursorPoint[PAUSE_WORLD_MAP]--;
if (pauseCtx->cursorPoint[PAUSE_WORLD_MAP] < OWL_WARP_GREAT_BAY_COAST) {
KaleidoScope_MoveCursorToSpecialPos(gPlayState, PAUSE_CURSOR_PAGE_LEFT);
return;
}
} while (!pauseCtx->worldMapPoints[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]]);
if (pauseCtx->worldMapPoints[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]]) {
pauseCtx->cursorItem[PAUSE_MAP] =
sOwlWarpPauseItems[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]] - ITEM_MAP_POINT_GREAT_BAY;
pauseCtx->cursorSlot[PAUSE_MAP] = 31 + pauseCtx->cursorPoint[PAUSE_WORLD_MAP];
Audio_PlaySfx(NA_SE_SY_CURSOR);
}
} else {
sStickAdjTimer++;
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT && pauseCtx->stickAdjX > 30) {
KaleidoScope_MoveCursorFromSpecialPos(gPlayState);
for (int i = OWL_WARP_GREAT_BAY_COAST; i <= OWL_WARP_STONE_TOWER; i++) {
if (pauseCtx->worldMapPoints[i]) {
pauseCtx->cursorPoint[PAUSE_WORLD_MAP] = i;
pauseCtx->cursorItem[PAUSE_MAP] =
sOwlWarpPauseItems[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]] - ITEM_MAP_POINT_GREAT_BAY;
pauseCtx->cursorSlot[PAUSE_MAP] = 31 + pauseCtx->cursorPoint[PAUSE_WORLD_MAP];
KaleidoScope_UpdateWorldMapCursor(gPlayState);
KaleidoScope_UpdateNamePanel(gPlayState);
return;
}
}
KaleidoScope_MoveCursorToSpecialPos(gPlayState, PAUSE_CURSOR_PAGE_RIGHT);
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT && pauseCtx->stickAdjX < -30) {
KaleidoScope_MoveCursorFromSpecialPos(gPlayState);
for (int i = OWL_WARP_STONE_TOWER; i >= OWL_WARP_GREAT_BAY_COAST; i--) {
if (pauseCtx->worldMapPoints[i]) {
pauseCtx->cursorPoint[PAUSE_WORLD_MAP] = i;
pauseCtx->cursorItem[PAUSE_MAP] =
sOwlWarpPauseItems[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]] - ITEM_MAP_POINT_GREAT_BAY;
pauseCtx->cursorSlot[PAUSE_MAP] = 31 + pauseCtx->cursorPoint[PAUSE_WORLD_MAP];
KaleidoScope_UpdateWorldMapCursor(gPlayState);
KaleidoScope_UpdateNamePanel(gPlayState);
return;
}
}
KaleidoScope_MoveCursorToSpecialPos(gPlayState, PAUSE_CURSOR_PAGE_LEFT);
}
}
void HandlePauseOwlWarp(PauseContext* pauseCtx) {
// Initialize worldMapPoints based on owl activation flags
for (int i = OWL_WARP_STONE_TOWER; i >= OWL_WARP_GREAT_BAY_COAST; i--) {
pauseCtx->worldMapPoints[i] = (gSaveContext.save.saveInfo.playerData.owlActivationFlags >> i) & 1;
}
// Special condition for when only the 15th owl statue is activated
if (gSaveContext.save.saveInfo.playerData.owlActivationFlags == (1 << 15)) {
for (int i = REGION_GREAT_BAY; i < REGION_MAX; i++) {
if ((gSaveContext.save.saveInfo.regionsVisited >> i) & 1) {
switch (i) {
case REGION_GREAT_BAY:
pauseCtx->worldMapPoints[OWL_WARP_GREAT_BAY_COAST] = true;
break;
case REGION_ZORA_HALL:
pauseCtx->worldMapPoints[OWL_WARP_ZORA_CAPE] = true;
break;
case REGION_ROMANI_RANCH:
pauseCtx->worldMapPoints[OWL_WARP_SNOWHEAD] = true;
break;
case REGION_DEKU_PALACE:
pauseCtx->worldMapPoints[OWL_WARP_MOUNTAIN_VILLAGE] = true;
break;
case REGION_WOODFALL:
pauseCtx->worldMapPoints[OWL_WARP_CLOCK_TOWN] = true;
break;
case REGION_CLOCK_TOWN:
pauseCtx->worldMapPoints[OWL_WARP_MILK_ROAD] = true;
break;
case REGION_SNOWHEAD:
pauseCtx->worldMapPoints[OWL_WARP_WOODFALL] = true;
break;
case REGION_IKANA_GRAVEYARD:
pauseCtx->worldMapPoints[OWL_WARP_SOUTHERN_SWAMP] = true;
break;
case REGION_IKANA_CANYON:
pauseCtx->worldMapPoints[OWL_WARP_IKANA_CANYON] = true;
break;
case REGION_GORON_VILLAGE:
pauseCtx->worldMapPoints[OWL_WARP_STONE_TOWER] = true;
break;
}
}
}
}
// Ensure cursor starts at an activated point
if (!pauseCtx->worldMapPoints[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]]) {
for (int i = OWL_WARP_GREAT_BAY_COAST; i <= OWL_WARP_STONE_TOWER; i++) {
if (pauseCtx->worldMapPoints[i]) {
pauseCtx->cursorPoint[PAUSE_WORLD_MAP] = i;
break;
}
}
}
Player* player = GET_PLAYER(gPlayState);
Input* input = &gPlayState->state.input[0];
if ((pauseCtx->state == PAUSE_STATE_MAIN && pauseCtx->pageIndex == PAUSE_MAP && pauseCtx->mapPageRoll == 0) ||
sIsConfirming) {
if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_B)) {
ClosePauseMenu(pauseCtx);
} else if (CHECK_BTN_ALL(input->press.button, BTN_A) && !sIsConfirming) {
if (pauseCtx->cursorSpecialPos == 0 && pauseCtx->worldMapPoints[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]]) {
Audio_PlaySfx(NA_SE_SY_DECIDE);
Message_StartTextbox(gPlayState, 0x1B93, NULL);
sIsConfirming = true;
}
} else if (sIsConfirming) {
HandleConfirmingState(pauseCtx, input);
} else {
KaleidoScope_UpdateOwlWarpNamePanel(gPlayState);
}
UpdateCursorForOwlWarpPoints(pauseCtx);
}
}
void RegisterPauseOwlWarp() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnKaleidoUpdate>([](PauseContext* pauseCtx) {
if (!sInDungeonScene && PauseOwlWarp_IsOwlWarpEnabled() && CHECK_QUEST_ITEM(QUEST_SONG_SOARING)) {
HandlePauseOwlWarp(pauseCtx);
}
});
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef PAUSE_OWL_WARP_H
#define PAUSE_OWL_WARP_H
#ifdef __cplusplus
extern "C" {
#endif
void RegisterPauseOwlWarp(void);
bool PauseOwlWarp_IsOwlWarpEnabled(void);
#ifdef __cplusplus
}
#endif
#endif // PAUSE_OWL_WARP_H
+1
View File
@@ -523,6 +523,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
$<$<COMPILE_LANGUAGE:C>:
#-Werror-implicit-function-declaration
-Wno-incompatible-pointer-types
-Wno-int-conversion
>
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
$<$<COMPILE_LANGUAGE:CXX>:
+2
View File
@@ -1328,6 +1328,8 @@ void osContGetReadData(OSContPad* pad);
// #region 2S2H [Port] Previously unavailable functions, made available for porting
void PadMgr_ThreadEntry();
void Heaps_Alloc(void);
void KaleidoScope_UpdateOwlWarpNamePanel(PlayState* play);
void KaleidoScope_UpdateNamePanel(PlayState* play);
// #endregion
// #region 2S2H [Port] New methods added for porting
void AudioSeq_SetPortVolumeScale(u8 seqPlayerIndex, f32 volume);
@@ -13,6 +13,8 @@
#include "BenPort.h"
#include "2s2h/Enhancements/Songs/PauseOwlWarp.h"
// 2S2H [Port] (and line 26) don't do pointer math and access the list of digits directly.
extern const char* sCounterTextures[];
@@ -675,7 +677,7 @@ void KaleidoScope_DrawWorldMap(PlayState* play) {
Gfx_SetupDL42_Opa(play->state.gfxCtx);
if (!IS_PAUSE_STATE_OWLWARP) {
if (!IS_PAUSE_STATE_OWLWARP && !PauseOwlWarp_IsOwlWarpEnabled()) {
// Browsing the world map regions on the pause menu
gDPLoadTextureBlock(POLY_OPA_DISP++, gWorldMapDotTex, G_IM_FMT_IA, G_IM_SIZ_8b, 8, 8, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
@@ -846,7 +848,7 @@ void KaleidoScope_UpdateWorldMapCursor(PlayState* play) {
s16 oldCursorPoint;
if ((pauseCtx->state == PAUSE_STATE_MAIN) && (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE) &&
(pauseCtx->pageIndex == PAUSE_MAP)) {
(pauseCtx->pageIndex == PAUSE_MAP) && !PauseOwlWarp_IsOwlWarpEnabled()) {
pauseCtx->cursorColorSet = PAUSE_CURSOR_COLOR_SET_WHITE;
oldCursorPoint = pauseCtx->cursorPoint[PAUSE_WORLD_MAP];
@@ -24,6 +24,8 @@
#include "2s2h/Enhancements/GameInteractor/GameInteractor.h"
#include "2s2h/Enhancements/Songs/PauseOwlWarp.h"
// Page Textures (Background of Page):
// Broken up into multiple textures.
// Numbered by column/row.
@@ -2901,7 +2903,7 @@ void KaleidoScope_UpdateCursorSize(PlayState* play) {
case PAUSE_MAP:
if (!sInDungeonScene) {
if (IS_PAUSE_STATE_OWLWARP) {
if (IS_PAUSE_STATE_OWLWARP || PauseOwlWarp_IsOwlWarpEnabled()) {
pauseCtx->cursorX = sOwlWarpWorldMapCursorsX[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]];
pauseCtx->cursorY = sOwlWarpWorldMapCursorsY[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]];
} else {