resimulate in caimbotmelee::canbackstab to prevent prediction error causing miss

This commit is contained in:
rei-2
2025-09-28 18:54:55 -04:00
parent 9f98cee55b
commit 95e2a87932
10 changed files with 128 additions and 75 deletions
@@ -2,6 +2,7 @@
#include "../Aimbot.h"
#include "../../Simulation/MovementSimulation/MovementSimulation.h"
#include "../../EnginePrediction/EnginePrediction.h"
#include "../../Ticks/Ticks.h"
#include "../../Visuals/Visuals.h"
@@ -177,7 +178,13 @@ void CAimbotMelee::UpdateInfo(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCm
}
if (m_iDoubletapTicks && Vars::Doubletap::AntiWarp.Value && pLocal->m_hGroundEntity())
F::Ticks.AntiWarp(pLocal, pCmd->viewangles.y, tStorage.m_MoveData.m_flForwardMove, tStorage.m_MoveData.m_flSideMove, iMax - i - 1);
F::MoveSim.RunTick(tStorage);
m_mRecordMap[I::EngineClient->GetLocalPlayer()].emplace_front(
pLocal->m_flSimulationTime() + TICKS_TO_TIME(i + 1),
tStorage.m_MoveData.m_vecAbsOrigin,
pLocal->m_vecMins(), pLocal->m_vecMaxs()
);
}
if (i < iSimTicks - m_iDoubletapTicks)
@@ -246,14 +253,38 @@ bool CAimbotMelee::CanBackstab(CBaseEntity* pTarget, CTFPlayer* pLocal, Vec3 vEy
}
}
Vec3 vToTarget = (pTarget->GetAbsOrigin() - m_vEyePos).To2D();
Vec3 vEyePos = m_vEyePos;
const float flCompDist = 0.0625f;
const float flSqCompDist = 0.0884f;
if (auto pCmd = G::CurrentUserCmd;
m_mRecordMap[pLocal->entindex()].empty() && pCmd->viewangles != vEyeAngles && G::CanPrimaryAttack)
{ // repredict, prevent prediction error causing miss
CUserCmd tOldCmd = *pCmd;
Vec3 vOldAngles = I::EngineClient->GetViewAngles();
int iOldAttacking = G::Attacking;
bool bOldSilent = G::PSilentAngles;
F::EnginePrediction.End(pLocal, pCmd);
G::Attacking = true;
Aim(pCmd, vEyeAngles);
F::Ticks.Start(pLocal, pCmd);
vEyePos = pLocal->GetShootPos();
F::EnginePrediction.End(pLocal, pCmd);
*pCmd = tOldCmd;
I::EngineClient->SetViewAngles(vOldAngles);
G::Attacking = iOldAttacking;
G::PSilentAngles = bOldSilent;
F::Ticks.Start(pLocal, pCmd);
}
Vec3 vToTarget = (pTarget->GetAbsOrigin() - vEyePos).To2D();
const float flDist = vToTarget.Normalize();
if (!flDist)
if (flDist < flSqCompDist)
return false;
float flTolerance = 0.0625f;
float flExtra = 2.f * flTolerance / flDist; // account for origin compression
const float flExtra = 2.f * flCompDist / flDist; // account for origin compression
float flPosVsTargetViewMinDot = 0.f + 0.0031f + flExtra;
float flPosVsOwnerViewMinDot = 0.5f + flExtra;
float flViewAnglesMinDot = -0.3f + 0.0031f; // 0.00306795676297 ?
@@ -347,7 +378,7 @@ int CAimbotMelee::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pW
tTarget.m_pEntity->m_vecMins() = pRecord->m_vMins + 0.125f; // account for origin compression
tTarget.m_pEntity->m_vecMaxs() = pRecord->m_vMaxs - 0.125f;
Vec3 vDiff = { 0, 0, std::clamp(m_vEyePos.z - pRecord->m_vOrigin.z, tTarget.m_pEntity->m_vecMins().z, tTarget.m_pEntity->m_vecMaxs().z) };
Vec3 vDiff = { 0, 0, std::clamp(m_vEyePos.z - pRecord->m_vOrigin.z, pRecord->m_vMins.z, pRecord->m_vMaxs.z) };
tTarget.m_vPos = pRecord->m_vOrigin + vDiff;
Aim(G::CurrentUserCmd->viewangles, Math::CalcAngle(m_vEyePos, tTarget.m_vPos), tTarget.m_vAngleTo);
@@ -2,8 +2,8 @@
#include "../Ticks/Ticks.h"
// account for origin compression when simulating local player
void CEnginePrediction::ScalePlayers(CBaseEntity* pLocal)
// account for interp and origin compression when simulating local player
void CEnginePrediction::AdjustPlayers(CBaseEntity* pLocal)
{
m_mRestore.clear();
@@ -13,8 +13,9 @@ void CEnginePrediction::ScalePlayers(CBaseEntity* pLocal)
if (pPlayer == pLocal || !pPlayer->IsAlive() || pPlayer->IsAGhost())
continue;
m_mRestore[pPlayer] = { pPlayer->m_vecMins(), pPlayer->m_vecMaxs() };
m_mRestore[pPlayer] = { pPlayer->GetAbsOrigin(), pPlayer->m_vecMins(), pPlayer->m_vecMaxs() };
pPlayer->SetAbsOrigin(pPlayer->m_vecOrigin());
pPlayer->m_vecMins() += 0.125f;
pPlayer->m_vecMaxs() -= 0.125f;
}
@@ -23,16 +24,14 @@ void CEnginePrediction::RestorePlayers()
{
for (auto& [pPlayer, tRestore] : m_mRestore)
{
pPlayer->m_vecMins() = tRestore.m_vecMins;
pPlayer->m_vecMaxs() = tRestore.m_vecMaxs;
pPlayer->SetAbsOrigin(tRestore.m_vOrigin);
pPlayer->m_vecMins() = tRestore.m_vMins;
pPlayer->m_vecMaxs() = tRestore.m_vMaxs;
}
}
void CEnginePrediction::Simulate(CTFPlayer* pLocal, CUserCmd* pCmd)
{
if (!I::MoveHelper)
return;
const int nOldTickBase = pLocal->m_nTickBase();
const bool bOldIsFirstPrediction = I::Prediction->m_bFirstTimePredicted;
const bool bOldInPrediction = I::Prediction->m_bInPrediction;
@@ -45,28 +44,11 @@ void CEnginePrediction::Simulate(CTFPlayer* pLocal, CUserCmd* pCmd)
I::Prediction->m_bInPrediction = true;
I::Prediction->SetLocalViewAngles(pCmd->viewangles);
Vec2 vOriginalMove; int iOriginalButtons;
if (m_bDoubletap = m_bInPrediction && (F::Ticks.m_bAntiWarp || F::Ticks.GetTicks(H::Entities.GetWeapon()) && Vars::Doubletap::AntiWarp.Value && pLocal->m_hGroundEntity()))
{
m_vOriginalOrigin = pLocal->m_vecOrigin();
m_vOriginalVelocity = pLocal->m_vecVelocity();
vOriginalMove = { pCmd->forwardmove, pCmd->sidemove };
iOriginalButtons = pCmd->buttons;
F::Ticks.AntiWarp(pLocal, pCmd->viewangles.y, pCmd->forwardmove, pCmd->sidemove);
}
AdjustPlayers(pLocal);
I::Prediction->SetupMove(pLocal, pCmd, I::MoveHelper, &m_MoveData);
ScalePlayers(pLocal);
I::GameMovement->ProcessMovement(pLocal, &m_MoveData);
RestorePlayers();
I::Prediction->FinishMove(pLocal, pCmd, &m_MoveData);
if (m_bDoubletap)
{
pCmd->forwardmove = vOriginalMove.x, pCmd->sidemove = vOriginalMove.y;
pCmd->buttons = iOriginalButtons;
}
RestorePlayers();
I::MoveHelper->SetHost(nullptr);
pLocal->m_pCurrentCommand() = nullptr;
@@ -76,8 +58,8 @@ void CEnginePrediction::Simulate(CTFPlayer* pLocal, CUserCmd* pCmd)
I::Prediction->m_bFirstTimePredicted = bOldIsFirstPrediction;
I::Prediction->m_bInPrediction = bOldInPrediction;
m_vOrigin = pLocal->m_vecOrigin();
m_vVelocity = pLocal->m_vecVelocity();
m_vOrigin = m_MoveData.m_vecAbsOrigin;
m_vVelocity = m_MoveData.m_vecVelocity;
m_vDirection = { m_MoveData.m_flForwardMove, -m_MoveData.m_flSideMove, m_MoveData.m_flUpMove };
m_vAngles = m_MoveData.m_vecViewAngles;
}
@@ -98,6 +80,9 @@ void CEnginePrediction::Start(CTFPlayer* pLocal, CUserCmd* pCmd)
I::GlobalVars->curtime = TICKS_TO_TIME(I::GlobalVars->tickcount);
I::GlobalVars->frametime = I::Prediction->m_bEnginePaused ? 0.f : TICK_INTERVAL;
m_vOldOrigin = pLocal->m_vecOrigin();
m_vOldVelocity = pLocal->m_vecVelocity();
Simulate(pLocal, pCmd);
}
@@ -111,12 +96,6 @@ void CEnginePrediction::End(CTFPlayer* pLocal, CUserCmd* pCmd)
I::GlobalVars->curtime = m_flOldCurrentTime;
I::GlobalVars->frametime = m_flOldFrameTime;
if (m_bDoubletap && !F::Ticks.m_bAntiWarp && !G::Attacking)
{
pLocal->m_vecOrigin() = m_vOriginalOrigin;
pLocal->m_vecVelocity() = m_vOriginalVelocity;
pLocal->SetAbsVelocity(m_vOriginalVelocity);
Simulate(pLocal, pCmd);
}
pLocal->SetAbsOrigin(pLocal->m_vecOrigin() = m_vOldOrigin);
pLocal->SetAbsVelocity(pLocal->m_vecVelocity() = m_vOldVelocity);
}
@@ -3,8 +3,9 @@
struct RestoreInfo_t
{
Vec3 m_vecMins = {};
Vec3 m_vecMaxs = {};
Vec3 m_vOrigin = {};
Vec3 m_vMins = {};
Vec3 m_vMaxs = {};
};
class CEnginePrediction
@@ -18,9 +19,8 @@ private:
float m_flOldCurrentTime = 0.f;
float m_flOldFrameTime = 0.f;
bool m_bDoubletap = false;
Vec3 m_vOriginalOrigin = {};
Vec3 m_vOriginalVelocity = {};
Vec3 m_vOldOrigin = {};
Vec3 m_vOldVelocity = {};
std::unordered_map<CTFPlayer*, RestoreInfo_t> m_mRestore = {};
@@ -28,7 +28,7 @@ public:
void Start(CTFPlayer* pLocal, CUserCmd* pCmd);
void End(CTFPlayer* pLocal, CUserCmd* pCmd);
void ScalePlayers(CBaseEntity* pLocal);
void AdjustPlayers(CBaseEntity* pLocal);
void RestorePlayers();
bool m_bInPrediction = false;
+8 -4
View File
@@ -483,19 +483,23 @@ int CMisc::AntiBackstab(CTFPlayer* pLocal, CUserCmd* pCmd, bool bSendPacket)
{
auto TargetIsBehind = [&]()
{
const float flCompDist = 0.0625f;
const float flSqCompDist = 0.0884f;
Vec3 vToTarget = (pLocal->m_vecOrigin() - pTargetPos.first).To2D();
const float flDist = vToTarget.Normalize();
if (!flDist)
if (flDist < flSqCompDist)
return true;
float flTolerance = 0.0625f;
float flExtra = 2.f * flTolerance / flDist; // account for origin compression
const float flExtra = 2.f * flCompDist / flDist; // account for origin compression
float flPosVsTargetViewMinDot = 0.f - 0.0031f - flExtra;
Vec3 vTargetForward; Math::AngleVectors(pCmd->viewangles, &vTargetForward);
vTargetForward.Normalize2D();
return vToTarget.Dot(vTargetForward) > flPosVsTargetViewMinDot;
const float flPosVsTargetViewDot = vToTarget.Dot(vTargetForward); // Behind?
return flPosVsTargetViewDot > flPosVsTargetViewMinDot;
};
if (!TargetIsBehind())
+30
View File
@@ -2,6 +2,7 @@
#include "../NetworkFix/NetworkFix.h"
#include "../PacketManip/AntiAim/AntiAim.h"
#include "../EnginePrediction/EnginePrediction.h"
#include "../Aimbot/AutoRocketJump/AutoRocketJump.h"
#include "../Backtrack/Backtrack.h"
@@ -276,6 +277,35 @@ void CTicks::ManagePacket(CUserCmd* pCmd, bool* pSendPacket)
}
}
void CTicks::Start(CTFPlayer* pLocal, CUserCmd* pCmd)
{
Vec2 vOriginalMove; int iOriginalButtons;
if (m_bPredictAntiwarp = m_bAntiWarp || GetTicks(H::Entities.GetWeapon()) && Vars::Doubletap::AntiWarp.Value && pLocal->m_hGroundEntity())
{
vOriginalMove = { pCmd->forwardmove, pCmd->sidemove };
iOriginalButtons = pCmd->buttons;
AntiWarp(pLocal, pCmd->viewangles.y, pCmd->forwardmove, pCmd->sidemove);
}
F::EnginePrediction.Start(pLocal, pCmd);
if (m_bPredictAntiwarp)
{
pCmd->forwardmove = vOriginalMove.x, pCmd->sidemove = vOriginalMove.y;
pCmd->buttons = iOriginalButtons;
}
}
void CTicks::End(CTFPlayer* pLocal, CUserCmd* pCmd)
{
if (m_bPredictAntiwarp && !m_bAntiWarp && !G::Attacking)
{
F::EnginePrediction.End(pLocal, pCmd);
F::EnginePrediction.Start(pLocal, pCmd);
}
}
bool CTicks::CanChoke()
{
static auto sv_maxusrcmdprocessticks = U::ConVars.FindVar("sv_maxusrcmdprocessticks");
+5
View File
@@ -21,12 +21,17 @@ private:
bool m_bShootAngle = false;
Vec3 m_vShootAngle = {};
bool m_bPredictAntiwarp = false;
public:
void Move(float accumulated_extra_samples, bool bFinalTick, CTFPlayer* pLocal);
void CreateMove(CTFPlayer* pLocal, CUserCmd* pCmd, bool* pSendPacket);
void Draw(CTFPlayer* pLocal);
void Reset();
void Start(CTFPlayer* pLocal, CUserCmd* pCmd);
void End(CTFPlayer* pLocal, CUserCmd* pCmd);
void AntiWarp(CTFPlayer* pLocal, float flYaw, float& flForwardMove, float& flSideMove, int iTicks = -1);
void AntiWarp(CTFPlayer* pLocal, CUserCmd* pCmd);
+18 -21
View File
@@ -203,7 +203,6 @@ static inline void AntiCheatCompatibility(CUserCmd* pCmd, bool* pSendPacket)
pCmd->viewangles = vHistory[0].m_vAngle + Vec3(0.f, REAL_EPSILON * 2);
vHistory[0].m_vAngle = pCmd->viewangles;
vHistory[0].m_bSendingPacket = *pSendPacket = vHistory[1].m_bSendingPacket;
G::Choking = !*pSendPacket;
}
// prevent aim snap checks
@@ -224,7 +223,6 @@ static inline void AntiCheatCompatibility(CUserCmd* pCmd, bool* pSendPacket)
pCmd->viewangles.y += SNAP_NOISE_EPSILON * 2;
vHistory[0].m_vAngle = pCmd->viewangles;
vHistory[0].m_bSendingPacket = *pSendPacket = vHistory[1].m_bSendingPacket;
G::Choking = !*pSendPacket;
}
}
}
@@ -251,27 +249,26 @@ MAKE_HOOK(CHLClient_CreateMove, U::Memory.GetVirtual(I::Client, 21), void,
I::Prediction->Update(I::ClientState->m_nDeltaTick, I::ClientState->m_nDeltaTick > 0, I::ClientState->last_command_ack, I::ClientState->lastoutgoingcommand + I::ClientState->chokedcommands);
UpdateInfo(pLocal, pWeapon, pCmd);
F::Spectate.CreateMove(pCmd);
F::Backtrack.CreateMove(pCmd);
F::Misc.RunPre(pLocal, pCmd);
F::EnginePrediction.Start(pLocal, pCmd);
F::Aimbot.Run(pLocal, pWeapon, pCmd);
F::CritHack.Run(pLocal, pWeapon, pCmd);
F::NoSpread.Run(pLocal, pWeapon, pCmd);
F::Resolver.CreateMove(pLocal);
F::Spectate.CreateMove(pCmd);
F::Backtrack.CreateMove(pCmd);
F::Misc.RunPre(pLocal, pCmd);
F::Ticks.Start(pLocal, pCmd);
F::Aimbot.Run(pLocal, pWeapon, pCmd);
F::Ticks.End(pLocal, pCmd);
F::CritHack.Run(pLocal, pWeapon, pCmd);
F::NoSpread.Run(pLocal, pWeapon, pCmd);
F::Resolver.CreateMove(pLocal);
F::Misc.RunPost(pLocal, pCmd, *pSendPacket);
F::PacketManip.Run(pLocal, pWeapon, pCmd, pSendPacket);
F::Visuals.CreateMove(pLocal, pWeapon);
F::Ticks.CreateMove(pLocal, pCmd, pSendPacket);
F::AntiAim.Run(pLocal, pWeapon, pCmd, *pSendPacket);
F::NoSpreadHitscan.AskForPlayerPerf();
F::EnginePrediction.End(pLocal, pCmd);
F::Misc.RunPost(pLocal, pCmd, *pSendPacket);
F::PacketManip.Run(pLocal, pWeapon, pCmd, pSendPacket);
F::Visuals.CreateMove(pLocal, pWeapon);
F::Ticks.CreateMove(pLocal, pCmd, pSendPacket);
F::AntiAim.Run(pLocal, pWeapon, pCmd, *pSendPacket);
F::NoSpreadHitscan.AskForPlayerPerf();
G::Choking = !*pSendPacket;
G::LastUserCmd = pCmd;
AntiCheatCompatibility(pCmd, pSendPacket);
LocalAnimations(pLocal, pCmd, *pSendPacket);
G::Choking = !*pSendPacket;
G::LastUserCmd = pCmd;
}
@@ -39,7 +39,7 @@ MAKE_HOOK(CPrediction_RunSimulation, S::CPrediction_RunSimulation(), void,
++it;
}
F::EnginePrediction.ScalePlayers(localPlayer);
F::EnginePrediction.AdjustPlayers(localPlayer);
CALL_ORIGINAL(rcx, current_command, curtime, cmd, localPlayer);
F::EnginePrediction.RestorePlayers();
}
@@ -2,6 +2,8 @@
#include "IMoveHelper.h"
#include "../Misc/IPrediction.h"
MAKE_SIGNATURE(CPrediction_RestoreEntityToPredictedFrame, "client.dll", "40 55 48 83 EC ? 8B EA", 0x0);
class CMoveData;
class CUserCmd;
class CBasePlayer;
@@ -32,6 +34,8 @@ public:
virtual void SetIdealPitch(CBasePlayer* player, const Vec3& origin, const Vec3& angles, const Vec3& viewheight) = 0;
virtual void _Update(bool received_new_world_update, bool validframe, int incoming_acknowledged, int outgoing_command) = 0;
SIGNATURE_ARGS(RestoreEntityToPredictedFrame, void, CPrediction, (int predicted_frame), this, predicted_frame);
CHandle<CBaseEntity> m_hLastGround;
bool m_bInPrediction;
bool m_bFirstTimePredicted;
@@ -41,6 +45,8 @@ public:
int m_nCommandsPredicted;
int m_nServerCommandsAcknowledged;
int m_bPreviousAckHadErrors;
int m_bPreviousAckErrorTriggersFullLatchReset;
CUtlVector<CHandle<CBaseEntity>> m_EntsWithPredictionErrorsInLastAck;
int m_nIncomingPacketNumber;
float m_flIdealPitch;
};
@@ -265,6 +265,7 @@ public:
return false;
}
VIRTUAL(GetPredDescMap, datamap_t*, 15, this);
//VIRTUAL(IsPlayer, bool, 132, this);
VIRTUAL(IsBaseCombatCharacter, bool, 133, this);
//VIRTUAL(IsNPC, bool, 135, this);