Proper fix for 2 handed idle animation (#6109)
This commit is contained in:
59
soh/soh/Enhancements/Fixes/FixTwoHandedIdleAnim.cpp
Normal file
59
soh/soh/Enhancements/Fixes/FixTwoHandedIdleAnim.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
#include "functions.h"
|
||||
}
|
||||
|
||||
#define FIDGET_SWORD_SWING 9
|
||||
#define FIDGET_ADJUST_SHIELD 12
|
||||
|
||||
static constexpr int32_t CVAR_FIX_TWO_HANDED_IDLE_DEFAULT = 0;
|
||||
#define CVAR_FIX_TWO_HANDED_IDLE_NAME CVAR_ENHANCEMENT("TwoHandedIdle")
|
||||
#define CVAR_FIX_TWO_HANDED_IDLE_VALUE CVarGetInteger(CVAR_FIX_TWO_HANDED_IDLE_NAME, CVAR_FIX_TWO_HANDED_IDLE_DEFAULT)
|
||||
|
||||
// clang-format off
|
||||
static RegisterShipInitFunc initFunc([]() {
|
||||
COND_VB_SHOULD(VB_SET_IDLE_ANIM, CVAR_FIX_TWO_HANDED_IDLE_VALUE, {
|
||||
Player* player = va_arg(args, Player*);
|
||||
s32 commonType = va_arg(args, s32);
|
||||
|
||||
// Fixes a bug here where the condition for reaching two-handed idle animation was impossible. Original condition:
|
||||
/*
|
||||
(
|
||||
(
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)
|
||||
) ||
|
||||
(
|
||||
(player->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||
(
|
||||
(commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD) ||
|
||||
// This should not have been grouped here, because two handed melee weapons do not have shield.
|
||||
(Player_GetMeleeWeaponHeld2(player) != 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
*/
|
||||
|
||||
*should = (
|
||||
// Animation is not FIDGET_SWORD_SWING and FIDGET_ADJUST_SHIELD (So it's either FIDGET_ADJUST_TUNIC or FIDGET_TAP_FEET)
|
||||
(
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)
|
||||
) ||
|
||||
// Animation is FIDGET_ADJUST_SHIELD and player is holding a shield in right hand
|
||||
(
|
||||
(player->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||
(commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD)
|
||||
) ||
|
||||
// Animation is FIDGET_SWORD_SWING and player is holding a melee weapon
|
||||
(
|
||||
(commonType + FIDGET_SWORD_SWING == FIDGET_SWORD_SWING) &&
|
||||
(Player_GetMeleeWeaponHeld(player) != 0)
|
||||
)
|
||||
);
|
||||
});
|
||||
}, { CVAR_FIX_TWO_HANDED_IDLE_NAME });
|
||||
// clang-format on
|
||||
@@ -2327,6 +2327,27 @@ typedef enum {
|
||||
// - `*Player`
|
||||
VB_SET_STATIC_FLOOR_TYPE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// (
|
||||
// (
|
||||
// (commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||
// (commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)
|
||||
// ) ||
|
||||
// (
|
||||
// (player->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||
// (
|
||||
// (commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD) ||
|
||||
// (Player_GetMeleeWeaponHeld2(player) != 0)
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `Player*`
|
||||
// - `s32` commonType
|
||||
VB_SET_IDLE_ANIM,
|
||||
|
||||
} GIVanillaBehavior;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8293,19 +8293,20 @@ void Player_ChooseNextIdleAnim(PlayState* play, Player* this) {
|
||||
//
|
||||
// Note that `FIDGET_SWORD_SWING` is the first common fidget type, which is why
|
||||
// all operations are done relative to this type.
|
||||
if (((commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)) ||
|
||||
((this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||
((commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD) ||
|
||||
(Player_GetMeleeWeaponHeld2(this) != 0)))) {
|
||||
if (GameInteractor_Should(VB_SET_IDLE_ANIM,
|
||||
(((commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||
(commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)) ||
|
||||
((this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||
((commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD) ||
|
||||
(Player_GetMeleeWeaponHeld2(this) != 0)))),
|
||||
this, commonType)) {
|
||||
//! @bug It is possible for `FIDGET_ADJUST_SHIELD` to be used even if
|
||||
//! a shield is not currently equipped. This is because of how being shieldless
|
||||
//! is implemented. There is no sword-only model type, only
|
||||
//! `PLAYER_MODELGROUP_SWORD_AND_SHIELD` exists. Therefore, the right hand type will be
|
||||
//! `PLAYER_MODELTYPE_RH_SHIELD` if sword is in hand, even if no shield is equipped.
|
||||
if ((commonType + FIDGET_SWORD_SWING == FIDGET_SWORD_SWING) &&
|
||||
Player_HoldsTwoHandedWeapon(this) &&
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TwoHandedIdle"), 0) == 1) {
|
||||
Player_HoldsTwoHandedWeapon(this)) {
|
||||
//! @bug This code is unreachable.
|
||||
//! The check above groups the `Player_GetMeleeWeaponHeld2` check and
|
||||
//! `PLAYER_MODELTYPE_RH_SHIELD` conditions together, meaning sword and shield must be
|
||||
|
||||
Reference in New Issue
Block a user