diff --git a/mm/2s2h/BenGui/BenMenu.cpp b/mm/2s2h/BenGui/BenMenu.cpp index d1ed1a72c3..9b4dd3f5be 100644 --- a/mm/2s2h/BenGui/BenMenu.cpp +++ b/mm/2s2h/BenGui/BenMenu.cpp @@ -1406,6 +1406,10 @@ void BenMenu::AddEnhancements() { .Options(CheckboxOptions().Tooltip("Restores the appearance of Woodfall mountain to not look poisoned " "when viewed from Termina Field after clearing Woodfall Temple\n\n" "Requires a scene reload to take effect.")); + AddWidget(path, "Bonk Collision", WIDGET_CVAR_CHECKBOX) + .CVar("gEnhancements.Restorations.BonkCollision") + .Options( + CheckboxOptions().Tooltip("Corrects rolls to allow bonking trees near the end of the roll, as in OoT.")); AddWidget(path, "Simulated Input Lag", WIDGET_CVAR_SLIDER_INT) .CVar(CVAR_SIMULATED_INPUT_LAG) .Options(IntSliderOptions() diff --git a/mm/2s2h/Enhancements/Restorations/BonkCollision.cpp b/mm/2s2h/Enhancements/Restorations/BonkCollision.cpp new file mode 100644 index 0000000000..dcbbee6cd1 --- /dev/null +++ b/mm/2s2h/Enhancements/Restorations/BonkCollision.cpp @@ -0,0 +1,20 @@ +#include +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gEnhancements.Restorations.BonkCollision" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + +void RegisterBonkCollision() { + COND_VB_SHOULD(VB_SET_PLAYER_CYLINDER_OC_FLAGS, CVAR, { + Player* player = va_arg(args, Player*); + u32 dmgFlags = va_arg(args, u32); + if (dmgFlags == DMG_NORMAL_ROLL) { + // OR the new flags instead of directly assigning them + player->cylinder.base.ocFlags1 |= OC1_ON | OC1_TYPE_ALL; + *should = false; + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterBonkCollision, { CVAR_NAME }); diff --git a/mm/2s2h/GameInteractor/GameInteractor.h b/mm/2s2h/GameInteractor/GameInteractor.h index 5ca04daddd..23cc19e0bb 100644 --- a/mm/2s2h/GameInteractor/GameInteractor.h +++ b/mm/2s2h/GameInteractor/GameInteractor.h @@ -262,6 +262,7 @@ typedef enum { VB_ENABLE_OBJECT_DEPENDENCY, VB_OBJ_MURE2_SET_CHILD_ROOM, VB_OBJ_MURE3_DROP_COLLECTIBLE, + VB_SET_PLAYER_CYLINDER_OC_FLAGS, } GIVanillaBehavior; typedef enum { diff --git a/mm/src/overlays/actors/ovl_player_actor/z_player.c b/mm/src/overlays/actors/ovl_player_actor/z_player.c index 4262624619..236028dd00 100644 --- a/mm/src/overlays/actors/ovl_player_actor/z_player.c +++ b/mm/src/overlays/actors/ovl_player_actor/z_player.c @@ -2903,7 +2903,9 @@ void Player_SetCylinderForAttack(Player* this, u32 dmgFlags, s32 damage, s32 rad if (radius > 30) { this->cylinder.base.ocFlags1 = OC1_NONE; } else { - this->cylinder.base.ocFlags1 = OC1_ON | OC1_TYPE_ALL; + if (GameInteractor_Should(VB_SET_PLAYER_CYLINDER_OC_FLAGS, true, this, dmgFlags)) { + this->cylinder.base.ocFlags1 = OC1_ON | OC1_TYPE_ALL; + } } this->cylinder.elem.elemMaterial = ELEM_MATERIAL_UNK2;