diff --git a/soh/include/functions.h b/soh/include/functions.h index 97e3be4d9..a8595680d 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -2461,6 +2461,9 @@ s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projected void PauseWarp_HandleSelection(); void PauseWarp_Execute(); +// Exposing for Roc's Feather +void func_80838940(Player* this, LinkAnimationHeader* anim, f32 arg2, PlayState* play, u16 sfxId); + // #endregion #ifdef __cplusplus diff --git a/soh/soh/Enhancements/Holiday/aMannus.cpp b/soh/soh/Enhancements/Holiday/aMannus.cpp new file mode 100644 index 000000000..8cf854b1d --- /dev/null +++ b/soh/soh/Enhancements/Holiday/aMannus.cpp @@ -0,0 +1,76 @@ +#include "Holiday.hpp" + +#define AUTHOR "aMannus" +#define CVAR(v) "gHoliday." AUTHOR "." v + +extern "C" { +#include ; +#include "functions.h"; +#include "variables.h"; +#include "macros.h"; +#include "objects/gameplay_keep/gameplay_keep.h" +extern PlayState* gPlayState; +} + +uint8_t rocsUseCount = 0; + +static void ConfigurationChanged() { + + COND_HOOK(OnPlayerUpdate, CVarGetInteger(CVAR("RocsFeather"), 0), []() { + Player* player = GET_PLAYER(gPlayState); + // Reset Rocs count when touching the ground + if (player->actor.bgCheckFlags & 1) { + rocsUseCount = 0; + } + }); + + COND_VB_SHOULD(VB_USE_ITEM, CVarGetInteger(CVAR("RocsFeather"), 0), { + int32_t* usedItem = va_arg(args, int32_t*); + Player* player = GET_PLAYER(gPlayState); + + // Roc's Feather behaviour + if (*usedItem == ITEM_NAYRUS_LOVE) { + *should = false; + + if (!rocsUseCount) { + rocsUseCount++; + player->linearVelocity = 5.0f; + player->actor.velocity.y = 8.0f; + player->actor.world.rot.y = player->yaw = player->actor.shape.rot.y; + + func_80838940(player, (LinkAnimationHeader*)&gPlayerAnim_link_fighter_backturn_jump, + !(2 & 1) ? 5.8f : 3.5f, gPlayState, 0); + + Vec3f effectsPos = player->actor.home.pos; + effectsPos.y += 3; + f32 effectsScale = 1; + if (!gSaveContext.linkAge) { + effectsScale = 1.5f; + } + EffectSsGRipple_Spawn(gPlayState, &effectsPos, 200 * effectsScale, 300 * effectsScale, 1); + EffectSsGSplash_Spawn(gPlayState, &effectsPos, NULL, NULL, 0, 150 * effectsScale); + + player->stateFlags2 &= ~(PLAYER_STATE2_HOPPING); + + Player_PlaySfx(&player->actor, NA_SE_PL_SKIP); + } + } + }); +} + +static void DrawMenu() { + ImGui::SeparatorText(AUTHOR); + + if (UIWidgets::EnhancementCheckbox("Roc's Feather", CVAR("RocsFeather"))) { + ConfigurationChanged(); + } + UIWidgets::Tooltip("Using Nayru's Love will now act as Roc's Feather instead! No magic required."); +} + +static void RegisterMod() { + // #region Leave this alone unless you know what you are doing + ConfigurationChanged(); + // #endregion +} + +static Holiday holiday(DrawMenu, RegisterMod); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 0225d8585..d33ff090c 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -344,6 +344,7 @@ typedef enum { VB_PLAY_THROW_ANIMATION, VB_INFLICT_VOID_DAMAGE, VB_GANONDORF_DECIDE_TO_FIGHT, + VB_USE_ITEM, /*** Give Items ***/ diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 28ef6e29d..151a47c13 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2572,8 +2572,10 @@ void Player_ProcessItemButtons(Player* this, PlayState* play) { sHeldItemButtonIsHeldDown = true; } } else { - this->heldItemButton = i; - Player_UseItem(play, this, item); + if (GameInteractor_Should(VB_USE_ITEM, true, &item)) { + this->heldItemButton = i; + Player_UseItem(play, this, item); + } } } }