Added interpolated_shoot_position

While the old fix was working, it was a bit too much noticeable while
surfing, this is an issue we don't want.
We need a proper check for cheaters too.
This commit is contained in:
Kamay Xutax 2024-08-27 22:44:41 +02:00
parent 273ac76745
commit 22cfdaabc9
4 changed files with 75 additions and 31 deletions

View file

@ -3145,33 +3145,42 @@ void _Host_RunFrame (float time)
#ifndef SWDS
const auto CalcInterpolationAmount = [&]()
{
// TODO_ENHANCED:
// Notice_Enhanced:
// This check permits to fix interpolation problems on the
// local player that valve has been (fucking finally)
// caring about on counter-strike 2.
//
// To recall the original issue, the
// problem that Valve cared about is that interpolation
// had some problems with interpolating the local
// player because the screen would never in the first
// place match the tick "screen", because interpolation
// amount could never reach 0.0 or 1.0
//
// Valve solution was to introduce bugs with lag
// compensating the local player and made the game worse,
// introducing a new way for cheaters to cheat even more
// on their games.
// I'm joking, but you can clearly see the outcome anyway.
//
// My solution is to simply set interpolation amount
// to 0.0 when a tick arrives.
//
// So when we shoot, we get the frame we shot with an
// interpolation amount at 0.0, perfectly aligned to user
// commands which is ideal for us.
//
// Now includes smoothing.
// TODO_ENHANCED:
// This check permits to fix interpolation problems on the
// local player that valve has been (fucking finally)
// caring about on counter-strike 2.
//
// To recall the original issue, the
// problem that Valve cared about is that interpolation
// had some problems with interpolating the local
// player because the screen would never in the first
// place match the tick "screen", because interpolation
// amount could never reach 0.0 or 1.0
//
// Valve solution was to introduce bugs with lag
// compensating the local player and made the game worse,
// introducing a new way for cheaters to cheat even more
// on their games.
// I'm joking, but you can clearly see the outcome anyway.
//
// My solution is to simply set interpolation amount
// to 0.0 when a tick arrives.
//
// So when we shoot, we get the frame we shot with an
// interpolation amount at 0.0, perfectly aligned to user
// commands which is ideal for us.
//
// README_ENHANCED:
// Unfortunately, some players still notice it with low enough fps.
// This is a problem; we return then to lag compensating the local player.
// Two choices here:
//
// 1) For precision we might need to send camera position, that is proven to work.
// 2) Send interpolation_amount so we calculate it server and in runcommand.
//
// Both works, but the first one requires validation,
// the second doesn't at the expense of some unprecisions due to floats.
// The first one is the easier route to avoid issues.
static ConVar cl_interpolation_amount_fix("cl_interpolation_amount_fix", "0", FCVAR_HIDDEN);

View file

@ -1330,6 +1330,17 @@ 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();
}
pVerified->m_cmd = *cmd;
pVerified->m_crc = cmd->GetChecksum();
}

View file

@ -119,6 +119,9 @@ void FX_FireBullets(
float flSoundTime
)
{
// Fallback if failed to find the interpolated shoot position.
Vector vHookedOrigin = vOrigin;
if (weapon_accuracy_noinaccuracy.GetBool())
{
fInaccuracy = 0.0f;
@ -132,6 +135,19 @@ 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.
if (pPlayer)
{
#ifdef CLIENT_DLL
if (pPlayer->m_pCurrentCommand) { vHookedOrigin = pPlayer->m_pCurrentCommand->interpolated_shoot_position; }
#else
if (pPlayer->GetCurrentCommand()) { vHookedOrigin = pPlayer->GetCurrentCommand()->interpolated_shoot_position; }
#endif
}
const char * weaponAlias = WeaponIDToAlias( iWeaponID );
if ( !weaponAlias )
@ -195,7 +211,7 @@ void FX_FireBullets(
// Dispatch one message for all the bullet impacts and sounds.
TE_FireBullets(
iPlayerIndex,
vOrigin,
vHookedOrigin,
vAngles,
iWeaponID,
iMode,
@ -250,7 +266,7 @@ void FX_FireBullets(
if ( bDoEffects)
{
FX_WeaponSound( iPlayerIndex, sound_type, vOrigin, pWeaponInfo, flSoundTime );
FX_WeaponSound( iPlayerIndex, sound_type, vHookedOrigin, pWeaponInfo, flSoundTime );
}
@ -301,7 +317,7 @@ void FX_FireBullets(
#endif
pPlayer->FireBullet(
iBullet,
vOrigin,
vHookedOrigin,
vAngles,
flRange,
iPenetration,

View file

@ -105,6 +105,8 @@ public:
#if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL )
entitygroundcontact.RemoveAll();
#endif
interpolated_shoot_position.Init();
}
CUserCmd& operator =( const CUserCmd& src )
@ -137,6 +139,7 @@ public:
entitygroundcontact = src.entitygroundcontact;
#endif
interpolated_shoot_position = src.interpolated_shoot_position;
return *this;
}
@ -165,6 +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_Final( &crc );
return crc;
@ -179,7 +183,8 @@ public:
upmove = 0.f;
buttons = 0;
impulse = 0;
debug_hitboxes = DEBUG_HITBOXES_OFF;
debug_hitboxes = DEBUG_HITBOXES_OFF;
interpolated_shoot_position.Init();
}
// For matching server and client commands for debugging
@ -226,6 +231,9 @@ public:
uint8 debug_hitboxes;
// TODO_ENHANCED: check README_ENHANCED in host.cpp!
Vector interpolated_shoot_position;
// Back channel to communicate IK state
#if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL )
CUtlVector< CEntityGroundContact > entitygroundcontact;