Improved prediction & fix being 1 off tick problems

This commit is contained in:
Kamay Xutax 2024-07-13 19:18:03 +02:00
parent cd6ecdc726
commit f8c641a9e5
13 changed files with 120 additions and 52 deletions

View file

@ -1357,6 +1357,9 @@ public:
bool BecameDormantThisPacket( void ) const; bool BecameDormantThisPacket( void ) const;
void SetDormantPredictable( bool dormant ); void SetDormantPredictable( bool dormant );
// TODO_ENHANCED: make trigger predictables.
virtual void GetGroundVelocityToApply( Vector &vecGroundVel ) { vecGroundVel = GetBaseVelocity(); }
int GetWaterLevel() const; int GetWaterLevel() const;
void SetWaterLevel( int nLevel ); void SetWaterLevel( int nLevel );
int GetWaterType() const; int GetWaterType() const;

View file

@ -5,6 +5,7 @@
// $NoKeywords: $ // $NoKeywords: $
//=============================================================================// //=============================================================================//
#include "cbase.h" #include "cbase.h"
#include <stdarg.h> #include <stdarg.h>
#include "engine/IEngineSound.h" #include "engine/IEngineSound.h"
#include "filesystem.h" #include "filesystem.h"
@ -108,7 +109,20 @@ void CMoveHelperClient::ResetTouchList( void )
bool CMoveHelperClient::AddToTouched( const trace_t& tr, const Vector& impactvelocity ) bool CMoveHelperClient::AddToTouched( const trace_t& tr, const Vector& impactvelocity )
{ {
int i; int i;
auto pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer )
return false;
if ( !tr.m_pEnt )
return false;
if ( tr.m_pEnt == pPlayer->GetBaseEntity() )
{
Assert( !"CMoveHelperClient::AddToTouched: Tried to add self to touchlist!!!" );
return false;
}
// Look for duplicates // Look for duplicates
for (i = 0; i < m_TouchList.Size(); i++) for (i = 0; i < m_TouchList.Size(); i++)
@ -147,7 +161,11 @@ void CMoveHelperClient::ProcessImpacts( void )
// Touch other objects that were intersected during the movement. // Touch other objects that were intersected during the movement.
for (int i = 0 ; i < m_TouchList.Size(); i++) for (int i = 0 ; i < m_TouchList.Size(); i++)
{ {
// We didn't touch an entity ...
if (!m_TouchList[i].trace.m_pEnt)
continue;
// Run the impact function as if we had run it during movement. // Run the impact function as if we had run it during movement.
C_BaseEntity *entity = ClientEntityList().GetEnt( m_TouchList[i].trace.m_pEnt->entindex() ); C_BaseEntity *entity = ClientEntityList().GetEnt( m_TouchList[i].trace.m_pEnt->entindex() );
if ( !entity ) if ( !entity )

View file

@ -6,7 +6,9 @@
//=============================================================================// //=============================================================================//
#include "cbase.h" #include "cbase.h"
#include "prediction.h" #include "prediction.h"
#include "cdll_client_int.h"
#include "igamemovement.h" #include "igamemovement.h"
#include "mathlib/mathlib.h"
#include "prediction_private.h" #include "prediction_private.h"
#include "ivrenderview.h" #include "ivrenderview.h"
#include "iinput.h" #include "iinput.h"
@ -687,12 +689,26 @@ void CPrediction::FinishMove( C_BasePlayer *player, CUserCmd *ucmd, CMoveData *m
player->m_RefEHandle = move->m_nPlayerHandle; player->m_RefEHandle = move->m_nPlayerHandle;
player->m_vecVelocity = move->m_vecVelocity; player->SetLocalVelocity(move->m_vecVelocity);
player->m_vecNetworkOrigin = move->GetAbsOrigin(); player->m_vecNetworkOrigin = move->GetAbsOrigin();
player->m_Local.m_nOldButtons = move->m_nButtons; player->m_Local.m_nOldButtons = move->m_nButtons;
float pitch = move->m_vecAngles[PITCH];
if (pitch > 180.0f)
{
pitch -= 360.0f;
}
pitch = clamp(pitch, -90.f, 90.f);
move->m_vecAngles[PITCH] = pitch;
player->SetPoseParameter(player->LookupPoseParameter("body_pitch"), pitch);
player->SetLocalAngles(move->m_vecAngles);
// NOTE: Don't copy this. the movement code modifies its local copy but is not expecting to be authoritative // NOTE: Don't copy this. the movement code modifies its local copy but is not expecting to be authoritative
//player->m_flMaxspeed = move->m_flClientMaxSpeed; //player->m_flMaxspeed = move->m_flClientMaxSpeed;
@ -816,6 +832,39 @@ void CPrediction::RunPostThink( C_BasePlayer *player )
#endif #endif
} }
void CPrediction::CheckMovingGround( CBasePlayer *player, double frametime )
{
VPROF( "CPrediction::CheckMovingGround()" );
CBaseEntity *groundentity;
if ( player->GetFlags() & FL_ONGROUND )
{
groundentity = player->GetGroundEntity();
if ( groundentity && ( groundentity->GetFlags() & FL_CONVEYOR) )
{
Vector vecNewVelocity;
groundentity->GetGroundVelocityToApply( vecNewVelocity );
if ( player->GetFlags() & FL_BASEVELOCITY )
{
vecNewVelocity += player->GetBaseVelocity();
}
player->SetBaseVelocity( vecNewVelocity );
player->AddFlag( FL_BASEVELOCITY );
}
}
if ( !( player->GetFlags() & FL_BASEVELOCITY ) )
{
// Apply momentum (add in half of the previous frame of velocity first)
player->ApplyAbsVelocityImpulse( (1.0 + ( frametime * 0.5 )) * player->GetBaseVelocity() );
player->SetBaseVelocity( vec3_origin );
}
player->RemoveFlag( FL_BASEVELOCITY );
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Predicts a single movement command for player // Purpose: Predicts a single movement command for player
// Input : *moveHelper - // Input : *moveHelper -
@ -830,15 +879,20 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
char sz[ 32 ]; char sz[ 32 ];
Q_snprintf( sz, sizeof( sz ), "runcommand%04d", ucmd->command_number ); Q_snprintf( sz, sizeof( sz ), "runcommand%04d", ucmd->command_number );
PREDICTION_TRACKVALUECHANGESCOPE( sz ); PREDICTION_TRACKVALUECHANGESCOPE( sz );
#endif #endif
StartCommand( player, ucmd ); StartCommand( player, ucmd );
// Set globals appropriately
gpGlobals->curtime = player->m_nTickBase * TICK_INTERVAL;
gpGlobals->frametime = m_bEnginePaused ? 0 : TICK_INTERVAL;
g_pGameMovement->StartTrackPredictionErrors( player ); g_pGameMovement->StartTrackPredictionErrors( player );
gpGlobals->frametime = m_bEnginePaused ? 0 : TICK_INTERVAL;
// Run post think after PreThink/Think function, this makes a room space for local interpolation.
gpGlobals->curtime = (player->m_nTickBase - 1) * TICK_INTERVAL;
RunPostThink( player );
gpGlobals->curtime = player->m_nTickBase * TICK_INTERVAL;
// TODO // TODO
// TODO: Check for impulse predicted? // TODO: Check for impulse predicted?
@ -868,11 +922,20 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
// Get button states // Get button states
player->UpdateButtonState( ucmd->buttons ); player->UpdateButtonState( ucmd->buttons );
// TODO // CheckMovingGround( player, gpGlobals->frametime );
// CheckMovingGround( player, ucmd->frametime );
// TODO g_pMoveData->m_vecOldAngles = player->pl.v_angle;
// g_pMoveData->m_vecOldAngles = player->pl.v_angle;
// TODO_ENHANCED: this will be implemented with trigger prediction update
// // Copy from command to player unless game .dll has set angle using fixangle
// if ( player->pl.fixangle == FIXANGLE_NONE )
// {
// player->pl.v_angle = ucmd->viewangles;
// }
// else if( player->pl.fixangle == FIXANGLE_RELATIVE )
// {
// player->pl.v_angle = ucmd->viewangles + player->pl.anglechange;
// }
// Copy from command to player unless game .dll has set angle using fixangle // Copy from command to player unless game .dll has set angle using fixangle
// if ( !player->pl.fixangle ) // if ( !player->pl.fixangle )
@ -905,7 +968,7 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
FinishMove( player, ucmd, g_pMoveData ); FinishMove( player, ucmd, g_pMoveData );
RunPostThink( player ); moveHelper->ProcessImpacts();
g_pGameMovement->FinishTrackPredictionErrors( player ); g_pGameMovement->FinishTrackPredictionErrors( player );

View file

@ -91,7 +91,7 @@ protected:
void RunPreThink( C_BasePlayer *player ); void RunPreThink( C_BasePlayer *player );
void RunThink (C_BasePlayer *ent, double frametime ); void RunThink (C_BasePlayer *ent, double frametime );
void RunPostThink( C_BasePlayer *player ); void RunPostThink( C_BasePlayer *player );
void CheckMovingGround( CBasePlayer *player, double frametime );
private: private:
virtual void _Update virtual void _Update
( (

View file

@ -210,7 +210,6 @@ public:
SetAbsVelocity( m_hPlayer->GetAbsVelocity() ); SetAbsVelocity( m_hPlayer->GetAbsVelocity() );
AddSolidFlags( FSOLID_NOT_SOLID ); AddSolidFlags( FSOLID_NOT_SOLID );
ChangeTeam( m_hPlayer->GetTeamNumber() ); ChangeTeam( m_hPlayer->GetTeamNumber() );
// UseClientSideAnimation();
} }
public: public:
@ -417,9 +416,6 @@ CCSPlayer::CCSPlayer()
{ {
m_PlayerAnimState = CreatePlayerAnimState( this, this, LEGANIM_9WAY, true ); m_PlayerAnimState = CreatePlayerAnimState( this, this, LEGANIM_9WAY, true );
// TODO: one day we need to remove this shit.
// UseClientSideAnimation();
m_iLastWeaponFireUsercmd = 0; m_iLastWeaponFireUsercmd = 0;
m_iAddonBits = 0; m_iAddonBits = 0;
m_bEscaped = false; m_bEscaped = false;

View file

@ -103,9 +103,6 @@ CHostage::CHostage()
{ {
g_Hostages.AddToTail( this ); g_Hostages.AddToTail( this );
m_PlayerAnimState = CreateHostageAnimState( this, this, LEGANIM_8WAY, false ); m_PlayerAnimState = CreateHostageAnimState( this, this, LEGANIM_8WAY, false );
// ENHANCED_TODO: remove this
// UseClientSideAnimation();
SetBloodColor( BLOOD_COLOR_RED ); SetBloodColor( BLOOD_COLOR_RED );
} }

View file

@ -7913,14 +7913,6 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data)
} }
} }
void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID)
{
int mask = (1<<PLAYER_FLAG_BITS) - 1;
int data = *(int *)pVarData;
pOut->m_Int = ( data & mask );
}
// -------------------------------------------------------------------------------- // // -------------------------------------------------------------------------------- //
// SendTable for CPlayerState. // SendTable for CPlayerState.
// -------------------------------------------------------------------------------- // // -------------------------------------------------------------------------------- //
@ -8003,7 +7995,7 @@ void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const voi
SendPropInt (SENDINFO(m_iBonusProgress), 15 ), SendPropInt (SENDINFO(m_iBonusProgress), 15 ),
SendPropInt (SENDINFO(m_iBonusChallenge), 4 ), SendPropInt (SENDINFO(m_iBonusChallenge), 4 ),
SendPropFloat (SENDINFO(m_flMaxspeed), 12, SPROP_ROUNDDOWN, 0.0f, 2048.0f ), // CL SendPropFloat (SENDINFO(m_flMaxspeed), 12, SPROP_ROUNDDOWN, 0.0f, 2048.0f ), // CL
SendPropInt (SENDINFO(m_fFlags), PLAYER_FLAG_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN, SendProxy_CropFlagsToPlayerFlagBitsLength ), SendPropInt (SENDINFO(m_fFlags)),
SendPropInt (SENDINFO(m_iObserverMode), 3, SPROP_UNSIGNED ), SendPropInt (SENDINFO(m_iObserverMode), 3, SPROP_UNSIGNED ),
SendPropEHandle (SENDINFO(m_hObserverTarget) ), SendPropEHandle (SENDINFO(m_hObserverTarget) ),
SendPropInt (SENDINFO(m_iFOV), 8, SPROP_UNSIGNED ), SendPropInt (SENDINFO(m_iFOV), 8, SPROP_UNSIGNED ),

View file

@ -316,7 +316,6 @@ void CommentarySystem_PePlayerRunCommand( CBasePlayer *player, CUserCmd *ucmd );
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *moveHelper ) void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *moveHelper )
{ {
const float playerCurTime = player->m_nTickBase * TICK_INTERVAL;
const float playerFrameTime = player->m_bGamePaused ? 0 : TICK_INTERVAL; const float playerFrameTime = player->m_bGamePaused ? 0 : TICK_INTERVAL;
const float flTimeAllowedForProcessing = player->ConsumeMovementTimeForUserCmdProcessing( playerFrameTime ); const float flTimeAllowedForProcessing = player->ConsumeMovementTimeForUserCmdProcessing( playerFrameTime );
if ( !player->IsBot() && ( flTimeAllowedForProcessing < playerFrameTime ) ) if ( !player->IsBot() && ( flTimeAllowedForProcessing < playerFrameTime ) )
@ -334,13 +333,20 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
} }
} }
return; // Don't process this command return; // Don't process this command
} }
StartCommand( player, ucmd ); StartCommand( player, ucmd );
g_pGameMovement->StartTrackPredictionErrors( player );
gpGlobals->frametime = playerFrameTime;
gpGlobals->curtime = (player->m_nTickBase - 1) * TICK_INTERVAL;
// Run post think first, this will let some space for client side interpolation.
RunPostThink( player );
// Set globals appropriately // Set globals appropriately
gpGlobals->curtime = playerCurTime; gpGlobals->curtime = player->m_nTickBase * TICK_INTERVAL;
gpGlobals->frametime = playerFrameTime;
extern ConVar sv_showhitboxes; extern ConVar sv_showhitboxes;
@ -381,8 +387,6 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
} }
*/ */
g_pGameMovement->StartTrackPredictionErrors( player );
CommentarySystem_PePlayerRunCommand( player, ucmd ); CommentarySystem_PePlayerRunCommand( player, ucmd );
// Do weapon selection // Do weapon selection
@ -453,13 +457,11 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
// 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 );
g_pGameMovement->FinishTrackPredictionErrors( player ); g_pGameMovement->FinishTrackPredictionErrors( player );
FinishCommand( player ); FinishCommand( player );

View file

@ -440,7 +440,7 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
return; return;
} }
// TODO: do proper teleportation checks. // TODO_ENHANCED: do proper teleportation checks.
// did we find a context smaller than target time ? // did we find a context smaller than target time ?
if ( recordSim->m_flSimulationTime <= flTargetSimulationTime ) if ( recordSim->m_flSimulationTime <= flTargetSimulationTime )

View file

@ -70,7 +70,7 @@ BEGIN_NETWORK_TABLE( CBaseGrenade, DT_BaseGrenade )
SendPropVector( SENDINFO( m_vecVelocity ), 0, SPROP_NOSCALE ), SendPropVector( SENDINFO( m_vecVelocity ), 0, SPROP_NOSCALE ),
// HACK: Use same flag bits as player for now // HACK: Use same flag bits as player for now
SendPropInt ( SENDINFO(m_fFlags), PLAYER_FLAG_BITS, SPROP_UNSIGNED, SendProxy_CropFlagsToPlayerFlagBitsLength ), SendPropInt ( SENDINFO(m_fFlags) ),
#else #else
RecvPropFloat( RECVINFO( m_flDamage ) ), RecvPropFloat( RECVINFO( m_flDamage ) ),
RecvPropFloat( RECVINFO( m_DmgRadius ) ), RecvPropFloat( RECVINFO( m_DmgRadius ) ),

2
ivp

@ -1 +1 @@
Subproject commit 47533475e01cbff05fbc3bbe8b4edc485f292cea Subproject commit c7c407320533bdce609712dbd535862a065c7da7

View file

@ -32,16 +32,15 @@ public:
CNetworkVar( bool, deadflag ); CNetworkVar( bool, deadflag );
// Viewing angle (player only) // Viewing angle (player only)
QAngle v_angle; QAngle v_angle;
// 0:nothing, 1:force view angles, 2:add avelocity
int fixangle;
// delta angle for fixangle == FIXANGLE_RELATIVE
QAngle anglechange;
// The client .dll only cares about deadflag // The client .dll only cares about deadflag
// the game and engine .dlls need to worry about the rest of this data // the game and engine .dlls need to worry about the rest of this data
#if !defined( CLIENT_DLL ) #if !defined( CLIENT_DLL )
// Player's network name // Player's network name
string_t netname; string_t netname;
// 0:nothing, 1:force view angles, 2:add avelocity
int fixangle;
// delta angle for fixangle == FIXANGLE_RELATIVE
QAngle anglechange;
// flag to single the HLTV/Replay fake client, not transmitted // flag to single the HLTV/Replay fake client, not transmitted
bool hltv; bool hltv;
bool replay; bool replay;

View file

@ -161,8 +161,6 @@
// NON-PLAYER SPECIFIC (i.e., not used by GameMovement or the client .dll ) -- Can still be applied to players, though // NON-PLAYER SPECIFIC (i.e., not used by GameMovement or the client .dll ) -- Can still be applied to players, though
#define FL_INWATER (1<<10) // In water #define FL_INWATER (1<<10) // In water
// NOTE if you move things up, make sure to change this value
#define PLAYER_FLAG_BITS 11
#define FL_FLY (1<<11) // Changes the SV_Movestep() behavior to not need to be on ground #define FL_FLY (1<<11) // Changes the SV_Movestep() behavior to not need to be on ground
#define FL_SWIM (1<<12) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water) #define FL_SWIM (1<<12) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water)