diff --git a/soh/soh/Enhancements/Graphics/SariaGestureFriendsForever.cpp b/soh/soh/Enhancements/Graphics/SariaGestureFriendsForever.cpp new file mode 100644 index 0000000000..d1035661bf --- /dev/null +++ b/soh/soh/Enhancements/Graphics/SariaGestureFriendsForever.cpp @@ -0,0 +1,41 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "src/overlays/actors/ovl_En_Sa/z_en_sa.h" +extern "C" PlayState* gPlayState; + +void EnSa_ChangeAnim(EnSa* enSa, s32 index); +} + +static constexpr int32_t CVAR_SARIA_GESTURE_DEFAULT = 0; +#define CVAR_SARIA_GESTURE_NAME CVAR_ENHANCEMENT("SariaGestureFriendsForever") +#define CVAR_SARIA_GESTURE_VALUE CVarGetInteger(CVAR_SARIA_GESTURE_NAME, CVAR_SARIA_GESTURE_DEFAULT) + +// Resets Saria back to her usual swaying animation; otherwise, she stands frozen +static void EnSa_ResetAnimation(EnSa* enSa) { + static bool sAnimationStarted = false; + + if (enSa->unk_20B == 7 && enSa->unk_20A == 2 && !sAnimationStarted) { + sAnimationStarted = true; + } + + if (sAnimationStarted && Animation_OnFrame(&enSa->skelAnime, enSa->skelAnime.endFrame)) { + EnSa_ChangeAnim(enSa, 4); + sAnimationStarted = false; + } +} + +static void RegisterSariaGestureFriendsForever() { + COND_VB_SHOULD(VB_SARIA_GESTURE, CVAR_SARIA_GESTURE_VALUE, { + bool isInHouse = gPlayState->sceneNum == SCENE_SARIAS_HOUSE; + *should = *should || isInHouse; + + if (isInHouse) { + EnSa* enSa = va_arg(args, EnSa*); + EnSa_ResetAnimation(enSa); + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterSariaGestureFriendsForever, { CVAR_SARIA_GESTURE_NAME }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index b0f44446dd..1b64f2b4d7 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -935,6 +935,14 @@ typedef enum { // - `*PlayState` VB_PLAY_HORSEBACK_ARCHERY, + // #### `result` + // ```c + // play->sceneNum == SCENE_KOKIRI_FOREST + // ``` + // #### `args` + // - `*EnSa` + VB_SARIA_GESTURE, + // #### `result` // ```c // true diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 150bf2efce..4b0b8f0ee2 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1202,6 +1202,11 @@ void SohMenu::AddMenuEnhancements() { .RaceDisable(false) .Options(CheckboxOptions().Tooltip( "Restores an unfinished feature to pulsate the boss room icon when you are in the boss room.")); + AddWidget(path, "Saria's Friends Forever Gesture", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("SariaGestureFriendsForever")) + .RaceDisable(false) + .Options(CheckboxOptions().Tooltip( + "Restores an unused animation of Saria when she says, \"Saria and Link will be friends forever.\"")); AddWidget(path, "Glitch Restorations", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Fish while Hovering", WIDGET_CVAR_CHECKBOX) diff --git a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c index 7475283b94..db1026c34e 100644 --- a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c +++ b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c @@ -544,7 +544,7 @@ void EnSa_Destroy(Actor* thisx, PlayState* play) { } void func_80AF6448(EnSa* this, PlayState* play) { - if (play->sceneNum == SCENE_KOKIRI_FOREST) { + if (GameInteractor_Should(VB_SARIA_GESTURE, play->sceneNum == SCENE_KOKIRI_FOREST, this)) { if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) { switch (this->actor.textId) { case 0x1002: