Added smoothed interpolation amount & fixed fews issues with prediction
Added vprof too
This commit is contained in:
parent
139f81eb02
commit
860bd3e883
6 changed files with 113 additions and 91 deletions
130
engine/host.cpp
130
engine/host.cpp
|
@ -4,6 +4,7 @@
|
||||||
//
|
//
|
||||||
//===========================================================================//
|
//===========================================================================//
|
||||||
|
|
||||||
|
#include "dbg.h"
|
||||||
#include "tier0/fasttimer.h"
|
#include "tier0/fasttimer.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -3139,7 +3140,68 @@ void _Host_RunFrame (float time)
|
||||||
g_pMDLCache->MarkFrame();
|
g_pMDLCache->MarkFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
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.
|
||||||
|
|
||||||
|
static float flLastInterpolationAmountOnTick = 0.0f;
|
||||||
|
float flInterpAmount = cl.m_tickRemainder / host_state.interval_per_tick;
|
||||||
|
|
||||||
|
if (numticks > 0)
|
||||||
|
{
|
||||||
|
#ifdef false
|
||||||
|
printf("interpolation amount was %f, corrected to "
|
||||||
|
"fix interpolation issues.\n",
|
||||||
|
flInterpAmount);
|
||||||
|
#endif
|
||||||
|
g_ClientGlobalVariables.interpolation_amount = 0.0f;
|
||||||
|
flLastInterpolationAmountOnTick = flInterpAmount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Just subtract the amount, so we can get a smooth interpolation being on a correct amount.
|
||||||
|
g_ClientGlobalVariables.interpolation_amount = flInterpAmount - flLastInterpolationAmountOnTick;
|
||||||
|
|
||||||
|
ErrorIfNot(g_ClientGlobalVariables.interpolation_amount >= 0.0f,
|
||||||
|
("Interpolation amount was bigger than 1 (%f)\n", g_ClientGlobalVariables.interpolation_amount));
|
||||||
|
#ifdef false
|
||||||
|
printf("current interp: %f, old amount: %f, time: %f, frametime: %f, last remainder not interpolated: %f\n",
|
||||||
|
g_ClientGlobalVariables.interpolation_amount,
|
||||||
|
flInterpAmount,
|
||||||
|
time,
|
||||||
|
host_frametime,
|
||||||
|
flLastInterpolationAmountOnTick);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
// Profile scope, protect from setjmp() problems
|
// Profile scope, protect from setjmp() problems
|
||||||
VPROF( "_Host_RunFrame" );
|
VPROF( "_Host_RunFrame" );
|
||||||
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "_Host_RunFrame" );
|
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "_Host_RunFrame" );
|
||||||
|
@ -3311,52 +3373,7 @@ void _Host_RunFrame (float time)
|
||||||
// This causes cl.gettime() to return the true clock being used for rendering (tickcount * rate + remainder)
|
// This causes cl.gettime() to return the true clock being used for rendering (tickcount * rate + remainder)
|
||||||
Host_SetClientInSimulation(false);
|
Host_SetClientInSimulation(false);
|
||||||
|
|
||||||
// TODO_ENHANCED:
|
CalcInterpolationAmount();
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// It might look a bit more unsmooth with lower fps
|
|
||||||
// but with high enough fps, the issue goes away anyway.
|
|
||||||
// It's not very noticeable which is very nice for us.
|
|
||||||
// No need to lag compensate the local player anymore !
|
|
||||||
if (numticks == 0)
|
|
||||||
{
|
|
||||||
g_ClientGlobalVariables.interpolation_amount = (cl.m_tickRemainder
|
|
||||||
/ host_state
|
|
||||||
.interval_per_tick);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_ClientGlobalVariables.interpolation_amount = 0.0f;
|
|
||||||
#ifdef false
|
|
||||||
printf("interpolation amount was %f, corrected to "
|
|
||||||
"fix interpolation issues.\n",
|
|
||||||
cl.m_tickRemainder
|
|
||||||
/ host_state.interval_per_tick);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(REPLAY_ENABLED)
|
#if defined(REPLAY_ENABLED)
|
||||||
// Update client-side replay history manager - called here
|
// Update client-side replay history manager - called here
|
||||||
|
@ -3465,23 +3482,8 @@ void _Host_RunFrame (float time)
|
||||||
// This causes cl.gettime() to return the true clock being used for rendering (tickcount * rate + remainder)
|
// This causes cl.gettime() to return the true clock being used for rendering (tickcount * rate + remainder)
|
||||||
Host_SetClientInSimulation( false );
|
Host_SetClientInSimulation( false );
|
||||||
|
|
||||||
// Please check Notice_Enhanced.
|
CalcInterpolationAmount();
|
||||||
if (numticks == 0)
|
|
||||||
{
|
|
||||||
g_ClientGlobalVariables.interpolation_amount = (cl.m_tickRemainder
|
|
||||||
/ host_state
|
|
||||||
.interval_per_tick);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_ClientGlobalVariables.interpolation_amount = 0.0f;
|
|
||||||
#ifdef false
|
|
||||||
printf("interpolation amount was %f, corrected to "
|
|
||||||
"fix interpolation issues.\n",
|
|
||||||
cl.m_tickRemainder
|
|
||||||
/ host_state.interval_per_tick);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
//-------------------
|
//-------------------
|
||||||
// Run prediction if it hasn't been run yet
|
// Run prediction if it hasn't been run yet
|
||||||
//-------------------
|
//-------------------
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
#if defined( CCSPlayer )
|
#if defined( CCSPlayer )
|
||||||
#undef CCSPlayer
|
#undef CCSPlayer
|
||||||
#endif
|
#endif
|
||||||
|
#include "debugoverlay_shared.h"
|
||||||
#include "materialsystem/imesh.h" //for materials->FindMaterial
|
#include "materialsystem/imesh.h" //for materials->FindMaterial
|
||||||
#include "iviewrender.h" //for view->
|
#include "iviewrender.h" //for view->
|
||||||
|
|
||||||
|
@ -2240,21 +2240,25 @@ void C_CSPlayer::Simulate( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < m_iBulletServerPositionCount; i++)
|
for (int i = 0; i < m_iBulletServerPositionCount; i++)
|
||||||
{
|
{
|
||||||
debugoverlay->AddSweptBoxOverlay(m_vecServerShootPosition[i],
|
NDebugOverlay::SweptBox(m_vecServerShootPosition[i],
|
||||||
m_vecBulletServerPositions[i],
|
m_vecBulletServerPositions[i],
|
||||||
Vector(-m_lastBulletDiameter,
|
Vector(-m_lastBulletDiameter, -m_lastBulletDiameter, -m_lastBulletDiameter) / 2,
|
||||||
-m_lastBulletDiameter,
|
Vector(m_lastBulletDiameter, m_lastBulletDiameter, m_lastBulletDiameter) / 2,
|
||||||
-m_lastBulletDiameter)
|
QAngle(0, 0, 0),
|
||||||
/ 2,
|
0,
|
||||||
Vector(m_lastBulletDiameter, m_lastBulletDiameter, m_lastBulletDiameter)
|
0,
|
||||||
/ 2,
|
255,
|
||||||
QAngle(0, 0, 0),
|
127,
|
||||||
0,
|
60.f);
|
||||||
0,
|
NDebugOverlay::Box(m_vecBulletServerPositions[i],
|
||||||
255,
|
Vector(-m_lastBulletDiameter, -m_lastBulletDiameter, -m_lastBulletDiameter) / 2,
|
||||||
127,
|
Vector(m_lastBulletDiameter, m_lastBulletDiameter, m_lastBulletDiameter) / 2,
|
||||||
60.f);
|
0,
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
127,
|
||||||
|
60.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastBulletDiameter = -1.0f;
|
m_lastBulletDiameter = -1.0f;
|
||||||
|
|
|
@ -890,6 +890,12 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
||||||
gpGlobals->frametime = m_bEnginePaused ? 0 : TICK_INTERVAL;
|
gpGlobals->frametime = m_bEnginePaused ? 0 : TICK_INTERVAL;
|
||||||
gpGlobals->curtime = player->m_nTickBase * TICK_INTERVAL;
|
gpGlobals->curtime = player->m_nTickBase * TICK_INTERVAL;
|
||||||
|
|
||||||
|
// Copy from command to player unless game .dll has set angle using fixangle
|
||||||
|
// if ( !player->pl.fixangle )
|
||||||
|
{
|
||||||
|
player->SetLocalViewAngles( ucmd->viewangles );
|
||||||
|
}
|
||||||
|
|
||||||
RunPostThink( player );
|
RunPostThink( player );
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -936,12 +942,6 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
||||||
// player->pl.v_angle = ucmd->viewangles + player->pl.anglechange;
|
// player->pl.v_angle = ucmd->viewangles + player->pl.anglechange;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Copy from command to player unless game .dll has set angle using fixangle
|
|
||||||
// if ( !player->pl.fixangle )
|
|
||||||
{
|
|
||||||
player->SetLocalViewAngles( ucmd->viewangles );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call standard client pre-think
|
// Call standard client pre-think
|
||||||
RunPreThink( player );
|
RunPreThink( player );
|
||||||
|
|
||||||
|
@ -1695,8 +1695,12 @@ void CPrediction::Update( int startframe, bool validframe,
|
||||||
|
|
||||||
_Update( received_new_world_update, validframe, incoming_acknowledged, outgoing_command );
|
_Update( received_new_world_update, validframe, incoming_acknowledged, outgoing_command );
|
||||||
|
|
||||||
|
// TODO_ENHANCED: This, exactly, have made me debugging for 2h...
|
||||||
|
// the value isn't saved.
|
||||||
|
bool is_taking_screenshot = gpGlobals->client_taking_screenshot;
|
||||||
// Restore current timer values, etc.
|
// Restore current timer values, etc.
|
||||||
*gpGlobals = saveVars;
|
*gpGlobals = saveVars;
|
||||||
|
gpGlobals->client_taking_screenshot = is_taking_screenshot;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -590,7 +590,15 @@ void CCSPlayer::FireBullet(
|
||||||
|
|
||||||
if (cl_showimpacts.GetInt() == 1
|
if (cl_showimpacts.GetInt() == 1
|
||||||
|| cl_showimpacts.GetInt() == 2)
|
|| cl_showimpacts.GetInt() == 2)
|
||||||
{
|
{
|
||||||
|
NDebugOverlay::Box(tr.endpos,
|
||||||
|
vecBulletRadiusMins,
|
||||||
|
vecBulletRadiusMaxs,
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
127,
|
||||||
|
60.f);
|
||||||
player->DrawClientHitboxes(60.0f, true);
|
player->DrawClientHitboxes(60.0f, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,7 +608,7 @@ void CCSPlayer::FireBullet(
|
||||||
#else
|
#else
|
||||||
if ( m_pCurrentCommand->debug_hitboxes == CUserCmd::DEBUG_HITBOXES_ON_HIT || m_pCurrentCommand->debug_hitboxes == CUserCmd::DEBUG_HITBOXES_ALWAYS_ON )
|
if ( m_pCurrentCommand->debug_hitboxes == CUserCmd::DEBUG_HITBOXES_ON_HIT || m_pCurrentCommand->debug_hitboxes == CUserCmd::DEBUG_HITBOXES_ALWAYS_ON )
|
||||||
{
|
{
|
||||||
if (iBullet < MAX_PLAYER_BULLET_SERVER_POSITIONS)
|
if (m_iBulletServerPositionCount.Get() < MAX_PLAYER_BULLET_SERVER_POSITIONS)
|
||||||
{
|
{
|
||||||
m_vecBulletServerPositions.Set(m_iBulletServerPositionCount.Get(), tr.endpos);
|
m_vecBulletServerPositions.Set(m_iBulletServerPositionCount.Get(), tr.endpos);
|
||||||
m_vecServerShootPosition.Set(m_iBulletServerPositionCount.Get(), vecSrc);
|
m_vecServerShootPosition.Set(m_iBulletServerPositionCount.Get(), vecSrc);
|
||||||
|
|
|
@ -13,12 +13,11 @@
|
||||||
#include "ilagcompensationmanager.h"
|
#include "ilagcompensationmanager.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ConVar debug_screenshot_bullet_position("debug_screenshot_bullet_position", "0");
|
|
||||||
ConVar weapon_accuracy_logging( "weapon_accuracy_logging", "0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY | FCVAR_ARCHIVE );
|
ConVar weapon_accuracy_logging( "weapon_accuracy_logging", "0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY | FCVAR_ARCHIVE );
|
||||||
ConVar weapon_accuracy_noinaccuracy( "weapon_accuracy_noinaccuracy", "0", FCVAR_REPLICATED );
|
ConVar weapon_accuracy_noinaccuracy( "weapon_accuracy_noinaccuracy", "0", FCVAR_REPLICATED );
|
||||||
|
|
||||||
#ifdef CLIENT_DLL
|
#ifdef CLIENT_DLL
|
||||||
|
ConVar debug_screenshot_bullet_position("debug_screenshot_bullet_position", "0");
|
||||||
#include "fx_impact.h"
|
#include "fx_impact.h"
|
||||||
|
|
||||||
// this is a cheap ripoff from CBaseCombatWeapon::WeaponSound():
|
// this is a cheap ripoff from CBaseCombatWeapon::WeaponSound():
|
||||||
|
@ -299,7 +298,9 @@ void FX_FireBullets(
|
||||||
{
|
{
|
||||||
#ifdef CLIENT_DLL
|
#ifdef CLIENT_DLL
|
||||||
if (debug_screenshot_bullet_position.GetBool())
|
if (debug_screenshot_bullet_position.GetBool())
|
||||||
|
{
|
||||||
gpGlobals->client_taking_screenshot = true;
|
gpGlobals->client_taking_screenshot = true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
pPlayer->FireBullet(
|
pPlayer->FireBullet(
|
||||||
iBullet,
|
iBullet,
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
#include "tier0/vprof_telemetry.h"
|
#include "tier0/vprof_telemetry.h"
|
||||||
|
|
||||||
// VProf is enabled by default in all configurations -except- X360 Retail.
|
// VProf is enabled by default in all configurations -except- X360 Retail.
|
||||||
|
#if !( defined( _GAMECONSOLE ) && defined( _CERT ) )
|
||||||
|
#define VPROF_ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_X360) && defined(VPROF_ENABLED)
|
#if defined(_X360) && defined(VPROF_ENABLED)
|
||||||
#include "tier0/pmc360.h"
|
#include "tier0/pmc360.h"
|
||||||
|
|
Loading…
Reference in a new issue