General fixes and improved lag comp performance

This commit is contained in:
Kamay Xutax 2024-08-31 06:18:28 +02:00
parent 380f352adf
commit 11d345802e
17 changed files with 499 additions and 527 deletions

View file

@ -1948,7 +1948,8 @@ void C_BaseAnimating::StandardBlendingRules( CStudioHdr *hdr, Vector pos[], Quat
return; return;
} }
if (GetSequence() >= hdr->GetNumSeq() || GetSequence() == -1 ) // CS weapons have this sometimes ...
if ( GetSequence() >= hdr->GetNumSeq() || GetSequence() == -1 )
{ {
SetSequence( 0 ); SetSequence( 0 );
} }
@ -4928,7 +4929,8 @@ void C_BaseAnimating::Simulate()
DelayedInitModelEffects(); 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() ); DoAnimationEvents( GetModelPtr() );
} }

View file

@ -534,6 +534,7 @@ protected:
float m_fadeMinDist; float m_fadeMinDist;
float m_fadeMaxDist; float m_fadeMaxDist;
float m_flFadeScale; float m_flFadeScale;
bool m_bClientSideAnimation;
private: private:
@ -567,7 +568,6 @@ private:
float m_flOldEncodedController[MAXSTUDIOBONECTRLS]; float m_flOldEncodedController[MAXSTUDIOBONECTRLS];
// Clientside animation // Clientside animation
bool m_bClientSideAnimation;
bool m_bLastClientSideFrameReset; bool m_bLastClientSideFrameReset;
int m_nNewSequenceParity; int m_nNewSequenceParity;

View file

@ -124,40 +124,6 @@ CAddonInfo g_AddonInfo[] =
{ "eholster", 0, "models/weapons/w_eq_eholster_elite.mdl", "models/weapons/w_eq_eholster.mdl" }, { "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 ) BEGIN_PREDICTION_DATA( C_CSPlayer )
#ifdef CS_SHIELD_ENABLED #ifdef CS_SHIELD_ENABLED
DEFINE_PRED_FIELD( m_bShieldDrawn, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), DEFINE_PRED_FIELD( m_bShieldDrawn, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
@ -767,7 +733,7 @@ C_CSPlayer::C_CSPlayer() :
{ {
m_angEyeAngles.Init(); 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_iLastAddonBits = m_iAddonBits = 0;
m_iLastPrimaryAddon = m_iLastSecondaryAddon = WEAPON_NONE; m_iLastPrimaryAddon = m_iLastSecondaryAddon = WEAPON_NONE;
@ -1689,6 +1655,11 @@ bool C_CSPlayer::Weapon_CanSwitchTo( CBaseCombatWeapon *pWeapon )
void C_CSPlayer::UpdateClientSideAnimation() void C_CSPlayer::UpdateClientSideAnimation()
{ {
if ( !m_bClientSideAnimation )
{
return;
}
// We do this in a different order than the base class. // 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, // 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. // 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 ) 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 ) void C_CSPlayer::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
@ -2330,11 +2303,11 @@ void C_CSPlayer::Simulate( void )
} }
} }
BaseClass::Simulate(); 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 );
} }
} }

View file

@ -1306,7 +1306,7 @@ 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].m_bEntityExists = false; cmd->simulationdata[i].entityexists = false;
} }
// 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.
@ -1319,9 +1319,9 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo
continue; continue;
} }
cmd->simulationdata[pEntity->index].m_flSimulationTime = pEntity->m_flInterpolatedSimulationTime; cmd->simulationdata[pEntity->index].lerp_time = pEntity->m_flInterpolatedSimulationTime;
cmd->simulationdata[pEntity->index].m_flAnimTime = pEntity->m_flSimulationTime; cmd->simulationdata[pEntity->index].animated_sim_time = pEntity->m_flSimulationTime;
cmd->simulationdata[pEntity->index].m_bEntityExists = true; cmd->simulationdata[pEntity->index].entityexists = true;
} }
#ifdef CSTRIKE_DLL #ifdef CSTRIKE_DLL

View file

@ -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, 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 ); boneSetup.CalcAutoplaySequences( pos, q, gpGlobals->curtime, &auto_ik );
} }
else else
@ -490,7 +490,7 @@ void CBaseAnimatingOverlay::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Q
if ( pStudioHdr->numbonecontrollers() ) if ( pStudioHdr->numbonecontrollers() )
{ {
boneSetup.CalcBoneAdj( pos, q, GetEncodedControllerArray() ); boneSetup.CalcBoneAdj( pos, q, GetBoneControllerArray() );
} }
} }

View file

@ -2805,8 +2805,12 @@ CBoneCache *CBaseAnimating::GetBoneCache( void )
CStudioHdr *pStudioHdr = GetModelPtr( ); CStudioHdr *pStudioHdr = GetModelPtr( );
Assert(pStudioHdr); Assert(pStudioHdr);
// Use this for lag compensation
float oldcurtime = gpGlobals->curtime;
gpGlobals->curtime = m_flSimulationTime;
CBoneCache *pcache = Studio_GetBoneCache( m_boneCacheHandle ); 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 // TF queries these bones to position weapons when players are killed
#if defined( TF_DLL ) #if defined( TF_DLL )
@ -2814,8 +2818,10 @@ CBoneCache *CBaseAnimating::GetBoneCache( void )
#endif #endif
if ( pcache ) 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 ); // 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! // in memory and still valid, use it!
return pcache; return pcache;
@ -2849,6 +2855,8 @@ CBoneCache *CBaseAnimating::GetBoneCache( void )
pcache = Studio_GetBoneCache( m_boneCacheHandle ); pcache = Studio_GetBoneCache( m_boneCacheHandle );
} }
Assert(pcache); Assert(pcache);
gpGlobals->curtime = oldcurtime;
return pcache; return pcache;
} }
@ -3035,7 +3043,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, 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 ); boneSetup.CalcAutoplaySequences( pos, q, gpGlobals->curtime, &auto_ik );
} }
else else
@ -3045,7 +3053,7 @@ void CBaseAnimating::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaterni
if ( pStudioHdr->numbonecontrollers() ) if ( pStudioHdr->numbonecontrollers() )
{ {
boneSetup.CalcBoneAdj( pos, q, GetEncodedControllerArray() ); boneSetup.CalcBoneAdj( pos, q, GetBoneControllerArray() );
} }
} }

View file

@ -325,7 +325,7 @@ public:
CBaseEntity *GetLightingOrigin(); CBaseEntity *GetLightingOrigin();
const float* GetPoseParameterArray() { return m_flPoseParameter.Base(); } 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, void BuildMatricesWithBoneMerge( const CStudioHdr *pStudioHdr, const QAngle& angles,
const Vector& origin, const Vector pos[MAXSTUDIOBONES], const Vector& origin, const Vector pos[MAXSTUDIOBONES],

View file

@ -240,45 +240,6 @@ IMPLEMENT_SERVERCLASS_ST_NOBASE( CCSRagdoll, DT_CSRagdoll )
SendPropInt( SENDINFO( m_bClientSideAnimation ), 1, SPROP_UNSIGNED ), SendPropInt( SENDINFO( m_bClientSideAnimation ), 1, SPROP_UNSIGNED ),
END_SEND_TABLE() 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 // 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 // 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 else
{ {
m_PlayerAnimState->DoAnimationEvent( event, nData ); m_PlayerAnimState->DoAnimationEvent( event, nData );
TE_PlayerAnimEvent( this, event, nData ); // Send to any clients who can see this guy.
} }
} }

View file

@ -782,7 +782,7 @@ protected:
void PushawayThink(); void PushawayThink();
private: public:
ICSPlayerAnimState *m_PlayerAnimState; ICSPlayerAnimState *m_PlayerAnimState;

View file

@ -22,8 +22,9 @@ abstract_class ILagCompensationManager
public: 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 BacktrackPlayer( CBasePlayer *player, CUserCmd *cmd ) = 0;
virtual void TrackPlayerData( CBasePlayer *pPlayer ) = 0;
}; };
extern ILagCompensationManager *lagcompensation; extern ILagCompensationManager *lagcompensation;

View file

@ -342,15 +342,15 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
return; // Don't process this command return; // Don't process this command
} }
gpGlobals->frametime = playerFrameTime; gpGlobals->frametime = playerFrameTime;
gpGlobals->curtime = player->m_nTickBase * TICK_INTERVAL; gpGlobals->curtime = player->m_nTickBase * TICK_INTERVAL;
StartCommand( player, ucmd );
g_pGameMovement->StartTrackPredictionErrors( player ); StartCommand( player, ucmd );
g_pGameMovement->StartTrackPredictionErrors( player );
// Prevent hacked clients from sending us invalid view angles to try to get leaf server code to crash // 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; 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 // If no clipping and cheats enabled and noclipduring game enabled, then leave
// forwardmove and angles stuff in usercmd // forwardmove and angles stuff in usercmd
if ( player->GetMoveType() == MOVETYPE_NOCLIP && if ( player->GetMoveType() == MOVETYPE_NOCLIP && sv_cheats->GetBool() && sv_noclipduringpause.GetBool() )
sv_cheats->GetBool() &&
sv_noclipduringpause.GetBool() )
{ {
gpGlobals->frametime = TICK_INTERVAL; gpGlobals->frametime = TICK_INTERVAL;
} }
@ -385,7 +383,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
// Do weapon selection // Do weapon selection
if ( ucmd->weaponselect != 0 ) if ( ucmd->weaponselect != 0 )
{ {
CBaseCombatWeapon *weapon = dynamic_cast< CBaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) ); CBaseCombatWeapon* weapon = dynamic_cast< CBaseCombatWeapon* >( CBaseEntity::Instance( ucmd->weaponselect ) );
if ( weapon ) if ( weapon )
{ {
VPROF( "player->SelectItem()" ); 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. // Latch in impulse.
if ( ucmd->impulse ) if ( ucmd->impulse )
{ {
// Discard impulse commands unless the vehicle allows them. // 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() ) if ( !pVehicle || player->UsingStandardWeaponsInVehicle() )
{ {
player->m_nImpulse = ucmd->impulse; player->m_nImpulse = ucmd->impulse;
@ -420,7 +419,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
{ {
player->pl.v_angle = ucmd->viewangles; 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; player->pl.v_angle = ucmd->viewangles + player->pl.anglechange;
} }
@ -446,18 +445,18 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
VPROF( "pVehicle->ProcessMovement()" ); VPROF( "pVehicle->ProcessMovement()" );
pVehicle->ProcessMovement( player, g_pMoveData ); pVehicle->ProcessMovement( player, g_pMoveData );
} }
// Copy output // Copy output
FinishMove( player, ucmd, g_pMoveData ); FinishMove( player, ucmd, g_pMoveData );
// Let server invoke any needed impact functions // Let server invoke any needed impact functions
VPROF_SCOPE_BEGIN( "moveHelper->ProcessImpacts" ); VPROF_SCOPE_BEGIN( "moveHelper->ProcessImpacts" );
moveHelper->ProcessImpacts(); moveHelper->ProcessImpacts();
VPROF_SCOPE_END(); VPROF_SCOPE_END();
RunPostThink( player ); RunPostThink( player );
ServiceEventQueue( player ); ServiceEventQueue( player );
g_pGameMovement->FinishTrackPredictionErrors( player ); g_pGameMovement->FinishTrackPredictionErrors( player );
@ -467,5 +466,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
if ( gpGlobals->frametime > 0 ) if ( gpGlobals->frametime > 0 )
{ {
player->m_nTickBase++; player->m_nTickBase++;
} }
lagcompensation->TrackPlayerData( player );
} }

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@
//=============================================================================// //=============================================================================//
#include "cbase.h" #include "cbase.h"
#include "const.h"
#include "debugoverlay_shared.h" #include "debugoverlay_shared.h"
#include "strtools.h" #include "strtools.h"
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
@ -38,7 +39,7 @@
#include "engine/ivdebugoverlay.h" #include "engine/ivdebugoverlay.h"
#include "obstacle_pushaway.h" #include "obstacle_pushaway.h"
#include "props_shared.h" #include "props_shared.h"
#include <iostream>
ConVar weapon_accuracy_nospread( "weapon_accuracy_nospread", "0", FCVAR_REPLICATED ); ConVar weapon_accuracy_nospread( "weapon_accuracy_nospread", "0", FCVAR_REPLICATED );
#define CS_MASK_SHOOT (MASK_SOLID|CONTENTS_DEBRIS) #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; float smallestFraction = tr->fraction;
const float maxRange = 60.0f; 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 ) for ( int k = 1; k <= gpGlobals->maxClients; ++k )
{ {
@ -508,7 +509,8 @@ void CCSPlayer::FireBullet(
CBasePlayer *lastPlayerHit = NULL; CBasePlayer *lastPlayerHit = NULL;
MDLCACHE_CRITICAL_SECTION(); 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; bool shouldDebugHitboxesOnHit = m_pCurrentCommand->debug_hitboxes & CUserCmd::DEBUG_HITBOXES_ON_HIT;
// TODO_ENHANCED: // TODO_ENHANCED:
@ -526,7 +528,29 @@ void CCSPlayer::FireBullet(
{ {
CBasePlayer* lagPlayer = UTIL_PlayerByIndex(i); CBasePlayer* lagPlayer = UTIL_PlayerByIndex(i);
if (lagPlayer && lagPlayer != this) 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 #ifdef CLIENT_DLL
if (!m_pCurrentCommand->hasbeenpredicted) if (!m_pCurrentCommand->hasbeenpredicted)
{ {

View file

@ -108,7 +108,7 @@ bool CBaseCSGrenade::Deploy()
bool CBaseCSGrenade::Holster( CBaseCombatWeapon *pSwitchingTo ) bool CBaseCSGrenade::Holster( CBaseCombatWeapon *pSwitchingTo )
{ {
m_bRedraw = false; m_bRedraw = false;
m_bPinPulled = false; // when this is holstered make sure the pin isnt pulled. m_bPinPulled = false; // when this is holstered make sure the pin isn<EFBFBD>t pulled.
m_fThrowTime = 0; m_fThrowTime = 0;
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
@ -222,10 +222,11 @@ void CBaseCSGrenade::ItemPostFrame()
return; return;
// If they let go of the fire button, they want to throw the grenade. // If they let go of the fire button, they want to throw the grenade.
if ( m_bPinPulled && !(pPlayer->m_nButtons & IN_ATTACK) ) if ( m_bPinPulled && !(pPlayer->m_nButtons & IN_ATTACK) )
{ {
#ifndef CLIENT_DLL
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE ); pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE );
#endif
StartGrenadeThrow(); StartGrenadeThrow();
MDLCACHE_CRITICAL_SECTION(); MDLCACHE_CRITICAL_SECTION();

View file

@ -162,20 +162,20 @@ void WriteUsercmd( bf_write *buf, const CUserCmd *to, const CUserCmd *from )
// Write finally simulation data with entity index // Write finally simulation data with entity index
for ( unsigned int i = 0; i <= highestEntityIndex; i++ ) 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->WriteOneBit( 1 );
buf->WriteBitFloat( to->simulationdata[i].m_flSimulationTime ); buf->WriteBitFloat( to->simulationdata[i].lerp_time );
} }
else else
{ {
buf->WriteOneBit( 0 ); 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->WriteOneBit( 1 );
buf->WriteBitFloat( to->simulationdata[i].m_flAnimTime ); buf->WriteBitFloat( to->simulationdata[i].animated_sim_time );
} }
else else
{ {
@ -309,12 +309,12 @@ void ReadUsercmd( bf_read *buf, CUserCmd *move, CUserCmd *from )
{ {
if (buf->ReadOneBit()) if (buf->ReadOneBit())
{ {
move->simulationdata[i].m_flSimulationTime = buf->ReadBitFloat(); move->simulationdata[i].lerp_time = buf->ReadBitFloat();
} }
if (buf->ReadOneBit()) if (buf->ReadOneBit())
{ {
move->simulationdata[i].m_flAnimTime = buf->ReadBitFloat(); move->simulationdata[i].animated_sim_time = buf->ReadBitFloat();
} }
} }

View file

@ -30,7 +30,7 @@
#endif #endif
#define MAX_LAYER_RECORDS (CBaseAnimatingOverlay::MAX_OVERLAYS) #define MAX_LAYER_RECORDS (CBaseAnimatingOverlay::MAX_OVERLAYS)
#define MAX_POSE_PARAMETERS (CBaseAnimating::NUM_POSEPAREMETERS) #define MAX_POSE_PARAMETERS (MAXSTUDIOPOSEPARAM)
#define MAX_ENCODED_CONTROLLERS (MAXSTUDIOBONECTRLS) #define MAX_ENCODED_CONTROLLERS (MAXSTUDIOBONECTRLS)
class bf_read; class bf_read;
@ -57,9 +57,9 @@ struct SimulationData
// TODO_ENHANCED: // TODO_ENHANCED:
// For now we send the last received update for animations. // For now we send the last received update for animations.
// anim time is unreliable on low fps. // anim time is unreliable on low fps.
float m_flSimulationTime; float lerp_time;
float m_flAnimTime; float animated_sim_time;
bool m_bEntityExists; bool entityexists;
}; };
class CEntityGroundContact class CEntityGroundContact

View file

@ -1531,5 +1531,106 @@ private:
char *m_szBuffer; // a copy of original string, with '\0' instead of separators 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 #endif // CCVECTOR_H