From eadade9dfcfb4e571484a1db45d75f31c245e357 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 12 Oct 2022 23:53:44 +0300 Subject: [PATCH] Don't process unexpected hit text keys (bug #7042) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/character.cpp | 61 +++++++++++++++++---------- apps/openmw/mwmechanics/character.hpp | 2 +- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38f20124b9..26c0b94a18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Bug #6993: Shooting your last round of ammunition causes the attack animation to cancel Bug #7009: Falling actors teleport to the ground without receiving any damage on cell loading Bug #7034: Misc items defined in one content file are not treated as keys if another content file uses them as such + Bug #7042: Weapon follow animations that immediately follow the hit animations cause multiple hits Bug #7044: Changing a class' services does not affect autocalculated NPCs Feature #6933: Support high-resolution cursor textures Feature #6945: Support S3TC-compressed and BGR/BGRA NiPixelData diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index c76c47e05f..73f7dd66bb 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1061,25 +1061,31 @@ namespace MWMechanics else mAnimation->showWeapons(false); } - else if (action == "chop hit") - charClass.hit(mPtr, mAttackStrength, ESM::Weapon::AT_Chop, mAttackVictim, mAttackHitPos, mAttackSuccess); - else if (action == "slash hit") - charClass.hit(mPtr, mAttackStrength, ESM::Weapon::AT_Slash, mAttackVictim, mAttackHitPos, mAttackSuccess); - else if (action == "thrust hit") - charClass.hit(mPtr, mAttackStrength, ESM::Weapon::AT_Thrust, mAttackVictim, mAttackHitPos, mAttackSuccess); - else if (action == "hit") - { - if (groupname == "attack1" || groupname == "swimattack1") - charClass.hit( - mPtr, mAttackStrength, ESM::Weapon::AT_Chop, mAttackVictim, mAttackHitPos, mAttackSuccess); - else if (groupname == "attack2" || groupname == "swimattack2") - charClass.hit( - mPtr, mAttackStrength, ESM::Weapon::AT_Slash, mAttackVictim, mAttackHitPos, mAttackSuccess); - else if (groupname == "attack3" || groupname == "swimattack3") - charClass.hit( - mPtr, mAttackStrength, ESM::Weapon::AT_Thrust, mAttackVictim, mAttackHitPos, mAttackSuccess); - else - charClass.hit(mPtr, mAttackStrength, -1, mAttackVictim, mAttackHitPos, mAttackSuccess); + else if (action == "chop hit" || action == "slash hit" || action == "thrust hit" || action == "hit") + { + int attackType = -1; + if (action == "hit") + { + if (groupname == "attack1" || groupname == "swimattack1") + attackType = ESM::Weapon::AT_Chop; + else if (groupname == "attack2" || groupname == "swimattack2") + attackType = ESM::Weapon::AT_Slash; + else if (groupname == "attack3" || groupname == "swimattack3") + attackType = ESM::Weapon::AT_Thrust; + } + else if (action == "chop hit") + attackType = ESM::Weapon::AT_Chop; + else if (action == "slash hit") + attackType = ESM::Weapon::AT_Slash; + else if (action == "thrust hit") + attackType = ESM::Weapon::AT_Thrust; + // We want to avoid hit keys that come out of nowhere (e.g. in the follow animation) + // and processing multiple hit keys for a single attack + if (mAttackStrength != -1.f) + { + charClass.hit(mPtr, mAttackStrength, attackType, mAttackVictim, mAttackHitPos, mAttackSuccess); + mAttackStrength = -1.f; + } } else if (isRandomAttackAnimation(groupname) && action == "start") { @@ -1102,7 +1108,7 @@ namespace MWMechanics } ++hitKey; } - if (!hasHitKey) + if (!hasHitKey && mAttackStrength != -1.f) { if (groupname == "attack1" || groupname == "swimattack1") charClass.hit( @@ -1113,12 +1119,20 @@ namespace MWMechanics else if (groupname == "attack3" || groupname == "swimattack3") charClass.hit( mPtr, mAttackStrength, ESM::Weapon::AT_Thrust, mAttackVictim, mAttackHitPos, mAttackSuccess); + mAttackStrength = -1.f; } } else if (action == "shoot attach") mAnimation->attachArrow(); else if (action == "shoot release") - mAnimation->releaseArrow(mAttackStrength); + { + // See notes for melee release above + if (mAttackStrength != -1.f) + { + mAnimation->releaseArrow(mAttackStrength); + mAttackStrength = -1.f; + } + } else if (action == "shoot follow attach") mAnimation->attachArrow(); // Make sure this key is actually for the RangeType we are casting. The flame atronach has @@ -1446,7 +1460,7 @@ namespace MWMechanics if (mUpperBodyState == UpperBodyState::WeaponEquipped && (mHitState == CharState_None || mHitState == CharState_Block)) { - mAttackStrength = 0; + mAttackStrength = -1.f; // Randomize attacks for non-bipedal creatures if (!cls.isBipedal(mPtr) @@ -1731,6 +1745,9 @@ namespace MWMechanics stop = strength + ' ' + stop; } + // Reset attack strength to make extra sure hits that come out of nowhere aren't processed + mAttackStrength = -1.f; + if (animPlaying) mAnimation->disable(mCurrentWeapon); MWRender::Animation::AnimPriority priorityFollow(priorityWeapon); diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 0e2aee6701..b397d788ea 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -164,7 +164,7 @@ namespace MWMechanics int mWeaponType{ ESM::Weapon::None }; std::string mCurrentWeapon; - float mAttackStrength{ 0.f }; + float mAttackStrength{ -1.f }; MWWorld::Ptr mAttackVictim; osg::Vec3f mAttackHitPos; bool mAttackSuccess{ false };