summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Longstaff <JordanLongstaff@users.noreply.github.com>2026-07-23 17:48:46 -0400
committerGitHub <noreply@github.com>2026-07-23 21:48:46 +0000
commit5c55c01c683952913b7547f6ba02116a25b8440f (patch)
tree2c0444222950116186272615497a0c0cabd513c0
parent35dcba5944203d254781d1ac5f870c2eed13b802 (diff)
Hookify frogs' Ocarina game (#6969)
-rw-r--r--soh/soh/Enhancements/Minigames/FrogsOcarinaGame.cpp53
-rw-r--r--soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h25
-rw-r--r--soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c29
3 files changed, 83 insertions, 24 deletions
diff --git a/soh/soh/Enhancements/Minigames/FrogsOcarinaGame.cpp b/soh/soh/Enhancements/Minigames/FrogsOcarinaGame.cpp
new file mode 100644
index 000000000..ba4f20a90
--- /dev/null
+++ b/soh/soh/Enhancements/Minigames/FrogsOcarinaGame.cpp
@@ -0,0 +1,53 @@
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+#include "functions.h"
+#include "src/overlays/actors/ovl_En_Fr/z_en_fr.h"
+extern PlayState* gPlayState;
+
+extern void EnFr_SetupReward(EnFr* enFr, PlayState* play, u8 unkCondition);
+}
+
+#define CVAR_FROGS_CUSTOMIZE_NAME CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame")
+#define CVAR_FROGS_CUSTOMIZE_VALUE CVarGetInteger(CVAR_FROGS_CUSTOMIZE_NAME, 0)
+
+#define CVAR_FROGS_MODIFY_TIME_NAME CVAR_ENHANCEMENT("FrogsModifyFailTime")
+#define CVAR_FROGS_MODIFY_TIME_VALUE CVarGetInteger(CVAR_FROGS_MODIFY_TIME_NAME, 1)
+
+#define CVAR_FROGS_INFINITE_TIME_NAME CVAR_ENHANCEMENT("FrogsUnlimitedFailTime")
+#define CVAR_FROGS_INFINITE_TIME_VALUE CVarGetInteger(CVAR_FROGS_INFINITE_TIME_NAME, 0)
+
+#define CVAR_FROGS_INSTANT_WIN_NAME CVAR_ENHANCEMENT("InstantFrogsGameWin")
+#define CVAR_FROGS_INSTANT_WIN_VALUE CVarGetInteger(CVAR_FROGS_INSTANT_WIN_NAME, 0)
+
+static void RegisterFrogsOcarinaGameModifyTime() {
+ COND_VB_SHOULD(VB_SET_FROG_OCARINA_GAME_TIME_LIMIT,
+ CVAR_FROGS_CUSTOMIZE_VALUE && (CVAR_FROGS_MODIFY_TIME_VALUE != 1), {
+ EnFr* enFr = va_arg(args, EnFr*);
+ s32 timeLimit = va_arg(args, s32);
+ enFr->frogSongTimer = timeLimit * CVAR_FROGS_MODIFY_TIME_VALUE;
+ *should = false;
+ });
+}
+
+static void RegisterFrogsOcarinaGameInfiniteTime() {
+ COND_VB_SHOULD(VB_FROGS_OCARINA_GAME_TIMER_TICK, CVAR_FROGS_CUSTOMIZE_VALUE && CVAR_FROGS_INFINITE_TIME_VALUE,
+ { *should = false; });
+}
+
+static void RegisterFrogsOcarinaGameInstantWin() {
+ COND_VB_SHOULD(VB_PLAY_FROG_OCARINA_GAME, CVAR_FROGS_CUSTOMIZE_VALUE && CVAR_FROGS_INSTANT_WIN_VALUE, {
+ EnFr* enFr = va_arg(args, EnFr*);
+ enFr->actor.textId = 0x40AC;
+ EnFr_SetupReward(enFr, gPlayState, false);
+ *should = false;
+ });
+}
+
+static RegisterShipInitFunc initFunc_ModifyTime(RegisterFrogsOcarinaGameModifyTime,
+ { CVAR_FROGS_CUSTOMIZE_NAME, CVAR_FROGS_MODIFY_TIME_NAME });
+static RegisterShipInitFunc initFunc_InfiniteTime(RegisterFrogsOcarinaGameInfiniteTime,
+ { CVAR_FROGS_CUSTOMIZE_NAME, CVAR_FROGS_INFINITE_TIME_NAME });
+static RegisterShipInitFunc initFunc_InstantWin(RegisterFrogsOcarinaGameInstantWin,
+ { CVAR_FROGS_CUSTOMIZE_NAME, CVAR_FROGS_INSTANT_WIN_NAME }); \ No newline at end of file
diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
index bcf4dc892..b53081db9 100644
--- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
+++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
@@ -805,6 +805,14 @@ typedef enum {
// ```
// #### `args`
// - None
+ VB_FROGS_OCARINA_GAME_TIMER_TICK,
+
+ // #### `result`
+ // ```c
+ // true
+ // ```
+ // #### `args`
+ // - None
VB_GANON_HEAL_BEFORE_FIGHT,
// #### `result`
@@ -1905,6 +1913,14 @@ typedef enum {
// true
// ```
// #### `args`
+ // - `*EnFr`
+ VB_PLAY_FROG_OCARINA_GAME,
+
+ // #### `result`
+ // ```c
+ // true
+ // ```
+ // #### `args`
// - `*EnHeishi2`
// - `bool` (clearCamera - true if the code clears a sub-camera, false otherwise)
VB_PLAY_GATE_OPENING_OR_CLOSING_CS,
@@ -2382,6 +2398,15 @@ typedef enum {
// #### `result`
// ```c
+ // true
+ // ```
+ // #### `args`
+ // - `*EnFr`
+ // - `s16` (default time limit)
+ VB_SET_FROG_OCARINA_GAME_TIME_LIMIT,
+
+ // #### `result`
+ // ```c
// SurfaceType_GetFloorEffect(&play->colCtx, poly, bgId) == 2
// ```
// #### `args`
diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c
index 67d7b3f35..47669a2ec 100644
--- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c
+++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c
@@ -824,22 +824,10 @@ void EnFr_SetupFrogSong(EnFr* this, PlayState* play) {
if (this->frogSongTimer != 0) {
this->frogSongTimer--;
} else {
- // #region SOH [Enhancement]
- if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0)) {
- this->frogSongTimer = 40 * CVarGetInteger(CVAR_ENHANCEMENT("FrogsModifyFailTime"), 1);
- if (CVarGetInteger(CVAR_ENHANCEMENT("InstantFrogsGameWin"), 0)) {
- this->actor.textId = 0x40AC;
- EnFr_SetupReward(this, play, false);
- } else {
- this->ocarinaNoteIndex = 0;
- func_8010BD58(play, OCARINA_ACTION_FROGS);
- this->ocarinaNote = EnFr_GetNextNoteFrogSong(this->ocarinaNoteIndex);
- EnFr_CheckOcarinaInputFrogSong(this->ocarinaNote);
- this->actionFunc = EnFr_ContinueFrogSong;
- }
- // #endregion
- } else {
+ if (GameInteractor_Should(VB_SET_FROG_OCARINA_GAME_TIME_LIMIT, true, this, 40)) {
this->frogSongTimer = 40;
+ }
+ if (GameInteractor_Should(VB_PLAY_FROG_OCARINA_GAME, true, this)) {
this->ocarinaNoteIndex = 0;
func_8010BD58(play, OCARINA_ACTION_FROGS);
this->ocarinaNote = EnFr_GetNextNoteFrogSong(this->ocarinaNoteIndex);
@@ -867,11 +855,7 @@ s32 EnFr_IsFrogSongComplete(EnFr* this, PlayState* play) {
ocarinaNote = EnFr_GetNextNoteFrogSong(ocarinaNoteIndex);
this->ocarinaNote = ocarinaNote;
EnFr_CheckOcarinaInputFrogSong(ocarinaNote);
- // #region SOH [Enhancement]
- if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0)) {
- this->frogSongTimer = sTimerFrogSong[index] * CVarGetInteger(CVAR_ENHANCEMENT("FrogsModifyFailTime"), 1);
- // #endregion
- } else {
+ if (GameInteractor_Should(VB_SET_FROG_OCARINA_GAME_TIME_LIMIT, true, this, sTimerFrogSong[index])) {
this->frogSongTimer = sTimerFrogSong[index];
}
}
@@ -896,10 +880,7 @@ void EnFr_ContinueFrogSong(EnFr* this, PlayState* play) {
if (this->frogSongTimer == 0) {
EnFr_OcarinaMistake(this, play);
} else {
- // #region SOH [Enhancement] - Don't decrement timer
- if (!CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0) ||
- !CVarGetInteger(CVAR_ENHANCEMENT("FrogsUnlimitedFailTime"), 0)) {
- // #endregion
+ if (GameInteractor_Should(VB_FROGS_OCARINA_GAME_TIMER_TICK, true)) {
this->frogSongTimer--;
}
if (play->msgCtx.msgMode == MSGMODE_FROGS_PLAYING) {