diff --git a/Amalgam/src/Features/Aimbot/Aimbot.cpp b/Amalgam/src/Features/Aimbot/Aimbot.cpp index 8456c0a3..612b3cf0 100644 --- a/Amalgam/src/Features/Aimbot/Aimbot.cpp +++ b/Amalgam/src/Features/Aimbot/Aimbot.cpp @@ -10,11 +10,12 @@ #include "../Misc/Misc.h" #include "../Visuals/Visuals.h" -bool CAimbot::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon) +bool CAimbot::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd) { if (!pWeapon || !pLocal->CanAttack() || !SDK::AttribHookValue(1, "mult_dmg", pWeapon) - || I::EngineVGui->IsGameUIVisible()) + || I::EngineVGui->IsGameUIVisible() + || pCmd->weaponselect) return false; return true; @@ -54,11 +55,8 @@ void CAimbot::RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd) if (abs(G::AimPoint.m_iTickCount - I::GlobalVars->tickcount) > G::AimPoint.m_iDuration) G::AimPoint = {}; - if (pCmd->weaponselect) - return; - F::AutoRocketJump.Run(pLocal, pWeapon, pCmd); - if (!ShouldRun(pLocal, pWeapon)) + if (!ShouldRun(pLocal, pWeapon, pCmd)) return; F::AutoDetonate.Run(pLocal, pCmd); diff --git a/Amalgam/src/Features/Aimbot/Aimbot.h b/Amalgam/src/Features/Aimbot/Aimbot.h index 8cbf9d3b..d4a6d7cb 100644 --- a/Amalgam/src/Features/Aimbot/Aimbot.h +++ b/Amalgam/src/Features/Aimbot/Aimbot.h @@ -4,7 +4,7 @@ class CAimbot { private: - bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon); + bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd); void RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd); void RunAimbot(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd, bool bSecondaryType = false); diff --git a/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp b/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp index 69c77cde..5fb0b538 100644 --- a/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp +++ b/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp @@ -3,6 +3,7 @@ #include "../Aimbot.h" #include "../../Ticks/Ticks.h" #include "../../Resolver/Resolver.h" +#include "../../NoSpread/NoSpread.h" #include "../../Simulation/MovementSimulation/MovementSimulation.h" #include "../../Visuals/Visuals.h" @@ -143,14 +144,108 @@ static inline std::vector GetTargets(CTFPlayer* pLocal, CTFWeaponBase* +std::vector CAimbotHitscan::GetHitboxes(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CBaseEntity* pTarget) +{ + std::vector vHitboxes = {}; + + if (pWeapon->GetWeaponID() == TF_WEAPON_LASER_POINTER) + { + CObjectSentrygun* pSentry = nullptr; + for (auto pEntity : H::Entities.GetGroup(EntityEnum::BuildingTeam)) + { + if (pEntity->IsSentrygun() && pEntity->As()->m_hBuilder().GetEntryIndex() == I::EngineClient->GetLocalPlayer()) + { + pSentry = pEntity->As(); + break; + } + } + if (!pSentry) + return vHitboxes; + + Vec3 vOrigin = pTarget->m_vecOrigin(); + { + MoveStorage tMoveStorage; // run movesim based on ping + F::MoveSim.Initialize(pTarget, tMoveStorage); + if (!tMoveStorage.m_bFailed) + { + for (int i = 1 - TIME_TO_TICKS(F::Backtrack.GetReal()); i <= 0; i++) + { + F::MoveSim.RunTick(tMoveStorage); + vOrigin = tMoveStorage.m_vPredictedOrigin; + } + } + F::MoveSim.Restore(tMoveStorage); + } + if (!SDK::VisPosWorld(nullptr, pTarget, pSentry->m_vecOrigin() + pSentry->GetOffset() / 2 * pSentry->m_flModelScale(), vOrigin + pTarget->GetOffset() / 2)) + return vHitboxes; + + vHitboxes.emplace_back(nullptr, vOrigin); + return vHitboxes; + } + + if (!pTarget->IsPlayer()) + { + vHitboxes.emplace_back(); + return vHitboxes; + } + + if (auto pSet = pTarget->As()->GetHitboxSet()) + { + std::vector> vBones; + for (int nHitbox = 0; nHitbox < pSet->numhitboxes; nHitbox++) + { + int iPriority = GetHitboxPriority(nHitbox, pLocal, pWeapon, pTarget); + if (iPriority == -1) + continue; + + auto pBox = pSet->pHitbox(nHitbox); + if (!pBox) + continue; + + vBones.emplace_back(pBox, nHitbox, iPriority); + } + std::sort(vBones.begin(), vBones.end(), [&](const auto& a, const auto& b) -> bool + { + return std::get<2>(a) < std::get<2>(b); + }); + vHitboxes.reserve(vBones.size()); + for (auto& [pBox, nHitbox, _] : vBones) + vHitboxes.emplace_back(pBox, std::nullopt, nHitbox); + } + + return vHitboxes; +} + int CAimbotHitscan::GetHitboxPriority(int nHitbox, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CBaseEntity* pTarget) { if (!F::AimbotGlobal.IsHitboxValid(pTarget, nHitbox, Vars::Aimbot::Hitscan::Hitboxes.Value)) return -1; bool bHeadshot = false; - if (pTarget->IsPlayer()) + switch (pWeapon->GetWeaponID()) { + case TF_WEAPON_SNIPERRIFLE: + case TF_WEAPON_SNIPERRIFLE_DECAP: + case TF_WEAPON_SNIPERRIFLE_CLASSIC: + { + auto pSniperRifle = pWeapon->As(); + + if (G::CanHeadshot + || pLocal->InCond(TF_COND_AIMING) && (pSniperRifle->GetRifleType() == RIFLE_JARATE && SDK::AttribHookValue(0, "jarate_duration", pWeapon) > 0 || Vars::Aimbot::Hitscan::Modifiers.Value & Vars::Aimbot::Hitscan::ModifiersEnum::WaitForHeadshot)) + bHeadshot = true; + break; + } + case TF_WEAPON_REVOLVER: + { + if (SDK::AttribHookValue(0, "set_weapon_mode", pWeapon) == 1 && (pWeapon->AmbassadorCanHeadshot() || Vars::Aimbot::Hitscan::Modifiers.Value & Vars::Aimbot::Hitscan::ModifiersEnum::WaitForHeadshot)) + bHeadshot = true; + } + } + + if (Vars::Aimbot::Hitscan::Hitboxes.Value & Vars::Aimbot::Hitscan::HitboxesEnum::BodyaimIfLethal && bHeadshot) + { + auto pPlayer = pTarget->As(); + switch (pWeapon->GetWeaponID()) { case TF_WEAPON_SNIPERRIFLE: @@ -159,54 +254,29 @@ int CAimbotHitscan::GetHitboxPriority(int nHitbox, CTFPlayer* pLocal, CTFWeaponB { auto pSniperRifle = pWeapon->As(); - if (G::CanHeadshot - || pLocal->InCond(TF_COND_AIMING) && (pSniperRifle->GetRifleType() == RIFLE_JARATE && SDK::AttribHookValue(0, "jarate_duration", pWeapon) > 0 || Vars::Aimbot::Hitscan::Modifiers.Value & Vars::Aimbot::Hitscan::ModifiersEnum::WaitForHeadshot)) - bHeadshot = true; + int iDamage = ceilf(std::max(pSniperRifle->m_flChargedDamage(), 50.f) * pSniperRifle->GetBodyshotMult(pPlayer)); + if (pPlayer->m_iHealth() <= iDamage) + bHeadshot = false; break; } case TF_WEAPON_REVOLVER: { - if (SDK::AttribHookValue(0, "set_weapon_mode", pWeapon) == 1 && (pWeapon->AmbassadorCanHeadshot() || Vars::Aimbot::Hitscan::Modifiers.Value & Vars::Aimbot::Hitscan::ModifiersEnum::WaitForHeadshot)) - bHeadshot = true; - } - } - - if (Vars::Aimbot::Hitscan::Hitboxes.Value & Vars::Aimbot::Hitscan::HitboxesEnum::BodyaimIfLethal && bHeadshot) - { - auto pPlayer = pTarget->As(); - - switch (pWeapon->GetWeaponID()) + if (SDK::AttribHookValue(0, "set_weapon_mode", pWeapon) == 1) { - case TF_WEAPON_SNIPERRIFLE: - case TF_WEAPON_SNIPERRIFLE_DECAP: - case TF_WEAPON_SNIPERRIFLE_CLASSIC: - { - auto pSniperRifle = pWeapon->As(); + float flDistTo = pTarget->m_vecOrigin().DistTo(pLocal->m_vecOrigin()); - int iDamage = ceilf(std::max(pSniperRifle->m_flChargedDamage(), 50.f) * pSniperRifle->GetBodyshotMult(pPlayer)); + float flMult = SDK::AttribHookValue(1, "mult_dmg", pWeapon); + int iDamage = ceilf(Math::RemapVal(flDistTo, 90.f, 900.f, 60.f, 21.f) * flMult); if (pPlayer->m_iHealth() <= iDamage) bHeadshot = false; - break; - } - case TF_WEAPON_REVOLVER: - { - if (SDK::AttribHookValue(0, "set_weapon_mode", pWeapon) == 1) - { - float flDistTo = pTarget->m_vecOrigin().DistTo(pLocal->m_vecOrigin()); - - float flMult = SDK::AttribHookValue(1, "mult_dmg", pWeapon); - int iDamage = ceilf(Math::RemapVal(flDistTo, 90.f, 900.f, 60.f, 21.f) * flMult); - if (pPlayer->m_iHealth() <= iDamage) - bHeadshot = false; - } - } } } + } } bool bHeadOnly = bHeadshot && Vars::Aimbot::Hitscan::Hitboxes.Value & Vars::Aimbot::Hitscan::HitboxesEnum::HeadshotOnly; - int iHeadPriority = bHeadOnly || bHeadshot ? 0 : 1; + int iHeadPriority = bHeadshot ? 0 : 1; int iBodyPriority = bHeadOnly ? -1 : bHeadshot ? 1 : 0; int iMiscPriority = bHeadOnly ? -1 : 2; int iLimbPriority = bHeadOnly ? -1 : 3; @@ -224,23 +294,102 @@ int CAimbotHitscan::GetHitboxPriority(int nHitbox, CTFPlayer* pLocal, CTFWeaponB return iLimbPriority; }; +void CAimbotHitscan::GetHitboxInfo(HitscanHitbox_t& tHitbox, CBaseEntity* pTarget, matrix3x4* aBones, const matrix3x4** pTransform, Vec3* pMins, Vec3* pMaxs) +{ + if (pMins && pMaxs) + { + if (tHitbox.m_pBox) + { + *pMins = tHitbox.m_pBox->bbmin; + *pMaxs = tHitbox.m_pBox->bbmax; + } + else if (pTarget) + { + *pMins = pTarget->m_vecMins(); + *pMaxs = pTarget->m_vecMaxs(); + } + } + + if (pTransform) + { + if (aBones && tHitbox.m_pBox) + *pTransform = &aBones[tHitbox.m_pBox->bone]; + else if (tHitbox.m_vPos) + *pTransform = &m_mMatrix, Math::MatrixInitialize(m_mMatrix, *tHitbox.m_vPos, false); + else if (pTarget) + *pTransform = &pTarget->m_Collision()->CollisionToWorldTransform(); + } +} + +void CAimbotHitscan::GetHullInfo(CBaseEntity* pTarget, TickRecord* pRecord, const matrix3x4** pTransform, Vec3* pMins, Vec3* pMaxs, float* pModelScale) +{ + if (!pTarget->IsPlayer()) + return; // only really important for player targets to check that our trace will be in the bbox + + if (pModelScale) + *pModelScale = pTarget->As()->m_flModelScale(); + + if (pMins && pMaxs) + { + float flModelScale = pModelScale ? *pModelScale : 1.f; + auto pGameRules = I::TFGameRules(); + auto pViewVectors = pGameRules ? pGameRules->GetViewVectors() : nullptr; + *pMins = (pViewVectors ? pViewVectors->m_vHullMin : Vec3(-24, -24, 0)) * flModelScale; + *pMaxs = (pViewVectors ? pViewVectors->m_vHullMax : Vec3(24, 24, 82)) * flModelScale; + } + + if (pTransform && pRecord) + *pTransform = &m_mHullMatrix, Math::MatrixInitialize(m_mHullMatrix, pRecord->m_vOrigin, false); +} + +std::vector CAimbotHitscan::GetHitboxPoints(CBaseEntity* pTarget, CTFWeaponBase* pWeapon, const Vec3& vMins, const Vec3& vMaxs, int nHitbox) +{ + std::vector vPoints = { Vec3() }; + + bool bPlayer = pTarget->IsPlayer(); + if (bPlayer && !F::AimbotGlobal.ShouldMultipoint(pTarget, nHitbox, Vars::Aimbot::Hitscan::MultipointHitboxes.Value) + || pWeapon->GetWeaponID() == TF_WEAPON_LASER_POINTER) + return vPoints; + + switch (Vars::Aimbot::General::AimType.Value) + { + case Vars::Aimbot::General::AimTypeEnum::Smooth: + case Vars::Aimbot::General::AimTypeEnum::Assistive: + if (!Vars::Aimbot::General::AssistStrength.Value) + return vPoints; // triggerbot + } + + float flScale = !bPlayer ? 0.5f : Vars::Aimbot::Hitscan::MultipointScale.Value / 100; + Vec3 vMinsS = (vMins - vMaxs) / 2 * flScale; + Vec3 vMaxsS = (vMaxs - vMins) / 2 * flScale; + + vPoints = { + Vec3(), + Vec3(vMinsS.x, vMinsS.y, vMaxsS.z), + Vec3(vMaxsS.x, vMinsS.y, vMaxsS.z), + Vec3(vMinsS.x, vMaxsS.y, vMaxsS.z), + Vec3(vMaxsS.x, vMaxsS.y, vMaxsS.z), + Vec3(vMinsS.x, vMinsS.y, vMinsS.z), + Vec3(vMaxsS.x, vMinsS.y, vMinsS.z), + Vec3(vMinsS.x, vMaxsS.y, vMinsS.z), + Vec3(vMaxsS.x, vMaxsS.y, vMinsS.z) + }; + + return vPoints; +} + int CAimbotHitscan::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon) { if (Vars::Aimbot::General::Ignore.Value & Vars::Aimbot::General::IgnoreEnum::Unsimulated && H::Entities.GetChoke(tTarget.m_pEntity->entindex()) > Vars::Aimbot::General::TickTolerance.Value) return false; m_vEyePos = pLocal->GetShootPos(); - const float flMaxRangeSqr = powf(pWeapon->GetRange(), 2.f); - - auto pModel = tTarget.m_pEntity->GetModel(); - if (!pModel) return false; - auto pHDR = I::ModelInfoClient->GetStudiomodel(pModel); - if (!pHDR) return false; - auto pSet = pHDR->pHitboxSet(tTarget.m_pEntity->As()->m_nHitboxSet()); - if (!pSet) return false; + float flMaxRangeSqr = powf(pWeapon->GetRange(), 2.f); + bool bPlayer = tTarget.m_pEntity->IsPlayer(); + bool bWrangler = pWeapon->GetWeaponID() == TF_WEAPON_LASER_POINTER; std::vector vRecords = {}; - if (F::Backtrack.GetRecords(tTarget.m_pEntity, vRecords)) + if (F::Backtrack.GetRecords(tTarget.m_pEntity, vRecords) && !bWrangler) { vRecords = F::Backtrack.GetValidRecords(vRecords, pLocal); if (vRecords.empty()) @@ -255,286 +404,108 @@ int CAimbotHitscan::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* vRecords = { &F::Backtrack.m_tRecord }; } + auto vHitboxes = GetHitboxes(pLocal, pWeapon, tTarget.m_pEntity); + if (vHitboxes.empty()) + return false; + int iReturn = false; - bool bPeekCheck = false; + + std::optional vPeekPos = std::nullopt; if (Vars::Aimbot::Hitscan::PeekAmount.Value && pWeapon->GetWeaponSpread()) { switch (Vars::Aimbot::Hitscan::PeekCheck.Value) { - case Vars::Aimbot::Hitscan::PeekCheckEnum::Off: break; - case Vars::Aimbot::Hitscan::PeekCheckEnum::DoubletapOnly: bPeekCheck = F::Ticks.GetTicks(pWeapon); break; - case Vars::Aimbot::Hitscan::PeekCheckEnum::Always: bPeekCheck = true; break; + case Vars::Aimbot::Hitscan::PeekCheckEnum::DoubletapOnly: + if (!F::Ticks.GetTicks(pWeapon)) + break; + [[fallthrough]]; + case Vars::Aimbot::Hitscan::PeekCheckEnum::Always: + vPeekPos = m_vEyePos - pLocal->m_vecVelocity() * TICKS_TO_TIME(Vars::Aimbot::Hitscan::PeekAmount.Value); } } - Vec3 vPeekPos = bPeekCheck ? m_vEyePos + pLocal->m_vecVelocity() * TICKS_TO_TIME(-Vars::Aimbot::Hitscan::PeekAmount.Value) : Vec3(); // if we're doubletapping, we can't change viewangles so work around that static int iTargetBone = 0; - Vec3* pDoubletapAngle = F::Ticks.GetShootAngle(); - if (pDoubletapAngle && tTarget.m_iTargetType == TargetEnum::Player) + Vec3* pHoldAngle = F::Ticks.GetShootAngle(); if (pHoldAngle && bPlayer && vRecords.size() > 1) { + Vec3 vHoldAngle = *pHoldAngle - F::NoSpread.GetOffset(); std::sort(vRecords.begin(), vRecords.end(), [&](const TickRecord* a, const TickRecord* b) -> bool { Vec3 vPosA = { a->m_aBones[iTargetBone][0][3], a->m_aBones[iTargetBone][1][3], a->m_aBones[iTargetBone][2][3] }; Vec3 vPosB = { b->m_aBones[iTargetBone][0][3], b->m_aBones[iTargetBone][1][3], b->m_aBones[iTargetBone][2][3] }; Vec3 vAnglesA = Math::CalcAngle(m_vEyePos, vPosA); Vec3 vAnglesB = Math::CalcAngle(m_vEyePos, vPosB); - return pDoubletapAngle->DeltaAngle(vAnglesA).Length2D() < pDoubletapAngle->DeltaAngle(vAnglesB).Length2D(); + return vHoldAngle.DeltaAngle(vAnglesA).Length2DSqr() < vHoldAngle.DeltaAngle(vAnglesB).Length2DSqr(); }); } - // wrangler - if (pWeapon->GetWeaponID() == TF_WEAPON_LASER_POINTER) - { - tTarget.m_vPos = tTarget.m_pEntity->m_vecOrigin(); - - MoveStorage tMoveStorage; // run movesim based on ping - F::MoveSim.Initialize(tTarget.m_pEntity, tMoveStorage); - if (!tMoveStorage.m_bFailed) - { - for (int i = 1 - TIME_TO_TICKS(F::Backtrack.GetReal()); i <= 0; i++) - { - F::MoveSim.RunTick(tMoveStorage); - tTarget.m_vPos = tMoveStorage.m_vPredictedOrigin; - } - } - F::MoveSim.Restore(tMoveStorage); - - float flBoneScale = std::max(Vars::Aimbot::Hitscan::BoneSizeMinimumScale.Value, Vars::Aimbot::Hitscan::MultipointScale.Value / 100.f); - float flBoneSubtract = Vars::Aimbot::Hitscan::BoneSizeSubtract.Value; - - Vec3 vMins = tTarget.m_pEntity->m_vecMins(); - Vec3 vMaxs = tTarget.m_pEntity->m_vecMaxs(); - Vec3 vCheckMins = (vMins + flBoneSubtract) * flBoneScale; - Vec3 vCheckMaxs = (vMaxs - flBoneSubtract) * flBoneScale; - - const matrix3x4 mTransform = { { 1, 0, 0, tTarget.m_vPos.x }, { 0, 1, 0, tTarget.m_vPos.y }, { 0, 0, 1, tTarget.m_vPos.z } }; - - tTarget.m_vPos += tTarget.m_pEntity->GetOffset() / 2; - if (m_vEyePos.DistToSqr(tTarget.m_vPos) > flMaxRangeSqr) - return false; - - if (SDK::VisPosWorld(pLocal, tTarget.m_pEntity, m_vEyePos, tTarget.m_vPos)) - { - Vec3 vAngles; bool bChanged = Aim(G::CurrentUserCmd->viewangles, Math::CalcAngle(m_vEyePos, tTarget.m_vPos), vAngles); - Vec3 vForward; Math::AngleVectors(vAngles, &vForward); - float flDist = m_vEyePos.DistTo(tTarget.m_vPos); - - if (!F::AimbotGlobal.ShouldAimAtAngle(vAngles)) - return false; - - if (!bChanged || Math::RayToOBB(m_vEyePos, vForward, vCheckMins, vCheckMaxs, mTransform) && SDK::VisPos(pLocal, tTarget.m_pEntity, m_vEyePos, m_vEyePos + vForward * flDist)) - { - tTarget.m_vAngleTo = vAngles; - tTarget.m_pRecord = vRecords.front(); - return true; - } - else - tTarget.m_vAngleTo = vAngles; - iReturn = 2; - } - - return iReturn; - } - - // non player - if (tTarget.m_iTargetType != TargetEnum::Player) - { - float flBoneScale = std::max(Vars::Aimbot::Hitscan::BoneSizeMinimumScale.Value, Vars::Aimbot::Hitscan::MultipointScale.Value / 100.f); - float flBoneSubtract = Vars::Aimbot::Hitscan::BoneSizeSubtract.Value; - - Vec3 vMins = tTarget.m_pEntity->m_vecMins(); - Vec3 vMaxs = tTarget.m_pEntity->m_vecMaxs(); - Vec3 vCheckMins = (vMins + flBoneSubtract) * flBoneScale; - Vec3 vCheckMaxs = (vMaxs - flBoneSubtract) * flBoneScale; - - const matrix3x4& mTransform = tTarget.m_pEntity->m_Collision()->CollisionToWorldTransform(); - - std::vector vPoints = { Vec3() }; - //if (Vars::Aimbot::Hitscan::MultipointScale.Value > 0.f) - { - bool bTriggerbot = (Vars::Aimbot::General::AimType.Value == Vars::Aimbot::General::AimTypeEnum::Smooth - || Vars::Aimbot::General::AimType.Value == Vars::Aimbot::General::AimTypeEnum::Assistive) - && !Vars::Aimbot::General::AssistStrength.Value; - - if (!bTriggerbot) - { - float flScale = 0.5f; //Vars::Aimbot::Hitscan::MultipointScale.Value / 100; - Vec3 vMinsS = (vMins - vMaxs) / 2 * flScale; - Vec3 vMaxsS = (vMaxs - vMins) / 2 * flScale; - - vPoints = { - Vec3(), - Vec3(vMinsS.x, vMinsS.y, vMaxsS.z), - Vec3(vMaxsS.x, vMinsS.y, vMaxsS.z), - Vec3(vMinsS.x, vMaxsS.y, vMaxsS.z), - Vec3(vMaxsS.x, vMaxsS.y, vMaxsS.z), - Vec3(vMinsS.x, vMinsS.y, vMinsS.z), - Vec3(vMaxsS.x, vMinsS.y, vMinsS.z), - Vec3(vMinsS.x, vMaxsS.y, vMinsS.z), - Vec3(vMaxsS.x, vMaxsS.y, vMinsS.z) - }; - } - } - - for (auto& vPoint : vPoints) - { - Vec3 vOrigin = tTarget.m_pEntity->GetCenter() + vPoint; - - if (m_vEyePos.DistToSqr(vOrigin) > flMaxRangeSqr) - continue; - - Vec3 vAngles; bool bChanged = Aim(G::CurrentUserCmd->viewangles, Math::CalcAngle(m_vEyePos, vOrigin), vAngles); - Vec3 vForward; Math::AngleVectors(vAngles, &vForward); - float flDist = m_vEyePos.DistTo(vOrigin); - - if (!F::AimbotGlobal.ShouldAimAtAngle(vAngles) || !bChanged && !SDK::VisPos(pLocal, tTarget.m_pEntity, m_vEyePos, vOrigin)) - continue; - - if (!bChanged || Math::RayToOBB(m_vEyePos, vForward, vCheckMins, vCheckMaxs, mTransform) && SDK::VisPos(pLocal, tTarget.m_pEntity, m_vEyePos, m_vEyePos + vForward * flDist)) - { - tTarget.m_vAngleTo = vAngles; - tTarget.m_pRecord = vRecords.front();; - tTarget.m_vPos = vOrigin; - return true; - } - else if (bChanged && SDK::VisPos(pLocal, tTarget.m_pEntity, m_vEyePos, vOrigin)) - { - if (iReturn != 2 || vAngles.DeltaAngle(G::CurrentUserCmd->viewangles).Length2D() < tTarget.m_vAngleTo.DeltaAngle(G::CurrentUserCmd->viewangles).Length2D()) - tTarget.m_vAngleTo = vAngles; - iReturn = 2; - } - } - - return iReturn; - } - - // player - std::vector> vHitboxes; - for (int nHitbox = 0; nHitbox < pSet->numhitboxes; nHitbox++) - { - int iPriority = GetHitboxPriority(nHitbox, pLocal, pWeapon, tTarget.m_pEntity); - if (iPriority == -1) - continue; - - auto pBox = pSet->pHitbox(nHitbox); - if (!pBox) continue; - - vHitboxes.emplace_back(pBox, nHitbox, iPriority); - } - std::sort(vHitboxes.begin(), vHitboxes.end(), [&](const auto& a, const auto& b) -> bool - { - return std::get<2>(a) < std::get<2>(b); - }); - - float flModelScale = tTarget.m_pEntity->As()->m_flModelScale(); - float flBoneScale = Vars::Aimbot::Hitscan::BoneSizeMinimumScale.Value; + float flBoneScale = std::max(Vars::Aimbot::Hitscan::BoneSizeMinimumScale.Value, Vars::Aimbot::Hitscan::MultipointScale.Value / 100.f); float flBoneSubtract = Vars::Aimbot::Hitscan::BoneSizeSubtract.Value; + float flModelScale = 1.f; + Vec3 vMins, vMaxs, vHullMins, vHullMaxs; + const matrix3x4* pTransform = &m_mMatrix, *pHullTransform = nullptr; - auto pGameRules = I::TFGameRules(); - auto pViewVectors = pGameRules ? pGameRules->GetViewVectors() : nullptr; - Vec3 vHullMins = (pViewVectors ? pViewVectors->m_vHullMin : Vec3(-24, -24, 0)) * flModelScale; - Vec3 vHullMaxs = (pViewVectors ? pViewVectors->m_vHullMax : Vec3(24, 24, 82)) * flModelScale; - + GetHullInfo(tTarget.m_pEntity, nullptr, nullptr, &vHullMins, &vHullMaxs, &flModelScale); for (auto pRecord : vRecords) { - bool bRunPeekCheck = bPeekCheck; - + bool bRunPeekCheck = vPeekPos.has_value(); auto aBones = pRecord->m_aBones; - if (!aBones) - continue; - const matrix3x4 mTransform = { { 1, 0, 0, pRecord->m_vOrigin.x }, { 0, 1, 0, pRecord->m_vOrigin.y }, { 0, 0, 1, pRecord->m_vOrigin.z } }; - - for (auto& [pBox, nHitbox, _] : vHitboxes) + GetHullInfo(tTarget.m_pEntity, bPlayer && !bWrangler ? pRecord : nullptr, &pHullTransform); + for (auto& tHitbox : vHitboxes) { - Vec3 vMins = pBox->bbmin; - Vec3 vMaxs = pBox->bbmax; + GetHitboxInfo(tHitbox, tTarget.m_pEntity, aBones, &pTransform, &vMins, &vMaxs); Vec3 vCheckMins = (vMins + flBoneSubtract / flModelScale) * flBoneScale; Vec3 vCheckMaxs = (vMaxs - flBoneSubtract / flModelScale) * flBoneScale; - Vec3 vAngle; Math::MatrixAngles(aBones[pBox->bone], vAngle); - - Vec3 vOffset; - { - Vec3 vOrigin, vCenter; - Math::VectorTransform({}, aBones[pBox->bone], vOrigin); - Math::VectorTransform((vMins + vMaxs) / 2, aBones[pBox->bone], vCenter); - vOffset = vCenter - vOrigin; - } - - std::vector vPoints = { Vec3() }; - if (F::AimbotGlobal.ShouldMultipoint(tTarget.m_pEntity, nHitbox, Vars::Aimbot::Hitscan::MultipointHitboxes.Value)) - { - flBoneScale = std::max(flBoneScale, Vars::Aimbot::Hitscan::MultipointScale.Value / 100.f); - bool bTriggerbot = (Vars::Aimbot::General::AimType.Value == Vars::Aimbot::General::AimTypeEnum::Smooth - || Vars::Aimbot::General::AimType.Value == Vars::Aimbot::General::AimTypeEnum::Assistive) - && !Vars::Aimbot::General::AssistStrength.Value; - - if (!bTriggerbot) - { - float flScale = Vars::Aimbot::Hitscan::MultipointScale.Value / 100; - Vec3 vMinsS = (vMins - vMaxs) / 2 * flScale; - Vec3 vMaxsS = (vMaxs - vMins) / 2 * flScale; - - vPoints = { - Vec3(), - Vec3(vMinsS.x, vMinsS.y, vMaxsS.z), - Vec3(vMaxsS.x, vMinsS.y, vMaxsS.z), - Vec3(vMinsS.x, vMaxsS.y, vMaxsS.z), - Vec3(vMaxsS.x, vMaxsS.y, vMaxsS.z), - Vec3(vMinsS.x, vMinsS.y, vMinsS.z), - Vec3(vMaxsS.x, vMinsS.y, vMinsS.z), - Vec3(vMinsS.x, vMaxsS.y, vMinsS.z), - Vec3(vMaxsS.x, vMaxsS.y, vMinsS.z) - }; - } - } + Vec3 vOrigin; Math::VectorTransform({}, *pTransform, vOrigin); + Vec3 vCenter; Math::VectorTransform((vMins + vMaxs) / 2, *pTransform, vCenter); + Vec3 vOffset = vCenter - vOrigin; + std::vector vPoints = GetHitboxPoints(tTarget.m_pEntity, pWeapon, vMins, vMaxs, tHitbox.m_iHitbox); for (auto& vPoint : vPoints) { - Vec3 vOrigin; Math::VectorTransform(vPoint, aBones[pBox->bone], vOrigin); vOrigin += vOffset; - + Math::VectorTransform(vPoint, *pTransform, vOrigin); vOrigin += vOffset; if (m_vEyePos.DistToSqr(vOrigin) > flMaxRangeSqr) continue; if (bRunPeekCheck) { bRunPeekCheck = false; - if (!SDK::VisPos(pLocal, tTarget.m_pEntity, vPeekPos, vOrigin)) - goto nextTick; // if we can't hit our primary hitbox, don't bother + if (!SDK::VisPos(pLocal, tTarget.m_pEntity, *vPeekPos, vOrigin)) + goto skip; // if we can't hit our primary hitbox, don't bother } Vec3 vAngles; bool bChanged = Aim(G::CurrentUserCmd->viewangles, Math::CalcAngle(m_vEyePos, vOrigin), vAngles); - Vec3 vForward; Math::AngleVectors(vAngles, &vForward); - float flDist = m_vEyePos.DistTo(vOrigin); - + if (pHoldAngle) vAngles -= F::NoSpread.GetOffset(); // hold angle recorded with nospread, correct it if (!F::AimbotGlobal.ShouldAimAtAngle(vAngles) || !bChanged && !SDK::VisPos(pLocal, tTarget.m_pEntity, m_vEyePos, vOrigin)) continue; // for the time being, no vischecks against other hitboxes - if ((!bChanged || Math::RayToOBB(m_vEyePos, vForward, vCheckMins, vCheckMaxs, aBones[pBox->bone], flModelScale) && SDK::VisPos(pLocal, tTarget.m_pEntity, m_vEyePos, m_vEyePos + vForward * flDist)) - && Math::RayToOBB(m_vEyePos, vForward, vHullMins, vHullMaxs, mTransform)) + Vec3 vForward; Math::AngleVectors(vAngles, &vForward); + if ((!bChanged || Math::RayToOBB(m_vEyePos, vForward, vCheckMins, vCheckMaxs, *pTransform, flModelScale) && SDK::VisPos(pLocal, tTarget.m_pEntity, m_vEyePos, m_vEyePos + vForward * m_vEyePos.DistTo(vOrigin))) + && (!pHullTransform || Math::RayToOBB(m_vEyePos, vForward, vHullMins, vHullMaxs, *pHullTransform))) { - iTargetBone = pBox->bone; - tTarget.m_vAngleTo = vAngles; tTarget.m_pRecord = pRecord; tTarget.m_vPos = vOrigin; - tTarget.m_nAimedHitbox = nHitbox; - tTarget.m_bBacktrack = true; + if (tHitbox.m_pBox) + { + tTarget.m_bBacktrack = true; + tTarget.m_nAimedHitbox = tHitbox.m_iHitbox; + iTargetBone = tHitbox.m_pBox->bone; + } return true; } else if (bChanged && SDK::VisPos(pLocal, tTarget.m_pEntity, m_vEyePos, vOrigin)) { - if (iReturn != 2 || vAngles.DeltaAngle(G::CurrentUserCmd->viewangles).Length2D() < tTarget.m_vAngleTo.DeltaAngle(G::CurrentUserCmd->viewangles).Length2D()) + if (iReturn != 2 || vAngles.DeltaAngle(G::CurrentUserCmd->viewangles).Length2DSqr() < tTarget.m_vAngleTo.DeltaAngle(G::CurrentUserCmd->viewangles).Length2DSqr()) tTarget.m_vAngleTo = vAngles; iReturn = 2; } } } - nextTick: - continue; + skip: continue; } return iReturn; @@ -613,19 +584,17 @@ bool CAimbotHitscan::ShouldFire(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser return true; } -bool CAimbotHitscan::Aim(Vec3 vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod) +bool CAimbotHitscan::Aim(const Vec3& vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod) { - auto pLocal = H::Entities.GetLocal(); - Vec3 vPunch = pLocal ? pLocal->m_vecPunchAngle() : Vec3(); - - if (Vec3* pDoubletapAngle = F::Ticks.GetShootAngle()) + if (Vec3* pHoldAngle = F::Ticks.GetShootAngle()) { - vOut = *pDoubletapAngle - vPunch; + vOut = *pHoldAngle; return true; } bool bReturn = false; - vToAngle -= vPunch; + if (auto pLocal = H::Entities.GetLocal()) + vToAngle -= pLocal->m_vecPunchAngle(); switch (iMethod) { case Vars::Aimbot::General::AimTypeEnum::Plain: @@ -640,8 +609,8 @@ bool CAimbotHitscan::Aim(Vec3 vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod) case Vars::Aimbot::General::AimTypeEnum::Assistive: Vec3 vMouseDelta = G::CurrentUserCmd->viewangles.DeltaAngle(G::LastUserCmd->viewangles); Vec3 vTargetDelta = vToAngle.DeltaAngle(G::LastUserCmd->viewangles); - float flMouseDelta = vMouseDelta.Length2D(), flTargetDelta = vTargetDelta.Length2D(); - vTargetDelta = vTargetDelta.Normalized() * std::min(flMouseDelta, flTargetDelta); + float flMouseDelta = vMouseDelta.Length2DSqr(), flTargetDelta = vTargetDelta.Length2DSqr(); + vTargetDelta = vTargetDelta.Normalized() * sqrtf(std::min(flMouseDelta, flTargetDelta)); vOut = vCurAngle - vMouseDelta + vMouseDelta.LerpAngle(vTargetDelta, Vars::Aimbot::General::AssistStrength.Value / 100.f); bReturn = true; break; diff --git a/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.h b/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.h index b8a13452..45c71ff8 100644 --- a/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.h +++ b/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.h @@ -3,18 +3,34 @@ #include "../AimbotGlobal/AimbotGlobal.h" +struct HitscanHitbox_t +{ + const mstudiobbox_t* m_pBox = nullptr; // bone + std::optional m_vPos = std::nullopt; // custom position + // otherwise use entity transform + + int m_iHitbox = 0; +}; + class CAimbotHitscan { private: + std::vector GetHitboxes(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CBaseEntity* pTarget); int GetHitboxPriority(int nHitbox, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CBaseEntity* pTarget); + void GetHitboxInfo(HitscanHitbox_t& tHitbox, CBaseEntity* pTarget, matrix3x4* aBones = nullptr, const matrix3x4** pTransform = nullptr, Vec3* pMins = nullptr, Vec3* pMaxs = nullptr); + void GetHullInfo(CBaseEntity* pTarget, TickRecord* pRecord = nullptr, const matrix3x4** pTransform = nullptr, Vec3* pMins = nullptr, Vec3* pMaxs = nullptr, float* pModelScale = nullptr); + std::vector GetHitboxPoints(CBaseEntity* pTarget, CTFWeaponBase* pWeapon, const Vec3& vMins, const Vec3& vMaxs, int nHitbox = 0); int CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon); - bool Aim(Vec3 vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod = Vars::Aimbot::General::AimType.Value); + bool Aim(const Vec3& vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod = Vars::Aimbot::General::AimType.Value); void Aim(CUserCmd* pCmd, Vec3& vAngles, int iMethod = Vars::Aimbot::General::AimType.Value); bool ShouldFire(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd, const Target_t& tTarget); Vec3 m_vEyePos = {}; + matrix3x4 m_mMatrix = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 } }; + matrix3x4 m_mHullMatrix = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 } }; + public: void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd); }; diff --git a/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp b/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp index edcca707..172aaa90 100644 --- a/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp +++ b/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp @@ -434,12 +434,12 @@ int CAimbotMelee::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pW -bool CAimbotMelee::Aim(Vec3 vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod) +bool CAimbotMelee::Aim(const Vec3& vCurAngle, const Vec3& vToAngle, Vec3& vOut, int iMethod) { /* - if (Vec3* pDoubletapAngle = F::Ticks.GetShootAngle()) + if (Vec3* pHoldAngle = F::Ticks.GetShootAngle()) { - vOut = *pDoubletapAngle; + vOut = *pHoldAngle; return true; } */ @@ -459,8 +459,8 @@ bool CAimbotMelee::Aim(Vec3 vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod) case Vars::Aimbot::General::AimTypeEnum::Assistive: Vec3 vMouseDelta = G::CurrentUserCmd->viewangles.DeltaAngle(G::LastUserCmd->viewangles); Vec3 vTargetDelta = vToAngle.DeltaAngle(G::LastUserCmd->viewangles); - float flMouseDelta = vMouseDelta.Length2D(), flTargetDelta = vTargetDelta.Length2D(); - vTargetDelta = vTargetDelta.Normalized() * std::min(flMouseDelta, flTargetDelta); + float flMouseDelta = vMouseDelta.Length2DSqr(), flTargetDelta = vTargetDelta.Length2DSqr(); + vTargetDelta = vTargetDelta.Normalized() * sqrtf(std::min(flMouseDelta, flTargetDelta)); vOut = vCurAngle - vMouseDelta + vMouseDelta.LerpAngle(vTargetDelta, Vars::Aimbot::General::AssistStrength.Value / 100.f); bReturn = true; break; diff --git a/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.h b/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.h index 0b6b2a4f..02d8db98 100644 --- a/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.h +++ b/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.h @@ -11,7 +11,7 @@ private: bool CanBackstab(CBaseEntity* pTarget, CTFPlayer* pLocal, Vec3 vEyeAngles); int CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon); - bool Aim(Vec3 vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod = Vars::Aimbot::General::AimType.Value); + bool Aim(const Vec3& vCurAngle, const Vec3& vToAngle, Vec3& vOut, int iMethod = Vars::Aimbot::General::AimType.Value); void Aim(CUserCmd* pCmd, Vec3& vAngles, int iMethod = Vars::Aimbot::General::AimType.Value); bool FindNearestBuildPoint(CBaseObject* pBuilding, CTFPlayer* pLocal, Vec3& vPoint); diff --git a/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp b/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp index 451d505b..12a624ca 100644 --- a/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp +++ b/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp @@ -1333,17 +1333,14 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i (Vars::Aimbot::General::AimType.Value == Vars::Aimbot::General::AimTypeEnum::Smooth || Vars::Aimbot::General::AimType.Value == Vars::Aimbot::General::AimTypeEnum::Assistive)) { // loop and see if closest hitbox is head - auto pModel = tTarget.m_pEntity->GetModel(); - if (!pModel) break; - auto pHDR = I::ModelInfoClient->GetStudiomodel(pModel); - if (!pHDR) break; - auto pSet = pHDR->pHitboxSet(tTarget.m_pEntity->As()->m_nHitboxSet()); - if (!pSet) break; - auto aBones = F::Backtrack.GetBones(tTarget.m_pEntity); if (!aBones) break; + auto pSet = tTarget.m_pEntity->As()->GetHitboxSet(); + if (!pSet) + break; + Vec3 vOffset = tOriginal.m_vOrigin - tTarget.m_vPos; Vec3 vPos = trace.endpos + F::ProjSim.GetVelocity().Normalized() * 16 + vOffset; @@ -1733,9 +1730,9 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas bool CAimbotProjectile::Aim(const Vec3& vCurAngle, const Vec3& vToAngle, Vec3& vOut, int iMethod) { /* - if (Vec3* pDoubletapAngle = F::Ticks.GetShootAngle()) + if (Vec3* pHoldAngle = F::Ticks.GetShootAngle()) { - vOut = *pDoubletapAngle; + vOut = *pHoldAngle; return true; } */ @@ -1755,8 +1752,8 @@ bool CAimbotProjectile::Aim(const Vec3& vCurAngle, const Vec3& vToAngle, Vec3& v case Vars::Aimbot::General::AimTypeEnum::Assistive: Vec3 vMouseDelta = G::CurrentUserCmd->viewangles.DeltaAngle(G::LastUserCmd->viewangles); Vec3 vTargetDelta = vToAngle.DeltaAngle(G::LastUserCmd->viewangles); - float flMouseDelta = vMouseDelta.Length2D(), flTargetDelta = vTargetDelta.Length2D(); - vTargetDelta = vTargetDelta.Normalized() * std::min(flMouseDelta, flTargetDelta); + float flMouseDelta = vMouseDelta.Length2DSqr(), flTargetDelta = vTargetDelta.Length2DSqr(); + vTargetDelta = vTargetDelta.Normalized() * sqrtf(std::min(flMouseDelta, flTargetDelta)); vOut = vCurAngle - vMouseDelta + vMouseDelta.LerpAngle(vTargetDelta, Vars::Aimbot::General::AssistStrength.Value / 100.f); bReturn = true; break; diff --git a/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.cpp b/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.cpp index 02be417d..31835089 100644 --- a/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.cpp +++ b/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.cpp @@ -3,6 +3,17 @@ #include "../../Simulation/ProjectileSimulation/ProjectileSimulation.h" #include "../../Simulation/MovementSimulation/MovementSimulation.h" +bool CAutoRocketJump::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd) +{ + if (!pLocal->IsAlive() || pLocal->IsAGhost() + || !pWeapon + || I::EngineVGui->IsGameUIVisible() + || m_iFrame == -1 && pCmd->weaponselect) + return false; + + return true; +} + bool CAutoRocketJump::SetAngles(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd) { m_vAngles = pCmd->viewangles; @@ -102,7 +113,7 @@ bool CAutoRocketJump::SetAngles(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser void CAutoRocketJump::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd) { - if (!pWeapon || !pLocal->IsAlive() || pLocal->IsAGhost() || I::EngineVGui->IsGameUIVisible()) + if (!ShouldRun(pLocal, pWeapon, pCmd)) { m_iFrame = -1; return; @@ -127,13 +138,8 @@ void CAutoRocketJump::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* p case TF_WEAPON_PARTICLE_CANNON: bValidWeapon = true; } } - if (!bValidWeapon) - { - m_iFrame = -1; - return; - } - if (m_iFrame == -1 && (bCurrGrounded && bBeggars ? G::Attacking == 1 : G::CanPrimaryAttack || G::Reloading) + if (bValidWeapon && m_iFrame == -1 && (bCurrGrounded && bBeggars ? G::Attacking == 1 : G::CanPrimaryAttack || G::Reloading) && SetAngles(pLocal, pWeapon, pCmd)) { bool bWillHit = false; diff --git a/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.h b/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.h index 6afeaa35..7a569076 100644 --- a/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.h +++ b/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.h @@ -4,6 +4,7 @@ class CAutoRocketJump { private: + bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd); bool SetAngles(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd); Vec3 m_vAngles = {}; diff --git a/Amalgam/src/Features/Backtrack/Backtrack.cpp b/Amalgam/src/Features/Backtrack/Backtrack.cpp index 26f6a4d6..f8008bb3 100644 --- a/Amalgam/src/Features/Backtrack/Backtrack.cpp +++ b/Amalgam/src/Features/Backtrack/Backtrack.cpp @@ -149,15 +149,15 @@ std::vector CBacktrack::GetValidRecords(std::vector& v return {}; std::vector vReturn = {}; - float flCorrect = std::clamp(GetReal(MAX_FLOWS, false) + ROUND_TO_TICKS(GetFakeInterp()), 0.f, m_flMaxUnlag); - int iServerTick = m_iTickCount + GetAnticipatedChoke() + Vars::Backtrack::Offset.Value + TIME_TO_TICKS(GetReal(FLOW_OUTGOING)); + float flCorrect = std::clamp(GetReal(MAX_FLOWS, false) + ROUND_TO_TICKS(GetFakeInterp()), 0.f, m_flMaxUnlag) + flTimeMod; + int iServerTick = m_iTickCount + TIME_TO_TICKS(GetReal(FLOW_OUTGOING)) + GetAnticipatedChoke() + Vars::Backtrack::Offset.Value; if (!Vars::Misc::Game::AntiCheatCompatibility.Value && GetWindow()) { for (auto pRecord : vRecords) { - float flDelta = fabsf(flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(pRecord->m_flSimTime + flTimeMod))); - if (flDelta > GetWindow()) + float flDelta = flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(pRecord->m_flSimTime)); + if (fabsf(flDelta) > GetWindow()) continue; vReturn.push_back(pRecord); @@ -169,8 +169,8 @@ std::vector CBacktrack::GetValidRecords(std::vector& v float flMinDelta = 0.2f; for (auto pRecord : vRecords) { - float flDelta = fabsf(flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(pRecord->m_flSimTime + flTimeMod))); - if (flDelta > flMinDelta) + float flDelta = flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(pRecord->m_flSimTime)); + if (fabsf(flDelta) > flMinDelta) continue; flMinDelta = flDelta; @@ -188,18 +188,16 @@ std::vector CBacktrack::GetValidRecords(std::vector& v return pLocal->m_vecOrigin().DistToSqr(a->m_vOrigin) < pLocal->m_vecOrigin().DistToSqr(b->m_vOrigin); }); else - { std::sort(vReturn.begin(), vReturn.end(), [&](const TickRecord* a, const TickRecord* b) -> bool { if (Vars::Backtrack::PreferOnShot.Value && a->m_bOnShot != b->m_bOnShot) return a->m_bOnShot > b->m_bOnShot; - const float flADelta = flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(a->m_flSimTime + flTimeMod)); - const float flBDelta = flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(b->m_flSimTime + flTimeMod)); + float flADelta = flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(a->m_flSimTime)); + float flBDelta = flCorrect - TICKS_TO_TIME(iServerTick - TIME_TO_TICKS(b->m_flSimTime)); return fabsf(flADelta) < fabsf(flBDelta); }); } - } return vReturn; } diff --git a/Amalgam/src/Features/Commands/Commands.cpp b/Amalgam/src/Features/Commands/Commands.cpp index 4cc91583..fa04829a 100644 --- a/Amalgam/src/Features/Commands/Commands.cpp +++ b/Amalgam/src/Features/Commands/Commands.cpp @@ -5,13 +5,21 @@ #include #include -#define AddCommand(sCommand, fCommand) \ +#define AddCommand(sCommand, ...) \ { \ FNV1A::Hash32Const(sCommand), \ [](const std::deque& vArgs) \ - fCommand \ + __VA_ARGS__ \ }, +//struct ConVarValues_t +//{ +// int m_iValue; +// float m_flValue; +// const char* m_sValue; +//}; +//static std::unordered_map s_mConVarValues = {}; + static std::unordered_map s_mCommands = { AddCommand("setcvar", { @@ -89,6 +97,29 @@ static std::unordered_map s_mCommands = { } reinterpret_cast(0)(); }) + //AddCommand("recordcvars", + //{ + // for (ConCommandBase* pBase = I::CVar->GetCommands(); pBase; pBase = pBase->m_pNext) + // { + // if (pBase->IsCommand()) + // continue; + + // auto pCVar = reinterpret_cast(pBase); + // s_mConVarValues[pCVar] = { pCVar->GetInt(), pCVar->GetFloat(), pCVar->GetString() }; + // } + //}) + //AddCommand("diffcvars", + //{ + // for (auto& [pCVar, tValues] : s_mConVarValues) + // { + // if (auto iOld = tValues.m_iValue, iNew = pCVar->GetInt(); iOld != iNew) + // SDK::Output(pCVar->GetName(), std::format("int: {} -> {}", iOld, iNew).c_str()); + // else if (auto flOld = tValues.m_flValue, flNew = pCVar->GetFloat(); flOld != flNew) + // SDK::Output(pCVar->GetName(), std::format("float: {} -> {}", flOld, flNew).c_str()); + // else if (auto sOld = tValues.m_sValue, sNew = pCVar->GetString(); sOld != sNew || FNV1A::Hash32(sOld) != FNV1A::Hash32(sNew)) + // SDK::Output(pCVar->GetName(), std::format("string: {} -> {}", sOld, sNew).c_str()); + // } + //}) }; bool CCommands::Run(const char* sCmd, std::deque& vArgs) diff --git a/Amalgam/src/Features/Commands/Commands.h b/Amalgam/src/Features/Commands/Commands.h index d8e643c2..d6d39fc6 100644 --- a/Amalgam/src/Features/Commands/Commands.h +++ b/Amalgam/src/Features/Commands/Commands.h @@ -1,5 +1,6 @@ #pragma once #include "../../SDK/SDK.h" + #include using CommandCallback = const std::function&)>; diff --git a/Amalgam/src/Features/NoSpread/NoSpread.cpp b/Amalgam/src/Features/NoSpread/NoSpread.cpp index 1e174b71..bfdf18e3 100644 --- a/Amalgam/src/Features/NoSpread/NoSpread.cpp +++ b/Amalgam/src/Features/NoSpread/NoSpread.cpp @@ -3,20 +3,44 @@ #include "NoSpreadProjectile/NoSpreadProjectile.h" #include "NoSpreadHitscan/NoSpreadHitscan.h" -bool CNoSpread::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon) +bool CNoSpread::ShouldRun(CTFWeaponBase* pWeapon) { if (!Vars::Aimbot::General::NoSpread.Value - || !pWeapon || !pLocal->CanAttack()) + || !pWeapon || G::Attacking != 1) return false; return true; } +void CNoSpread::StoreAngle(CUserCmd* pCmd, bool bFinal) +{ + if (!Vars::Aimbot::General::NoSpread.Value) + { + m_vOffset = {}; + return; + } + + if (G::PrimaryWeaponType == EWeaponType::HITSCAN && I::ClientState->chokedcommands && m_vOffset) + return; + + if (!bFinal) + m_vAngles = pCmd->viewangles; + else + m_vOffset = pCmd->viewangles - m_vAngles; +} + void CNoSpread::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd) { - if (!ShouldRun(pLocal, pWeapon)) + StoreAngle(pCmd, false); + if (!ShouldRun(pWeapon)) return; F::NoSpreadHitscan.Run(pLocal, pWeapon, pCmd); F::NoSpreadProjectile.Run(pLocal, pWeapon, pCmd); + StoreAngle(pCmd, true); +} + +Vec3 CNoSpread::GetOffset() +{ + return m_vOffset; } \ No newline at end of file diff --git a/Amalgam/src/Features/NoSpread/NoSpread.h b/Amalgam/src/Features/NoSpread/NoSpread.h index 15613b16..013b59f4 100644 --- a/Amalgam/src/Features/NoSpread/NoSpread.h +++ b/Amalgam/src/Features/NoSpread/NoSpread.h @@ -4,10 +4,15 @@ class CNoSpread { private: - bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon); + bool ShouldRun(CTFWeaponBase* pWeapon); + void StoreAngle(CUserCmd* pCmd, bool bFinal); + + Vec3 m_vAngles = {}; + Vec3 m_vOffset = {}; public: void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd); + Vec3 GetOffset(); }; ADD_FEATURE(CNoSpread, NoSpread); \ No newline at end of file diff --git a/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.cpp b/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.cpp index 19b65e5a..37e3be81 100644 --- a/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.cpp +++ b/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.cpp @@ -19,13 +19,14 @@ void CNoSpreadHitscan::Reset() m_bSynced = false; } -bool CNoSpreadHitscan::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bCreateMove) +bool CNoSpreadHitscan::ShouldRun(CTFWeaponBase* pWeapon) { - if (G::PrimaryWeaponType != EWeaponType::HITSCAN - || (bCreateMove ? pWeapon->GetWeaponSpread() : S::CTFWeaponBaseGun_GetWeaponSpread.Call(pWeapon)) <= 0.f) + if (pWeapon + ? G::PrimaryWeaponType != EWeaponType::HITSCAN || pWeapon->GetWeaponSpread() <= 0.f + : !Vars::Aimbot::General::NoSpread.Value || !I::EngineClient->IsInGame()) return false; - return bCreateMove ? G::Attacking == 1 : true; + return true; } int CNoSpreadHitscan::GetSeed(CUserCmd* pCmd) @@ -66,7 +67,7 @@ std::string CNoSpreadHitscan::GetFormat(int iServerTime) void CNoSpreadHitscan::AskForPlayerPerf() { - if (!Vars::Aimbot::General::NoSpread.Value || !I::EngineClient->IsInGame()) + if (!ShouldRun()) return Reset(); if (G::Choking) @@ -83,7 +84,7 @@ void CNoSpreadHitscan::AskForPlayerPerf() bool CNoSpreadHitscan::ParsePlayerPerf(const std::string& sMsg) { - if (!Vars::Aimbot::General::NoSpread.Value) + if (!ShouldRun()) return false; std::smatch tMatch; std::regex_match(sMsg, tMatch, std::regex(R"((\d+.\d+)\s\d+\s\d+\s\d+.\d+\s\d+.\d+\svel\s\d+.\d+)")); @@ -129,7 +130,7 @@ bool CNoSpreadHitscan::ParsePlayerPerf(const std::string& sMsg) void CNoSpreadHitscan::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd) { - if (!ShouldRun(pLocal, pWeapon, true)) + if (!ShouldRun(pWeapon)) return; m_iSeed = GetSeed(pCmd); @@ -194,13 +195,9 @@ void CNoSpreadHitscan::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* void CNoSpreadHitscan::Draw(CTFPlayer* pLocal) { - if (!(Vars::Menu::Indicators.Value & Vars::Menu::IndicatorsEnum::SeedPrediction) || !Vars::Aimbot::General::NoSpread.Value || !pLocal->IsAlive()) + if (!(Vars::Menu::Indicators.Value & Vars::Menu::IndicatorsEnum::SeedPrediction) || !ShouldRun() || !pLocal->IsAlive()) return; - //auto pWeapon = H::Entities.GetWeapon(); - //if (!pWeapon || !ShouldRun(pLocal, pWeapon)) - // return; - int x = Vars::Menu::SeedPredictionDisplay.Value.x; int y = Vars::Menu::SeedPredictionDisplay.Value.y + 8; const auto& fFont = H::Fonts.GetFont(FONT_INDICATORS); diff --git a/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.h b/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.h index 71c0ac1f..1c496a24 100644 --- a/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.h +++ b/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.h @@ -6,6 +6,7 @@ class CNoSpreadHitscan { private: + bool ShouldRun(CTFWeaponBase* pWeapon = nullptr); int GetSeed(CUserCmd* pCmd); float CalcMantissaStep(float flV); std::string GetFormat(int iServerTime); @@ -19,7 +20,6 @@ private: public: void Reset(); - bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bCreateMove = false); void AskForPlayerPerf(); bool ParsePlayerPerf(const std::string& sMsg); diff --git a/Amalgam/src/Features/NoSpread/NoSpreadProjectile/NoSpreadProjectile.cpp b/Amalgam/src/Features/NoSpread/NoSpreadProjectile/NoSpreadProjectile.cpp index c9fcdbdd..2d773d2e 100644 --- a/Amalgam/src/Features/NoSpread/NoSpreadProjectile/NoSpreadProjectile.cpp +++ b/Amalgam/src/Features/NoSpread/NoSpreadProjectile/NoSpreadProjectile.cpp @@ -1,16 +1,16 @@ #include "NoSpreadProjectile.h" -bool CNoSpreadProjectile::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon) +bool CNoSpreadProjectile::ShouldRun(CTFWeaponBase* pWeapon) { if (G::PrimaryWeaponType != EWeaponType::PROJECTILE) return false; - return G::Attacking == 1; + return true; } void CNoSpreadProjectile::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd) { - if (!ShouldRun(pLocal, pWeapon)) + if (!ShouldRun(pWeapon)) return; switch (pWeapon->GetWeaponID()) diff --git a/Amalgam/src/Features/NoSpread/NoSpreadProjectile/NoSpreadProjectile.h b/Amalgam/src/Features/NoSpread/NoSpreadProjectile/NoSpreadProjectile.h index 002a33ec..1ac769fe 100644 --- a/Amalgam/src/Features/NoSpread/NoSpreadProjectile/NoSpreadProjectile.h +++ b/Amalgam/src/Features/NoSpread/NoSpreadProjectile/NoSpreadProjectile.h @@ -4,7 +4,7 @@ class CNoSpreadProjectile { private: - bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon); + bool ShouldRun(CTFWeaponBase* pWeapon); public: void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd); diff --git a/Amalgam/src/Features/Ticks/Ticks.cpp b/Amalgam/src/Features/Ticks/Ticks.cpp index 77e4f283..37d91967 100644 --- a/Amalgam/src/Features/Ticks/Ticks.cpp +++ b/Amalgam/src/Features/Ticks/Ticks.cpp @@ -389,14 +389,14 @@ void CTicks::SaveShootAngle(CUserCmd* pCmd, bool bSendPacket) static auto sv_maxusrcmdprocessticks_holdaim = H::ConVars.FindVar("sv_maxusrcmdprocessticks_holdaim"); if (bSendPacket) - m_bShootAngle = false; - else if (!m_bShootAngle && G::Attacking == 1 && sv_maxusrcmdprocessticks_holdaim->GetBool()) - m_vShootAngle = pCmd->viewangles, m_bShootAngle = true; + m_vShootAngle = std::nullopt; + else if (!m_vShootAngle && G::Attacking == 1 && sv_maxusrcmdprocessticks_holdaim->GetBool()) + m_vShootAngle = pCmd->viewangles; } Vec3* CTicks::GetShootAngle() { - if (m_bShootAngle && I::ClientState->chokedcommands) - return &m_vShootAngle; + if (m_vShootAngle && I::ClientState->chokedcommands) + return &m_vShootAngle.value(); return nullptr; } diff --git a/Amalgam/src/Features/Ticks/Ticks.h b/Amalgam/src/Features/Ticks/Ticks.h index c0552913..3f864374 100644 --- a/Amalgam/src/Features/Ticks/Ticks.h +++ b/Amalgam/src/Features/Ticks/Ticks.h @@ -17,9 +17,7 @@ private: bool m_bGoalReached = true; Vec3 m_vShootPos = {}; - - bool m_bShootAngle = false; - Vec3 m_vShootAngle = {}; + std::optional m_vShootAngle = std::nullopt; bool m_bPredictAntiwarp = false; bool m_bTimingUnsure = false; // we aren't sure when we'll actually fire, hold aim diff --git a/Amalgam/src/Features/Visuals/Visuals.cpp b/Amalgam/src/Features/Visuals/Visuals.cpp index 2b02228c..4fe03722 100644 --- a/Amalgam/src/Features/Visuals/Visuals.cpp +++ b/Amalgam/src/Features/Visuals/Visuals.cpp @@ -437,12 +437,9 @@ std::vector CVisuals::GetHitboxes(matrix3x4* aBones, CBaseAnimating* std::vector vBoxes = {}; - auto pModel = pEntity->GetModel(); - if (!pModel) return vBoxes; - auto pHDR = I::ModelInfoClient->GetStudiomodel(pModel); - if (!pHDR) return vBoxes; - auto pSet = pHDR->pHitboxSet(pEntity->m_nHitboxSet()); - if (!pSet) return vBoxes; + auto pSet = pEntity->GetHitboxSet(); + if (!pSet) + return vBoxes; if (vHitboxes.empty()) { @@ -453,7 +450,8 @@ std::vector CVisuals::GetHitboxes(matrix3x4* aBones, CBaseAnimating* for (int nHitbox : vHitboxes) { auto pBox = pSet->pHitbox(nHitbox); - if (!pBox) continue; + if (!pBox) + continue; bool bTargeted = nHitbox == iTarget; Vec3 vAngle; Math::MatrixAngles(aBones[pBox->bone], vAngle); diff --git a/Amalgam/src/SDK/Definitions/Main/CBaseAnimating.cpp b/Amalgam/src/SDK/Definitions/Main/CBaseAnimating.cpp index 440745fe..c1128e7c 100644 --- a/Amalgam/src/SDK/Definitions/Main/CBaseAnimating.cpp +++ b/Amalgam/src/SDK/Definitions/Main/CBaseAnimating.cpp @@ -2,42 +2,44 @@ #include "../../SDK.h" +mstudiohitboxset_t* CBaseAnimating::GetHitboxSet() +{ + auto pHDR = GetStudiomodel(); + if (!pHDR) + return nullptr; + + return pHDR->pHitboxSet(m_nHitboxSet()); +} + int CBaseAnimating::GetHitboxGroup(int nHitbox) { - auto pModel = GetModel(); - if (!pModel) return -1; - auto pHDR = I::ModelInfoClient->GetStudiomodel(pModel); - if (!pHDR) return -1; - auto pSet = pHDR->pHitboxSet(m_nHitboxSet()); - if (!pSet) return -1; + auto pSet = GetHitboxSet(); + if (!pSet) + return -1; auto pBox = pSet->pHitbox(nHitbox); - if (!pBox) return -1; + if (!pBox) + return -1; return pBox->group; } int CBaseAnimating::GetNumOfHitboxes() { - auto pModel = GetModel(); - if (!pModel) return 0; - auto pHDR = I::ModelInfoClient->GetStudiomodel(pModel); - if (!pHDR) return 0; - auto pSet = pHDR->pHitboxSet(m_nHitboxSet()); - if (!pSet) return 0; + auto pSet = GetHitboxSet(); + if (!pSet) + return 0; return pSet->numhitboxes; } Vec3 CBaseAnimating::GetHitboxOrigin(matrix3x4* aBones, int nHitbox, Vec3 vOffset) { - auto pModel = GetModel(); - if (!pModel) return {}; - auto pHDR = I::ModelInfoClient->GetStudiomodel(pModel); - if (!pHDR) return {}; - auto pSet = pHDR->pHitboxSet(m_nHitboxSet()); - if (!pSet || pSet->numhitboxes <= nHitbox) return {}; + auto pSet = GetHitboxSet(); + if (!pSet || pSet->numhitboxes <= nHitbox) + return {}; auto pBox = pSet->pHitbox(nHitbox); - if (!pBox) return {}; + if (!pBox) + return {}; Vec3 vOut; Math::VectorTransform(vOffset, aBones[pBox->bone], vOut); return vOut; @@ -45,14 +47,12 @@ Vec3 CBaseAnimating::GetHitboxOrigin(matrix3x4* aBones, int nHitbox, Vec3 vOffse Vec3 CBaseAnimating::GetHitboxCenter(matrix3x4* aBones, int nHitbox, Vec3 vOffset) { - auto pModel = GetModel(); - if (!pModel) return {}; - auto pHDR = I::ModelInfoClient->GetStudiomodel(pModel); - if (!pHDR) return {}; - auto pSet = pHDR->pHitboxSet(m_nHitboxSet()); - if (!pSet || pSet->numhitboxes <= nHitbox) return {}; + auto pSet = GetHitboxSet(); + if (!pSet || pSet->numhitboxes <= nHitbox) + return {}; auto pBox = pSet->pHitbox(nHitbox); - if (!pBox) return {}; + if (!pBox) + return {}; Vec3 vOut; Math::VectorTransform((pBox->bbmin + pBox->bbmax) / 2 + vOffset, aBones[pBox->bone], vOut); return vOut; @@ -60,14 +60,12 @@ Vec3 CBaseAnimating::GetHitboxCenter(matrix3x4* aBones, int nHitbox, Vec3 vOffse void CBaseAnimating::GetHitboxInfo(matrix3x4* aBones, int nHitbox, Vec3* pCenter, Vec3* pMins, Vec3* pMaxs, matrix3x4* pMatrix, Vec3 vOffset) { - auto pModel = GetModel(); - if (!pModel) return; - auto pHDR = I::ModelInfoClient->GetStudiomodel(pModel); - if (!pHDR) return; - auto pSet = pHDR->pHitboxSet(m_nHitboxSet()); - if (!pSet || pSet->numhitboxes <= nHitbox) return; + auto pSet = GetHitboxSet(); + if (!pSet || pSet->numhitboxes <= nHitbox) + return; auto pBox = pSet->pHitbox(nHitbox); - if (!pBox) return; + if (!pBox) + return; if (pMins) *pMins = pBox->bbmin; diff --git a/Amalgam/src/SDK/Definitions/Main/CBaseAnimating.h b/Amalgam/src/SDK/Definitions/Main/CBaseAnimating.h index 2f15edb7..aee3bbb8 100644 --- a/Amalgam/src/SDK/Definitions/Main/CBaseAnimating.h +++ b/Amalgam/src/SDK/Definitions/Main/CBaseAnimating.h @@ -56,6 +56,7 @@ public: return bReturn; } + mstudiohitboxset_t* GetHitboxSet(); int GetHitboxGroup(int nHitbox); int GetNumOfHitboxes(); Vec3 GetHitboxOrigin(matrix3x4* aBones, int nHitbox, Vec3 vOffset = {}); diff --git a/Amalgam/src/SDK/Definitions/Main/CBaseEntity.cpp b/Amalgam/src/SDK/Definitions/Main/CBaseEntity.cpp index 086aba3b..06922aff 100644 --- a/Amalgam/src/SDK/Definitions/Main/CBaseEntity.cpp +++ b/Amalgam/src/SDK/Definitions/Main/CBaseEntity.cpp @@ -33,6 +33,15 @@ Vec3 CBaseEntity::GetRenderCenter() return GetRenderOrigin() + (vMaxs - vMins) / 2; } +studiohdr_t* CBaseEntity::GetStudiomodel() +{ + auto pModel = GetModel(); + if (!pModel) + return nullptr; + + return I::ModelInfoClient->GetStudiomodel(pModel); +} + int CBaseEntity::IsInValidTeam() { switch (int nTeamNum = m_iTeamNum()) diff --git a/Amalgam/src/SDK/Definitions/Main/CBaseEntity.h b/Amalgam/src/SDK/Definitions/Main/CBaseEntity.h index d7ce3383..edb0387d 100644 --- a/Amalgam/src/SDK/Definitions/Main/CBaseEntity.h +++ b/Amalgam/src/SDK/Definitions/Main/CBaseEntity.h @@ -296,6 +296,7 @@ public: Vec3 GetOffset(); Vec3 GetCenter(); Vec3 GetRenderCenter(); + studiohdr_t* GetStudiomodel(); int IsInValidTeam(); int SolidMask(); int GetHitboxToBase(int nHitbox); diff --git a/Amalgam/src/SDK/Definitions/Main/CTFPlayer.cpp b/Amalgam/src/SDK/Definitions/Main/CTFPlayer.cpp index 69084a21..9ea8e259 100644 --- a/Amalgam/src/SDK/Definitions/Main/CTFPlayer.cpp +++ b/Amalgam/src/SDK/Definitions/Main/CTFPlayer.cpp @@ -121,16 +121,14 @@ bool CTFPlayer::IsCritBoosted() || InCond(TF_COND_CRITBOOSTED_RUNE_TEMP)) return true; - auto pWeapon = m_hActiveWeapon()->As(); - if (!pWeapon) - return false; - - auto pWeaponInfo = pWeapon->m_pWeaponInfo(); - if (!pWeaponInfo) - return false; - - if (InCond(TF_COND_CRITBOOSTED_RAGE_BUFF) && pWeaponInfo->m_iWeaponType == TF_WPN_TYPE_PRIMARY) - return true; + if (auto pWeapon = m_hActiveWeapon()->As()) + { + if (auto pWeaponInfo = pWeapon->m_pWeaponInfo()) + { + if (InCond(TF_COND_CRITBOOSTED_RAGE_BUFF) && pWeaponInfo->m_iWeaponType == TF_WPN_TYPE_PRIMARY) + return true; + } + } return false; } diff --git a/Amalgam/src/SDK/Helpers/ConVars/ConVars.cpp b/Amalgam/src/SDK/Helpers/ConVars/ConVars.cpp index a88664ff..07a76864 100644 --- a/Amalgam/src/SDK/Helpers/ConVars/ConVars.cpp +++ b/Amalgam/src/SDK/Helpers/ConVars/ConVars.cpp @@ -7,12 +7,10 @@ bool CConVars::Unlock() { if (!m_bUnlocked) { - ConCommandBase* pCmdBase = I::CVar->GetCommands(); - while (pCmdBase != nullptr) + for (ConCommandBase* pBase = I::CVar->GetCommands(); pBase; pBase = pBase->m_pNext) { - m_mFlagMap[pCmdBase] = pCmdBase->m_nFlags; - pCmdBase->m_nFlags &= ~(FCVAR_HIDDEN | FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT | FCVAR_NOT_CONNECTED); - pCmdBase = pCmdBase->m_pNext; + m_mFlagMap[pBase] = pBase->m_nFlags; + pBase->m_nFlags &= ~(FCVAR_HIDDEN | FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT | FCVAR_NOT_CONNECTED); } m_bUnlocked = true; diff --git a/Amalgam/src/SDK/Helpers/Entities/Entities.cpp b/Amalgam/src/SDK/Helpers/Entities/Entities.cpp index 717c51bf..905911e3 100644 --- a/Amalgam/src/SDK/Helpers/Entities/Entities.cpp +++ b/Amalgam/src/SDK/Helpers/Entities/Entities.cpp @@ -254,10 +254,10 @@ void CEntities::Store() if (n != I::EngineClient->GetLocalPlayer()) { bool bDormant = pPlayer->IsDormant(); - float flSimTime = pPlayer->m_flSimulationTime(), flOldSimTime = pPlayer->m_flOldSimulationTime(); - if (float flDeltaTime = m_aDeltaTimes[n] = TICKS_TO_TIME(std::clamp(TIME_TO_TICKS(flSimTime - flOldSimTime) - iLag, 0, 24))) + if (float flOldSimTime = m_aSimTimes[n], flSimTime = m_aSimTimes[n] = pPlayer->m_flSimulationTime(); + m_aDeltaTimes[n] = flSimTime != flOldSimTime) { - m_aLagTimes[n] = flDeltaTime; + m_aDeltaTimes[n] = m_aLagTimes[n] = TICKS_TO_TIME(std::clamp(TIME_TO_TICKS(flSimTime - flOldSimTime) - iLag, 1, 24)); m_aSetTicks[n] = I::GlobalVars->tickcount; if (!bDormant) { @@ -267,12 +267,11 @@ void CEntities::Store() if (pPlayer->IsAlive()) F::CheaterDetection.ReportChoke(pPlayer, m_aChokes[n]); + + m_aOldAngles[n] = m_aEyeAngles[n], m_aEyeAngles[n] = pPlayer->As()->GetEyeAngles(); } else m_aOrigins[n].clear(); - - m_aOldAngles[n] = m_aEyeAngles[n]; - m_aEyeAngles[n] = pPlayer->As()->GetEyeAngles(); } m_aChokes[n] = I::GlobalVars->tickcount - m_aSetTicks[n]; } @@ -507,18 +506,18 @@ CTFPlayerResource* CEntities::GetResource() return m_pPlayerResource; } -const std::vector& CEntities::GetGroup(byte iGroup) { return m_aGroups[iGroup]; } +const std::vector& CEntities::GetGroup(uint8_t iGroup) { return m_aGroups[iGroup]; } -float CEntities::GetDeltaTime(byte iIndex) { return iIndex < MAX_PLAYERS ? m_aDeltaTimes[iIndex] : TICK_INTERVAL; } -float CEntities::GetLagTime(byte iIndex) { return iIndex < MAX_PLAYERS ? m_aLagTimes[iIndex] : TICK_INTERVAL; } -int CEntities::GetChoke(byte iIndex) { return iIndex < MAX_PLAYERS ? m_aChokes[iIndex] : 0; } -Vec3 CEntities::GetEyeAngles(byte iIndex) { return iIndex < MAX_PLAYERS ? m_aEyeAngles[iIndex] : Vec3(); } -Vec3 CEntities::GetDeltaAngles(byte iIndex) { return iIndex < MAX_PLAYERS ? m_aEyeAngles[iIndex].DeltaAngle(m_aOldAngles[iIndex]) / GetLagTime(iIndex) * (F::Backtrack.GetReal() + TICKS_TO_TIME(F::Backtrack.GetAnticipatedChoke())) : Vec3(); } -bool CEntities::GetLagCompensation(byte iIndex) { return iIndex < MAX_PLAYERS ? m_aLagCompensation[iIndex] : false; } -void CEntities::SetLagCompensation(byte iIndex, bool bLagComp) { if (iIndex < MAX_PLAYERS) m_aLagCompensation[iIndex] = bLagComp; } -Vec3* CEntities::GetAvgVelocity(byte iIndex) { return iIndex < MAX_PLAYERS && iIndex != I::EngineClient->GetLocalPlayer() ? &m_aAvgVelocities[iIndex] : nullptr; } -void CEntities::SetAvgVelocity(byte iIndex, Vec3 vAvgVelocity) { if (iIndex < MAX_PLAYERS) m_aAvgVelocities[iIndex] = vAvgVelocity; } -std::deque* CEntities::GetOrigins(byte iIndex) { return iIndex < MAX_PLAYERS ? &m_aOrigins[iIndex] : nullptr; } +float CEntities::GetDeltaTime(uint16_t iIndex) { return iIndex < MAX_PLAYERS ? m_aDeltaTimes[iIndex] : TICK_INTERVAL; } +float CEntities::GetLagTime(uint16_t iIndex) { return iIndex < MAX_PLAYERS ? m_aLagTimes[iIndex] : TICK_INTERVAL; } +int CEntities::GetChoke(uint16_t iIndex) { return iIndex < MAX_PLAYERS ? m_aChokes[iIndex] : 0; } +Vec3 CEntities::GetEyeAngles(uint16_t iIndex) { return iIndex < MAX_PLAYERS ? m_aEyeAngles[iIndex] : Vec3(); } +Vec3 CEntities::GetDeltaAngles(uint16_t iIndex) { return iIndex < MAX_PLAYERS ? m_aEyeAngles[iIndex].DeltaAngle(m_aOldAngles[iIndex]) / GetLagTime(iIndex) * (F::Backtrack.GetReal() + TICKS_TO_TIME(F::Backtrack.GetAnticipatedChoke())) : Vec3(); } +bool CEntities::GetLagCompensation(uint16_t iIndex) { return iIndex < MAX_PLAYERS ? m_aLagCompensation[iIndex] : false; } +void CEntities::SetLagCompensation(uint16_t iIndex, bool bLagComp) { if (iIndex < MAX_PLAYERS) m_aLagCompensation[iIndex] = bLagComp; } +Vec3* CEntities::GetAvgVelocity(uint16_t iIndex) { return iIndex < MAX_PLAYERS && iIndex != I::EngineClient->GetLocalPlayer() ? &m_aAvgVelocities[iIndex] : nullptr; } +void CEntities::SetAvgVelocity(uint16_t iIndex, Vec3 vAvgVelocity) { if (iIndex < MAX_PLAYERS) m_aAvgVelocities[iIndex] = vAvgVelocity; } +std::deque* CEntities::GetOrigins(uint16_t iIndex) { return iIndex < MAX_PLAYERS ? &m_aOrigins[iIndex] : nullptr; } uint32_t CEntities::GetModel(unsigned short iIndex) { return iIndex < MAX_EDICTS ? m_aModels[iIndex] : 0; } bool CEntities::GetDormancy(unsigned short iIndex) { return iIndex < MAX_EDICTS ? m_aDormancy[iIndex] : false; } diff --git a/Amalgam/src/SDK/Helpers/Entities/Entities.h b/Amalgam/src/SDK/Helpers/Entities/Entities.h index 00e2e740..aeb6b12f 100644 --- a/Amalgam/src/SDK/Helpers/Entities/Entities.h +++ b/Amalgam/src/SDK/Helpers/Entities/Entities.h @@ -35,7 +35,7 @@ private: std::array, EntityEnum::GroupsMax> m_aGroups = {}; - std::array m_aDeltaTimes = {}, m_aLagTimes = {}; + std::array m_aSimTimes = {}, m_aDeltaTimes = {}, m_aLagTimes = {}; std::array m_aChokes = {}, m_aSetTicks = {}; std::array m_aOldAngles = {}, m_aEyeAngles = {}; std::array m_aLagCompensation = {}; @@ -71,18 +71,18 @@ public: CTFWeaponBase* GetWeapon(); CTFPlayerResource* GetResource(); - const std::vector& GetGroup(byte iGroup); + const std::vector& GetGroup(uint8_t iGroup); - float GetDeltaTime(byte iIndex); - float GetLagTime(byte iIndex); - int GetChoke(byte iIndex); - Vec3 GetEyeAngles(byte iIndex); - Vec3 GetDeltaAngles(byte iIndex); - bool GetLagCompensation(byte iIndex); - void SetLagCompensation(byte iIndex, bool bLagComp); - Vec3* GetAvgVelocity(byte iIndex); - void SetAvgVelocity(byte iIndex, Vec3 vAvgVelocity); - std::deque* GetOrigins(byte iIndex); + float GetDeltaTime(uint16_t iIndex); + float GetLagTime(uint16_t iIndex); + int GetChoke(uint16_t iIndex); + Vec3 GetEyeAngles(uint16_t iIndex); + Vec3 GetDeltaAngles(uint16_t iIndex); + bool GetLagCompensation(uint16_t iIndex); + void SetLagCompensation(uint16_t iIndex, bool bLagComp); + Vec3* GetAvgVelocity(uint16_t iIndex); + void SetAvgVelocity(uint16_t iIndex, Vec3 vAvgVelocity); + std::deque* GetOrigins(uint16_t iIndex); uint32_t GetModel(unsigned short iIndex); bool GetDormancy(unsigned short iIndex); diff --git a/Amalgam/src/Utils/Math/Math.h b/Amalgam/src/Utils/Math/Math.h index b15b14ba..e4e934e3 100644 --- a/Amalgam/src/Utils/Math/Math.h +++ b/Amalgam/src/Utils/Math/Math.h @@ -337,6 +337,27 @@ namespace Math return vOut; } + inline void MatrixInitialize(matrix3x4& mMatrix, const Vec3& vOrigin, const Vec3& vXAxis, const Vec3& vYAxis, const Vec3& vZAxis) + { + mMatrix[0][0] = vXAxis.x, mMatrix[0][1] = vYAxis.x, mMatrix[0][2] = vZAxis.x, mMatrix[0][3] = vOrigin.x; + mMatrix[1][0] = vXAxis.y, mMatrix[1][1] = vYAxis.y, mMatrix[1][2] = vZAxis.y, mMatrix[1][3] = vOrigin.y; + mMatrix[2][0] = vXAxis.z, mMatrix[2][1] = vYAxis.z, mMatrix[2][2] = vZAxis.z, mMatrix[2][3] = vOrigin.z; + } + + inline void MatrixInitialize(matrix3x4& mMatrix, const Vec3& vOrigin = {}, bool bAxes = true) + { + if (bAxes) + { + mMatrix[0][0] = 1, mMatrix[0][1] = 0, mMatrix[0][2] = 0; + mMatrix[1][0] = 0, mMatrix[1][1] = 1, mMatrix[1][2] = 0; + mMatrix[2][0] = 0, mMatrix[2][1] = 0, mMatrix[2][2] = 1; + } + + mMatrix[0][3] = vOrigin.x; + mMatrix[1][3] = vOrigin.y; + mMatrix[2][3] = vOrigin.z; + } + inline void MatrixCopy(const matrix3x4& mIn, matrix3x4& mOut) { for (int i = 0; i < 3; i++)