General fixes and improved lag comp performance
This commit is contained in:
parent
380f352adf
commit
11d345802e
17 changed files with 499 additions and 527 deletions
|
@ -1948,7 +1948,8 @@ void C_BaseAnimating::StandardBlendingRules( CStudioHdr *hdr, Vector pos[], Quat
|
|||
return;
|
||||
}
|
||||
|
||||
if (GetSequence() >= hdr->GetNumSeq() || GetSequence() == -1 )
|
||||
// CS weapons have this sometimes ...
|
||||
if ( GetSequence() >= hdr->GetNumSeq() || GetSequence() == -1 )
|
||||
{
|
||||
SetSequence( 0 );
|
||||
}
|
||||
|
@ -4928,7 +4929,8 @@ void C_BaseAnimating::Simulate()
|
|||
DelayedInitModelEffects();
|
||||
}
|
||||
|
||||
if ( gpGlobals->frametime != 0.0f )
|
||||
// TODO_ENHANCED: check if there's other stuff like this! This can break lag compensation.
|
||||
if ( gpGlobals->frametime != 0.0f && m_bClientSideAnimation )
|
||||
{
|
||||
DoAnimationEvents( GetModelPtr() );
|
||||
}
|
||||
|
|
|
@ -534,6 +534,7 @@ protected:
|
|||
float m_fadeMinDist;
|
||||
float m_fadeMaxDist;
|
||||
float m_flFadeScale;
|
||||
bool m_bClientSideAnimation;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -567,7 +568,6 @@ private:
|
|||
float m_flOldEncodedController[MAXSTUDIOBONECTRLS];
|
||||
|
||||
// Clientside animation
|
||||
bool m_bClientSideAnimation;
|
||||
bool m_bLastClientSideFrameReset;
|
||||
|
||||
int m_nNewSequenceParity;
|
||||
|
|
|
@ -124,40 +124,6 @@ CAddonInfo g_AddonInfo[] =
|
|||
{ "eholster", 0, "models/weapons/w_eq_eholster_elite.mdl", "models/weapons/w_eq_eholster.mdl" },
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------- //
|
||||
// Player animation event. Sent to the client when a player fires, jumps, reloads, etc..
|
||||
// -------------------------------------------------------------------------------- //
|
||||
|
||||
class C_TEPlayerAnimEvent : public C_BaseTempEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_TEPlayerAnimEvent, C_BaseTempEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual void PostDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
// Create the effect.
|
||||
C_CSPlayer *pPlayer = dynamic_cast< C_CSPlayer* >( m_hPlayer.Get() );
|
||||
if ( pPlayer && !pPlayer->IsDormant() )
|
||||
{
|
||||
pPlayer->DoAnimationEvent( (PlayerAnimEvent_t)m_iEvent.Get(), m_nData );
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
CNetworkHandle( CBasePlayer, m_hPlayer );
|
||||
CNetworkVar( int, m_iEvent );
|
||||
CNetworkVar( int, m_nData );
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_EVENT( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent, CTEPlayerAnimEvent );
|
||||
|
||||
BEGIN_RECV_TABLE_NOBASE( C_TEPlayerAnimEvent, DT_TEPlayerAnimEvent )
|
||||
RecvPropEHandle( RECVINFO( m_hPlayer ) ),
|
||||
RecvPropInt( RECVINFO( m_iEvent ) ),
|
||||
RecvPropInt( RECVINFO( m_nData ) )
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( C_CSPlayer )
|
||||
#ifdef CS_SHIELD_ENABLED
|
||||
DEFINE_PRED_FIELD( m_bShieldDrawn, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
|
@ -767,7 +733,7 @@ C_CSPlayer::C_CSPlayer() :
|
|||
{
|
||||
m_angEyeAngles.Init();
|
||||
|
||||
AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR );
|
||||
// AddVar( &m_angEyeAngles, &m_iv_angEyeAngles, LATCH_SIMULATION_VAR );
|
||||
|
||||
m_iLastAddonBits = m_iAddonBits = 0;
|
||||
m_iLastPrimaryAddon = m_iLastSecondaryAddon = WEAPON_NONE;
|
||||
|
@ -1689,6 +1655,11 @@ bool C_CSPlayer::Weapon_CanSwitchTo( CBaseCombatWeapon *pWeapon )
|
|||
|
||||
void C_CSPlayer::UpdateClientSideAnimation()
|
||||
{
|
||||
if ( !m_bClientSideAnimation )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We do this in a different order than the base class.
|
||||
// We need our cycle to be valid for when we call the playeranimstate update code,
|
||||
// or else it'll synchronize the upper body anims with the wrong cycle.
|
||||
|
@ -2074,6 +2045,8 @@ void C_CSPlayer::PlayReloadEffect()
|
|||
|
||||
void C_CSPlayer::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
|
||||
{
|
||||
// do nothing ... let server doing its animations.
|
||||
return;
|
||||
}
|
||||
|
||||
void C_CSPlayer::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
|
||||
|
@ -2332,9 +2305,9 @@ void C_CSPlayer::Simulate( void )
|
|||
|
||||
BaseClass::Simulate();
|
||||
|
||||
if ((cl_showhitboxes.GetInt() == 1 || cl_showhitboxes.GetInt() == 2) && !IsLocalPlayer())
|
||||
if ( ( cl_showhitboxes.GetInt() == 1 || cl_showhitboxes.GetInt() == 2 ) && !IsLocalPlayer() )
|
||||
{
|
||||
DrawClientHitboxes(gpGlobals->frametime, true);
|
||||
DrawClientHitboxes( gpGlobals->frametime, true );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1306,7 +1306,7 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo
|
|||
|
||||
for ( int i = 0; i < MAX_EDICTS; i++ )
|
||||
{
|
||||
cmd->simulationdata[i].m_bEntityExists = false;
|
||||
cmd->simulationdata[i].entityexists = false;
|
||||
}
|
||||
|
||||
// Send interpolated simulation time for lag compensation, let it also auto-vectorize this.
|
||||
|
@ -1319,9 +1319,9 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo
|
|||
continue;
|
||||
}
|
||||
|
||||
cmd->simulationdata[pEntity->index].m_flSimulationTime = pEntity->m_flInterpolatedSimulationTime;
|
||||
cmd->simulationdata[pEntity->index].m_flAnimTime = pEntity->m_flSimulationTime;
|
||||
cmd->simulationdata[pEntity->index].m_bEntityExists = true;
|
||||
cmd->simulationdata[pEntity->index].lerp_time = pEntity->m_flInterpolatedSimulationTime;
|
||||
cmd->simulationdata[pEntity->index].animated_sim_time = pEntity->m_flSimulationTime;
|
||||
cmd->simulationdata[pEntity->index].entityexists = true;
|
||||
}
|
||||
|
||||
#ifdef CSTRIKE_DLL
|
||||
|
|
|
@ -480,7 +480,7 @@ void CBaseAnimatingOverlay::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Q
|
|||
if ( m_pIk )
|
||||
{
|
||||
CIKContext auto_ik;
|
||||
auto_ik.Init( pStudioHdr, GetAbsAngles(), GetAbsOrigin(), gpGlobals->curtime, 0, boneMask );
|
||||
auto_ik.Init( pStudioHdr, GetAbsAngles(), GetAbsOrigin(), gpGlobals->curtime, m_iIKCounter, boneMask );
|
||||
boneSetup.CalcAutoplaySequences( pos, q, gpGlobals->curtime, &auto_ik );
|
||||
}
|
||||
else
|
||||
|
@ -490,7 +490,7 @@ void CBaseAnimatingOverlay::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Q
|
|||
|
||||
if ( pStudioHdr->numbonecontrollers() )
|
||||
{
|
||||
boneSetup.CalcBoneAdj( pos, q, GetEncodedControllerArray() );
|
||||
boneSetup.CalcBoneAdj( pos, q, GetBoneControllerArray() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2805,8 +2805,12 @@ CBoneCache *CBaseAnimating::GetBoneCache( void )
|
|||
CStudioHdr *pStudioHdr = GetModelPtr( );
|
||||
Assert(pStudioHdr);
|
||||
|
||||
// Use this for lag compensation
|
||||
float oldcurtime = gpGlobals->curtime;
|
||||
gpGlobals->curtime = m_flSimulationTime;
|
||||
|
||||
CBoneCache *pcache = Studio_GetBoneCache( m_boneCacheHandle );
|
||||
int boneMask = BONE_USED_BY_HITBOX | BONE_USED_BY_ATTACHMENT;
|
||||
int boneMask = BONE_USED_BY_ANYTHING;
|
||||
|
||||
// TF queries these bones to position weapons when players are killed
|
||||
#if defined( TF_DLL )
|
||||
|
@ -2814,8 +2818,10 @@ CBoneCache *CBaseAnimating::GetBoneCache( void )
|
|||
#endif
|
||||
if ( pcache )
|
||||
{
|
||||
if ( pcache->IsValid( gpGlobals->curtime ) && (pcache->m_boneMask & boneMask) == boneMask && pcache->m_timeValid <= gpGlobals->curtime)
|
||||
// Only validate for current time.
|
||||
if ( (pcache->m_boneMask & boneMask) == boneMask && pcache->m_timeValid == gpGlobals->curtime)
|
||||
{
|
||||
gpGlobals->curtime = oldcurtime;
|
||||
// Msg("%s:%s:%s (%x:%x:%8.4f) cache\n", GetClassname(), GetDebugName(), STRING(GetModelName()), boneMask, pcache->m_boneMask, pcache->m_timeValid );
|
||||
// in memory and still valid, use it!
|
||||
return pcache;
|
||||
|
@ -2849,6 +2855,8 @@ CBoneCache *CBaseAnimating::GetBoneCache( void )
|
|||
pcache = Studio_GetBoneCache( m_boneCacheHandle );
|
||||
}
|
||||
Assert(pcache);
|
||||
|
||||
gpGlobals->curtime = oldcurtime;
|
||||
return pcache;
|
||||
}
|
||||
|
||||
|
@ -3035,7 +3043,7 @@ void CBaseAnimating::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaterni
|
|||
if ( m_pIk )
|
||||
{
|
||||
CIKContext auto_ik;
|
||||
auto_ik.Init( pStudioHdr, GetAbsAngles(), GetAbsOrigin(), gpGlobals->curtime, 0, boneMask );
|
||||
auto_ik.Init( pStudioHdr, GetAbsAngles(), GetAbsOrigin(), gpGlobals->curtime, m_iIKCounter, boneMask );
|
||||
boneSetup.CalcAutoplaySequences( pos, q, gpGlobals->curtime, &auto_ik );
|
||||
}
|
||||
else
|
||||
|
@ -3045,7 +3053,7 @@ void CBaseAnimating::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaterni
|
|||
|
||||
if ( pStudioHdr->numbonecontrollers() )
|
||||
{
|
||||
boneSetup.CalcBoneAdj( pos, q, GetEncodedControllerArray() );
|
||||
boneSetup.CalcBoneAdj( pos, q, GetBoneControllerArray() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -325,7 +325,7 @@ public:
|
|||
CBaseEntity *GetLightingOrigin();
|
||||
|
||||
const float* GetPoseParameterArray() { return m_flPoseParameter.Base(); }
|
||||
const float *GetEncodedControllerArray() { return m_flEncodedController.Base(); }
|
||||
const float *GetBoneControllerArray() { return m_flEncodedController.Base(); }
|
||||
|
||||
void BuildMatricesWithBoneMerge( const CStudioHdr *pStudioHdr, const QAngle& angles,
|
||||
const Vector& origin, const Vector pos[MAXSTUDIOBONES],
|
||||
|
|
|
@ -240,45 +240,6 @@ IMPLEMENT_SERVERCLASS_ST_NOBASE( CCSRagdoll, DT_CSRagdoll )
|
|||
SendPropInt( SENDINFO( m_bClientSideAnimation ), 1, SPROP_UNSIGNED ),
|
||||
END_SEND_TABLE()
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------- //
|
||||
// Player animation event. Sent to the client when a player fires, jumps, reloads, etc..
|
||||
// -------------------------------------------------------------------------------- //
|
||||
|
||||
class CTEPlayerAnimEvent : public CBaseTempEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CTEPlayerAnimEvent, CBaseTempEntity );
|
||||
DECLARE_SERVERCLASS();
|
||||
|
||||
CTEPlayerAnimEvent( const char *name ) : CBaseTempEntity( name )
|
||||
{
|
||||
}
|
||||
|
||||
CNetworkHandle( CBasePlayer, m_hPlayer );
|
||||
CNetworkVar( int, m_iEvent );
|
||||
CNetworkVar( int, m_nData );
|
||||
};
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST_NOBASE( CTEPlayerAnimEvent, DT_TEPlayerAnimEvent )
|
||||
SendPropEHandle( SENDINFO( m_hPlayer ) ),
|
||||
SendPropInt( SENDINFO( m_iEvent ), Q_log2( PLAYERANIMEVENT_COUNT ) + 1, SPROP_UNSIGNED ),
|
||||
SendPropInt( SENDINFO( m_nData ), 32 )
|
||||
END_SEND_TABLE()
|
||||
|
||||
static CTEPlayerAnimEvent g_TEPlayerAnimEvent( "PlayerAnimEvent" );
|
||||
|
||||
void TE_PlayerAnimEvent( CBasePlayer *pPlayer, PlayerAnimEvent_t event, int nData )
|
||||
{
|
||||
CPVSFilter filter( (const Vector&)pPlayer->EyePosition() );
|
||||
|
||||
g_TEPlayerAnimEvent.m_hPlayer = pPlayer;
|
||||
g_TEPlayerAnimEvent.m_iEvent = event;
|
||||
g_TEPlayerAnimEvent.m_nData = nData;
|
||||
g_TEPlayerAnimEvent.Create( filter, 0 );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Filters updates to a variable so that only non-local players see
|
||||
// the changes. This is so we can send a low-res origin to non-local players
|
||||
|
@ -6664,7 +6625,6 @@ void CCSPlayer::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
|
|||
else
|
||||
{
|
||||
m_PlayerAnimState->DoAnimationEvent( event, nData );
|
||||
TE_PlayerAnimEvent( this, event, nData ); // Send to any clients who can see this guy.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -782,7 +782,7 @@ protected:
|
|||
|
||||
void PushawayThink();
|
||||
|
||||
private:
|
||||
public:
|
||||
|
||||
ICSPlayerAnimState *m_PlayerAnimState;
|
||||
|
||||
|
|
|
@ -22,8 +22,9 @@ abstract_class ILagCompensationManager
|
|||
public:
|
||||
// Called during player movement to set up/restore after lag compensation
|
||||
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;
|
||||
|
|
|
@ -350,7 +350,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
|||
g_pGameMovement->StartTrackPredictionErrors( player );
|
||||
|
||||
// Prevent hacked clients from sending us invalid view angles to try to get leaf server code to crash
|
||||
if ( !ucmd->viewangles.IsValid() || !IsEntityQAngleReasonable(ucmd->viewangles) )
|
||||
if ( !ucmd->viewangles.IsValid() || !IsEntityQAngleReasonable( ucmd->viewangles ) )
|
||||
{
|
||||
ucmd->viewangles = vec3_angle;
|
||||
}
|
||||
|
@ -363,9 +363,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
|||
{
|
||||
// If no clipping and cheats enabled and noclipduring game enabled, then leave
|
||||
// forwardmove and angles stuff in usercmd
|
||||
if ( player->GetMoveType() == MOVETYPE_NOCLIP &&
|
||||
sv_cheats->GetBool() &&
|
||||
sv_noclipduringpause.GetBool() )
|
||||
if ( player->GetMoveType() == MOVETYPE_NOCLIP && sv_cheats->GetBool() && sv_noclipduringpause.GetBool() )
|
||||
{
|
||||
gpGlobals->frametime = TICK_INTERVAL;
|
||||
}
|
||||
|
@ -385,7 +383,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
|||
// Do weapon selection
|
||||
if ( ucmd->weaponselect != 0 )
|
||||
{
|
||||
CBaseCombatWeapon *weapon = dynamic_cast< CBaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) );
|
||||
CBaseCombatWeapon* weapon = dynamic_cast< CBaseCombatWeapon* >( CBaseEntity::Instance( ucmd->weaponselect ) );
|
||||
if ( weapon )
|
||||
{
|
||||
VPROF( "player->SelectItem()" );
|
||||
|
@ -393,13 +391,14 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
|||
}
|
||||
}
|
||||
|
||||
IServerVehicle *pVehicle = player->GetVehicle();
|
||||
IServerVehicle* pVehicle = player->GetVehicle();
|
||||
|
||||
// Latch in impulse.
|
||||
if ( ucmd->impulse )
|
||||
{
|
||||
// Discard impulse commands unless the vehicle allows them.
|
||||
// FIXME: UsingStandardWeapons seems like a bad filter for this. The flashlight is an impulse command, for example.
|
||||
// FIXME: UsingStandardWeapons seems like a bad filter for this. The flashlight is an impulse command, for
|
||||
// example.
|
||||
if ( !pVehicle || player->UsingStandardWeaponsInVehicle() )
|
||||
{
|
||||
player->m_nImpulse = ucmd->impulse;
|
||||
|
@ -420,7 +419,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
|||
{
|
||||
player->pl.v_angle = ucmd->viewangles;
|
||||
}
|
||||
else if( player->pl.fixangle == FIXANGLE_RELATIVE )
|
||||
else if ( player->pl.fixangle == FIXANGLE_RELATIVE )
|
||||
{
|
||||
player->pl.v_angle = ucmd->viewangles + player->pl.anglechange;
|
||||
}
|
||||
|
@ -468,4 +467,6 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
|||
{
|
||||
player->m_nTickBase++;
|
||||
}
|
||||
|
||||
lagcompensation->TrackPlayerData( player );
|
||||
}
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "bone_setup.h"
|
||||
#include "cbase.h"
|
||||
#include "icvar.h"
|
||||
#include "player.h"
|
||||
#include "shareddefs.h"
|
||||
#include "studio.h"
|
||||
#include "usercmd.h"
|
||||
#include "igamesystem.h"
|
||||
#include "ilagcompensationmanager.h"
|
||||
|
@ -21,19 +23,19 @@
|
|||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define LC_NONE 0
|
||||
#define LC_ALIVE (1<<0)
|
||||
#define LC_ALIVE ( 1 << 0 )
|
||||
|
||||
#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)
|
||||
#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 )
|
||||
|
||||
#define MAX_TICKS_SAVED 2048
|
||||
|
||||
ConVar sv_unlag( "sv_unlag", "1", FCVAR_DEVELOPMENTONLY, "Enables player lag compensation" );
|
||||
ConVar sv_maxunlag( "sv_maxunlag", "1.0", FCVAR_DEVELOPMENTONLY, "Maximum lag compensation in seconds", true, 0.0f, true, 1.0f );
|
||||
ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "0", FCVAR_DEVELOPMENTONLY, "Flushes entity bone cache on lag compensation" );
|
||||
ConVar sv_unlag_fixstuck( "sv_unlag_fixstuck", "0", FCVAR_DEVELOPMENTONLY, "Disallow backtracking a player for lag compensation if it will cause them to become stuck" );
|
||||
ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "0", 0, "Flushes entity bone cache on lag compensation" );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
|
@ -41,10 +43,10 @@ ConVar sv_unlag_fixstuck( "sv_unlag_fixstuck", "0", FCVAR_DEVELOPMENTONLY, "Disa
|
|||
|
||||
struct LagRecord
|
||||
{
|
||||
public:
|
||||
public:
|
||||
LagRecord()
|
||||
{
|
||||
m_fFlags = 0;
|
||||
m_fFlags = LC_NONE;
|
||||
m_vecOrigin.Init();
|
||||
m_vecAngles.Init();
|
||||
m_vecMinsPreScaled.Init();
|
||||
|
@ -54,14 +56,19 @@ public:
|
|||
m_masterSequence = 0;
|
||||
m_masterCycle = 0;
|
||||
|
||||
for (int i = 0; i < MAX_LAYER_RECORDS; i++)
|
||||
for ( int layerIndex = 0; layerIndex < MAX_LAYER_RECORDS; ++layerIndex )
|
||||
{
|
||||
m_poseParameters[i] = -1;
|
||||
m_layerRecords[layerIndex] = {};
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_ENCODED_CONTROLLERS; i++)
|
||||
for ( int i = 0; i < MAXSTUDIOPOSEPARAM; i++ )
|
||||
{
|
||||
m_encodedControllers[i] = -1;
|
||||
m_poseParameters[i] = 0;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < MAXSTUDIOBONECTRLS; i++ )
|
||||
{
|
||||
m_encodedControllers[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,19 +81,21 @@ public:
|
|||
m_vecMaxsPreScaled = src.m_vecMaxsPreScaled;
|
||||
m_flSimulationTime = src.m_flSimulationTime;
|
||||
m_flAnimTime = src.m_flAnimTime;
|
||||
for( int layerIndex = 0; layerIndex < MAX_LAYER_RECORDS; ++layerIndex )
|
||||
|
||||
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 < MAX_LAYER_RECORDS; i++)
|
||||
for ( int i = 0; i < MAXSTUDIOPOSEPARAM; i++ )
|
||||
{
|
||||
m_poseParameters[i] = src.m_poseParameters[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_LAYER_RECORDS; i++)
|
||||
for ( int i = 0; i < MAXSTUDIOBONECTRLS; i++ )
|
||||
{
|
||||
m_encodedControllers[i] = src.m_encodedControllers[i];
|
||||
}
|
||||
|
@ -108,11 +117,10 @@ public:
|
|||
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_poseParameters[MAXSTUDIOPOSEPARAM];
|
||||
float m_encodedControllers[MAXSTUDIOBONECTRLS];
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Try to take the player from his current origin to vWantedPos.
|
||||
// If it can't get there, leave the player where he is.
|
||||
|
@ -121,7 +129,8 @@ public:
|
|||
ConVar sv_unlag_debug( "sv_unlag_debug", "0", FCVAR_GAMEDLL | FCVAR_DEVELOPMENTONLY );
|
||||
|
||||
float g_flFractionScale = 0.95;
|
||||
static void RestorePlayerTo( CBasePlayer *pPlayer, const Vector &vWantedPos )
|
||||
|
||||
static void RestorePlayerTo( CBasePlayer* pPlayer, const Vector& vWantedPos )
|
||||
{
|
||||
// Try to move to the wanted position from our current position.
|
||||
trace_t tr;
|
||||
|
@ -132,28 +141,41 @@ static void RestorePlayerTo( CBasePlayer *pPlayer, const Vector &vWantedPos )
|
|||
if ( sv_unlag_debug.GetBool() )
|
||||
{
|
||||
DevMsg( "RestorePlayerTo() could not restore player position for client \"%s\" ( %.1f %.1f %.1f )\n",
|
||||
pPlayer->GetPlayerName(), vWantedPos.x, vWantedPos.y, vWantedPos.z );
|
||||
pPlayer->GetPlayerName(),
|
||||
vWantedPos.x,
|
||||
vWantedPos.y,
|
||||
vWantedPos.z );
|
||||
}
|
||||
|
||||
UTIL_TraceEntity( pPlayer, pPlayer->GetLocalOrigin(), vWantedPos, MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr );
|
||||
UTIL_TraceEntity( pPlayer,
|
||||
pPlayer->GetAbsOrigin(),
|
||||
vWantedPos,
|
||||
MASK_PLAYERSOLID,
|
||||
pPlayer,
|
||||
COLLISION_GROUP_PLAYER_MOVEMENT,
|
||||
&tr );
|
||||
if ( tr.startsolid || tr.allsolid )
|
||||
{
|
||||
// In this case, the guy got stuck back wherever we lag compensated him to. Nasty.
|
||||
|
||||
if ( sv_unlag_debug.GetBool() )
|
||||
{
|
||||
DevMsg( " restore failed entirely\n" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can get to a valid place, but not all the way back to where we were.
|
||||
Vector vPos;
|
||||
VectorLerp( pPlayer->GetLocalOrigin(), vWantedPos, tr.fraction * g_flFractionScale, vPos );
|
||||
VectorLerp( pPlayer->GetAbsOrigin(), vWantedPos, tr.fraction * g_flFractionScale, vPos );
|
||||
UTIL_SetOrigin( pPlayer, vPos, true );
|
||||
|
||||
if ( sv_unlag_debug.GetBool() )
|
||||
{
|
||||
DevMsg( " restore got most of the way\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cool, the player can go back to whence he came.
|
||||
|
@ -161,14 +183,14 @@ static void RestorePlayerTo( CBasePlayer *pPlayer, const Vector &vWantedPos )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CLagCompensationManager : public CAutoGameSystemPerFrame, public ILagCompensationManager
|
||||
class CLagCompensationManager : public CAutoGameSystemPerFrame,
|
||||
public ILagCompensationManager
|
||||
{
|
||||
public:
|
||||
CLagCompensationManager( char const *name ) : CAutoGameSystemPerFrame( name )
|
||||
public:
|
||||
CLagCompensationManager( const char* name )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -183,105 +205,58 @@ public:
|
|||
ClearHistory();
|
||||
}
|
||||
|
||||
// called after entities think
|
||||
virtual void FrameUpdatePostEntityThink();
|
||||
|
||||
// ILagCompensationManager stuff
|
||||
|
||||
// Called during player movement to set up/restore after lag compensation
|
||||
void StartLagCompensation( CBasePlayer *player, CUserCmd *cmd );
|
||||
void FinishLagCompensation( CBasePlayer *player );
|
||||
void StartLagCompensation( CBasePlayer* player, CUserCmd* cmd );
|
||||
void FinishLagCompensation( CBasePlayer* player );
|
||||
virtual void TrackPlayerData( CBasePlayer* pPlayer );
|
||||
|
||||
private:
|
||||
virtual void BacktrackPlayer( CBasePlayer *player, CUserCmd *cmd );
|
||||
private:
|
||||
void BacktrackPlayer( CBasePlayer* player, CUserCmd* cmd );
|
||||
|
||||
void ClearHistory()
|
||||
{
|
||||
for ( int i=0; i<MAX_PLAYERS; i++ )
|
||||
m_PlayerTrack[i].Purge();
|
||||
for ( int i = 0; i < MAX_EDICTS; i++ )
|
||||
{
|
||||
m_EntityTrack[i].Clear();
|
||||
}
|
||||
}
|
||||
|
||||
// keep a list of lag records for each player
|
||||
CUtlFixedLinkedList< LagRecord > m_PlayerTrack[ MAX_PLAYERS ];
|
||||
// keep a list of lag records for each entities
|
||||
CUtlCircularBuffer< LagRecord, MAX_TICKS_SAVED > m_EntityTrack[MAX_EDICTS];
|
||||
|
||||
// Scratchpad for determining what needs to be restored
|
||||
CBitVec<MAX_PLAYERS> m_RestorePlayer;
|
||||
CBitVec< MAX_EDICTS > m_RestorePlayer;
|
||||
bool m_bNeedToRestore;
|
||||
|
||||
LagRecord m_RestoreData[ MAX_PLAYERS ]; // player data before we moved him back
|
||||
LagRecord m_ChangeData[ MAX_PLAYERS ]; // player data where we moved him back
|
||||
|
||||
CBasePlayer *m_pCurrentPlayer; // The player we are doing lag compensation for
|
||||
LagRecord m_RestoreData[MAX_EDICTS]; // entities data before we moved him back
|
||||
LagRecord m_ChangeData[MAX_EDICTS]; // entities data where we moved him back
|
||||
};
|
||||
|
||||
static CLagCompensationManager g_LagCompensationManager( "CLagCompensationManager" );
|
||||
ILagCompensationManager *lagcompensation = &g_LagCompensationManager;
|
||||
|
||||
ILagCompensationManager* lagcompensation = &g_LagCompensationManager;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called once per frame after all entities have had a chance to think
|
||||
//-----------------------------------------------------------------------------
|
||||
void CLagCompensationManager::FrameUpdatePostEntityThink()
|
||||
void CLagCompensationManager::TrackPlayerData( CBasePlayer* pPlayer )
|
||||
{
|
||||
if ( (gpGlobals->maxClients <= 1) || !sv_unlag.GetBool() )
|
||||
if ( ( gpGlobals->maxClients <= 1 ) || !sv_unlag.GetBool() )
|
||||
{
|
||||
ClearHistory();
|
||||
return;
|
||||
}
|
||||
|
||||
VPROF_BUDGET( "FrameUpdatePostEntityThink", "CLagCompensationManager" );
|
||||
VPROF_BUDGET( "TrackPlayerData", "CLagCompensationManager" );
|
||||
|
||||
// remove all records before that time:
|
||||
int flDeadtime = gpGlobals->curtime - sv_maxunlag.GetFloat();
|
||||
|
||||
// Iterate all active players
|
||||
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
|
||||
|
||||
CUtlFixedLinkedList< LagRecord > *track = &m_PlayerTrack[i-1];
|
||||
|
||||
if ( !pPlayer )
|
||||
{
|
||||
if ( track->Count() > 0 )
|
||||
{
|
||||
track->RemoveAll();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Assert( track->Count() < 1000 ); // insanity check
|
||||
|
||||
// remove tail records that are too old
|
||||
intp tailIndex = track->Tail();
|
||||
while ( track->IsValidIndex( tailIndex ) )
|
||||
{
|
||||
LagRecord &tail = track->Element( tailIndex );
|
||||
|
||||
// if tail is within limits, stop
|
||||
if ( tail.m_flSimulationTime >= flDeadtime )
|
||||
break;
|
||||
|
||||
// remove tail, get new tail
|
||||
track->Remove( tailIndex );
|
||||
tailIndex = track->Tail();
|
||||
}
|
||||
|
||||
// check if head has same simulation time
|
||||
if ( track->Count() > 0 )
|
||||
{
|
||||
LagRecord &head = track->Element( track->Head() );
|
||||
|
||||
// check if player changed simulation time since last time updated
|
||||
if ( head.m_flSimulationTime >= pPlayer->GetSimulationTime() )
|
||||
continue; // don't add new entry for same or older time
|
||||
}
|
||||
auto track = &m_EntityTrack[pPlayer->entindex()];
|
||||
|
||||
// add new record to player track
|
||||
LagRecord &record = track->Element( track->AddToHead() );
|
||||
LagRecord record;
|
||||
|
||||
record.m_fFlags = 0;
|
||||
record.m_fFlags = LC_NONE;
|
||||
if ( pPlayer->IsAlive() )
|
||||
{
|
||||
record.m_fFlags |= LC_ALIVE;
|
||||
|
@ -289,16 +264,17 @@ void CLagCompensationManager::FrameUpdatePostEntityThink()
|
|||
|
||||
record.m_flSimulationTime = pPlayer->GetSimulationTime();
|
||||
record.m_flAnimTime = pPlayer->GetAnimTime();
|
||||
record.m_vecAngles = pPlayer->GetLocalAngles();
|
||||
record.m_vecOrigin = pPlayer->GetLocalOrigin();
|
||||
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();
|
||||
for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
||||
|
||||
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
||||
{
|
||||
CAnimationLayer *currentLayer = pPlayer->GetAnimOverlay(layerIndex);
|
||||
if( currentLayer )
|
||||
CAnimationLayer* currentLayer = pPlayer->GetAnimOverlay( layerIndex );
|
||||
if ( currentLayer )
|
||||
{
|
||||
record.m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle;
|
||||
record.m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder;
|
||||
|
@ -306,56 +282,47 @@ void CLagCompensationManager::FrameUpdatePostEntityThink()
|
|||
record.m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight;
|
||||
}
|
||||
}
|
||||
|
||||
record.m_masterSequence = pPlayer->GetSequence();
|
||||
record.m_masterCycle = pPlayer->GetCycle();
|
||||
|
||||
CStudioHdr *hdr = pPlayer->GetModelPtr();
|
||||
if( hdr )
|
||||
CStudioHdr* hdr = pPlayer->GetModelPtr();
|
||||
|
||||
if ( hdr )
|
||||
{
|
||||
for( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
||||
for ( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
||||
{
|
||||
record.m_poseParameters[paramIndex] = pPlayer->GetPoseParameterArray()[ paramIndex ];
|
||||
record.m_poseParameters[paramIndex] = pPlayer->GetPoseParameterArray()[paramIndex];
|
||||
}
|
||||
}
|
||||
|
||||
if( hdr )
|
||||
if ( hdr )
|
||||
{
|
||||
for( int paramIndex = 0; paramIndex < hdr->GetNumBoneControllers(); paramIndex++ )
|
||||
for ( int paramIndex = 0; paramIndex < hdr->GetNumBoneControllers(); paramIndex++ )
|
||||
{
|
||||
record.m_encodedControllers[paramIndex] = pPlayer->GetEncodedControllerArray()[ paramIndex ];
|
||||
}
|
||||
record.m_encodedControllers[paramIndex] = pPlayer->GetBoneControllerArray()[paramIndex];
|
||||
}
|
||||
}
|
||||
|
||||
//Clear the current player.
|
||||
m_pCurrentPlayer = NULL;
|
||||
track->Push( record );
|
||||
}
|
||||
|
||||
// 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 )
|
||||
{
|
||||
//DONT LAG COMP AGAIN THIS FRAME IF THERES ALREADY ONE IN PROGRESS
|
||||
//IF YOU'RE HITTING THIS THEN IT MEANS THERES A CODE BUG
|
||||
if ( m_pCurrentPlayer )
|
||||
{
|
||||
Assert( m_pCurrentPlayer == NULL );
|
||||
Warning( "Trying to start a new lag compensation session while one is already active!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Assume no players need to be restored
|
||||
m_RestorePlayer.ClearAll();
|
||||
m_bNeedToRestore = false;
|
||||
|
||||
m_pCurrentPlayer = player;
|
||||
|
||||
if ( !player->m_bLagCompensation // Player not wanting lag compensation
|
||||
|| (gpGlobals->maxClients <= 1) // no lag compensation in single player
|
||||
|| ( gpGlobals->maxClients <= 1 ) // no lag compensation in single player
|
||||
|| !sv_unlag.GetBool() // disabled by server admin
|
||||
|| player->IsBot() // not for bots
|
||||
|| player->IsObserver() // not for spectators
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: Put this here so that it won't show up in single player mode.
|
||||
VPROF_BUDGET( "StartLagCompensation", VPROF_BUDGETGROUP_OTHER_NETWORKING );
|
||||
|
@ -363,10 +330,10 @@ void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCm
|
|||
Q_memset( m_ChangeData, 0, sizeof( m_ChangeData ) );
|
||||
|
||||
// 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 );
|
||||
CBasePlayer* pPlayer = UTIL_PlayerByIndex( i );
|
||||
|
||||
if ( !pPlayer )
|
||||
{
|
||||
|
@ -381,75 +348,73 @@ void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCm
|
|||
|
||||
// Custom checks for if things should lag compensate (based on things like what team the player is on).
|
||||
if ( !player->WantsLagCompensationOnEntity( pPlayer, cmd, pEntityTransmitBits ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Move other player back in time
|
||||
BacktrackPlayer( pPlayer, cmd );
|
||||
}
|
||||
}
|
||||
|
||||
void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *cmd )
|
||||
void CLagCompensationManager::BacktrackPlayer( CBasePlayer* pPlayer, CUserCmd* cmd )
|
||||
{
|
||||
Vector org;
|
||||
Vector minsPreScaled;
|
||||
Vector maxsPreScaled;
|
||||
QAngle ang;
|
||||
LagRecord* nextRecordSim;
|
||||
LagRecord* recordSim;
|
||||
LagRecord* recordAnim;
|
||||
|
||||
VPROF_BUDGET( "BacktrackPlayer", "CLagCompensationManager" );
|
||||
int pl_index = pPlayer->entindex() - 1;
|
||||
int pl_index = pPlayer->entindex();
|
||||
|
||||
float flTargetSimulationTime = cmd->simulationdata[pl_index + 1].m_flSimulationTime;
|
||||
float flTargetSimulatedAnimationTime = cmd->simulationdata[pl_index + 1].m_flAnimTime;
|
||||
float flTargetLerpSimTime = cmd->simulationdata[pl_index].lerp_time;
|
||||
float flTargetAnimatedSimulationTime = cmd->simulationdata[pl_index].animated_sim_time;
|
||||
|
||||
// get track history of this player
|
||||
CUtlFixedLinkedList< LagRecord > *trackSim = &m_PlayerTrack[ pl_index ];
|
||||
CUtlFixedLinkedList< LagRecord > *trackAnim = &m_PlayerTrack[ pl_index ];
|
||||
auto track = &m_EntityTrack[pl_index];
|
||||
|
||||
// check if we have at leat one entry
|
||||
if ( trackSim->Count() <= 0 || trackAnim->Count() <= 0 )
|
||||
return;
|
||||
|
||||
intp currSim = trackSim->Head();
|
||||
|
||||
LagRecord *prevRecordSim = NULL;
|
||||
LagRecord *recordSim = NULL;
|
||||
LagRecord *recordAnim = NULL;
|
||||
|
||||
Vector prevOrg = pPlayer->GetLocalOrigin();
|
||||
bool foundAnimationData = false;
|
||||
|
||||
// Walk context looking for any invalidating event
|
||||
while( trackSim->IsValidIndex(currSim) )
|
||||
for ( int i = 0; i < MAX_TICKS_SAVED; i++ )
|
||||
{
|
||||
// remember last record
|
||||
prevRecordSim = recordSim;
|
||||
recordSim = track->Get( i );
|
||||
|
||||
// get next record
|
||||
recordSim = &trackSim->Element(currSim);
|
||||
|
||||
if (recordSim->m_flSimulationTime
|
||||
<= flTargetSimulatedAnimationTime && !foundAnimationData)
|
||||
if ( !recordSim )
|
||||
{
|
||||
recordAnim = recordSim;
|
||||
foundAnimationData = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !(recordSim->m_fFlags & LC_ALIVE) )
|
||||
if ( !( recordSim->m_fFlags & LC_ALIVE ) )
|
||||
{
|
||||
// player most be alive, lost track
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO_ENHANCED: do proper teleportation checks.
|
||||
if ( flTargetLerpSimTime == recordSim->m_flSimulationTime )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// did we find a context smaller than target time ?
|
||||
if ( recordSim->m_flSimulationTime <= flTargetSimulationTime )
|
||||
break; // hurra, stop
|
||||
if ( recordSim->m_flSimulationTime < flTargetLerpSimTime )
|
||||
{
|
||||
nextRecordSim = track->Get( i - 1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
prevOrg = recordSim->m_vecOrigin;
|
||||
for ( int i = 0; i < MAX_TICKS_SAVED; i++ )
|
||||
{
|
||||
recordAnim = track->Get( i );
|
||||
|
||||
// go one step back
|
||||
currSim = trackSim->Next( currSim );
|
||||
if ( !recordAnim )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ( recordAnim->m_flSimulationTime == flTargetAnimatedSimulationTime )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert( recordAnim );
|
||||
|
@ -466,26 +431,25 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
|
|||
}
|
||||
|
||||
float fracSim = 0.0f;
|
||||
if ( prevRecordSim &&
|
||||
(recordSim->m_flSimulationTime < flTargetSimulationTime) &&
|
||||
(recordSim->m_flSimulationTime < prevRecordSim->m_flSimulationTime) )
|
||||
if ( nextRecordSim && ( recordSim->m_flSimulationTime < flTargetLerpSimTime )
|
||||
&& ( recordSim->m_flSimulationTime < nextRecordSim->m_flSimulationTime ) )
|
||||
{
|
||||
// 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 );
|
||||
Assert( flTargetSimulationTime < prevRecordSim->m_flSimulationTime );
|
||||
Assert( flTargetLerpSimTime < prevRecordSim->m_flSimulationTime );
|
||||
|
||||
// calc fraction between both records
|
||||
fracSim = float(( double(flTargetSimulationTime) - double(recordSim->m_flSimulationTime) ) /
|
||||
( double(prevRecordSim->m_flSimulationTime) - double(recordSim->m_flSimulationTime) ));
|
||||
fracSim = float( ( double( flTargetLerpSimTime ) - double( recordSim->m_flSimulationTime ) )
|
||||
/ ( double( nextRecordSim->m_flSimulationTime ) - double( recordSim->m_flSimulationTime ) ) );
|
||||
|
||||
Assert( fracSim > 0 && fracSim < 1 ); // should never extrapolate
|
||||
|
||||
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 );
|
||||
ang = Lerp( fracSim, recordSim->m_vecAngles, nextRecordSim->m_vecAngles );
|
||||
org = Lerp( fracSim, recordSim->m_vecOrigin, nextRecordSim->m_vecOrigin );
|
||||
minsPreScaled = Lerp( fracSim, recordSim->m_vecMinsPreScaled, nextRecordSim->m_vecMinsPreScaled );
|
||||
maxsPreScaled = Lerp( fracSim, recordSim->m_vecMaxsPreScaled, nextRecordSim->m_vecMaxsPreScaled );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -497,72 +461,13 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
|
|||
maxsPreScaled = recordSim->m_vecMaxsPreScaled;
|
||||
}
|
||||
|
||||
// See if this is still a valid position for us to teleport to
|
||||
if ( sv_unlag_fixstuck.GetBool() )
|
||||
{
|
||||
// Try to move to the wanted position from our current position.
|
||||
trace_t tr;
|
||||
UTIL_TraceEntity( pPlayer, org, org, MASK_PLAYERSOLID, &tr );
|
||||
if ( tr.startsolid || tr.allsolid )
|
||||
{
|
||||
if ( sv_unlag_debug.GetBool() )
|
||||
DevMsg( "WARNING: BackupPlayer trying to back player into a bad position - client %s\n", pPlayer->GetPlayerName() );
|
||||
|
||||
CBasePlayer *pHitPlayer = dynamic_cast<CBasePlayer *>( tr.m_pEnt );
|
||||
|
||||
// don't lag compensate the current player
|
||||
if ( pHitPlayer && ( pHitPlayer != m_pCurrentPlayer ) )
|
||||
{
|
||||
// If we haven't backtracked this player, do it now
|
||||
// this deliberately ignores WantsLagCompensationOnEntity.
|
||||
if ( !m_RestorePlayer.Get( pHitPlayer->entindex() - 1 ) )
|
||||
{
|
||||
// prevent recursion - save a copy of m_RestorePlayer,
|
||||
// pretend that this player is off-limits
|
||||
int pl_index = pPlayer->entindex() - 1;
|
||||
|
||||
// Temp turn this flag on
|
||||
m_RestorePlayer.Set( pl_index );
|
||||
|
||||
BacktrackPlayer( pHitPlayer, cmd );
|
||||
|
||||
// Remove the temp flag
|
||||
m_RestorePlayer.Clear( pl_index );
|
||||
}
|
||||
}
|
||||
|
||||
// now trace us back as far as we can go
|
||||
UTIL_TraceEntity( pPlayer, pPlayer->GetLocalOrigin(), org, MASK_PLAYERSOLID, &tr );
|
||||
|
||||
if ( tr.startsolid || tr.allsolid )
|
||||
{
|
||||
// Our starting position is bogus
|
||||
|
||||
if ( sv_unlag_debug.GetBool() )
|
||||
DevMsg( "Backtrack failed completely, bad starting position\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can get to a valid place, but not all the way to the target
|
||||
Vector vPos;
|
||||
VectorLerp( pPlayer->GetLocalOrigin(), org, tr.fraction * g_flFractionScale, vPos );
|
||||
|
||||
// This is as close as we're going to get
|
||||
org = vPos;
|
||||
|
||||
if ( sv_unlag_debug.GetBool() )
|
||||
DevMsg( "Backtrack got most of the way\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if this represents a change for the player
|
||||
int flags = 0;
|
||||
LagRecord *restore = &m_RestoreData[ pl_index ];
|
||||
LagRecord *change = &m_ChangeData[ pl_index ];
|
||||
LagRecord* restore = &m_RestoreData[pl_index];
|
||||
LagRecord* change = &m_ChangeData[pl_index];
|
||||
|
||||
QAngle angdiff = pPlayer->GetLocalAngles() - ang;
|
||||
Vector orgdiff = pPlayer->GetLocalOrigin() - org;
|
||||
QAngle angdiff = pPlayer->GetAbsAngles() - ang;
|
||||
Vector orgdiff = pPlayer->GetAbsOrigin() - org;
|
||||
|
||||
// Always remember the pristine simulation time in case we need to restore it.
|
||||
restore->m_flSimulationTime = pPlayer->GetSimulationTime();
|
||||
|
@ -571,13 +476,14 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
|
|||
if ( angdiff.LengthSqr() > 0.0f )
|
||||
{
|
||||
flags |= LC_ANGLES_CHANGED;
|
||||
restore->m_vecAngles = pPlayer->GetLocalAngles();
|
||||
pPlayer->SetLocalAngles( ang );
|
||||
restore->m_vecAngles = pPlayer->GetAbsAngles();
|
||||
pPlayer->SetAbsAngles( ang );
|
||||
change->m_vecAngles = ang;
|
||||
}
|
||||
|
||||
// Use absolute equality here
|
||||
if ( minsPreScaled != pPlayer->CollisionProp()->OBBMinsPreScaled() || maxsPreScaled != pPlayer->CollisionProp()->OBBMaxsPreScaled() )
|
||||
if ( minsPreScaled != pPlayer->CollisionProp()->OBBMinsPreScaled()
|
||||
|| maxsPreScaled != pPlayer->CollisionProp()->OBBMaxsPreScaled() )
|
||||
{
|
||||
flags |= LC_SIZE_CHANGED;
|
||||
|
||||
|
@ -594,8 +500,8 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
|
|||
if ( orgdiff.LengthSqr() > 0.0f )
|
||||
{
|
||||
flags |= LC_ORIGIN_CHANGED;
|
||||
restore->m_vecOrigin = pPlayer->GetLocalOrigin();
|
||||
pPlayer->SetLocalOrigin( org );
|
||||
restore->m_vecOrigin = pPlayer->GetAbsOrigin();
|
||||
pPlayer->SetAbsOrigin( org );
|
||||
change->m_vecOrigin = org;
|
||||
}
|
||||
|
||||
|
@ -606,22 +512,21 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
|
|||
restore->m_masterSequence = pPlayer->GetSequence();
|
||||
restore->m_masterCycle = pPlayer->GetCycle();
|
||||
|
||||
pPlayer->SetSequence(recordAnim->m_masterSequence);
|
||||
pPlayer->SetCycle(recordAnim->m_masterCycle);
|
||||
pPlayer->SetSequence( recordAnim->m_masterSequence );
|
||||
pPlayer->SetCycle( recordAnim->m_masterCycle );
|
||||
|
||||
////////////////////////
|
||||
// Now do all the layers
|
||||
int layerCount = pPlayer->GetNumAnimOverlays();
|
||||
for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
||||
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
||||
{
|
||||
CAnimationLayer *currentLayer = pPlayer->GetAnimOverlay(layerIndex);
|
||||
if( currentLayer )
|
||||
CAnimationLayer* currentLayer = pPlayer->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_weight = currentLayer->m_flWeight;
|
||||
|
||||
currentLayer->m_flCycle = recordAnim->m_layerRecords[layerIndex].m_cycle;
|
||||
currentLayer->m_nOrder = recordAnim->m_layerRecords[layerIndex].m_order;
|
||||
|
@ -633,88 +538,86 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
|
|||
flags |= LC_POSE_PARAMS_CHANGED;
|
||||
|
||||
// Now do pose parameters
|
||||
CStudioHdr *hdr = pPlayer->GetModelPtr();
|
||||
if( hdr )
|
||||
CStudioHdr* hdr = pPlayer->GetModelPtr();
|
||||
if ( hdr )
|
||||
{
|
||||
for( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
||||
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);
|
||||
pPlayer->SetPoseParameterRaw( paramIndex, poseParameter );
|
||||
}
|
||||
}
|
||||
|
||||
flags |= LC_ENCD_CONS_CHANGED;
|
||||
|
||||
if( hdr )
|
||||
if ( hdr )
|
||||
{
|
||||
for( int paramIndex = 0; paramIndex < hdr->GetNumBoneControllers(); paramIndex++ )
|
||||
for ( int encIndex = 0; encIndex < hdr->GetNumBoneControllers(); encIndex++ )
|
||||
{
|
||||
restore->m_encodedControllers[paramIndex] = pPlayer->GetEncodedControllerArray()[paramIndex];
|
||||
float encodedController = recordAnim->m_encodedControllers[paramIndex];
|
||||
restore->m_encodedControllers[encIndex] = pPlayer->GetBoneControllerArray()[encIndex];
|
||||
float encodedController = recordAnim->m_encodedControllers[encIndex];
|
||||
|
||||
pPlayer->SetBoneControllerRaw( paramIndex, encodedController );
|
||||
pPlayer->SetBoneControllerRaw( encIndex, encodedController );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !flags )
|
||||
{
|
||||
return; // we didn't change anything
|
||||
}
|
||||
|
||||
// Set lag compensated player's times
|
||||
pPlayer->SetSimulationTime(flTargetSimulationTime);
|
||||
pPlayer->SetSimulationTime( flTargetLerpSimTime );
|
||||
// pPlayer->SetAnimTime(animationData->m_flAnimTime);
|
||||
|
||||
if ( sv_lagflushbonecache.GetBool() )
|
||||
{
|
||||
pPlayer->InvalidateBoneCache();
|
||||
}
|
||||
|
||||
/*char text[256]; Q_snprintf( text, sizeof(text), "time %.2f", flTargetTime );
|
||||
pPlayer->DrawServerHitboxes( 10 );
|
||||
NDebugOverlay::Text( org, text, false, 10 );
|
||||
NDebugOverlay::EntityBounds( pPlayer, 255, 0, 0, 32, 10 ); */
|
||||
|
||||
m_RestorePlayer.Set( pl_index ); //remember that we changed this player
|
||||
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 )
|
||||
{
|
||||
VPROF_BUDGET_FLAGS( "FinishLagCompensation", VPROF_BUDGETGROUP_OTHER_NETWORKING, BUDGETFLAG_CLIENT|BUDGETFLAG_SERVER );
|
||||
|
||||
m_pCurrentPlayer = NULL;
|
||||
VPROF_BUDGET_FLAGS( "FinishLagCompensation",
|
||||
VPROF_BUDGETGROUP_OTHER_NETWORKING,
|
||||
BUDGETFLAG_CLIENT | BUDGETFLAG_SERVER );
|
||||
|
||||
if ( !m_bNeedToRestore )
|
||||
{
|
||||
return; // no player was changed at all
|
||||
}
|
||||
|
||||
// Iterate all active players
|
||||
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
|
||||
{
|
||||
int pl_index = i - 1;
|
||||
|
||||
if ( !m_RestorePlayer.Get( pl_index ) )
|
||||
if ( !m_RestorePlayer.Get( i ) )
|
||||
{
|
||||
// player wasn't changed by lag compensation
|
||||
continue;
|
||||
}
|
||||
|
||||
CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
|
||||
CBasePlayer* pPlayer = UTIL_PlayerByIndex( i );
|
||||
if ( !pPlayer )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LagRecord *restore = &m_RestoreData[ pl_index ];
|
||||
LagRecord *change = &m_ChangeData[ pl_index ];
|
||||
LagRecord* restore = &m_RestoreData[i];
|
||||
LagRecord* change = &m_ChangeData[i];
|
||||
|
||||
if ( restore->m_fFlags & LC_SIZE_CHANGED )
|
||||
{
|
||||
// see if simulation made any changes, if no, then do the restore, otherwise,
|
||||
// leave new values in
|
||||
if ( pPlayer->CollisionProp()->OBBMinsPreScaled() == change->m_vecMinsPreScaled &&
|
||||
pPlayer->CollisionProp()->OBBMaxsPreScaled() == change->m_vecMaxsPreScaled )
|
||||
if ( pPlayer->CollisionProp()->OBBMinsPreScaled() == change->m_vecMinsPreScaled
|
||||
&& pPlayer->CollisionProp()->OBBMaxsPreScaled() == change->m_vecMaxsPreScaled )
|
||||
{
|
||||
// Restore it
|
||||
pPlayer->SetSize( restore->m_vecMinsPreScaled, restore->m_vecMaxsPreScaled );
|
||||
|
@ -729,30 +632,30 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player )
|
|||
|
||||
if ( restore->m_fFlags & LC_ANGLES_CHANGED )
|
||||
{
|
||||
if ( pPlayer->GetLocalAngles() == change->m_vecAngles )
|
||||
if ( pPlayer->GetAbsAngles() == change->m_vecAngles )
|
||||
{
|
||||
pPlayer->SetLocalAngles( restore->m_vecAngles );
|
||||
pPlayer->SetAbsAngles( restore->m_vecAngles );
|
||||
}
|
||||
}
|
||||
|
||||
if ( restore->m_fFlags & LC_ORIGIN_CHANGED )
|
||||
{
|
||||
// Okay, let's see if we can do something reasonable with the change
|
||||
Vector delta = pPlayer->GetLocalOrigin() - change->m_vecOrigin;
|
||||
Vector delta = pPlayer->GetAbsOrigin() - change->m_vecOrigin;
|
||||
|
||||
RestorePlayerTo( pPlayer, restore->m_vecOrigin + delta );
|
||||
}
|
||||
|
||||
if( restore->m_fFlags & LC_ANIMATION_CHANGED )
|
||||
if ( restore->m_fFlags & LC_ANIMATION_CHANGED )
|
||||
{
|
||||
pPlayer->SetSequence(restore->m_masterSequence);
|
||||
pPlayer->SetCycle(restore->m_masterCycle);
|
||||
pPlayer->SetSequence( restore->m_masterSequence );
|
||||
pPlayer->SetCycle( restore->m_masterCycle );
|
||||
|
||||
int layerCount = pPlayer->GetNumAnimOverlays();
|
||||
for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
||||
for ( int layerIndex = 0; layerIndex < layerCount; ++layerIndex )
|
||||
{
|
||||
CAnimationLayer *currentLayer = pPlayer->GetAnimOverlay(layerIndex);
|
||||
if( currentLayer )
|
||||
CAnimationLayer* currentLayer = pPlayer->GetAnimOverlay( layerIndex );
|
||||
if ( currentLayer )
|
||||
{
|
||||
currentLayer->m_flCycle = restore->m_layerRecords[layerIndex].m_cycle;
|
||||
currentLayer->m_nOrder = restore->m_layerRecords[layerIndex].m_order;
|
||||
|
@ -762,33 +665,31 @@ void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player )
|
|||
}
|
||||
}
|
||||
|
||||
if( restore->m_fFlags & LC_POSE_PARAMS_CHANGED )
|
||||
CStudioHdr* hdr = pPlayer->GetModelPtr();
|
||||
|
||||
if ( restore->m_fFlags & LC_POSE_PARAMS_CHANGED )
|
||||
{
|
||||
CStudioHdr *hdr = pPlayer->GetModelPtr();
|
||||
if( hdr )
|
||||
if ( hdr )
|
||||
{
|
||||
for( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
||||
for ( int paramIndex = 0; paramIndex < hdr->GetNumPoseParameters(); paramIndex++ )
|
||||
{
|
||||
pPlayer->SetPoseParameterRaw( paramIndex, restore->m_poseParameters[paramIndex] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( restore->m_fFlags & LC_ENCD_CONS_CHANGED )
|
||||
if ( restore->m_fFlags & LC_ENCD_CONS_CHANGED )
|
||||
{
|
||||
CStudioHdr *hdr = pPlayer->GetModelPtr();
|
||||
if( hdr )
|
||||
if ( hdr )
|
||||
{
|
||||
for( int paramIndex = 0; paramIndex < hdr->GetNumBoneControllers(); paramIndex++ )
|
||||
for ( int encIndex = 0; encIndex < hdr->GetNumBoneControllers(); encIndex++ )
|
||||
{
|
||||
pPlayer->SetBoneControllerRaw( paramIndex, restore->m_encodedControllers[paramIndex] );
|
||||
pPlayer->SetBoneControllerRaw( encIndex, restore->m_encodedControllers[encIndex] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pPlayer->SetSimulationTime( restore->m_flSimulationTime );
|
||||
pPlayer->SetAnimTime(restore->m_flAnimTime);
|
||||
pPlayer->SetAnimTime( restore->m_flAnimTime );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "const.h"
|
||||
#include "debugoverlay_shared.h"
|
||||
#include "strtools.h"
|
||||
#ifndef CLIENT_DLL
|
||||
|
@ -38,7 +39,7 @@
|
|||
#include "engine/ivdebugoverlay.h"
|
||||
#include "obstacle_pushaway.h"
|
||||
#include "props_shared.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
ConVar weapon_accuracy_nospread( "weapon_accuracy_nospread", "0", FCVAR_REPLICATED );
|
||||
#define CS_MASK_SHOOT (MASK_SOLID|CONTENTS_DEBRIS)
|
||||
|
@ -193,7 +194,7 @@ void UTIL_ClipTraceToPlayersHull(const Vector& vecAbsStart, const Vector& vecAbs
|
|||
float smallestFraction = tr->fraction;
|
||||
const float maxRange = 60.0f;
|
||||
|
||||
ray.Init( vecAbsStart, vecAbsEnd , mins, maxs );
|
||||
ray.Init( vecAbsStart, vecAbsEnd, mins, maxs );
|
||||
|
||||
for ( int k = 1; k <= gpGlobals->maxClients; ++k )
|
||||
{
|
||||
|
@ -508,7 +509,8 @@ void CCSPlayer::FireBullet(
|
|||
CBasePlayer *lastPlayerHit = NULL;
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
bool shouldDebugHitboxesOnFire = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_FIRE;
|
||||
// Only show for one bullet.
|
||||
bool shouldDebugHitboxesOnFire = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_FIRE && iBullet == 0;
|
||||
bool shouldDebugHitboxesOnHit = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_HIT;
|
||||
|
||||
// TODO_ENHANCED:
|
||||
|
@ -527,6 +529,28 @@ void CCSPlayer::FireBullet(
|
|||
CBasePlayer* lagPlayer = UTIL_PlayerByIndex(i);
|
||||
if (lagPlayer && lagPlayer != this)
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
if ( !m_pCurrentCommand->hasbeenpredicted )
|
||||
{
|
||||
std::string text = "client:\n";
|
||||
|
||||
auto angles = lagPlayer->GetRenderAngles();
|
||||
|
||||
text += "x: " + std::to_string(angles.x) + ", y: " + std::to_string(angles.y) + ", z: " + std::to_string(angles.z) + '\n';
|
||||
|
||||
NDebugOverlay::EntityBounds( lagPlayer, 255, 0, 0, 32, 60 );
|
||||
std::cout << text;
|
||||
}
|
||||
#else
|
||||
std::string text = "server:\n";
|
||||
|
||||
auto angles = lagPlayer->GetAbsAngles();
|
||||
|
||||
text += "x: " + std::to_string(angles.x) + ", y: " + std::to_string(angles.y) + ", z: " + std::to_string(angles.z) + '\n';
|
||||
|
||||
NDebugOverlay::EntityBounds( lagPlayer, 0, 255, 0, 32, 60 );
|
||||
std::cout << text;
|
||||
#endif
|
||||
#ifdef CLIENT_DLL
|
||||
if (!m_pCurrentCommand->hasbeenpredicted)
|
||||
{
|
||||
|
|
|
@ -108,7 +108,7 @@ bool CBaseCSGrenade::Deploy()
|
|||
bool CBaseCSGrenade::Holster( CBaseCombatWeapon *pSwitchingTo )
|
||||
{
|
||||
m_bRedraw = false;
|
||||
m_bPinPulled = false; // when this is holstered make sure the pin isn’t pulled.
|
||||
m_bPinPulled = false; // when this is holstered make sure the pin isn<EFBFBD>t pulled.
|
||||
m_fThrowTime = 0;
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
|
@ -224,8 +224,9 @@ void CBaseCSGrenade::ItemPostFrame()
|
|||
// If they let go of the fire button, they want to throw the grenade.
|
||||
if ( m_bPinPulled && !(pPlayer->m_nButtons & IN_ATTACK) )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE );
|
||||
|
||||
#endif
|
||||
StartGrenadeThrow();
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
|
|
@ -162,20 +162,20 @@ void WriteUsercmd( bf_write *buf, const CUserCmd *to, const CUserCmd *from )
|
|||
// Write finally simulation data with entity index
|
||||
for ( unsigned int i = 0; i <= highestEntityIndex; i++ )
|
||||
{
|
||||
if ( from->simulationdata[i].m_flSimulationTime != to->simulationdata[i].m_flSimulationTime )
|
||||
if ( from->simulationdata[i].lerp_time != to->simulationdata[i].lerp_time )
|
||||
{
|
||||
buf->WriteOneBit( 1 );
|
||||
buf->WriteBitFloat( to->simulationdata[i].m_flSimulationTime );
|
||||
buf->WriteBitFloat( to->simulationdata[i].lerp_time );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf->WriteOneBit( 0 );
|
||||
}
|
||||
|
||||
if ( from->simulationdata[i].m_flAnimTime != to->simulationdata[i].m_flAnimTime )
|
||||
if ( from->simulationdata[i].animated_sim_time != to->simulationdata[i].animated_sim_time )
|
||||
{
|
||||
buf->WriteOneBit( 1 );
|
||||
buf->WriteBitFloat( to->simulationdata[i].m_flAnimTime );
|
||||
buf->WriteBitFloat( to->simulationdata[i].animated_sim_time );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -309,12 +309,12 @@ void ReadUsercmd( bf_read *buf, CUserCmd *move, CUserCmd *from )
|
|||
{
|
||||
if (buf->ReadOneBit())
|
||||
{
|
||||
move->simulationdata[i].m_flSimulationTime = buf->ReadBitFloat();
|
||||
move->simulationdata[i].lerp_time = buf->ReadBitFloat();
|
||||
}
|
||||
|
||||
if (buf->ReadOneBit())
|
||||
{
|
||||
move->simulationdata[i].m_flAnimTime = buf->ReadBitFloat();
|
||||
move->simulationdata[i].animated_sim_time = buf->ReadBitFloat();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#endif
|
||||
|
||||
#define MAX_LAYER_RECORDS (CBaseAnimatingOverlay::MAX_OVERLAYS)
|
||||
#define MAX_POSE_PARAMETERS (CBaseAnimating::NUM_POSEPAREMETERS)
|
||||
#define MAX_POSE_PARAMETERS (MAXSTUDIOPOSEPARAM)
|
||||
#define MAX_ENCODED_CONTROLLERS (MAXSTUDIOBONECTRLS)
|
||||
|
||||
class bf_read;
|
||||
|
@ -57,9 +57,9 @@ struct SimulationData
|
|||
// TODO_ENHANCED:
|
||||
// For now we send the last received update for animations.
|
||||
// anim time is unreliable on low fps.
|
||||
float m_flSimulationTime;
|
||||
float m_flAnimTime;
|
||||
bool m_bEntityExists;
|
||||
float lerp_time;
|
||||
float animated_sim_time;
|
||||
bool entityexists;
|
||||
};
|
||||
|
||||
class CEntityGroundContact
|
||||
|
|
|
@ -1531,5 +1531,106 @@ private:
|
|||
char *m_szBuffer; // a copy of original string, with '\0' instead of separators
|
||||
};
|
||||
|
||||
template < typename T, size_t N >
|
||||
class CUtlCircularBuffer
|
||||
{
|
||||
public:
|
||||
using pT = T*;
|
||||
|
||||
enum PushType
|
||||
{
|
||||
Filling,
|
||||
Updating
|
||||
};
|
||||
|
||||
public:
|
||||
inline pT Get( const int wantedSlot = 0 )
|
||||
{
|
||||
const auto real_slot = _Slot( wantedSlot );
|
||||
|
||||
return ( real_slot == -1 ) ? NULL : &_buffer[real_slot];
|
||||
}
|
||||
|
||||
public:
|
||||
inline PushType Push( T&& element )
|
||||
{
|
||||
if ( _filled_history >= N )
|
||||
{
|
||||
if ( _index >= ( N - 1 ) )
|
||||
{
|
||||
_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_index++;
|
||||
}
|
||||
|
||||
_buffer[_index] = element;
|
||||
|
||||
return Updating;
|
||||
}
|
||||
|
||||
_buffer[_filled_history] = element;
|
||||
_index = _filled_history;
|
||||
_filled_history++;
|
||||
|
||||
return Filling;
|
||||
}
|
||||
|
||||
inline PushType Push( const T& element )
|
||||
{
|
||||
if ( _filled_history >= N )
|
||||
{
|
||||
if ( _index >= ( N - 1 ) )
|
||||
{
|
||||
_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_index++;
|
||||
}
|
||||
|
||||
_buffer[_index] = element;
|
||||
|
||||
return Updating;
|
||||
}
|
||||
|
||||
_buffer[_filled_history] = element;
|
||||
_index = _filled_history;
|
||||
_filled_history++;
|
||||
|
||||
return Filling;
|
||||
}
|
||||
|
||||
inline void Clear()
|
||||
{
|
||||
_index = 0;
|
||||
_filled_history = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
inline int _Slot( const int wantedSlot = 0 ) const
|
||||
{
|
||||
if ( wantedSlot >= _filled_history || wantedSlot < 0 || _filled_history <= 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( _filled_history >= N )
|
||||
{
|
||||
const int calc_slot = ( _index - wantedSlot );
|
||||
return ( calc_slot < 0 ) ? calc_slot + N : calc_slot;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( _filled_history - 1 ) - wantedSlot;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T _buffer[N];
|
||||
int _filled_history {};
|
||||
int _index {};
|
||||
};
|
||||
|
||||
#endif // CCVECTOR_H
|
||||
|
|
Loading…
Reference in a new issue