Removed interpolation for animations for now

This cause looping issues due to cycle,
until I find a proper solution for it,
it is disabled for accuracy purposes
and also because we can't trust the client.

This is really hard to see though with high tickrate.
This commit is contained in:
Kamay Xutax 2024-07-12 03:59:34 +02:00
parent 854991ab8c
commit 2e5867b300
14 changed files with 159 additions and 347 deletions

View file

@ -662,7 +662,8 @@ class C_BaseAnimatingGameSystem : public CAutoGameSystem
C_BaseAnimating::C_BaseAnimating()
: m_iv_flCycle( "C_BaseAnimating::m_iv_flCycle" ),
m_iv_flPoseParameter( "C_BaseAnimating::m_iv_flPoseParameter" ),
m_iv_flEncodedController("C_BaseAnimating::m_iv_flEncodedController")
m_iv_flEncodedController("C_BaseAnimating::m_iv_flEncodedController"),
m_iv_Sequence("C_BaseAnimating::m_iv_Sequence")
{
m_vecForce.Init();
m_nForceBone = -1;
@ -680,9 +681,12 @@ C_BaseAnimating::C_BaseAnimating()
for ( i = 0; i < ARRAYSIZE( m_flEncodedController ); i++ )
{
m_flEncodedController[ i ] = 0.0f;
}
}
AddBaseAnimatingInterpolatedVars();
for ( i = 0; i < ARRAYSIZE( m_flPoseParameter ); i++ )
{
m_flPoseParameter[ i ] = 0.0f;
}
m_iMostRecentModelBoneCounter = 0xFFFFFFFF;
m_iMostRecentBoneSetupRequest = g_iPreviousBoneCounter - 1;
@ -736,7 +740,9 @@ C_BaseAnimating::C_BaseAnimating()
m_flCycle = 0;
m_flOldCycle = 0;
m_flAnimTime = gpGlobals->curtime;
m_flOldAnimTime = gpGlobals->curtime;
m_flOldAnimTime = gpGlobals->curtime;
AddBaseAnimatingInterpolatedVars();
}
//-----------------------------------------------------------------------------
@ -747,7 +753,8 @@ C_BaseAnimating::~C_BaseAnimating()
int i = g_PreviousBoneSetups.Find( this );
if ( i != -1 )
g_PreviousBoneSetups.FastRemove( i );
RemoveFromClientSideAnimationList();
RemoveFromClientSideAnimationList();
RemoveBaseAnimatingInterpolatedVars();
TermRopes();
delete m_pRagdollInfo;
@ -839,8 +846,6 @@ ShadowType_t C_BaseAnimating::ShadowCastType()
void C_BaseAnimating::SetPredictable( bool state )
{
BaseClass::SetPredictable( state );
UpdateRelevantInterpolatedVars();
}
//-----------------------------------------------------------------------------
@ -851,33 +856,34 @@ void C_BaseAnimating::UseClientSideAnimation()
m_bClientSideAnimation = true;
}
void C_BaseAnimating::UpdateRelevantInterpolatedVars()
{
MDLCACHE_CRITICAL_SECTION();
// Remove any interpolated vars that need to be removed.
if ( !GetPredictable() && !IsClientCreated() && GetModelPtr() && GetModelPtr()->SequencesAvailable() )
{
AddBaseAnimatingInterpolatedVars();
}
else
{
RemoveBaseAnimatingInterpolatedVars();
}
}
void C_BaseAnimating::AddBaseAnimatingInterpolatedVars()
{
AddVar( m_flEncodedController, &m_iv_flEncodedController, LATCH_ANIMATION_VAR, true );
AddVar( m_flPoseParameter, &m_iv_flPoseParameter, LATCH_ANIMATION_VAR, true );
AddVar( &m_flCycle, &m_iv_flCycle, LATCH_ANIMATION_VAR, true );
// AddVar( m_flEncodedController, &m_iv_flEncodedController, LATCH_ANIMATION_VAR );
// AddVar( m_flPoseParameter, &m_iv_flPoseParameter, LATCH_ANIMATION_VAR );
int flags = LATCH_ANIMATION_VAR;
if ( m_bClientSideAnimation )
flags |= EXCLUDE_AUTO_INTERPOLATE;
// AddVar( &m_flCycle, &m_iv_flCycle, flags );
// AddVar( &m_nSequence, &m_iv_Sequence, flags );
}
void C_BaseAnimating::RemoveBaseAnimatingInterpolatedVars()
{
RemoveVar( m_flEncodedController, false );
RemoveVar( m_flPoseParameter, false );
RemoveVar( &m_flCycle, false );
#ifdef HL2MP
// HACK: Don't want to remove interpolation for predictables in hl2dm, though
// The animation state stuff sets the pose parameters -- so they should interp
// but m_flCycle is not touched, so it's only set during prediction (which occurs on tick boundaries)
// and so needs to continue to be interpolated for smooth rendering of the lower body of the local player in third person, etc.
if ( !GetPredictable() )
#endif
{
RemoveVar( &m_flCycle, false );
RemoveVar( &m_nSequence, false );
}
}
void C_BaseAnimating::StudioFrameAdvanceInternal( CStudioHdr *pStudioHdr, float flCycleDelta )
@ -1120,6 +1126,8 @@ CStudioHdr *C_BaseAnimating::OnNewModel()
Assert( hdr->GetNumPoseParameters() <= ARRAYSIZE( m_flPoseParameter ) );
m_iv_flPoseParameter.SetMaxCount(hdr->GetNumPoseParameters());
int i;
for ( i = 0; i < hdr->GetNumPoseParameters() ; i++ )
{
@ -1130,11 +1138,13 @@ CStudioHdr *C_BaseAnimating::OnNewModel()
if ( !IsServerEntity() )
{
SetPoseParameter( hdr, i, 0.0 );
}
}
}
int boneControllerCount = MIN( hdr->numbonecontrollers(), ARRAYSIZE( m_flEncodedController ) );
m_iv_flEncodedController.SetMaxCount( boneControllerCount );
for ( i = 0; i < boneControllerCount ; i++ )
{
bool loop = (hdr->pBonecontroller( i )->type & (STUDIO_XR | STUDIO_YR | STUDIO_ZR)) != 0;
@ -1175,8 +1185,6 @@ CStudioHdr *C_BaseAnimating::OnNewModel()
m_bResetSequenceInfoOnLoad = false;
ResetSequenceInfo();
}
UpdateRelevantInterpolatedVars();
return hdr;
}
@ -4336,7 +4344,7 @@ bool C_BaseAnimating::Interpolate( float flCurrentTime )
QAngle oldAngles;
Vector oldVel;
float flOldCycle = GetCycle();
int nChangeFlags = 0;
int nChangeFlags = 0;
int bNoMoreChanges;
int retVal = BaseInterpolatePart1( flCurrentTime, oldOrigin, oldAngles, oldVel, bNoMoreChanges );
@ -4599,7 +4607,7 @@ void C_BaseAnimating::PostDataUpdate( DataUpdateType_t updateType )
{
ClientSideAnimationChanged();
}
}
}
}
//-----------------------------------------------------------------------------
@ -5345,36 +5353,7 @@ float C_BaseAnimating::FrameAdvance( float flInterval )
m_flOldAnimTime = m_flAnimTime - flInterval;
float flCycleRate = GetSequenceCycleRate( hdr, GetSequence() );
float flAddCycle = flInterval * flCycleRate * m_flPlaybackRate;
if( GetServerIntendedCycle() != -1.0f )
{
// The server would like us to ease in a correction so that we will animate the same on the client and server.
// So we will actually advance the average of what we would have done and what the server wants.
float serverCycle = GetServerIntendedCycle();
float serverAdvance = serverCycle - GetCycle();
bool adjustOkay = serverAdvance > 0.0f;// only want to go forward. backing up looks really jarring, even when slight
if( serverAdvance < -0.8f )
{
// Oh wait, it was just a wraparound from .9 to .1.
serverAdvance += 1;
adjustOkay = true;
}
if( adjustOkay )
{
float originalAdvance = flAddCycle;
flAddCycle = (serverAdvance + flAddCycle) / 2;
const float MAX_CYCLE_ADJUSTMENT = 0.1f;
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() + flAddCycle, GetCycle() + originalAdvance );
}
SetServerIntendedCycle(-1.0f); // Only use a correction once, it isn't valid any time but right now.
}
float flAddCycle = flInterval * flCycleRate * m_flPlaybackRate;
float flNewCycle = GetCycle() + flAddCycle;
@ -6144,8 +6123,6 @@ void C_BaseAnimating::AddToClientSideAnimationList()
clientanimating_t list( this, 0 );
m_ClientSideAnimationListHandle = g_ClientSideAnimationList.AddToTail( list );
ClientSideAnimationChanged();
UpdateRelevantInterpolatedVars();
}
void C_BaseAnimating::RemoveFromClientSideAnimationList()
@ -6178,8 +6155,6 @@ void C_BaseAnimating::RemoveFromClientSideAnimationList()
// Invalidate our handle no matter what.
m_ClientSideAnimationListHandle = INVALID_CLIENTSIDEANIMATION_LIST_HANDLE;
UpdateRelevantInterpolatedVars();
}

View file

@ -431,10 +431,6 @@ public:
// Load the model's keyvalues section and create effects listed inside it
void InitModelEffects( void );
// Sometimes the server wants to update the client's cycle to get the two to run in sync (for proper hit detection)
virtual void SetServerIntendedCycle( float intended ) { (void)intended; }
virtual float GetServerIntendedCycle( void ) { return -1.0f; }
// For prediction
int SelectWeightedSequence ( int activity );
void ResetSequenceInfo( void );
@ -482,7 +478,6 @@ private:
void DelayedInitModelEffects( void );
void UpdateRelevantInterpolatedVars();
void AddBaseAnimatingInterpolatedVars();
void RemoveBaseAnimatingInterpolatedVars();
@ -591,6 +586,7 @@ private:
// Current animation sequence
int m_nSequence;
CInterpolatedVar< int > m_iv_Sequence;
bool m_bReceivedSequence;
// Current cycle location from server

View file

@ -86,7 +86,7 @@ void ResizeAnimationLayerCallback( void *pStruct, int offsetToUtlVector, int len
// remove all entries
for ( int i=0; i < pVec->Count(); i++ )
{
pEnt->RemoveVar( &pVec->Element( i ) );
// pEnt->RemoveVar( &pVec->Element( i ) );
}
// adjust vector sizes
@ -106,7 +106,7 @@ void ResizeAnimationLayerCallback( void *pStruct, int offsetToUtlVector, int len
{
IInterpolatedVar *pWatcher = &pVecIV->Element( i );
pWatcher->SetDebugName( s_m_iv_AnimOverlayNames[i] );
pEnt->AddVar( &pVec->Element( i ), pWatcher, LATCH_ANIMATION_VAR, true );
// pEnt->AddVar( &pVec->Element( i ), pWatcher, LATCH_ANIMATION_VAR );
}
// FIXME: need to set historical values of nOrder in pVecIV to MAX_OVERLAY
@ -211,7 +211,7 @@ void C_BaseAnimatingOverlay::AccumulateLayers( IBoneSetup &boneSetup, Vector pos
int layer[MAX_OVERLAYS] = {};
int i;
for (i = 0; i < m_AnimOverlay.Count(); i++)
{
{
layer[i] = MAX_OVERLAYS;
}
for (i = 0; i < m_AnimOverlay.Count(); i++)
@ -221,7 +221,7 @@ void C_BaseAnimatingOverlay::AccumulateLayers( IBoneSetup &boneSetup, Vector pos
{
layer[pLayer.m_nOrder] = i;
}
}
}
for (i = 0; i < m_AnimOverlay.Count(); i++)
{
if (layer[i] >= 0 && layer[i] < m_AnimOverlay.Count())

View file

@ -8,6 +8,8 @@
#include "c_cs_player.h"
#include "c_user_message_register.h"
#include "cdll_client_int.h"
#include "dt_recv.h"
#include "interpolatedvar.h"
#include "shareddefs.h"
#include "studio.h"
#include "view.h"
@ -669,35 +671,6 @@ void RecvProxy_HasDefuser( const CRecvProxyData *pData, void *pStruct, void *pOu
}
}
void C_CSPlayer::RecvProxy_CycleLatch( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
// This receive proxy looks to see if the server's value is close enough to what we think it should
// be. We've been running the same code; this is an error correction for changes we didn't simulate
// while they were out of PVS.
C_CSPlayer *pPlayer = (C_CSPlayer *)pStruct;
if( pPlayer->IsLocalPlayer() )
return; // Don't need to fixup ourselves.
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) )
{
closeEnough = true;// Handle wrapping around 1->0
}
if( !closeEnough )
{
// Server disagrees too greatly. Correct our value.
if ( pPlayer && pPlayer->GetTeam() )
{
DevMsg( 2, "%s %s(%d): Cycle latch wants to correct %.2f in to %.2f.\n",
pPlayer->GetTeam()->Get_Name(), pPlayer->GetPlayerName(), pPlayer->entindex(), currentCycle, incomingCycle );
}
pPlayer->SetServerIntendedCycle( incomingCycle );
}
}
void __MsgFunc_ReloadEffect( bf_read &msg )
{
int iPlayer = msg.ReadShort();
@ -740,8 +713,7 @@ IMPLEMENT_CLIENTCLASS_DT( C_CSPlayer, DT_CSPlayer, CCSPlayer )
RecvPropInt( RECVINFO( m_bInBuyZone ) ),
RecvPropInt( RECVINFO( m_iClass ) ),
RecvPropInt( RECVINFO( m_ArmorValue ) ),
RecvPropFloat( RECVINFO( m_angEyeAngles[0] ) ),
RecvPropFloat( RECVINFO( m_angEyeAngles[1] ) ),
RecvPropQAngles( RECVINFO( m_angEyeAngles ) ),
RecvPropFloat( RECVINFO( m_flStamina ) ),
RecvPropInt( RECVINFO( m_bHasDefuser ), 0, RecvProxy_HasDefuser ),
RecvPropInt( RECVINFO( m_bNightVisionOn), 0, RecvProxy_NightVision ),
@ -776,8 +748,7 @@ IMPLEMENT_CLIENTCLASS_DT( C_CSPlayer, DT_CSPlayer, CCSPlayer )
RecvPropFloat( RECVINFO( m_flFlashMaxAlpha)),
RecvPropInt( RECVINFO( m_iProgressBarDuration ) ),
RecvPropFloat( RECVINFO( m_flProgressBarStartTime ) ),
RecvPropEHandle( RECVINFO( m_hRagdoll ) ),
RecvPropFloat( RECVINFO( m_cycleLatch ), SPROP_NOSCALE, &C_CSPlayer::RecvProxy_CycleLatch ),
RecvPropEHandle( RECVINFO( m_hRagdoll ) )
END_RECV_TABLE()
@ -788,7 +759,7 @@ C_CSPlayer::C_CSPlayer() :
{
m_angEyeAngles.Init();
AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR );
// AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_ANIMATION_VAR );
m_iLastAddonBits = m_iAddonBits = 0;
m_iLastPrimaryAddon = m_iLastSecondaryAddon = WEAPON_NONE;
@ -805,9 +776,7 @@ C_CSPlayer::C_CSPlayer() :
m_Activity = ACT_IDLE;
m_pFlashlightBeam = NULL;
m_fNextThinkPushAway = 0.0f;
m_serverIntendedCycle = -1.0f;
m_fNextThinkPushAway = 0.0f;
view->SetScreenOverlayMaterial( NULL );

View file

@ -126,10 +126,6 @@ public:
virtual void CreateLightEffects( void ) {} //no dimlight effects
// Sometimes the server wants to update the client's cycle to get the two to run in sync (for proper hit detection)
virtual void SetServerIntendedCycle( float intended ) { m_serverIntendedCycle = intended; }
virtual float GetServerIntendedCycle( void ) { return m_serverIntendedCycle; }
virtual bool ShouldReceiveProjectedTextures( int flags )
{
return ( this != C_BasePlayer::GetLocalPlayer() );
@ -294,9 +290,6 @@ public:
CNetworkVar( float, m_flFlashMaxAlpha );
CNetworkVar( float, m_flFlashDuration );
// Having the RecvProxy in the player allows us to keep the var private
static void RecvProxy_CycleLatch( const CRecvProxyData *pData, void *pStruct, void *pOut );
// Bots and hostages auto-duck during jumps
bool m_duckUntilOnGround;
@ -371,10 +364,6 @@ private:
int m_iLastPrimaryAddon;
int m_iLastSecondaryAddon;
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
//=============================================================================
// HPE_BEGIN:
// [tj] Network variables that track who are dominating and being dominated by

View file

@ -1327,38 +1327,8 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo
continue;
}
if (pBasePlayer->IsLocalPlayer())
{
continue;
}
if (!pBasePlayer->GetModelPtr())
{
continue;
}
cmd->has_animation[pBasePlayer->index] = true;
cmd->animationdata[pBasePlayer->index].m_flAnimTime = pBasePlayer->m_flInterpolatedAnimTime;
pBasePlayer->GetBoneControllers(cmd->animationdata[pBasePlayer->index].m_encodedControllers);
pBasePlayer->GetPoseParameters(pBasePlayer->GetModelPtr(),
cmd->animationdata[pBasePlayer->index].m_poseParameters);
cmd->animationdata[pBasePlayer->index].m_masterCycle = pBasePlayer->GetCycle();
cmd->animationdata[pBasePlayer->index].m_masterSequence = pBasePlayer->GetSequence();
for (int j = 0; j < pBasePlayer->GetNumAnimOverlays(); j++)
{
cmd->animationdata[pBasePlayer->index].m_layerRecords[j].m_cycle =
pBasePlayer->GetAnimOverlay(j)->m_flCycle.GetRaw();
cmd->animationdata[pBasePlayer->index].m_layerRecords[j].m_sequence =
pBasePlayer->GetAnimOverlay(j)->m_nSequence.GetRaw();
cmd->animationdata[pBasePlayer->index].m_layerRecords[j].m_order =
pBasePlayer->GetAnimOverlay(j)->m_nOrder;
cmd->animationdata[pBasePlayer->index].m_layerRecords[j].m_weight =
pBasePlayer->GetAnimOverlay(j)->m_flWeight.GetRaw();
}
cmd->animationdata[pBasePlayer->index].m_flAnimTime = pBasePlayer->m_flAnimTime;
}
pVerified->m_cmd = *cmd;

View file

@ -158,6 +158,29 @@ inline float LoopingLerp_Hermite( float t, float p0, float p1, float p2 )
return s;
}
template <>
inline int LoopingLerp( float flPercent, int from, int to )
{
return from;
}
template <>
inline int Lerp( float flPercent, int const &from, int const &to )
{
return from;
}
template <>
inline int LoopingLerp_Hermite( float flPercent, int prev, int from, int to )
{
return from;
}
template <>
inline int Lerp_Hermite( float flPercent, const int& prev, const int& from, const int& to )
{
return from;
}
// NOTE: C_AnimationLayer has its own versions of these functions in animationlayer.h.

View file

@ -380,7 +380,7 @@ void CBaseAnimating::Spawn()
//-----------------------------------------------------------------------------
void CBaseAnimating::UseClientSideAnimation()
{
m_bClientSideAnimation = true;
m_bClientSideAnimation = false;
}
#define MAX_ANIMTIME_INTERVAL 0.2f

View file

@ -2589,7 +2589,7 @@ inline void CBaseEntity::NetworkStateChanged( void *pVar )
{
// Make sure it's a semi-reasonable pointer.
Assert( (char*)pVar > (char*)this );
Assert( (char*)pVar - (char*)this < 32768 );
// Assert( (char*)pVar - (char*)this < 32768 );
// Good, they passed an offset so we can track this variable's change
// and avoid sending the whole entity.

View file

@ -8,6 +8,7 @@
#include "cbase.h"
#include "cs_player.h"
#include "cs_gamerules.h"
#include "dt_send.h"
#include "trains.h"
#include "vcollide_parse.h"
#include "in_buttons.h"
@ -337,8 +338,7 @@ IMPLEMENT_SERVERCLASS_ST( CCSPlayer, DT_CSPlayer )
SendPropInt( SENDINFO( m_bInBuyZone ), 1, SPROP_UNSIGNED ),
SendPropInt( SENDINFO( m_iClass ), Q_log2( CS_NUM_CLASSES )+1, SPROP_UNSIGNED ),
SendPropInt( SENDINFO( m_ArmorValue ), 8 ),
SendPropAngle( SENDINFO_VECTORELEM(m_angEyeAngles, 0), 11, SPROP_CHANGES_OFTEN ),
SendPropAngle( SENDINFO_VECTORELEM(m_angEyeAngles, 1), 11, SPROP_CHANGES_OFTEN ),
SendPropQAngles(SENDINFO(m_angEyeAngles)),
SendPropBool( SENDINFO( m_bHasDefuser ) ),
SendPropBool( SENDINFO( m_bNightVisionOn ) ), //send as int so we can use a RecvProxy on the client
SendPropBool( SENDINFO( m_bHasNightVision ) ),
@ -370,8 +370,7 @@ IMPLEMENT_SERVERCLASS_ST( CCSPlayer, DT_CSPlayer )
SendPropFloat( SENDINFO(m_flFlashMaxAlpha), 0, SPROP_NOSCALE ),
SendPropInt( SENDINFO( m_iProgressBarDuration ), 4, SPROP_UNSIGNED ),
SendPropFloat( SENDINFO( m_flProgressBarStartTime ), 0, SPROP_NOSCALE ),
SendPropEHandle( SENDINFO( m_hRagdoll ) ),
SendPropFloat( SENDINFO( m_cycleLatch ), 0, SPROP_NOSCALE ),
SendPropEHandle( SENDINFO( m_hRagdoll ) )
END_SEND_TABLE()
@ -474,10 +473,7 @@ CCSPlayer::CCSPlayer()
m_lastDamageHealth = 0;
m_lastDamageArmor = 0;
m_applyDeafnessTime = 0.0f;
m_cycleLatch = 0;
m_cycleLatchTimer.Invalidate();
m_applyDeafnessTime = 0.0f;
m_iShouldHaveCash = 0;
@ -908,10 +904,7 @@ void CCSPlayer::Spawn()
m_flNextAttack = gpGlobals->curtime; // Allow reloads to finish, since we're playing the deploy anim instead. This mimics goldsrc behavior, anyway.
}
m_applyDeafnessTime = 0.0f;
m_cycleLatch = 0.0f;
m_cycleLatchTimer.Start( RandomFloat( 0.0f, CycleLatchInterval ) );
m_applyDeafnessTime = 0.0f;
StockPlayerAmmo();
}
@ -1645,14 +1638,6 @@ void CCSPlayer::PostThink()
StopSound( "Player.AmbientUnderWater" );
SetPlayerUnderwater( false );
}
if( IsAlive() && m_cycleLatchTimer.IsElapsed() )
{
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() = GetCycle();// 4 point fixed
}
}

View file

@ -906,9 +906,6 @@ private:
// This lets us rate limit the commands the players can execute so they don't overflow things like reliable buffers.
CUtlDict<float,int> m_RateLimitLastCommandTimes;
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;
//=============================================================================
// HPE_BEGIN:
// [menglish, tj] Achievement-based addition to CS player class.

View file

@ -5,6 +5,7 @@
// $NoKeywords: $
//=============================================================================//
#include "bone_setup.h"
#include "cbase.h"
#include "icvar.h"
#include "usercmd.h"
@ -313,7 +314,7 @@ void CLagCompensationManager::FrameUpdatePostEntityThink()
{
for( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
{
record.m_poseParameters[paramIndex] = pPlayer->GetPoseParameter( paramIndex );
record.m_poseParameters[paramIndex] = pPlayer->GetPoseParameterArray()[ paramIndex ];
}
}
@ -321,7 +322,7 @@ void CLagCompensationManager::FrameUpdatePostEntityThink()
{
for( int paramIndex = 0; paramIndex < hdr->GetNumBoneControllers(); paramIndex++ )
{
record.m_encodedControllers[paramIndex] = pPlayer->GetBoneController( paramIndex );
record.m_encodedControllers[paramIndex] = pPlayer->GetEncodedControllerArray()[ paramIndex ];
}
}
}
@ -387,6 +388,33 @@ void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCm
}
}
template <class T>
inline T LoopingLerp( float flPercent, T flFrom, T flTo )
{
T s = flTo * flPercent + flFrom * (1.0f - flPercent);
return s;
}
template <>
inline float LoopingLerp( float flPercent, float flFrom, float flTo )
{
if ( fabs( flTo - flFrom ) >= 0.5f )
{
if (flFrom < flTo)
flFrom += 1.0f;
else
flTo += 1.0f;
}
float s = flTo * flPercent + flFrom * (1.0f - flPercent);
s = s - (int)(s);
if (s < 0.0f)
s = s + 1.0f;
return s;
}
void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *cmd )
{
Vector org;
@ -402,9 +430,10 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
// get track history of this player
CUtlFixedLinkedList< LagRecord > *trackSim = &m_PlayerTrack[ pl_index ];
CUtlFixedLinkedList< LagRecord > *trackAnim = &m_PlayerTrack[ pl_index ];
// check if we have at leat one entry
if ( trackSim->Count() <= 0 )
if ( trackSim->Count() <= 0 || trackAnim->Count() <= 0 )
return;
intp currSim = trackSim->Head();
@ -441,9 +470,35 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
currSim = trackSim->Next( currSim );
}
intp currAnim = trackAnim->Head();
LagRecord *recordAnim = NULL;
// Walk context looking for any invalidating event
while( trackAnim->IsValidIndex(currAnim) )
{
// get next record
recordAnim = &trackAnim->Element( currAnim );
if ( !(recordAnim->m_fFlags & LC_ALIVE) )
{
// player most be alive, lost track
return;
}
// TODO: do proper teleportation checks.
// did we find a context smaller than target time ?
if ( recordAnim->m_flAnimTime <= animationData->m_flAnimTime )
break; // hurra, stop
// go one step back
currAnim = trackAnim->Next( currAnim );
}
Assert( recordAnim );
Assert( recordSim );
if ( !recordSim )
if ( !recordSim or !recordAnim )
{
if ( sv_unlag_debug.GetBool() )
{
@ -453,7 +508,7 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
return; // that should never happen
}
float fracSim = 0.0f;
float fracSim = 0.0f;
if ( prevRecordSim &&
(recordSim->m_flSimulationTime < flTargetSimulationTime) &&
(recordSim->m_flSimulationTime < prevRecordSim->m_flSimulationTime) )
@ -464,9 +519,9 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
Assert( prevRecordSim->m_flSimulationTime > recordSim->m_flSimulationTime );
Assert( flTargetSimulationTime < prevRecordSim->m_flSimulationTime );
// calc fraction between both records
fracSim = ( flTargetSimulationTime - recordSim->m_flSimulationTime ) /
( prevRecordSim->m_flSimulationTime - recordSim->m_flSimulationTime );
// calc fraction between both records
fracSim = float(( double(flTargetSimulationTime) - double(recordSim->m_flSimulationTime) ) /
( double(prevRecordSim->m_flSimulationTime) - double(recordSim->m_flSimulationTime) ));
Assert( fracSim > 0 && fracSim < 1 ); // should never extrapolate
@ -594,8 +649,8 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
restore->m_masterSequence = pPlayer->GetSequence();
restore->m_masterCycle = pPlayer->GetCycle();
pPlayer->SetSequence(animationData->m_masterSequence);
pPlayer->SetCycle(animationData->m_masterCycle);
pPlayer->SetSequence(recordAnim->m_masterSequence);
pPlayer->SetCycle(recordAnim->m_masterCycle);
////////////////////////
// Now do all the layers
@ -611,10 +666,10 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
restore->m_layerRecords[layerIndex].m_weight = currentLayer
->m_flWeight;
currentLayer->m_flCycle = animationData->m_layerRecords[layerIndex].m_cycle;
currentLayer->m_nOrder = animationData->m_layerRecords[layerIndex].m_order;
currentLayer->m_nSequence = animationData->m_layerRecords[layerIndex].m_sequence;
currentLayer->m_flWeight = animationData->m_layerRecords[layerIndex].m_weight;
currentLayer->m_flCycle = recordAnim->m_layerRecords[layerIndex].m_cycle;
currentLayer->m_nOrder = recordAnim->m_layerRecords[layerIndex].m_order;
currentLayer->m_nSequence = recordAnim->m_layerRecords[layerIndex].m_sequence;
currentLayer->m_flWeight = recordAnim->m_layerRecords[layerIndex].m_weight;
}
}
@ -626,10 +681,10 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
{
for( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
{
restore->m_poseParameters[paramIndex] = pPlayer->GetPoseParameter(paramIndex);
float poseParameter = animationData->m_poseParameters[paramIndex];
restore->m_poseParameters[paramIndex] = pPlayer->GetPoseParameterArray()[paramIndex];
float poseParameter = recordAnim->m_poseParameters[paramIndex];
pPlayer->SetPoseParameterRaw( paramIndex, poseParameter );
pPlayer->SetPoseParameterRaw(paramIndex, poseParameter);
}
}
@ -639,8 +694,8 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
{
for( int paramIndex = 0; paramIndex < hdr->GetNumBoneControllers(); paramIndex++ )
{
restore->m_encodedControllers[paramIndex] = pPlayer->GetBoneController(paramIndex);
float encodedController = animationData->m_encodedControllers[paramIndex];
restore->m_encodedControllers[paramIndex] = pPlayer->GetEncodedControllerArray()[paramIndex];
float encodedController = recordAnim->m_encodedControllers[paramIndex];
pPlayer->SetBoneControllerRaw( paramIndex, encodedController );
}
@ -666,8 +721,6 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
restore->m_fFlags = flags; // we need to restore these flags
change->m_fFlags = flags; // we have changed these flags
static ConVar *sv_showplayerhitboxes = g_pCVar->FindVar("sv_showplayerhitboxes");
if (sv_showhitboxes.GetInt() == pPlayer->entindex())
pPlayer->DrawServerHitboxes(0.0f, true);
}
@ -762,7 +815,7 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player )
{
for( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
{
pPlayer->SetPoseParameter( paramIndex, restore->m_poseParameters[paramIndex] );
pPlayer->SetPoseParameterRaw( paramIndex, restore->m_poseParameters[paramIndex] );
}
}
}
@ -774,7 +827,7 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player )
{
for( int paramIndex = 0; paramIndex < hdr->GetNumBoneControllers(); paramIndex++ )
{
pPlayer->SetBoneController( paramIndex, restore->m_encodedControllers[paramIndex] );
pPlayer->SetBoneControllerRaw( paramIndex, restore->m_encodedControllers[paramIndex] );
}
}
}

View file

@ -213,95 +213,6 @@ void WriteUsercmd( bf_write *buf, const CUserCmd *to, const CUserCmd *from )
{
buf->WriteOneBit(0);
}
if (to->animationdata[i].m_masterSequence != from->animationdata[i].m_masterSequence)
{
buf->WriteOneBit( 1 );
buf->WriteVarInt32( to->animationdata[i].m_masterSequence );
}
else
{
buf->WriteOneBit(0);
}
if (to->animationdata[i].m_masterCycle != from->animationdata[i].m_masterCycle)
{
buf->WriteOneBit( 1 );
buf->WriteFloat( to->animationdata[i].m_masterCycle );
}
else
{
buf->WriteOneBit(0);
}
for (int j = 0; j < MAX_POSE_PARAMETERS; j++)
{
if (to->animationdata[i].m_poseParameters[j] != from->animationdata[i].m_poseParameters[j])
{
buf->WriteOneBit( 1 );
buf->WriteFloat( to->animationdata[i].m_poseParameters[j] );
}
else
{
buf->WriteOneBit(0);
}
}
for (int j = 0; j < MAX_ENCODED_CONTROLLERS; j++)
{
if (to->animationdata[i].m_encodedControllers[j] != from->animationdata[i].m_encodedControllers[j])
{
buf->WriteOneBit( 1 );
buf->WriteFloat( to->animationdata[i].m_encodedControllers[j] );
}
else
{
buf->WriteOneBit(0);
}
}
for (int j = 0; j < MAX_LAYER_RECORDS; j++)
{
if (to->animationdata[i].m_layerRecords[j].m_cycle != from->animationdata[i].m_layerRecords[j].m_cycle)
{
buf->WriteOneBit( 1 );
buf->WriteFloat( to->animationdata[i].m_layerRecords[j].m_cycle );
}
else
{
buf->WriteOneBit(0);
}
if (to->animationdata[i].m_layerRecords[j].m_order != from->animationdata[i].m_layerRecords[j].m_order)
{
buf->WriteOneBit( 1 );
buf->WriteVarInt32( to->animationdata[i].m_layerRecords[j].m_order );
}
else
{
buf->WriteOneBit(0);
}
if (to->animationdata[i].m_layerRecords[j].m_sequence != from->animationdata[i].m_layerRecords[j].m_sequence)
{
buf->WriteOneBit( 1 );
buf->WriteVarInt32( to->animationdata[i].m_layerRecords[j].m_sequence );
}
else
{
buf->WriteOneBit(0);
}
if (to->animationdata[i].m_layerRecords[j].m_weight != from->animationdata[i].m_layerRecords[j].m_weight)
{
buf->WriteOneBit( 1 );
buf->WriteFloat( to->animationdata[i].m_layerRecords[j].m_weight );
}
else
{
buf->WriteOneBit(0);
}
}
}
#if defined( HL2_CLIENT_DLL )
@ -451,55 +362,6 @@ void ReadUsercmd( bf_read *buf, CUserCmd *move, CUserCmd *from )
{
move->animationdata[i].m_flAnimTime = buf->ReadFloat();
}
if (buf->ReadOneBit())
{
move->animationdata[i].m_masterSequence = buf->ReadVarInt32();
}
if (buf->ReadOneBit())
{
move->animationdata[i].m_masterCycle = buf->ReadFloat();
}
for (int j = 0; j < MAX_POSE_PARAMETERS; j++)
{
if (buf->ReadOneBit())
{
move->animationdata[i].m_poseParameters[j] = buf->ReadFloat();
}
}
for (int j = 0; j < MAX_ENCODED_CONTROLLERS; j++)
{
if (buf->ReadOneBit())
{
move->animationdata[i].m_encodedControllers[j] = buf->ReadFloat();
}
}
for (int j = 0; j < MAX_LAYER_RECORDS; j++)
{
if (buf->ReadOneBit())
{
move->animationdata[i].m_layerRecords[j].m_cycle = buf->ReadFloat();
}
if (buf->ReadOneBit())
{
move->animationdata[i].m_layerRecords[j].m_order = buf->ReadVarInt32();
}
if (buf->ReadOneBit())
{
move->animationdata[i].m_layerRecords[j].m_sequence = buf->ReadVarInt32();
}
if (buf->ReadOneBit())
{
move->animationdata[i].m_layerRecords[j].m_weight = buf->ReadFloat();
}
}
}
#if defined( HL2_DLL )

View file

@ -53,14 +53,7 @@ struct LayerRecord
struct ClientSideAnimationData
{
float m_flAnimTime;
// Player animation details, so we can get the legs in the right spot.
LayerRecord m_layerRecords[MAX_LAYER_RECORDS];
int m_masterSequence;
float m_masterCycle;
float m_poseParameters[MAX_POSE_PARAMETERS];
float m_encodedControllers[MAX_ENCODED_CONTROLLERS];
float m_flAnimTime;
};
class CEntityGroundContact