Improved lag compensation for entities
This commit is contained in:
parent
87337859f4
commit
f696159421
20 changed files with 381 additions and 434 deletions
|
@ -78,7 +78,7 @@ bool CLC_Move::WriteToBuffer( bf_write &buffer )
|
||||||
buffer.WriteUBitLong( m_nNewCommands, NUM_NEW_COMMAND_BITS );
|
buffer.WriteUBitLong( m_nNewCommands, NUM_NEW_COMMAND_BITS );
|
||||||
buffer.WriteUBitLong( m_nBackupCommands, NUM_BACKUP_COMMAND_BITS );
|
buffer.WriteUBitLong( m_nBackupCommands, NUM_BACKUP_COMMAND_BITS );
|
||||||
|
|
||||||
buffer.WriteWord( m_nLength );
|
buffer.WriteLong( m_nLength );
|
||||||
|
|
||||||
return buffer.WriteBits( m_DataOut.GetData(), m_nLength );
|
return buffer.WriteBits( m_DataOut.GetData(), m_nLength );
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ bool CLC_Move::ReadFromBuffer( bf_read &buffer )
|
||||||
|
|
||||||
m_nNewCommands = buffer.ReadUBitLong( NUM_NEW_COMMAND_BITS );
|
m_nNewCommands = buffer.ReadUBitLong( NUM_NEW_COMMAND_BITS );
|
||||||
m_nBackupCommands = buffer.ReadUBitLong( NUM_BACKUP_COMMAND_BITS );
|
m_nBackupCommands = buffer.ReadUBitLong( NUM_BACKUP_COMMAND_BITS );
|
||||||
m_nLength = buffer.ReadWord();
|
m_nLength = buffer.ReadLong();
|
||||||
m_DataIn = buffer;
|
m_DataIn = buffer;
|
||||||
return buffer.SeekRelative( m_nLength );
|
return buffer.SeekRelative( m_nLength );
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ void WriteConfig_f( ConVar *var, const char *pOldString );
|
||||||
// If we get more than 250 messages in the incoming buffer queue, dump any above this #
|
// If we get more than 250 messages in the incoming buffer queue, dump any above this #
|
||||||
#define MAX_INCOMING_MESSAGES 250
|
#define MAX_INCOMING_MESSAGES 250
|
||||||
// Size of command send buffer
|
// Size of command send buffer
|
||||||
#define MAX_CMD_BUFFER 0x10000
|
#define MAX_CMD_BUFFER 0x100000
|
||||||
|
|
||||||
CGlobalVarsBase g_ClientGlobalVariables( true );
|
CGlobalVarsBase g_ClientGlobalVariables( true );
|
||||||
IVideoRecorder *g_pVideoRecorder = NULL;
|
IVideoRecorder *g_pVideoRecorder = NULL;
|
||||||
|
|
|
@ -106,7 +106,15 @@ public:
|
||||||
C_BaseAnimating();
|
C_BaseAnimating();
|
||||||
~C_BaseAnimating();
|
~C_BaseAnimating();
|
||||||
|
|
||||||
virtual C_BaseAnimating* GetBaseAnimating() { return this; }
|
virtual C_BaseAnimating* GetBaseAnimating()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsUsingClientSideAnimation()
|
||||||
|
{
|
||||||
|
return m_bClientSideAnimation;
|
||||||
|
}
|
||||||
|
|
||||||
bool UsesPowerOfTwoFrameBufferTexture( void );
|
bool UsesPowerOfTwoFrameBufferTexture( void );
|
||||||
|
|
||||||
|
|
|
@ -690,7 +690,6 @@ IMPLEMENT_CLIENTCLASS_DT( C_CSPlayer, DT_CSPlayer, CCSPlayer )
|
||||||
RecvPropInt( RECVINFO( m_iClass ) ),
|
RecvPropInt( RECVINFO( m_iClass ) ),
|
||||||
RecvPropInt( RECVINFO( m_ArmorValue ) ),
|
RecvPropInt( RECVINFO( m_ArmorValue ) ),
|
||||||
RecvPropQAngles( RECVINFO( m_angEyeAngles ) ),
|
RecvPropQAngles( RECVINFO( m_angEyeAngles ) ),
|
||||||
RecvPropQAngles( RECVINFO( m_angRenderAngles ) ),
|
|
||||||
RecvPropFloat( RECVINFO( m_flStamina ) ),
|
RecvPropFloat( RECVINFO( m_flStamina ) ),
|
||||||
RecvPropInt( RECVINFO( m_bHasDefuser ), 0, RecvProxy_HasDefuser ),
|
RecvPropInt( RECVINFO( m_bHasDefuser ), 0, RecvProxy_HasDefuser ),
|
||||||
RecvPropInt( RECVINFO( m_bNightVisionOn), 0, RecvProxy_NightVision ),
|
RecvPropInt( RECVINFO( m_bNightVisionOn), 0, RecvProxy_NightVision ),
|
||||||
|
@ -736,10 +735,8 @@ C_CSPlayer::C_CSPlayer() :
|
||||||
m_iv_angRenderAngles( "C_CSPlayer::m_iv_angRenderAngles" )
|
m_iv_angRenderAngles( "C_CSPlayer::m_iv_angRenderAngles" )
|
||||||
{
|
{
|
||||||
m_angEyeAngles.Init();
|
m_angEyeAngles.Init();
|
||||||
m_angRenderAngles.Init();
|
|
||||||
|
|
||||||
AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR );
|
AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR );
|
||||||
// AddVar( &m_angRenderAngles, &m_iv_angRenderAngles, LATCH_SIMULATION_VAR );
|
|
||||||
|
|
||||||
m_iLastAddonBits = m_iAddonBits = 0;
|
m_iLastAddonBits = m_iAddonBits = 0;
|
||||||
m_iLastPrimaryAddon = m_iLastSecondaryAddon = WEAPON_NONE;
|
m_iLastPrimaryAddon = m_iLastSecondaryAddon = WEAPON_NONE;
|
||||||
|
@ -890,7 +887,7 @@ const QAngle& C_CSPlayer::GetRenderAngles()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return m_angRenderAngles;
|
return BaseClass::GetRenderAngles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2183,7 +2180,7 @@ void C_CSPlayer::FireGameEvent( IGameEvent* event )
|
||||||
|
|
||||||
C_AnimationLayer backupAnimLayers[C_BaseAnimatingOverlay::MAX_OVERLAYS];
|
C_AnimationLayer backupAnimLayers[C_BaseAnimatingOverlay::MAX_OVERLAYS];
|
||||||
Vector vecBackupPosition = player->GetAbsOrigin();
|
Vector vecBackupPosition = player->GetAbsOrigin();
|
||||||
QAngle angBackupAngles = player->GetRenderAngles();
|
QAngle angBackupAngles = player->GetAbsAngles();
|
||||||
auto flOldCycle = player->GetCycle();
|
auto flOldCycle = player->GetCycle();
|
||||||
auto iOldSequence = player->GetSequence();
|
auto iOldSequence = player->GetSequence();
|
||||||
|
|
||||||
|
@ -2208,9 +2205,9 @@ void C_CSPlayer::FireGameEvent( IGameEvent* event )
|
||||||
event->GetFloat( "position_y" ),
|
event->GetFloat( "position_y" ),
|
||||||
event->GetFloat( "position_z" ) ) );
|
event->GetFloat( "position_z" ) ) );
|
||||||
|
|
||||||
player->m_angRenderAngles = QAngle( event->GetFloat( "angle_x" ),
|
player->SetAbsAngles( QAngle( event->GetFloat( "angle_x" ),
|
||||||
event->GetFloat( "angle_y" ),
|
event->GetFloat( "angle_y" ),
|
||||||
event->GetFloat( "angle_z" ) );
|
event->GetFloat( "angle_z" ) ) );
|
||||||
|
|
||||||
const auto numposeparams = event->GetInt( "num_poseparams" );
|
const auto numposeparams = event->GetInt( "num_poseparams" );
|
||||||
Assert( numposeparams == player->GetModelPtr()->GetNumPoseParameters() );
|
Assert( numposeparams == player->GetModelPtr()->GetNumPoseParameters() );
|
||||||
|
@ -2314,17 +2311,19 @@ void C_CSPlayer::FireGameEvent( IGameEvent* event )
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pRecord->m_angRenderAngles != player->m_angRenderAngles )
|
auto angles = player->GetAbsAngles();
|
||||||
|
|
||||||
|
if ( pRecord->m_angAbsRotation != angles )
|
||||||
{
|
{
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
V_sprintf_safe( buffer,
|
V_sprintf_safe( buffer,
|
||||||
"angles: %f != %f, %f != %f, %f != %f",
|
"angles: %f != %f, %f != %f, %f != %f",
|
||||||
player->m_angRenderAngles.x,
|
angles.x,
|
||||||
pRecord->m_angRenderAngles.x,
|
pRecord->m_angAbsRotation.x,
|
||||||
player->m_angRenderAngles.y,
|
angles.y,
|
||||||
pRecord->m_angRenderAngles.y,
|
pRecord->m_angAbsRotation.y,
|
||||||
player->m_angRenderAngles.z,
|
angles.z,
|
||||||
pRecord->m_angRenderAngles.z );
|
pRecord->m_angAbsRotation.z );
|
||||||
|
|
||||||
NDebugOverlay::EntityTextAtPosition( pRecord->m_vecAbsOrigin, pos, buffer, flDuration );
|
NDebugOverlay::EntityTextAtPosition( pRecord->m_vecAbsOrigin, pos, buffer, flDuration );
|
||||||
pos++;
|
pos++;
|
||||||
|
@ -2441,7 +2440,7 @@ void C_CSPlayer::FireGameEvent( IGameEvent* event )
|
||||||
player->m_nSequence = iOldSequence;
|
player->m_nSequence = iOldSequence;
|
||||||
player->m_flCycle = flOldCycle;
|
player->m_flCycle = flOldCycle;
|
||||||
player->SetAbsOrigin( vecBackupPosition );
|
player->SetAbsOrigin( vecBackupPosition );
|
||||||
player->m_angRenderAngles = angBackupAngles;
|
player->SetAbsAngles( angBackupAngles );
|
||||||
|
|
||||||
for ( int i = 0; i < MAXSTUDIOPOSEPARAM; i++ )
|
for ( int i = 0; i < MAXSTUDIOPOSEPARAM; i++ )
|
||||||
{
|
{
|
||||||
|
|
|
@ -325,9 +325,7 @@ private:
|
||||||
bool m_bHasHelmet;
|
bool m_bHasHelmet;
|
||||||
int m_iClass;
|
int m_iClass;
|
||||||
int m_ArmorValue;
|
int m_ArmorValue;
|
||||||
public:
|
|
||||||
QAngle m_angEyeAngles;
|
QAngle m_angEyeAngles;
|
||||||
QAngle m_angRenderAngles;
|
|
||||||
private:
|
private:
|
||||||
bool m_bHasDefuser;
|
bool m_bHasDefuser;
|
||||||
float m_fNextThinkPushAway;
|
float m_fNextThinkPushAway;
|
||||||
|
@ -411,7 +409,7 @@ private:
|
||||||
{
|
{
|
||||||
int m_nAttackerTickBase;
|
int m_nAttackerTickBase;
|
||||||
Vector m_vecAbsOrigin;
|
Vector m_vecAbsOrigin;
|
||||||
QAngle m_angRenderAngles;
|
QAngle m_angAbsRotation;
|
||||||
float m_flSimulationTime;
|
float m_flSimulationTime;
|
||||||
int m_nSequence;
|
int m_nSequence;
|
||||||
float m_flCycle;
|
float m_flCycle;
|
||||||
|
|
|
@ -1306,21 +1306,33 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo
|
||||||
|
|
||||||
for ( int i = 0; i < MAX_EDICTS; i++ )
|
for ( int i = 0; i < MAX_EDICTS; i++ )
|
||||||
{
|
{
|
||||||
cmd->simulationdata[i].entityexists = false;
|
cmd->simulationdata[i] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send interpolated simulation time for lag compensation, let it also auto-vectorize this.
|
// Send interpolated simulation time for lag compensation, let it also auto-vectorize this.
|
||||||
for ( int i = 0; i < MAX_EDICTS; i++ )
|
for ( int i = 0; i < MAX_EDICTS; i++ )
|
||||||
{
|
{
|
||||||
auto pEntity = ClientEntityList().GetEnt( i );
|
const auto pEntity = ClientEntityList().GetEnt( i );
|
||||||
|
|
||||||
if ( !pEntity )
|
if ( !pEntity )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( pEntity->ShouldPredict() )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
cmd->simulationdata[pEntity->index].sim_time = pEntity->m_flInterpolatedSimulationTime;
|
cmd->simulationdata[pEntity->index].sim_time = pEntity->m_flInterpolatedSimulationTime;
|
||||||
|
|
||||||
|
auto pAnim = pEntity->GetBaseAnimating();
|
||||||
|
|
||||||
|
if ( pAnim && !pAnim->IsUsingClientSideAnimation() )
|
||||||
|
{
|
||||||
cmd->simulationdata[pEntity->index].anim_time = pEntity->m_flAnimTime;
|
cmd->simulationdata[pEntity->index].anim_time = pEntity->m_flAnimTime;
|
||||||
|
}
|
||||||
|
|
||||||
cmd->simulationdata[pEntity->index].entityexists = true;
|
cmd->simulationdata[pEntity->index].entityexists = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -480,7 +480,7 @@ void CBaseAnimatingOverlay::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Q
|
||||||
if ( m_pIk )
|
if ( m_pIk )
|
||||||
{
|
{
|
||||||
CIKContext auto_ik;
|
CIKContext auto_ik;
|
||||||
auto_ik.Init( pStudioHdr, GetRenderAngles(), GetRenderOrigin(), gpGlobals->curtime, m_iIKCounter, boneMask );
|
auto_ik.Init( pStudioHdr, GetAbsAngles(), GetAbsOrigin(), gpGlobals->curtime, m_iIKCounter, boneMask );
|
||||||
boneSetup.CalcAutoplaySequences( pos, q, gpGlobals->curtime, &auto_ik );
|
boneSetup.CalcAutoplaySequences( pos, q, gpGlobals->curtime, &auto_ik );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -1670,7 +1670,7 @@ void CBaseAnimating::CalculateIKLocks( float currentTime )
|
||||||
|
|
||||||
// FIXME: trace based on gravity or trace based on angles?
|
// FIXME: trace based on gravity or trace based on angles?
|
||||||
Vector up;
|
Vector up;
|
||||||
AngleVectors( GetRenderAngles(), NULL, NULL, &up );
|
AngleVectors( GetAbsAngles(), NULL, NULL, &up );
|
||||||
|
|
||||||
// FIXME: check number of slots?
|
// FIXME: check number of slots?
|
||||||
float minHeight = FLT_MAX;
|
float minHeight = FLT_MAX;
|
||||||
|
@ -1692,7 +1692,7 @@ void CBaseAnimating::CalculateIKLocks( float currentTime )
|
||||||
Vector p1, p2;
|
Vector p1, p2;
|
||||||
|
|
||||||
// adjust ground to original ground position
|
// adjust ground to original ground position
|
||||||
estGround = (pTarget->est.pos - GetRenderOrigin());
|
estGround = (pTarget->est.pos - GetAbsOrigin());
|
||||||
estGround = estGround - (estGround * up) * up;
|
estGround = estGround - (estGround * up) * up;
|
||||||
estGround = GetAbsOrigin() + estGround + pTarget->est.floor * up;
|
estGround = GetAbsOrigin() + estGround + pTarget->est.floor * up;
|
||||||
|
|
||||||
|
@ -1781,7 +1781,7 @@ void CBaseAnimating::CalculateIKLocks( float currentTime )
|
||||||
else if (trace.DidHitNonWorldEntity())
|
else if (trace.DidHitNonWorldEntity())
|
||||||
{
|
{
|
||||||
pTarget->SetPos( trace.endpos );
|
pTarget->SetPos( trace.endpos );
|
||||||
pTarget->SetAngles( GetRenderAngles() );
|
pTarget->SetAngles( GetAbsAngles() );
|
||||||
|
|
||||||
// only do this on forward tracking or commited IK ground rules
|
// only do this on forward tracking or commited IK ground rules
|
||||||
if (pTarget->est.release < 0.1)
|
if (pTarget->est.release < 0.1)
|
||||||
|
@ -1815,7 +1815,7 @@ void CBaseAnimating::CalculateIKLocks( float currentTime )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pTarget->SetPos( trace.endpos );
|
pTarget->SetPos( trace.endpos );
|
||||||
pTarget->SetAngles( GetRenderAngles() );
|
pTarget->SetAngles( GetAbsAngles() );
|
||||||
pTarget->SetOnWorld( true );
|
pTarget->SetOnWorld( true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2031,7 +2031,7 @@ void CBaseAnimating::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask )
|
||||||
// FIXME: pass this into Studio_BuildMatrices to skip transforms
|
// FIXME: pass this into Studio_BuildMatrices to skip transforms
|
||||||
CBoneBitList boneComputed;
|
CBoneBitList boneComputed;
|
||||||
m_iIKCounter++;
|
m_iIKCounter++;
|
||||||
m_pIk->Init( pStudioHdr, GetRenderAngles(), adjOrigin, gpGlobals->curtime, m_iIKCounter, boneMask );
|
m_pIk->Init( pStudioHdr, GetAbsAngles(), adjOrigin, gpGlobals->curtime, m_iIKCounter, boneMask );
|
||||||
GetSkeleton( pStudioHdr, pos, q, boneMask );
|
GetSkeleton( pStudioHdr, pos, q, boneMask );
|
||||||
|
|
||||||
UpdateIKLocks( gpGlobals->curtime );
|
UpdateIKLocks( gpGlobals->curtime );
|
||||||
|
@ -2055,7 +2055,7 @@ void CBaseAnimating::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask )
|
||||||
{
|
{
|
||||||
BuildMatricesWithBoneMerge(
|
BuildMatricesWithBoneMerge(
|
||||||
pStudioHdr,
|
pStudioHdr,
|
||||||
GetRenderAngles(),
|
GetAbsAngles(),
|
||||||
adjOrigin,
|
adjOrigin,
|
||||||
pos,
|
pos,
|
||||||
q,
|
q,
|
||||||
|
@ -2074,7 +2074,7 @@ void CBaseAnimating::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask )
|
||||||
|
|
||||||
Studio_BuildMatrices(
|
Studio_BuildMatrices(
|
||||||
pStudioHdr,
|
pStudioHdr,
|
||||||
GetRenderAngles(),
|
GetAbsAngles(),
|
||||||
adjOrigin,
|
adjOrigin,
|
||||||
pos,
|
pos,
|
||||||
q,
|
q,
|
||||||
|
@ -3036,7 +3036,7 @@ void CBaseAnimating::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaterni
|
||||||
if ( m_pIk )
|
if ( m_pIk )
|
||||||
{
|
{
|
||||||
CIKContext auto_ik;
|
CIKContext auto_ik;
|
||||||
auto_ik.Init( pStudioHdr, GetRenderAngles(), GetAbsOrigin(), gpGlobals->curtime, m_iIKCounter, boneMask );
|
auto_ik.Init( pStudioHdr, GetAbsAngles(), GetAbsOrigin(), gpGlobals->curtime, m_iIKCounter, boneMask );
|
||||||
boneSetup.CalcAutoplaySequences( pos, q, gpGlobals->curtime, &auto_ik );
|
boneSetup.CalcAutoplaySequences( pos, q, gpGlobals->curtime, &auto_ik );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -426,8 +426,6 @@ public:
|
||||||
bool IsCurrentlyTouching( void ) const;
|
bool IsCurrentlyTouching( void ) const;
|
||||||
const Vector& GetAbsOrigin( void ) const;
|
const Vector& GetAbsOrigin( void ) const;
|
||||||
const QAngle& GetAbsAngles( void ) const;
|
const QAngle& GetAbsAngles( void ) const;
|
||||||
virtual const Vector& GetRenderOrigin( void ) const { return GetAbsOrigin(); }
|
|
||||||
virtual const QAngle& GetRenderAngles( void ) const { return GetAbsAngles(); }
|
|
||||||
|
|
||||||
SolidType_t GetSolid() const;
|
SolidType_t GetSolid() const;
|
||||||
int GetSolidFlags( void ) const;
|
int GetSolidFlags( void ) const;
|
||||||
|
|
|
@ -302,7 +302,6 @@ IMPLEMENT_SERVERCLASS_ST( CCSPlayer, DT_CSPlayer )
|
||||||
SendPropInt( SENDINFO( m_iClass ), Q_log2( CS_NUM_CLASSES )+1, SPROP_UNSIGNED ),
|
SendPropInt( SENDINFO( m_iClass ), Q_log2( CS_NUM_CLASSES )+1, SPROP_UNSIGNED ),
|
||||||
SendPropInt( SENDINFO( m_ArmorValue ), 8 ),
|
SendPropInt( SENDINFO( m_ArmorValue ), 8 ),
|
||||||
SendPropQAngles(SENDINFO(m_angEyeAngles)),
|
SendPropQAngles(SENDINFO(m_angEyeAngles)),
|
||||||
SendPropQAngles(SENDINFO(m_angRenderAngles)),
|
|
||||||
SendPropBool( SENDINFO( m_bHasDefuser ) ),
|
SendPropBool( SENDINFO( m_bHasDefuser ) ),
|
||||||
SendPropBool( SENDINFO( m_bNightVisionOn ) ), //send as int so we can use a RecvProxy on the client
|
SendPropBool( SENDINFO( m_bNightVisionOn ) ), //send as int so we can use a RecvProxy on the client
|
||||||
SendPropBool( SENDINFO( m_bHasNightVision ) ),
|
SendPropBool( SENDINFO( m_bHasNightVision ) ),
|
||||||
|
@ -1164,7 +1163,7 @@ void CCSPlayer::Event_Killed( const CTakeDamageInfo &info )
|
||||||
{
|
{
|
||||||
if ( RandomInt( 0, 100 ) < 20 )
|
if ( RandomInt( 0, 100 ) < 20 )
|
||||||
{
|
{
|
||||||
CHolidayGift::Create( WorldSpaceCenter(), GetRenderAngles(), EyeAngles(), GetAbsVelocity(), this );
|
CHolidayGift::Create( WorldSpaceCenter(), GetAbsAngles(), EyeAngles(), GetAbsVelocity(), this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1455,7 +1454,7 @@ void CCSPlayer::UpdateRadar()
|
||||||
WRITE_SBITLONG( pPlayer->GetAbsOrigin().x/4, COORD_INTEGER_BITS-1 );
|
WRITE_SBITLONG( pPlayer->GetAbsOrigin().x/4, COORD_INTEGER_BITS-1 );
|
||||||
WRITE_SBITLONG( pPlayer->GetAbsOrigin().y/4, COORD_INTEGER_BITS-1 );
|
WRITE_SBITLONG( pPlayer->GetAbsOrigin().y/4, COORD_INTEGER_BITS-1 );
|
||||||
WRITE_SBITLONG( pPlayer->GetAbsOrigin().z/4, COORD_INTEGER_BITS-1 );
|
WRITE_SBITLONG( pPlayer->GetAbsOrigin().z/4, COORD_INTEGER_BITS-1 );
|
||||||
WRITE_SBITLONG( AngleNormalize( pPlayer->GetRenderAngles().y ), 9 );
|
WRITE_SBITLONG( AngleNormalize( pPlayer->GetAbsAngles().y ), 9 );
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE_BYTE( 0 ); // end marker
|
WRITE_BYTE( 0 ); // end marker
|
||||||
|
@ -1584,7 +1583,8 @@ void CCSPlayer::PostThink()
|
||||||
|
|
||||||
m_PlayerAnimState->Update( m_angEyeAngles[YAW], m_angEyeAngles[PITCH] );
|
m_PlayerAnimState->Update( m_angEyeAngles[YAW], m_angEyeAngles[PITCH] );
|
||||||
|
|
||||||
m_angRenderAngles = m_PlayerAnimState->GetRenderAngles();
|
// Use the m_angRotation instead.
|
||||||
|
SetAbsAngles( m_PlayerAnimState->GetRenderAngles() );
|
||||||
|
|
||||||
// check if we need to apply a deafness DSP effect.
|
// check if we need to apply a deafness DSP effect.
|
||||||
if ((m_applyDeafnessTime != 0.0f) && (m_applyDeafnessTime <= gpGlobals->curtime))
|
if ((m_applyDeafnessTime != 0.0f) && (m_applyDeafnessTime <= gpGlobals->curtime))
|
||||||
|
@ -2780,7 +2780,7 @@ void CCSPlayer::DropShield( void )
|
||||||
#ifdef CS_SHIELD_ENABLED
|
#ifdef CS_SHIELD_ENABLED
|
||||||
//Drop an item_defuser
|
//Drop an item_defuser
|
||||||
Vector vForward, vRight;
|
Vector vForward, vRight;
|
||||||
AngleVectors( GetRenderAngles(), &vForward, &vRight, NULL );
|
AngleVectors( GetAbsAngles(), &vForward, &vRight, NULL );
|
||||||
|
|
||||||
RemoveShield();
|
RemoveShield();
|
||||||
|
|
||||||
|
@ -6719,7 +6719,7 @@ void CCSPlayer::DropWeapons( bool fromDeath, bool friendlyFire )
|
||||||
{
|
{
|
||||||
//Drop an item_defuser
|
//Drop an item_defuser
|
||||||
Vector vForward, vRight;
|
Vector vForward, vRight;
|
||||||
AngleVectors( GetRenderAngles(), &vForward, &vRight, NULL );
|
AngleVectors( GetAbsAngles(), &vForward, &vRight, NULL );
|
||||||
|
|
||||||
CBaseAnimating *pDefuser = (CBaseAnimating *)CBaseEntity::Create( "item_defuser", WorldSpaceCenter(), GetLocalAngles(), this );
|
CBaseAnimating *pDefuser = (CBaseAnimating *)CBaseEntity::Create( "item_defuser", WorldSpaceCenter(), GetLocalAngles(), this );
|
||||||
pDefuser->ApplyAbsVelocityImpulse( vForward * 200 + vRight * random->RandomFloat( -50, 50 ) );
|
pDefuser->ApplyAbsVelocityImpulse( vForward * 200 + vRight * random->RandomFloat( -50, 50 ) );
|
||||||
|
|
|
@ -288,8 +288,6 @@ public:
|
||||||
|
|
||||||
virtual int GetNextObserverSearchStartPoint( bool bReverse );
|
virtual int GetNextObserverSearchStartPoint( bool bReverse );
|
||||||
|
|
||||||
virtual const QAngle& GetRenderAngles( void ) const { return m_angRenderAngles; }
|
|
||||||
|
|
||||||
// In shared code.
|
// In shared code.
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -816,7 +814,6 @@ public:
|
||||||
|
|
||||||
// Copyed from EyeAngles() so we can send it to the client.
|
// Copyed from EyeAngles() so we can send it to the client.
|
||||||
CNetworkQAngle( m_angEyeAngles );
|
CNetworkQAngle( m_angEyeAngles );
|
||||||
CNetworkQAngle( m_angRenderAngles );
|
|
||||||
|
|
||||||
bool m_bVCollisionInitted;
|
bool m_bVCollisionInitted;
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,15 @@
|
||||||
|
|
||||||
#ifndef ILAGCOMPENSATIONMANAGER_H
|
#ifndef ILAGCOMPENSATIONMANAGER_H
|
||||||
#define ILAGCOMPENSATIONMANAGER_H
|
#define ILAGCOMPENSATIONMANAGER_H
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
class CBasePlayer;
|
class CBasePlayer;
|
||||||
|
class CBaseEntity;
|
||||||
class CUserCmd;
|
class CUserCmd;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -23,8 +27,6 @@ public:
|
||||||
// Called during player movement to set up/restore after lag compensation
|
// Called during player movement to set up/restore after lag compensation
|
||||||
virtual void StartLagCompensation( CBasePlayer* player, CUserCmd* cmd ) = 0;
|
virtual void StartLagCompensation( CBasePlayer* player, CUserCmd* cmd ) = 0;
|
||||||
virtual void FinishLagCompensation( CBasePlayer* player ) = 0;
|
virtual void FinishLagCompensation( CBasePlayer* player ) = 0;
|
||||||
virtual void BacktrackPlayer( CBasePlayer *player, CUserCmd *cmd ) = 0;
|
|
||||||
virtual void TrackPlayerData( CBasePlayer *pPlayer ) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ILagCompensationManager *lagcompensation;
|
extern ILagCompensationManager *lagcompensation;
|
||||||
|
|
|
@ -746,12 +746,17 @@ static void NormalizeAngles( QAngle& angles )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBasePlayer::WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec<MAX_EDICTS> *pEntityTransmitBits )
|
bool CBasePlayer::WantsLagCompensationOnEntity( const CBaseEntity *pEntity, const CUserCmd *pCmd, const CBitVec<MAX_EDICTS> *pEntityTransmitBits )
|
||||||
{
|
{
|
||||||
// Team members shouldn't be adjusted unless friendly fire is on.
|
// Team members shouldn't be adjusted unless friendly fire is on.
|
||||||
if ( !friendlyfire.GetInt() && pPlayer->GetTeamNumber() == GetTeamNumber() )
|
if ( !friendlyfire.GetInt() && pEntity->GetTeamNumber() == GetTeamNumber() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if ( pEntity->GetOwnerEntity() == this )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: Do not check for this, it is possible to knife from behind in CS:S
|
// NOTE: Do not check for this, it is possible to knife from behind in CS:S
|
||||||
// Vector vShootPosition = Weapon_ShootPosition();
|
// Vector vShootPosition = Weapon_ShootPosition();
|
||||||
// const Vector &vHisOrigin = pPlayer->GetAbsOrigin();
|
// const Vector &vHisOrigin = pPlayer->GetAbsOrigin();
|
||||||
|
@ -7929,12 +7934,12 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data)
|
||||||
|
|
||||||
// If HL2_DLL is defined, then baseflex.cpp already sends these.
|
// If HL2_DLL is defined, then baseflex.cpp already sends these.
|
||||||
#ifndef HL2_DLL
|
#ifndef HL2_DLL
|
||||||
SendPropFloat ( SENDINFO_VECTORELEM(m_vecViewOffset, 0), -1, 0, -32.0, 32.0f),
|
SendPropFloat ( SENDINFO_VECTORELEM(m_vecViewOffset, 0)),
|
||||||
SendPropFloat ( SENDINFO_VECTORELEM(m_vecViewOffset, 1), -1, 0, -32.0, 32.0f),
|
SendPropFloat ( SENDINFO_VECTORELEM(m_vecViewOffset, 1)),
|
||||||
SendPropFloat ( SENDINFO_VECTORELEM(m_vecViewOffset, 2), -1, 0, 0.0f, 256.0f),
|
SendPropFloat ( SENDINFO_VECTORELEM(m_vecViewOffset, 2)),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SendPropFloat ( SENDINFO(m_flFriction), 8, SPROP_ROUNDDOWN, 0.0f, 4.0f),
|
SendPropFloat ( SENDINFO(m_flFriction) ),
|
||||||
|
|
||||||
SendPropArray3 ( SENDINFO_ARRAY3(m_iAmmo), SendPropInt( SENDINFO_ARRAY(m_iAmmo), -1, SPROP_VARINT | SPROP_UNSIGNED ) ),
|
SendPropArray3 ( SENDINFO_ARRAY3(m_iAmmo), SendPropInt( SENDINFO_ARRAY(m_iAmmo), -1, SPROP_VARINT | SPROP_UNSIGNED ) ),
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#ifndef PLAYER_H
|
#ifndef PLAYER_H
|
||||||
#define PLAYER_H
|
#define PLAYER_H
|
||||||
|
#include "baseentity.h"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
@ -282,7 +283,7 @@ public:
|
||||||
// Returns true if this player wants pPlayer to be moved back in time when this player runs usercmds.
|
// Returns true if this player wants pPlayer to be moved back in time when this player runs usercmds.
|
||||||
// Saves a lot of overhead on the server if we can cull out entities that don't need to lag compensate
|
// Saves a lot of overhead on the server if we can cull out entities that don't need to lag compensate
|
||||||
// (like team members, entities out of our PVS, etc).
|
// (like team members, entities out of our PVS, etc).
|
||||||
virtual bool WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec<MAX_EDICTS> *pEntityTransmitBits );
|
virtual bool WantsLagCompensationOnEntity( const CBaseEntity *pEntity, const CUserCmd *pCmd, const CBitVec<MAX_EDICTS> *pEntityTransmitBits );
|
||||||
|
|
||||||
virtual void Spawn( void );
|
virtual void Spawn( void );
|
||||||
virtual void Activate( void );
|
virtual void Activate( void );
|
||||||
|
|
|
@ -308,8 +308,12 @@ void CPlayerMove::RunPostThink( CBasePlayer *player )
|
||||||
{
|
{
|
||||||
VPROF( "CPlayerMove::RunPostThink" );
|
VPROF( "CPlayerMove::RunPostThink" );
|
||||||
|
|
||||||
|
lagcompensation->StartLagCompensation( player, player->GetCurrentCommand() );
|
||||||
|
|
||||||
// Run post-think
|
// Run post-think
|
||||||
player->PostThink();
|
player->PostThink();
|
||||||
|
|
||||||
|
lagcompensation->FinishLagCompensation( player );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentarySystem_PePlayerRunCommand( CBasePlayer *player, CUserCmd *ucmd );
|
void CommentarySystem_PePlayerRunCommand( CBasePlayer *player, CUserCmd *ucmd );
|
||||||
|
@ -467,6 +471,4 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
||||||
{
|
{
|
||||||
player->m_nTickBase++;
|
player->m_nTickBase++;
|
||||||
}
|
}
|
||||||
|
|
||||||
lagcompensation->TrackPlayerData( player );
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
//=============================================================================//
|
//=============================================================================//
|
||||||
|
|
||||||
#include "cbase.h"
|
#include "cbase.h"
|
||||||
#ifdef CSTRIKE_DLL
|
|
||||||
#include "cs_player.h"
|
|
||||||
#endif
|
|
||||||
#include "icvar.h"
|
#include "icvar.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "shareddefs.h"
|
#include "shareddefs.h"
|
||||||
|
@ -34,9 +31,10 @@
|
||||||
#define LC_ANIMATION_CHANGED ( 1 << 11 )
|
#define LC_ANIMATION_CHANGED ( 1 << 11 )
|
||||||
#define LC_POSE_PARAMS_CHANGED ( 1 << 12 )
|
#define LC_POSE_PARAMS_CHANGED ( 1 << 12 )
|
||||||
#define LC_ENCD_CONS_CHANGED ( 1 << 13 )
|
#define LC_ENCD_CONS_CHANGED ( 1 << 13 )
|
||||||
|
#define LC_ANIM_OVERS_CHANGED ( 1 << 14 )
|
||||||
|
|
||||||
// Default to 1 second max.
|
// Default to 1 second max.
|
||||||
#define MAX_TICKS_SAVED 1000
|
#define MAX_TICKS_SAVED 1024
|
||||||
|
|
||||||
ConVar sv_unlag( "sv_unlag", "1", FCVAR_DEVELOPMENTONLY, "Enables player lag compensation" );
|
ConVar sv_unlag( "sv_unlag", "1", FCVAR_DEVELOPMENTONLY, "Enables player lag compensation" );
|
||||||
// Enable by default to avoid some bugs.
|
// Enable by default to avoid some bugs.
|
||||||
|
@ -53,84 +51,11 @@ struct LayerRecord
|
||||||
float m_weight;
|
float m_weight;
|
||||||
int m_order;
|
int m_order;
|
||||||
int m_flags;
|
int m_flags;
|
||||||
|
|
||||||
LayerRecord()
|
|
||||||
{
|
|
||||||
m_sequence = 0;
|
|
||||||
m_cycle = 0;
|
|
||||||
m_weight = 0;
|
|
||||||
m_order = 0;
|
|
||||||
m_flags = 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LagRecord
|
struct LagRecord
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LagRecord()
|
|
||||||
{
|
|
||||||
m_fFlags = LC_NONE;
|
|
||||||
m_vecOrigin.Init();
|
|
||||||
m_vecAngles.Init();
|
|
||||||
m_vecMinsPreScaled.Init();
|
|
||||||
m_vecMaxsPreScaled.Init();
|
|
||||||
m_flSimulationTime = -1;
|
|
||||||
m_flAnimTime = -1;
|
|
||||||
m_masterSequence = 0;
|
|
||||||
m_masterCycle = 0;
|
|
||||||
|
|
||||||
for ( int layerIndex = 0; layerIndex < MAX_LAYER_RECORDS; ++layerIndex )
|
|
||||||
{
|
|
||||||
m_layerRecords[layerIndex] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( int i = 0; i < MAXSTUDIOPOSEPARAM; i++ )
|
|
||||||
{
|
|
||||||
m_poseParameters[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( int i = 0; i < MAXSTUDIOBONECTRLS; i++ )
|
|
||||||
{
|
|
||||||
m_encodedControllers[i] = 0;
|
|
||||||
}
|
|
||||||
#ifdef CSTRIKE_DLL
|
|
||||||
m_angRenderAngles.Init();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
LagRecord( const LagRecord& src )
|
|
||||||
{
|
|
||||||
m_fFlags = src.m_fFlags;
|
|
||||||
m_vecOrigin = src.m_vecOrigin;
|
|
||||||
m_vecAngles = src.m_vecAngles;
|
|
||||||
m_vecMinsPreScaled = src.m_vecMinsPreScaled;
|
|
||||||
m_vecMaxsPreScaled = src.m_vecMaxsPreScaled;
|
|
||||||
m_flSimulationTime = src.m_flSimulationTime;
|
|
||||||
m_flAnimTime = src.m_flAnimTime;
|
|
||||||
|
|
||||||
for ( int layerIndex = 0; layerIndex < MAX_LAYER_RECORDS; ++layerIndex )
|
|
||||||
{
|
|
||||||
m_layerRecords[layerIndex] = src.m_layerRecords[layerIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
m_masterSequence = src.m_masterSequence;
|
|
||||||
m_masterCycle = src.m_masterCycle;
|
|
||||||
|
|
||||||
for ( int i = 0; i < MAXSTUDIOPOSEPARAM; i++ )
|
|
||||||
{
|
|
||||||
m_poseParameters[i] = src.m_poseParameters[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( int i = 0; i < MAXSTUDIOBONECTRLS; i++ )
|
|
||||||
{
|
|
||||||
m_encodedControllers[i] = src.m_encodedControllers[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CSTRIKE_DLL
|
|
||||||
m_angRenderAngles = src.m_angRenderAngles;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Did player die this frame
|
// Did player die this frame
|
||||||
int m_fFlags;
|
int m_fFlags;
|
||||||
|
|
||||||
|
@ -149,9 +74,6 @@ struct LagRecord
|
||||||
float m_masterCycle;
|
float m_masterCycle;
|
||||||
float m_poseParameters[MAXSTUDIOPOSEPARAM];
|
float m_poseParameters[MAXSTUDIOPOSEPARAM];
|
||||||
float m_encodedControllers[MAXSTUDIOBONECTRLS];
|
float m_encodedControllers[MAXSTUDIOBONECTRLS];
|
||||||
#ifdef CSTRIKE_DLL
|
|
||||||
QAngle m_angRenderAngles;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -163,28 +85,28 @@ ConVar sv_unlag_debug( "sv_unlag_debug", "0" );
|
||||||
|
|
||||||
float g_flFractionScale = 0.95;
|
float g_flFractionScale = 0.95;
|
||||||
|
|
||||||
static void RestorePlayerTo( CBasePlayer* pPlayer, const Vector& vWantedPos )
|
static void RestorePlayerTo( CBaseEntity* pEntity, const Vector& vWantedPos )
|
||||||
{
|
{
|
||||||
// Try to move to the wanted position from our current position.
|
// Try to move to the wanted position from our current position.
|
||||||
trace_t tr;
|
trace_t tr;
|
||||||
VPROF_BUDGET( "RestorePlayerTo", "CLagCompensationManager" );
|
VPROF_BUDGET( "RestorePlayerTo", "CLagCompensationManager" );
|
||||||
UTIL_TraceEntity( pPlayer, vWantedPos, vWantedPos, MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr );
|
UTIL_TraceEntity( pEntity, vWantedPos, vWantedPos, MASK_PLAYERSOLID, pEntity->GetRefEHandle().Get(), COLLISION_GROUP_PLAYER_MOVEMENT, &tr );
|
||||||
if ( tr.startsolid || tr.allsolid )
|
if ( tr.startsolid || tr.allsolid )
|
||||||
{
|
{
|
||||||
if ( sv_unlag_debug.GetBool() )
|
if ( sv_unlag_debug.GetBool() )
|
||||||
{
|
{
|
||||||
DevMsg( "RestorePlayerTo() could not restore player position for client \"%s\" ( %.1f %.1f %.1f )\n",
|
DevMsg( "RestorePlayerTo() could not restore player position for client \"%i\" ( %.1f %.1f %.1f )\n",
|
||||||
pPlayer->GetPlayerName(),
|
pEntity->entindex(),
|
||||||
vWantedPos.x,
|
vWantedPos.x,
|
||||||
vWantedPos.y,
|
vWantedPos.y,
|
||||||
vWantedPos.z );
|
vWantedPos.z );
|
||||||
}
|
}
|
||||||
|
|
||||||
UTIL_TraceEntity( pPlayer,
|
UTIL_TraceEntity( pEntity,
|
||||||
pPlayer->GetAbsOrigin(),
|
pEntity->GetAbsOrigin(),
|
||||||
vWantedPos,
|
vWantedPos,
|
||||||
MASK_PLAYERSOLID,
|
MASK_PLAYERSOLID,
|
||||||
pPlayer,
|
pEntity->GetRefEHandle().Get(),
|
||||||
COLLISION_GROUP_PLAYER_MOVEMENT,
|
COLLISION_GROUP_PLAYER_MOVEMENT,
|
||||||
&tr );
|
&tr );
|
||||||
if ( tr.startsolid || tr.allsolid )
|
if ( tr.startsolid || tr.allsolid )
|
||||||
|
@ -200,8 +122,8 @@ static void RestorePlayerTo( CBasePlayer* pPlayer, const Vector& vWantedPos )
|
||||||
{
|
{
|
||||||
// We can get to a valid place, but not all the way back to where we were.
|
// We can get to a valid place, but not all the way back to where we were.
|
||||||
Vector vPos;
|
Vector vPos;
|
||||||
VectorLerp( pPlayer->GetAbsOrigin(), vWantedPos, tr.fraction * g_flFractionScale, vPos );
|
VectorLerp( pEntity->GetAbsOrigin(), vWantedPos, tr.fraction * g_flFractionScale, vPos );
|
||||||
UTIL_SetOrigin( pPlayer, vPos, true );
|
UTIL_SetOrigin( pEntity, vPos, true );
|
||||||
|
|
||||||
if ( sv_unlag_debug.GetBool() )
|
if ( sv_unlag_debug.GetBool() )
|
||||||
{
|
{
|
||||||
|
@ -212,7 +134,7 @@ static void RestorePlayerTo( CBasePlayer* pPlayer, const Vector& vWantedPos )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Cool, the player can go back to whence he came.
|
// Cool, the player can go back to whence he came.
|
||||||
UTIL_SetOrigin( pPlayer, tr.endpos, true );
|
UTIL_SetOrigin( pEntity, tr.endpos, true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,12 +150,12 @@ class CLagCompensationManager : public CAutoGameSystemPerFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
// IServerSystem stuff
|
// IServerSystem stuff
|
||||||
virtual void Shutdown()
|
void Shutdown() override
|
||||||
{
|
{
|
||||||
ClearHistory();
|
ClearHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void LevelShutdownPostEntity()
|
void LevelShutdownPostEntity() override
|
||||||
{
|
{
|
||||||
ClearHistory();
|
ClearHistory();
|
||||||
}
|
}
|
||||||
|
@ -241,12 +163,10 @@ class CLagCompensationManager : public CAutoGameSystemPerFrame,
|
||||||
// ILagCompensationManager stuff
|
// ILagCompensationManager stuff
|
||||||
|
|
||||||
// Called during player movement to set up/restore after lag compensation
|
// Called during player movement to set up/restore after lag compensation
|
||||||
void StartLagCompensation( CBasePlayer* player, CUserCmd* cmd );
|
void StartLagCompensation( CBasePlayer* player, CUserCmd* cmd ) override;
|
||||||
void FinishLagCompensation( CBasePlayer* player );
|
void FinishLagCompensation( CBasePlayer* player ) override;
|
||||||
virtual void TrackPlayerData( CBasePlayer* pPlayer );
|
void TrackEntities( void );
|
||||||
|
inline void BacktrackEntity( CBaseEntity* pEntity, int loopIndex, CUserCmd* cmd );
|
||||||
private:
|
|
||||||
void BacktrackPlayer( CBasePlayer* player, CUserCmd* cmd );
|
|
||||||
|
|
||||||
void ClearHistory()
|
void ClearHistory()
|
||||||
{
|
{
|
||||||
|
@ -256,11 +176,16 @@ class CLagCompensationManager : public CAutoGameSystemPerFrame,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FrameUpdatePostEntityThink() override
|
||||||
|
{
|
||||||
|
TrackEntities();
|
||||||
|
}
|
||||||
|
|
||||||
// keep a list of lag records for each entities
|
// keep a list of lag records for each entities
|
||||||
CUtlCircularBuffer< LagRecord, MAX_TICKS_SAVED > m_EntityTrack[MAX_EDICTS];
|
CUtlCircularBuffer< LagRecord, MAX_TICKS_SAVED > m_EntityTrack[MAX_EDICTS];
|
||||||
|
|
||||||
// Scratchpad for determining what needs to be restored
|
// Scratchpad for determining what needs to be restored
|
||||||
CBitVec< MAX_EDICTS > m_RestorePlayer;
|
CBitVec< MAX_EDICTS > m_RestoreEntity;
|
||||||
bool m_bNeedToRestore;
|
bool m_bNeedToRestore;
|
||||||
|
|
||||||
LagRecord m_RestoreData[MAX_EDICTS]; // entities data before we moved him back
|
LagRecord m_RestoreData[MAX_EDICTS]; // entities data before we moved him back
|
||||||
|
@ -273,40 +198,72 @@ ILagCompensationManager* lagcompensation = &g_LagCompensationManager;
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Called once per frame after all entities have had a chance to think
|
// Purpose: Called once per frame after all entities have had a chance to think
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CLagCompensationManager::TrackPlayerData( CBasePlayer* pPlayer )
|
void CLagCompensationManager::TrackEntities()
|
||||||
{
|
{
|
||||||
if ( ( gpGlobals->maxClients <= 1 ) || !sv_unlag.GetBool() )
|
LagRecord record;
|
||||||
|
|
||||||
|
if ( !sv_unlag.GetBool() )
|
||||||
{
|
{
|
||||||
ClearHistory();
|
ClearHistory();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VPROF_BUDGET( "TrackPlayerData", "CLagCompensationManager" );
|
VPROF_BUDGET( "TrackEntities", "CLagCompensationManager" );
|
||||||
|
|
||||||
// remove all records before that time:
|
for ( int i = 0; i < MAX_EDICTS; i++ )
|
||||||
auto track = &m_EntityTrack[pPlayer->entindex()];
|
|
||||||
|
|
||||||
// add new record to player track
|
|
||||||
LagRecord record;
|
|
||||||
|
|
||||||
record.m_fFlags = LC_NONE;
|
|
||||||
if ( pPlayer->IsAlive() )
|
|
||||||
{
|
{
|
||||||
record.m_fFlags |= LC_ALIVE;
|
CBaseEntity* pEntity = UTIL_EntityByIndex( i );
|
||||||
|
|
||||||
|
if ( !pEntity )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
record.m_flSimulationTime = pPlayer->GetSimulationTime();
|
// remove all records before that time:
|
||||||
record.m_flAnimTime = pPlayer->GetAnimTime();
|
auto track = &m_EntityTrack[i];
|
||||||
record.m_vecAngles = pPlayer->GetAbsAngles();
|
|
||||||
record.m_vecOrigin = pPlayer->GetAbsOrigin();
|
|
||||||
record.m_vecMinsPreScaled = pPlayer->CollisionProp()->OBBMinsPreScaled();
|
|
||||||
record.m_vecMaxsPreScaled = pPlayer->CollisionProp()->OBBMaxsPreScaled();
|
|
||||||
|
|
||||||
int layerCount = pPlayer->GetNumAnimOverlays();
|
// add new record to player track
|
||||||
|
|
||||||
|
record.m_fFlags = LC_NONE;
|
||||||
|
record.m_flSimulationTime = pEntity->GetSimulationTime();
|
||||||
|
record.m_flAnimTime = pEntity->GetAnimTime();
|
||||||
|
record.m_vecAngles = pEntity->GetAbsAngles();
|
||||||
|
record.m_vecOrigin = pEntity->GetAbsOrigin();
|
||||||
|
record.m_vecMinsPreScaled = pEntity->CollisionProp()->OBBMinsPreScaled();
|
||||||
|
record.m_vecMaxsPreScaled = pEntity->CollisionProp()->OBBMaxsPreScaled();
|
||||||
|
|
||||||
|
auto pAnim = dynamic_cast< CBaseAnimating* >( pEntity );
|
||||||
|
|
||||||
|
if ( pAnim )
|
||||||
|
{
|
||||||
|
record.m_masterSequence = pAnim->GetSequence();
|
||||||
|
record.m_masterCycle = pAnim->GetCycle();
|
||||||
|
|
||||||
|
CStudioHdr* hdr = pAnim->GetModelPtr();
|
||||||
|
|
||||||
|
if ( hdr )
|
||||||
|
{
|
||||||
|
for ( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
||||||
|
{
|
||||||
|
record.m_poseParameters[paramIndex] = pAnim->GetPoseParameterArray()[paramIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int boneIndex = 0; boneIndex < hdr->GetNumBoneControllers(); boneIndex++ )
|
||||||
|
{
|
||||||
|
record.m_encodedControllers[boneIndex] = pAnim->GetBoneControllerArray()[boneIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pAnimOverlay = dynamic_cast< CBaseAnimatingOverlay* >( pEntity );
|
||||||
|
|
||||||
|
if ( pAnimOverlay )
|
||||||
|
{
|
||||||
|
int layerCount = pAnimOverlay->GetNumAnimOverlays();
|
||||||
|
|
||||||
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
||||||
{
|
{
|
||||||
CAnimationLayer* currentLayer = pPlayer->GetAnimOverlay( layerIndex );
|
CAnimationLayer* currentLayer = pAnimOverlay->GetAnimOverlay( layerIndex );
|
||||||
if ( currentLayer )
|
if ( currentLayer )
|
||||||
{
|
{
|
||||||
record.m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle;
|
record.m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle;
|
||||||
|
@ -316,49 +273,20 @@ void CLagCompensationManager::TrackPlayerData( CBasePlayer* pPlayer )
|
||||||
record.m_layerRecords[layerIndex].m_flags = currentLayer->m_fFlags;
|
record.m_layerRecords[layerIndex].m_flags = currentLayer->m_fFlags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record.m_masterSequence = pPlayer->GetSequence();
|
|
||||||
record.m_masterCycle = pPlayer->GetCycle();
|
|
||||||
|
|
||||||
CStudioHdr* hdr = pPlayer->GetModelPtr();
|
|
||||||
|
|
||||||
if ( hdr )
|
|
||||||
{
|
|
||||||
for ( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
|
||||||
{
|
|
||||||
record.m_poseParameters[paramIndex] = pPlayer->GetPoseParameterArray()[paramIndex];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( hdr )
|
|
||||||
{
|
|
||||||
for ( int boneIndex = 0; boneIndex < hdr->GetNumBoneControllers(); boneIndex++ )
|
|
||||||
{
|
|
||||||
record.m_encodedControllers[boneIndex] = pPlayer->GetBoneControllerArray()[boneIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CSTRIKE_DLL
|
|
||||||
const auto csPlayer = ToCSPlayer( pPlayer );
|
|
||||||
|
|
||||||
if ( csPlayer )
|
|
||||||
{
|
|
||||||
record.m_angRenderAngles = csPlayer->m_angRenderAngles;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
track->Push( record );
|
track->Push( record );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Called during player movement to set up/restore after lag compensation
|
// Called during player movement to set up/restore after lag compensation
|
||||||
void CLagCompensationManager::StartLagCompensation( CBasePlayer* player, CUserCmd* cmd )
|
void CLagCompensationManager::StartLagCompensation( CBasePlayer* player, CUserCmd* cmd )
|
||||||
{
|
{
|
||||||
// Assume no players need to be restored
|
// Assume no players need to be restored
|
||||||
m_RestorePlayer.ClearAll();
|
m_RestoreEntity.ClearAll();
|
||||||
m_bNeedToRestore = false;
|
m_bNeedToRestore = false;
|
||||||
|
|
||||||
if ( !player->m_bLagCompensation // Player not wanting lag compensation
|
if ( !player->m_bLagCompensation // Player not wanting lag compensation
|
||||||
|| ( gpGlobals->maxClients <= 1 ) // no lag compensation in single player
|
|
||||||
|| !sv_unlag.GetBool() // disabled by server admin
|
|| !sv_unlag.GetBool() // disabled by server admin
|
||||||
|| player->IsBot() // not for bots
|
|| player->IsBot() // not for bots
|
||||||
|| player->IsObserver() // not for spectators
|
|| player->IsObserver() // not for spectators
|
||||||
|
@ -374,56 +302,62 @@ void CLagCompensationManager::StartLagCompensation( CBasePlayer* player, CUserCm
|
||||||
|
|
||||||
// Iterate all active players
|
// Iterate all active players
|
||||||
const CBitVec< MAX_EDICTS >* pEntityTransmitBits = engine->GetEntityTransmitBitsForClient( player->entindex() - 1 );
|
const CBitVec< MAX_EDICTS >* pEntityTransmitBits = engine->GetEntityTransmitBitsForClient( player->entindex() - 1 );
|
||||||
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
|
|
||||||
{
|
|
||||||
CBasePlayer* pPlayer = UTIL_PlayerByIndex( i );
|
|
||||||
|
|
||||||
if ( !pPlayer )
|
for ( int i = 0; i < MAX_EDICTS; i++ )
|
||||||
|
{
|
||||||
|
CBaseEntity* pEntity = UTIL_EntityByIndex( i );
|
||||||
|
|
||||||
|
if ( !pEntity )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't lag compensate yourself you loser...
|
// Don't lag compensate yourself you loser...
|
||||||
if ( player == pPlayer )
|
if ( player->entindex() == pEntity->entindex() )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom checks for if things should lag compensate (based on things like what team the player is on).
|
// Custom checks for if things should lag compensate (based on things like what team the player is on).
|
||||||
if ( !player->WantsLagCompensationOnEntity( pPlayer, cmd, pEntityTransmitBits ) )
|
if ( !player->WantsLagCompensationOnEntity( pEntity, cmd, pEntityTransmitBits ) )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move other player back in time
|
// Move other player back in time
|
||||||
BacktrackPlayer( pPlayer, cmd );
|
BacktrackEntity( pEntity, i, cmd );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* cmd )
|
inline void CLagCompensationManager::BacktrackEntity( CBaseEntity* pEntity, int loopindex, CUserCmd* cmd )
|
||||||
{
|
{
|
||||||
VPROF_BUDGET( "BacktrackPlayer", "CLagCompensationManager" );
|
VPROF_BUDGET( "BacktrackEntity", "CLagCompensationManager" );
|
||||||
|
|
||||||
Vector org;
|
Vector org;
|
||||||
Vector minsPreScaled;
|
Vector minsPreScaled;
|
||||||
Vector maxsPreScaled;
|
Vector maxsPreScaled;
|
||||||
QAngle ang;
|
QAngle ang;
|
||||||
#ifdef CSTRIKE_DLL
|
|
||||||
QAngle renderAngles;
|
|
||||||
#endif
|
|
||||||
LagRecord* prevRecordSim;
|
LagRecord* prevRecordSim;
|
||||||
LagRecord* recordSim;
|
LagRecord* recordSim;
|
||||||
LagRecord* recordAnim;
|
LagRecord* recordAnim;
|
||||||
|
|
||||||
#ifdef CSTRIKE_DLL
|
int pl_index = loopindex;
|
||||||
auto csPlayer = ToCSPlayer( pPlayer );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int pl_index = pPlayer->entindex();
|
|
||||||
|
|
||||||
float flTargetSimTime = cmd->simulationdata[pl_index].sim_time;
|
float flTargetSimTime = cmd->simulationdata[pl_index].sim_time;
|
||||||
float flTargetAnimTime = cmd->simulationdata[pl_index].anim_time;
|
float flTargetAnimTime = cmd->simulationdata[pl_index].anim_time;
|
||||||
|
|
||||||
|
// Somehow the client didn't care.
|
||||||
|
if (flTargetSimTime == 0)
|
||||||
|
{
|
||||||
|
if ( sv_unlag_debug.GetBool() )
|
||||||
|
{
|
||||||
|
DevMsg( "Client has refused to lag compensate this entity, probably already predicted ( %i )\n", pEntity->entindex() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// get track history of this player
|
// get track history of this player
|
||||||
auto track = &m_EntityTrack[pl_index];
|
auto track = &m_EntityTrack[pl_index];
|
||||||
bool foundSim = false;
|
bool foundSim = false;
|
||||||
|
@ -438,11 +372,6 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !( recordSim->m_fFlags & LC_ALIVE ) )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( flTargetSimTime == recordSim->m_flSimulationTime )
|
if ( flTargetSimTime == recordSim->m_flSimulationTime )
|
||||||
{
|
{
|
||||||
foundSim = true;
|
foundSim = true;
|
||||||
|
@ -457,33 +386,14 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; i < MAX_TICKS_SAVED; i++ )
|
if ( !foundSim )
|
||||||
{
|
|
||||||
recordAnim = track->Get( i );
|
|
||||||
|
|
||||||
if ( !recordAnim )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( recordAnim->m_flAnimTime == flTargetAnimTime )
|
|
||||||
{
|
|
||||||
foundAnim = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert( recordAnim );
|
|
||||||
Assert( recordSim );
|
|
||||||
|
|
||||||
if ( !foundAnim || !foundSim )
|
|
||||||
{
|
{
|
||||||
if ( sv_unlag_debug.GetBool() )
|
if ( sv_unlag_debug.GetBool() )
|
||||||
{
|
{
|
||||||
DevMsg( "No valid positions in history for BacktrackPlayer client ( %s )\n", pPlayer->GetPlayerName() );
|
DevMsg( "No valid simulation in history for BacktrackPlayer client ( %i )\n", pEntity->entindex() );
|
||||||
}
|
}
|
||||||
|
|
||||||
return; // that should never happen
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float fracSim = 0.0f;
|
float fracSim = 0.0f;
|
||||||
|
@ -522,40 +432,31 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c
|
||||||
LagRecord* restore = &m_RestoreData[pl_index];
|
LagRecord* restore = &m_RestoreData[pl_index];
|
||||||
LagRecord* change = &m_ChangeData[pl_index];
|
LagRecord* change = &m_ChangeData[pl_index];
|
||||||
|
|
||||||
QAngle angdiff = pPlayer->GetAbsAngles() - ang;
|
QAngle angdiff = pEntity->GetAbsAngles() - ang;
|
||||||
Vector orgdiff = pPlayer->GetAbsOrigin() - org;
|
Vector orgdiff = pEntity->GetAbsOrigin() - org;
|
||||||
|
|
||||||
// Always remember the pristine simulation time in case we need to restore it.
|
// Always remember the pristine simulation time in case we need to restore it.
|
||||||
restore->m_flSimulationTime = pPlayer->GetSimulationTime();
|
restore->m_flSimulationTime = pEntity->GetSimulationTime();
|
||||||
restore->m_flAnimTime = pPlayer->GetAnimTime();
|
restore->m_flAnimTime = pEntity->GetAnimTime();
|
||||||
|
|
||||||
#ifdef CSTRIKE_DLL
|
|
||||||
if ( csPlayer )
|
|
||||||
{
|
|
||||||
renderAngles = recordAnim->m_angRenderAngles;
|
|
||||||
restore->m_angRenderAngles = csPlayer->m_angRenderAngles;
|
|
||||||
csPlayer->m_angRenderAngles = renderAngles;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( angdiff.LengthSqr() > 0.0f )
|
if ( angdiff.LengthSqr() > 0.0f )
|
||||||
{
|
{
|
||||||
flags |= LC_ANGLES_CHANGED;
|
flags |= LC_ANGLES_CHANGED;
|
||||||
restore->m_vecAngles = pPlayer->GetAbsAngles();
|
restore->m_vecAngles = pEntity->GetAbsAngles();
|
||||||
pPlayer->SetAbsAngles( ang );
|
pEntity->SetAbsAngles( ang );
|
||||||
change->m_vecAngles = ang;
|
change->m_vecAngles = ang;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use absolute equality here
|
// Use absolute equality here
|
||||||
if ( minsPreScaled != pPlayer->CollisionProp()->OBBMinsPreScaled()
|
if ( minsPreScaled != pEntity->CollisionProp()->OBBMinsPreScaled()
|
||||||
|| maxsPreScaled != pPlayer->CollisionProp()->OBBMaxsPreScaled() )
|
|| maxsPreScaled != pEntity->CollisionProp()->OBBMaxsPreScaled() )
|
||||||
{
|
{
|
||||||
flags |= LC_SIZE_CHANGED;
|
flags |= LC_SIZE_CHANGED;
|
||||||
|
|
||||||
restore->m_vecMinsPreScaled = pPlayer->CollisionProp()->OBBMinsPreScaled();
|
restore->m_vecMinsPreScaled = pEntity->CollisionProp()->OBBMinsPreScaled();
|
||||||
restore->m_vecMaxsPreScaled = pPlayer->CollisionProp()->OBBMaxsPreScaled();
|
restore->m_vecMaxsPreScaled = pEntity->CollisionProp()->OBBMaxsPreScaled();
|
||||||
|
|
||||||
pPlayer->SetSize( minsPreScaled, maxsPreScaled );
|
pEntity->SetSize( minsPreScaled, maxsPreScaled );
|
||||||
|
|
||||||
change->m_vecMinsPreScaled = minsPreScaled;
|
change->m_vecMinsPreScaled = minsPreScaled;
|
||||||
change->m_vecMaxsPreScaled = maxsPreScaled;
|
change->m_vecMaxsPreScaled = maxsPreScaled;
|
||||||
|
@ -565,27 +466,130 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c
|
||||||
if ( orgdiff.LengthSqr() > 0.0f )
|
if ( orgdiff.LengthSqr() > 0.0f )
|
||||||
{
|
{
|
||||||
flags |= LC_ORIGIN_CHANGED;
|
flags |= LC_ORIGIN_CHANGED;
|
||||||
restore->m_vecOrigin = pPlayer->GetAbsOrigin();
|
restore->m_vecOrigin = pEntity->GetAbsOrigin();
|
||||||
pPlayer->SetAbsOrigin( org );
|
pEntity->SetAbsOrigin( org );
|
||||||
change->m_vecOrigin = org;
|
change->m_vecOrigin = org;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto pAnim = pEntity->GetBaseAnimating();
|
||||||
|
|
||||||
|
auto Finish = [&]()
|
||||||
|
{
|
||||||
|
if ( !flags )
|
||||||
|
{
|
||||||
|
return; // we didn't change anything
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set lag compensated player's times
|
||||||
|
pEntity->SetSimulationTime( flTargetSimTime );
|
||||||
|
pEntity->SetAnimTime( flTargetAnimTime );
|
||||||
|
|
||||||
|
if ( sv_lagflushbonecache.GetBool() )
|
||||||
|
{
|
||||||
|
if ( pAnim )
|
||||||
|
{
|
||||||
|
pAnim->InvalidateBoneCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_RestoreEntity.Set( pl_index ); // remember that we changed this player
|
||||||
|
m_bNeedToRestore = true; // we changed at least one player
|
||||||
|
restore->m_fFlags = flags; // we need to restore these flags
|
||||||
|
change->m_fFlags = flags; // we have changed these flags
|
||||||
|
};
|
||||||
|
|
||||||
|
// Somehow the client didn't care.
|
||||||
|
if (flTargetAnimTime == 0)
|
||||||
|
{
|
||||||
|
if ( sv_unlag_debug.GetBool() && !pAnim )
|
||||||
|
{
|
||||||
|
DevMsg( "Client has no anim time info ( %i )\n", pEntity->entindex() );
|
||||||
|
}
|
||||||
|
|
||||||
|
Finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pAnim )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < MAX_TICKS_SAVED; i++ )
|
||||||
|
{
|
||||||
|
recordAnim = track->Get( i );
|
||||||
|
|
||||||
|
if ( !recordAnim )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( recordAnim->m_flAnimTime == flTargetAnimTime )
|
||||||
|
{
|
||||||
|
foundAnim = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !foundAnim )
|
||||||
|
{
|
||||||
|
if ( sv_unlag_debug.GetBool() )
|
||||||
|
{
|
||||||
|
DevMsg( "Can't lag compensate, no history for animation fpr client entity ( %i )\n", pEntity->entindex() );
|
||||||
|
}
|
||||||
|
|
||||||
|
Finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pAnimOverlay = dynamic_cast< CBaseAnimatingOverlay* >( pEntity );
|
||||||
|
|
||||||
|
if ( pAnim && foundAnim )
|
||||||
|
{
|
||||||
// Sorry for the loss of the optimization for the case of people
|
// Sorry for the loss of the optimization for the case of people
|
||||||
// standing still, but you breathe even on the server.
|
// standing still, but you breathe even on the server.
|
||||||
// This is quicker than actually comparing all bazillion floats.
|
// This is quicker than actually comparing all bazillion floats.
|
||||||
flags |= LC_ANIMATION_CHANGED;
|
flags |= LC_ANIMATION_CHANGED;
|
||||||
restore->m_masterSequence = pPlayer->GetSequence();
|
restore->m_masterSequence = pAnim->GetSequence();
|
||||||
restore->m_masterCycle = pPlayer->GetCycle();
|
restore->m_masterCycle = pAnim->GetCycle();
|
||||||
|
|
||||||
pPlayer->SetSequence( recordAnim->m_masterSequence );
|
pAnim->SetSequence( recordAnim->m_masterSequence );
|
||||||
pPlayer->SetCycle( recordAnim->m_masterCycle );
|
pAnim->SetCycle( recordAnim->m_masterCycle );
|
||||||
|
|
||||||
|
// Now do pose parameters
|
||||||
|
CStudioHdr* hdr = pAnim->GetModelPtr();
|
||||||
|
|
||||||
|
if ( hdr )
|
||||||
|
{
|
||||||
|
for ( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
||||||
|
{
|
||||||
|
restore->m_poseParameters[paramIndex] = pAnim->GetPoseParameterArray()[paramIndex];
|
||||||
|
float poseParameter = recordAnim->m_poseParameters[paramIndex];
|
||||||
|
|
||||||
|
pAnim->SetPoseParameterRaw( paramIndex, poseParameter );
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= LC_POSE_PARAMS_CHANGED;
|
||||||
|
|
||||||
|
for ( int encIndex = 0; encIndex < hdr->GetNumBoneControllers(); encIndex++ )
|
||||||
|
{
|
||||||
|
restore->m_encodedControllers[encIndex] = pAnim->GetBoneControllerArray()[encIndex];
|
||||||
|
float encodedController = recordAnim->m_encodedControllers[encIndex];
|
||||||
|
|
||||||
|
pAnim->SetBoneControllerRaw( encIndex, encodedController );
|
||||||
|
}
|
||||||
|
|
||||||
|
flags |= LC_ENCD_CONS_CHANGED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pAnimOverlay && foundAnim )
|
||||||
|
{
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// Now do all the layers
|
// Now do all the layers
|
||||||
int layerCount = pPlayer->GetNumAnimOverlays();
|
int layerCount = pAnimOverlay->GetNumAnimOverlays();
|
||||||
|
|
||||||
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
||||||
{
|
{
|
||||||
CAnimationLayer* currentLayer = pPlayer->GetAnimOverlay( layerIndex );
|
CAnimationLayer* currentLayer = pAnimOverlay->GetAnimOverlay( layerIndex );
|
||||||
if ( currentLayer )
|
if ( currentLayer )
|
||||||
{
|
{
|
||||||
restore->m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle;
|
restore->m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle;
|
||||||
|
@ -602,52 +606,10 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flags |= LC_POSE_PARAMS_CHANGED;
|
flags |= LC_ANIM_OVERS_CHANGED;
|
||||||
|
|
||||||
// Now do pose parameters
|
|
||||||
CStudioHdr* hdr = pPlayer->GetModelPtr();
|
|
||||||
if ( hdr )
|
|
||||||
{
|
|
||||||
for ( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
|
||||||
{
|
|
||||||
restore->m_poseParameters[paramIndex] = pPlayer->GetPoseParameterArray()[paramIndex];
|
|
||||||
float poseParameter = recordAnim->m_poseParameters[paramIndex];
|
|
||||||
|
|
||||||
pPlayer->SetPoseParameterRaw( paramIndex, poseParameter );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
flags |= LC_ENCD_CONS_CHANGED;
|
Finish();
|
||||||
|
|
||||||
if ( hdr )
|
|
||||||
{
|
|
||||||
for ( int encIndex = 0; encIndex < hdr->GetNumBoneControllers(); encIndex++ )
|
|
||||||
{
|
|
||||||
restore->m_encodedControllers[encIndex] = pPlayer->GetBoneControllerArray()[encIndex];
|
|
||||||
float encodedController = recordAnim->m_encodedControllers[encIndex];
|
|
||||||
|
|
||||||
pPlayer->SetBoneControllerRaw( encIndex, encodedController );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !flags )
|
|
||||||
{
|
|
||||||
return; // we didn't change anything
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set lag compensated player's times
|
|
||||||
pPlayer->SetSimulationTime( flTargetSimTime );
|
|
||||||
pPlayer->SetAnimTime( flTargetAnimTime );
|
|
||||||
|
|
||||||
if ( sv_lagflushbonecache.GetBool() )
|
|
||||||
{
|
|
||||||
pPlayer->InvalidateBoneCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_RestorePlayer.Set( pl_index ); // remember that we changed this player
|
|
||||||
m_bNeedToRestore = true; // we changed at least one player
|
|
||||||
restore->m_fFlags = flags; // we need to restore these flags
|
|
||||||
change->m_fFlags = flags; // we have changed these flags
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLagCompensationManager::FinishLagCompensation( CBasePlayer* player )
|
void CLagCompensationManager::FinishLagCompensation( CBasePlayer* player )
|
||||||
|
@ -662,16 +624,16 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer* player )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate all active players
|
// Iterate all active players
|
||||||
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
|
for ( int i = 0; i < MAX_EDICTS; i++ )
|
||||||
{
|
{
|
||||||
if ( !m_RestorePlayer.Get( i ) )
|
if ( !m_RestoreEntity.Get( i ) )
|
||||||
{
|
{
|
||||||
// player wasn't changed by lag compensation
|
// player wasn't changed by lag compensation
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBasePlayer* pPlayer = UTIL_PlayerByIndex( i );
|
CBaseEntity* pEntity = UTIL_EntityByIndex( i );
|
||||||
if ( !pPlayer )
|
if ( !pEntity )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -679,58 +641,61 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer* player )
|
||||||
LagRecord* restore = &m_RestoreData[i];
|
LagRecord* restore = &m_RestoreData[i];
|
||||||
LagRecord* change = &m_ChangeData[i];
|
LagRecord* change = &m_ChangeData[i];
|
||||||
|
|
||||||
#ifdef CSTRIKE_DLL
|
|
||||||
auto csPlayer = ToCSPlayer( pPlayer );
|
|
||||||
|
|
||||||
if ( csPlayer )
|
|
||||||
{
|
|
||||||
csPlayer->m_angRenderAngles = restore->m_angRenderAngles;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( restore->m_fFlags & LC_SIZE_CHANGED )
|
if ( restore->m_fFlags & LC_SIZE_CHANGED )
|
||||||
{
|
{
|
||||||
// see if simulation made any changes, if no, then do the restore, otherwise,
|
pEntity->SetSize( restore->m_vecMinsPreScaled, restore->m_vecMaxsPreScaled );
|
||||||
// leave new values in
|
|
||||||
if ( pPlayer->CollisionProp()->OBBMinsPreScaled() == change->m_vecMinsPreScaled
|
|
||||||
&& pPlayer->CollisionProp()->OBBMaxsPreScaled() == change->m_vecMaxsPreScaled )
|
|
||||||
{
|
|
||||||
// Restore it
|
|
||||||
pPlayer->SetSize( restore->m_vecMinsPreScaled, restore->m_vecMaxsPreScaled );
|
|
||||||
}
|
|
||||||
#ifdef STAGING_ONLY
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Warning( "Should we really not restore the size?\n" );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( restore->m_fFlags & LC_ANGLES_CHANGED )
|
if ( restore->m_fFlags & LC_ANGLES_CHANGED )
|
||||||
{
|
{
|
||||||
if ( pPlayer->GetAbsAngles() == change->m_vecAngles )
|
pEntity->SetAbsAngles( restore->m_vecAngles );
|
||||||
{
|
|
||||||
pPlayer->SetAbsAngles( restore->m_vecAngles );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( restore->m_fFlags & LC_ORIGIN_CHANGED )
|
if ( restore->m_fFlags & LC_ORIGIN_CHANGED )
|
||||||
{
|
{
|
||||||
// Okay, let's see if we can do something reasonable with the change
|
pEntity->SetAbsOrigin( restore->m_vecOrigin );
|
||||||
Vector delta = pPlayer->GetAbsOrigin() - change->m_vecOrigin;
|
|
||||||
|
|
||||||
RestorePlayerTo( pPlayer, restore->m_vecOrigin + delta );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto pAnim = dynamic_cast< CBaseAnimating* >( pEntity );
|
||||||
|
auto pAnimOverlay = dynamic_cast< CBaseAnimatingOverlay* >( pEntity );
|
||||||
|
|
||||||
|
if ( pAnim )
|
||||||
|
{
|
||||||
if ( restore->m_fFlags & LC_ANIMATION_CHANGED )
|
if ( restore->m_fFlags & LC_ANIMATION_CHANGED )
|
||||||
{
|
{
|
||||||
pPlayer->SetSequence( restore->m_masterSequence );
|
pAnim->SetSequence( restore->m_masterSequence );
|
||||||
pPlayer->SetCycle( restore->m_masterCycle );
|
pAnim->SetCycle( restore->m_masterCycle );
|
||||||
|
}
|
||||||
|
|
||||||
|
CStudioHdr* hdr = pAnim->GetModelPtr();
|
||||||
|
|
||||||
|
if ( hdr )
|
||||||
|
{
|
||||||
|
if ( restore->m_fFlags & LC_POSE_PARAMS_CHANGED )
|
||||||
|
{
|
||||||
|
for ( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
||||||
|
{
|
||||||
|
pAnim->SetPoseParameterRaw( paramIndex, restore->m_poseParameters[paramIndex] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( restore->m_fFlags & LC_ENCD_CONS_CHANGED )
|
||||||
|
{
|
||||||
|
for ( int encIndex = 0; encIndex < hdr->GetNumBoneControllers(); encIndex++ )
|
||||||
|
{
|
||||||
|
pAnim->SetBoneControllerRaw( encIndex, restore->m_encodedControllers[encIndex] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( restore->m_fFlags & LC_ANIM_OVERS_CHANGED && pAnimOverlay )
|
||||||
|
{
|
||||||
|
int layerCount = pAnimOverlay->GetNumAnimOverlays();
|
||||||
|
|
||||||
int layerCount = pPlayer->GetNumAnimOverlays();
|
|
||||||
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
||||||
{
|
{
|
||||||
CAnimationLayer* currentLayer = pPlayer->GetAnimOverlay( layerIndex );
|
CAnimationLayer* currentLayer = pAnimOverlay->GetAnimOverlay( layerIndex );
|
||||||
if ( currentLayer )
|
if ( currentLayer )
|
||||||
{
|
{
|
||||||
currentLayer->m_flCycle = restore->m_layerRecords[layerIndex].m_cycle;
|
currentLayer->m_flCycle = restore->m_layerRecords[layerIndex].m_cycle;
|
||||||
|
@ -742,31 +707,7 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer* player )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CStudioHdr* hdr = pPlayer->GetModelPtr();
|
pEntity->SetSimulationTime( restore->m_flSimulationTime );
|
||||||
|
pEntity->SetAnimTime( restore->m_flAnimTime );
|
||||||
if ( restore->m_fFlags & LC_POSE_PARAMS_CHANGED )
|
|
||||||
{
|
|
||||||
if ( hdr )
|
|
||||||
{
|
|
||||||
for ( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
|
||||||
{
|
|
||||||
pPlayer->SetPoseParameterRaw( paramIndex, restore->m_poseParameters[paramIndex] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( restore->m_fFlags & LC_ENCD_CONS_CHANGED )
|
|
||||||
{
|
|
||||||
if ( hdr )
|
|
||||||
{
|
|
||||||
for ( int encIndex = 0; encIndex < hdr->GetNumBoneControllers(); encIndex++ )
|
|
||||||
{
|
|
||||||
pPlayer->SetBoneControllerRaw( encIndex, restore->m_encodedControllers[encIndex] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pPlayer->SetSimulationTime( restore->m_flSimulationTime );
|
|
||||||
pPlayer->SetAnimTime( restore->m_flAnimTime );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -542,8 +542,8 @@ void CCSPlayer::FireBullet(
|
||||||
QAngle angles[MAXSTUDIOBONES];
|
QAngle angles[MAXSTUDIOBONES];
|
||||||
int indexes[MAXSTUDIOBONES];
|
int indexes[MAXSTUDIOBONES];
|
||||||
|
|
||||||
auto angle = lagPlayer->GetRenderAngles();
|
auto angle = lagPlayer->GetAbsAngles();
|
||||||
auto position = lagPlayer->GetRenderOrigin();
|
auto position = lagPlayer->GetAbsOrigin();
|
||||||
|
|
||||||
event->SetFloat( "position_x", position.x );
|
event->SetFloat( "position_x", position.x );
|
||||||
event->SetFloat( "position_y", position.y );
|
event->SetFloat( "position_y", position.y );
|
||||||
|
|
|
@ -297,11 +297,6 @@ void FX_FireBullets(
|
||||||
pPlayer->StartNewBulletGroup();
|
pPlayer->StartNewBulletGroup();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined (CLIENT_DLL)
|
|
||||||
// Move other players back to history positions based on local player's lag
|
|
||||||
lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RandomSeed( iSeed ); // init random system with this seed
|
RandomSeed( iSeed ); // init random system with this seed
|
||||||
|
|
||||||
// Get accuracy displacement
|
// Get accuracy displacement
|
||||||
|
@ -340,8 +335,8 @@ void FX_FireBullets(
|
||||||
|
|
||||||
C_CSPlayer::HitboxRecord record;
|
C_CSPlayer::HitboxRecord record;
|
||||||
|
|
||||||
record.m_vecAbsOrigin = lagPlayer->GetRenderOrigin();
|
record.m_vecAbsOrigin = lagPlayer->GetAbsOrigin();
|
||||||
record.m_angRenderAngles = lagPlayer->m_angRenderAngles;
|
record.m_angAbsRotation = lagPlayer->GetAbsAngles();
|
||||||
|
|
||||||
record.m_nAttackerTickBase = pPlayer->m_nTickBase;
|
record.m_nAttackerTickBase = pPlayer->m_nTickBase;
|
||||||
record.m_flSimulationTime = lagPlayer->m_flInterpolatedSimulationTime;
|
record.m_flSimulationTime = lagPlayer->m_flInterpolatedSimulationTime;
|
||||||
|
@ -393,10 +388,6 @@ void FX_FireBullets(
|
||||||
x0 + x1[iBullet], y0 + y1[iBullet] );
|
x0 + x1[iBullet], y0 + y1[iBullet] );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined (CLIENT_DLL)
|
|
||||||
lagcompensation->FinishLagCompensation( pPlayer );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EndGroupingSounds();
|
EndGroupingSounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -235,14 +235,7 @@ void CKnife::SecondaryAttack()
|
||||||
CCSPlayer *pPlayer = GetPlayerOwner();
|
CCSPlayer *pPlayer = GetPlayerOwner();
|
||||||
if ( pPlayer && !pPlayer->m_bIsDefusing && !CSGameRules()->IsFreezePeriod() )
|
if ( pPlayer && !pPlayer->m_bIsDefusing && !CSGameRules()->IsFreezePeriod() )
|
||||||
{
|
{
|
||||||
#if !defined (CLIENT_DLL)
|
|
||||||
// Move other players back to history positions based on local player's lag
|
|
||||||
lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() );
|
|
||||||
#endif
|
|
||||||
SwingOrStab( true );
|
SwingOrStab( true );
|
||||||
#if !defined (CLIENT_DLL)
|
|
||||||
lagcompensation->FinishLagCompensation( pPlayer );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
wscript
2
wscript
|
@ -547,7 +547,7 @@ def configure(conf):
|
||||||
'/arch:SSE' if conf.env.DEST_CPU == 'x86' else '/arch:AVX',
|
'/arch:SSE' if conf.env.DEST_CPU == 'x86' else '/arch:AVX',
|
||||||
'/GF',
|
'/GF',
|
||||||
'/Gy',
|
'/Gy',
|
||||||
'/fp:fast',
|
'/fp:precise',
|
||||||
'/Zc:forScope',
|
'/Zc:forScope',
|
||||||
'/Zc:wchar_t',
|
'/Zc:wchar_t',
|
||||||
'/GR',
|
'/GR',
|
||||||
|
|
Loading…
Reference in a new issue