void lagcompinsation::extrapolate(C_BasePlayer* player, Vector& origin, Vector& velocity, int& flags, bool on_ground)
{
static const auto sv_gravity = Source::m_pCvar->FindVar(_("sv_gravity"));
static const auto sv_jump_impulse = Source::m_pCvar->FindVar(_("sv_jump_impulse"));
if (!(flags & FL_ONGROUND))
velocity.z -= TICKS_TO_TIME(sv_gravity->GetFloat());
else if (player->m_fFlags() & FL_ONGROUND && !on_ground)
velocity.z = sv_jump_impulse->GetFloat();
const auto src = origin;
auto end = src + velocity * Source::m_pGlobalVars->interval_per_tick;
Ray_t r;
r.Init(src, end, player->OBBMins(), player->OBBMaxs());
trace_t t;
CTraceFilter filter;
filter.pSkip = player;
Source::m_pEngineTrace->TraceRay(r, MASK_PLAYERSOLID, &filter, &t);
if (t.fraction != 1.f)
{
for (auto i = 0; i < 2; i++)
{
velocity -= t.plane.normal * velocity.Dot(t.plane.normal);
const auto dot = velocity.Dot(t.plane.normal);
if (dot < 0.f)
velocity -= Vector(dot * t.plane.normal.x,
dot * t.plane.normal.y, dot * t.plane.normal.z);
end = t.endpos + velocity * TICKS_TO_TIME(1.f - t.fraction);
r.Init(t.endpos, end, player->OBBMins(), player->OBBMaxs());
Source::m_pEngineTrace->TraceRay(r, MASK_PLAYERSOLID, &filter, &t);
if (t.fraction == 1.f)
break;
}
}
origin = end = t.endpos;
end.z -= 2.f;
r.Init(origin, end, player->OBBMins(), player->OBBMaxs());
Source::m_pEngineTrace->TraceRay(r, MASK_PLAYERSOLID, &filter, &t);
flags &= FL_ONGROUND;
if (t.DidHit() && t.plane.normal.z > .7f)
flags |= FL_ONGROUND;
}