mirror of
https://github.com/rei-kes/Amalgam.git
synced 2024-12-22 15:48:00 +08:00
Improve/fix a couple things mainly related to doubletap & movesim
This commit is contained in:
parent
c45439c16d
commit
70ca468968
@ -314,7 +314,10 @@ int CAimbotHitscan::CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* p
|
||||
if (Vars::Aimbot::General::Ignore.Value & UNSIMULATED && G::ChokeMap[target.m_pEntity->entindex()] > Vars::Aimbot::General::TickTolerance.Value)
|
||||
return false;
|
||||
|
||||
Vec3 vEyePos = pLocal->GetShootPos();
|
||||
Vec3 vEyePos = pLocal->GetShootPos(), vPeekPos = {};
|
||||
float flSpread = pWeapon->GetWeaponSpread();
|
||||
if (flSpread)
|
||||
vPeekPos = pLocal->GetShootPos() + pLocal->GetAbsVelocity() * TICKS_TO_TIME(-Vars::Aimbot::General::HitscanPeek.Value);
|
||||
const float flMaxRange = powf(GetMaxRange(pWeapon), 2.f);
|
||||
|
||||
auto pModel = target.m_pEntity->GetModel();
|
||||
@ -350,6 +353,16 @@ int CAimbotHitscan::CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* p
|
||||
}
|
||||
}
|
||||
|
||||
static int iPreferredTick = 0; // if we're doubletapping, we can't change viewangles so have a preferred tick to use
|
||||
if (!I::ClientState->chokedcommands)
|
||||
iPreferredTick = 0;
|
||||
if (iPreferredTick)
|
||||
{
|
||||
auto pivot = std::find_if(vRecords.begin(), vRecords.end(), [](auto& s) -> bool { return s.iTickCount == iPreferredTick; });
|
||||
if (pivot != vRecords.end())
|
||||
std::rotate(vRecords.begin(), pivot, pivot + 1);
|
||||
}
|
||||
|
||||
auto RayToOBB = [](const Vec3& origin, const Vec3& direction, const Vec3& position, const Vec3& min, const Vec3& max, const matrix3x4 orientation) -> bool
|
||||
{
|
||||
if (Vars::Aimbot::General::AimType.Value != 2)
|
||||
@ -446,7 +459,11 @@ int CAimbotHitscan::CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* p
|
||||
Vec3 vForward = {};
|
||||
Math::AngleVectors(vAngles, &vForward);
|
||||
|
||||
if (SDK::VisPos(pLocal, target.m_pEntity, vEyePos, vTransformed))
|
||||
bool bPeekCheck = flSpread ? SDK::VisPos(pLocal, target.m_pEntity, vPeekPos, vTransformed) : true;
|
||||
if (bPeekCheck)
|
||||
flSpread = 0.f; // only use with a single hitbox
|
||||
|
||||
if (SDK::VisPos(pLocal, target.m_pEntity, vEyePos, vTransformed) && bPeekCheck)
|
||||
{
|
||||
target.m_vAngleTo = vAngles;
|
||||
if (RayToOBB(vEyePos, vForward, vCenter, vMins, vMaxs, boneMatrix[pair.first->bone])) // for the time being, no vischecks against other hitboxes
|
||||
@ -460,6 +477,8 @@ int CAimbotHitscan::CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* p
|
||||
}
|
||||
if (bWillHit)
|
||||
{
|
||||
iPreferredTick = pTick.iTickCount;
|
||||
|
||||
target.m_Tick = pTick;
|
||||
target.m_vPos = vTransformed;
|
||||
if (target.m_TargetType == ETargetType::PLAYER)
|
||||
@ -510,7 +529,11 @@ int CAimbotHitscan::CanHit(Target_t& target, CTFPlayer* pLocal, CTFWeaponBase* p
|
||||
Vec3 vForward = {};
|
||||
Math::AngleVectors(vAngles, &vForward);
|
||||
|
||||
if (SDK::VisPos(pLocal, target.m_pEntity, vEyePos, vTransformed))
|
||||
bool bPeekCheck = flSpread ? SDK::VisPos(pLocal, target.m_pEntity, vPeekPos, vTransformed) : true;
|
||||
if (bPeekCheck)
|
||||
flSpread = 0.f; // only use with a single hitbox
|
||||
|
||||
if (SDK::VisPos(pLocal, target.m_pEntity, vEyePos, vTransformed) && bPeekCheck)
|
||||
{
|
||||
target.m_vAngleTo = vAngles;
|
||||
if (RayToOBB(vEyePos, vForward, target.m_pEntity->m_vecOrigin(), vMins, vMaxs, transform)) // for the time being, no vischecks against other hitboxes
|
||||
|
@ -648,6 +648,7 @@ bool CAimbotMelee::RunSapper(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd
|
||||
|
||||
if (pCmd->buttons & IN_ATTACK)
|
||||
{
|
||||
G::IsAttacking = true;
|
||||
target.m_vAngleTo = Aim(pCmd->viewangles, Math::CalcAngle(vLocalPos, target.m_vPos));
|
||||
target.m_vAngleTo.x = pCmd->viewangles.x; // we don't need to care about pitch
|
||||
Aim(pCmd, target.m_vAngleTo);
|
||||
|
@ -152,15 +152,16 @@ void CMenu::MenuAimbot()
|
||||
{
|
||||
if (Section("debug## aimbot"))
|
||||
{
|
||||
FSlider("hitscan peek", Vars::Aimbot::General::HitscanPeek, 0, 10);
|
||||
FSlider("offset## nospread", Vars::Aimbot::General::NoSpreadOffset, -5.f, 5.f, 1.f, "%.1f", FSlider_Precision);
|
||||
FSlider("average", Vars::Aimbot::General::NoSpreadAverage, 1, 100);
|
||||
FSlider("average", Vars::Aimbot::General::NoSpreadAverage, 1, 25);
|
||||
} EndSection();
|
||||
}
|
||||
if (Section("Backtrack"))
|
||||
{
|
||||
FToggle("Enabled", Vars::Backtrack::Enabled);
|
||||
FToggle("Prefer on shot", Vars::Backtrack::PreferOnShot, FToggle_Middle);
|
||||
FSlider("Fake latency", Vars::Backtrack::Latency, 0, F::Backtrack.flMaxUnlag * 1000, 5, "%d", FSlider_Clamp); // unreliable above 900
|
||||
FSlider("Fake latency", Vars::Backtrack::Latency, 0, F::Backtrack.flMaxUnlag * 1000, 5, "%d", FSlider_Clamp); // unreliable above 1000 - ping probably
|
||||
FSlider("Fake interp", Vars::Backtrack::Interp, 0, F::Backtrack.flMaxUnlag * 1000, 5, "%d", FSlider_Clamp);
|
||||
FSlider("Window", Vars::Backtrack::Window, 1, 200, 5, "%d", FSlider_Clamp);
|
||||
} EndSection();
|
||||
|
@ -512,6 +512,24 @@ void CMisc::AntiWarp(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
}
|
||||
else
|
||||
vVelocity = pLocal->m_vecVelocity();
|
||||
|
||||
/*
|
||||
static bool bSet = false;
|
||||
|
||||
if (!G::AntiWarp)
|
||||
{
|
||||
bSet = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!G::IsAttacking && !bSet)
|
||||
{
|
||||
bSet = true;
|
||||
SDK::StopMovement(pLocal, pCmd);
|
||||
}
|
||||
else
|
||||
pCmd->forwardmove = pCmd->sidemove = 0.f;
|
||||
*/
|
||||
}
|
||||
|
||||
void CMisc::LegJitter(CTFPlayer* pLocal, CUserCmd* pCmd, bool pSendPacket)
|
||||
|
@ -125,7 +125,21 @@ void CMovementSimulation::FillVelocities()
|
||||
if (TIME_TO_TICKS(flSimTime - flOldSimTime) <= 0)
|
||||
return;
|
||||
|
||||
mVelocities[iEntIndex].push_front({ vVelocity, flSimTime });
|
||||
const VelocityData vRecord = {
|
||||
vVelocity,
|
||||
pEntity->IsOnGround(),
|
||||
flSimTime
|
||||
};
|
||||
|
||||
if (!mVelocities[iEntIndex].empty())
|
||||
{
|
||||
const VelocityData vLast = mVelocities[iEntIndex][0];
|
||||
|
||||
if (vRecord.m_bGrounded != vLast.m_bGrounded)
|
||||
mVelocities[iEntIndex].clear();
|
||||
}
|
||||
|
||||
mVelocities[iEntIndex].push_front(vRecord);
|
||||
|
||||
if (mVelocities[iEntIndex].size() > 66)
|
||||
mVelocities[iEntIndex].pop_back();
|
||||
@ -217,8 +231,8 @@ bool CMovementSimulation::Initialize(CBaseEntity* pEntity, PlayerStorage& player
|
||||
break;
|
||||
|
||||
const auto& pRecord1 = mVelocityRecords[i], &pRecord2 = mVelocityRecords[i + 1];
|
||||
const float flYaw1 = Math::VelocityToAngles(pRecord1.first).y, flYaw2 = Math::VelocityToAngles(pRecord2.first).y;
|
||||
const float flTime1 = pRecord1.second, flTime2 = pRecord2.second;
|
||||
const float flYaw1 = Math::VelocityToAngles(pRecord1.m_vVelocity).y, flYaw2 = Math::VelocityToAngles(pRecord2.m_vVelocity).y;
|
||||
const float flTime1 = pRecord1.m_flSimTime, flTime2 = pRecord2.m_flSimTime;
|
||||
|
||||
float flYaw = (flYaw1 - flYaw2) / TIME_TO_TICKS(flTime1 - flTime2);
|
||||
flYaw = fmodf(flYaw + 180.f, 360.f);
|
||||
@ -283,14 +297,14 @@ bool CMovementSimulation::SetupMoveData(PlayerStorage& playerStorage)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMovementSimulation::GetYawDifference(const std::deque<std::pair<Vec3, float>>& mVelocityRecords, size_t i, float* flYaw)
|
||||
bool CMovementSimulation::GetYawDifference(const std::deque<VelocityData>& mVelocityRecords, size_t i, float* flYaw)
|
||||
{
|
||||
if (mVelocityRecords.size() <= i + 2)
|
||||
return false;
|
||||
|
||||
const auto& pRecord1 = mVelocityRecords[i], &pRecord2 = mVelocityRecords[i + 1];
|
||||
const float flYaw1 = Math::VelocityToAngles(pRecord1.first).y, flYaw2 = Math::VelocityToAngles(pRecord2.first).y;
|
||||
const float flTime1 = pRecord1.second, flTime2 = pRecord2.second;
|
||||
const float flYaw1 = Math::VelocityToAngles(pRecord1.m_vVelocity).y, flYaw2 = Math::VelocityToAngles(pRecord2.m_vVelocity).y;
|
||||
const float flTime1 = pRecord1.m_flSimTime, flTime2 = pRecord2.m_flSimTime;
|
||||
|
||||
const int iTicks = std::max(TIME_TO_TICKS(flTime1 - flTime2), 1);
|
||||
*flYaw = (flYaw1 - flYaw2) / iTicks;
|
||||
@ -300,7 +314,7 @@ bool CMovementSimulation::GetYawDifference(const std::deque<std::pair<Vec3, floa
|
||||
static int iSign = 0;
|
||||
const int iLastSign = iSign;
|
||||
const int iCurSign = iSign = *flYaw > 0 ? 1 : -1;
|
||||
if (fabsf(*flYaw) < 640.f / pRecord1.first.Length2D() / iTicks) // dumb way to get straight bool
|
||||
if (fabsf(*flYaw) < 200.f / pRecord1.m_vVelocity.Length2D() / iTicks) // dumb way to get straight bool
|
||||
return false;
|
||||
|
||||
return !i || iLastSign == iCurSign ? true : false;
|
||||
|
@ -66,6 +66,13 @@ struct PlayerStorage
|
||||
bool m_bInitFailed = false;
|
||||
};
|
||||
|
||||
struct VelocityData
|
||||
{
|
||||
Vec3 m_vVelocity = {};
|
||||
bool m_bGrounded = true;
|
||||
float m_flSimTime = 0.f;
|
||||
};
|
||||
|
||||
class CMovementSimulation
|
||||
{
|
||||
private:
|
||||
@ -73,7 +80,7 @@ private:
|
||||
void Reset(PlayerStorage& playerStorage);
|
||||
|
||||
bool SetupMoveData(PlayerStorage& playerStorage);
|
||||
bool GetYawDifference(const std::deque<std::pair<Vec3, float>>& mPositionRecords, size_t i, float* flYaw);
|
||||
bool GetYawDifference(const std::deque<VelocityData>& mPositionRecords, size_t i, float* flYaw);
|
||||
float GetAverageYaw(const int iIndex, const int iSamples);
|
||||
bool StrafePrediction(PlayerStorage& playerStorage, const int iSamples);
|
||||
|
||||
@ -81,7 +88,7 @@ private:
|
||||
bool m_bOldFirstTimePredicted = false;
|
||||
float m_flOldFrametime = 0.f;
|
||||
|
||||
std::unordered_map<int, std::deque<std::pair<Vec3, float>>> mVelocities;
|
||||
std::unordered_map<int, std::deque<VelocityData>> mVelocities;
|
||||
|
||||
public:
|
||||
void FillVelocities();
|
||||
|
@ -334,7 +334,7 @@ void CVisuals::DrawDebugInfo(CTFPlayer* pLocal)
|
||||
Vec3 vVelocity = pLocal->m_vecVelocity();
|
||||
H::Draw.String(fFont, x, y += fFont.m_nTall + 1, { 255, 255, 255, 255 }, ALIGN_TOPLEFT, "Velocity: %.3f (%.3f, %.3f, %.3f)", vVelocity.Length(), vVelocity.x, vVelocity.y, vVelocity.z);
|
||||
|
||||
H::Draw.String(fFont, x, y += fFont.m_nTall + 1, { 255, 255, 255, 255 }, ALIGN_TOPLEFT, std::format("Attacking: {}", G::IsAttacking).c_str());
|
||||
H::Draw.String(fFont, x, y += fFont.m_nTall + 1, { 255, 255, 255, 255 }, ALIGN_TOPLEFT, std::format("Attacking: {} ({}, {})", G::IsAttacking, G::CanPrimaryAttack, G::CanSecondaryAttack).c_str());
|
||||
|
||||
H::Draw.String(fFont, x, y += fFont.m_nTall + 1, { 255, 255, 255, 255 }, ALIGN_TOPLEFT, "RoundState: %i", SDK::GetRoundState());
|
||||
|
||||
|
@ -39,11 +39,11 @@ MAKE_HOOK(BaseClientDLL_FrameStageNotify, U::Memory.GetVFunc(I::BaseClientDLL, 3
|
||||
H::Entities.Fill();
|
||||
for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
|
||||
{
|
||||
G::VelocityMap[pEntity->entindex()] = { pEntity->m_vecOrigin(), pEntity->m_vecMaxs().z - pEntity->m_vecMins().z, pEntity->m_flSimulationTime() };
|
||||
|
||||
if (pEntity->entindex() == I::EngineClient->GetLocalPlayer())
|
||||
continue; // local player managed in CPrediction_RunCommand
|
||||
|
||||
G::VelocityMap[pEntity->entindex()] = { pEntity->m_vecOrigin(), pEntity->m_vecMaxs().z - pEntity->m_vecMins().z, pEntity->m_flSimulationTime() };
|
||||
|
||||
static auto sv_maxusrcmdprocessticks = U::ConVars.FindVar("sv_maxusrcmdprocessticks");
|
||||
const int iTicks = sv_maxusrcmdprocessticks ? sv_maxusrcmdprocessticks->GetInt() : 24;
|
||||
if (auto iDifference = std::min(TIME_TO_TICKS(pEntity->m_flSimulationTime() - pEntity->m_flOldSimulationTime()), iTicks))
|
||||
|
@ -44,32 +44,51 @@ MAKE_HOOK(ClientModeShared_CreateMove, U::Memory.GetVFunc(I::ClientModeShared, 2
|
||||
if (G::WeaponDefIndex != nOldDefIndex || !pWeapon->m_iClip1() || !pLocal->IsAlive() || pLocal->IsTaunting() || pLocal->IsBonked() || pLocal->IsAGhost() || pLocal->IsInBumperKart())
|
||||
G::WaitForShift = 1;
|
||||
|
||||
bool bCanAttack = pLocal->CanAttack() && (pWeapon->m_iWeaponID() == TF_WEAPON_FLAME_BALL ? pLocal->m_flTankPressure() >= 100.f : true);
|
||||
G::CanPrimaryAttack = bCanAttack && pWeapon->CanPrimaryAttack(pLocal);
|
||||
G::CanSecondaryAttack = bCanAttack && pWeapon->CanSecondaryAttack(pLocal);
|
||||
G::CanPrimaryAttack = G::CanSecondaryAttack = false;
|
||||
bool bCanAttack = pLocal->CanAttack();
|
||||
switch (SDK::GetRoundState())
|
||||
{
|
||||
case GR_STATE_BETWEEN_RNDS:
|
||||
case GR_STATE_GAME_OVER:
|
||||
if (pLocal->m_fFlags() & FL_FROZEN)
|
||||
G::CanPrimaryAttack = G::CanSecondaryAttack = false;
|
||||
bCanAttack = bCanAttack && !(pLocal->m_fFlags() & FL_FROZEN);
|
||||
}
|
||||
if (pWeapon->m_iSlot() != SLOT_MELEE)
|
||||
if (bCanAttack)
|
||||
{
|
||||
if (pWeapon->IsInReload())
|
||||
G::CanPrimaryAttack = pWeapon->HasPrimaryAmmoForShot();
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_FLAME_BALL:
|
||||
G::CanPrimaryAttack = G::CanSecondaryAttack = pLocal->m_flTankPressure() >= 100.f;
|
||||
break;
|
||||
case TF_WEAPON_BUILDER:
|
||||
G::CanPrimaryAttack = true;
|
||||
break;
|
||||
default:
|
||||
G::CanPrimaryAttack = pWeapon->CanPrimaryAttack(pLocal);
|
||||
G::CanSecondaryAttack = pWeapon->CanSecondaryAttack(pLocal);
|
||||
|
||||
if (pWeapon->m_iWeaponID() == TF_WEAPON_MINIGUN && pWeapon->As<CTFMinigun>()->m_iWeaponState() != AC_STATE_FIRING && pWeapon->As<CTFMinigun>()->m_iWeaponState() != AC_STATE_SPINNING)
|
||||
G::CanPrimaryAttack = false;
|
||||
if (pWeapon->m_iSlot() == SLOT_MELEE)
|
||||
break;
|
||||
|
||||
if (pWeapon->IsInReload())
|
||||
G::CanPrimaryAttack = pWeapon->HasPrimaryAmmoForShot();
|
||||
|
||||
if (pWeapon->m_iWeaponID() == TF_WEAPON_FLAREGUN_REVENGE && pCmd->buttons & IN_ATTACK2)
|
||||
G::CanPrimaryAttack = false;
|
||||
if (G::WeaponDefIndex != Soldier_m_TheBeggarsBazooka && pWeapon->m_iClip1() == 0)
|
||||
G::CanPrimaryAttack = false;
|
||||
|
||||
if (pWeapon->m_bEnergyWeapon() && !pWeapon->m_flEnergy())
|
||||
G::CanPrimaryAttack = false;
|
||||
if (pWeapon->m_bEnergyWeapon() && !pWeapon->m_flEnergy())
|
||||
G::CanPrimaryAttack = false;
|
||||
|
||||
if (G::WeaponDefIndex != Soldier_m_TheBeggarsBazooka && pWeapon->m_iClip1() == 0)
|
||||
G::CanPrimaryAttack = false;
|
||||
switch (pWeapon->m_iWeaponID())
|
||||
{
|
||||
case TF_WEAPON_MINIGUN:
|
||||
if (pWeapon->As<CTFMinigun>()->m_iWeaponState() != AC_STATE_FIRING && pWeapon->As<CTFMinigun>()->m_iWeaponState() != AC_STATE_SPINNING)
|
||||
G::CanPrimaryAttack = false;
|
||||
break;
|
||||
case TF_WEAPON_FLAREGUN_REVENGE:
|
||||
if (pCmd->buttons & IN_ATTACK2)
|
||||
G::CanPrimaryAttack = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
G::IsAttacking = SDK::IsAttacking(pLocal, pWeapon, pCmd);
|
||||
|
@ -431,11 +431,9 @@ bool SDK::IsAttacking(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, const CUserCmd*
|
||||
return trace.DidHit() && !(trace.surface.flags & 0x0004) /*SURF_SKY*/;
|
||||
}
|
||||
case TF_WEAPON_MINIGUN:
|
||||
{
|
||||
return (pWeapon->As<CTFMinigun>()->m_iWeaponState() == AC_STATE_FIRING || pWeapon->As<CTFMinigun>()->m_iWeaponState() == AC_STATE_SPINNING) &&
|
||||
pCmd->buttons & IN_ATTACK && G::CanPrimaryAttack;
|
||||
}
|
||||
}
|
||||
|
||||
return pCmd->buttons & IN_ATTACK && G::CanPrimaryAttack;
|
||||
}
|
||||
@ -469,7 +467,7 @@ bool SDK::StopMovement(CTFPlayer* pLocal, CUserCmd* pCmd)
|
||||
if (!G::IsAttacking)
|
||||
{
|
||||
const float direction = Math::VelocityToAngles(pLocal->m_vecVelocity()).y;
|
||||
pCmd->viewangles = { -90, direction, 0 };
|
||||
pCmd->viewangles = { 90, direction, 0 };
|
||||
pCmd->sidemove = 0; pCmd->forwardmove = 0;
|
||||
return true;
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ namespace Vars
|
||||
CVar(FOVCircle, true)
|
||||
CVar(NoSpread, false)
|
||||
|
||||
CVar(HitscanPeek, 3, NOSAVE) // debug
|
||||
CVar(NoSpreadOffset, 0.f, NOSAVE) // debug
|
||||
CVar(NoSpreadAverage, 5, NOSAVE) // debug
|
||||
SUBNAMESPACE_END(Global)
|
||||
|
Loading…
Reference in New Issue
Block a user