@@ -231,17 +231,12 @@ 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
234235 m_MovementStateNames[MOVEMENTSTATE_CRAWL] = " crawl" ;
235236 m_MovementStateNames[MOVEMENTSTATE_ROLL] = " roll" ;
236237 m_MovementStateNames[MOVEMENTSTATE_JUMP] = " jump" ;
237238 m_MovementStateNames[MOVEMENTSTATE_FALL] = " fall" ;
238239 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" ;
244- m_MovementStateNames[MOVEMENTSTATE_HANGING] = " hanging" ;
245240
246241 // Create the player model
247242 if (m_bIsLocalPlayer)
@@ -1718,12 +1713,14 @@ void CClientPed::SetUsesCollision(bool bUsesCollision)
17181713
17191714float CClientPed::GetMaxHealth ()
17201715{
1716+ // TODO: Verify this formula
1717+
17211718 // Grab his player health stat
17221719 float fStat = GetStat (MAX_HEALTH);
17231720
17241721 // Do a linear interpolation to get how much health this would allow
1725- // Assumes: 100 health = 569 stat, 176 health = 1000 stat.
1726- float fMaxHealth = fStat * 0 . 176f ;
1722+ // Assumes: 100 health = 569 stat, 200 health = 1000 stat.
1723+ float fMaxHealth = 100 . 0f + ( 100 . 0f / 431 . 0f * ( fStat - 569 . 0f )) ;
17271724
17281725 // Return the max health. Make sure it can't be below 1
17291726 if (fMaxHealth < 1 .0f )
@@ -2425,69 +2422,53 @@ eMovementState CClientPed::GetMovementState()
24252422 const char * szComplexTaskName = GetTaskManager ()->GetActiveTask ()->GetTaskName ();
24262423 const char * szSimpleTaskName = GetTaskManager ()->GetSimplestActiveTask ()->GetTaskName ();
24272424
2428- // Check tasks
2429- if (strcmp (szSimpleTaskName, " TASK_SIMPLE_CLIMB" ) == 0 ) // Is he climbing?
2430- {
2431- CTaskSimpleClimb* climbingTask = dynamic_cast <CTaskSimpleClimb*>(GetTaskManager ()->GetSimplestActiveTask ());
2432- if (climbingTask && climbingTask->GetHeightForPos () == eClimbHeights::CLIMB_GRAB)
2433- return MOVEMENTSTATE_HANGING;
2434-
2425+ // Is he climbing?
2426+ if (strcmp (szSimpleTaskName, " TASK_SIMPLE_CLIMB" ) == 0 )
24352427 return MOVEMENTSTATE_CLIMB;
2436- }
2437- else if (strcmp (szComplexTaskName, " TASK_COMPLEX_JUMP" ) == 0 ) // Is he jumping?
2428+
2429+ // Is he jumping?
2430+ else if (strcmp (szComplexTaskName, " TASK_COMPLEX_JUMP" ) == 0 )
24382431 return MOVEMENTSTATE_JUMP;
2439- else if (strcmp (szSimpleTaskName, " TASK_SIMPLE_GO_TO_POINT" ) == 0 ) // Entering vehicle (walking to the doors)?
2440- return MOVEMENTSTATE_WALK_TO_POINT;
2441- else if (strcmp (szSimpleTaskName, " TASK_SIMPLE_SWIM" ) == 0 ) // Is he swimming?
2442- return MOVEMENTSTATE_SWIM;
2443- else if (strcmp (szSimpleTaskName, " TASK_SIMPLE_JETPACK" ) == 0 ) // Is he flying?
2444- {
2445- if (cs.ButtonCross != 0 )
2446- return MOVEMENTSTATE_ASCENT_JETPACK;
2447- else if (cs.ButtonSquare != 0 )
2448- return MOVEMENTSTATE_DESCENT_JETPACK;
2449- else
2450- return MOVEMENTSTATE_JETPACK;
2451- }
24522432
2453- // Check movement state
2454- 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?
2433+ // Is he falling?
2434+ else if (!IsOnGround () && !GetContactEntity ())
24552435 return MOVEMENTSTATE_FALL;
24562436
2457- // Sometimes it returns 'fall' or 'walk', so it's better to return false instead
2458- if (IsEnteringVehicle () || IsLeavingVehicle ())
2459- return MOVEMENTSTATE_UNKNOWN;
2437+ // Grab his controller state
2438+ bool bWalkKey = false ;
2439+ if (GetType () == CCLIENTPLAYER)
2440+ bWalkKey = CClientPad::GetControlState (" walk" , cs, true );
2441+ else
2442+ m_Pad.GetControlState (" walk" , bWalkKey);
24602443
2444+ // Is he standing up?
24612445 if (!IsDucked ())
24622446 {
2463- bool walking = false ;
2464- if (GetType () == CCLIENTPLAYER)
2465- walking = CClientPad::GetControlState (" walk" , cs, true );
2466- else
2467- m_Pad.GetControlState (" walk" , walking);
2447+ unsigned int iRunState = m_pPlayerPed->GetRunState ();
24682448
2469- switch (m_pPlayerPed->GetMoveState ())
2470- {
2471- case PedMoveState::PEDMOVE_STILL:
2472- return MOVEMENTSTATE_STAND;
2473- case PedMoveState::PEDMOVE_WALK:
2474- return (cs.LeftStickX == 0 && cs.LeftStickY == 0 ) ? MOVEMENTSTATE_STAND : MOVEMENTSTATE_WALK;
2475- case PedMoveState::PEDMOVE_SPRINT:
2476- return MOVEMENTSTATE_SPRINT;
2477- case PedMoveState::PEDMOVE_RUN:
2478- 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)
2479- }
2449+ // Is he moving the contoller at all?
2450+ if (iRunState == 1 && cs.LeftStickX == 0 && cs.LeftStickY == 0 )
2451+ return MOVEMENTSTATE_STAND;
2452+
2453+ // Is he either pressing the walk key, or has run state 1?
2454+ if (iRunState == 1 || bWalkKey && iRunState == 6 )
2455+ return MOVEMENTSTATE_WALK;
2456+ else if (iRunState == 4 )
2457+ return MOVEMENTSTATE_POWERWALK;
2458+ else if (iRunState == 6 )
2459+ return MOVEMENTSTATE_JOG;
2460+ else if (iRunState == 7 )
2461+ return MOVEMENTSTATE_SPRINT;
24802462 }
24812463 else
24822464 {
24832465 // Is he moving the contoller at all?
24842466 if (cs.LeftStickX == 0 && cs.LeftStickY == 0 )
24852467 return MOVEMENTSTATE_CROUCH;
24862468 else
2487- return (cs. LeftStickX != 0 && cs. RightShoulder1 != 0 ) ? MOVEMENTSTATE_ROLL : MOVEMENTSTATE_CRAWL;
2469+ return MOVEMENTSTATE_CRAWL;
24882470 }
24892471 }
2490-
24912472 return MOVEMENTSTATE_UNKNOWN;
24922473}
24932474
@@ -2914,11 +2895,6 @@ void CClientPed::StreamedInPulse(bool bDoStandardPulses)
29142895 }
29152896 }
29162897
2917- // Are we need to update anim speed & progress?
2918- // We need to do it here because the anim starts on the next frame after calling RunNamedAnimation
2919- if (m_pAnimationBlock && m_AnimationCache.progressWaitForStreamIn && IsAnimationInProgress ())
2920- UpdateAnimationProgressAndSpeed ();
2921-
29222898 // Update our alpha
29232899 unsigned char ucAlpha = m_ucAlpha;
29242900 // Are we in a different interior to the camera? set our alpha to 0
@@ -3709,8 +3685,8 @@ void CClientPed::_CreateModel()
37093685 Kill (WEAPONTYPE_UNARMED, 0 , false , true );
37103686 }
37113687
3712- // Are we still playing a animation?
3713- if (m_pAnimationBlock && IsAnimationInProgress () )
3688+ // Are we still playing animation?
3689+ if ((m_AnimationCache. bLoop || m_AnimationCache. bFreezeLastFrame || m_AnimationCache. progressWaitForStreamIn ) && m_pAnimationBlock )
37143690 {
37153691 if (m_bisCurrentAnimationCustom)
37163692 {
@@ -3987,8 +3963,8 @@ void CClientPed::_ChangeModel()
39873963 }
39883964 m_bDontChangeRadio = false ;
39893965
3990- // Are we still playing a animation?
3991- if (m_pAnimationBlock && IsAnimationInProgress () )
3966+ // Are we still playing a looped animation?
3967+ if ((m_AnimationCache. bLoop || m_AnimationCache. bFreezeLastFrame || m_AnimationCache. progressWaitForStreamIn ) && m_pAnimationBlock )
39923968 {
39933969 if (m_bisCurrentAnimationCustom)
39943970 {
@@ -5760,23 +5736,7 @@ bool CClientPed::IsRunningAnimation()
57605736 }
57615737 return false ;
57625738 }
5763- return (m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame ) && m_pAnimationBlock;
5764- }
5765-
5766- bool CClientPed::IsAnimationInProgress ()
5767- {
5768- bool constAnim = m_AnimationCache.bLoop || m_AnimationCache.bFreezeLastFrame ;
5769-
5770- if (!m_pAnimationBlock)
5771- return constAnim;
5772-
5773- float elapsedTime = static_cast <float >(GetTimestamp () - m_AnimationCache.startTime ) / 1000 .0f ;
5774-
5775- auto animBlendHierarchy = g_pGame->GetAnimManager ()->GetAnimation (m_AnimationCache.strName .c_str (), m_pAnimationBlock);
5776- if (!animBlendHierarchy)
5777- return constAnim;
5778-
5779- return constAnim || elapsedTime < animBlendHierarchy->GetTotalTime ();
5739+ return (m_AnimationCache.bLoop && m_pAnimationBlock);
57805740}
57815741
57825742void CClientPed::RunNamedAnimation (std::unique_ptr<CAnimBlock>& pBlock, const char * szAnimName, int iTime, int iBlend, bool bLoop, bool bUpdatePosition,
@@ -5864,6 +5824,10 @@ void CClientPed::RunNamedAnimation(std::unique_ptr<CAnimBlock>& pBlock, const ch
58645824 m_AnimationCache.bUpdatePosition = bUpdatePosition;
58655825 m_AnimationCache.bInterruptable = bInterruptable;
58665826 m_AnimationCache.bFreezeLastFrame = bFreezeLastFrame;
5827+ m_AnimationCache.progress = 0 .0f ;
5828+ m_AnimationCache.speed = 1 .0f ;
5829+ m_AnimationCache.progressWaitForStreamIn = false ;
5830+ m_AnimationCache.elapsedTime = 0 .0f ;
58675831}
58685832
58695833void CClientPed::KillAnimation ()
@@ -5902,45 +5866,39 @@ void CClientPed::RunAnimationFromCache()
59025866 if (!m_pAnimationBlock)
59035867 return ;
59045868
5869+ bool needCalcProgress = m_AnimationCache.progressWaitForStreamIn ;
5870+ float elapsedTime = m_AnimationCache.elapsedTime ;
5871+
59055872 // Copy our name incase it gets deleted
59065873 std::string animName = m_AnimationCache.strName ;
59075874
59085875 // Run our animation
59095876 RunNamedAnimation (m_pAnimationBlock, animName.c_str (), m_AnimationCache.iTime , m_AnimationCache.iBlend , m_AnimationCache.bLoop , m_AnimationCache.bUpdatePosition , m_AnimationCache.bInterruptable , m_AnimationCache.bFreezeLastFrame );
59105877
5911- // Set anim progress & speed
5912- m_AnimationCache.progressWaitForStreamIn = true ;
5913- }
5914-
5915- void CClientPed::UpdateAnimationProgressAndSpeed ()
5916- {
5917- if (!m_AnimationCache.progressWaitForStreamIn )
5918- return ;
5919-
5920- // Get current anim
5921- auto animAssoc = g_pGame->GetAnimManager ()->RpAnimBlendClumpGetAssociation (GetClump (), m_AnimationCache.strName .c_str ());
5878+ auto animAssoc = g_pGame->GetAnimManager ()->RpAnimBlendClumpGetAssociation (GetClump (), animName.c_str ());
59225879 if (!animAssoc)
59235880 return ;
59245881
5925- float animLength = animAssoc->GetLength ();
5926- float progress = 0 .0f ;
5927- float elapsedTime = static_cast <float >(GetTimestamp () - m_AnimationCache.startTime ) / 1000 .0f ;
5928-
5929- if (m_AnimationCache.bFreezeLastFrame ) // time and loop is ignored if freezeLastFrame is true
5930- progress = (elapsedTime / animLength) * m_AnimationCache.speed ;
5931- else
5882+ // If the anim is synced from the server side, we need to calculate the progress
5883+ float progress = m_AnimationCache.progress ;
5884+ if (needCalcProgress)
59325885 {
5933- if (m_AnimationCache.bLoop )
5934- progress = std::fmod (elapsedTime * m_AnimationCache.speed , animLength) / animLength;
5886+ float animLength = animAssoc->GetLength ();
5887+
5888+ if (m_AnimationCache.bFreezeLastFrame ) // time and loop is ignored if freezeLastFrame is true
5889+ progress = (elapsedTime / animLength) * m_AnimationCache.speed ;
59355890 else
5936- // For non-looped animations, limit duration to animLength if time exceeds it
5937- progress = (elapsedTime / (m_AnimationCache.iTime <= animLength ? m_AnimationCache.iTime : animLength)) * m_AnimationCache.speed ;
5891+ {
5892+ if (m_AnimationCache.bLoop )
5893+ progress = std::fmod (elapsedTime * m_AnimationCache.speed , animLength) / animLength;
5894+ else
5895+ // For non-looped animations, limit duration to animLength if time exceeds it
5896+ progress = (elapsedTime / (m_AnimationCache.iTime <= animLength ? m_AnimationCache.iTime : animLength)) * m_AnimationCache.speed ;
5897+ }
59385898 }
59395899
59405900 animAssoc->SetCurrentProgress (std::clamp (progress, 0 .0f , 1 .0f ));
59415901 animAssoc->SetCurrentSpeed (m_AnimationCache.speed );
5942-
5943- m_AnimationCache.progressWaitForStreamIn = false ;
59445902}
59455903
59465904void CClientPed::PostWeaponFire ()
@@ -6145,7 +6103,7 @@ bool CClientPed::ShouldBeStealthAiming()
61456103 {
61466104 // We need to be either crouched, walking or standing
61476105 SBindableGTAControl* pWalkControl = pKeyBinds->GetBindableFromControl (" walk" );
6148- if (m_pPlayerPed->GetMoveState () == PedMoveState::PEDMOVE_STILL || m_pPlayerPed->GetMoveState () == PedMoveState::PEDMOVE_WALK || pWalkControl && pWalkControl->bState )
6106+ if (m_pPlayerPed->GetRunState () == 1 || m_pPlayerPed->GetRunState () == 4 || pWalkControl && pWalkControl->bState )
61496107 {
61506108 // Do we have a target ped?
61516109 CClientPed* pTargetPed = GetTargetedPed ();
@@ -6524,6 +6482,12 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger)
65246482 return false ;
65256483 }
65266484
6485+ // Check the server is compatible if we are a ped
6486+ if (!IsLocalPlayer () && !g_pNet->CanServerBitStream (eBitStreamVersion::PedEnterExit))
6487+ {
6488+ return false ;
6489+ }
6490+
65276491 // Are we already inside a vehicle
65286492 if (GetOccupiedVehicle ())
65296493 {
@@ -6692,7 +6656,11 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger)
66926656 return false ;
66936657 }
66946658
6695- pBitStream->Write (GetID ());
6659+ // Write the ped ID to it if server supports it
6660+ if (g_pNet->CanServerBitStream (eBitStreamVersion::PedEnterExit))
6661+ {
6662+ pBitStream->Write (GetID ());
6663+ }
66966664
66976665 // Write the vehicle id to it and that we're requesting to get into it
66986666 pBitStream->Write (pVehicle->GetID ());
@@ -6755,6 +6723,12 @@ bool CClientPed::ExitVehicle()
67556723 return false ;
67566724 }
67576725
6726+ // Check the server is compatible if we are a ped
6727+ if (!IsLocalPlayer () && !g_pNet->CanServerBitStream (eBitStreamVersion::PedEnterExit))
6728+ {
6729+ return false ;
6730+ }
6731+
67586732 // Are we already sending an in/out request or not allowed to create a new in/out?
67596733 if (m_bNoNewVehicleTask // Are we permitted to even enter a vehicle?
67606734 || m_VehicleInOutID != INVALID_ELEMENT_ID // Make sure we're not already processing a vehicle enter (would refer to valid ID if we were)
@@ -6815,7 +6789,11 @@ bool CClientPed::ExitVehicle()
68156789 return false ;
68166790 }
68176791
6818- pBitStream->Write (GetID ());
6792+ // Write the ped ID to it if server supports it
6793+ if (g_pNet->CanServerBitStream (eBitStreamVersion::PedEnterExit))
6794+ {
6795+ pBitStream->Write (GetID ());
6796+ }
68196797
68206798 // Write the vehicle id to it and that we're requesting to get out of it
68216799 pBitStream->Write (pOccupiedVehicle->GetID ());
@@ -6943,7 +6921,10 @@ void CClientPed::UpdateVehicleInOut()
69436921 if (pBitStream)
69446922 {
69456923 // Write the ped ID to it
6946- pBitStream->Write (GetID ());
6924+ if (g_pNet->CanServerBitStream (eBitStreamVersion::PedEnterExit))
6925+ {
6926+ pBitStream->Write (GetID ());
6927+ }
69476928
69486929 // Write the car id and the action id (enter complete)
69496930 pBitStream->Write (m_VehicleInOutID);
@@ -6993,7 +6974,10 @@ void CClientPed::UpdateVehicleInOut()
69936974 if (pBitStream)
69946975 {
69956976 // Write the ped or player ID to it
6996- pBitStream->Write (GetID ());
6977+ if (g_pNet->CanServerBitStream (eBitStreamVersion::PedEnterExit))
6978+ {
6979+ pBitStream->Write (GetID ());
6980+ }
69976981
69986982 // Write the car id and the action id (enter complete)
69996983 pBitStream->Write (m_VehicleInOutID);
@@ -7037,7 +7021,10 @@ void CClientPed::UpdateVehicleInOut()
70377021 if (pBitStream)
70387022 {
70397023 // Write the ped or player ID to it
7040- pBitStream->Write (GetID ());
7024+ if (g_pNet->CanServerBitStream (eBitStreamVersion::PedEnterExit))
7025+ {
7026+ pBitStream->Write (GetID ());
7027+ }
70417028
70427029 // Write the car id and the action id (enter complete)
70437030 pBitStream->Write (m_VehicleInOutID);
@@ -7149,7 +7136,10 @@ void CClientPed::UpdateVehicleInOut()
71497136 return ;
71507137
71517138 // Write the ped or player ID to it
7152- pBitStream->Write (GetID ());
7139+ if (g_pNet->CanServerBitStream (eBitStreamVersion::PedEnterExit))
7140+ {
7141+ pBitStream->Write (GetID ());
7142+ }
71537143
71547144 // Vehicle id
71557145 pBitStream->Write (pOccupiedVehicle->GetID ());
0 commit comments