From 8a48258b1bd407bcb381e0853163f7c87594fe88 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 15 Aug 2018 14:16:19 +0400 Subject: [PATCH 1/8] Fix attack after shoot --- apps/openmw/mwmechanics/character.cpp | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 6f9cb941d..594a8c9d0 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1385,14 +1385,6 @@ bool CharacterController::updateWeaponState() MWBase::Environment::get().getWorld()->breakInvisibility(mPtr); mAttackStrength = 0; - // Randomize attacks for non-bipedal creatures with Weapon flag - if (mPtr.getClass().getTypeName() == typeid(ESM::Creature).name() && - !mPtr.getClass().isBipedal(mPtr) && - (!mAnimation->hasAnimation(mCurrentWeapon) || isRandomAttackAnimation(mCurrentWeapon))) - { - mCurrentWeapon = chooseRandomAttackAnimation(); - } - if(mWeaponType == WeapType_Spell) { // Unset casting flag, otherwise pressing the mouse button down would @@ -1401,15 +1393,10 @@ bool CharacterController::updateWeaponState() if (mPtr == player) { MWBase::Environment::get().getWorld()->getPlayer().setAttackingOrSpell(false); - } - - const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - // For the player, set the spell we want to cast - // This has to be done at the start of the casting animation, - // *not* when selecting a spell in the GUI (otherwise you could change the spell mid-animation) - if (mPtr == player) - { + // For the player, set the spell we want to cast + // This has to be done at the start of the casting animation, + // *not* when selecting a spell in the GUI (otherwise you could change the spell mid-animation) std::string selectedSpell = MWBase::Environment::get().getWindowManager()->getSelectedSpell(); stats.getSpells().setSelectedSpell(selectedSpell); } @@ -1421,6 +1408,7 @@ bool CharacterController::updateWeaponState() MWMechanics::CastSpell cast(mPtr, NULL, false, mCastingManualSpell); cast.playSpellCastingEffects(spellid); + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Spell *spell = store.get().find(spellid); const ESM::ENAMstruct &lastEffect = spell->mEffects.mList.back(); const ESM::MagicEffect *effect; @@ -1520,13 +1508,12 @@ bool CharacterController::updateWeaponState() startKey = mAttackType+" start"; stopKey = mAttackType+" min attack"; } - - if (isRandomAttackAnimation(mCurrentWeapon)) + else if (isRandomAttackAnimation(mCurrentWeapon)) { startKey = "start"; stopKey = "stop"; } - else if (mAttackType != "shoot") + else { if(mPtr == getPlayer()) { From e444b9581c57884e604a2e882bb79b3e07921f06 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 15 Aug 2018 17:33:27 +0400 Subject: [PATCH 2/8] Do not play min attack -> max attack animation when attack strength is 0 (bug #4591) --- apps/openmw/mwmechanics/character.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 594a8c9d0..1748e3d45 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1670,11 +1670,6 @@ bool CharacterController::updateWeaponState() std::string start, stop; switch(mUpperBodyState) { - case UpperCharState_StartToMinAttack: - start = mAttackType+" min attack"; - stop = mAttackType+" max attack"; - mUpperBodyState = UpperCharState_MinAttackToMaxAttack; - break; case UpperCharState_MinAttackToMaxAttack: //hack to avoid body pos desync when jumping/sneaking in 'max attack' state if(!mAnimation->isPlaying(mCurrentWeapon)) @@ -1682,6 +1677,23 @@ bool CharacterController::updateWeaponState() MWRender::Animation::BlendMask_All, false, 0, mAttackType+" min attack", mAttackType+" max attack", 0.999f, 0); break; + case UpperCharState_StartToMinAttack: + { + // If actor is already stopped prepairing attack, do not play the "min attack -> max attack" part. + // Happens if the player did not hold the attack button. + // Note: if the "min attack"->"max attack" is a stub, "play" it anyway. Attack strength will be 1. + float minAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon+": "+mAttackType+" "+"min attack"); + float maxAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon+": "+mAttackType+" "+"max attack"); + if (mAttackingOrSpell || minAttackTime == maxAttackTime) + { + start = mAttackType+" min attack"; + stop = mAttackType+" max attack"; + mUpperBodyState = UpperCharState_MinAttackToMaxAttack; + break; + } + playSwishSound(0.0f); + } + // Fall-through case UpperCharState_MaxAttackToMinHit: if(mAttackType == "shoot") { From 15fa47827b5e2c053c1b4830cc31a58fafb5818f Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 15 Aug 2018 19:05:57 +0400 Subject: [PATCH 3/8] AiCombat: Avoid jittering when aiming in melee --- apps/openmw/mwmechanics/aicombat.cpp | 27 +++++++++++++++++++-------- apps/openmw/mwmechanics/aicombat.hpp | 2 +- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index cd9709885..438f4f7c6 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -372,21 +372,32 @@ namespace MWMechanics actorMovementSettings.mPosition[1] = storage.mMovement.mPosition[1]; actorMovementSettings.mPosition[2] = storage.mMovement.mPosition[2]; - rotateActorOnAxis(actor, 2, actorMovementSettings, storage.mMovement); - rotateActorOnAxis(actor, 0, actorMovementSettings, storage.mMovement); + rotateActorOnAxis(actor, 2, actorMovementSettings, storage); + rotateActorOnAxis(actor, 0, actorMovementSettings, storage); } void AiCombat::rotateActorOnAxis(const MWWorld::Ptr& actor, int axis, - MWMechanics::Movement& actorMovementSettings, MWMechanics::Movement& desiredMovement) + MWMechanics::Movement& actorMovementSettings, AiCombatStorage& storage) { actorMovementSettings.mRotation[axis] = 0; - float& targetAngleRadians = desiredMovement.mRotation[axis]; + float& targetAngleRadians = storage.mMovement.mRotation[axis]; if (targetAngleRadians != 0) { - if (smoothTurn(actor, targetAngleRadians, axis)) + // Some attack animations contain small amount of movement. + // Since we use cone shapes for melee, we can use a threshold to avoid jittering + std::shared_ptr& currentAction = storage.mCurrentAction; + bool isRangedCombat = false; + currentAction->getCombatRange(isRangedCombat); + // Check if the actor now facing desired direction, no need to turn any more + if (isRangedCombat) + { + if (smoothTurn(actor, targetAngleRadians, axis)) + targetAngleRadians = 0; + } + else { - // actor now facing desired direction, no need to turn any more - targetAngleRadians = 0; + if (smoothTurn(actor, targetAngleRadians, axis, osg::DegreesToRadians(3.f))) + targetAngleRadians = 0; } } } @@ -453,7 +464,7 @@ namespace MWMechanics if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25) { mMovement.mPosition[0] = Misc::Rng::rollProbability() < 0.5 ? 1.0f : -1.0f; // to the left/right - mTimerCombatMove = 0.05f + 0.15f * Misc::Rng::rollClosedProbability(); + mTimerCombatMove = 0.1f + 0.1f * Misc::Rng::rollClosedProbability(); mCombatMove = true; } } diff --git a/apps/openmw/mwmechanics/aicombat.hpp b/apps/openmw/mwmechanics/aicombat.hpp index 7c9891bcc..88feba481 100644 --- a/apps/openmw/mwmechanics/aicombat.hpp +++ b/apps/openmw/mwmechanics/aicombat.hpp @@ -129,7 +129,7 @@ namespace MWMechanics /// Transfer desired movement (from AiCombatStorage) to Actor void updateActorsMovement(const MWWorld::Ptr& actor, float duration, AiCombatStorage& storage); void rotateActorOnAxis(const MWWorld::Ptr& actor, int axis, - MWMechanics::Movement& actorMovementSettings, MWMechanics::Movement& desiredMovement); + MWMechanics::Movement& actorMovementSettings, AiCombatStorage& storage); }; From 3a6c480d414ed51bfa3cc80acfe3aa1cdd57545e Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 15 Aug 2018 19:10:15 +0400 Subject: [PATCH 4/8] Do not reset idle animations when turning --- apps/openmw/mwmechanics/character.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 1748e3d45..dd7c15ff6 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -411,8 +411,8 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character if(force || movement != mMovementState) { mMovementState = movement; - - if (movement != CharState_None) + // Turning animations should not interrupt idle ones + if (movement != CharState_None && !isTurning()) mIdleState = CharState_None; std::string movementAnimName; From 66a8402cdf3a3eb443a4609d13ec5e147d1cbb3c Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Wed, 15 Aug 2018 23:12:38 +0400 Subject: [PATCH 5/8] Add missing changelog entries --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8eef0d45..54a1a8ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ Bug #4230: AiTravel package issues break some Tribunal quests Bug #4231: Infected rats from the "Crimson Plague" quest rendered unconscious by change in Drain Fatigue functionality Bug #4251: Stationary NPCs do not return to their position after combat + Bug #4271: Scamp flickers when attacking Bug #4274: Pre-0.43 death animations are not forward-compatible with 0.43+ Bug #4286: Scripted animations can be interrupted Bug #4291: Non-persistent actors that started the game as dead do not play death animations @@ -92,6 +93,7 @@ Bug #4574: Player turning animations are twitchy Bug #4575: Weird result of attack animation blending with movement animations Bug #4576: Reset of idle animations when attack can not be started + Bug #4591: Attack strength should be 0 if player did not hold the attack button Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #3083: Play animation when NPC is casting spell via script Feature #3103: Provide option for disposition to get increased by successful trade From b7a448cf42833c573612d532547380cede021625 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 16 Aug 2018 11:21:48 +0400 Subject: [PATCH 6/8] Update idle animations after reset of mIdleState (bug #4531) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/character.cpp | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54a1a8ea7..8d9e9f97a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,7 @@ Bug #4503: Cast and ExplodeSpell commands increase alteration skill Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute Bug #4519: Knockdown does not discard movement in the 1st-person mode + Bug #4531: Movement does not reset idle animations Bug #4539: Paper Doll is affected by GUI scaling Bug #4545: Creatures flee from werewolves Bug #4551: Replace 0 sound range with default range separately diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index dd7c15ff6..855285b07 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -411,10 +411,6 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character if(force || movement != mMovementState) { mMovementState = movement; - // Turning animations should not interrupt idle ones - if (movement != CharState_None && !isTurning()) - mIdleState = CharState_None; - std::string movementAnimName; MWRender::Animation::BlendMask movemask = MWRender::Animation::BlendMask_All; const StateInfo *movestate = std::find_if(sMovementList, sMovementListEnd, FindCharState(mMovementState)); @@ -531,7 +527,7 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character void CharacterController::refreshIdleAnims(const WeaponInfo* weap, CharacterState idle, bool force) { - if(force || idle != mIdleState || (!mAnimation->isPlaying(mCurrentIdle) && mAnimQueue.empty())) + if(force || idle != mIdleState || mIdleState == CharState_None || (!mAnimation->isPlaying(mCurrentIdle) && mAnimQueue.empty())) { mIdleState = idle; size_t numLoops = ~0ul; @@ -562,10 +558,12 @@ void CharacterController::refreshIdleAnims(const WeaponInfo* weap, CharacterStat // play until the Loop Stop key 2 to 5 times, then play until the Stop key // this replicates original engine behavior for the "Idle1h" 1st-person animation numLoops = 1 + Misc::Rng::rollDice(4); - } + } } - mAnimation->disable(mCurrentIdle); + if(!mCurrentIdle.empty()) + mAnimation->disable(mCurrentIdle); + mCurrentIdle = idleGroup; if(!mCurrentIdle.empty()) mAnimation->play(mCurrentIdle, idlePriority, MWRender::Animation::BlendMask_All, false, @@ -2093,7 +2091,15 @@ void CharacterController::update(float duration) if(mAnimQueue.empty() || inwater || sneak) { - idlestate = (inwater ? CharState_IdleSwim : (sneak && !inJump ? CharState_IdleSneak : CharState_Idle)); + // Note: turning animations should not interrupt idle ones + if (inwater) + idlestate = CharState_IdleSwim; + else if (sneak && !inJump) + idlestate = CharState_IdleSneak; + else if (movestate != CharState_None && !isTurning()) + idlestate = CharState_None; + else + idlestate = CharState_Idle; } else updateAnimQueue(); From a73d42e711e68b759cc81d51543cbb791209ff73 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 16 Aug 2018 14:37:18 +0400 Subject: [PATCH 7/8] Do not stop idle animation in spellcasting stance --- apps/openmw/mwmechanics/character.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 855285b07..bdbf204c0 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -561,13 +561,21 @@ void CharacterController::refreshIdleAnims(const WeaponInfo* weap, CharacterStat } } + // There is no need to restart anim if the new and old anims are the same. + // Just update a number of loops. + float startPoint = 0; + if (!mCurrentIdle.empty() && mCurrentIdle == idleGroup) + { + mAnimation->getInfo(mCurrentIdle, &startPoint); + } + if(!mCurrentIdle.empty()) mAnimation->disable(mCurrentIdle); mCurrentIdle = idleGroup; if(!mCurrentIdle.empty()) mAnimation->play(mCurrentIdle, idlePriority, MWRender::Animation::BlendMask_All, false, - 1.0f, "start", "stop", 0.0f, numLoops, true); + 1.0f, "start", "stop", startPoint, numLoops, true); } } @@ -2091,12 +2099,13 @@ void CharacterController::update(float duration) if(mAnimQueue.empty() || inwater || sneak) { - // Note: turning animations should not interrupt idle ones + // Note: turning animations should not interrupt idle ones. + // Also movement should not stop idle animation for spellcasting stance. if (inwater) idlestate = CharState_IdleSwim; else if (sneak && !inJump) idlestate = CharState_IdleSneak; - else if (movestate != CharState_None && !isTurning()) + else if (movestate != CharState_None && !isTurning() && mWeaponType != WeapType_Spell) idlestate = CharState_None; else idlestate = CharState_Idle; From 16edac8c479660ab511bf78e3653a883c2c2ef97 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 16 Aug 2018 17:47:06 +0400 Subject: [PATCH 8/8] Fix incorrect 'preparing' word spelling --- apps/openmw/mwbase/mechanicsmanager.hpp | 2 +- apps/openmw/mwinput/inputmanagerimp.cpp | 4 ++-- apps/openmw/mwmechanics/actors.cpp | 4 ++-- apps/openmw/mwmechanics/actors.hpp | 2 +- apps/openmw/mwmechanics/character.cpp | 4 ++-- apps/openmw/mwmechanics/character.hpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 4 ++-- apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 995c8d736..fe3fc5721 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -257,7 +257,7 @@ namespace MWBase virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId) = 0; virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count) = 0; - virtual bool isAttackPrepairing(const MWWorld::Ptr& ptr) = 0; + virtual bool isAttackPreparing(const MWWorld::Ptr& ptr) = 0; virtual bool isRunning(const MWWorld::Ptr& ptr) = 0; virtual bool isSneaking(const MWWorld::Ptr& ptr) = 0; }; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 709c61196..65fc0c098 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -1004,9 +1004,9 @@ namespace MWInput if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"]) return; - // We want to interrupt animation only if attack is prepairing, but still is not triggered + // We want to interrupt animation only if attack is preparing, but still is not triggered // Otherwise we will get a "speedshooting" exploit, when player can skip reload animation by hitting "Toggle Weapon" key twice - if (MWBase::Environment::get().getMechanicsManager()->isAttackPrepairing(mPlayer->getPlayer())) + if (MWBase::Environment::get().getMechanicsManager()->isAttackPreparing(mPlayer->getPlayer())) mPlayer->setAttackingOrSpell(false); else if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer())) return; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 6a605c056..e794e0aaa 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -897,14 +897,14 @@ namespace MWMechanics } } - bool Actors::isAttackPrepairing(const MWWorld::Ptr& ptr) + bool Actors::isAttackPreparing(const MWWorld::Ptr& ptr) { PtrActorMap::iterator it = mActors.find(ptr); if (it == mActors.end()) return false; CharacterController* ctrl = it->second->getCharacterController(); - return ctrl->isAttackPrepairing(); + return ctrl->isAttackPreparing(); } bool Actors::isRunning(const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 492ff1e2e..8c94ce45f 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -118,7 +118,7 @@ namespace MWMechanics int countDeaths (const std::string& id) const; ///< Return the number of deaths for actors with the given ID. - bool isAttackPrepairing(const MWWorld::Ptr& ptr); + bool isAttackPreparing(const MWWorld::Ptr& ptr); bool isRunning(const MWWorld::Ptr& ptr); bool isSneaking(const MWWorld::Ptr& ptr); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index bdbf204c0..c7c6b57d0 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1685,7 +1685,7 @@ bool CharacterController::updateWeaponState() break; case UpperCharState_StartToMinAttack: { - // If actor is already stopped prepairing attack, do not play the "min attack -> max attack" part. + // If actor is already stopped preparing attack, do not play the "min attack -> max attack" part. // Happens if the player did not hold the attack button. // Note: if the "min attack"->"max attack" is a stub, "play" it anyway. Attack strength will be 1. float minAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon+": "+mAttackType+" "+"min attack"); @@ -2507,7 +2507,7 @@ bool CharacterController::isRandomAttackAnimation(const std::string& group) cons group == "attack3" || group == "swimattack3"); } -bool CharacterController::isAttackPrepairing() const +bool CharacterController::isAttackPreparing() const { return mUpperBodyState == UpperCharState_StartToMinAttack || mUpperBodyState == UpperCharState_MinAttackToMaxAttack; diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 631f78208..43d26e52f 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -281,7 +281,7 @@ public: void forceStateUpdate(); - bool isAttackPrepairing() const; + bool isAttackPreparing() const; bool isCastingSpell() const; bool isReadyToBlock() const; bool isKnockedDown() const; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 7814b4a91..dbc2cd93c 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -435,9 +435,9 @@ namespace MWMechanics return mActors.isActorDetected(actor, observer); } - bool MechanicsManager::isAttackPrepairing(const MWWorld::Ptr& ptr) + bool MechanicsManager::isAttackPreparing(const MWWorld::Ptr& ptr) { - return mActors.isAttackPrepairing(ptr); + return mActors.isAttackPreparing(ptr); } bool MechanicsManager::isRunning(const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 676a75caf..e9ec14685 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -223,7 +223,7 @@ namespace MWMechanics virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count); - virtual bool isAttackPrepairing(const MWWorld::Ptr& ptr); + virtual bool isAttackPreparing(const MWWorld::Ptr& ptr); virtual bool isRunning(const MWWorld::Ptr& ptr); virtual bool isSneaking(const MWWorld::Ptr& ptr);