Начинающий
-
Автор темы
- #1
Код:
//========= Flow, All rights reserved. ================//
// TimeSimulator
// Purpose: Shifting cmd time accordingly to targeted entity.
// for more accurate lagcompensation results.
//=====================================================//
#include "Utilities.h"
#include "Backtrack.h"
#define FLOW_INCOMING 1
#define TIME_TO_TICKS( dt ) ( (int)( 0.5f + (float)(dt) / SSDK::I::GlobalVars()->interval_per_tick ) )
#define TICKS_TO_TIME( t ) ( SSDK::I::GlobalVars()->interval_per_tick *( t ) )
#define LC_NONE 0
#define LC_ALIVE (1<<0)
#define LC_ORIGIN_CHANGED (1<<8)
#define LC_ANGLES_CHANGED (1<<9)
#define LC_SIZE_CHANGED (1<<10)
#define LC_ANIMATION_CHANGED (1<<11)
#define LAG_COMPENSATION_TELEPORTED_DISTANCE_SQR ( 64.0f * 64.0f )
#define LAG_COMPENSATION_EPS_SQR ( 0.1f * 0.1f )
// Allow 4 units of error ( about 1 / 8 bbox width )
#define LAG_COMPENSATION_ERROR_EPS_SQR ( 4.0f * 4.0f )
LagRecord_t::LagRecord_t()
{
m_vecPreviousOrigin = SSDK::Vector(0, 0, 0);
m_flSimulationTime = 0.0f;
m_bValidRecord = false;
}
template<class T, class U>
T clamp(T in, U low, U high)
{
if (in <= low)
return low;
if (in >= high)
return high;
return in;
}
int GetEstimatedServerTickCount(float latency)
{
return (int)floorf((float)((float)(latency) / (float)((uintptr_t)&SSDK::I::GlobalVars()->interval_per_tick)) + 0.5) + 1 + (int)((uintptr_t)&SSDK::I::GlobalVars()->tickcount);
}
float inline GetEstimatedServerTime()
{
CBaseEntity *pPlayer = CBaseEntity::GetLocalPlayer();
return SSDK::I::GlobalVars()->curtime = *pPlayer->GetTickBase() * SSDK::I::GlobalVars()->interval_per_tick;
}
float GetNetworkLatency()
{
// Get true latency
SSDK::INetChannelInfo *nci = SSDK::I::Engine()->GetNetChannelInfo();
if (nci)
{
float IncomingLatency = nci->GetAvgLatency(FLOW_INCOMING);
//float OutgoingLatency = nci->GetAvgLatency(FLOW_OUTGOING);
return IncomingLatency;// +OutgoingLatency;
}
return 0.0f;
}
void CTimeSimulator::Cache()
{
SSDK::IClientEntity* pLP = SSDK::I::EntityList()->GetClientEntity(SSDK::I::Engine()->GetLocalPlayer());
static DWORD s_dwTickbaseoffs = GET_NETVAR("DT_BasePlayer", "m_nTickBase");
static DWORD s_dwSimtimmeoffs = GET_NETVAR("DT_BaseEntity", "m_flSimulationTime");
int iTickBase = *(int*)((unsigned long)pLP + s_dwTickbaseoffs);
float flCurrentTime = SSDK::I::GlobalVars()->interval_per_tick * iTickBase;
for (int s = 1; s <= SSDK::I::GlobalVars()->maxClients; ++s)
{
m_PlayerTable[s].m_bValidRecord = false;
CBaseEntity *pEntity = (CBaseEntity*)SSDK::I::EntityList()->GetClientEntity(s);
if (!pEntity)
continue;
if (!pEntity->IsValid())
continue;
float flSimTime = *(float*)((DWORD)pEntity + s_dwSimtimmeoffs);
// Origin delta differance rejection
if (m_PlayerTable[s].m_vecPreviousOrigin.Length() > 0)
{
SSDK::Vector delta = pEntity->GetAbsOrigin() - m_PlayerTable[s].m_vecPreviousOrigin;
if (delta.Length2DSqr() > 64)
{
m_PlayerTable[s].m_vecPreviousOrigin = pEntity->GetAbsOrigin();
m_PlayerTable[s].m_vecPreviousAngles = pEntity->GetAbsAngles();
m_PlayerTable[s].m_flPreviousSimulationTime = pEntity->m_flSimulationTime();
continue;
}
}
else
{
m_PlayerTable[s].m_vecPreviousOrigin = pEntity->GetAbsOrigin();
}
m_PlayerTable[s].m_vecOrigin = pEntity->GetAbsOrigin();
m_PlayerTable[s].m_vecAngles = pEntity->GetAbsAngles();
m_PlayerTable[s].m_flSimulationTime = pEntity->m_flSimulationTime();
// Time differance rejection
if (fabs(flSimTime - flCurrentTime) > 1.0f)
continue;
float latency = GetNetworkLatency();
const float SV_MAXUNLAG = 1.0f;
float m_flLerpTime = SSDK::I::CVar()->FindVar("cl_interp_ratio")->fValue / SSDK::I::CVar()->FindVar("cl_updaterate")->fValue;
int lerpTicks = TIME_TO_TICKS(m_flLerpTime);
SSDK::I::GlobalVars()->tickcount += lerpTicks;
float correct = clamp(latency + TICKS_TO_TIME(lerpTicks), 0.0f, SV_MAXUNLAG);
int targettick = SSDK::I::GlobalVars()->tickcount - lerpTicks;
float deltaTime = correct - TICKS_TO_TIME(GetEstimatedServerTickCount(latency) - targettick);
if (fabs(deltaTime) > 0.2f)
{
continue;
}
m_PlayerTable[s].m_flSimulationTime = flSimTime;
m_PlayerTable[s].m_bValidRecord = true;
BacktrackEntity(pEntity, targettick);
}
}
template <class T>
FORCEINLINE T Lerp(float flPercent, T const &A, T const &B)
{
return A + (B - A) * flPercent;
}
void CTimeSimulator::BacktrackEntity(CBaseEntity *pPlayer, float flTargetTime)
{
SSDK::Vector org, mins, maxs;
SSDK::QAngle ang;
int pl_index = pPlayer->GetIndex();
auto m_pCurrentPlayer = pPlayer;
float frac = 0.0f;
if (m_PlayerTable[pl_index].m_bValidRecord &&
(m_PlayerTable[pl_index].m_flSimulationTime < flTargetTime) &&
(m_PlayerTable[pl_index].m_flSimulationTime < m_PrevPlayerTable[pl_index].m_flSimulationTime))
{
// we didn't find the exact time but have a valid previous record
// so interpolate between these two records;
Assert(prevRecord->m_flSimulationTime > record->m_flSimulationTime);
Assert(flTargetTime < prevRecord->m_flSimulationTime);
// calc fraction between both records
frac = (flTargetTime - m_PlayerTable[pl_index].m_flSimulationTime) /
(m_PrevPlayerTable[pl_index].m_flSimulationTime - m_PlayerTable[pl_index].m_flSimulationTime);
Assert(frac > 0 && frac < 1); // should never extrapolate
ang = Lerp(frac, m_PlayerTable[pl_index].m_vecAngles, m_PrevPlayerTable[pl_index].m_vecAngles);
org = Lerp(frac, m_PlayerTable[pl_index].m_vecOrigin, m_PrevPlayerTable[pl_index].m_vecOrigin);
}
else
{
// we found the exact record or no other record to interpolate with
// just copy these values since they are the best we have
ang = m_PlayerTable[pl_index].m_vecAngles;
org = m_PlayerTable[pl_index].m_vecOrigin;
}
// See if this represents a change for the player
int flags = 0;
SSDK::LagRecord *restore = &m_RestoreData[pl_index];
SSDK::LagRecord *change = &m_ChangeData[pl_index];
SSDK::QAngle angdiff = pPlayer->GetAbsAngles() - ang;
SSDK::Vector orgdiff = pPlayer->GetAbsOrigin() - org;
// Always remember the pristine simulation time in case we need to restore it.
restore->m_flSimulationTime = pPlayer->m_flSimulationTime();
flags |= LC_ANGLES_CHANGED;
restore->m_vecAngles = pPlayer->GetAbsAngles();
//pPlayer->GetAbsAngles(ang);
change->m_vecAngles = ang;
flags |= LC_ORIGIN_CHANGED;
restore->m_vecOrigin = pPlayer->GetAbsOrigin();
*pPlayer->GetOrigin() = org;
change->m_vecOrigin = org;
/*char text[256]; Q_snprintf( text, sizeof(text), "time %.2f", flTargetTime );
pPlayer->DrawServerHitboxes( 10 );
NDebugOverlay::Text( org, text, false, 10 );
NDebugOverlay::EntityBounds( pPlayer, 255, 0, 0, 32, 10 ); */
//m_RestorePlayer.Set(pl_index); //remember that we changed this player
m_bNeedToRestore = true; // we changed at least one player
restore->m_fFlags = flags; // we need to restore these flags
change->m_fFlags = flags; // we have changed these flags
}
#define TICK_INTERVAL ( SSDK::I::GlobalVars()->interval_per_tick )
#define TIME_TO_TICKS( dt ) ( (int)( 0.5f + (float)(dt) / TICK_INTERVAL ) )
bool CTimeSimulator::ProcessCmd(int iTargetIndex,SSDK::CUserCmd* pCmd)
{
if (iTargetIndex == -1 || iTargetIndex > SSDK::I::GlobalVars()->maxClients)
return false;
if (!m_PlayerTable[iTargetIndex].m_bValidRecord)
return false;
pCmd->tick_count = TIME_TO_TICKS(m_PlayerTable[iTargetIndex].m_flSimulationTime);
return true;
}
I pasted this backtrack i guess. and it isnt working. it just doesnt do anything :/.
Thanks for any advance.