lob arc angles

fix vphys projectiles passing through bottom side of displacements in simulation
This commit is contained in:
rei-2
2026-03-19 17:55:31 -04:00
parent 0f3a2adeda
commit a95148a68e
27 changed files with 1515 additions and 1220 deletions
+2
View File
@@ -968,6 +968,7 @@
<ClCompile Include="src\Hooks\CHLTVCamera_CalcView.cpp" /> <ClCompile Include="src\Hooks\CHLTVCamera_CalcView.cpp" />
<ClCompile Include="src\Hooks\CInput_ValidateUserCmd.cpp" /> <ClCompile Include="src\Hooks\CInput_ValidateUserCmd.cpp" />
<ClCompile Include="src\Hooks\CModelLoader_Map_LoadModel.cpp" /> <ClCompile Include="src\Hooks\CModelLoader_Map_LoadModel.cpp" />
<ClCompile Include="src\Hooks\CM_TraceToDispTree.cpp" />
<ClCompile Include="src\Hooks\CTFPlayerShared_ShouldSuppressPrediction.cpp" /> <ClCompile Include="src\Hooks\CTFPlayerShared_ShouldSuppressPrediction.cpp" />
<ClCompile Include="src\Hooks\CTFRocketLauncher_CheckReloadMisfire.cpp" /> <ClCompile Include="src\Hooks\CTFRocketLauncher_CheckReloadMisfire.cpp" />
<ClCompile Include="src\Hooks\CTFPlayer_FireBullet.cpp" /> <ClCompile Include="src\Hooks\CTFPlayer_FireBullet.cpp" />
@@ -1321,6 +1322,7 @@
<ClInclude Include="src\SDK\Definitions\Interfaces\ISpatialPartition.h" /> <ClInclude Include="src\SDK\Definitions\Interfaces\ISpatialPartition.h" />
<ClInclude Include="src\SDK\Definitions\Misc\ServerClass.h" /> <ClInclude Include="src\SDK\Definitions\Misc\ServerClass.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CSmartPtr.h" /> <ClInclude Include="src\SDK\Definitions\Misc\CSmartPtr.h" />
<ClInclude Include="src\SDK\Definitions\Misc\TraceInfo.h" />
<ClInclude Include="src\SDK\Definitions\Misc\VCollide.h" /> <ClInclude Include="src\SDK\Definitions\Misc\VCollide.h" />
<ClInclude Include="src\SDK\Definitions\Steam\ISteamAppList.h" /> <ClInclude Include="src\SDK\Definitions\Steam\ISteamAppList.h" />
<ClInclude Include="src\SDK\Definitions\Steam\ISteamApps.h" /> <ClInclude Include="src\SDK\Definitions\Steam\ISteamApps.h" />
+2
View File
@@ -205,6 +205,7 @@
<ClCompile Include="src\SDK\Definitions\Misc\CByteSwap.cpp" /> <ClCompile Include="src\SDK\Definitions\Misc\CByteSwap.cpp" />
<ClCompile Include="src\Features\World\World.cpp" /> <ClCompile Include="src\Features\World\World.cpp" />
<ClCompile Include="src\Hooks\CModelLoader_Map_LoadModel.cpp" /> <ClCompile Include="src\Hooks\CModelLoader_Map_LoadModel.cpp" />
<ClCompile Include="src\Hooks\CM_TraceToDispTree.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\Utils\UtlVector\UtlVector.h" /> <ClInclude Include="src\Utils\UtlVector\UtlVector.h" />
@@ -608,6 +609,7 @@
<ClInclude Include="src\Features\World\World.h" /> <ClInclude Include="src\Features\World\World.h" />
<ClInclude Include="src\SDK\Definitions\Interfaces\WorldBrushData.h" /> <ClInclude Include="src\SDK\Definitions\Interfaces\WorldBrushData.h" />
<ClInclude Include="src\SDK\Definitions\Interfaces\CDispCollTree.h" /> <ClInclude Include="src\SDK\Definitions\Interfaces\CDispCollTree.h" />
<ClInclude Include="src\SDK\Definitions\Misc\TraceInfo.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="cpp.hint" /> <None Include="cpp.hint" />
+11 -5
View File
@@ -7,6 +7,7 @@
#include "../Features/EnginePrediction/EnginePrediction.h" #include "../Features/EnginePrediction/EnginePrediction.h"
#include "../Features/Visuals/Materials/Materials.h" #include "../Features/Visuals/Materials/Materials.h"
#include "../Features/Visuals/Visuals.h" #include "../Features/Visuals/Visuals.h"
#include "../Features/Spectate/Spectate.h"
#include "../SDK/Events/Events.h" #include "../SDK/Events/Events.h"
#include <Psapi.h> #include <Psapi.h>
@@ -145,17 +146,22 @@ void CCore::Unload()
if (F::Menu.m_bIsOpen) if (F::Menu.m_bIsOpen)
I::MatSystemSurface->SetCursorAlwaysVisible(false); I::MatSystemSurface->SetCursorAlwaysVisible(false);
if (I::Input->CAM_IsThirdPerson()) H::ConVars.FindVar("cl_wpn_sway_interp")->SetValue(0.f);
H::ConVars.FindVar("cl_wpn_sway_scale")->SetValue(0.f);
F::Visuals.RestoreWorldModulation();
if (auto pLocal = H::Entities.GetLocal())
{ {
if (auto pLocal = H::Entities.GetLocal()) if (F::Spectate.HasTarget())
{
F::Spectate.NetUpdateStart(pLocal);
I::EngineClient->SetViewAngles(F::Spectate.m_vOldView);
}
if (I::Input->CAM_IsThirdPerson())
{ {
I::Input->CAM_ToFirstPerson(); I::Input->CAM_ToFirstPerson();
pLocal->ThirdPersonSwitch(); pLocal->ThirdPersonSwitch();
} }
} }
F::Visuals.RestoreWorldModulation();
H::ConVars.FindVar("cl_wpn_sway_interp")->SetValue(0.f);
H::ConVars.FindVar("cl_wpn_sway_scale")->SetValue(0.f);
Sleep(250); Sleep(250);
F::EnginePrediction.Unload(); F::EnginePrediction.Unload();
+1 -1
View File
@@ -90,7 +90,7 @@ void CAimbot::Draw(CTFPlayer* pLocal)
if (Vars::Aimbot::General::AimFOV.Value >= 90.f) if (Vars::Aimbot::General::AimFOV.Value >= 90.f)
return; return;
float flRadius = tanf(DEG2RAD(Vars::Aimbot::General::AimFOV.Value)) / tanf(DEG2RAD(G::FOV) / 2) * float(H::Draw.m_nScreenW) * (4.f / 6.f) / (16.f / 9.f); float flRadius = tanf(Math::Deg2Rad(Vars::Aimbot::General::AimFOV.Value)) / tanf(Math::Deg2Rad(G::FOV) / 2) * float(H::Draw.m_nScreenW) * (4.f / 6.f) / (16.f / 9.f);
H::Draw.LineCircle(H::Draw.m_nScreenW / 2, H::Draw.m_nScreenH / 2, flRadius, 68, Vars::Colors::FOVCircle.Value); H::Draw.LineCircle(H::Draw.m_nScreenW / 2, H::Draw.m_nScreenH / 2, flRadius, 68, Vars::Colors::FOVCircle.Value);
} }
@@ -283,7 +283,7 @@ int CAimbotHitscan::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase*
std::sort(vRecords.begin(), vRecords.end(), [&](const TickRecord* a, const TickRecord* b) -> bool 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 vPosA = { a->m_aBones[iTargetBone][0][3], a->m_aBones[iTargetBone][1][3], a->m_aBones[iTargetBone][2][3] };
Vec3 vPosB = { 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 vAnglesA = Math::CalcAngle(m_vEyePos, vPosA);
Vec3 vAnglesB = Math::CalcAngle(m_vEyePos, vPosB); Vec3 vAnglesB = Math::CalcAngle(m_vEyePos, vPosB);
return pDoubletapAngle->DeltaAngle(vAnglesA).Length2D() < pDoubletapAngle->DeltaAngle(vAnglesB).Length2D(); return pDoubletapAngle->DeltaAngle(vAnglesA).Length2D() < pDoubletapAngle->DeltaAngle(vAnglesB).Length2D();
@@ -650,7 +650,8 @@ bool CAimbotHitscan::Aim(Vec3 vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod)
break; break;
} }
Math::ClampAngles(vOut); //if (iMethod != Vars::Aimbot::General::AimTypeEnum::Silent || Vars::Misc::Game::AntiCheatCompatibility.Value)
Math::ClampAngles(vOut);
return bReturn; return bReturn;
} }
@@ -450,7 +450,8 @@ bool CAimbotMelee::Aim(Vec3 vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod)
break; break;
} }
Math::ClampAngles(vOut); if (iMethod != Vars::Aimbot::General::AimTypeEnum::Silent || Vars::Misc::Game::AntiCheatCompatibility.Value)
Math::ClampAngles(vOut);
return bReturn; return bReturn;
} }
@@ -178,7 +178,7 @@ static inline std::vector<Target_t> GetTargets(CTFPlayer* pLocal, CTFWeaponBase*
float CAimbotProjectile::GetSplashRadius(CTFWeaponBase* pWeapon, CTFPlayer* pPlayer) float CAimbotProjectile::GetSplashRadius(CTFWeaponBase* pWeapon, CTFPlayer* pPlayer, float flScale)
{ {
float flRadius = 0.f; float flRadius = 0.f;
switch (pWeapon->GetWeaponID()) switch (pWeapon->GetWeaponID())
@@ -193,6 +193,11 @@ float CAimbotProjectile::GetSplashRadius(CTFWeaponBase* pWeapon, CTFPlayer* pPla
case TF_WEAPON_FLAREGUN_REVENGE: case TF_WEAPON_FLAREGUN_REVENGE:
if (pWeapon->As<CTFFlareGun>()->GetFlareGunType() == FLAREGUN_SCORCHSHOT) if (pWeapon->As<CTFFlareGun>()->GetFlareGunType() == FLAREGUN_SCORCHSHOT)
flRadius = TF_FLARE_DET_RADIUS; flRadius = TF_FLARE_DET_RADIUS;
break;
case TF_WEAPON_JAR:
case TF_WEAPON_JAR_MILK:
case TF_WEAPON_JAR_GAS:
return JAR_EXPLODE_RADIUS * flScale;
} }
if (!flRadius) if (!flRadius)
return 0.f; return 0.f;
@@ -206,7 +211,7 @@ float CAimbotProjectile::GetSplashRadius(CTFWeaponBase* pWeapon, CTFPlayer* pPla
if (pPlayer->InCond(TF_COND_BLASTJUMPING) && SDK::AttribHookValue(1.f, "rocketjump_attackrate_bonus", pWeapon) != 1.f) if (pPlayer->InCond(TF_COND_BLASTJUMPING) && SDK::AttribHookValue(1.f, "rocketjump_attackrate_bonus", pWeapon) != 1.f)
flRadius *= 0.8f; flRadius *= 0.8f;
} }
return flRadius * Vars::Aimbot::Projectile::SplashRadius.Value / 100; return flRadius * flScale;
} }
float CAimbotProjectile::GetSplashRadius(CBaseEntity* pProjectile, CTFWeaponBase* pWeapon, CTFPlayer* pPlayer, float flScale, CTFWeaponBase* pAirblast) float CAimbotProjectile::GetSplashRadius(CBaseEntity* pProjectile, CTFWeaponBase* pWeapon, CTFPlayer* pPlayer, float flScale, CTFWeaponBase* pAirblast)
@@ -233,6 +238,11 @@ float CAimbotProjectile::GetSplashRadius(CBaseEntity* pProjectile, CTFWeaponBase
case ETFClassID::CTFProjectile_Flare: case ETFClassID::CTFProjectile_Flare:
if (pWeapon && pWeapon->As<CTFFlareGun>()->GetFlareGunType() == FLAREGUN_SCORCHSHOT) if (pWeapon && pWeapon->As<CTFFlareGun>()->GetFlareGunType() == FLAREGUN_SCORCHSHOT)
flRadius = TF_FLARE_DET_RADIUS; flRadius = TF_FLARE_DET_RADIUS;
break;
case ETFClassID::CTFProjectile_Jar:
case ETFClassID::CTFProjectile_JarMilk:
case ETFClassID::CTFProjectile_JarGas:
return JAR_EXPLODE_RADIUS * flScale;
} }
if (pPlayer && pWeapon) if (pPlayer && pWeapon)
{ {
@@ -315,11 +325,17 @@ static inline int GetHitboxPriority(int nHitbox, Target_t& tTarget, Info_t& tInf
return -1; return -1;
}; };
std::unordered_map<int, Vec3> CAimbotProjectile::GetDirectPoints() Directs_t CAimbotProjectile::GetDirects()
{ {
std::unordered_map<int, Vec3> mPoints = {}; Directs_t mDirects = {};
if (Vars::Aimbot::Projectile::SplashPrediction.Value == Vars::Aimbot::Projectile::SplashPredictionEnum::Only && m_tInfo.m_flRadius)
return mDirects;
auto& tTarget = *m_tInfo.m_pTarget; auto& tTarget = *m_tInfo.m_pTarget;
byte iFlags = PointFlagsEnum::Regular;
if (Vars::Aimbot::Projectile::Modifiers.Value & Vars::Aimbot::Projectile::ModifiersEnum::AlternateAngles)
iFlags |= PointFlagsEnum::Alternate;
const Vec3 vMins = tTarget.m_pEntity->m_vecMins(), vMaxs = tTarget.m_pEntity->m_vecMaxs(); const Vec3 vMins = tTarget.m_pEntity->m_vecMins(), vMaxs = tTarget.m_pEntity->m_vecMaxs();
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
@@ -362,17 +378,35 @@ std::unordered_map<int, Vec3> CAimbotProjectile::GetDirectPoints()
vOff.x = std::clamp(vOff.x, vMins.x + Vars::Aimbot::Projectile::HuntsmanClamp.Value, vMaxs.x - Vars::Aimbot::Projectile::HuntsmanClamp.Value); vOff.x = std::clamp(vOff.x, vMins.x + Vars::Aimbot::Projectile::HuntsmanClamp.Value, vMaxs.x - Vars::Aimbot::Projectile::HuntsmanClamp.Value);
vOff.y = std::clamp(vOff.y, vMins.y + Vars::Aimbot::Projectile::HuntsmanClamp.Value, vMaxs.y - Vars::Aimbot::Projectile::HuntsmanClamp.Value); vOff.y = std::clamp(vOff.y, vMins.y + Vars::Aimbot::Projectile::HuntsmanClamp.Value, vMaxs.y - Vars::Aimbot::Projectile::HuntsmanClamp.Value);
vOff.z = std::clamp(vOff.z, vMins.z + Vars::Aimbot::Projectile::HuntsmanClamp.Value, vMaxs.z - Vars::Aimbot::Projectile::HuntsmanClamp.Value); vOff.z = std::clamp(vOff.z, vMins.z + Vars::Aimbot::Projectile::HuntsmanClamp.Value, vMaxs.z - Vars::Aimbot::Projectile::HuntsmanClamp.Value);
mPoints[iPriority] = vOff; mDirects[iPriority] = { vOff, iFlags };
} }
else else
mPoints[iPriority] = Vec3(0, 0, vMaxs.z - Vars::Aimbot::Projectile::VerticalShift.Value); mDirects[iPriority] = { Vec3(0, 0, vMaxs.z - Vars::Aimbot::Projectile::VerticalShift.Value), iFlags };
break;
case BOUNDS_BODY:
mDirects[iPriority] = { Vec3(0, 0, (vMaxs.z - vMins.z) / 2), iFlags };
break;
case BOUNDS_FEET:
mDirects[iPriority] = { Vec3(0, 0, vMins.z + Vars::Aimbot::Projectile::VerticalShift.Value), iFlags };
break; break;
case BOUNDS_BODY: mPoints[iPriority] = Vec3(0, 0, (vMaxs.z - vMins.z) / 2); break;
case BOUNDS_FEET: mPoints[iPriority] = Vec3(0, 0, vMins.z + Vars::Aimbot::Projectile::VerticalShift.Value); break;
} }
} }
return mPoints; return mDirects;
}
Splashes_t CAimbotProjectile::GetSplashes()
{
Splashes_t vSplashes = {};
if (Vars::Aimbot::Projectile::SplashPrediction.Value == Vars::Aimbot::Projectile::SplashPredictionEnum::Off || !m_tInfo.m_flRadius)
return vSplashes;
vSplashes.push_back(PointFlagsEnum::Regular);
if (Vars::Aimbot::Projectile::Modifiers.Value & Vars::Aimbot::Projectile::ModifiersEnum::AlternateAngles)
vSplashes.push_back(PointFlagsEnum::Alternate);
return vSplashes;
} }
static inline std::vector<Vec3> ComputeSphere(float flRadius, int iSamples) static inline std::vector<Vec3> ComputeSphere(float flRadius, int iSamples)
@@ -386,7 +420,7 @@ static inline std::vector<Vec3> ComputeSphere(float flRadius, int iSamples)
float flRotateX = Vars::Aimbot::Projectile::SplashRotateX.Value < 0.f ? SDK::RandomFloat(0.f, 360.f) : Vars::Aimbot::Projectile::SplashRotateX.Value; float flRotateX = Vars::Aimbot::Projectile::SplashRotateX.Value < 0.f ? SDK::RandomFloat(0.f, 360.f) : Vars::Aimbot::Projectile::SplashRotateX.Value;
float flRotateY = Vars::Aimbot::Projectile::SplashRotateY.Value < 0.f ? SDK::RandomFloat(0.f, 360.f) : Vars::Aimbot::Projectile::SplashRotateY.Value; float flRotateY = Vars::Aimbot::Projectile::SplashRotateY.Value < 0.f ? SDK::RandomFloat(0.f, 360.f) : Vars::Aimbot::Projectile::SplashRotateY.Value;
float a = PI * (3.f - sqrtf(5.f)); float a = Math::PI * (3.f - sqrtf(5.f));
for (int n = 0; n < iSamples; n++) for (int n = 0; n < iSamples; n++)
{ {
float t = a * n; float t = a * n;
@@ -514,7 +548,7 @@ static inline void HandleFace(const Face_t& tFace, std::vector<Vec3>& vPoints, f
} }
// possibly add air splash for autodet weapons // possibly add air splash for autodet weapons
void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Vec3>& vSplashPoints) void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Vec3>& vSplashPoints, byte iFlags)
{ {
vSplashPoints.clear(); vSplashPoints.clear();
@@ -558,10 +592,10 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Vec3>& vSpl
else else
{ {
Point_t tPoint = { vPoint, {} }; Point_t tPoint = { vPoint, {} };
CalculateAngle(m_tInfo.m_vLocalEye, tPoint.m_vPoint, 0, tPoint.m_tSolution, CalculateFlagsEnum::None); CalculateAngle(m_tInfo.m_vLocalEye, tPoint.m_vPoint, 0, tPoint.m_tSolution, iFlags);
if (tPoint.m_tSolution.m_iCalculated == CalculateResultEnum::Bad) if (tPoint.m_tSolution.m_iCalculated == CalculateResultEnum::Bad)
return false; return false;
vPoint -= Vec3(0, 0, (m_tInfo.m_flGravity * 800.f * pow(tPoint.m_tSolution.m_flTime, 2)) / 2); vPoint -= Vec3(0, 0, (m_tInfo.m_flGravity * 800.f * powf(tPoint.m_tSolution.m_flTime, 2)) / 2);
vAngle = Vec3(tPoint.m_tSolution.m_flPitch, tPoint.m_tSolution.m_flYaw); vAngle = Vec3(tPoint.m_tSolution.m_flPitch, tPoint.m_tSolution.m_flYaw);
} }
return fCheckNormal(trace.plane.normal, vPoint, &vAngle); return fCheckNormal(trace.plane.normal, vPoint, &vAngle);
@@ -571,7 +605,7 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Vec3>& vSpl
{ {
Vec3 vPoint = vSpherePoints[i] + vTargetCenter; Vec3 vPoint = vSpherePoints[i] + vTargetCenter;
Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, vPoint, 0, tSolution, false); Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, vPoint, 0, tSolution, iFlags);
if (tSolution.m_iCalculated == CalculateResultEnum::Bad) if (tSolution.m_iCalculated == CalculateResultEnum::Bad)
continue; continue;
@@ -593,10 +627,10 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Vec3>& vSpl
else else
{ {
Point_t tPoint = { vPoint, {} }; Point_t tPoint = { vPoint, {} };
CalculateAngle(m_tInfo.m_vLocalEye, tPoint.m_vPoint, 0, tPoint.m_tSolution, CalculateFlagsEnum::None); CalculateAngle(m_tInfo.m_vLocalEye, tPoint.m_vPoint, 0, tPoint.m_tSolution, iFlags);
if (tPoint.m_tSolution.m_iCalculated == CalculateResultEnum::Bad) if (tPoint.m_tSolution.m_iCalculated == CalculateResultEnum::Bad)
return false; return false;
vPoint -= Vec3(0, 0, (m_tInfo.m_flGravity * 800.f * pow(tPoint.m_tSolution.m_flTime, 2)) / 2); vPoint -= Vec3(0, 0, (m_tInfo.m_flGravity * 800.f * powf(tPoint.m_tSolution.m_flTime, 2)) / 2);
vAngle = Vec3(tPoint.m_tSolution.m_flPitch, tPoint.m_tSolution.m_flYaw); vAngle = Vec3(tPoint.m_tSolution.m_flPitch, tPoint.m_tSolution.m_flYaw);
} }
return fCheckNormal(vNormal, vPoint, &vAngle); return fCheckNormal(vNormal, vPoint, &vAngle);
@@ -624,7 +658,7 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Vec3>& vSpl
#endif #endif
} }
std::vector<Point_t> CAimbotProjectile::GetSplashPoints(Vec3 vOrigin, std::vector<Vec3>& vSplashPoints, int iSimTime) std::vector<Point_t> CAimbotProjectile::GetSplashPoints(Vec3 vOrigin, std::vector<Vec3>& vSplashPoints, int iSimTime, byte iFlags)
{ {
std::vector<std::pair<Point_t, float>> vPointDistances = {}; std::vector<std::pair<Point_t, float>> vPointDistances = {};
@@ -634,7 +668,7 @@ std::vector<Point_t> CAimbotProjectile::GetSplashPoints(Vec3 vOrigin, std::vecto
for (auto it = vSplashPoints.begin(); it != vSplashPoints.end();) for (auto it = vSplashPoints.begin(); it != vSplashPoints.end();)
{ {
Point_t tPoint = { *it, {} }; Point_t tPoint = { *it, {} };
CalculateAngle(m_tInfo.m_vLocalEye, tPoint.m_vPoint, iSimTime, tPoint.m_tSolution, CalculateFlagsEnum::Accuracy, !m_tInfo.m_iArmTime ? 0 : -1); CalculateAngle(m_tInfo.m_vLocalEye, tPoint.m_vPoint, iSimTime, tPoint.m_tSolution, iFlags, !m_tInfo.m_iArmTime ? 0 : -1);
if (tPoint.m_tSolution.m_iCalculated != CalculateResultEnum::Good) if (tPoint.m_tSolution.m_iCalculated != CalculateResultEnum::Good)
{ {
++it; ++it;
@@ -710,13 +744,13 @@ static inline Vec3 PullPoint(const Vec3& vPoint, Vec3 vLocalPos, Info_t& tInfo,
const Vec3 vDelta = vTargetPos - vLocalPos; const Vec3 vDelta = vTargetPos - vLocalPos;
const float flDist = vDelta.Length2D(); const float flDist = vDelta.Length2D();
const float flRoot = pow(tInfo.m_flVelocity, 4) - flGrav * (flGrav * pow(flDist, 2) + 2.f * vDelta.z * pow(tInfo.m_flVelocity, 2)); const float flRoot = powf(tInfo.m_flVelocity, 4) - flGrav * (flGrav * powf(flDist, 2) + 2.f * vDelta.z * powf(tInfo.m_flVelocity, 2));
if (flRoot < 0.f) if (flRoot < 0.f)
return vPoint; return vPoint;
float flPitch = atan((pow(tInfo.m_flVelocity, 2) - sqrt(flRoot)) / (flGrav * flDist)); float flPitch = atan((powf(tInfo.m_flVelocity, 2) - sqrt(flRoot)) / (flGrav * flDist));
float flTime = flDist / (cos(flPitch) * tInfo.m_flVelocity) - tInfo.m_flOffsetTime; float flTime = flDist / (cos(flPitch) * tInfo.m_flVelocity) - tInfo.m_flOffsetTime;
return vLocalPos + Vec3(0, 0, (flGrav * pow(flTime, 2)) / 2); return vLocalPos + Vec3(0, 0, (flGrav * powf(flTime, 2)) / 2);
}; };
vLocalPos = fHeightenLocalPos(); vLocalPos = fHeightenLocalPos();
@@ -727,97 +761,145 @@ static inline Vec3 PullPoint(const Vec3& vPoint, Vec3 vLocalPos, Info_t& tInfo,
static inline void SolveProjectileSpeed(CTFWeaponBase* pWeapon, const Vec3& vLocalPos, const Vec3& vTargetPos, float& flVelocity, float& flDragTime, const float flGravity) static inline float GetDrag(float flVelocity, ProjectileInfo* pInfo, int iFlags)
{ { // stupid, would like not to hardcode magic values
if (!F::ProjSim.m_pObj->IsDragEnabled() || F::ProjSim.m_pObj->m_dragBasis.IsZero()) if (!(iFlags & CalculateFlagsEnum::AccountDrag) || !F::ProjSim.m_pObj->m_dragCoefficient || !F::ProjSim.m_pObj->m_dragBasis)
return; return 0.f;
const float flGrav = flGravity * 800.0f;
const Vec3 vDelta = vTargetPos - vLocalPos;
const float flDist = vDelta.Length2D();
const float flRoot = pow(flVelocity, 4) - flGrav * (flGrav * pow(flDist, 2) + 2.f * vDelta.z * pow(flVelocity, 2));
if (flRoot < 0.f)
return;
const float flPitch = atan((pow(flVelocity, 2) - sqrt(flRoot)) / (flGrav * flDist));
const float flTime = flDist / (cos(flPitch) * flVelocity);
float flDrag = 0.f;
if (Vars::Aimbot::Projectile::DragOverride.Value) if (Vars::Aimbot::Projectile::DragOverride.Value)
flDrag = Vars::Aimbot::Projectile::DragOverride.Value; return Vars::Aimbot::Projectile::DragOverride.Value;
if (!(iFlags & CalculateFlagsEnum::AlternateAngle))
{
switch (pInfo->m_uType)
{
case FNV1A::Hash32Const("models/weapons/w_models/w_grenade_grenadelauncher.mdl"):
if (!SDK::AttribHookValue(0, "grenade_no_spin", pInfo->m_pWeapon))
return Math::RemapVal(flVelocity, 1217.f, k_flMaxVelocity, 0.120f, 0.200f); // 0.120 normal, 0.200 capped, 0.300 v3000
else
return Math::RemapVal(flVelocity, 1217.f, k_flMaxVelocity, 0.060f, 0.085f); // 0.060 normal, 0.085 capped, 0.120 v3000
case FNV1A::Hash32Const("models/weapons/w_models/w_cannonball.mdl"):
return Math::RemapVal(flVelocity, 1454.f, k_flMaxVelocity, 0.385f, 0.530f); // 0.385 normal, 0.530 capped, 0.790 v3000
case FNV1A::Hash32Const("models/weapons/w_models/w_stickybomb.mdl"):
return Math::RemapVal(flVelocity, 922.f, k_flMaxVelocity, 0.085f, 0.190f); // 0.085 low, 0.190 capped, 0.230 v2400
case FNV1A::Hash32Const("models/workshop_partner/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl"):
return 0.310f;
case FNV1A::Hash32Const("models/weapons/w_models/w_baseball.mdl"):
return 0.180f;
case FNV1A::Hash32Const("models/weapons/c_models/c_xms_festive_ornament.mdl"):
return 0.285f;
case FNV1A::Hash32Const("models/weapons/c_models/urinejar.mdl"):
case FNV1A::Hash32Const("models/workshop/weapons/c_models/c_madmilk/c_madmilk.mdl"):
case FNV1A::Hash32Const("models/weapons/c_models/c_breadmonster/c_breadmonster.mdl"):
case FNV1A::Hash32Const("models/weapons/c_models/c_breadmonster/c_breadmonster_milk.mdl"):
return 0.057f;
case FNV1A::Hash32Const("models/weapons/c_models/c_gascan/c_gascan.mdl"):
return 0.530f;
}
}
else else
{ {
switch (pWeapon->m_iItemDefinitionIndex()) // the remaps are dumb but they work so /shrug switch (pInfo->m_uType)
{ {
case Demoman_m_GrenadeLauncher: case FNV1A::Hash32Const("models/weapons/w_models/w_grenade_grenadelauncher.mdl"):
case Demoman_m_GrenadeLauncherR: if (!SDK::AttribHookValue(0, "grenade_no_spin", pInfo->m_pWeapon))
case Demoman_m_FestiveGrenadeLauncher: return Math::RemapVal(flVelocity, 1217.f, k_flMaxVelocity, 0.056f, 0.062f);
case Demoman_m_Autumn: else
case Demoman_m_MacabreWeb: return Math::RemapVal(flVelocity, 1217.f, k_flMaxVelocity, 0.030f, 0.033f);
case Demoman_m_Rainbow: case FNV1A::Hash32Const("models/weapons/w_models/w_cannonball.mdl"):
case Demoman_m_SweetDreams: return Math::RemapVal(flVelocity, 1454.f, k_flMaxVelocity, 0.099f, 0.092f);
case Demoman_m_CoffinNail: case FNV1A::Hash32Const("models/weapons/w_models/w_stickybomb.mdl"):
case Demoman_m_TopShelf: return Math::RemapVal(flVelocity, 922.f, k_flMaxVelocity, 0.048f, 0.060f);
case Demoman_m_Warhawk: case FNV1A::Hash32Const("models/workshop_partner/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl"):
case Demoman_m_ButcherBird: return 0.075f;
case Demoman_m_TheIronBomber: flDrag = Math::RemapVal(flVelocity, 1217.f, k_flMaxVelocity, 0.120f, 0.200f); break; // 0.120 normal, 0.200 capped, 0.300 v3000 case FNV1A::Hash32Const("models/weapons/w_models/w_baseball.mdl"):
case Demoman_m_TheLochnLoad: flDrag = Math::RemapVal(flVelocity, 1504.f, k_flMaxVelocity, 0.070f, 0.085f); break; // 0.070 normal, 0.085 capped, 0.120 v3000 return 0.057f;
case Demoman_m_TheLooseCannon: flDrag = Math::RemapVal(flVelocity, 1454.f, k_flMaxVelocity, 0.385f, 0.530f); break; // 0.385 normal, 0.530 capped, 0.790 v3000 case FNV1A::Hash32Const("models/weapons/c_models/c_xms_festive_ornament.mdl"):
case Demoman_s_StickybombLauncher: return 0.072f;
case Demoman_s_StickybombLauncherR: case FNV1A::Hash32Const("models/weapons/c_models/urinejar.mdl"):
case Demoman_s_FestiveStickybombLauncher: case FNV1A::Hash32Const("models/workshop/weapons/c_models/c_madmilk/c_madmilk.mdl"):
case Demoman_s_TheQuickiebombLauncher: case FNV1A::Hash32Const("models/weapons/c_models/c_breadmonster/c_breadmonster.mdl"):
case Demoman_s_TheScottishResistance: flDrag = Math::RemapVal(flVelocity, 922.f, k_flMaxVelocity, 0.085f, 0.190f); break; // 0.085 low, 0.190 capped, 0.230 v2400 case FNV1A::Hash32Const("models/weapons/c_models/c_breadmonster/c_breadmonster_milk.mdl"):
case Scout_s_TheFlyingGuillotine: return 0.030f;
case Scout_s_TheFlyingGuillotineG: flDrag = 0.310f; break; case FNV1A::Hash32Const("models/weapons/c_models/c_gascan/c_gascan.mdl"):
case Scout_t_TheSandman: flDrag = 0.180f; break; return 0.089f;
case Scout_t_TheWrapAssassin: flDrag = 0.285f; break;
case Scout_s_MadMilk:
case Scout_s_MutatedMilk:
case Sniper_s_Jarate:
case Sniper_s_FestiveJarate:
case Sniper_s_TheSelfAwareBeautyMark: flDrag = 0.057f; break;
} }
} }
float flOverride = Vars::Aimbot::Projectile::TimeOverride.Value; return 0.f;
flDragTime = powf(flTime, 2) * flDrag / (flOverride ? flOverride : 1.5f); // rough estimate to prevent m_flTime being too low
flVelocity = flVelocity - flVelocity * flTime * flDrag;
} }
void CAimbotProjectile::CalculateAngle(const Vec3& vLocalPos, const Vec3& vTargetPos, int iSimTime, Solution_t& tOut, int iFlags, int iTolerance)
static inline bool GetAngle(const Vec3& vLocalPos, const Vec3& vTargetPos, int iFlags, Info_t& tInfo, float& flPitch, float& flYaw, float& flTime)
{
float flVelocity = tInfo.m_flVelocity;
float flGrav = tInfo.m_flGravity * 800.f;
Vec3 vDelta = vTargetPos - vLocalPos;
float flDist = vDelta.Length2D();
float flDrag = GetDrag(flVelocity, F::ProjSim.m_pCurrent, iFlags);
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vTargetPos);
flYaw = vAngleTo.y;
if (!flGrav)
flPitch = -Math::Deg2Rad(vAngleTo.x);
else
{
float flRoot = powf(flVelocity, 4) - flGrav * (flGrav * powf(flDist, 2) + 2.f * vDelta.z * powf(flVelocity, 2));
if (flRoot < 0.f)
return false;
if (!(iFlags & CalculateFlagsEnum::AlternateAngle))
flPitch = atan((powf(flVelocity, 2) - sqrt(flRoot)) / (flGrav * flDist));
else
flPitch = atan((powf(flVelocity, 2) + sqrt(flRoot)) / (flGrav * flDist));
if (flDrag)
{ // drag is handled in a stupid manner, would like something better than this
float flTime = flDist / (flVelocity * cos(flPitch));
flVelocity *= 1 - flDrag * flTime;
flRoot = powf(flVelocity, 4) - flGrav * (flGrav * powf(flDist, 2) + 2.f * vDelta.z * powf(flVelocity, 2));
if (flRoot < 0.f)
return false;
if (!(iFlags & CalculateFlagsEnum::AlternateAngle))
flPitch = atan((powf(flVelocity, 2) - sqrt(flRoot)) / (flGrav * flDist));
else
flPitch = atan((powf(flVelocity, 2) + sqrt(flRoot)) / (flGrav * flDist));
//flVelocity = flVelocity / (flDrag * flTime) * (1.f - powf(Math::E, -flDrag * flTime));
flVelocity = flVelocity / (1 + 0.5f * (1 - powf(Math::E, -flDrag * flTime)));
flVelocity *= 1 + vDelta.z / flVelocity * TICK_INTERVAL * flTime;
}
}
flTime = flDist / (flVelocity * cos(flPitch));
if (Vars::Aimbot::Projectile::TimeOverride.Value)
flTime *= Vars::Aimbot::Projectile::TimeOverride.Value;
return true;
}
void CAimbotProjectile::CalculateAngle(const Vec3& vLocalPos, const Vec3& vTargetPos, int iSimTime, Solution_t& tOut, byte iFlags, int iTolerance)
{ {
if (tOut.m_iCalculated != CalculateResultEnum::Pending) if (tOut.m_iCalculated != CalculateResultEnum::Pending)
return; return;
const float flGrav = m_tInfo.m_flGravity * 800.f;
float flPitch, flYaw; float flPitch, flYaw;
{ // basic trajectory pass { // basic trajectory pass
float flVelocity = m_tInfo.m_flVelocity, flDragTime = 0.f; //Vec3 vForward, vRight, vUp; Math::AngleVectors(Math::CalcAngle(vLocalPos, vTargetPos), &vForward, &vRight, &vUp);
if (iFlags & CalculateFlagsEnum::AccountDrag && m_tInfo.m_pWeapon && F::ProjSim.m_pObj->IsDragEnabled() && !F::ProjSim.m_pObj->m_dragBasis.IsZero()) //Vec3 vShootPos = vLocalPos + (vForward * m_tInfo.m_vOffset.x) + (vRight * m_tInfo.m_vOffset.y) + (vUp * m_tInfo.m_vOffset.z);
if (!GetAngle(vLocalPos, vTargetPos, iFlags, m_tInfo, flPitch, flYaw, tOut.m_flTime))
{ {
Vec3 vForward, vRight, vUp; Math::AngleVectors(Math::CalcAngle(vLocalPos, vTargetPos), &vForward, &vRight, &vUp); tOut.m_iCalculated = CalculateResultEnum::Bad;
Vec3 vShootPos = vLocalPos + (vForward * m_tInfo.m_vOffset.x) + (vRight * m_tInfo.m_vOffset.y) + (vUp * m_tInfo.m_vOffset.z); return;
SolveProjectileSpeed(m_tInfo.m_pWeapon, vShootPos, vTargetPos, flVelocity, flDragTime, m_tInfo.m_flGravity);
} }
Vec3 vDelta = vTargetPos - vLocalPos; tOut.m_flTime -= m_tInfo.m_flOffsetTime;
float flDist = vDelta.Length2D(); tOut.m_flPitch = flPitch = -Math::Rad2Deg(flPitch) - m_tInfo.m_vAngFix.x;
tOut.m_flYaw = flYaw -= m_tInfo.m_vAngFix.y;
Vec3 vAngleTo = Math::CalcAngle(vLocalPos, vTargetPos);
if (!flGrav)
flPitch = -DEG2RAD(vAngleTo.x);
else
{ // arch
float flRoot = pow(flVelocity, 4) - flGrav * (flGrav * pow(flDist, 2) + 2.f * vDelta.z * pow(flVelocity, 2));
if (tOut.m_iCalculated = flRoot < 0.f ? CalculateResultEnum::Bad : CalculateResultEnum::Pending)
return;
flPitch = atan((pow(flVelocity, 2) - sqrt(flRoot)) / (flGrav * flDist));
}
tOut.m_flTime = flDist / (cos(flPitch) * flVelocity) - m_tInfo.m_flOffsetTime + flDragTime;
tOut.m_flPitch = flPitch = -RAD2DEG(flPitch) - m_tInfo.m_vAngFix.x;
tOut.m_flYaw = flYaw = vAngleTo.y - m_tInfo.m_vAngFix.y;
} }
int iTimeTo = ceilf(tOut.m_flTime / TICK_INTERVAL); int iTimeTo = ceilf(tOut.m_flTime / TICK_INTERVAL);
@@ -827,8 +909,11 @@ void CAimbotProjectile::CalculateAngle(const Vec3& vLocalPos, const Vec3& vTarge
tOut.m_iCalculated = bGood ? CalculateResultEnum::Good : CalculateResultEnum::Time; tOut.m_iCalculated = bGood ? CalculateResultEnum::Good : CalculateResultEnum::Time;
return; return;
} }
else if (tOut.m_iCalculated = bGood ? CalculateResultEnum::Pending : CalculateResultEnum::Time) else if (!bGood)
{
tOut.m_iCalculated = CalculateResultEnum::Time;
return; return;
}
int iSimFlags = (iFlags & CalculateFlagsEnum::SetupClip ? ProjSimEnum::Redirect : ProjSimEnum::None) | ProjSimEnum::NoRandomAngles | ProjSimEnum::PredictCmdNum; int iSimFlags = (iFlags & CalculateFlagsEnum::SetupClip ? ProjSimEnum::Redirect : ProjSimEnum::None) | ProjSimEnum::NoRandomAngles | ProjSimEnum::PredictCmdNum;
#ifdef SPLASH_DEBUG5 #ifdef SPLASH_DEBUG5
@@ -836,7 +921,7 @@ void CAimbotProjectile::CalculateAngle(const Vec3& vLocalPos, const Vec3& vTarge
{ {
if (Vars::Visuals::Trajectory::Override.Value) if (Vars::Visuals::Trajectory::Override.Value)
{ {
if (!Vars::Visuals::Trajectory::Pipes.Value) if (!Vars::Visuals::Trajectory::ForwardRedirect.Value)
s_mTraceCount[__FUNCTION__": setup trace"]++; s_mTraceCount[__FUNCTION__": setup trace"]++;
} }
else else
@@ -861,63 +946,53 @@ void CAimbotProjectile::CalculateAngle(const Vec3& vLocalPos, const Vec3& vTarge
} }
#endif #endif
m_tProjInfo = {}; m_tProjInfo = {};
if (tOut.m_iCalculated = !F::ProjSim.GetInfo(m_tInfo.m_pLocal, m_tInfo.m_pWeapon, { flPitch, flYaw, 0 }, m_tProjInfo, iSimFlags) ? CalculateResultEnum::Bad : CalculateResultEnum::Pending) if (!F::ProjSim.GetInfo(m_tInfo.m_pLocal, m_tInfo.m_pWeapon, { flPitch, flYaw, 0 }, m_tProjInfo, iSimFlags))
{
tOut.m_iCalculated = CalculateResultEnum::Bad;
return; return;
}
{ // calculate trajectory from projectile origin { // calculate trajectory from projectile origin
float flVelocity = m_tInfo.m_flVelocity, flDragTime = 0.f; if (!GetAngle(m_tProjInfo.m_vPos, vTargetPos, iFlags, m_tInfo, tOut.m_flPitch, tOut.m_flYaw, tOut.m_flTime))
if (iFlags & CalculateFlagsEnum::AccountDrag && F::ProjSim.m_pObj->IsDragEnabled() && !F::ProjSim.m_pObj->m_dragBasis.IsZero())
SolveProjectileSpeed(m_tInfo.m_pWeapon, m_tProjInfo.m_vPos, vTargetPos, flVelocity, flDragTime, m_tInfo.m_flGravity);
Vec3 vDelta = vTargetPos - m_tProjInfo.m_vPos;
float flDist = vDelta.Length2D();
Vec3 vAngleTo = Math::CalcAngle(m_tProjInfo.m_vPos, vTargetPos);
if (!flGrav)
tOut.m_flPitch = -DEG2RAD(vAngleTo.x);
else
{ // arch
float flRoot = pow(flVelocity, 4) - flGrav * (flGrav * pow(flDist, 2) + 2.f * vDelta.z * pow(flVelocity, 2));
if (tOut.m_iCalculated = flRoot < 0.f ? CalculateResultEnum::Bad : CalculateResultEnum::Pending)
return;
tOut.m_flPitch = atan((pow(flVelocity, 2) - sqrt(flRoot)) / (flGrav * flDist));
}
tOut.m_flTime = flDist / (cos(tOut.m_flPitch) * flVelocity) + flDragTime;
}
{ // correct yaw
Vec3 vShootPos = (m_tProjInfo.m_vPos - vLocalPos).To2D();
Vec3 vTarget = vTargetPos - vLocalPos;
Vec3 vForward; Math::AngleVectors(m_tProjInfo.m_vAng, &vForward); vForward.Normalize2D();
float flB = 2 * (vShootPos.x * vForward.x + vShootPos.y * vForward.y);
float flC = vShootPos.Length2DSqr() - vTarget.Length2DSqr();
auto vSolutions = Math::SolveQuadratic(1.f, flB, flC);
if (!vSolutions.empty())
{ {
vShootPos += vForward * vSolutions.front(); tOut.m_iCalculated = CalculateResultEnum::Bad;
tOut.m_flYaw = flYaw - (RAD2DEG(atan2(vShootPos.y, vShootPos.x)) - flYaw); return;
flYaw = RAD2DEG(atan2(vShootPos.y, vShootPos.x));
} }
}
{ // correct pitch { // correct yaw
if (flGrav) Vec3 vShootPos = (m_tProjInfo.m_vPos - vLocalPos).To2D();
{ Vec3 vTarget = vTargetPos - vLocalPos;
flPitch -= m_tProjInfo.m_vAng.x; Vec3 vForward; Math::AngleVectors(m_tProjInfo.m_vAng, &vForward); vForward.Normalize2D();
tOut.m_flPitch = -RAD2DEG(tOut.m_flPitch) + flPitch - m_tInfo.m_vAngFix.x; float flB = 2 * (vShootPos.x * vForward.x + vShootPos.y * vForward.y);
} float flC = vShootPos.Length2DSqr() - vTarget.Length2DSqr();
else
{
Vec3 vShootPos = Math::RotatePoint(m_tProjInfo.m_vPos - vLocalPos, {}, { 0, -flYaw, 0 }); vShootPos.y = 0;
Vec3 vTarget = Math::RotatePoint(vTargetPos - vLocalPos, {}, { 0, -flYaw, 0 });
Vec3 vForward; Math::AngleVectors(m_tProjInfo.m_vAng - Vec3(0, flYaw, 0), &vForward); vForward.y = 0; vForward.Normalize();
float flB = 2 * (vShootPos.x * vForward.x + vShootPos.z * vForward.z);
float flC = (powf(vShootPos.x, 2) + powf(vShootPos.z, 2)) - (powf(vTarget.x, 2) + powf(vTarget.z, 2));
auto vSolutions = Math::SolveQuadratic(1.f, flB, flC); auto vSolutions = Math::SolveQuadratic(1.f, flB, flC);
if (!vSolutions.empty()) if (!vSolutions.empty())
{ {
vShootPos += vForward * vSolutions.front(); vShootPos += vForward * vSolutions.front();
tOut.m_flPitch = flPitch - (RAD2DEG(atan2(-vShootPos.z, vShootPos.x)) - flPitch); tOut.m_flYaw = flYaw - (Math::Rad2Deg(atan2(vShootPos.y, vShootPos.x)) - flYaw);
flYaw = Math::Rad2Deg(atan2(vShootPos.y, vShootPos.x));
}
}
{ // correct pitch
if (m_tInfo.m_flGravity)
{
flPitch -= m_tProjInfo.m_vAng.x;
tOut.m_flPitch = -Math::Rad2Deg(tOut.m_flPitch) + flPitch - m_tInfo.m_vAngFix.x;
}
else
{
Vec3 vShootPos = Math::RotatePoint(m_tProjInfo.m_vPos - vLocalPos, {}, { 0, -flYaw, 0 }); vShootPos.y = 0;
Vec3 vTarget = Math::RotatePoint(vTargetPos - vLocalPos, {}, { 0, -flYaw, 0 });
Vec3 vForward; Math::AngleVectors(m_tProjInfo.m_vAng - Vec3(0, flYaw, 0), &vForward); vForward.y = 0; vForward.Normalize();
float flB = 2 * (vShootPos.x * vForward.x + vShootPos.z * vForward.z);
float flC = (powf(vShootPos.x, 2) + powf(vShootPos.z, 2)) - (powf(vTarget.x, 2) + powf(vTarget.z, 2));
auto vSolutions = Math::SolveQuadratic(1.f, flB, flC);
if (!vSolutions.empty())
{
vShootPos += vForward * vSolutions.front();
tOut.m_flPitch = flPitch - (Math::Rad2Deg(atan2(-vShootPos.z, vShootPos.x)) - flPitch);
}
} }
} }
} }
@@ -934,12 +1009,13 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
auto pLocal = m_tInfo.m_pLocal; auto pLocal = m_tInfo.m_pLocal;
auto pWeapon = m_tInfo.m_pWeapon; auto pWeapon = m_tInfo.m_pWeapon;
auto& tTarget = *m_tInfo.m_pTarget; auto& tTarget = *m_tInfo.m_pTarget;
int iTimingTolerance = TIME_TO_TICKS(m_tInfo.m_flBoundingTime);
int iSimFlags = ProjSimEnum::Redirect | ProjSimEnum::InitCheck | ProjSimEnum::NoRandomAngles | ProjSimEnum::PredictCmdNum; int iSimFlags = ProjSimEnum::Redirect | ProjSimEnum::InitCheck | ProjSimEnum::NoRandomAngles | ProjSimEnum::PredictCmdNum;
#ifdef SPLASH_DEBUG5 #ifdef SPLASH_DEBUG5
if (Vars::Visuals::Trajectory::Override.Value) if (Vars::Visuals::Trajectory::Override.Value)
{ {
if (!Vars::Visuals::Trajectory::Pipes.Value) if (!Vars::Visuals::Trajectory::ForwardRedirect.Value)
s_mTraceCount[__FUNCTION__": setup trace"]++; s_mTraceCount[__FUNCTION__": setup trace"]++;
} }
else else
@@ -1059,7 +1135,7 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
{ {
bool bTime = bSplash bool bTime = bSplash
? trace.endpos.DistTo(vPoint) < m_tProjInfo.m_flVelocity * TICK_INTERVAL + m_tProjInfo.m_vHull.z ? trace.endpos.DistTo(vPoint) < m_tProjInfo.m_flVelocity * TICK_INTERVAL + m_tProjInfo.m_vHull.z
: iSimTime - n < 5 || pWeapon->GetWeaponID() == TF_WEAPON_LUNCHBOX; // projectile so slow it causes problems if we don't waive this check : iSimTime - n < iTimingTolerance;
bool bTarget = trace.m_pEnt == tTarget.m_pEntity || bSplash; bool bTarget = trace.m_pEnt == tTarget.m_pEntity || bSplash;
bool bValid = bTarget && bTime; bool bValid = bTarget && bTime;
if (bValid && bSplash) if (bValid && bSplash)
@@ -1143,8 +1219,9 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
} }
else if (!bSplash && bTarget && pWeapon->GetWeaponID() == TF_WEAPON_PIPEBOMBLAUNCHER) else if (!bSplash && bTarget && pWeapon->GetWeaponID() == TF_WEAPON_PIPEBOMBLAUNCHER)
{ // run for more ticks to check for splash { // run for more ticks to check for splash
iSimTime = n + 5; iSimTime = n + iTimingTolerance;
bSplash = bArmTime = true; bSplash = bArmTime = true;
filter.pSkip = tTarget.m_pEntity;
} }
else else
break; break;
@@ -1211,60 +1288,73 @@ bool CAimbotProjectile::HandlePoint(const Vec3& vOrigin, int iSimTime, float flP
return bReturn; return bReturn;
} }
bool CAimbotProjectile::HandleDirect(std::vector<Direct_t>& vDirectHistory) bool CAimbotProjectile::HandleDirect(DirectHistory_t& mDirectHistory)
{ {
if (vDirectHistory.empty()) if (mDirectHistory.empty())
return false; return false;
std::sort(vDirectHistory.begin(), vDirectHistory.end(), [&](const Direct_t& a, const Direct_t& b) -> bool for (auto& vDirectHistory : mDirectHistory | std::views::values)
{
return a.m_iPriority < b.m_iPriority;
});
m_flTimeTo = vDirectHistory.front().m_flTime + m_tInfo.m_flLatency;
for (auto& tHistory : vDirectHistory)
{ {
if (HandlePoint(tHistory.m_vOrigin, tHistory.m_iSimtime, tHistory.m_flPitch, tHistory.m_flYaw, tHistory.m_flTime, tHistory.m_vPoint)) std::sort(vDirectHistory.begin(), vDirectHistory.end(), [&](const Direct_t& a, const Direct_t& b) -> bool
return true; {
return a.m_iPriority < b.m_iPriority;
});
m_flTimeTo = vDirectHistory.front().m_flTime + m_tInfo.m_flLatency;
for (auto& tHistory : vDirectHistory)
{
if (HandlePoint(tHistory.m_vOrigin, tHistory.m_iSimtime, tHistory.m_flPitch, tHistory.m_flYaw, tHistory.m_flTime, tHistory.m_vPoint))
return true;
}
} }
return false; return false;
} }
bool CAimbotProjectile::HandleSplash(std::vector<Splash_t>& vSplashHistory) bool CAimbotProjectile::HandleSplash(SplashHistory_t& mSplashHistory)
{ {
if (vSplashHistory.empty()) if (mSplashHistory.empty())
return false; return false;
std::sort(vSplashHistory.begin(), vSplashHistory.end(), [&](const Splash_t& a, const Splash_t& b) -> bool for (auto& [iType, vSplashHistory] : mSplashHistory)
{
return a.m_flTimeTo < b.m_flTimeTo;
});
SetupSplashPoints(vSplashHistory.front().m_vOrigin, m_vSplashPoints);
if (m_vSplashPoints.empty())
return false;
float flLowestDistance = std::numeric_limits<float>::max();
for (auto& tHistory : vSplashHistory)
{ {
if (m_tInfo.m_iArmTime && tHistory.m_iSimtime < m_tInfo.m_iArmTime) std::sort(vSplashHistory.begin(), vSplashHistory.end(), [&](const Splash_t& a, const Splash_t& b) -> bool
continue; {
return a.m_flTimeTo < b.m_flTimeTo;
});
byte iFlags = CalculateFlagsEnum::None;
if (iType == PointFlagsEnum::Alternate)
iFlags |= CalculateFlagsEnum::AlternateAngle;
SetupSplashPoints(vSplashHistory.front().m_vOrigin, m_vSplashPoints, iFlags);
if (m_vSplashPoints.empty())
return false;
std::vector<Point_t> vSplashPoints = {}; iFlags |= CalculateFlagsEnum::Accuracy;
vSplashPoints = GetSplashPoints(tHistory.m_vOrigin, m_vSplashPoints, tHistory.m_iSimtime); float flLowestDistance = std::numeric_limits<float>::max();
for (auto& tHistory : vSplashHistory)
for (auto& tPoint : vSplashPoints)
{ {
float flDistance = tHistory.m_vOrigin.DistTo(tPoint.m_vPoint); if (m_tInfo.m_iArmTime && tHistory.m_iSimtime < m_tInfo.m_iArmTime)
if (flDistance > flLowestDistance)
continue; continue;
if (HandlePoint(tHistory.m_vOrigin, tHistory.m_iSimtime, tPoint.m_tSolution.m_flPitch, tPoint.m_tSolution.m_flYaw, tPoint.m_tSolution.m_flTime, tPoint.m_vPoint, true)) std::vector<Point_t> vSplashPoints = {};
flLowestDistance = flDistance; vSplashPoints = GetSplashPoints(tHistory.m_vOrigin, m_vSplashPoints, tHistory.m_iSimtime, iFlags);
for (auto& tPoint : vSplashPoints)
{
float flDistance = tHistory.m_vOrigin.DistTo(tPoint.m_vPoint);
if (flDistance > flLowestDistance)
continue;
if (HandlePoint(tHistory.m_vOrigin, tHistory.m_iSimtime, tPoint.m_tSolution.m_flPitch, tPoint.m_tSolution.m_flYaw, tPoint.m_tSolution.m_flTime, tPoint.m_vPoint, true))
flLowestDistance = flDistance;
}
} }
if (flLowestDistance != std::numeric_limits<float>::max())
return true;
} }
return flLowestDistance != std::numeric_limits<float>::max(); return false;
} }
int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bVisuals) int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bVisuals)
@@ -1296,7 +1386,7 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas
m_tInfo.m_flGravity = m_tProjInfo.m_flGravity; m_tInfo.m_flGravity = m_tProjInfo.m_flGravity;
m_tInfo.m_iSplashCount = !m_tInfo.m_flGravity ? Vars::Aimbot::Projectile::SplashCountDirect.Value : Vars::Aimbot::Projectile::SplashCountArc.Value; m_tInfo.m_iSplashCount = !m_tInfo.m_flGravity ? Vars::Aimbot::Projectile::SplashCountDirect.Value : Vars::Aimbot::Projectile::SplashCountArc.Value;
m_tInfo.m_flRadius = GetSplashRadius(pWeapon, pLocal); m_tInfo.m_flRadius = GetSplashRadius(pWeapon, pLocal, Vars::Aimbot::Projectile::SplashRadius.Value / 100);
m_tInfo.m_flRadiusTime = m_tInfo.m_flRadius / m_tInfo.m_flVelocity; m_tInfo.m_flRadiusTime = m_tInfo.m_flRadius / m_tInfo.m_flVelocity;
m_tInfo.m_flBoundingTime = m_tInfo.m_flRadiusTime + tTarget.m_pEntity->GetSize().Length() / m_tInfo.m_flVelocity; m_tInfo.m_flBoundingTime = m_tInfo.m_flRadiusTime + tTarget.m_pEntity->GetSize().Length() / m_tInfo.m_flVelocity;
m_tInfo.m_iArmTime = TIME_TO_TICKS(ArmTime(pWeapon)); m_tInfo.m_iArmTime = TIME_TO_TICKS(ArmTime(pWeapon));
@@ -1310,14 +1400,13 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas
Directs_t mDirects = GetDirects();
Splashes_t vSplashes = GetSplashes();
DirectHistory_t mDirectHistory = {};
SplashHistory_t mSplashHistory = {};
int iMaxTime = TIME_TO_TICKS(std::min(m_tProjInfo.m_flLifetime, Vars::Aimbot::Projectile::MaxSimulationTime.Value)); int iMaxTime = TIME_TO_TICKS(std::min(m_tProjInfo.m_flLifetime, Vars::Aimbot::Projectile::MaxSimulationTime.Value));
int iSplash = Vars::Aimbot::Projectile::SplashPrediction.Value && m_tInfo.m_flRadius ? Vars::Aimbot::Projectile::SplashPrediction.Value : Vars::Aimbot::Projectile::SplashPredictionEnum::Off;
auto mDirectPoints = iSplash == Vars::Aimbot::Projectile::SplashPredictionEnum::Only ? std::unordered_map<int, Vec3>() : GetDirectPoints();
std::vector<Direct_t> vDirectHistory = {};
std::vector<Splash_t> vSplashHistory = {};
for (int i = 1 - TIME_TO_TICKS(m_tInfo.m_flLatency); i <= iMaxTime; i++) for (int i = 1 - TIME_TO_TICKS(m_tInfo.m_flLatency); i <= iMaxTime; i++)
{ {
if (!m_tMoveStorage.m_bFailed) if (!m_tMoveStorage.m_bFailed)
@@ -1328,26 +1417,11 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas
if (i < 0) if (i < 0)
continue; continue;
bool bDirectBreaks = true; for (auto& [iIndex, tOffset] : mDirects)
if (iSplash)
{ {
Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, tTarget.m_vPos, i, tSolution, CalculateFlagsEnum::None); Vec3& vOffset = tOffset.m_vOffset;
if (tSolution.m_iCalculated != CalculateResultEnum::Bad) byte iType = tOffset.m_iFlags & -tOffset.m_iFlags;
{
const float flTimeTo = tSolution.m_flTime - TICKS_TO_TIME(i);
bDirectBreaks = false;
if (flTimeTo < m_tInfo.m_flBoundingTime)
{
bDirectBreaks = flTimeTo < -m_tInfo.m_flBoundingTime && (!m_tInfo.m_iArmTime || m_tInfo.m_iArmTime < i);
if (!bDirectBreaks)
vSplashHistory.emplace_back(History_t(tTarget.m_vPos, i), fabsf(flTimeTo));
}
}
}
for (auto& [iIndex, vOffset] : mDirectPoints)
{
Vec3 vPoint = tTarget.m_vPos + vOffset; Vec3 vPoint = tTarget.m_vPos + vOffset;
if (Vars::Aimbot::Projectile::HuntsmanPullPoint.Value && tTarget.m_nAimedHitbox == HITBOX_HEAD) if (Vars::Aimbot::Projectile::HuntsmanPullPoint.Value && tTarget.m_nAimedHitbox == HITBOX_HEAD)
{ {
@@ -1362,32 +1436,64 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas
case CalculateResultEnum::Good: case CalculateResultEnum::Good:
if (m_tInfo.m_iArmTime && m_tInfo.m_iArmTime > i && !m_tMoveStorage.m_MoveData.m_vecVelocity.IsZero()) if (m_tInfo.m_iArmTime && m_tInfo.m_iArmTime > i && !m_tMoveStorage.m_MoveData.m_vecVelocity.IsZero())
break; break;
vDirectHistory.emplace_back(History_t(tTarget.m_vPos, i), tSolution.m_flPitch, tSolution.m_flYaw, tSolution.m_flTime, vPoint, iIndex); mDirectHistory[iType].emplace_back(History_t(tTarget.m_vPos, i), tSolution.m_flPitch, tSolution.m_flYaw, tSolution.m_flTime, vPoint, iIndex);
[[fallthrough]]; [[fallthrough]];
case CalculateResultEnum::Bad: case CalculateResultEnum::Bad:
mDirectPoints.erase(iIndex); tOffset.m_iFlags &= ~iType;
if (!(tOffset.m_iFlags /*& (PointFlagsEnum::Regular | PointFlagsEnum::Alternate)*/))
mDirects.erase(iIndex);
} }
} }
if (bDirectBreaks && mDirectPoints.empty())
for (auto it = vSplashes.begin(); it != vSplashes.end();)
{
byte iFlags = CalculateFlagsEnum::AccountDrag;
if (*it == PointFlagsEnum::Alternate)
iFlags |= CalculateFlagsEnum::AlternateAngle;
Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, tTarget.m_vPos, i, tSolution, iFlags);
if (tSolution.m_iCalculated == CalculateResultEnum::Bad && mDirects.empty())
{
it = vSplashes.erase(it);
continue;
}
const float flTimeTo = tSolution.m_flTime - TICKS_TO_TIME(i);
if (flTimeTo > m_tInfo.m_flBoundingTime)
{
++it;
continue;
}
if (flTimeTo < -m_tInfo.m_flBoundingTime && (!m_tInfo.m_iArmTime || m_tInfo.m_iArmTime < i))
{
it = vSplashes.erase(it);
continue;
}
mSplashHistory[*it].emplace_back(History_t(tTarget.m_vPos, i), fabsf(flTimeTo));
++it;
}
if (mDirects.empty() && vSplashes.empty())
break; break;
} }
m_iResult = false; m_iResult = false;
switch (iSplash) switch (m_tInfo.m_flRadius ? Vars::Aimbot::Projectile::SplashPrediction.Value : Vars::Aimbot::Projectile::SplashPredictionEnum::Off)
{ {
case Vars::Aimbot::Projectile::SplashPredictionEnum::Off: case Vars::Aimbot::Projectile::SplashPredictionEnum::Off:
HandleDirect(vDirectHistory); HandleDirect(mDirectHistory);
break; break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Include: case Vars::Aimbot::Projectile::SplashPredictionEnum::Include:
if (!HandleDirect(vDirectHistory)) if (!HandleDirect(mDirectHistory))
HandleSplash(vSplashHistory); HandleSplash(mSplashHistory);
break; break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Prefer: case Vars::Aimbot::Projectile::SplashPredictionEnum::Prefer:
if (!HandleSplash(vSplashHistory)) if (!HandleSplash(mSplashHistory))
HandleDirect(vDirectHistory); HandleDirect(mDirectHistory);
break; break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Only: case Vars::Aimbot::Projectile::SplashPredictionEnum::Only:
HandleSplash(vSplashHistory); HandleSplash(mSplashHistory);
} }
F::MoveSim.Restore(m_tMoveStorage); F::MoveSim.Restore(m_tMoveStorage);
@@ -1459,7 +1565,8 @@ bool CAimbotProjectile::Aim(const Vec3& vCurAngle, const Vec3& vToAngle, Vec3& v
break; break;
} }
Math::ClampAngles(vOut); if (iMethod != Vars::Aimbot::General::AimTypeEnum::Silent || Vars::Misc::Game::AntiCheatCompatibility.Value)
Math::ClampAngles(vOut);
return bReturn; return bReturn;
} }
@@ -1960,14 +2067,13 @@ bool CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBa
Directs_t mDirects = GetDirects();
Splashes_t vSplashes = GetSplashes();
DirectHistory_t mDirectHistory = {};
SplashHistory_t mSplashHistory = {};
int iMaxTime = TIME_TO_TICKS(Vars::Aimbot::Projectile::MaxSimulationTime.Value); int iMaxTime = TIME_TO_TICKS(Vars::Aimbot::Projectile::MaxSimulationTime.Value);
int iSplash = Vars::Aimbot::Projectile::SplashPrediction.Value && m_tInfo.m_flRadius ? Vars::Aimbot::Projectile::SplashPrediction.Value : Vars::Aimbot::Projectile::SplashPredictionEnum::Off;
auto mDirectPoints = iSplash == Vars::Aimbot::Projectile::SplashPredictionEnum::Only ? std::unordered_map<int, Vec3>() : GetDirectPoints();
std::vector<Direct_t> vDirectHistory = {};
std::vector<Splash_t> vSplashHistory = {};
for (int i = 1 - TIME_TO_TICKS(m_tInfo.m_flLatency); i <= iMaxTime; i++) for (int i = 1 - TIME_TO_TICKS(m_tInfo.m_flLatency); i <= iMaxTime; i++)
{ {
if (!m_tMoveStorage.m_bFailed) if (!m_tMoveStorage.m_bFailed)
@@ -1978,26 +2084,11 @@ bool CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBa
if (i < 0) if (i < 0)
continue; continue;
bool bDirectBreaks = true; for (auto& [iIndex, tOffset] : mDirects)
if (iSplash)
{ {
Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, tTarget.m_vPos, i, tSolution, CalculateFlagsEnum::None); Vec3& vOffset = tOffset.m_vOffset;
if (tSolution.m_iCalculated != CalculateResultEnum::Bad) byte iType = tOffset.m_iFlags & -tOffset.m_iFlags;
{
const float flTimeTo = tSolution.m_flTime - TICKS_TO_TIME(i);
bDirectBreaks = false;
if (flTimeTo < m_tInfo.m_flBoundingTime)
{
bDirectBreaks = flTimeTo < -m_tInfo.m_flBoundingTime;
if (!bDirectBreaks)
vSplashHistory.emplace_back(History_t(tTarget.m_vPos, i), fabsf(flTimeTo));
}
}
}
for (auto& [iIndex, vOffset] : mDirectPoints)
{
Vec3 vPoint = tTarget.m_vPos + vOffset; Vec3 vPoint = tTarget.m_vPos + vOffset;
if (Vars::Aimbot::Projectile::HuntsmanPullPoint.Value && tTarget.m_nAimedHitbox == HITBOX_HEAD) if (Vars::Aimbot::Projectile::HuntsmanPullPoint.Value && tTarget.m_nAimedHitbox == HITBOX_HEAD)
{ {
@@ -2010,32 +2101,64 @@ bool CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBa
switch (tSolution.m_iCalculated) switch (tSolution.m_iCalculated)
{ {
case CalculateResultEnum::Good: case CalculateResultEnum::Good:
vDirectHistory.emplace_back(History_t(tTarget.m_vPos, i), tSolution.m_flPitch, tSolution.m_flYaw, tSolution.m_flTime, vPoint, iIndex); mDirectHistory[iType].emplace_back(History_t(tTarget.m_vPos, i), tSolution.m_flPitch, tSolution.m_flYaw, tSolution.m_flTime, vPoint, iIndex);
[[fallthrough]]; [[fallthrough]];
case CalculateResultEnum::Bad: case CalculateResultEnum::Bad:
mDirectPoints.erase(iIndex); tOffset.m_iFlags &= ~iType;
if (!(tOffset.m_iFlags /*& (PointFlagsEnum::Regular | PointFlagsEnum::Alternate)*/))
mDirects.erase(iIndex);
} }
} }
if (bDirectBreaks && mDirectPoints.empty())
for (auto it = vSplashes.begin(); it != vSplashes.end();)
{
byte iFlags = CalculateFlagsEnum::AccountDrag;
if (*it == PointFlagsEnum::Alternate)
iFlags |= CalculateFlagsEnum::AlternateAngle;
Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, tTarget.m_vPos, i, tSolution, CalculateFlagsEnum::None);
if (tSolution.m_iCalculated == CalculateResultEnum::Bad && mDirects.empty())
{
it = vSplashes.erase(it);
continue;
}
const float flTimeTo = tSolution.m_flTime - TICKS_TO_TIME(i);
if (flTimeTo > m_tInfo.m_flBoundingTime)
{
++it;
continue;
}
if (flTimeTo < -m_tInfo.m_flBoundingTime)
{
it = vSplashes.erase(it);
continue;
}
mSplashHistory[*it].emplace_back(History_t(tTarget.m_vPos, i), fabsf(flTimeTo));
++it;
}
if (mDirects.empty() && vSplashes.empty())
break; break;
} }
m_iResult = false; m_iResult = false;
switch (iSplash) switch (m_tInfo.m_flRadius ? Vars::Aimbot::Projectile::SplashPrediction.Value : Vars::Aimbot::Projectile::SplashPredictionEnum::Off)
{ {
case Vars::Aimbot::Projectile::SplashPredictionEnum::Off: case Vars::Aimbot::Projectile::SplashPredictionEnum::Off:
HandleDirect(vDirectHistory); HandleDirect(mDirectHistory);
break; break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Include: case Vars::Aimbot::Projectile::SplashPredictionEnum::Include:
if (!HandleDirect(vDirectHistory)) if (!HandleDirect(mDirectHistory))
HandleSplash(vSplashHistory); HandleSplash(mSplashHistory);
break; break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Prefer: case Vars::Aimbot::Projectile::SplashPredictionEnum::Prefer:
if (!HandleSplash(vSplashHistory)) if (!HandleSplash(mSplashHistory))
HandleDirect(vDirectHistory); HandleDirect(mDirectHistory);
break; break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Only: case Vars::Aimbot::Projectile::SplashPredictionEnum::Only:
HandleSplash(vSplashHistory); HandleSplash(mSplashHistory);
} }
F::MoveSim.Restore(m_tMoveStorage); F::MoveSim.Restore(m_tMoveStorage);
@@ -5,7 +5,8 @@
#include "../../Simulation/MovementSimulation/MovementSimulation.h" #include "../../Simulation/MovementSimulation/MovementSimulation.h"
#include "../../Simulation/ProjectileSimulation/ProjectileSimulation.h" #include "../../Simulation/ProjectileSimulation/ProjectileSimulation.h"
Enum(CalculateFlags, None = 0, TwoPass = 1 << 0, SetupClip = 1 << 1, AccountDrag = 1 << 2, Accuracy = TwoPass | SetupClip | AccountDrag) Enum(PointFlags, None = 0, Regular = 1 << 0, Alternate = 1 << 1)
Enum(CalculateFlags, None = 0, TwoPass = 1 << 0, SetupClip = 1 << 1, AccountDrag = 1 << 2, AlternateAngle = 1 << 3, Accuracy = TwoPass | SetupClip | AccountDrag)
Enum(CalculateResult, Pending, Good, Time, Bad) Enum(CalculateResult, Pending, Good, Time, Bad)
struct Info_t struct Info_t
@@ -46,6 +47,14 @@ struct Point_t
Solution_t m_tSolution = {}; Solution_t m_tSolution = {};
}; };
struct Offset_t
{
Vec3 m_vOffset;
byte m_iFlags;
};
using Directs_t = std::unordered_map<byte, Offset_t>;
using Splashes_t = std::vector<byte>;
struct History_t struct History_t
{ {
Vec3 m_vOrigin; Vec3 m_vOrigin;
@@ -63,20 +72,23 @@ struct Splash_t : History_t
{ {
float m_flTimeTo; float m_flTimeTo;
}; };
using DirectHistory_t = std::unordered_map<byte, std::vector<Direct_t>>;
using SplashHistory_t = std::unordered_map<byte, std::vector<Splash_t>>;
class CAimbotProjectile class CAimbotProjectile
{ {
private: private:
std::unordered_map<int, Vec3> GetDirectPoints(); Directs_t GetDirects();
void SetupSplashPoints(Vec3& vOrigin, std::vector<Vec3>& vSplashPoints); Splashes_t GetSplashes();
std::vector<Point_t> GetSplashPoints(Vec3 vOrigin, std::vector<Vec3>& vSplashPoints, int iSimTime); void SetupSplashPoints(Vec3& vOrigin, std::vector<Vec3>& vSplashPoints, byte iFlags = CalculateFlagsEnum::None);
std::vector<Point_t> GetSplashPoints(Vec3 vOrigin, std::vector<Vec3>& vSplashPoints, int iSimTime, byte iFlags = CalculateFlagsEnum::Accuracy);
void CalculateAngle(const Vec3& vLocalPos, const Vec3& vTargetPos, int iSimTime, Solution_t& tOut, int iFlags = CalculateFlagsEnum::Accuracy, int iTolerance = -1); void CalculateAngle(const Vec3& vLocalPos, const Vec3& vTargetPos, int iSimTime, Solution_t& tOut, byte iFlags = CalculateFlagsEnum::Accuracy, int iTolerance = -1);
bool TestAngle(const Vec3& vPoint, const Vec3& vAngles, int iSimTime, bool bSplash, bool bSecondTest = false); bool TestAngle(const Vec3& vPoint, const Vec3& vAngles, int iSimTime, bool bSplash, bool bSecondTest = false);
bool HandlePoint(const Vec3& vOrigin, int iSimTime, float flPitch, float flYaw, float flTime, const Vec3& vPoint, bool bSplash = false); bool HandlePoint(const Vec3& vOrigin, int iSimTime, float flPitch, float flYaw, float flTime, const Vec3& vPoint, bool bSplash = false);
bool HandleDirect(std::vector<Direct_t>& vDirectHistory); bool HandleDirect(DirectHistory_t& vDirectHistory);
bool HandleSplash(std::vector<Splash_t>& vSplashHistory); bool HandleSplash(SplashHistory_t& vSplashHistory);
int CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bVisuals = true); int CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bVisuals = true);
bool RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd); bool RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
@@ -108,7 +120,7 @@ private:
public: public:
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd); void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
float GetSplashRadius(CTFWeaponBase* pWeapon, CTFPlayer* pPlayer); float GetSplashRadius(CTFWeaponBase* pWeapon, CTFPlayer* pPlayer, float flScale = 1.f);
bool AutoAirblast(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd, CBaseEntity* pProjectile); bool AutoAirblast(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd, CBaseEntity* pProjectile);
float GetSplashRadius(CBaseEntity* pProjectile, CTFWeaponBase* pWeapon = nullptr, CTFPlayer* pPlayer = nullptr, float flScale = 1.f, CTFWeaponBase* pAirblast = nullptr); float GetSplashRadius(CBaseEntity* pProjectile, CTFWeaponBase* pWeapon = nullptr, CTFPlayer* pPlayer = nullptr, float flScale = 1.f, CTFWeaponBase* pAirblast = nullptr);
@@ -154,7 +154,7 @@ bool CAutoDetonate::CheckTargets(CTFPlayer* pLocal, EntityEnum::EntityEnum iGrou
bool CAutoDetonate::CheckSelf(CTFPlayer* pLocal, EntityEnum::EntityEnum iGroup) bool CAutoDetonate::CheckSelf(CTFPlayer* pLocal, EntityEnum::EntityEnum iGroup)
{ {
if (!(Vars::Aimbot::Projectile::AutoDetonate.Value & Vars::Aimbot::Projectile::AutoDetonateEnum::PreventSelfDamage) || !pLocal->IsAlive() || pLocal->IsAGhost()) if (!(Vars::Aimbot::Projectile::AutoDetonate.Value & Vars::Aimbot::Projectile::AutoDetonateEnum::PreventSelfDamage) || !pLocal->IsAlive() || pLocal->IsAGhost() || pLocal->IsInvulnerable())
return false; return false;
auto& vProjectiles = H::Entities.GetGroup(iGroup); auto& vProjectiles = H::Entities.GetGroup(iGroup);
@@ -78,8 +78,8 @@ bool CAutoRocketJump::SetAngles(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser
if (!vSolutions.empty()) if (!vSolutions.empty())
{ {
vShootPos += vForward * vSolutions.front(); vShootPos += vForward * vSolutions.front();
m_vAngles.y = flYaw - (RAD2DEG(atan2(vShootPos.y, vShootPos.x)) - flYaw); m_vAngles.y = flYaw - (Math::Rad2Deg(atan2(vShootPos.y, vShootPos.x)) - flYaw);
flYaw = RAD2DEG(atan2(vShootPos.y, vShootPos.x)); flYaw = Math::Rad2Deg(atan2(vShootPos.y, vShootPos.x));
} }
} }
@@ -93,7 +93,7 @@ bool CAutoRocketJump::SetAngles(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser
if (!vSolutions.empty()) if (!vSolutions.empty())
{ {
vShootPos += vForward * vSolutions.front(); vShootPos += vForward * vSolutions.front();
m_vAngles.x = flPitch - (RAD2DEG(atan2(-vShootPos.z, vShootPos.x)) - flPitch); m_vAngles.x = flPitch - (Math::Rad2Deg(atan2(-vShootPos.z, vShootPos.x)) - flPitch);
} }
} }
+17 -9
View File
@@ -254,21 +254,29 @@ namespace ImGui
if (bVertical) if (bVertical)
{ {
pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x - flInset + vSize.x, vDrawPos.y + flSize }, uTitle, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight); if (!bTwoToneBorder)
pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flSize }, { vDrawPos.x - flInset + vSize.x, vDrawPos.y - flInset + vSize.y }, uBackground, H::Draw.Scale(3), ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight); pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x + vSize.x - flInset, vDrawPos.y + flSize }, uTitle, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight);
if (bTwoToneBorder) else
pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flSize - H::Draw.Scale() }, {vDrawPos.x - flInset + vSize.x, vDrawPos.y + flSize }, uBorder); {
pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x + vSize.x - flInset, vDrawPos.y + flSize - H::Draw.Scale() }, uTitle, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight);
pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flSize - H::Draw.Scale() }, { vDrawPos.x + vSize.x - flInset, vDrawPos.y + flSize }, uBorder);
}
pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flSize }, { vDrawPos.x + vSize.x - flInset, vDrawPos.y + vSize.y - flInset }, uBackground, H::Draw.Scale(3), ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight);
} }
else else
{ {
pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x + flSize, vDrawPos.y - flInset + vSize.y }, uTitle, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomLeft); if (!bTwoToneBorder)
pDrawList->AddRectFilled({ vDrawPos.x + flSize, vDrawPos.y + flInset }, { vDrawPos.x - flInset + vSize.x, vDrawPos.y - flInset + vSize.y }, uBackground, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomRight); pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x + flSize, vDrawPos.y + vSize.y - flInset }, uTitle, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomLeft);
if (bTwoToneBorder) else
pDrawList->AddRectFilled({ vDrawPos.x + flSize - H::Draw.Scale(), vDrawPos.y + flInset }, { vDrawPos.x + flSize, vDrawPos.y - flInset + vSize.y }, uBorder); {
pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x + flSize - H::Draw.Scale(), vDrawPos.y + vSize.y - flInset }, uTitle, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomLeft);
pDrawList->AddRectFilled({ vDrawPos.x + flSize - H::Draw.Scale(), vDrawPos.y + flInset }, { vDrawPos.x + flSize, vDrawPos.y + vSize.y - flInset }, uBorder);
}
pDrawList->AddRectFilled({ vDrawPos.x + flSize, vDrawPos.y + flInset }, { vDrawPos.x + vSize.x - flInset, vDrawPos.y + vSize.y - flInset }, uBackground, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomRight);
} }
flInset += H::Draw.Scale(0.5f) - 0.5f - H::Draw.Scale(); flInset += H::Draw.Scale(0.5f) - 0.5f - H::Draw.Scale();
pDrawList->AddRect({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x - flInset + vSize.x, vDrawPos.y - flInset + vSize.y }, uBorder, H::Draw.Scale(4), ImDrawFlags_None, H::Draw.Scale()); pDrawList->AddRect({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x + vSize.x - flInset, vDrawPos.y + vSize.y - flInset }, uBorder, H::Draw.Scale(4), ImDrawFlags_None, H::Draw.Scale());
} }
inline void Divider(float flPrePadding = H::Draw.Scale(8), float flPostPadding = H::Draw.Scale(7), float flInset = H::Draw.Scale(), ImU32 uBorder = F::Render.Background2) inline void Divider(float flPrePadding = H::Draw.Scale(8), float flPostPadding = H::Draw.Scale(7), float flInset = H::Draw.Scale(), ImU32 uBorder = F::Render.Background2)
{ {
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -140,7 +140,7 @@ void CMisc::AutoStrafe(CTFPlayer* pLocal, CUserCmd* pCmd)
break; break;
float flTurnScale = Math::RemapVal(Vars::Misc::Movement::AutoStrafeTurnScale.Value, 0.f, 1.f, 0.9f, 1.f); float flTurnScale = Math::RemapVal(Vars::Misc::Movement::AutoStrafeTurnScale.Value, 0.f, 1.f, 0.9f, 1.f);
float flRotation = DEG2RAD((flDirDelta > 0.f ? -90.f : 90.f) + flDirDelta * flTurnScale); float flRotation = Math::Deg2Rad((flDirDelta > 0.f ? -90.f : 90.f) + flDirDelta * flTurnScale);
float flCosRot = cosf(flRotation), flSinRot = sinf(flRotation); float flCosRot = cosf(flRotation), flSinRot = sinf(flRotation);
pCmd->forwardmove = flCosRot * flForward - flSinRot * flSide; pCmd->forwardmove = flCosRot * flForward - flSinRot * flSide;
@@ -23,7 +23,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
if (Vars::Visuals::Trajectory::Override.Value) if (Vars::Visuals::Trajectory::Override.Value)
{ {
SDK::GetProjectileFireSetup(pPlayer, vAngles, { Vars::Visuals::Trajectory::OffsetX.Value, Vars::Visuals::Trajectory::OffsetY.Value, Vars::Visuals::Trajectory::OffsetZ.Value }, vPos, vAngle, Vars::Visuals::Trajectory::ForwardRedirect.Value, !bRedirect ? 1.f : Vars::Visuals::Trajectory::ForwardCutoff.Value, bInterp); SDK::GetProjectileFireSetup(pPlayer, vAngles, { Vars::Visuals::Trajectory::OffsetX.Value, Vars::Visuals::Trajectory::OffsetY.Value, Vars::Visuals::Trajectory::OffsetZ.Value }, vPos, vAngle, bRedirect ? Vars::Visuals::Trajectory::ForwardRedirect.Value : 0.f, Vars::Visuals::Trajectory::ForwardCutoff.Value, bInterp);
tProjInfo = { pPlayer, pWeapon, FNV1A::Hash32Const("custom"), vPos, vAngle, { Vars::Visuals::Trajectory::Hull.Value, Vars::Visuals::Trajectory::Hull.Value, Vars::Visuals::Trajectory::Hull.Value }, Vars::Visuals::Trajectory::Speed.Value, Vars::Visuals::Trajectory::Gravity.Value, Vars::Visuals::Trajectory::LifeTime.Value }; tProjInfo = { pPlayer, pWeapon, FNV1A::Hash32Const("custom"), vPos, vAngle, { Vars::Visuals::Trajectory::Hull.Value, Vars::Visuals::Trajectory::Hull.Value, Vars::Visuals::Trajectory::Hull.Value }, Vars::Visuals::Trajectory::Speed.Value, Vars::Visuals::Trajectory::Gravity.Value, Vars::Visuals::Trajectory::LifeTime.Value };
return true; return true;
@@ -360,7 +360,9 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
if (!m_pEnv || !m_pObj) if (!m_pEnv || !m_pObj)
return false; return false;
//set drag m_pCurrent = &tProjInfo;
// set drag
{ {
float flDrag = 0.f; float flDrag = 0.f;
Vec3 vDragBasis = {}; Vec3 vDragBasis = {};
@@ -403,7 +405,7 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
break; break;
case FNV1A::Hash32Const("models/weapons/w_models/w_baseball.mdl"): case FNV1A::Hash32Const("models/weapons/w_models/w_baseball.mdl"):
flDrag = 1.f; flDrag = 1.f;
vDragBasis = { 0.009000f /*0.006645f*/, 0.006581f, 0.006710f}; vDragBasis = { 0.009000f /*0.006645f*/, 0.006581f, 0.006710f };
vAngDragBasis = { 0.002233f, 0.002246f, 0.002206f }; vAngDragBasis = { 0.002233f, 0.002246f, 0.002206f };
break; break;
case FNV1A::Hash32Const("models/weapons/c_models/c_xms_festive_ornament.mdl"): case FNV1A::Hash32Const("models/weapons/c_models/c_xms_festive_ornament.mdl"):
@@ -443,7 +445,7 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
m_pObj->m_angDragBasis = vAngDragBasis; m_pObj->m_angDragBasis = vAngDragBasis;
} }
//set position and velocity // set position and velocity
{ {
Vec3 vVelocity, vAngularVelocity; Vec3 vVelocity, vAngularVelocity;
if (!bWorld) if (!bWorld)
@@ -478,7 +480,8 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
vAngularVelocity = { 600.f, float(SDK::RandomInt(-1200, 1200)), 0.f }; vAngularVelocity = { 600.f, float(SDK::RandomInt(-1200, 1200)), 0.f };
break; break;
} }
vAngularVelocity = { 600.f, -1200.f, 0.f }; if (!tProjInfo.m_pWeapon || !SDK::AttribHookValue(0, "grenade_no_spin", tProjInfo.m_pWeapon))
vAngularVelocity = { 600.f, -1200.f, 0.f };
break; break;
case FNV1A::Hash32Const("models/workshop_partner/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl"): case FNV1A::Hash32Const("models/workshop_partner/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl"):
vVelocity = vForward * 10 + vUp; vVelocity = vForward * 10 + vUp;
@@ -554,12 +557,11 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
m_pObj->SetVelocity(&vVelocity, &vAngularVelocity); m_pObj->SetVelocity(&vVelocity, &vAngularVelocity);
} }
//set m_pEnv params // set m_pEnv params
{ {
float flMaxVelocity = 1000000.f; float flMaxVelocity = 1000000.f;
float vMaxAngularVelocity = 1000000.f; float vMaxAngularVelocity = 1000000.f;
//only pipes need k_flMaxVelocity and k_flMaxAngularVelocity
switch (tProjInfo.m_uType) switch (tProjInfo.m_uType)
{ {
case FNV1A::Hash32Const("custom"): case FNV1A::Hash32Const("custom"):
@@ -585,7 +587,7 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
params.maxAngularVelocity = vMaxAngularVelocity; params.maxAngularVelocity = vMaxAngularVelocity;
m_pEnv->SetPerformanceSettings(&params); m_pEnv->SetPerformanceSettings(&params);
m_pEnv->SetAirDensity(2.f); m_pEnv->SetAirDensity(AIR_DENSITY);
m_pEnv->SetGravity({ 0.f, 0.f, -(800.f * tProjInfo.m_flGravity) }); m_pEnv->SetGravity({ 0.f, 0.f, -(800.f * tProjInfo.m_flGravity) });
m_pEnv->ResetSimulationClock(); m_pEnv->ResetSimulationClock();
@@ -678,6 +680,9 @@ void CProjectileSimulation::SetupTrace(CTraceFilterCollideable& filter, int& nMa
} }
} }
} }
if (m_pObj->m_dragCoefficient && m_pObj->m_angDragBasis)
nMask |= CONTENTS_DISPSOLID;
} }
void CProjectileSimulation::SetupTrace(CTraceFilterCollideable& filter, int& nMask, CBaseEntity* pProjectile) void CProjectileSimulation::SetupTrace(CTraceFilterCollideable& filter, int& nMask, CBaseEntity* pProjectile)
@@ -209,6 +209,7 @@ public:
IPhysicsEnvironment* m_pEnv = nullptr; IPhysicsEnvironment* m_pEnv = nullptr;
IPhysicsObject* m_pObj = nullptr; IPhysicsObject* m_pObj = nullptr;
ProjectileInfo* m_pCurrent = nullptr;
}; };
ADD_FEATURE(CProjectileSimulation, ProjSim); ADD_FEATURE(CProjectileSimulation, ProjSim);
@@ -21,7 +21,7 @@ void COffscreenArrows::DrawArrowTo(const Vec3& vFromPos, const Vec3& vToPos, Col
} }
Vec3 vAngle = Math::VectorAngles({ vCenter.x - vScreen.x, vCenter.y - vScreen.y, 0 }); Vec3 vAngle = Math::VectorAngles({ vCenter.x - vScreen.x, vCenter.y - vScreen.y, 0 });
const float flDeg = DEG2RAD(vAngle.y); const float flDeg = Math::Deg2Rad(vAngle.y);
const float flCos = cos(flDeg); const float flCos = cos(flDeg);
const float flSin = sin(flDeg); const float flSin = sin(flDeg);
+1 -1
View File
@@ -28,7 +28,7 @@ static std::vector<Vec3> SplashTrace(Vec3 vOrigin, float flRadius, Vec3 vNormal
std::vector<Vec3> vPoints = {}; std::vector<Vec3> vPoints = {};
for (float i = 0.f; i < iSegments; i++) for (float i = 0.f; i < iSegments; i++)
{ {
Vec3 vPoint = vOrigin + (vRight * cos(2 * PI * i / iSegments) + vUp * sin(2 * PI * i / iSegments)) * flRadius; Vec3 vPoint = vOrigin + (vRight * cos(2 * Math::PI * i / iSegments) + vUp * sin(2 * Math::PI * i / iSegments)) * flRadius;
if (bTrace) if (bTrace)
{ {
CGameTrace trace = {}; CGameTrace trace = {};
+73
View File
@@ -0,0 +1,73 @@
#include "../SDK/SDK.h"
#include "../SDK/Definitions/Misc/TraceInfo.h"
#include <optional>
MAKE_SIGNATURE(CM_TraceToDispTree_True, "engine.dll", "48 8B C4 48 89 58 ? 48 89 70 ? 57 48 81 EC ? ? ? ? F3 0F 10 01", 0x0);
MAKE_SIGNATURE(CM_TraceToDispTree_False, "engine.dll", "48 8B C4 48 89 58 ? 48 89 70 ? 57 48 83 EC ? F3 0F 10 01", 0x0);
MAKE_SIGNATURE(IntersectRayWithTriangle, "engine.dll", "48 8B C4 48 81 EC ? ? ? ? 80 BC 24", 0x0);
MAKE_SIGNATURE(CDispCollTree_SweepAABBTriIntersect, "engine.dll", "48 8B C4 48 89 70 ? 48 89 78 ? 55 41 56 41 57 48 8D 68", 0x0);
MAKE_SIGNATURE(CDispCollTree_EdgeCrossAxis_0, "engine.dll", "48 83 EC ? B8 ? ? ? ? 66 44 3B C0 75 ? B0 ? 48 83 C4 ? C3 48 8B 89 ? ? ? ? F3 0F 10 05 ? ? ? ? 0F 29 74 24 ? 0F 29 7C 24 ? 44 0F 29 04 24 41 0F B7 C0 66 45 85 C0 79 ? 25 ? ? ? ? 48 8D 04 40 F3 44 0F 10 04 81", 0x0);
#define DISPCOLL_DIST_EPSILON 0.03125f
static int s_iMask = 0;
static std::optional<Vec3> s_vOriginal = {};
static CDispCollTri* s_pTri = nullptr;
MAKE_HOOK(CM_TraceToDispTree_True, S::CM_TraceToDispTree_True(), float,
TraceInfo_t* pTraceInfo, CDispCollTree* pDispTree, float startFrac, float endFrac)
{
DEBUG_RETURN(CM_TraceToDispTree_True, pTraceInfo, pDispTree, startFrac, endFrac);
s_iMask = pTraceInfo->m_contents;
return CALL_ORIGINAL(pTraceInfo, pDispTree, startFrac, endFrac);
}
MAKE_HOOK(CM_TraceToDispTree_False, S::CM_TraceToDispTree_False(), float,
TraceInfo_t* pTraceInfo, CDispCollTree* pDispTree, float startFrac, float endFrac)
{
DEBUG_RETURN(CM_TraceToDispTree_False, pTraceInfo, pDispTree, startFrac, endFrac);
s_iMask = pTraceInfo->m_contents;
return CALL_ORIGINAL(pTraceInfo, pDispTree, startFrac, endFrac);
}
MAKE_HOOK(IntersectRayWithTriangle, S::IntersectRayWithTriangle(), float,
const Ray_t& ray, const Vector& v1, const Vector& v2, const Vector& v3, bool oneSided)
{
if (s_iMask & CONTENTS_DISPSOLID)
oneSided = false;
return CALL_ORIGINAL(ray, v1, v2, v3, oneSided);
}
MAKE_HOOK(CDispCollTree_SweepAABBTriIntersect, S::CDispCollTree_SweepAABBTriIntersect(), void,
void* rcx, const Ray_t& ray, const Vector& rayDir, int iTri, CDispCollTri* pTri, CBaseTrace* pTrace)
{
DEBUG_RETURN(CDispCollTree_SweepAABBTriIntersect, rcx, ray, rayDir, iTri, pTri, pTrace);
if (s_iMask & CONTENTS_DISPSOLID && pTri->m_vecNormal.Dot(ray.m_Delta) > DISPCOLL_DIST_EPSILON)
{
s_vOriginal = pTri->m_vecNormal, s_pTri = pTri;
pTri->m_vecNormal = -pTri->m_vecNormal;
}
CALL_ORIGINAL(rcx, ray, rayDir, iTri, pTri, pTrace);
if (s_vOriginal)
pTri->m_vecNormal = s_vOriginal.value(), s_vOriginal = std::nullopt;
}
MAKE_HOOK(CDispCollTree_EdgeCrossAxis_0, S::CDispCollTree_EdgeCrossAxis_0(), void,
void* rcx, const Ray_t& ray, unsigned short iPlane, CDispCollHelper* pHelper)
{
DEBUG_RETURN(CDispCollTree_EdgeCrossAxis_0, rcx, ray, iPlane, pHelper);
if (s_vOriginal)
s_pTri->m_vecNormal = s_vOriginal.value(), s_vOriginal = std::nullopt;
CALL_ORIGINAL(rcx, ray, iPlane, pHelper);
}
@@ -198,6 +198,7 @@
#define TF_ROCKET_RADIUS (146.f) #define TF_ROCKET_RADIUS (146.f)
#define TF_FLARE_DET_RADIUS (110.f) #define TF_FLARE_DET_RADIUS (110.f)
#define TF_FLARE_RADIUS_FOR_FJS (100.f) #define TF_FLARE_RADIUS_FOR_FJS (100.f)
#define JAR_EXPLODE_RADIUS (200.f)
#define TF_PLAYER_VIEW_OFFSET Vector( 0, 0, 64.0 ) #define TF_PLAYER_VIEW_OFFSET Vector( 0, 0, 64.0 )
#define TF_BURNING_FREQUENCY 0.5f #define TF_BURNING_FREQUENCY 0.5f
@@ -2,6 +2,7 @@
#include "../Misc/IAppSystem.h" #include "../Misc/IAppSystem.h"
#include "../Types.h" #include "../Types.h"
#define AIR_DENSITY 2
#define k_flMaxVelocity 2000.0f #define k_flMaxVelocity 2000.0f
#define k_flMaxAngularVelocity 360.0f * 10.0f #define k_flMaxAngularVelocity 360.0f * 10.0f
#define DEFAULT_MIN_FRICTION_MASS 10.0f #define DEFAULT_MIN_FRICTION_MASS 10.0f
@@ -55,6 +55,7 @@
#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans #define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans
#define CONTENTS_LADDER 0x20000000 #define CONTENTS_LADDER 0x20000000
#define CONTENTS_HITBOX 0x40000000 // use accurate hitboxes on trace #define CONTENTS_HITBOX 0x40000000 // use accurate hitboxes on trace
#define CONTENTS_DISPSOLID 0x80000000 // no normal checks when tracing against displacements
// NOTE: These are stored in a short in the engine now. Don't use more than 16 bits // NOTE: These are stored in a short in the engine now. Don't use more than 16 bits
#define SURF_LIGHT 0x0001 // value will hold the light strength #define SURF_LIGHT 0x0001 // value will hold the light strength
@@ -0,0 +1,33 @@
#pragma once
#include "CUtlVector.h"
#include "BaseTypes.h"
#include "../Main/CGameTrace.h"
#include "../Types.h"
#define MAX_CHECK_COUNT_DEPTH 2
typedef uint32 TraceCounter_t;
typedef CUtlVector<TraceCounter_t> CTraceCounterVec;
struct TraceInfo_t
{
Vector m_start;
Vector m_end;
Vector m_mins;
Vector m_maxs;
Vector m_extents;
Vector m_delta;
Vector m_invDelta;
trace_t m_trace;
trace_t m_stabTrace;
int m_contents;
bool m_ispoint;
bool m_isswept;
void* m_pBSPData;
Vector m_DispStabDir;
int m_bDispHit;
bool m_bCheckPrimary;
int m_nCheckDepth;
TraceCounter_t m_Count[MAX_CHECK_COUNT_DEPTH];
CTraceCounterVec m_BrushCounters[MAX_CHECK_COUNT_DEPTH];
CTraceCounterVec m_DispCounters[MAX_CHECK_COUNT_DEPTH];
};
+33 -13
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include <numbers>
#include <string> #include <string>
#include <format> #include <format>
#include <array> #include <array>
@@ -9,15 +10,34 @@
#include <map> #include <map>
#include <ranges> #include <ranges>
#define PI 3.14159265358979323846
#define M_RADPI 57.295779513082
#define DEG2RAD(x) ((float)(x) * (float)((float)(PI) / 180.f))
#define RAD2DEG(x) ((float)(x) * (float)(180.f / (float)(PI)))
#pragma warning (disable : 26495) #pragma warning (disable : 26495)
namespace Math namespace Math
{ {
template <class T = float>
constexpr T PI_V = static_cast<T>(3.141592653589793);
constexpr float PI = PI_V<>;
template <class T = float>
constexpr T RAD_V = static_cast<T>(57.29577951308232);
constexpr float RAD = RAD_V<>;
template <class T = float>
constexpr T E_V = static_cast<T>(2.718281828459045);
constexpr float E = E_V<>;
template <class T = float>
inline T Deg2Rad(T v)
{
return v * PI_V<T> / T(180);
}
template <class T = float>
inline T Rad2Deg(T v)
{
return v * T(180) / PI_V<T>;
}
inline float DeltaAngle(const float flAngleA, const float flAngleB) inline float DeltaAngle(const float flAngleA, const float flAngleB)
{ {
float flOut = fmodf((flAngleA - flAngleB) + 180.f, 360.f); float flOut = fmodf((flAngleA - flAngleB) + 180.f, 360.f);
@@ -698,15 +718,15 @@ public:
inline Vec3 ToAngle() const noexcept inline Vec3 ToAngle() const noexcept
{ {
return { RAD2DEG(atan2(-z, hypot(x, y))), return { Math::Rad2Deg(atan2(-z, hypot(x, y))),
RAD2DEG(atan2(y, x)), Math::Rad2Deg(atan2(y, x)),
0.f }; 0.f };
} }
inline Vec3 FromAngle() const noexcept inline Vec3 FromAngle() const noexcept
{ {
return { cos(DEG2RAD(x)) * cos(DEG2RAD(y)), return { cos(Math::Deg2Rad(x)) * cos(Math::Deg2Rad(y)),
cos(DEG2RAD(x)) * sin(DEG2RAD(y)), cos(Math::Deg2Rad(x)) * sin(Math::Deg2Rad(y)),
-sin(DEG2RAD(x)) }; -sin(Math::Deg2Rad(x)) };
} }
}; };
using Vector = Vec3; using Vector = Vec3;
@@ -749,9 +769,9 @@ private:
{ {
float sr, sp, sy, cr, cp, cy; float sr, sp, sy, cr, cp, cy;
SinCos(DEG2RAD(vAngles[1]), &sy, &cy); SinCos(Math::Deg2Rad(vAngles[1]), &sy, &cy);
SinCos(DEG2RAD(vAngles[0]), &sp, &cp); SinCos(Math::Deg2Rad(vAngles[0]), &sp, &cp);
SinCos(DEG2RAD(vAngles[2]), &sr, &cr); SinCos(Math::Deg2Rad(vAngles[2]), &sr, &cr);
// matrix = (YAW * PITCH) * ROLL // matrix = (YAW * PITCH) * ROLL
m2[0][0] = cp * cy; m2[0][0] = cp * cy;
+4 -4
View File
@@ -292,7 +292,7 @@ void CDraw::FillRoundRect(int x, int y, int w, int h, int iRadius, Color_t tColo
const float a = 90.f * i; const float a = 90.f * i;
for (int j = 0; j < _iCount; j++) for (int j = 0; j < _iCount; j++)
{ {
const float _a = DEG2RAD(a + j * flDelta); const float _a = Math::Deg2Rad(a + j * flDelta);
vVertices.emplace_back(Vertex_t({ { _x + iRadius * sinf(_a), _y - iRadius * cosf(_a) } })); vVertices.emplace_back(Vertex_t({ { _x + iRadius * sinf(_a), _y - iRadius * cosf(_a) } }));
} }
} }
@@ -314,7 +314,7 @@ void CDraw::LineRoundRect(int x, int y, int w, int h, int iRadius, Color_t tColo
const float a = 90.f * i; const float a = 90.f * i;
for (int j = 0; j < _iCount; j++) for (int j = 0; j < _iCount; j++)
{ {
const float _a = DEG2RAD(a + j * flDelta); const float _a = Math::Deg2Rad(a + j * flDelta);
vVertices.emplace_back(Vertex_t({ { _x + iRadius * sinf(_a), _y - iRadius * cosf(_a) } })); vVertices.emplace_back(Vertex_t({ { _x + iRadius * sinf(_a), _y - iRadius * cosf(_a) } }));
} }
} }
@@ -326,8 +326,8 @@ void CDraw::FillCircle(int x, int y, float iRadius, int iSegments, Color_t tColo
{ {
std::vector<Vertex_t> vVertices = {}; std::vector<Vertex_t> vVertices = {};
const float step = static_cast<float>(PI) * 2.0f / iSegments; const float flStep = Math::PI * 2.f / iSegments;
for (float a = 0; a < PI * 2.0f; a += step) for (float a = 0; a < Math::PI * 2.f; a += flStep)
vVertices.emplace_back(Vector2D{ iRadius * cosf(a) + x, iRadius * sinf(a) + y }); vVertices.emplace_back(Vector2D{ iRadius * cosf(a) + x, iRadius * sinf(a) + y });
FillPolygon(vVertices, tColor); FillPolygon(vVertices, tColor);
+3 -3
View File
@@ -720,7 +720,7 @@ void SDK::FixMovement(CUserCmd* pCmd, const Vec3& vCurAngle, const Vec3& vTarget
float flCurYaw = vCurAngle.y + (bCurOOB ? 180.f : 0.f); float flCurYaw = vCurAngle.y + (bCurOOB ? 180.f : 0.f);
float flTargetYaw = vTargetAngle.y + (bTargetOOB ? 180.f : 0.f); float flTargetYaw = vTargetAngle.y + (bTargetOOB ? 180.f : 0.f);
float flYaw = DEG2RAD(flTargetYaw - flCurYaw + vMoveAng.y); float flYaw = Math::Deg2Rad(flTargetYaw - flCurYaw + vMoveAng.y);
pCmd->forwardmove = cos(flYaw) * flSpeed; pCmd->forwardmove = cos(flYaw) * flSpeed;
pCmd->sidemove = sin(flYaw) * flSpeed * (bTargetOOB ? -1 : 1); pCmd->sidemove = sin(flYaw) * flSpeed * (bTargetOOB ? -1 : 1);
@@ -766,8 +766,8 @@ Vec3 SDK::ComputeMove(const CUserCmd* pCmd, CTFPlayer* pLocal, const Vec3& vFrom
Vec3 vSilent = vDiff.To2D(); Vec3 vSilent = vDiff.To2D();
Vec3 vAngle = Math::VectorAngles(vSilent); Vec3 vAngle = Math::VectorAngles(vSilent);
const float flYaw = DEG2RAD(vAngle.y - pCmd->viewangles.y); const float flYaw = Math::Deg2Rad(vAngle.y - pCmd->viewangles.y);
const float flPitch = DEG2RAD(vAngle.x - pCmd->viewangles.x); const float flPitch = Math::Deg2Rad(vAngle.x - pCmd->viewangles.x);
Vec3 vMove = { cos(flYaw) * 450.f, -sin(flYaw) * 450.f, -cos(flPitch) * 450.f }; Vec3 vMove = { cos(flYaw) * 450.f, -sin(flYaw) * 450.f, -cos(flPitch) * 450.f };
if (!(I::EngineTrace->GetPointContents(pLocal->GetShootPos()) & CONTENTS_WATER)) // only apply upmove in water if (!(I::EngineTrace->GetPointContents(pLocal->GetShootPos()) & CONTENTS_WATER)) // only apply upmove in water
+5 -5
View File
@@ -319,9 +319,9 @@ NAMESPACE_BEGIN(Vars)
CVarEnum(Hitboxes, VA_LIST("Hitboxes", "Projectile hitboxes"), 0b001111, DROPDOWN_MULTI, nullptr, CVarEnum(Hitboxes, VA_LIST("Hitboxes", "Projectile hitboxes"), 0b001111, DROPDOWN_MULTI, nullptr,
VA_LIST("Auto", "##Divider", "Head", "Body", "Feet", "##Divider", "Bodyaim if lethal", "Prioritize feet"), VA_LIST("Auto", "##Divider", "Head", "Body", "Feet", "##Divider", "Bodyaim if lethal", "Prioritize feet"),
Auto = 1 << 0, Head = 1 << 1, Body = 1 << 2, Feet = 1 << 3, BodyaimIfLethal = 1 << 4, PrioritizeFeet = 1 << 5); Auto = 1 << 0, Head = 1 << 1, Body = 1 << 2, Feet = 1 << 3, BodyaimIfLethal = 1 << 4, PrioritizeFeet = 1 << 5);
CVarEnum(Modifiers, VA_LIST("Modifiers", "Projectile modifiers"), 0b1010, DROPDOWN_MULTI, nullptr, CVarEnum(Modifiers, VA_LIST("Modifiers", "Projectile modifiers"), 0b0010, DROPDOWN_MULTI, nullptr,
VA_LIST("Charge weapon", "Cancel charge", "Use arm time"), VA_LIST("Charge weapon", "Cancel charge", "Use arm time", "Alternate angles"),
ChargeWeapon = 1 << 0, CancelCharge = 1 << 1, UseArmTime = 1 << 2); ChargeWeapon = 1 << 0, CancelCharge = 1 << 1, UseArmTime = 1 << 2, AlternateAngles = 1 << 3);
CVar(MaxSimulationTime, "Max simulation time", 2.f, SLIDER_MIN | SLIDER_PRECISION, 0.1f, 2.5f, 0.25f, "%gs"); CVar(MaxSimulationTime, "Max simulation time", 2.f, SLIDER_MIN | SLIDER_PRECISION, 0.1f, 2.5f, 0.25f, "%gs");
CVar(HitChance, "Hit chance", 0.f, SLIDER_CLAMP | SLIDER_PRECISION, 0.f, 100.f, 10.f, "%g%%"); CVar(HitChance, "Hit chance", 0.f, SLIDER_CLAMP | SLIDER_PRECISION, 0.f, 100.f, 10.f, "%g%%");
CVar(AutodetRadius, "Autodet radius", 90.f, SLIDER_CLAMP | SLIDER_PRECISION, 0.f, 100.f, 10.f, "%g%%"); CVar(AutodetRadius, "Autodet radius", 90.f, SLIDER_CLAMP | SLIDER_PRECISION, 0.f, 100.f, 10.f, "%g%%");
@@ -670,8 +670,8 @@ NAMESPACE_BEGIN(Vars)
CVar(OffsetX, "Offset X", 16.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, -25.f, 25.f, 0.5f); CVar(OffsetX, "Offset X", 16.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, -25.f, 25.f, 0.5f);
CVar(OffsetY, "Offset Y", 8.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, -25.f, 25.f, 0.5f); CVar(OffsetY, "Offset Y", 8.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, -25.f, 25.f, 0.5f);
CVar(OffsetZ, "Offset Z", -6.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, -25.f, 25.f, 0.5f); CVar(OffsetZ, "Offset Z", -6.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, -25.f, 25.f, 0.5f);
CVar(ForwardRedirect, "Forward redirect", 2000.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, 0.f, 2000.f, 100.f); CVar(ForwardRedirect, "Forward redirect", 0.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, 0.f, 2000.f, 100.f);
CVar(ForwardCutoff, "Forward cutoff", 0.1f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, 0.f, 1.f, 0.1f); CVar(ForwardCutoff, "Forward cutoff", 0.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, 0.f, 1.f, 0.1f);
CVar(Hull, "Hull", 5.f, NOSAVE | DEBUGVAR | SLIDER_MIN | SLIDER_PRECISION, 0.f, 10.f, 0.5f); CVar(Hull, "Hull", 5.f, NOSAVE | DEBUGVAR | SLIDER_MIN | SLIDER_PRECISION, 0.f, 10.f, 0.5f);
CVar(Speed, "Speed", 1200.f, NOSAVE | DEBUGVAR | SLIDER_MIN | SLIDER_PRECISION, 0.f, 5000.f, 50.f); CVar(Speed, "Speed", 1200.f, NOSAVE | DEBUGVAR | SLIDER_MIN | SLIDER_PRECISION, 0.f, 5000.f, 50.f);
CVar(Gravity, "Gravity", 1.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, 0.f, 1.f, 0.1f); CVar(Gravity, "Gravity", 1.f, NOSAVE | DEBUGVAR | SLIDER_PRECISION, 0.f, 1.f, 0.1f);
+22 -22
View File
@@ -105,11 +105,11 @@ namespace Math
} }
else else
{ {
flYaw = RAD2DEG(atan2f(vForward.y, vForward.x)); flYaw = Rad2Deg(atan2f(vForward.y, vForward.x));
if (flYaw < 0) if (flYaw < 0)
flYaw += 360; flYaw += 360;
flPitch = RAD2DEG(atan2f(-vForward.z, vForward.Length2D())); flPitch = Rad2Deg(atan2f(-vForward.z, vForward.Length2D()));
if (flPitch < 0) if (flPitch < 0)
flPitch += 360; flPitch += 360;
} }
@@ -129,8 +129,8 @@ namespace Math
inline void AngleVectors(const Vec3& vAngles, Vec3* pForward = nullptr, Vec3* pRight = nullptr, Vec3* pUp = nullptr) inline void AngleVectors(const Vec3& vAngles, Vec3* pForward = nullptr, Vec3* pRight = nullptr, Vec3* pUp = nullptr)
{ {
float sp, sy, sr, cp, cy, cr; float sp, sy, sr, cp, cy, cr;
SinCos(DEG2RAD(vAngles.x), &sp, &cp); SinCos(Deg2Rad(vAngles.x), &sp, &cp);
SinCos(DEG2RAD(vAngles.y), &sy, &cy); SinCos(Deg2Rad(vAngles.y), &sy, &cy);
if (pForward) if (pForward)
{ {
@@ -141,7 +141,7 @@ namespace Math
if (pRight || pUp) if (pRight || pUp)
{ {
SinCos(DEG2RAD(vAngles.z), &sr, &cr); SinCos(Deg2Rad(vAngles.z), &sr, &cr);
if (pRight) if (pRight)
{ {
@@ -165,8 +165,8 @@ namespace Math
float flHyp = std::sqrtf((vDelta.x * vDelta.x) + (vDelta.y * vDelta.y)); float flHyp = std::sqrtf((vDelta.x * vDelta.x) + (vDelta.y * vDelta.y));
Vec3 vAngles = { Vec3 vAngles = {
atanf(vDelta.z / flHyp) * float(M_RADPI), atanf(vDelta.z / flHyp) * RAD,
atanf(vDelta.y / vDelta.x) * float(M_RADPI), atanf(vDelta.y / vDelta.x) * RAD,
0.f 0.f
}; };
@@ -187,7 +187,7 @@ namespace Math
Vec3 vToForward = Vec3(); Vec3 vToForward = Vec3();
AngleVectors(vToAng, &vToForward); AngleVectors(vToAng, &vToForward);
float flResult = RAD2DEG(acos(vFromForward.Dot(vToForward))); float flResult = Rad2Deg(acos(vFromForward.Dot(vToForward)));
if (!isfinite(flResult) || isinf(flResult) || isnan(flResult)) if (!isfinite(flResult) || isinf(flResult) || isnan(flResult))
flResult = 0.f; flResult = 0.f;
@@ -199,9 +199,9 @@ namespace Math
Vec3 vOffset = vPoint - vOrigin; Vec3 vOffset = vPoint - vOrigin;
float sp, sy, sr, cp, cy, cr; float sp, sy, sr, cp, cy, cr;
SinCos(DEG2RAD(vAngles.x), &sp, &cp); SinCos(Deg2Rad(vAngles.x), &sp, &cp);
SinCos(DEG2RAD(vAngles.y), &sy, &cy); SinCos(Deg2Rad(vAngles.y), &sy, &cy);
SinCos(DEG2RAD(vAngles.z), &sr, &cr); SinCos(Deg2Rad(vAngles.z), &sr, &cr);
Vec3 vX = { Vec3 vX = {
cy * cp, cy * cp,
@@ -277,9 +277,9 @@ namespace Math
inline void AngleMatrix(const Vec3& vAngles, matrix3x4& mMatrix, bool bClearOrigin = true) inline void AngleMatrix(const Vec3& vAngles, matrix3x4& mMatrix, bool bClearOrigin = true)
{ {
float sp, sy, sr, cp, cy, cr; float sp, sy, sr, cp, cy, cr;
SinCos(DEG2RAD(vAngles.x), &sp, &cp); SinCos(Deg2Rad(vAngles.x), &sp, &cp);
SinCos(DEG2RAD(vAngles.y), &sy, &cy); SinCos(Deg2Rad(vAngles.y), &sy, &cy);
SinCos(DEG2RAD(vAngles.z), &sr, &cr); SinCos(Deg2Rad(vAngles.z), &sr, &cr);
mMatrix[0][0] = cp * cy; mMatrix[0][0] = cp * cy;
mMatrix[1][0] = cp * sy; mMatrix[1][0] = cp * sy;
@@ -315,14 +315,14 @@ namespace Math
float flLen = vForward.Length2D(); float flLen = vForward.Length2D();
if (flLen > 0.001f) if (flLen > 0.001f)
{ {
vAngles.x = RAD2DEG(std::atan2(-vForward.z, flLen)); vAngles.x = Rad2Deg(std::atan2(-vForward.z, flLen));
vAngles.y = RAD2DEG(std::atan2(vForward.y, vForward.x)); vAngles.y = Rad2Deg(std::atan2(vForward.y, vForward.x));
vAngles.z = RAD2DEG(std::atan2(vLeft.z, vUp.z)); vAngles.z = Rad2Deg(std::atan2(vLeft.z, vUp.z));
} }
else else
{ {
vAngles.x = RAD2DEG(std::atan2(-vForward.z, flLen)); vAngles.x = Rad2Deg(std::atan2(-vForward.z, flLen));
vAngles.y = RAD2DEG(std::atan2(-vLeft.x, vLeft.y)); vAngles.y = Rad2Deg(std::atan2(-vLeft.x, vLeft.y));
vAngles.z = 0; vAngles.z = 0;
} }
} }
@@ -411,7 +411,7 @@ namespace Math
GetMatrixOrigin(mMatrix, vOut); GetMatrixOrigin(mMatrix, vOut);
return vOut; return vOut;
} }
inline void ConcatTransforms(const matrix3x4& mIn1, const matrix3x4& mIn2, matrix3x4& mOut) inline void ConcatTransforms(const matrix3x4& mIn1, const matrix3x4& mIn2, matrix3x4& mOut)
{ {
if (&mIn1 == &mOut) if (&mIn1 == &mOut)
@@ -461,7 +461,7 @@ namespace Math
float q = 2 * powf(b, 3) / 27 - b * c / 3 + d; float q = 2 * powf(b, 3) / 27 - b * c / 3 + d;
if (p == 0.f) if (p == 0.f)
return pow(q, 1.f / 3); return powf(q, 1.f / 3);
if (q == 0.f) if (q == 0.f)
return 0.f; return 0.f;
@@ -476,7 +476,7 @@ namespace Math
return -2 * t * cosh(acosh(-g) / 3) - b / 3; return -2 * t * cosh(acosh(-g) / 3) - b / 3;
return 2 * t * cosh(acosh(g) / 3) - b / 3; return 2 * t * cosh(acosh(g) / 3) - b / 3;
} }
inline std::vector<float> SolveQuartic(float a, float b, float c, float d, float e) inline std::vector<float> SolveQuartic(float a, float b, float c, float d, float e)
{ {
std::vector<float> vRoots = {}; std::vector<float> vRoots = {};