Hookify Lost Woods Ocarina game (#6976)

This commit is contained in:
Jordan Longstaff
2026-07-24 12:28:36 -04:00
committed by GitHub
parent 44909ab230
commit 9d1e5d2811
4 changed files with 164 additions and 62 deletions
@@ -0,0 +1,105 @@
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "functions.h"
#include "variables.h"
#include "src/overlays/actors/ovl_En_Skj/z_en_skj.h"
extern PlayState* gPlayState;
void EnSkj_WaitForPlayback(EnSkj* enSkj, PlayState* play);
}
typedef enum {
OCARINA_GAME_STARTING_NOTES = 3,
OCARINA_GAME_ROUND_ONE_NOTES = 5,
OCARINA_GAME_ROUND_TWO_NOTES = 6,
OCARINA_GAME_ROUND_THREE_NOTES = 8,
} OcarinaGameDefaults;
#define CVAR_CUSTOMIZE_NAME CVAR_ENHANCEMENT("CustomizeOcarinaGame")
#define CVAR_CUSTOMIZE_VALUE CVarGetInteger(CVAR_CUSTOMIZE_NAME, 0)
#define CVAR_STARTING_NOTES_NAME CVAR_ENHANCEMENT("OcarinaGame.StartingNotes")
#define CVAR_STARTING_NOTES_VALUE CVarGetInteger(CVAR_STARTING_NOTES_NAME, OCARINA_GAME_STARTING_NOTES)
#define CVAR_ROUND_ONE_NOTES_NAME CVAR_ENHANCEMENT("OcarinaGame.RoundOneNotes")
#define CVAR_ROUND_ONE_NOTES_VALUE CVarGetInteger(CVAR_ROUND_ONE_NOTES_NAME, OCARINA_GAME_ROUND_ONE_NOTES)
#define CVAR_ROUND_TWO_NOTES_NAME CVAR_ENHANCEMENT("OcarinaGame.RoundTwoNotes")
#define CVAR_ROUND_TWO_NOTES_VALUE CVarGetInteger(CVAR_ROUND_TWO_NOTES_NAME, OCARINA_GAME_ROUND_TWO_NOTES)
#define CVAR_ROUND_THREE_NOTES_NAME CVAR_ENHANCEMENT("OcarinaGame.RoundThreeNotes")
#define CVAR_ROUND_THREE_NOTES_VALUE CVarGetInteger(CVAR_ROUND_THREE_NOTES_NAME, OCARINA_GAME_ROUND_THREE_NOTES)
#define CVAR_NOTE_SPEED_NAME CVAR_ENHANCEMENT("OcarinaGame.NoteSpeed")
#define CVAR_NOTE_SPEED_VALUE CVarGetInteger(CVAR_NOTE_SPEED_NAME, 1)
#define CVAR_INFINITE_TIME_NAME CVAR_ENHANCEMENT("OcarinaUnlimitedFailTime")
#define CVAR_INFINITE_TIME_VALUE CVarGetInteger(CVAR_INFINITE_TIME_NAME, 0)
#define CVAR_INSTANT_WIN_NAME CVAR_ENHANCEMENT("InstantOcarinaGameWin")
#define CVAR_INSTANT_WIN_VALUE CVarGetInteger(CVAR_INSTANT_WIN_NAME, 0)
static void RegisterLostWoodsOcarinaGameRoundNotesSetup() {
COND_VB_SHOULD(VB_SET_LOST_WOODS_OCARINA_GAME_NOTES, CVAR_CUSTOMIZE_VALUE, {
s32 minigameRound = va_arg(args, s32);
u8* roundNotes = va_arg(args, u8*);
switch (minigameRound) {
case 0:
*roundNotes = CVAR_ROUND_ONE_NOTES_VALUE;
break;
case 1:
*roundNotes = CVAR_ROUND_TWO_NOTES_VALUE;
break;
default:
*roundNotes = CVAR_ROUND_THREE_NOTES_VALUE;
break;
}
*should = false;
});
}
static void RegisterLostWoodsOcarinaGameStartingNotesSetup() {
COND_VB_SHOULD(VB_SET_LOST_WOODS_OCARINA_GAME_STARTING_NOTES,
CVAR_CUSTOMIZE_VALUE && (CVAR_STARTING_NOTES_VALUE != OCARINA_GAME_STARTING_NOTES), {
for (u8 i = 0; i < CVAR_STARTING_NOTES_VALUE; i++) {
AudioOcarina_MemoryGameNextNote();
}
*should = false;
});
}
static void RegisterLostWoodsOcarinaGameModifyNoteSpeed() {
COND_VB_SHOULD(VB_MODIFY_LOST_WOODS_OCARINA_GAME_NOTE_SPEED, CVAR_CUSTOMIZE_VALUE && (CVAR_NOTE_SPEED_VALUE != 1), {
s32 appendPos = va_arg(args, s32);
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][appendPos].length /= CVAR_NOTE_SPEED_VALUE;
});
}
static void RegisterLostWoodsOcarinaGameInfiniteTime() {
COND_VB_SHOULD(VB_LOST_WOODS_OCARINA_GAME_TIMER_TICK, CVAR_CUSTOMIZE_VALUE && CVAR_INFINITE_TIME_VALUE,
{ *should = false; });
}
static void RegisterLostWoodsOcarinaGameInstantWin() {
COND_VB_SHOULD(VB_PLAY_LOST_WOODS_OCARINA_GAME, CVAR_CUSTOMIZE_VALUE && CVAR_INSTANT_WIN_VALUE, {
EnSkj* enSkj = va_arg(args, EnSkj*);
gPlayState->msgCtx.ocarinaMode = OCARINA_MODE_0F;
enSkj->multiuseTimer = 160;
enSkj->actionFunc = EnSkj_WaitForPlayback;
*should = false;
});
}
static RegisterShipInitFunc initFunc_Notes(RegisterLostWoodsOcarinaGameRoundNotesSetup, { CVAR_CUSTOMIZE_NAME });
static RegisterShipInitFunc initFunc_StartingNotes(RegisterLostWoodsOcarinaGameStartingNotesSetup,
{ CVAR_CUSTOMIZE_NAME, CVAR_STARTING_NOTES_NAME });
static RegisterShipInitFunc initFunc_ModifyTime(RegisterLostWoodsOcarinaGameModifyNoteSpeed,
{ CVAR_CUSTOMIZE_NAME, CVAR_NOTE_SPEED_NAME });
static RegisterShipInitFunc initFunc_InfiniteTime(RegisterLostWoodsOcarinaGameInfiniteTime,
{ CVAR_CUSTOMIZE_NAME, CVAR_INFINITE_TIME_NAME });
static RegisterShipInitFunc initFunc_InstantWin(RegisterLostWoodsOcarinaGameInstantWin,
{ CVAR_CUSTOMIZE_NAME, CVAR_INSTANT_WIN_NAME });
@@ -1552,6 +1552,14 @@ typedef enum {
// - `*DoorShutter`
VB_LOCK_BOSS_DOOR,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - None
VB_LOST_WOODS_OCARINA_GAME_TIMER_TICK,
// #### `result`
// ```c
// true
@@ -1600,6 +1608,14 @@ typedef enum {
// - `*EnMd`
VB_MIDO_SPAWN,
// #### `result`
// ```c
// false
// ```
// #### `args`
// - `s32` (note append position)
VB_MODIFY_LOST_WOODS_OCARINA_GAME_NOTE_SPEED,
// #### `result`
// ```c
// this->interactInfo.talkState == NPC_TALK_STATE_ACTION
@@ -1933,6 +1949,14 @@ typedef enum {
// - None
VB_PLAY_GORON_FREE_CS,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `*EnSkj`
VB_PLAY_LOST_WOODS_OCARINA_GAME,
// #### `result`
// ```c
// true
@@ -2413,6 +2437,23 @@ typedef enum {
// - `s16` (default time limit)
VB_SET_FROG_OCARINA_GAME_TIME_LIMIT,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `s32` (round number, zero-based)
// - `*u8` (note end position)
VB_SET_LOST_WOODS_OCARINA_GAME_NOTES,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - None
VB_SET_LOST_WOODS_OCARINA_GAME_STARTING_NOTES,
// #### `result`
// ```c
// true
+13 -43
View File
@@ -2403,35 +2403,16 @@ void AudioOcarina_RecordSong(void) {
void AudioOcarina_MemoryGameInit(u8 minigameRound) {
u8 i;
// #region SOH [Enhancement]
if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 0)) {
u8 startingNotes = 3;
u8 roundOneCount = CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.RoundOneNotes"), 5);
u8 roundTwoCount = CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.RoundTwoNotes"), 6);
u8 roundThreeCount = CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.RoundThreeNotes"), 8);
u8 modMinigameNoteCnts[] = { roundOneCount, roundTwoCount, roundThreeCount };
if (minigameRound > 2) {
minigameRound = 2;
}
startingNotes = CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.StartingNotes"), 3);
if (minigameRound > 2) {
minigameRound = 2;
}
sOcaMemoryGameAppendPos = 0;
sOcaMemoryGameEndPos = modMinigameNoteCnts[minigameRound];
for (i = 0; i < startingNotes; i++) {
AudioOcarina_MemoryGameNextNote();
}
// #endregion
} else {
if (minigameRound > 2) {
minigameRound = 2;
}
sOcaMemoryGameAppendPos = 0;
sOcaMemoryGameAppendPos = 0;
if (GameInteractor_Should(VB_SET_LOST_WOODS_OCARINA_GAME_NOTES, true, minigameRound, &sOcaMemoryGameEndPos)) {
sOcaMemoryGameEndPos = sOcaMemoryGameNumNotes[minigameRound];
}
if (GameInteractor_Should(VB_SET_LOST_WOODS_OCARINA_GAME_STARTING_NOTES, true)) {
for (i = 0; i < 3; i++) {
AudioOcarina_MemoryGameNextNote();
}
@@ -2453,24 +2434,13 @@ s32 AudioOcarina_MemoryGameNextNote(void) {
randomPitch = sButtonToPitchMap[(randomButtonIndex + 1) % 5];
}
// #region SOH [Enhancement]
if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 0)) {
int noteSpeed = 0x2D;
noteSpeed = noteSpeed / CVarGetInteger(CVAR_ENHANCEMENT("OcarinaGame.NoteSpeed"), 1);
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].pitch = randomPitch;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].length = 0x2D;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].volume = 0x50;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].vibrato = 0;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].bend = 0;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].pitch = randomPitch;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].length = noteSpeed;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].volume = 0x50;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].vibrato = 0;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].bend = 0;
// #endregion
} else {
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].pitch = randomPitch;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].length = 0x2D;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].volume = 0x50;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].vibrato = 0;
sOcarinaSongNotes[OCARINA_SONG_MEMORY_GAME][sOcaMemoryGameAppendPos].bend = 0;
}
GameInteractor_Should(VB_MODIFY_LOST_WOODS_OCARINA_GAME_NOTE_SPEED, false, sOcaMemoryGameAppendPos);
sOcaMemoryGameAppendPos++;
+5 -19
View File
@@ -1414,21 +1414,12 @@ void EnSkj_StartOcarinaMinigame(EnSkj* this, PlayState* play) {
EnSkj_TurnPlayer(this, player);
if (dialogState == TEXT_STATE_CLOSING) {
// #region SOH [Enhancement]
if (CVarGetInteger(CVAR_ENHANCEMENT("InstantOcarinaGameWin"), 0) &&
CVarGetInteger(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 0)) {
play->msgCtx.ocarinaMode = OCARINA_MODE_0F;
if (dialogState == TEXT_STATE_CLOSING && GameInteractor_Should(VB_PLAY_LOST_WOODS_OCARINA_GAME, true, this)) {
func_8010BD58(play, OCARINA_ACTION_MEMORY_GAME);
if (sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid != NULL) {
sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid->minigameState = SKULL_KID_OCARINA_PLAY_NOTES;
this->songFailTimer = 160;
this->actionFunc = EnSkj_WaitForPlayback;
// #endregion
} else {
func_8010BD58(play, OCARINA_ACTION_MEMORY_GAME);
if (sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid != NULL) {
sOcarinaMinigameSkullKids[SKULL_KID_LEFT].skullkid->minigameState = SKULL_KID_OCARINA_PLAY_NOTES;
this->songFailTimer = 160;
this->actionFunc = EnSkj_WaitForPlayback;
}
}
}
}
@@ -1478,12 +1469,7 @@ void EnSkj_WaitForPlayback(EnSkj* this, PlayState* play) {
break;
case MSGMODE_MEMORY_GAME_PLAYER_PLAYING:
if (this->songFailTimer != 0) {
// #region SOH [Enhancement]
if (CVarGetInteger(CVAR_ENHANCEMENT("OcarinaUnlimitedFailTime"), 0) == 1 &&
CVarGetInteger(CVAR_ENHANCEMENT("CustomizeOcarinaGame"), 0) == 1) {
// don't decrement timer
// #endregion
} else {
if (GameInteractor_Should(VB_LOST_WOODS_OCARINA_GAME_TIMER_TICK, true)) {
this->songFailTimer--;
}
} else { // took too long, game failed