@@ -231,12 +231,16 @@ void CClientPed::Init(CClientManager* pManager, unsigned long ulModelID, bool bI
231231 m_MovementStateNames[MOVEMENTSTATE_JOG] = " jog" ;
232232 m_MovementStateNames[MOVEMENTSTATE_SPRINT] = " sprint" ;
233233 m_MovementStateNames[MOVEMENTSTATE_CROUCH] = " crouch" ;
234- // These two are inactive for now
235234 m_MovementStateNames[MOVEMENTSTATE_CRAWL] = " crawl" ;
236235 m_MovementStateNames[MOVEMENTSTATE_ROLL] = " roll" ;
237236 m_MovementStateNames[MOVEMENTSTATE_JUMP] = " jump" ;
238237 m_MovementStateNames[MOVEMENTSTATE_FALL] = " fall" ;
239238 m_MovementStateNames[MOVEMENTSTATE_CLIMB] = " climb" ;
239+ m_MovementStateNames[MOVEMENTSTATE_SWIM] = " swim" ;
240+ m_MovementStateNames[MOVEMENTSTATE_WALK_TO_POINT] = " walk_to_point" ;
241+ m_MovementStateNames[MOVEMENTSTATE_ASCENT_JETPACK] = " ascent_jetpack" ;
242+ m_MovementStateNames[MOVEMENTSTATE_DESCENT_JETPACK] = " descent_jetpack" ;
243+ m_MovementStateNames[MOVEMENTSTATE_JETPACK] = " jetpack_flying" ;
240244
241245 // Create the player model
242246 if (m_bIsLocalPlayer)
@@ -2420,53 +2424,63 @@ eMovementState CClientPed::GetMovementState()
24202424 const char * szComplexTaskName = GetTaskManager ()->GetActiveTask ()->GetTaskName ();
24212425 const char * szSimpleTaskName = GetTaskManager ()->GetSimplestActiveTask ()->GetTaskName ();
24222426
2423- // Is he climbing?
2424- if (strcmp (szSimpleTaskName, " TASK_SIMPLE_CLIMB" ) == 0 )
2427+ // Check tasks
2428+ if (strcmp (szSimpleTaskName, " TASK_SIMPLE_CLIMB" ) == 0 ) // Is he climbing?
24252429 return MOVEMENTSTATE_CLIMB;
2426-
2427- // Is he jumping?
2428- else if (strcmp (szComplexTaskName, " TASK_COMPLEX_JUMP" ) == 0 )
2430+ else if (strcmp (szComplexTaskName, " TASK_COMPLEX_JUMP" ) == 0 ) // Is he jumping?
24292431 return MOVEMENTSTATE_JUMP;
2432+ else if (strcmp (szSimpleTaskName, " TASK_SIMPLE_GO_TO_POINT" ) == 0 ) // Entering vehicle (walking to the doors)?
2433+ return MOVEMENTSTATE_WALK_TO_POINT;
2434+ else if (strcmp (szSimpleTaskName, " TASK_SIMPLE_SWIM" ) == 0 ) // Is he swimming?
2435+ return MOVEMENTSTATE_SWIM;
2436+ else if (strcmp (szSimpleTaskName, " TASK_SIMPLE_JETPACK" ) == 0 ) // Is he flying?
2437+ {
2438+ if (cs.ButtonCross != 0 )
2439+ return MOVEMENTSTATE_ASCENT_JETPACK;
2440+ else if (cs.ButtonSquare != 0 )
2441+ return MOVEMENTSTATE_DESCENT_JETPACK;
2442+ else
2443+ return MOVEMENTSTATE_JETPACK;
2444+ }
24302445
2431- // Is he falling?
2432- else if (!IsOnGround () && !GetContactEntity ())
2446+ // Check movement state
2447+ if (!IsOnGround () && !GetContactEntity () && !m_pPlayerPed-> IsStandingOnEntity () && !m_pPlayerPed-> IsInWater () && ( strcmp (szSimpleTaskName, " TASK_SIMPLE_IN_AIR " ) == 0 || strcmp (szSimpleTaskName, " TASK_SIMPLE_FALL " ) == 0 )) // Is he falling?
24332448 return MOVEMENTSTATE_FALL;
24342449
2435- // Grab his controller state
2436- bool bWalkKey = false ;
2437- if (GetType () == CCLIENTPLAYER)
2438- bWalkKey = CClientPad::GetControlState (" walk" , cs, true );
2439- else
2440- m_Pad.GetControlState (" walk" , bWalkKey);
2450+ // Sometimes it returns 'fall' or 'walk', so it's better to return false instead
2451+ if (IsEnteringVehicle () || IsLeavingVehicle ())
2452+ return MOVEMENTSTATE_UNKNOWN;
24412453
2442- // Is he standing up?
24432454 if (!IsDucked ())
24442455 {
2445- unsigned int iRunState = m_pPlayerPed->GetRunState ();
2456+ bool walking = false ;
2457+ if (GetType () == CCLIENTPLAYER)
2458+ walking = CClientPad::GetControlState (" walk" , cs, true );
2459+ else
2460+ m_Pad.GetControlState (" walk" , walking);
24462461
2447- // Is he moving the contoller at all?
2448- if (iRunState == 1 && cs.LeftStickX == 0 && cs.LeftStickY == 0 )
2449- return MOVEMENTSTATE_STAND;
2450-
2451- // Is he either pressing the walk key, or has run state 1?
2452- if (iRunState == 1 || bWalkKey && iRunState == 6 )
2453- return MOVEMENTSTATE_WALK;
2454- else if (iRunState == 4 )
2455- return MOVEMENTSTATE_POWERWALK;
2456- else if (iRunState == 6 )
2457- return MOVEMENTSTATE_JOG;
2458- else if (iRunState == 7 )
2459- return MOVEMENTSTATE_SPRINT;
2462+ switch (m_pPlayerPed->GetMoveState ())
2463+ {
2464+ case PedMoveState::PEDMOVE_STILL:
2465+ return MOVEMENTSTATE_STAND;
2466+ case PedMoveState::PEDMOVE_WALK:
2467+ return (cs.LeftStickX == 0 && cs.LeftStickY == 0 ) ? MOVEMENTSTATE_STAND : MOVEMENTSTATE_WALK;
2468+ case PedMoveState::PEDMOVE_SPRINT:
2469+ return MOVEMENTSTATE_SPRINT;
2470+ case PedMoveState::PEDMOVE_RUN:
2471+ return walking ? MOVEMENTSTATE_WALK : MOVEMENTSTATE_JOG; // FileEX: It should be MOVEMENTSTATE_RUN, but we're keeping JOG for backward compatibility (PEDMOVE_JOG is unused in SA)
2472+ }
24602473 }
24612474 else
24622475 {
24632476 // Is he moving the contoller at all?
24642477 if (cs.LeftStickX == 0 && cs.LeftStickY == 0 )
24652478 return MOVEMENTSTATE_CROUCH;
24662479 else
2467- return MOVEMENTSTATE_CRAWL;
2480+ return (cs. LeftStickX != 0 && cs. RightShoulder1 != 0 ) ? MOVEMENTSTATE_ROLL : MOVEMENTSTATE_CRAWL;
24682481 }
24692482 }
2483+
24702484 return MOVEMENTSTATE_UNKNOWN;
24712485}
24722486
@@ -2893,6 +2907,11 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses)
28932907 }
28942908 }
28952909
2910+ // Are we need to update anim speed & progress?
2911+ // We need to do it here because the anim starts on the next frame after calling RunNamedAnimation
2912+ if (m_pAnimationBlock && m_AnimationCache.progressWaitForStreamIn && IsAnimationInProgress ())
2913+ UpdateAnimationProgressAndSpeed ();
2914+
28962915 // Update our alpha
28972916 unsigned char ucAlpha = m_ucAlpha;
28982917 // Are we in a different interior to the camera? set our alpha to 0
@@ -3683,8 +3702,8 @@ void CClientPed::_CreateModel()
36833702 Kill (WEAPONTYPE_UNARMED, 0 , false , true );
36843703 }
36853704
3686- // Are we still playing animation?
3687- if ((m_AnimationCache. bLoop || m_AnimationCache. bFreezeLastFrame || m_AnimationCache. progressWaitForStreamIn ) && m_pAnimationBlock )
3705+ // Are we still playing a animation?
3706+ if (m_pAnimationBlock && IsAnimationInProgress () )
36883707 {
36893708 if (m_bisCurrentAnimationCustom)
36903709 {
@@ -3961,8 +3980,8 @@ void CClientPed::_ChangeModel()
39613980 }
39623981 m_bDontChangeRadio = false ;
39633982
3964- // Are we still playing a looped animation?
3965- if ((m_AnimationCache. bLoop || m_AnimationCache. bFreezeLastFrame || m_AnimationCache. progressWaitForStreamIn ) && m_pAnimationBlock )
3983+ // Are we still playing a animation?
3984+ if (m_pAnimationBlock && IsAnimationInProgress () )
39663985 {
39673986 if (m_bisCurrentAnimationCustom)
39683987 {
@@ -5729,7 +5748,23 @@ bool CClientPed::IsRunningAnimation()
57295748 }
57305749 return false ;
57315750 }
5732- return (m_AnimationCache.bLoop && m_pAnimationBlock);
5751+ return (m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame ) && m_pAnimationBlock;
5752+ }
5753+
5754+ bool CClientPed::IsAnimationInProgress ()
5755+ {
5756+ bool constAnim = m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame ;
5757+
5758+ if (!m_pAnimationBlock)
5759+ return constAnim;
5760+
5761+ float elapsedTime = static_cast <float >(GetTimestamp () - m_AnimationCache.startTime ) / 1000 .0f ;
5762+
5763+ auto animBlendHierarchy = g_pGame->GetAnimManager ()->GetAnimation (m_AnimationCache.strName .c_str (), m_pAnimationBlock);
5764+ if (!animBlendHierarchy)
5765+ return constAnim;
5766+
5767+ return constAnim || elapsedTime < animBlendHierarchy->GetTotalTime ();
57335768}
57345769
57355770void CClientPed::RunNamedAnimation (std::unique_ptr<CAnimBlock>& pBlock, const char * szAnimName, int iTime, int iBlend, bool bLoop, bool bUpdatePosition,
@@ -5817,10 +5852,6 @@ void CClientPed::RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const ch
58175852 m_AnimationCache.bUpdatePosition = bUpdatePosition;
58185853 m_AnimationCache.bInterruptable = bInterruptable;
58195854 m_AnimationCache.bFreezeLastFrame = bFreezeLastFrame;
5820- m_AnimationCache.progress = 0 .0f ;
5821- m_AnimationCache.speed = 1 .0f ;
5822- m_AnimationCache.progressWaitForStreamIn = false ;
5823- m_AnimationCache.elapsedTime = 0 .0f ;
58245855}
58255856
58265857void CClientPed::KillAnimation ()
@@ -5859,39 +5890,45 @@ void CClientPed::RunAnimationFromCache()
58595890 if (!m_pAnimationBlock)
58605891 return ;
58615892
5862- bool needCalcProgress = m_AnimationCache.progressWaitForStreamIn ;
5863- float elapsedTime = m_AnimationCache.elapsedTime ;
5864-
58655893 // Copy our name incase it gets deleted
58665894 std::string animName = m_AnimationCache.strName ;
58675895
58685896 // Run our animation
58695897 RunNamedAnimation (m_pAnimationBlock, animName.c_str (), m_AnimationCache.iTime , m_AnimationCache.iBlend , m_AnimationCache.bLoop , m_AnimationCache.bUpdatePosition , m_AnimationCache.bInterruptable , m_AnimationCache.bFreezeLastFrame );
58705898
5871- auto animAssoc = g_pGame->GetAnimManager ()->RpAnimBlendClumpGetAssociation (GetClump (), animName.c_str ());
5899+ // Set anim progress & speed
5900+ m_AnimationCache.progressWaitForStreamIn = true ;
5901+ }
5902+
5903+ void CClientPed::UpdateAnimationProgressAndSpeed ()
5904+ {
5905+ if (!m_AnimationCache.progressWaitForStreamIn )
5906+ return ;
5907+
5908+ // Get current anim
5909+ auto animAssoc = g_pGame->GetAnimManager ()->RpAnimBlendClumpGetAssociation (GetClump (), m_AnimationCache.strName .c_str ());
58725910 if (!animAssoc)
58735911 return ;
58745912
5875- // If the anim is synced from the server side, we need to calculate the progress
5876- float progress = m_AnimationCache.progress ;
5877- if (needCalcProgress)
5878- {
5879- float animLength = animAssoc->GetLength ();
5913+ float animLength = animAssoc->GetLength ();
5914+ float progress = 0 .0f ;
5915+ float elapsedTime = static_cast <float >(GetTimestamp () - m_AnimationCache.startTime ) / 1000 .0f ;
58805916
5881- if (m_AnimationCache.bFreezeLastFrame ) // time and loop is ignored if freezeLastFrame is true
5882- progress = (elapsedTime / animLength) * m_AnimationCache.speed ;
5917+ if (m_AnimationCache.bFreezeLastFrame ) // time and loop is ignored if freezeLastFrame is true
5918+ progress = (elapsedTime / animLength) * m_AnimationCache.speed ;
5919+ else
5920+ {
5921+ if (m_AnimationCache.bLoop )
5922+ progress = std::fmod (elapsedTime * m_AnimationCache.speed , animLength) / animLength;
58835923 else
5884- {
5885- if (m_AnimationCache.bLoop )
5886- progress = std::fmod (elapsedTime * m_AnimationCache.speed , animLength) / animLength;
5887- else
5888- // For non-looped animations, limit duration to animLength if time exceeds it
5889- progress = (elapsedTime / (m_AnimationCache.iTime <= animLength ? m_AnimationCache.iTime : animLength)) * m_AnimationCache.speed ;
5890- }
5924+ // For non-looped animations, limit duration to animLength if time exceeds it
5925+ progress = (elapsedTime / (m_AnimationCache.iTime <= animLength ? m_AnimationCache.iTime : animLength)) * m_AnimationCache.speed ;
58915926 }
58925927
58935928 animAssoc->SetCurrentProgress (std::clamp (progress, 0 .0f , 1 .0f ));
58945929 animAssoc->SetCurrentSpeed (m_AnimationCache.speed );
5930+
5931+ m_AnimationCache.progressWaitForStreamIn = false ;
58955932}
58965933
58975934void CClientPed::PostWeaponFire ()
@@ -6096,7 +6133,7 @@ bool CClientPed::ShouldBeStealthAiming()
60966133 {
60976134 // We need to be either crouched, walking or standing
60986135 SBindableGTAControl* pWalkControl = pKeyBinds->GetBindableFromControl (" walk" );
6099- if (m_pPlayerPed->GetRunState () == 1 || m_pPlayerPed->GetRunState () == 4 || pWalkControl && pWalkControl->bState )
6136+ if (m_pPlayerPed->GetMoveState () == PedMoveState::PEDMOVE_STILL || m_pPlayerPed->GetMoveState () == PedMoveState::PEDMOVE_WALK || pWalkControl && pWalkControl->bState )
61006137 {
61016138 // Do we have a target ped?
61026139 CClientPed* pTargetPed = GetTargetedPed ();
0 commit comments