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`
|
// - `*Player`
|
||||||
VB_SET_STATIC_FLOOR_TYPE,
|
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;
|
} GIVanillaBehavior;
|
||||||
|
|
||||||
#endif
|
#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
|
// Note that `FIDGET_SWORD_SWING` is the first common fidget type, which is why
|
||||||
// all operations are done relative to this type.
|
// all operations are done relative to this type.
|
||||||
if (((commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
if (GameInteractor_Should(VB_SET_IDLE_ANIM,
|
||||||
|
(((commonType + FIDGET_SWORD_SWING != FIDGET_SWORD_SWING) &&
|
||||||
(commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)) ||
|
(commonType + FIDGET_SWORD_SWING != FIDGET_ADJUST_SHIELD)) ||
|
||||||
((this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
((this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
|
||||||
((commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD) ||
|
((commonType + FIDGET_SWORD_SWING == FIDGET_ADJUST_SHIELD) ||
|
||||||
(Player_GetMeleeWeaponHeld2(this) != 0)))) {
|
(Player_GetMeleeWeaponHeld2(this) != 0)))),
|
||||||
|
this, commonType)) {
|
||||||
//! @bug It is possible for `FIDGET_ADJUST_SHIELD` to be used even if
|
//! @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
|
//! a shield is not currently equipped. This is because of how being shieldless
|
||||||
//! is implemented. There is no sword-only model type, only
|
//! is implemented. There is no sword-only model type, only
|
||||||
//! `PLAYER_MODELGROUP_SWORD_AND_SHIELD` exists. Therefore, the right hand type will be
|
//! `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.
|
//! `PLAYER_MODELTYPE_RH_SHIELD` if sword is in hand, even if no shield is equipped.
|
||||||
if ((commonType + FIDGET_SWORD_SWING == FIDGET_SWORD_SWING) &&
|
if ((commonType + FIDGET_SWORD_SWING == FIDGET_SWORD_SWING) &&
|
||||||
Player_HoldsTwoHandedWeapon(this) &&
|
Player_HoldsTwoHandedWeapon(this)) {
|
||||||
CVarGetInteger(CVAR_ENHANCEMENT("TwoHandedIdle"), 0) == 1) {
|
|
||||||
//! @bug This code is unreachable.
|
//! @bug This code is unreachable.
|
||||||
//! The check above groups the `Player_GetMeleeWeaponHeld2` check and
|
//! The check above groups the `Player_GetMeleeWeaponHeld2` check and
|
||||||
//! `PLAYER_MODELTYPE_RH_SHIELD` conditions together, meaning sword and shield must be
|
//! `PLAYER_MODELTYPE_RH_SHIELD` conditions together, meaning sword and shield must be
|
||||||
|
|||||||
Reference in New Issue
Block a user