css_enhanced_waf/game/server/player_lagcompensation.cpp

660 lines
18 KiB
C++
Raw Normal View History

2020-04-22 18:56:21 +02:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
2020-04-22 18:56:21 +02:00
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "icvar.h"
#include "player.h"
#include "shareddefs.h"
#include "studio.h"
2020-04-22 18:56:21 +02:00
#include "usercmd.h"
#include "igamesystem.h"
#include "ilagcompensationmanager.h"
#include "inetchannelinfo.h"
#include "util.h"
2020-04-22 18:56:21 +02:00
#include "utllinkedlist.h"
#include "BaseAnimatingOverlay.h"
#include "tier0/vprof.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define LC_NONE 0
#define LC_ALIVE ( 1 << 0 )
2020-04-22 18:56:21 +02:00
#define LC_ORIGIN_CHANGED ( 1 << 8 )
#define LC_ANGLES_CHANGED ( 1 << 9 )
#define LC_SIZE_CHANGED ( 1 << 10 )
#define LC_ANIMATION_CHANGED ( 1 << 11 )
#define LC_POSE_PARAMS_CHANGED ( 1 << 12 )
#define LC_ENCD_CONS_CHANGED ( 1 << 13 )
2024-09-03 22:44:31 +02:00
#define LC_ANIM_OVERS_CHANGED ( 1 << 14 )
// Default to 1 second max.
2024-09-03 22:44:31 +02:00
#define MAX_TICKS_SAVED 1024
2020-04-22 18:56:21 +02:00
ConVar sv_unlag( "sv_unlag", "1", 0, "Enables entity lag compensation" );
// Enable by default to avoid some bugs.
ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "1", 0, "Flushes entity bone cache on lag compensation" );
2020-04-22 18:56:21 +02:00
//-----------------------------------------------------------------------------
// Purpose:
2020-04-22 18:56:21 +02:00
//-----------------------------------------------------------------------------
struct LayerRecord
{
int m_sequence;
float m_cycle;
float m_weight;
int m_order;
int m_flags;
};
2020-04-22 18:56:21 +02:00
struct LagRecord
{
public:
// Did entity die this frame
int m_fFlags;
2020-04-22 18:56:21 +02:00
// Player position, orientation and bbox
Vector m_vecOrigin;
QAngle m_vecAngles;
Vector m_vecMinsPreScaled;
Vector m_vecMaxsPreScaled;
float m_flSimulationTime;
float m_flAnimTime;
2020-04-22 18:56:21 +02:00
// 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[MAXSTUDIOPOSEPARAM];
float m_encodedControllers[MAXSTUDIOBONECTRLS];
2020-04-22 18:56:21 +02:00
};
//
// Try to take the entity from his current origin to vWantedPos.
// If it can't get there, leave the entity where he is.
//
2020-04-22 18:56:21 +02:00
2024-09-03 12:45:53 +02:00
ConVar sv_unlag_debug( "sv_unlag_debug", "0" );
2020-04-22 18:56:21 +02:00
//-----------------------------------------------------------------------------
// Purpose:
2020-04-22 18:56:21 +02:00
//-----------------------------------------------------------------------------
class CLagCompensationManager : public CAutoGameSystemPerFrame,
public ILagCompensationManager
2020-04-22 18:56:21 +02:00
{
public:
CLagCompensationManager( const char* name )
2020-04-22 18:56:21 +02:00
{
}
// IServerSystem stuff
2024-09-03 22:44:31 +02:00
void Shutdown() override
2020-04-22 18:56:21 +02:00
{
ClearHistory();
}
2024-09-03 22:44:31 +02:00
void LevelShutdownPostEntity() override
2020-04-22 18:56:21 +02:00
{
ClearHistory();
}
// ILagCompensationManager stuff
// Called during player movement to set up/restore after lag compensation
2024-09-03 22:44:31 +02:00
void StartLagCompensation( CBasePlayer* player, CUserCmd* cmd ) override;
void FinishLagCompensation( CBasePlayer* player ) override;
void TrackEntities( void );
inline void BacktrackEntity( CBaseEntity* pEntity, int loopIndex, CUserCmd* cmd );
2020-04-22 18:56:21 +02:00
void ClearHistory()
{
for ( int i = 0; i < MAX_EDICTS; i++ )
{
m_EntityTrack[i].Clear();
}
2020-04-22 18:56:21 +02:00
}
2024-09-03 22:44:31 +02:00
void FrameUpdatePostEntityThink() override
{
TrackEntities();
}
// keep a list of lag records for each entities
CUtlCircularBuffer< LagRecord, MAX_TICKS_SAVED > m_EntityTrack[MAX_EDICTS];
2020-04-22 18:56:21 +02:00
// Scratchpad for determining what needs to be restored
2024-09-03 22:44:31 +02:00
CBitVec< MAX_EDICTS > m_RestoreEntity;
bool m_bNeedToRestore;
2020-04-22 18:56:21 +02:00
LagRecord m_RestoreData[MAX_EDICTS]; // entities data before we moved him back
LagRecord m_ChangeData[MAX_EDICTS]; // entities data where we moved him back
2020-04-22 18:56:21 +02:00
};
static CLagCompensationManager g_LagCompensationManager( "CLagCompensationManager" );
ILagCompensationManager* lagcompensation = &g_LagCompensationManager;
2020-04-22 18:56:21 +02:00
//-----------------------------------------------------------------------------
// Purpose: Called once per frame after all entities have had a chance to think
//-----------------------------------------------------------------------------
2024-09-03 22:44:31 +02:00
void CLagCompensationManager::TrackEntities()
{
2024-09-03 22:44:31 +02:00
LagRecord record;
if ( !sv_unlag.GetBool() )
2020-04-22 18:56:21 +02:00
{
ClearHistory();
return;
}
2024-09-03 22:44:31 +02:00
VPROF_BUDGET( "TrackEntities", "CLagCompensationManager" );
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
for ( int i = 0; i < MAX_EDICTS; i++ )
{
CBaseEntity* pEntity = UTIL_EntityByIndex( i );
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
if ( !pEntity )
{
continue;
}
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
// remove all records before that time:
auto track = &m_EntityTrack[i];
2020-04-22 18:56:21 +02:00
// add new record to entity track
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
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();
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
auto pAnim = dynamic_cast< CBaseAnimating* >( pEntity );
if ( pAnim )
2020-04-22 18:56:21 +02:00
{
2024-09-03 22:44:31 +02:00
record.m_masterSequence = pAnim->GetSequence();
record.m_masterCycle = pAnim->GetCycle();
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
CStudioHdr* hdr = pAnim->GetModelPtr();
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
if ( hdr )
{
for ( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
{
record.m_poseParameters[paramIndex] = pAnim->GetPoseParameterArray()[paramIndex];
}
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
for ( int boneIndex = 0; boneIndex < hdr->GetNumBoneControllers(); boneIndex++ )
{
record.m_encodedControllers[boneIndex] = pAnim->GetBoneControllerArray()[boneIndex];
}
}
}
2024-09-03 22:44:31 +02:00
auto pAnimOverlay = dynamic_cast< CBaseAnimatingOverlay* >( pEntity );
if ( pAnimOverlay )
{
2024-09-03 22:44:31 +02:00
int layerCount = pAnimOverlay->GetNumAnimOverlays();
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
{
CAnimationLayer* currentLayer = pAnimOverlay->GetAnimOverlay( layerIndex );
if ( currentLayer )
{
record.m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle;
record.m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder;
record.m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence;
record.m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight;
record.m_layerRecords[layerIndex].m_flags = currentLayer->m_fFlags;
}
}
}
2024-09-03 22:44:31 +02:00
track->Push( record );
}
2020-04-22 18:56:21 +02:00
}
// Called during player movement to set up/restore after lag compensation
void CLagCompensationManager::StartLagCompensation( CBasePlayer* player, CUserCmd* cmd )
2020-04-22 18:56:21 +02:00
{
// Assume no entities need to be restored
2024-09-03 22:44:31 +02:00
m_RestoreEntity.ClearAll();
2020-04-22 18:56:21 +02:00
m_bNeedToRestore = false;
if ( !player->m_bLagCompensation // Player not wanting lag compensation
|| !sv_unlag.GetBool() // disabled by server admin
|| player->IsBot() // not for bots
|| player->IsObserver() // not for spectators
)
{
2020-04-22 18:56:21 +02:00
return;
}
2020-04-22 18:56:21 +02:00
// NOTE: Put this here so that it won't show up in single player mode.
VPROF_BUDGET( "StartLagCompensation", VPROF_BUDGETGROUP_OTHER_NETWORKING );
Q_memset( m_RestoreData, 0, sizeof( m_RestoreData ) );
Q_memset( m_ChangeData, 0, sizeof( m_ChangeData ) );
// Iterate all active entities
const CBitVec< MAX_EDICTS >* pEntityTransmitBits = engine->GetEntityTransmitBitsForClient( player->entindex() - 1 );
2024-09-03 22:44:31 +02:00
for ( int i = 0; i < MAX_EDICTS; i++ )
2020-04-22 18:56:21 +02:00
{
2024-09-03 22:44:31 +02:00
CBaseEntity* pEntity = UTIL_EntityByIndex( i );
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
if ( !pEntity )
2020-04-22 18:56:21 +02:00
{
continue;
}
// Don't lag compensate yourself you loser...
2024-09-03 22:44:31 +02:00
if ( player->entindex() == pEntity->entindex() )
2020-04-22 18:56:21 +02:00
{
continue;
}
// Custom checks for if things should lag compensate (based on things like what team the entity is on).
2024-09-03 22:44:31 +02:00
if ( !player->WantsLagCompensationOnEntity( pEntity, cmd, pEntityTransmitBits ) )
{
2020-04-22 18:56:21 +02:00
continue;
}
2020-04-22 18:56:21 +02:00
// Move other entity back in time
2024-09-03 22:44:31 +02:00
BacktrackEntity( pEntity, i, cmd );
2020-04-22 18:56:21 +02:00
}
}
2024-09-03 22:44:31 +02:00
inline void CLagCompensationManager::BacktrackEntity( CBaseEntity* pEntity, int loopindex, CUserCmd* cmd )
2020-04-22 18:56:21 +02:00
{
2024-09-03 22:44:31 +02:00
VPROF_BUDGET( "BacktrackEntity", "CLagCompensationManager" );
2024-08-31 06:36:59 +02:00
2020-04-22 18:56:21 +02:00
Vector org;
Vector minsPreScaled;
Vector maxsPreScaled;
QAngle ang;
2024-09-03 22:44:31 +02:00
2024-09-02 03:53:23 +02:00
LagRecord* prevRecordSim;
LagRecord* recordSim;
LagRecord* recordAnim;
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
int pl_index = loopindex;
2020-04-22 18:56:21 +02:00
float flTargetSimTime = cmd->simulationdata[pl_index].sim_time;
float flTargetAnimTime = cmd->simulationdata[pl_index].anim_time;
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
// Somehow the client didn't care.
if ( flTargetSimTime == 0 )
2024-09-03 22:44:31 +02:00
{
if ( sv_unlag_debug.GetBool() )
{
DevMsg( "Client has refused to lag compensate this entity, probably already predicted ( %i )\n",
pEntity->entindex() );
2024-09-03 22:44:31 +02:00
}
return;
}
// get track history of this entity
auto track = &m_EntityTrack[pl_index];
bool foundSim = false;
2024-09-03 12:45:53 +02:00
bool foundAnim = false;
2020-04-22 18:56:21 +02:00
for ( int i = 0; i < MAX_TICKS_SAVED; i++ )
2020-04-22 18:56:21 +02:00
{
recordSim = track->Get( i );
2020-04-22 18:56:21 +02:00
if ( !recordSim )
{
break;
}
2024-07-12 15:15:40 +02:00
if ( flTargetSimTime == recordSim->m_flSimulationTime )
2020-04-22 18:56:21 +02:00
{
2024-09-03 12:45:53 +02:00
foundSim = true;
break;
2020-04-22 18:56:21 +02:00
}
if ( recordSim->m_flSimulationTime < flTargetSimTime )
{
foundSim = true;
2024-09-02 03:53:23 +02:00
prevRecordSim = track->Get( i - 1 );
break;
}
}
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
if ( !foundSim )
2020-04-22 18:56:21 +02:00
{
if ( sv_unlag_debug.GetBool() )
{
2024-09-03 22:44:31 +02:00
DevMsg( "No valid simulation in history for BacktrackPlayer client ( %i )\n", pEntity->entindex() );
2020-04-22 18:56:21 +02:00
}
2024-09-03 22:44:31 +02:00
return;
2020-04-22 18:56:21 +02:00
}
float fracSim = 0.0f;
if ( prevRecordSim && ( recordSim->m_flSimulationTime < flTargetSimTime )
2024-09-02 03:53:23 +02:00
&& ( recordSim->m_flSimulationTime < prevRecordSim->m_flSimulationTime ) )
2020-04-22 18:56:21 +02:00
{
// we didn't find the exact time but have a valid previous record
// so interpolate between these two records;
Assert( prevRecordSim->m_flSimulationTime > recordSim->m_flSimulationTime );
2024-09-03 12:45:53 +02:00
Assert( flTargetSimTime < prevRecordSim->m_flSimulationTime );
2020-04-22 18:56:21 +02:00
// calc fraction between both records
fracSim = float( ( double( flTargetSimTime ) - double( recordSim->m_flSimulationTime ) )
2024-09-02 03:53:23 +02:00
/ ( double( prevRecordSim->m_flSimulationTime ) - double( recordSim->m_flSimulationTime ) ) );
2020-04-22 18:56:21 +02:00
Assert( fracSim > 0 && fracSim < 1 ); // should never extrapolate
2020-04-22 18:56:21 +02:00
2024-09-02 03:53:23 +02:00
ang = Lerp( fracSim, recordSim->m_vecAngles, prevRecordSim->m_vecAngles );
org = Lerp( fracSim, recordSim->m_vecOrigin, prevRecordSim->m_vecOrigin );
minsPreScaled = Lerp( fracSim, recordSim->m_vecMinsPreScaled, prevRecordSim->m_vecMinsPreScaled );
maxsPreScaled = Lerp( fracSim, recordSim->m_vecMaxsPreScaled, prevRecordSim->m_vecMaxsPreScaled );
2020-04-22 18:56:21 +02:00
}
else
{
// we found the exact record or no other record to interpolate with
// just copy these values since they are the best we have
org = recordSim->m_vecOrigin;
ang = recordSim->m_vecAngles;
minsPreScaled = recordSim->m_vecMinsPreScaled;
maxsPreScaled = recordSim->m_vecMaxsPreScaled;
2020-04-22 18:56:21 +02:00
}
// See if this represents a change for the entity
int flags = 0;
LagRecord* restore = &m_RestoreData[pl_index];
LagRecord* change = &m_ChangeData[pl_index];
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
QAngle angdiff = pEntity->GetAbsAngles() - ang;
Vector orgdiff = pEntity->GetAbsOrigin() - org;
2020-04-22 18:56:21 +02:00
// Always remember the pristine simulation time in case we need to restore it.
2024-09-03 22:44:31 +02:00
restore->m_flSimulationTime = pEntity->GetSimulationTime();
restore->m_flAnimTime = pEntity->GetAnimTime();
if ( angdiff.LengthSqr() > 0.0f )
2020-04-22 18:56:21 +02:00
{
flags |= LC_ANGLES_CHANGED;
2024-09-03 22:44:31 +02:00
restore->m_vecAngles = pEntity->GetAbsAngles();
pEntity->SetAbsAngles( ang );
2020-04-22 18:56:21 +02:00
change->m_vecAngles = ang;
}
// Use absolute equality here
2024-09-03 22:44:31 +02:00
if ( minsPreScaled != pEntity->CollisionProp()->OBBMinsPreScaled()
|| maxsPreScaled != pEntity->CollisionProp()->OBBMaxsPreScaled() )
2020-04-22 18:56:21 +02:00
{
flags |= LC_SIZE_CHANGED;
2024-09-03 22:44:31 +02:00
restore->m_vecMinsPreScaled = pEntity->CollisionProp()->OBBMinsPreScaled();
restore->m_vecMaxsPreScaled = pEntity->CollisionProp()->OBBMaxsPreScaled();
2024-09-03 22:44:31 +02:00
pEntity->SetSize( minsPreScaled, maxsPreScaled );
2020-04-22 18:56:21 +02:00
change->m_vecMinsPreScaled = minsPreScaled;
change->m_vecMaxsPreScaled = maxsPreScaled;
}
// Note, do origin at end since it causes a relink into the k/d tree
if ( orgdiff.LengthSqr() > 0.0f )
2020-04-22 18:56:21 +02:00
{
flags |= LC_ORIGIN_CHANGED;
2024-09-03 22:44:31 +02:00
restore->m_vecOrigin = pEntity->GetAbsOrigin();
pEntity->SetAbsOrigin( org );
2020-04-22 18:56:21 +02:00
change->m_vecOrigin = org;
}
2024-09-03 22:44:31 +02:00
auto pAnim = pEntity->GetBaseAnimating();
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
auto Finish = [&]()
{
if ( !flags )
{
return; // we didn't change anything
}
2020-04-22 18:56:21 +02:00
// Set lag compensated entity's times
2024-09-03 22:44:31 +02:00
pEntity->SetSimulationTime( flTargetSimTime );
pEntity->SetAnimTime( flTargetAnimTime );
if ( sv_lagflushbonecache.GetBool() )
{
if ( pAnim )
{
pAnim->InvalidateBoneCache();
}
}
m_RestoreEntity.Set( pl_index ); // remember that we changed this entity
m_bNeedToRestore = true; // we changed at least one entity
2024-09-03 22:44:31 +02:00
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 )
2020-04-22 18:56:21 +02:00
{
2024-09-03 22:44:31 +02:00
if ( sv_unlag_debug.GetBool() && !pAnim )
2020-04-22 18:56:21 +02:00
{
2024-09-03 22:44:31 +02:00
DevMsg( "Client has no anim time info ( %i )\n", pEntity->entindex() );
}
2024-09-03 22:44:31 +02:00
Finish();
return;
}
2024-09-03 22:44:31 +02:00
if ( pAnim )
{
2024-09-03 22:44:31 +02:00
for ( int i = 0; i < MAX_TICKS_SAVED; i++ )
{
2024-09-03 22:44:31 +02:00
recordAnim = track->Get( i );
if ( !recordAnim )
{
break;
}
2024-09-03 22:44:31 +02:00
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() );
}
2024-09-03 22:44:31 +02:00
Finish();
return;
}
2024-09-03 22:44:31 +02:00
auto pAnimOverlay = dynamic_cast< CBaseAnimatingOverlay* >( pEntity );
2024-09-03 22:44:31 +02:00
if ( pAnim && foundAnim )
{
2024-09-03 22:44:31 +02:00
// Sorry for the loss of the optimization for the case of people
// standing still, but you breathe even on the server.
// This is quicker than actually comparing all bazillion floats.
flags |= LC_ANIMATION_CHANGED;
restore->m_masterSequence = pAnim->GetSequence();
restore->m_masterCycle = pAnim->GetCycle();
pAnim->SetSequence( recordAnim->m_masterSequence );
pAnim->SetCycle( recordAnim->m_masterCycle );
// Now do pose parameters
CStudioHdr* hdr = pAnim->GetModelPtr();
if ( hdr )
{
2024-09-03 22:44:31 +02:00
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 );
}
2024-09-03 22:44:31 +02:00
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];
2024-09-03 22:44:31 +02:00
pAnim->SetBoneControllerRaw( encIndex, encodedController );
}
2024-09-03 22:44:31 +02:00
flags |= LC_ENCD_CONS_CHANGED;
}
}
2024-09-03 22:44:31 +02:00
if ( pAnimOverlay && foundAnim )
{
2024-09-03 22:44:31 +02:00
////////////////////////
// Now do all the layers
int layerCount = pAnimOverlay->GetNumAnimOverlays();
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
{
CAnimationLayer* currentLayer = pAnimOverlay->GetAnimOverlay( layerIndex );
if ( currentLayer )
{
restore->m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle;
restore->m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder;
restore->m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence;
restore->m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight;
restore->m_layerRecords[layerIndex].m_flags = currentLayer->m_fFlags;
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;
currentLayer->m_fFlags = recordAnim->m_layerRecords[layerIndex].m_flags;
}
}
2024-09-03 22:44:31 +02:00
flags |= LC_ANIM_OVERS_CHANGED;
}
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
Finish();
2020-04-22 18:56:21 +02:00
}
void CLagCompensationManager::FinishLagCompensation( CBasePlayer* player )
2020-04-22 18:56:21 +02:00
{
VPROF_BUDGET_FLAGS( "FinishLagCompensation",
VPROF_BUDGETGROUP_OTHER_NETWORKING,
BUDGETFLAG_CLIENT | BUDGETFLAG_SERVER );
2020-04-22 18:56:21 +02:00
if ( !m_bNeedToRestore )
{
return; // no entities was changed at all
}
2020-04-22 18:56:21 +02:00
// Iterate all active entities
for ( int i = 0; i < MAX_EDICTS; i++ )
2020-04-22 18:56:21 +02:00
{
2024-09-03 22:44:31 +02:00
if ( !m_RestoreEntity.Get( i ) )
2020-04-22 18:56:21 +02:00
{
// entity wasn't changed by lag compensation
2020-04-22 18:56:21 +02:00
continue;
}
2024-09-03 22:44:31 +02:00
CBaseEntity* pEntity = UTIL_EntityByIndex( i );
if ( !pEntity )
2020-04-22 18:56:21 +02:00
{
continue;
}
LagRecord* restore = &m_RestoreData[i];
LagRecord* change = &m_ChangeData[i];
2020-04-22 18:56:21 +02:00
if ( restore->m_fFlags & LC_SIZE_CHANGED )
{
2024-09-03 22:44:31 +02:00
pEntity->SetSize( restore->m_vecMinsPreScaled, restore->m_vecMaxsPreScaled );
2020-04-22 18:56:21 +02:00
}
if ( restore->m_fFlags & LC_ANGLES_CHANGED )
{
2024-09-03 22:44:31 +02:00
pEntity->SetAbsAngles( restore->m_vecAngles );
2020-04-22 18:56:21 +02:00
}
if ( restore->m_fFlags & LC_ORIGIN_CHANGED )
{
2024-09-03 22:44:31 +02:00
pEntity->SetAbsOrigin( restore->m_vecOrigin );
2020-04-22 18:56:21 +02:00
}
2024-09-03 22:44:31 +02:00
auto pAnim = dynamic_cast< CBaseAnimating* >( pEntity );
auto pAnimOverlay = dynamic_cast< CBaseAnimatingOverlay* >( pEntity );
2020-04-22 18:56:21 +02:00
2024-09-03 22:44:31 +02:00
if ( pAnim )
{
if ( restore->m_fFlags & LC_ANIMATION_CHANGED )
2020-04-22 18:56:21 +02:00
{
2024-09-03 22:44:31 +02:00
pAnim->SetSequence( restore->m_masterSequence );
pAnim->SetCycle( restore->m_masterCycle );
2020-04-22 18:56:21 +02:00
}
2024-09-03 22:44:31 +02:00
CStudioHdr* hdr = pAnim->GetModelPtr();
if ( hdr )
{
2024-09-03 22:44:31 +02:00
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 )
{
2024-09-03 22:44:31 +02:00
for ( int encIndex = 0; encIndex < hdr->GetNumBoneControllers(); encIndex++ )
{
pAnim->SetBoneControllerRaw( encIndex, restore->m_encodedControllers[encIndex] );
}
}
}
}
2024-09-03 22:44:31 +02:00
if ( restore->m_fFlags & LC_ANIM_OVERS_CHANGED && pAnimOverlay )
2020-04-22 18:56:21 +02:00
{
2024-09-03 22:44:31 +02:00
int layerCount = pAnimOverlay->GetNumAnimOverlays();
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
{
2024-09-03 22:44:31 +02:00
CAnimationLayer* currentLayer = pAnimOverlay->GetAnimOverlay( layerIndex );
if ( currentLayer )
{
2024-09-03 22:44:31 +02:00
currentLayer->m_flCycle = restore->m_layerRecords[layerIndex].m_cycle;
currentLayer->m_nOrder = restore->m_layerRecords[layerIndex].m_order;
currentLayer->m_nSequence = restore->m_layerRecords[layerIndex].m_sequence;
currentLayer->m_flWeight = restore->m_layerRecords[layerIndex].m_weight;
currentLayer->m_fFlags = restore->m_layerRecords[layerIndex].m_flags;
}
}
2020-04-22 18:56:21 +02:00
}
2024-09-03 22:44:31 +02:00
pEntity->SetSimulationTime( restore->m_flSimulationTime );
pEntity->SetAnimTime( restore->m_flAnimTime );
2020-04-22 18:56:21 +02:00
}
}