diff --git a/game/client/c_baseanimating.cpp b/game/client/c_baseanimating.cpp index f1a1007acc..dd00fc8d5a 100644 --- a/game/client/c_baseanimating.cpp +++ b/game/client/c_baseanimating.cpp @@ -7,6 +7,7 @@ #include "cbase.h" #include "c_baseanimating.h" #include "c_sprite.h" +#include "cdll_client_int.h" #include "model_types.h" #include "bone_setup.h" #include "ivrenderview.h" @@ -898,6 +899,52 @@ void C_BaseAnimating::RemoveBaseAnimatingInterpolatedVars() } } +void C_BaseAnimating::StudioFrameAdvanceInternal( CStudioHdr *pStudioHdr, float flCycleDelta ) +{ + float flNewCycle = GetCycle() + flCycleDelta; + if (flNewCycle < 0.0 || flNewCycle >= 1.0) + { + if (m_bSequenceLoops) + { + flNewCycle -= (int)(flNewCycle); + } + else + { + flNewCycle = (flNewCycle < 0.0f) ? 0.0f : 1.0f; + } + m_bSequenceFinished = true; // just in case it wasn't caught in GetEvents + } + else if (flNewCycle > GetLastVisibleCycle( pStudioHdr, GetSequence() )) + { + m_bSequenceFinished = true; + } + + SetCycle( flNewCycle ); + + /* + if (!IsPlayer()) + Msg("%s %6.3f : %6.3f %6.3f (%.3f) %.3f\n", + GetClassname(), gpGlobals->curtime, + m_flAnimTime.Get(), m_flPrevAnimTime, flInterval, GetCycle() ); + */ + + m_flGroundSpeed = GetSequenceGroundSpeed( pStudioHdr, GetSequence() ) * GetModelScale(); + + // Msg("%s : %s : %5.1f\n", GetClassname(), GetSequenceName( GetSequence() ), GetCycle() ); + InvalidatePhysicsRecursive( ANIMATION_CHANGED ); + + InvalidateBoneCacheIfOlderThan( 0 ); +} + +void C_BaseAnimating::InvalidateBoneCacheIfOlderThan( float deltaTime ) +{ + CBoneCache *pcache = Studio_GetBoneCache( m_hitboxBoneCacheHandle ); + if ( !pcache || !pcache->IsValid( gpGlobals->curtime, deltaTime ) ) + { + InvalidateBoneCache(); + } +} + void C_BaseAnimating::LockStudioHdr() { Assert( m_hStudioHdr == MDLHANDLE_INVALID && m_pStudioHdr == NULL ); @@ -5304,7 +5351,7 @@ void C_BaseAnimating::GetBlendedLinearVelocity( Vector *pVec ) float C_BaseAnimating::FrameAdvance( float flInterval ) { CStudioHdr *hdr = GetModelPtr(); - if ( !hdr ) + if ( !hdr || !hdr->SequencesAvailable() ) return 0.0f; #ifdef DEBUG @@ -5313,24 +5360,30 @@ float C_BaseAnimating::FrameAdvance( float flInterval ) bool bWatch = false; // Q_strstr( hdr->name, "medkit_large" ) ? true : false; #endif - float curtime = gpGlobals->curtime; + UpdateModelScale(); + + if ( !m_flOldAnimTime ) + { + m_flOldAnimTime = m_flAnimTime; + } if (flInterval == 0.0f) { - flInterval = ( curtime - m_flAnimTime ); + flInterval = GetAnimTimeInterval(); if (flInterval <= 0.001f) { return 0.0f; } } - if ( !m_flAnimTime ) - { - flInterval = 0.0f; - } + // Set current + m_flAnimTime = gpGlobals->curtime; - float cyclerate = GetSequenceCycleRate( hdr, GetSequence() ); - float addcycle = flInterval * cyclerate * m_flPlaybackRate; + // Latch prev + m_flOldAnimTime = m_flAnimTime - flInterval; + + float flCycleRate = GetSequenceCycleRate( hdr, GetSequence() ); + float flAddCycle = flInterval * flCycleRate * m_flPlaybackRate; if( GetServerIntendedCycle() != -1.0f ) { @@ -5348,42 +5401,28 @@ float C_BaseAnimating::FrameAdvance( float flInterval ) if( adjustOkay ) { - float originalAdvance = addcycle; - addcycle = (serverAdvance + addcycle) / 2; + float originalAdvance = flAddCycle; + flAddCycle = (serverAdvance + flAddCycle) / 2; const float MAX_CYCLE_ADJUSTMENT = 0.1f; - addcycle = MIN( MAX_CYCLE_ADJUSTMENT, addcycle );// Don't do too big of a jump; it's too jarring as well. + flAddCycle = MIN( MAX_CYCLE_ADJUSTMENT, flAddCycle );// Don't do too big of a jump; it's too jarring as well. DevMsg( 2, "(%d): Cycle latch used to correct %.2f in to %.2f instead of %.2f.\n", - entindex(), GetCycle(), GetCycle() + addcycle, GetCycle() + originalAdvance ); + entindex(), GetCycle(), GetCycle() + flAddCycle, GetCycle() + originalAdvance ); } SetServerIntendedCycle(-1.0f); // Only use a correction once, it isn't valid any time but right now. } - float flNewCycle = GetCycle() + addcycle; - m_flAnimTime = curtime; + float flNewCycle = GetCycle() + flAddCycle; if ( bWatch ) { Msg("%i CLIENT Time: %6.3f : (Interval %f) : cycle %f rate %f add %f\n", - gpGlobals->tickcount, gpGlobals->curtime, flInterval, flNewCycle, cyclerate, addcycle ); + gpGlobals->tickcount, gpGlobals->curtime, flInterval, flNewCycle, flCycleRate, flAddCycle ); } - if ( (flNewCycle < 0.0f) || (flNewCycle >= 1.0f) ) - { - if ( IsSequenceLooping( hdr, GetSequence() ) ) - { - flNewCycle -= (int)(flNewCycle); - } - else - { - flNewCycle = (flNewCycle < 0.0f) ? 0.0f : 1.0f; - } - m_bSequenceFinished = true; - } - - SetCycle( flNewCycle ); + StudioFrameAdvanceInternal( hdr, flAddCycle ); return flInterval; } diff --git a/game/client/c_baseanimating.h b/game/client/c_baseanimating.h index 53c417529f..b17762762e 100644 --- a/game/client/c_baseanimating.h +++ b/game/client/c_baseanimating.h @@ -363,6 +363,7 @@ public: int GetNumBodyGroups( void ); class CBoneCache *GetBoneCache( CStudioHdr *pStudioHdr ); + void InvalidateBoneCacheIfOlderThan( float deltaTime ); void SetHitboxSet( int setnum ); void SetHitboxSetByName( const char *setname ); int GetHitboxSet( void ); @@ -635,6 +636,7 @@ private: virtual void OnModelLoadComplete( const model_t* pModel ); private: + void StudioFrameAdvanceInternal( CStudioHdr *pStudioHdr, float flInterval ); void LockStudioHdr(); void UnlockStudioHdr(); mutable CStudioHdr *m_pStudioHdr; diff --git a/game/client/cstrike/c_cs_player.cpp b/game/client/cstrike/c_cs_player.cpp index d4bfd07b68..63af2e5a7e 100644 --- a/game/client/cstrike/c_cs_player.cpp +++ b/game/client/cstrike/c_cs_player.cpp @@ -675,7 +675,7 @@ void C_CSPlayer::RecvProxy_CycleLatch( const CRecvProxyData *pData, void *pStruc if( pPlayer->IsLocalPlayer() ) return; // Don't need to fixup ourselves. - float incomingCycle = (float)(pData->m_Value.m_Int) / 16; // Came in as 4 bit fixed point + float incomingCycle = pData->m_Value.m_Float; // Came in as 4 bit fixed point float currentCycle = pPlayer->GetCycle(); bool closeEnough = fabs(currentCycle - incomingCycle) < CycleLatchTolerance; if( fabs(currentCycle - incomingCycle) > (1 - CycleLatchTolerance) ) @@ -783,7 +783,7 @@ IMPLEMENT_CLIENTCLASS_DT( C_CSPlayer, DT_CSPlayer, CCSPlayer ) RecvPropInt( RECVINFO( m_iProgressBarDuration ) ), RecvPropFloat( RECVINFO( m_flProgressBarStartTime ) ), RecvPropEHandle( RECVINFO( m_hRagdoll ) ), - RecvPropInt( RECVINFO( m_cycleLatch ), 0, &C_CSPlayer::RecvProxy_CycleLatch ), + RecvPropFloat( RECVINFO( m_cycleLatch ), SPROP_NOSCALE, &C_CSPlayer::RecvProxy_CycleLatch ), END_RECV_TABLE() diff --git a/game/client/cstrike/c_cs_player.h b/game/client/cstrike/c_cs_player.h index 0d50a20bd6..ba65608e20 100644 --- a/game/client/cstrike/c_cs_player.h +++ b/game/client/cstrike/c_cs_player.h @@ -374,7 +374,7 @@ private: int m_iLastPrimaryAddon; int m_iLastSecondaryAddon; - int m_cycleLatch; // server periodically updates this to fix up our anims, here it is a 4 bit fixed point + float m_cycleLatch; // server periodically updates this to fix up our anims, here it is a 4 bit fixed point float m_serverIntendedCycle; // server periodically updates this to fix up our anims, here it is the float we want, or -1 for no override diff --git a/game/server/baseanimating.cpp b/game/server/baseanimating.cpp index 39f03900b3..a2e8dcfd6d 100644 --- a/game/server/baseanimating.cpp +++ b/game/server/baseanimating.cpp @@ -498,8 +498,7 @@ void CBaseAnimating::StudioFrameAdvance() } // Time since last animation - float flInterval = gpGlobals->curtime - m_flAnimTime; - flInterval = clamp( flInterval, 0.f, MAX_ANIMTIME_INTERVAL ); + float flInterval = GetAnimTimeInterval(); //Msg( "%i %s interval %f\n", entindex(), GetClassname(), flInterval ); if (flInterval <= 0.001f) @@ -508,11 +507,12 @@ void CBaseAnimating::StudioFrameAdvance() return; } - // Latch prev - m_flPrevAnimTime = m_flAnimTime; // Set current m_flAnimTime = gpGlobals->curtime; + // Latch prev + m_flPrevAnimTime = m_flAnimTime - flInterval; + // Drive cycle float flCycleRate = GetSequenceCycleRate( pStudioHdr, GetSequence() ) * m_flPlaybackRate; diff --git a/game/server/cstrike/cs_player.cpp b/game/server/cstrike/cs_player.cpp index 210812699e..fecff79018 100644 --- a/game/server/cstrike/cs_player.cpp +++ b/game/server/cstrike/cs_player.cpp @@ -398,7 +398,7 @@ IMPLEMENT_SERVERCLASS_ST( CCSPlayer, DT_CSPlayer ) SendPropInt( SENDINFO( m_iProgressBarDuration ), 4, SPROP_UNSIGNED ), SendPropFloat( SENDINFO( m_flProgressBarStartTime ), 0, SPROP_NOSCALE ), SendPropEHandle( SENDINFO( m_hRagdoll ) ), - SendPropInt( SENDINFO( m_cycleLatch ), 4, SPROP_UNSIGNED ), + SendPropFloat( SENDINFO( m_cycleLatch ), 0, SPROP_NOSCALE ), END_SEND_TABLE() @@ -936,7 +936,7 @@ void CCSPlayer::Spawn() m_applyDeafnessTime = 0.0f; - m_cycleLatch = 0; + m_cycleLatch = 0.0f; m_cycleLatchTimer.Start( RandomFloat( 0.0f, CycleLatchInterval ) ); StockPlayerAmmo(); @@ -1677,7 +1677,7 @@ void CCSPlayer::PostThink() m_cycleLatchTimer.Start( CycleLatchInterval ); // Cycle is a float from 0 to 1. We don't need to transmit a whole float for that. Compress it in to a small fixed point - m_cycleLatch.GetForModify() = 16 * GetCycle();// 4 point fixed + m_cycleLatch.GetForModify() = GetCycle();// 4 point fixed } } diff --git a/game/server/cstrike/cs_player.h b/game/server/cstrike/cs_player.h index 9448131d4d..2825adb2ae 100644 --- a/game/server/cstrike/cs_player.h +++ b/game/server/cstrike/cs_player.h @@ -906,7 +906,7 @@ private: // This lets us rate limit the commands the players can execute so they don't overflow things like reliable buffers. CUtlDict m_RateLimitLastCommandTimes; - CNetworkVar(int, m_cycleLatch); // Every so often, we are going to transmit our cycle to the client to correct divergence caused by PVS changes + CNetworkVar(float, m_cycleLatch); // Every so often, we are going to transmit our cycle to the client to correct divergence caused by PVS changes CountdownTimer m_cycleLatchTimer; //=============================================================================