diff --git a/game/client/c_baseplayer.cpp b/game/client/c_baseplayer.cpp index 6b415be115..28f9faec28 100644 --- a/game/client/c_baseplayer.cpp +++ b/game/client/c_baseplayer.cpp @@ -254,8 +254,7 @@ END_RECV_TABLE() RecvPropInt ( RECVINFO( m_nWaterLevel ) ), RecvPropFloat ( RECVINFO( m_flLaggedMovementValue )), - RecvPropVector(RECVINFO(m_vecPreviouslyPredictedOrigin)), - RecvPropVector(RECVINFO(m_vecPreviousShootPosition)), + RecvPropVector(RECVINFO(m_vecPreviouslyPredictedOrigin)) END_RECV_TABLE() @@ -376,7 +375,6 @@ BEGIN_PREDICTION_DATA( C_BasePlayer ) DEFINE_PRED_FIELD_TOL( m_vecBaseVelocity, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.05 ), DEFINE_PRED_FIELD_TOL(m_vecPreviouslyPredictedOrigin, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, coordTolerance), - DEFINE_PRED_FIELD_TOL(m_vecPreviousShootPosition, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, coordTolerance), DEFINE_FIELD( m_nButtons, FIELD_INTEGER ), DEFINE_FIELD( m_flWaterJumpTime, FIELD_FLOAT ), DEFINE_FIELD( m_nImpulse, FIELD_INTEGER ), diff --git a/game/client/c_baseplayer.h b/game/client/c_baseplayer.h index 3f5195c20d..068fcf398a 100644 --- a/game/client/c_baseplayer.h +++ b/game/client/c_baseplayer.h @@ -652,7 +652,6 @@ public: float m_fLastUpdateServerTime; int m_nLastUpdateTickBase; int m_nLastUpdateServerTickCount; - Vector m_vecPreviousShootPosition; }; EXTERN_RECV_TABLE(DT_BasePlayer); diff --git a/game/client/prediction.cpp b/game/client/prediction.cpp index 7deca43b39..e298900a4e 100644 --- a/game/client/prediction.cpp +++ b/game/client/prediction.cpp @@ -769,13 +769,14 @@ void CPrediction::StartCommand( C_BasePlayer *player, CUserCmd *cmd ) #if !defined( NO_ENTITY_PREDICTION ) VPROF( "CPrediction::StartCommand" ); - player->m_vecPreviousShootPosition = player->Weapon_ShootPosition(); - CPredictableId::ResetInstanceCounters(); player->m_pCurrentCommand = cmd; C_BaseEntity::SetPredictionRandomSeed( cmd ); C_BaseEntity::SetPredictionPlayer( player ); + + InterpolationContexts[BEFORE_MOVEMENT].m_vecViewOffset = player->GetViewOffset(); + InterpolationContexts[BEFORE_MOVEMENT].m_vecAbsOrigin = player->GetAbsOrigin(); #endif } @@ -843,6 +844,40 @@ void CPrediction::RunThink (C_BasePlayer *player, double frametime ) #endif } +void CPrediction::StartInterpolatingPlayer( C_BasePlayer *player ) +{ +#if !defined( NO_ENTITY_PREDICTION ) + VPROF( "CPrediction::StartInterpolatingPlayer" ); + + // Let's interpolate the local player, this is similar to lag compensation, + // except it isn't since local player is always predicted. (except if user didn't want to for some reasons) + InterpolationContexts[AFTER_MOVEMENT].m_vecViewOffset = player->GetViewOffset(); + InterpolationContexts[AFTER_MOVEMENT].m_vecAbsOrigin = player->GetAbsOrigin(); + + auto pCmd = player->m_pCurrentCommand; + + Vector vecNewAbsOrigin = VectorLerp( InterpolationContexts[BEFORE_MOVEMENT].m_vecAbsOrigin, + InterpolationContexts[AFTER_MOVEMENT].m_vecAbsOrigin, + pCmd->interpolated_amount ); + Vector vecNewViewOffset = VectorLerp( InterpolationContexts[BEFORE_MOVEMENT].m_vecViewOffset, + InterpolationContexts[AFTER_MOVEMENT].m_vecViewOffset, + pCmd->interpolated_amount ); + + player->SetAbsOrigin( vecNewAbsOrigin ); + player->SetViewOffset( vecNewViewOffset ); +#endif +} + +void CPrediction::FinishInterpolatingPlayer( C_BasePlayer *player ) +{ +#if !defined( NO_ENTITY_PREDICTION ) + VPROF( "CPrediction::FinishInterpolatingPlayer" ); + + player->SetAbsOrigin( InterpolationContexts[AFTER_MOVEMENT].m_vecAbsOrigin ); + player->SetViewOffset( InterpolationContexts[AFTER_MOVEMENT].m_vecViewOffset ); +#endif +} + //----------------------------------------------------------------------------- // Purpose: Called after player movement // Input : *player - @@ -992,8 +1027,12 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper moveHelper->ProcessImpacts(); + StartInterpolatingPlayer( player ); + RunPostThink( player ); + FinishInterpolatingPlayer( player ); + ServiceEventQueue( player ); g_pGameMovement->FinishTrackPredictionErrors( player ); diff --git a/game/client/prediction.h b/game/client/prediction.h index 53bf47a75f..cc7f4c7cdd 100644 --- a/game/client/prediction.h +++ b/game/client/prediction.h @@ -96,6 +96,8 @@ protected: // Helpers to call pre and post think for player, and to call think if a think function is set void RunPreThink( C_BasePlayer *player ); void RunThink (C_BasePlayer *ent, double frametime ); + void StartInterpolatingPlayer( C_BasePlayer* player ); + void FinishInterpolatingPlayer( C_BasePlayer* player ); void RunPostThink( C_BasePlayer *player ); void CheckMovingGround( CBasePlayer *player, double frametime ); private: @@ -166,6 +168,20 @@ private: }; TouchedHistory m_touchedHistory[MULTIPLAYER_BACKUP][MAX_EDICTS]; + + // TODO_ENHANCED: checks if this affects vehicles properly too! It should. + enum INTERPOLATION_CONTEXT + { + BEFORE_MOVEMENT, + AFTER_MOVEMENT, + INTERPOLATION_CONTEXT_MAX + }; + + struct InterpolationContext + { + Vector m_vecAbsOrigin; + Vector m_vecViewOffset; + } InterpolationContexts[INTERPOLATION_CONTEXT_MAX]; }; extern CPrediction *prediction; diff --git a/game/server/player.cpp b/game/server/player.cpp index b04feed755..4d2c0296ea 100644 --- a/game/server/player.cpp +++ b/game/server/player.cpp @@ -451,8 +451,7 @@ BEGIN_DATADESC( CBasePlayer ) DEFINE_FIELD( m_bDuckToggled, FIELD_BOOLEAN ), DEFINE_FIELD( m_flForwardMove, FIELD_FLOAT ), DEFINE_FIELD( m_flSideMove, FIELD_FLOAT ), - DEFINE_FIELD( m_vecPreviouslyPredictedOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecPreviousShootPosition, FIELD_POSITION_VECTOR ), + DEFINE_FIELD( m_vecPreviouslyPredictedOrigin, FIELD_POSITION_VECTOR ), DEFINE_FIELD( m_nNumCrateHudHints, FIELD_INTEGER ), @@ -7971,8 +7970,7 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data) SendPropInt ( SENDINFO( m_nWaterLevel ), 2, SPROP_UNSIGNED ), SendPropFloat ( SENDINFO( m_flLaggedMovementValue ), 0, SPROP_NOSCALE ), - SendPropVector ( SENDINFO( m_vecPreviouslyPredictedOrigin ), 0, SPROP_NOSCALE), - SendPropVector ( SENDINFO( m_vecPreviousShootPosition ), 0, SPROP_NOSCALE), + SendPropVector ( SENDINFO( m_vecPreviouslyPredictedOrigin ), 0, SPROP_NOSCALE) END_SEND_TABLE() diff --git a/game/server/player.h b/game/server/player.h index 460a1ce616..3a720b367c 100644 --- a/game/server/player.h +++ b/game/server/player.h @@ -1212,7 +1212,6 @@ private: public: virtual unsigned int PlayerSolidMask( bool brushOnly = false ) const; // returns the solid mask for the given player, so bots can have a more-restrictive set - CNetworkVar(Vector, m_vecPreviousShootPosition); }; typedef CHandle CBasePlayerHandle; diff --git a/game/server/player_command.cpp b/game/server/player_command.cpp index b6a1e35785..95078a7323 100644 --- a/game/server/player_command.cpp +++ b/game/server/player_command.cpp @@ -48,8 +48,6 @@ void CPlayerMove::StartCommand( CBasePlayer *player, CUserCmd *cmd ) { VPROF( "CPlayerMove::StartCommand" ); - player->m_vecPreviousShootPosition = player->Weapon_ShootPosition(); - #if !defined( NO_ENTITY_PREDICTION ) CPredictableId::ResetInstanceCounters(); #endif @@ -57,7 +55,10 @@ void CPlayerMove::StartCommand( CBasePlayer *player, CUserCmd *cmd ) player->m_pCurrentCommand = cmd; CBaseEntity::SetPredictionRandomSeed( cmd ); CBaseEntity::SetPredictionPlayer( player ); - + + InterpolationContexts[BEFORE_MOVEMENT].m_vecViewOffset = player->GetViewOffset(); + InterpolationContexts[BEFORE_MOVEMENT].m_vecAbsOrigin = player->GetAbsOrigin(); + #if defined (HL2_DLL) // pull out backchannel data and move this out @@ -298,6 +299,36 @@ void CPlayerMove::RunThink (CBasePlayer *player, double frametime ) player->Think(); } +void CPlayerMove::StartInterpolatingPlayer( CBasePlayer *player ) +{ + VPROF( "CPlayerMove::StartInterpolatingPlayer" ); + + // Let's interpolate the local player, this is similar to lag compensation, + // except it isn't since local player is always predicted. (except if user didn't want to for some reasons) + InterpolationContexts[AFTER_MOVEMENT].m_vecViewOffset = player->GetViewOffset(); + InterpolationContexts[AFTER_MOVEMENT].m_vecAbsOrigin = player->GetAbsOrigin(); + + auto pCmd = player->m_pCurrentCommand; + + Vector vecNewAbsOrigin = VectorLerp( InterpolationContexts[BEFORE_MOVEMENT].m_vecAbsOrigin, + InterpolationContexts[AFTER_MOVEMENT].m_vecAbsOrigin, + pCmd->interpolated_amount ); + Vector vecNewViewOffset = VectorLerp( InterpolationContexts[BEFORE_MOVEMENT].m_vecViewOffset, + InterpolationContexts[AFTER_MOVEMENT].m_vecViewOffset, + pCmd->interpolated_amount ); + + player->SetAbsOrigin( vecNewAbsOrigin ); + player->SetViewOffset( vecNewViewOffset ); +} + +void CPlayerMove::FinishInterpolatingPlayer( CBasePlayer *player ) +{ + VPROF( "CPlayerMove::FinishInterpolatingPlayer" ); + + player->SetAbsOrigin( InterpolationContexts[AFTER_MOVEMENT].m_vecAbsOrigin ); + player->SetViewOffset( InterpolationContexts[AFTER_MOVEMENT].m_vecViewOffset ); +} + //----------------------------------------------------------------------------- // Purpose: Called after player movement // Input : *player - @@ -458,8 +489,12 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper moveHelper->ProcessImpacts(); VPROF_SCOPE_END(); + StartInterpolatingPlayer( player ); + RunPostThink( player ); + FinishInterpolatingPlayer( player ); + ServiceEventQueue( player ); g_pGameMovement->FinishTrackPredictionErrors( player ); diff --git a/game/server/player_command.h b/game/server/player_command.h index 574fc8dd33..ca4c2dedfb 100644 --- a/game/server/player_command.h +++ b/game/server/player_command.h @@ -52,6 +52,22 @@ protected: void RunPreThink( CBasePlayer *player ); void RunThink (CBasePlayer *ent, double frametime ); void RunPostThink( CBasePlayer *player ); + void StartInterpolatingPlayer( CBasePlayer* player ); + void FinishInterpolatingPlayer( CBasePlayer* player ); + + // TODO_ENHANCED: checks if this affects vehicles properly too! It should. + enum INTERPOLATION_CONTEXT + { + BEFORE_MOVEMENT, + AFTER_MOVEMENT, + INTERPOLATION_CONTEXT_MAX + }; + + struct InterpolationContext + { + Vector m_vecAbsOrigin; + Vector m_vecViewOffset; + } InterpolationContexts[INTERPOLATION_CONTEXT_MAX]; }; diff --git a/game/shared/cstrike/cs_player_shared.cpp b/game/shared/cstrike/cs_player_shared.cpp index 8f934f9e04..aa6d53963a 100644 --- a/game/shared/cstrike/cs_player_shared.cpp +++ b/game/shared/cstrike/cs_player_shared.cpp @@ -46,7 +46,6 @@ ConVar weapon_accuracy_nospread( "weapon_accuracy_nospread", "0", FCVAR_REPLICAT void DispatchEffect( const char *pName, const CEffectData &data ); - #ifdef _DEBUG // This is some extra code to collect weapon accuracy stats: diff --git a/game/shared/cstrike/fx_cs_shared.cpp b/game/shared/cstrike/fx_cs_shared.cpp index eab95327b8..4da366f6d0 100644 --- a/game/shared/cstrike/fx_cs_shared.cpp +++ b/game/shared/cstrike/fx_cs_shared.cpp @@ -154,10 +154,10 @@ void FX_FireBullets( #endif } - if ( playerCmd ) - { - vHookedOrigin = VectorLerp( pPlayer->m_vecPreviousShootPosition, vOrigin, playerCmd->interpolated_amount ); - } +// if ( playerCmd ) +// { +// vHookedOrigin = VectorLerp( pPlayer->m_vecPreviousEyePosition, vOrigin, playerCmd->interpolated_amount ); +// } // #ifndef CLIENT_DLL // DevMsg("server new shoot pos: %f %f %f - %f, has command: %s\n", vHookedOrigin.x, vHookedOrigin.y, vHookedOrigin.z, playerCmd->interpolated_amount, playerCmd ? "true" : "false" ); diff --git a/game/shared/cstrike/weapon_knife.cpp b/game/shared/cstrike/weapon_knife.cpp index 5945d7edd2..3b2010f057 100644 --- a/game/shared/cstrike/weapon_knife.cpp +++ b/game/shared/cstrike/weapon_knife.cpp @@ -334,18 +334,18 @@ bool CKnife::SwingOrStab( bool bStab ) Vector vForward; AngleVectors( pPlayer->EyeAngles(), &vForward ); Vector vecSrc = pPlayer->Weapon_ShootPosition(); - CUserCmd* playerCmd = NULL; +// CUserCmd* playerCmd = NULL; -#ifdef CLIENT_DLL - playerCmd = pPlayer->m_pCurrentCommand; -#else - playerCmd = pPlayer->GetCurrentCommand(); -#endif +// #ifdef CLIENT_DLL +// playerCmd = pPlayer->m_pCurrentCommand; +// #else +// playerCmd = pPlayer->GetCurrentCommand(); +// #endif - if (playerCmd) - { - vecSrc = VectorLerp(pPlayer->m_vecPreviousShootPosition, vecSrc, playerCmd->interpolated_amount); - } +// if (playerCmd) +// { +// vecSrc = VectorLerp(pPlayer->m_vecPreviousEyePosition, vecSrc, playerCmd->interpolated_amount); +// } Vector vecEnd = vecSrc + vForward * fRange;