mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-31 14:36:39 +00:00
Merge pull request #1874 from akortunov/combat_anims
Fix some issues with attack animations
This commit is contained in:
commit
7f3769d5fc
11 changed files with 81 additions and 53 deletions
|
@ -39,6 +39,7 @@
|
||||||
Bug #4230: AiTravel package issues break some Tribunal quests
|
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 #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 #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 #4274: Pre-0.43 death animations are not forward-compatible with 0.43+
|
||||||
Bug #4286: Scripted animations can be interrupted
|
Bug #4286: Scripted animations can be interrupted
|
||||||
Bug #4291: Non-persistent actors that started the game as dead do not play death animations
|
Bug #4291: Non-persistent actors that started the game as dead do not play death animations
|
||||||
|
@ -83,6 +84,7 @@
|
||||||
Bug #4503: Cast and ExplodeSpell commands increase alteration skill
|
Bug #4503: Cast and ExplodeSpell commands increase alteration skill
|
||||||
Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute
|
Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute
|
||||||
Bug #4519: Knockdown does not discard movement in the 1st-person mode
|
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 #4539: Paper Doll is affected by GUI scaling
|
||||||
Bug #4545: Creatures flee from werewolves
|
Bug #4545: Creatures flee from werewolves
|
||||||
Bug #4551: Replace 0 sound range with default range separately
|
Bug #4551: Replace 0 sound range with default range separately
|
||||||
|
@ -95,6 +97,7 @@
|
||||||
Bug #4574: Player turning animations are twitchy
|
Bug #4574: Player turning animations are twitchy
|
||||||
Bug #4575: Weird result of attack animation blending with movement animations
|
Bug #4575: Weird result of attack animation blending with movement animations
|
||||||
Bug #4576: Reset of idle animations when attack can not be started
|
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 #1645: Casting effects from objects
|
Feature #1645: Casting effects from objects
|
||||||
Feature #2606: Editor: Implemented (optional) case sensitive global search
|
Feature #2606: Editor: Implemented (optional) case sensitive global search
|
||||||
Feature #3083: Play animation when NPC is casting spell via script
|
Feature #3083: Play animation when NPC is casting spell via script
|
||||||
|
|
|
@ -257,7 +257,7 @@ namespace MWBase
|
||||||
virtual void cleanupSummonedCreature(const MWWorld::Ptr& caster, int creatureActorId) = 0;
|
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 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 isRunning(const MWWorld::Ptr& ptr) = 0;
|
||||||
virtual bool isSneaking(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isSneaking(const MWWorld::Ptr& ptr) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1004,9 +1004,9 @@ namespace MWInput
|
||||||
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
if (!mControlSwitch["playerfighting"] || !mControlSwitch["playercontrols"])
|
||||||
return;
|
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
|
// 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);
|
mPlayer->setAttackingOrSpell(false);
|
||||||
else if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
else if (MWBase::Environment::get().getMechanicsManager()->isAttackingOrSpell(mPlayer->getPlayer()))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -896,14 +896,14 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Actors::isAttackPrepairing(const MWWorld::Ptr& ptr)
|
bool Actors::isAttackPreparing(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
PtrActorMap::iterator it = mActors.find(ptr);
|
PtrActorMap::iterator it = mActors.find(ptr);
|
||||||
if (it == mActors.end())
|
if (it == mActors.end())
|
||||||
return false;
|
return false;
|
||||||
CharacterController* ctrl = it->second->getCharacterController();
|
CharacterController* ctrl = it->second->getCharacterController();
|
||||||
|
|
||||||
return ctrl->isAttackPrepairing();
|
return ctrl->isAttackPreparing();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Actors::isRunning(const MWWorld::Ptr& ptr)
|
bool Actors::isRunning(const MWWorld::Ptr& ptr)
|
||||||
|
|
|
@ -118,7 +118,7 @@ namespace MWMechanics
|
||||||
int countDeaths (const std::string& id) const;
|
int countDeaths (const std::string& id) const;
|
||||||
///< Return the number of deaths for actors with the given ID.
|
///< 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 isRunning(const MWWorld::Ptr& ptr);
|
||||||
bool isSneaking(const MWWorld::Ptr& ptr);
|
bool isSneaking(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
|
|
@ -372,20 +372,31 @@ namespace MWMechanics
|
||||||
actorMovementSettings.mPosition[1] = storage.mMovement.mPosition[1];
|
actorMovementSettings.mPosition[1] = storage.mMovement.mPosition[1];
|
||||||
actorMovementSettings.mPosition[2] = storage.mMovement.mPosition[2];
|
actorMovementSettings.mPosition[2] = storage.mMovement.mPosition[2];
|
||||||
|
|
||||||
rotateActorOnAxis(actor, 2, actorMovementSettings, storage.mMovement);
|
rotateActorOnAxis(actor, 2, actorMovementSettings, storage);
|
||||||
rotateActorOnAxis(actor, 0, actorMovementSettings, storage.mMovement);
|
rotateActorOnAxis(actor, 0, actorMovementSettings, storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiCombat::rotateActorOnAxis(const MWWorld::Ptr& actor, int axis,
|
void AiCombat::rotateActorOnAxis(const MWWorld::Ptr& actor, int axis,
|
||||||
MWMechanics::Movement& actorMovementSettings, MWMechanics::Movement& desiredMovement)
|
MWMechanics::Movement& actorMovementSettings, AiCombatStorage& storage)
|
||||||
{
|
{
|
||||||
actorMovementSettings.mRotation[axis] = 0;
|
actorMovementSettings.mRotation[axis] = 0;
|
||||||
float& targetAngleRadians = desiredMovement.mRotation[axis];
|
float& targetAngleRadians = storage.mMovement.mRotation[axis];
|
||||||
if (targetAngleRadians != 0)
|
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<Action>& 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)
|
||||||
{
|
{
|
||||||
// actor now facing desired direction, no need to turn any more
|
if (smoothTurn(actor, targetAngleRadians, axis))
|
||||||
|
targetAngleRadians = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (smoothTurn(actor, targetAngleRadians, axis, osg::DegreesToRadians(3.f)))
|
||||||
targetAngleRadians = 0;
|
targetAngleRadians = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,7 +464,7 @@ namespace MWMechanics
|
||||||
if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25)
|
if (distToTarget <= rangeAttackOfTarget && Misc::Rng::rollClosedProbability() < 0.25)
|
||||||
{
|
{
|
||||||
mMovement.mPosition[0] = Misc::Rng::rollProbability() < 0.5 ? 1.0f : -1.0f; // to the left/right
|
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;
|
mCombatMove = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ namespace MWMechanics
|
||||||
/// Transfer desired movement (from AiCombatStorage) to Actor
|
/// Transfer desired movement (from AiCombatStorage) to Actor
|
||||||
void updateActorsMovement(const MWWorld::Ptr& actor, float duration, AiCombatStorage& storage);
|
void updateActorsMovement(const MWWorld::Ptr& actor, float duration, AiCombatStorage& storage);
|
||||||
void rotateActorOnAxis(const MWWorld::Ptr& actor, int axis,
|
void rotateActorOnAxis(const MWWorld::Ptr& actor, int axis,
|
||||||
MWMechanics::Movement& actorMovementSettings, MWMechanics::Movement& desiredMovement);
|
MWMechanics::Movement& actorMovementSettings, AiCombatStorage& storage);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -411,10 +411,6 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character
|
||||||
if(force || movement != mMovementState)
|
if(force || movement != mMovementState)
|
||||||
{
|
{
|
||||||
mMovementState = movement;
|
mMovementState = movement;
|
||||||
|
|
||||||
if (movement != CharState_None)
|
|
||||||
mIdleState = CharState_None;
|
|
||||||
|
|
||||||
std::string movementAnimName;
|
std::string movementAnimName;
|
||||||
MWRender::Animation::BlendMask movemask = MWRender::Animation::BlendMask_All;
|
MWRender::Animation::BlendMask movemask = MWRender::Animation::BlendMask_All;
|
||||||
const StateInfo *movestate = std::find_if(sMovementList, sMovementListEnd, FindCharState(mMovementState));
|
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)
|
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;
|
mIdleState = idle;
|
||||||
size_t numLoops = ~0ul;
|
size_t numLoops = ~0ul;
|
||||||
|
@ -565,11 +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);
|
mAnimation->disable(mCurrentIdle);
|
||||||
|
|
||||||
mCurrentIdle = idleGroup;
|
mCurrentIdle = idleGroup;
|
||||||
if(!mCurrentIdle.empty())
|
if(!mCurrentIdle.empty())
|
||||||
mAnimation->play(mCurrentIdle, idlePriority, MWRender::Animation::BlendMask_All, false,
|
mAnimation->play(mCurrentIdle, idlePriority, MWRender::Animation::BlendMask_All, false,
|
||||||
1.0f, "start", "stop", 0.0f, numLoops, true);
|
1.0f, "start", "stop", startPoint, numLoops, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1385,14 +1391,6 @@ bool CharacterController::updateWeaponState()
|
||||||
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
|
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
|
||||||
mAttackStrength = 0;
|
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)
|
if(mWeaponType == WeapType_Spell)
|
||||||
{
|
{
|
||||||
// Unset casting flag, otherwise pressing the mouse button down would
|
// Unset casting flag, otherwise pressing the mouse button down would
|
||||||
|
@ -1401,15 +1399,10 @@ bool CharacterController::updateWeaponState()
|
||||||
if (mPtr == player)
|
if (mPtr == player)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setAttackingOrSpell(false);
|
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
|
// For the player, set the spell we want to cast
|
||||||
// This has to be done at the start of the casting animation,
|
// 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)
|
// *not* when selecting a spell in the GUI (otherwise you could change the spell mid-animation)
|
||||||
if (mPtr == player)
|
|
||||||
{
|
|
||||||
std::string selectedSpell = MWBase::Environment::get().getWindowManager()->getSelectedSpell();
|
std::string selectedSpell = MWBase::Environment::get().getWindowManager()->getSelectedSpell();
|
||||||
stats.getSpells().setSelectedSpell(selectedSpell);
|
stats.getSpells().setSelectedSpell(selectedSpell);
|
||||||
}
|
}
|
||||||
|
@ -1421,6 +1414,7 @@ bool CharacterController::updateWeaponState()
|
||||||
MWMechanics::CastSpell cast(mPtr, NULL, false, mCastingManualSpell);
|
MWMechanics::CastSpell cast(mPtr, NULL, false, mCastingManualSpell);
|
||||||
cast.playSpellCastingEffects(spellid);
|
cast.playSpellCastingEffects(spellid);
|
||||||
|
|
||||||
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
const ESM::Spell *spell = store.get<ESM::Spell>().find(spellid);
|
||||||
const ESM::ENAMstruct &lastEffect = spell->mEffects.mList.back();
|
const ESM::ENAMstruct &lastEffect = spell->mEffects.mList.back();
|
||||||
const ESM::MagicEffect *effect;
|
const ESM::MagicEffect *effect;
|
||||||
|
@ -1520,13 +1514,12 @@ bool CharacterController::updateWeaponState()
|
||||||
startKey = mAttackType+" start";
|
startKey = mAttackType+" start";
|
||||||
stopKey = mAttackType+" min attack";
|
stopKey = mAttackType+" min attack";
|
||||||
}
|
}
|
||||||
|
else if (isRandomAttackAnimation(mCurrentWeapon))
|
||||||
if (isRandomAttackAnimation(mCurrentWeapon))
|
|
||||||
{
|
{
|
||||||
startKey = "start";
|
startKey = "start";
|
||||||
stopKey = "stop";
|
stopKey = "stop";
|
||||||
}
|
}
|
||||||
else if (mAttackType != "shoot")
|
else
|
||||||
{
|
{
|
||||||
if(mPtr == getPlayer())
|
if(mPtr == getPlayer())
|
||||||
{
|
{
|
||||||
|
@ -1683,11 +1676,6 @@ bool CharacterController::updateWeaponState()
|
||||||
std::string start, stop;
|
std::string start, stop;
|
||||||
switch(mUpperBodyState)
|
switch(mUpperBodyState)
|
||||||
{
|
{
|
||||||
case UpperCharState_StartToMinAttack:
|
|
||||||
start = mAttackType+" min attack";
|
|
||||||
stop = mAttackType+" max attack";
|
|
||||||
mUpperBodyState = UpperCharState_MinAttackToMaxAttack;
|
|
||||||
break;
|
|
||||||
case UpperCharState_MinAttackToMaxAttack:
|
case UpperCharState_MinAttackToMaxAttack:
|
||||||
//hack to avoid body pos desync when jumping/sneaking in 'max attack' state
|
//hack to avoid body pos desync when jumping/sneaking in 'max attack' state
|
||||||
if(!mAnimation->isPlaying(mCurrentWeapon))
|
if(!mAnimation->isPlaying(mCurrentWeapon))
|
||||||
|
@ -1695,6 +1683,23 @@ bool CharacterController::updateWeaponState()
|
||||||
MWRender::Animation::BlendMask_All, false,
|
MWRender::Animation::BlendMask_All, false,
|
||||||
0, mAttackType+" min attack", mAttackType+" max attack", 0.999f, 0);
|
0, mAttackType+" min attack", mAttackType+" max attack", 0.999f, 0);
|
||||||
break;
|
break;
|
||||||
|
case UpperCharState_StartToMinAttack:
|
||||||
|
{
|
||||||
|
// 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");
|
||||||
|
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:
|
case UpperCharState_MaxAttackToMinHit:
|
||||||
if(mAttackType == "shoot")
|
if(mAttackType == "shoot")
|
||||||
{
|
{
|
||||||
|
@ -2094,7 +2099,16 @@ void CharacterController::update(float duration)
|
||||||
|
|
||||||
if(mAnimQueue.empty() || inwater || sneak)
|
if(mAnimQueue.empty() || inwater || sneak)
|
||||||
{
|
{
|
||||||
idlestate = (inwater ? CharState_IdleSwim : (sneak && !inJump ? CharState_IdleSneak : CharState_Idle));
|
// 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() && mWeaponType != WeapType_Spell)
|
||||||
|
idlestate = CharState_None;
|
||||||
|
else
|
||||||
|
idlestate = CharState_Idle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
updateAnimQueue();
|
updateAnimQueue();
|
||||||
|
@ -2493,7 +2507,7 @@ bool CharacterController::isRandomAttackAnimation(const std::string& group) cons
|
||||||
group == "attack3" || group == "swimattack3");
|
group == "attack3" || group == "swimattack3");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterController::isAttackPrepairing() const
|
bool CharacterController::isAttackPreparing() const
|
||||||
{
|
{
|
||||||
return mUpperBodyState == UpperCharState_StartToMinAttack ||
|
return mUpperBodyState == UpperCharState_StartToMinAttack ||
|
||||||
mUpperBodyState == UpperCharState_MinAttackToMaxAttack;
|
mUpperBodyState == UpperCharState_MinAttackToMaxAttack;
|
||||||
|
|
|
@ -281,7 +281,7 @@ public:
|
||||||
|
|
||||||
void forceStateUpdate();
|
void forceStateUpdate();
|
||||||
|
|
||||||
bool isAttackPrepairing() const;
|
bool isAttackPreparing() const;
|
||||||
bool isCastingSpell() const;
|
bool isCastingSpell() const;
|
||||||
bool isReadyToBlock() const;
|
bool isReadyToBlock() const;
|
||||||
bool isKnockedDown() const;
|
bool isKnockedDown() const;
|
||||||
|
|
|
@ -436,9 +436,9 @@ namespace MWMechanics
|
||||||
return mActors.isActorDetected(actor, observer);
|
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)
|
bool MechanicsManager::isRunning(const MWWorld::Ptr& ptr)
|
||||||
|
|
|
@ -229,7 +229,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
virtual void confiscateStolenItemToOwner(const MWWorld::Ptr &player, const MWWorld::Ptr &item, const MWWorld::Ptr& victim, int count);
|
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 isRunning(const MWWorld::Ptr& ptr);
|
||||||
virtual bool isSneaking(const MWWorld::Ptr& ptr);
|
virtual bool isSneaking(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue