mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-29 00:06:43 +00:00
Do not update mIdleState directly
This commit is contained in:
parent
929d78d6a3
commit
0136f0552b
2 changed files with 78 additions and 48 deletions
|
@ -243,7 +243,7 @@ std::string CharacterController::chooseRandomGroup (const std::string& prefix, i
|
||||||
return prefix + toString(roll);
|
return prefix + toString(roll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::refreshHitRecoilAnims()
|
void CharacterController::refreshHitRecoilAnims(CharacterState& idle)
|
||||||
{
|
{
|
||||||
bool recovery = mPtr.getClass().getCreatureStats(mPtr).getHitRecovery();
|
bool recovery = mPtr.getClass().getCreatureStats(mPtr).getHitRecovery();
|
||||||
bool knockdown = mPtr.getClass().getCreatureStats(mPtr).getKnockedDown();
|
bool knockdown = mPtr.getClass().getCreatureStats(mPtr).getKnockedDown();
|
||||||
|
@ -348,14 +348,16 @@ void CharacterController::refreshHitRecoilAnims()
|
||||||
mAnimation->play(mCurrentHit, Priority_Knockdown, MWRender::Animation::BlendMask_All, true, 1, "loop stop", "stop", 0.0f, 0);
|
mAnimation->play(mCurrentHit, Priority_Knockdown, MWRender::Animation::BlendMask_All, true, 1, "loop stop", "stop", 0.0f, 0);
|
||||||
}
|
}
|
||||||
if (mHitState != CharState_None)
|
if (mHitState != CharState_None)
|
||||||
mIdleState = CharState_None;
|
idle = CharState_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, bool force)
|
void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, CharacterState& idle, bool force)
|
||||||
{
|
{
|
||||||
if(force || jump != mJumpState)
|
if(force || jump != mJumpState)
|
||||||
{
|
{
|
||||||
mIdleState = CharState_None;
|
if (jump != JumpState_None)
|
||||||
|
idle = CharState_None;
|
||||||
|
|
||||||
bool startAtLoop = (jump == mJumpState);
|
bool startAtLoop = (jump == mJumpState);
|
||||||
mJumpState = jump;
|
mJumpState = jump;
|
||||||
|
|
||||||
|
@ -372,6 +374,11 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState
|
||||||
jumpmask = MWRender::Animation::BlendMask_LowerBody;
|
jumpmask = MWRender::Animation::BlendMask_LowerBody;
|
||||||
jumpAnimName = "jump";
|
jumpAnimName = "jump";
|
||||||
|
|
||||||
|
// Since we apply movement only for lower body, do not reset idle animations.
|
||||||
|
// For upper body there will be idle animation.
|
||||||
|
if (idle == CharState_None)
|
||||||
|
idle = CharState_Idle;
|
||||||
|
|
||||||
// For crossbow animations use 1h ones as fallback
|
// For crossbow animations use 1h ones as fallback
|
||||||
if (mWeaponType == WeapType_Crossbow)
|
if (mWeaponType == WeapType_Crossbow)
|
||||||
jumpAnimName += "1h";
|
jumpAnimName += "1h";
|
||||||
|
@ -406,20 +413,21 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, bool force)
|
void CharacterController::refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, CharacterState& idle, bool force)
|
||||||
{
|
{
|
||||||
if(force || movement != mMovementState)
|
std::string movementAnimName;
|
||||||
|
MWRender::Animation::BlendMask movemask;
|
||||||
|
const StateInfo *movestate;
|
||||||
|
if(force || movement != mMovementState || idle != mIdleState)
|
||||||
{
|
{
|
||||||
mMovementState = movement;
|
movemask = MWRender::Animation::BlendMask_All;
|
||||||
std::string movementAnimName;
|
movestate = std::find_if(sMovementList, sMovementListEnd, FindCharState(movement));
|
||||||
MWRender::Animation::BlendMask movemask = MWRender::Animation::BlendMask_All;
|
|
||||||
const StateInfo *movestate = std::find_if(sMovementList, sMovementListEnd, FindCharState(mMovementState));
|
|
||||||
if(movestate != sMovementListEnd)
|
if(movestate != sMovementListEnd)
|
||||||
{
|
{
|
||||||
movementAnimName = movestate->groupname;
|
movementAnimName = movestate->groupname;
|
||||||
if(weap != sWeaponTypeListEnd && movementAnimName.find("swim") == std::string::npos)
|
if(weap != sWeaponTypeListEnd && movementAnimName.find("swim") == std::string::npos)
|
||||||
{
|
{
|
||||||
if (mWeaponType == WeapType_Spell && (mMovementState == CharState_TurnLeft || mMovementState == CharState_TurnRight)) // Spellcasting stance turning is a special case
|
if (mWeaponType == WeapType_Spell && (movement == CharState_TurnLeft || movement == CharState_TurnRight)) // Spellcasting stance turning is a special case
|
||||||
movementAnimName = weap->shortgroup + movementAnimName;
|
movementAnimName = weap->shortgroup + movementAnimName;
|
||||||
else
|
else
|
||||||
movementAnimName += weap->shortgroup;
|
movementAnimName += weap->shortgroup;
|
||||||
|
@ -429,12 +437,24 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character
|
||||||
movemask = MWRender::Animation::BlendMask_LowerBody;
|
movemask = MWRender::Animation::BlendMask_LowerBody;
|
||||||
movementAnimName = movestate->groupname;
|
movementAnimName = movestate->groupname;
|
||||||
|
|
||||||
|
// Since we apply movement only for lower body, do not reset idle animations.
|
||||||
|
// For upper body there will be idle animation.
|
||||||
|
if (idle == CharState_None)
|
||||||
|
idle = CharState_Idle;
|
||||||
|
|
||||||
// For crossbow animations use 1h ones as fallback
|
// For crossbow animations use 1h ones as fallback
|
||||||
if (mWeaponType == WeapType_Crossbow)
|
if (mWeaponType == WeapType_Crossbow)
|
||||||
movementAnimName += "1h";
|
movementAnimName += "1h";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(force || movement != mMovementState)
|
||||||
|
{
|
||||||
|
mMovementState = movement;
|
||||||
|
if(movestate != sMovementListEnd)
|
||||||
|
{
|
||||||
if(!mAnimation->hasAnimation(movementAnimName))
|
if(!mAnimation->hasAnimation(movementAnimName))
|
||||||
{
|
{
|
||||||
std::string::size_type swimpos = movementAnimName.find("swim");
|
std::string::size_type swimpos = movementAnimName.find("swim");
|
||||||
|
@ -532,7 +552,15 @@ 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 || mIdleState == CharState_None || (!mAnimation->isPlaying(mCurrentIdle) && mAnimQueue.empty()))
|
// FIXME: if one of the below states is close to their last animation frame (i.e. will be disabled in the coming update),
|
||||||
|
// the idle animation should be displayed
|
||||||
|
if (((mUpperBodyState != UpperCharState_Nothing && mUpperBodyState != UpperCharState_WeapEquiped)
|
||||||
|
|| (mMovementState != CharState_None && !isTurning())
|
||||||
|
|| mHitState != CharState_None)
|
||||||
|
&& !mPtr.getClass().isBipedal(mPtr))
|
||||||
|
idle = CharState_None;
|
||||||
|
|
||||||
|
if(force || idle != mIdleState || (!mAnimation->isPlaying(mCurrentIdle) && mAnimQueue.empty()))
|
||||||
{
|
{
|
||||||
mIdleState = idle;
|
mIdleState = idle;
|
||||||
size_t numLoops = ~0ul;
|
size_t numLoops = ~0ul;
|
||||||
|
@ -591,24 +619,16 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mPtr.getClass().isActor())
|
if (mPtr.getClass().isActor())
|
||||||
refreshHitRecoilAnims();
|
refreshHitRecoilAnims(idle);
|
||||||
|
|
||||||
const WeaponInfo *weap = std::find_if(sWeaponTypeList, sWeaponTypeListEnd, FindWeaponType(mWeaponType));
|
const WeaponInfo *weap = std::find_if(sWeaponTypeList, sWeaponTypeListEnd, FindWeaponType(mWeaponType));
|
||||||
if (!mPtr.getClass().hasInventoryStore(mPtr))
|
if (!mPtr.getClass().hasInventoryStore(mPtr))
|
||||||
weap = sWeaponTypeListEnd;
|
weap = sWeaponTypeListEnd;
|
||||||
|
|
||||||
refreshJumpAnims(weap, jump, force);
|
refreshJumpAnims(weap, jump, idle, force);
|
||||||
refreshMovementAnims(weap, movement, force);
|
refreshMovementAnims(weap, movement, idle, force);
|
||||||
|
|
||||||
// idle handled last as it can depend on the other states
|
// idle handled last as it can depend on the other states
|
||||||
// FIXME: if one of the below states is close to their last animation frame (i.e. will be disabled in the coming update),
|
|
||||||
// the idle animation should be displayed
|
|
||||||
if (((mUpperBodyState != UpperCharState_Nothing && mUpperBodyState != UpperCharState_WeapEquiped)
|
|
||||||
|| (mMovementState != CharState_None && !isTurning())
|
|
||||||
|| mHitState != CharState_None)
|
|
||||||
&& !mPtr.getClass().isBipedal(mPtr))
|
|
||||||
idle = CharState_None;
|
|
||||||
|
|
||||||
refreshIdleAnims(weap, idle, force);
|
refreshIdleAnims(weap, idle, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1200,7 +1220,7 @@ bool CharacterController::updateCarriedLeftVisible(WeaponType weaptype) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterController::updateWeaponState()
|
bool CharacterController::updateWeaponState(CharacterState& idle)
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = mPtr.getClass();
|
const MWWorld::Class &cls = mPtr.getClass();
|
||||||
CreatureStats &stats = cls.getCreatureStats(mPtr);
|
CreatureStats &stats = cls.getCreatureStats(mPtr);
|
||||||
|
@ -1570,11 +1590,11 @@ bool CharacterController::updateWeaponState()
|
||||||
|
|
||||||
// We should reset player's idle animation in the first-person mode.
|
// We should reset player's idle animation in the first-person mode.
|
||||||
if (resetIdle && mPtr == player && MWBase::Environment::get().getWorld()->isFirstPerson())
|
if (resetIdle && mPtr == player && MWBase::Environment::get().getWorld()->isFirstPerson())
|
||||||
mIdleState = CharState_None;
|
idle = CharState_None;
|
||||||
|
|
||||||
// In other cases we should not break swim and sneak animations
|
// In other cases we should not break swim and sneak animations
|
||||||
if (resetIdle && mIdleState != CharState_IdleSneak && mIdleState != CharState_IdleSwim)
|
if (resetIdle && mIdleState != CharState_IdleSneak && mIdleState != CharState_IdleSwim)
|
||||||
mIdleState = CharState_None;
|
idle = CharState_None;
|
||||||
|
|
||||||
animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
|
animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
|
||||||
if(mUpperBodyState == UpperCharState_MinAttackToMaxAttack && !isKnockedDown())
|
if(mUpperBodyState == UpperCharState_MinAttackToMaxAttack && !isKnockedDown())
|
||||||
|
@ -2085,12 +2105,18 @@ void CharacterController::update(float duration)
|
||||||
: (sneak ? CharState_SneakBack
|
: (sneak ? CharState_SneakBack
|
||||||
: (isrunning ? CharState_RunBack : CharState_WalkBack)));
|
: (isrunning ? CharState_RunBack : CharState_WalkBack)));
|
||||||
}
|
}
|
||||||
else if(rot.z() != 0.0f && !sneak && !(mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson()))
|
else if(rot.z() != 0.0f)
|
||||||
{
|
{
|
||||||
if(rot.z() > rotationThreshold)
|
// It seems only bipedal actors use turning animations.
|
||||||
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
|
// Also do not use turning animations in the first-person view and when sneaking.
|
||||||
else if(rot.z() < -rotationThreshold)
|
bool isFirstPlayer = mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson();
|
||||||
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft;
|
if (!sneak && !isFirstPlayer && mPtr.getClass().isBipedal(mPtr))
|
||||||
|
{
|
||||||
|
if(rot.z() > rotationThreshold)
|
||||||
|
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
|
||||||
|
else if(rot.z() < -rotationThreshold)
|
||||||
|
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2108,16 +2134,21 @@ void CharacterController::update(float duration)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mTurnAnimationThreshold -= duration;
|
if (mPtr.getClass().isBipedal(mPtr))
|
||||||
if (movestate == CharState_TurnRight || movestate == CharState_TurnLeft ||
|
|
||||||
movestate == CharState_SwimTurnRight || movestate == CharState_SwimTurnLeft)
|
|
||||||
{
|
{
|
||||||
mTurnAnimationThreshold = 0.05f;
|
if (mTurnAnimationThreshold > 0)
|
||||||
}
|
mTurnAnimationThreshold -= duration;
|
||||||
else if (movestate == CharState_None && isTurning()
|
|
||||||
&& mTurnAnimationThreshold > 0)
|
if (movestate == CharState_TurnRight || movestate == CharState_TurnLeft ||
|
||||||
{
|
movestate == CharState_SwimTurnRight || movestate == CharState_SwimTurnLeft)
|
||||||
movestate = mMovementState;
|
{
|
||||||
|
mTurnAnimationThreshold = 0.05f;
|
||||||
|
}
|
||||||
|
else if (movestate == CharState_None && isTurning()
|
||||||
|
&& mTurnAnimationThreshold > 0)
|
||||||
|
{
|
||||||
|
movestate = mMovementState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2126,13 +2157,12 @@ void CharacterController::update(float duration)
|
||||||
|
|
||||||
if(mAnimQueue.empty() || inwater || sneak)
|
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)
|
if (inwater)
|
||||||
idlestate = CharState_IdleSwim;
|
idlestate = CharState_IdleSwim;
|
||||||
else if (sneak && !inJump)
|
else if (sneak && !inJump)
|
||||||
idlestate = CharState_IdleSneak;
|
idlestate = CharState_IdleSneak;
|
||||||
else if (movestate != CharState_None && !isTurning() && mWeaponType != WeapType_Spell)
|
else if (movestate != CharState_None && !isTurning())
|
||||||
idlestate = CharState_None;
|
idlestate = CharState_None;
|
||||||
else
|
else
|
||||||
idlestate = CharState_Idle;
|
idlestate = CharState_Idle;
|
||||||
|
@ -2144,7 +2174,7 @@ void CharacterController::update(float duration)
|
||||||
{
|
{
|
||||||
// bipedal means hand-to-hand could be used (which is handled in updateWeaponState). an existing InventoryStore means an actual weapon could be used.
|
// bipedal means hand-to-hand could be used (which is handled in updateWeaponState). an existing InventoryStore means an actual weapon could be used.
|
||||||
if(cls.isBipedal(mPtr) || cls.hasInventoryStore(mPtr))
|
if(cls.isBipedal(mPtr) || cls.hasInventoryStore(mPtr))
|
||||||
forcestateupdate = updateWeaponState() || forcestateupdate;
|
forcestateupdate = updateWeaponState(idlestate) || forcestateupdate;
|
||||||
else
|
else
|
||||||
forcestateupdate = updateCreatureState() || forcestateupdate;
|
forcestateupdate = updateCreatureState() || forcestateupdate;
|
||||||
|
|
||||||
|
|
|
@ -213,14 +213,14 @@ class CharacterController : public MWRender::Animation::TextKeyListener
|
||||||
void setAttackTypeBasedOnMovement();
|
void setAttackTypeBasedOnMovement();
|
||||||
|
|
||||||
void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false);
|
void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false);
|
||||||
void refreshHitRecoilAnims();
|
void refreshHitRecoilAnims(CharacterState& idle);
|
||||||
void refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, bool force=false);
|
void refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, CharacterState& idle, bool force=false);
|
||||||
void refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, bool force=false);
|
void refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, CharacterState& idle, bool force=false);
|
||||||
void refreshIdleAnims(const WeaponInfo* weap, CharacterState idle, bool force=false);
|
void refreshIdleAnims(const WeaponInfo* weap, CharacterState idle, bool force=false);
|
||||||
|
|
||||||
void clearAnimQueue(bool clearPersistAnims = false);
|
void clearAnimQueue(bool clearPersistAnims = false);
|
||||||
|
|
||||||
bool updateWeaponState();
|
bool updateWeaponState(CharacterState& idle);
|
||||||
bool updateCreatureState();
|
bool updateCreatureState();
|
||||||
void updateIdleStormState(bool inwater);
|
void updateIdleStormState(bool inwater);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue