diff --git a/engine/host.cpp b/engine/host.cpp index 0ec1511476..3ed5781497 100644 --- a/engine/host.cpp +++ b/engine/host.cpp @@ -2655,9 +2655,18 @@ void _Host_RunFrame_Input( float accumulated_extra_samples, bool bFinalTick ) g_HostTimes.EndFrameSegment( FRAME_SEGMENT_CMD_EXECUTE ); + // TODO_ENHANCED: HACKHACK: + // the player is one frame in late because interpolation amount is calculated after CreateMove + // Just in case, we set it there too to interpolate with correct data! + + float old_interpolation_amount = g_ClientGlobalVariables.interpolation_amount; + g_ClientGlobalVariables.interpolation_amount = cl.m_tickRemainder / host_state.interval_per_tick; + // Send any current movement commands to server and flush reliable buffer even if not moving yet. CL_Move( accumulated_extra_samples, bFinalTick ); + g_ClientGlobalVariables.interpolation_amount = old_interpolation_amount; + #endif g_HostTimes.EndFrameSegment( FRAME_SEGMENT_INPUT ); diff --git a/game/client/c_baseplayer.h b/game/client/c_baseplayer.h index 1910f4a13e..460d143147 100644 --- a/game/client/c_baseplayer.h +++ b/game/client/c_baseplayer.h @@ -649,6 +649,7 @@ public: float m_fLastUpdateServerTime; int m_nLastUpdateTickBase; int m_nLastUpdateServerTickCount; + Vector m_vecPreviousShootPosition; }; EXTERN_RECV_TABLE(DT_BasePlayer); diff --git a/game/client/in_main.cpp b/game/client/in_main.cpp index 3a6c743d87..e0f94d4112 100644 --- a/game/client/in_main.cpp +++ b/game/client/in_main.cpp @@ -15,6 +15,8 @@ #include #include "bone_setup.h" #include "convar.h" +#include "imovehelper.h" +#include "ipredictionsystem.h" #include "studio.h" #include "util_shared.h" #include "c_baseplayer.h" @@ -1330,16 +1332,7 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo } #endif - C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer(); - - if (pPlayer) - { - cmd->interpolated_shoot_position = pPlayer->Weapon_ShootPosition(); - } - else - { - cmd->interpolated_shoot_position.Init(); - } + cmd->interpolated_amount = gpGlobals->interpolation_amount; pVerified->m_cmd = *cmd; pVerified->m_crc = cmd->GetChecksum(); diff --git a/game/client/prediction.cpp b/game/client/prediction.cpp index ad468fd745..b7ba3f32c0 100644 --- a/game/client/prediction.cpp +++ b/game/client/prediction.cpp @@ -769,6 +769,8 @@ 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; @@ -919,12 +921,6 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper player->SetLocalViewAngles( ucmd->viewangles ); } - moveHelper->ProcessImpacts(); - - RunPostThink( player ); - - ServiceEventQueue( player ); - // TODO // TODO: Check for impulse predicted? @@ -994,6 +990,12 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper FinishMove( player, ucmd, g_pMoveData ); + moveHelper->ProcessImpacts(); + + RunPostThink( player ); + + ServiceEventQueue( player ); + g_pGameMovement->FinishTrackPredictionErrors( player ); FinishCommand( player ); diff --git a/game/server/player.h b/game/server/player.h index 017368df09..1412731da7 100644 --- a/game/server/player.h +++ b/game/server/player.h @@ -1211,6 +1211,7 @@ 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 + Vector m_vecPreviousShootPosition; }; typedef CHandle CBasePlayerHandle; diff --git a/game/server/player_command.cpp b/game/server/player_command.cpp index 883c61e431..410436b7a6 100644 --- a/game/server/player_command.cpp +++ b/game/server/player_command.cpp @@ -48,6 +48,8 @@ void CPlayerMove::StartCommand( CBasePlayer *player, CUserCmd *cmd ) { VPROF( "CPlayerMove::StartCommand" ); + player->m_vecPreviousShootPosition = player->Weapon_ShootPosition(); + #if !defined( NO_ENTITY_PREDICTION ) CPredictableId::ResetInstanceCounters(); #endif @@ -353,15 +355,6 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper ucmd->viewangles = vec3_angle; } - // Let server invoke any needed impact functions - VPROF_SCOPE_BEGIN( "moveHelper->ProcessImpacts" ); - moveHelper->ProcessImpacts(); - VPROF_SCOPE_END(); - - RunPostThink( player ); - - ServiceEventQueue( player ); - // Add and subtract buttons we're forcing on the player ucmd->buttons |= player->m_afButtonForced; ucmd->buttons &= ~player->m_afButtonDisabled; @@ -457,6 +450,15 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper // Copy output FinishMove( player, ucmd, g_pMoveData ); + // Let server invoke any needed impact functions + VPROF_SCOPE_BEGIN( "moveHelper->ProcessImpacts" ); + moveHelper->ProcessImpacts(); + VPROF_SCOPE_END(); + + RunPostThink( player ); + + ServiceEventQueue( player ); + g_pGameMovement->FinishTrackPredictionErrors( player ); FinishCommand( player ); diff --git a/game/shared/cstrike/fx_cs_shared.cpp b/game/shared/cstrike/fx_cs_shared.cpp index a60a5decee..f00708eb1b 100644 --- a/game/shared/cstrike/fx_cs_shared.cpp +++ b/game/shared/cstrike/fx_cs_shared.cpp @@ -7,6 +7,8 @@ #include "cbase.h" #include "fx_cs_shared.h" #include "convar.h" +#include "mathlib/vector.h" +#include "usercmd.h" #include "weapon_csbase.h" #ifndef CLIENT_DLL @@ -135,19 +137,26 @@ void FX_FireBullets( CCSPlayer *pPlayer = ToCSPlayer( UTIL_PlayerByIndex( iPlayerIndex) ); #endif - // TODO_ENHANCED: - // Check if interpolated_shoot_position is within interpolation bounds! (between old shoot pos and new) - // This is to check for cheaters abusing the shooting position. + // DevMsg("original shoot pos: %f %f %f\n", vHookedOrigin.x, vHookedOrigin.y, vHookedOrigin.z ); + + CUserCmd* playerCmd = NULL; if (pPlayer) { #ifdef CLIENT_DLL - if (pPlayer->m_pCurrentCommand) { vHookedOrigin = pPlayer->m_pCurrentCommand->interpolated_shoot_position; } + playerCmd = pPlayer->m_pCurrentCommand; #else - if (pPlayer->GetCurrentCommand()) { vHookedOrigin = pPlayer->GetCurrentCommand()->interpolated_shoot_position; } + playerCmd = pPlayer->GetCurrentCommand(); #endif } - + + if (playerCmd) + { + vHookedOrigin = VectorLerp(pPlayer->m_vecPreviousShootPosition, vOrigin, playerCmd->interpolated_amount); + } + + // DevMsg("new shoot pos: %f %f %f, has command: %s\n", vHookedOrigin.x, vHookedOrigin.y, vHookedOrigin.z, playerCmd ? "true" : "false" ); + const char * weaponAlias = WeaponIDToAlias( iWeaponID ); if ( !weaponAlias ) diff --git a/game/shared/cstrike/weapon_knife.cpp b/game/shared/cstrike/weapon_knife.cpp index 9bc549b915..2cef0f38e6 100644 --- a/game/shared/cstrike/weapon_knife.cpp +++ b/game/shared/cstrike/weapon_knife.cpp @@ -339,7 +339,24 @@ bool CKnife::SwingOrStab( bool bStab ) float fRange = bStab ? 32 : 48; // knife range Vector vForward; AngleVectors( pPlayer->EyeAngles(), &vForward ); + Vector vecSrc = pPlayer->Weapon_ShootPosition(); + CUserCmd* playerCmd = NULL; + + if (pPlayer) + { +#ifdef CLIENT_DLL + playerCmd = pPlayer->m_pCurrentCommand; +#else + playerCmd = pPlayer->GetCurrentCommand(); +#endif + } + + if (playerCmd) + { + vecSrc = VectorLerp(pPlayer->m_vecPreviousShootPosition, vecSrc, playerCmd->interpolated_amount); + } + Vector vecEnd = vecSrc + vForward * fRange; trace_t tr; diff --git a/game/shared/usercmd.h b/game/shared/usercmd.h index f10dfaea28..764e88c0a7 100644 --- a/game/shared/usercmd.h +++ b/game/shared/usercmd.h @@ -106,7 +106,7 @@ public: entitygroundcontact.RemoveAll(); #endif - interpolated_shoot_position.Init(); + interpolated_amount = 0.0f; } CUserCmd& operator =( const CUserCmd& src ) @@ -139,7 +139,7 @@ public: entitygroundcontact = src.entitygroundcontact; #endif - interpolated_shoot_position = src.interpolated_shoot_position; + interpolated_amount = src.interpolated_amount; return *this; } @@ -168,7 +168,7 @@ public: CRC32_ProcessBuffer(&crc, &mousedy, sizeof(mousedy)); CRC32_ProcessBuffer(&crc, simulationdata, sizeof(simulationdata)); CRC32_ProcessBuffer(&crc, &debug_hitboxes, sizeof(debug_hitboxes)); - CRC32_ProcessBuffer( &crc, &interpolated_shoot_position, sizeof(interpolated_shoot_position)); + CRC32_ProcessBuffer(&crc, &interpolated_amount, sizeof(interpolated_amount)); CRC32_Final( &crc ); return crc; @@ -184,7 +184,7 @@ public: buttons = 0; impulse = 0; debug_hitboxes = DEBUG_HITBOXES_OFF; - interpolated_shoot_position.Init(); + interpolated_amount = 0.0f; } // For matching server and client commands for debugging @@ -232,7 +232,7 @@ public: uint8 debug_hitboxes; // TODO_ENHANCED: check README_ENHANCED in host.cpp! - Vector interpolated_shoot_position; + float interpolated_amount; // Back channel to communicate IK state #if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL )