diff --git a/Amalgam/Amalgam.vcxproj b/Amalgam/Amalgam.vcxproj
index 2eac861c..a531a26d 100644
--- a/Amalgam/Amalgam.vcxproj
+++ b/Amalgam/Amalgam.vcxproj
@@ -968,6 +968,7 @@
+
@@ -1321,6 +1322,7 @@
+
diff --git a/Amalgam/Amalgam.vcxproj.filters b/Amalgam/Amalgam.vcxproj.filters
index 64cdebac..c103b6eb 100644
--- a/Amalgam/Amalgam.vcxproj.filters
+++ b/Amalgam/Amalgam.vcxproj.filters
@@ -205,6 +205,7 @@
+
@@ -608,6 +609,7 @@
+
diff --git a/Amalgam/src/Core/Core.cpp b/Amalgam/src/Core/Core.cpp
index 2c29b98d..11c52648 100644
--- a/Amalgam/src/Core/Core.cpp
+++ b/Amalgam/src/Core/Core.cpp
@@ -7,6 +7,7 @@
#include "../Features/EnginePrediction/EnginePrediction.h"
#include "../Features/Visuals/Materials/Materials.h"
#include "../Features/Visuals/Visuals.h"
+#include "../Features/Spectate/Spectate.h"
#include "../SDK/Events/Events.h"
#include
@@ -145,17 +146,22 @@ void CCore::Unload()
if (F::Menu.m_bIsOpen)
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();
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);
F::EnginePrediction.Unload();
diff --git a/Amalgam/src/Features/Aimbot/Aimbot.cpp b/Amalgam/src/Features/Aimbot/Aimbot.cpp
index b437695b..d5ff38f8 100644
--- a/Amalgam/src/Features/Aimbot/Aimbot.cpp
+++ b/Amalgam/src/Features/Aimbot/Aimbot.cpp
@@ -90,7 +90,7 @@ void CAimbot::Draw(CTFPlayer* pLocal)
if (Vars::Aimbot::General::AimFOV.Value >= 90.f)
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);
}
diff --git a/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp b/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp
index 06c8a833..c4943b8b 100644
--- a/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp
+++ b/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp
@@ -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
{
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 vAnglesB = Math::CalcAngle(m_vEyePos, vPosB);
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;
}
- Math::ClampAngles(vOut);
+ //if (iMethod != Vars::Aimbot::General::AimTypeEnum::Silent || Vars::Misc::Game::AntiCheatCompatibility.Value)
+ Math::ClampAngles(vOut);
return bReturn;
}
diff --git a/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp b/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp
index 56de90a4..af4a45bd 100644
--- a/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp
+++ b/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp
@@ -450,7 +450,8 @@ bool CAimbotMelee::Aim(Vec3 vCurAngle, Vec3 vToAngle, Vec3& vOut, int iMethod)
break;
}
- Math::ClampAngles(vOut);
+ if (iMethod != Vars::Aimbot::General::AimTypeEnum::Silent || Vars::Misc::Game::AntiCheatCompatibility.Value)
+ Math::ClampAngles(vOut);
return bReturn;
}
diff --git a/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp b/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp
index 9c959754..7823f827 100644
--- a/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp
+++ b/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp
@@ -178,7 +178,7 @@ static inline std::vector GetTargets(CTFPlayer* pLocal, CTFWeaponBase*
-float CAimbotProjectile::GetSplashRadius(CTFWeaponBase* pWeapon, CTFPlayer* pPlayer)
+float CAimbotProjectile::GetSplashRadius(CTFWeaponBase* pWeapon, CTFPlayer* pPlayer, float flScale)
{
float flRadius = 0.f;
switch (pWeapon->GetWeaponID())
@@ -193,6 +193,11 @@ float CAimbotProjectile::GetSplashRadius(CTFWeaponBase* pWeapon, CTFPlayer* pPla
case TF_WEAPON_FLAREGUN_REVENGE:
if (pWeapon->As()->GetFlareGunType() == FLAREGUN_SCORCHSHOT)
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)
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)
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)
@@ -233,6 +238,11 @@ float CAimbotProjectile::GetSplashRadius(CBaseEntity* pProjectile, CTFWeaponBase
case ETFClassID::CTFProjectile_Flare:
if (pWeapon && pWeapon->As()->GetFlareGunType() == FLAREGUN_SCORCHSHOT)
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)
{
@@ -315,11 +325,17 @@ static inline int GetHitboxPriority(int nHitbox, Target_t& tTarget, Info_t& tInf
return -1;
};
-std::unordered_map CAimbotProjectile::GetDirectPoints()
+Directs_t CAimbotProjectile::GetDirects()
{
- std::unordered_map 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;
+ 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();
for (int i = 0; i < 3; i++)
@@ -362,17 +378,35 @@ std::unordered_map CAimbotProjectile::GetDirectPoints()
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.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
- 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;
- 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 ComputeSphere(float flRadius, int iSamples)
@@ -386,7 +420,7 @@ static inline std::vector 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 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++)
{
float t = a * n;
@@ -514,7 +548,7 @@ static inline void HandleFace(const Face_t& tFace, std::vector& vPoints, f
}
// possibly add air splash for autodet weapons
-void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector& vSplashPoints)
+void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector& vSplashPoints, byte iFlags)
{
vSplashPoints.clear();
@@ -558,10 +592,10 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector& vSpl
else
{
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)
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);
}
return fCheckNormal(trace.plane.normal, vPoint, &vAngle);
@@ -571,7 +605,7 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector& vSpl
{
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)
continue;
@@ -593,10 +627,10 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector& vSpl
else
{
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)
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);
}
return fCheckNormal(vNormal, vPoint, &vAngle);
@@ -624,7 +658,7 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector& vSpl
#endif
}
-std::vector CAimbotProjectile::GetSplashPoints(Vec3 vOrigin, std::vector& vSplashPoints, int iSimTime)
+std::vector CAimbotProjectile::GetSplashPoints(Vec3 vOrigin, std::vector& vSplashPoints, int iSimTime, byte iFlags)
{
std::vector> vPointDistances = {};
@@ -634,7 +668,7 @@ std::vector CAimbotProjectile::GetSplashPoints(Vec3 vOrigin, std::vecto
for (auto it = vSplashPoints.begin(); it != vSplashPoints.end();)
{
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)
{
++it;
@@ -710,13 +744,13 @@ static inline Vec3 PullPoint(const Vec3& vPoint, Vec3 vLocalPos, Info_t& tInfo,
const Vec3 vDelta = vTargetPos - vLocalPos;
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)
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;
- return vLocalPos + Vec3(0, 0, (flGrav * pow(flTime, 2)) / 2);
+ return vLocalPos + Vec3(0, 0, (flGrav * powf(flTime, 2)) / 2);
};
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)
-{
- if (!F::ProjSim.m_pObj->IsDragEnabled() || F::ProjSim.m_pObj->m_dragBasis.IsZero())
- return;
+static inline float GetDrag(float flVelocity, ProjectileInfo* pInfo, int iFlags)
+{ // stupid, would like not to hardcode magic values
+ if (!(iFlags & CalculateFlagsEnum::AccountDrag) || !F::ProjSim.m_pObj->m_dragCoefficient || !F::ProjSim.m_pObj->m_dragBasis)
+ 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)
- 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
{
- switch (pWeapon->m_iItemDefinitionIndex()) // the remaps are dumb but they work so /shrug
+ switch (pInfo->m_uType)
{
- case Demoman_m_GrenadeLauncher:
- case Demoman_m_GrenadeLauncherR:
- case Demoman_m_FestiveGrenadeLauncher:
- case Demoman_m_Autumn:
- case Demoman_m_MacabreWeb:
- case Demoman_m_Rainbow:
- case Demoman_m_SweetDreams:
- case Demoman_m_CoffinNail:
- case Demoman_m_TopShelf:
- case Demoman_m_Warhawk:
- case Demoman_m_ButcherBird:
- 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 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
- 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 Demoman_s_StickybombLauncher:
- case Demoman_s_StickybombLauncherR:
- case Demoman_s_FestiveStickybombLauncher:
- case Demoman_s_TheQuickiebombLauncher:
- 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 Scout_s_TheFlyingGuillotine:
- case Scout_s_TheFlyingGuillotineG: flDrag = 0.310f; break;
- case Scout_t_TheSandman: flDrag = 0.180f; break;
- 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;
+ 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.056f, 0.062f);
+ else
+ return Math::RemapVal(flVelocity, 1217.f, k_flMaxVelocity, 0.030f, 0.033f);
+ case FNV1A::Hash32Const("models/weapons/w_models/w_cannonball.mdl"):
+ return Math::RemapVal(flVelocity, 1454.f, k_flMaxVelocity, 0.099f, 0.092f);
+ case FNV1A::Hash32Const("models/weapons/w_models/w_stickybomb.mdl"):
+ return Math::RemapVal(flVelocity, 922.f, k_flMaxVelocity, 0.048f, 0.060f);
+ case FNV1A::Hash32Const("models/workshop_partner/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl"):
+ return 0.075f;
+ case FNV1A::Hash32Const("models/weapons/w_models/w_baseball.mdl"):
+ return 0.057f;
+ case FNV1A::Hash32Const("models/weapons/c_models/c_xms_festive_ornament.mdl"):
+ return 0.072f;
+ 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.030f;
+ case FNV1A::Hash32Const("models/weapons/c_models/c_gascan/c_gascan.mdl"):
+ return 0.089f;
}
}
- float flOverride = Vars::Aimbot::Projectile::TimeOverride.Value;
- flDragTime = powf(flTime, 2) * flDrag / (flOverride ? flOverride : 1.5f); // rough estimate to prevent m_flTime being too low
- flVelocity = flVelocity - flVelocity * flTime * flDrag;
+ return 0.f;
}
-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)
return;
- const float flGrav = m_tInfo.m_flGravity * 800.f;
-
float flPitch, flYaw;
{ // basic trajectory pass
- float flVelocity = m_tInfo.m_flVelocity, flDragTime = 0.f;
- if (iFlags & CalculateFlagsEnum::AccountDrag && m_tInfo.m_pWeapon && F::ProjSim.m_pObj->IsDragEnabled() && !F::ProjSim.m_pObj->m_dragBasis.IsZero())
+ //Vec3 vForward, vRight, vUp; Math::AngleVectors(Math::CalcAngle(vLocalPos, vTargetPos), &vForward, &vRight, &vUp);
+ //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);
- Vec3 vShootPos = vLocalPos + (vForward * m_tInfo.m_vOffset.x) + (vRight * m_tInfo.m_vOffset.y) + (vUp * m_tInfo.m_vOffset.z);
- SolveProjectileSpeed(m_tInfo.m_pWeapon, vShootPos, vTargetPos, flVelocity, flDragTime, m_tInfo.m_flGravity);
+ tOut.m_iCalculated = CalculateResultEnum::Bad;
+ return;
}
- Vec3 vDelta = vTargetPos - vLocalPos;
- float flDist = vDelta.Length2D();
-
- 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;
+ tOut.m_flTime -= m_tInfo.m_flOffsetTime;
+ tOut.m_flPitch = flPitch = -Math::Rad2Deg(flPitch) - m_tInfo.m_vAngFix.x;
+ tOut.m_flYaw = flYaw -= m_tInfo.m_vAngFix.y;
}
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;
return;
}
- else if (tOut.m_iCalculated = bGood ? CalculateResultEnum::Pending : CalculateResultEnum::Time)
+ else if (!bGood)
+ {
+ tOut.m_iCalculated = CalculateResultEnum::Time;
return;
+ }
int iSimFlags = (iFlags & CalculateFlagsEnum::SetupClip ? ProjSimEnum::Redirect : ProjSimEnum::None) | ProjSimEnum::NoRandomAngles | ProjSimEnum::PredictCmdNum;
#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::Pipes.Value)
+ if (!Vars::Visuals::Trajectory::ForwardRedirect.Value)
s_mTraceCount[__FUNCTION__": setup trace"]++;
}
else
@@ -861,63 +946,53 @@ void CAimbotProjectile::CalculateAngle(const Vec3& vLocalPos, const Vec3& vTarge
}
#endif
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;
+ }
{ // calculate trajectory from projectile origin
- float flVelocity = m_tInfo.m_flVelocity, flDragTime = 0.f;
- 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())
+ if (!GetAngle(m_tProjInfo.m_vPos, vTargetPos, iFlags, m_tInfo, tOut.m_flPitch, tOut.m_flYaw, tOut.m_flTime))
{
- vShootPos += vForward * vSolutions.front();
- tOut.m_flYaw = flYaw - (RAD2DEG(atan2(vShootPos.y, vShootPos.x)) - flYaw);
- flYaw = RAD2DEG(atan2(vShootPos.y, vShootPos.x));
+ tOut.m_iCalculated = CalculateResultEnum::Bad;
+ return;
}
- }
- { // correct pitch
- if (flGrav)
- {
- flPitch -= m_tProjInfo.m_vAng.x;
- tOut.m_flPitch = -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));
+ { // 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_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 pWeapon = m_tInfo.m_pWeapon;
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;
#ifdef SPLASH_DEBUG5
if (Vars::Visuals::Trajectory::Override.Value)
{
- if (!Vars::Visuals::Trajectory::Pipes.Value)
+ if (!Vars::Visuals::Trajectory::ForwardRedirect.Value)
s_mTraceCount[__FUNCTION__": setup trace"]++;
}
else
@@ -1059,7 +1135,7 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
{
bool bTime = bSplash
? 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 bValid = bTarget && bTime;
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)
{ // run for more ticks to check for splash
- iSimTime = n + 5;
+ iSimTime = n + iTimingTolerance;
bSplash = bArmTime = true;
+ filter.pSkip = tTarget.m_pEntity;
}
else
break;
@@ -1211,60 +1288,73 @@ bool CAimbotProjectile::HandlePoint(const Vec3& vOrigin, int iSimTime, float flP
return bReturn;
}
-bool CAimbotProjectile::HandleDirect(std::vector& vDirectHistory)
+bool CAimbotProjectile::HandleDirect(DirectHistory_t& mDirectHistory)
{
- if (vDirectHistory.empty())
+ if (mDirectHistory.empty())
return false;
- std::sort(vDirectHistory.begin(), vDirectHistory.end(), [&](const Direct_t& a, const Direct_t& b) -> bool
- {
- return a.m_iPriority < b.m_iPriority;
- });
- m_flTimeTo = vDirectHistory.front().m_flTime + m_tInfo.m_flLatency;
-
- for (auto& tHistory : vDirectHistory)
+ for (auto& vDirectHistory : mDirectHistory | std::views::values)
{
- if (HandlePoint(tHistory.m_vOrigin, tHistory.m_iSimtime, tHistory.m_flPitch, tHistory.m_flYaw, tHistory.m_flTime, tHistory.m_vPoint))
- return true;
+ std::sort(vDirectHistory.begin(), vDirectHistory.end(), [&](const Direct_t& a, const Direct_t& b) -> bool
+ {
+ 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;
}
-bool CAimbotProjectile::HandleSplash(std::vector& vSplashHistory)
+bool CAimbotProjectile::HandleSplash(SplashHistory_t& mSplashHistory)
{
- if (vSplashHistory.empty())
+ if (mSplashHistory.empty())
return false;
- std::sort(vSplashHistory.begin(), vSplashHistory.end(), [&](const Splash_t& a, const Splash_t& b) -> bool
- {
- 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::max();
- for (auto& tHistory : vSplashHistory)
+ for (auto& [iType, vSplashHistory] : mSplashHistory)
{
- if (m_tInfo.m_iArmTime && tHistory.m_iSimtime < m_tInfo.m_iArmTime)
- continue;
+ std::sort(vSplashHistory.begin(), vSplashHistory.end(), [&](const Splash_t& a, const Splash_t& b) -> bool
+ {
+ 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 vSplashPoints = {};
- vSplashPoints = GetSplashPoints(tHistory.m_vOrigin, m_vSplashPoints, tHistory.m_iSimtime);
-
- for (auto& tPoint : vSplashPoints)
+ iFlags |= CalculateFlagsEnum::Accuracy;
+ float flLowestDistance = std::numeric_limits::max();
+ for (auto& tHistory : vSplashHistory)
{
- float flDistance = tHistory.m_vOrigin.DistTo(tPoint.m_vPoint);
- if (flDistance > flLowestDistance)
+ if (m_tInfo.m_iArmTime && tHistory.m_iSimtime < m_tInfo.m_iArmTime)
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;
+ std::vector vSplashPoints = {};
+ 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::max())
+ return true;
}
- return flLowestDistance != std::numeric_limits::max();
+ return false;
}
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_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_flBoundingTime = m_tInfo.m_flRadiusTime + tTarget.m_pEntity->GetSize().Length() / m_tInfo.m_flVelocity;
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 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() : GetDirectPoints();
-
- std::vector vDirectHistory = {};
- std::vector vSplashHistory = {};
-
for (int i = 1 - TIME_TO_TICKS(m_tInfo.m_flLatency); i <= iMaxTime; i++)
{
if (!m_tMoveStorage.m_bFailed)
@@ -1328,26 +1417,11 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas
if (i < 0)
continue;
- bool bDirectBreaks = true;
- if (iSplash)
+ for (auto& [iIndex, tOffset] : mDirects)
{
- Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, tTarget.m_vPos, i, tSolution, CalculateFlagsEnum::None);
- if (tSolution.m_iCalculated != CalculateResultEnum::Bad)
- {
- const float flTimeTo = tSolution.m_flTime - TICKS_TO_TIME(i);
+ Vec3& vOffset = tOffset.m_vOffset;
+ byte iType = tOffset.m_iFlags & -tOffset.m_iFlags;
- 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;
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:
if (m_tInfo.m_iArmTime && m_tInfo.m_iArmTime > i && !m_tMoveStorage.m_MoveData.m_vecVelocity.IsZero())
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]];
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;
}
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:
- HandleDirect(vDirectHistory);
+ HandleDirect(mDirectHistory);
break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Include:
- if (!HandleDirect(vDirectHistory))
- HandleSplash(vSplashHistory);
+ if (!HandleDirect(mDirectHistory))
+ HandleSplash(mSplashHistory);
break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Prefer:
- if (!HandleSplash(vSplashHistory))
- HandleDirect(vDirectHistory);
+ if (!HandleSplash(mSplashHistory))
+ HandleDirect(mDirectHistory);
break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Only:
- HandleSplash(vSplashHistory);
+ HandleSplash(mSplashHistory);
}
F::MoveSim.Restore(m_tMoveStorage);
@@ -1459,7 +1565,8 @@ bool CAimbotProjectile::Aim(const Vec3& vCurAngle, const Vec3& vToAngle, Vec3& v
break;
}
- Math::ClampAngles(vOut);
+ if (iMethod != Vars::Aimbot::General::AimTypeEnum::Silent || Vars::Misc::Game::AntiCheatCompatibility.Value)
+ Math::ClampAngles(vOut);
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 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() : GetDirectPoints();
-
- std::vector vDirectHistory = {};
- std::vector vSplashHistory = {};
-
for (int i = 1 - TIME_TO_TICKS(m_tInfo.m_flLatency); i <= iMaxTime; i++)
{
if (!m_tMoveStorage.m_bFailed)
@@ -1978,26 +2084,11 @@ bool CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBa
if (i < 0)
continue;
- bool bDirectBreaks = true;
- if (iSplash)
+ for (auto& [iIndex, tOffset] : mDirects)
{
- Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, tTarget.m_vPos, i, tSolution, CalculateFlagsEnum::None);
- if (tSolution.m_iCalculated != CalculateResultEnum::Bad)
- {
- const float flTimeTo = tSolution.m_flTime - TICKS_TO_TIME(i);
+ Vec3& vOffset = tOffset.m_vOffset;
+ byte iType = tOffset.m_iFlags & -tOffset.m_iFlags;
- 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;
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)
{
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]];
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;
}
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:
- HandleDirect(vDirectHistory);
+ HandleDirect(mDirectHistory);
break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Include:
- if (!HandleDirect(vDirectHistory))
- HandleSplash(vSplashHistory);
+ if (!HandleDirect(mDirectHistory))
+ HandleSplash(mSplashHistory);
break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Prefer:
- if (!HandleSplash(vSplashHistory))
- HandleDirect(vDirectHistory);
+ if (!HandleSplash(mSplashHistory))
+ HandleDirect(mDirectHistory);
break;
case Vars::Aimbot::Projectile::SplashPredictionEnum::Only:
- HandleSplash(vSplashHistory);
+ HandleSplash(mSplashHistory);
}
F::MoveSim.Restore(m_tMoveStorage);
diff --git a/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.h b/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.h
index 8985a447..4e99c689 100644
--- a/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.h
+++ b/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.h
@@ -5,7 +5,8 @@
#include "../../Simulation/MovementSimulation/MovementSimulation.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)
struct Info_t
@@ -46,6 +47,14 @@ struct Point_t
Solution_t m_tSolution = {};
};
+struct Offset_t
+{
+ Vec3 m_vOffset;
+ byte m_iFlags;
+};
+using Directs_t = std::unordered_map;
+using Splashes_t = std::vector;
+
struct History_t
{
Vec3 m_vOrigin;
@@ -63,20 +72,23 @@ struct Splash_t : History_t
{
float m_flTimeTo;
};
+using DirectHistory_t = std::unordered_map>;
+using SplashHistory_t = std::unordered_map>;
class CAimbotProjectile
{
private:
- std::unordered_map GetDirectPoints();
- void SetupSplashPoints(Vec3& vOrigin, std::vector& vSplashPoints);
- std::vector GetSplashPoints(Vec3 vOrigin, std::vector& vSplashPoints, int iSimTime);
+ Directs_t GetDirects();
+ Splashes_t GetSplashes();
+ void SetupSplashPoints(Vec3& vOrigin, std::vector& vSplashPoints, byte iFlags = CalculateFlagsEnum::None);
+ std::vector GetSplashPoints(Vec3 vOrigin, std::vector& 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 HandlePoint(const Vec3& vOrigin, int iSimTime, float flPitch, float flYaw, float flTime, const Vec3& vPoint, bool bSplash = false);
- bool HandleDirect(std::vector& vDirectHistory);
- bool HandleSplash(std::vector& vSplashHistory);
+ bool HandleDirect(DirectHistory_t& vDirectHistory);
+ bool HandleSplash(SplashHistory_t& vSplashHistory);
int CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bVisuals = true);
bool RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
@@ -108,7 +120,7 @@ private:
public:
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);
float GetSplashRadius(CBaseEntity* pProjectile, CTFWeaponBase* pWeapon = nullptr, CTFPlayer* pPlayer = nullptr, float flScale = 1.f, CTFWeaponBase* pAirblast = nullptr);
diff --git a/Amalgam/src/Features/Aimbot/AutoDetonate/AutoDetonate.cpp b/Amalgam/src/Features/Aimbot/AutoDetonate/AutoDetonate.cpp
index b1c3be5d..04dee66e 100644
--- a/Amalgam/src/Features/Aimbot/AutoDetonate/AutoDetonate.cpp
+++ b/Amalgam/src/Features/Aimbot/AutoDetonate/AutoDetonate.cpp
@@ -154,7 +154,7 @@ bool CAutoDetonate::CheckTargets(CTFPlayer* pLocal, EntityEnum::EntityEnum iGrou
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;
auto& vProjectiles = H::Entities.GetGroup(iGroup);
diff --git a/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.cpp b/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.cpp
index 899f3e8b..c44723ca 100644
--- a/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.cpp
+++ b/Amalgam/src/Features/Aimbot/AutoRocketJump/AutoRocketJump.cpp
@@ -78,8 +78,8 @@ bool CAutoRocketJump::SetAngles(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser
if (!vSolutions.empty())
{
vShootPos += vForward * vSolutions.front();
- m_vAngles.y = flYaw - (RAD2DEG(atan2(vShootPos.y, vShootPos.x)) - flYaw);
- flYaw = RAD2DEG(atan2(vShootPos.y, vShootPos.x));
+ m_vAngles.y = flYaw - (Math::Rad2Deg(atan2(vShootPos.y, vShootPos.x)) - flYaw);
+ flYaw = Math::Rad2Deg(atan2(vShootPos.y, vShootPos.x));
}
}
@@ -93,7 +93,7 @@ bool CAutoRocketJump::SetAngles(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser
if (!vSolutions.empty())
{
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);
}
}
diff --git a/Amalgam/src/Features/ImGui/Menu/Components.h b/Amalgam/src/Features/ImGui/Menu/Components.h
index fd84739d..b28e8bd1 100644
--- a/Amalgam/src/Features/ImGui/Menu/Components.h
+++ b/Amalgam/src/Features/ImGui/Menu/Components.h
@@ -254,21 +254,29 @@ namespace ImGui
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);
- 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);
- if (bTwoToneBorder)
- pDrawList->AddRectFilled({ vDrawPos.x + flInset, vDrawPos.y + flSize - H::Draw.Scale() }, {vDrawPos.x - flInset + vSize.x, vDrawPos.y + flSize }, uBorder);
+ if (!bTwoToneBorder)
+ 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);
+ else
+ {
+ 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
{
- 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);
- 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);
- if (bTwoToneBorder)
- pDrawList->AddRectFilled({ vDrawPos.x + flSize - H::Draw.Scale(), vDrawPos.y + flInset }, { vDrawPos.x + flSize, vDrawPos.y - flInset + vSize.y }, uBorder);
+ if (!bTwoToneBorder)
+ 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);
+ else
+ {
+ 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();
- 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)
{
diff --git a/Amalgam/src/Features/ImGui/Menu/Menu.cpp b/Amalgam/src/Features/ImGui/Menu/Menu.cpp
index 43048e48..a74eb1b8 100644
--- a/Amalgam/src/Features/ImGui/Menu/Menu.cpp
+++ b/Amalgam/src/Features/ImGui/Menu/Menu.cpp
@@ -27,18 +27,13 @@ void CMenu::DrawMenu()
PushStyleVar(ImGuiStyleVar_WindowMinSize, { H::Draw.Scale(750), H::Draw.Scale(500) });
if (Begin("Main", nullptr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoBackground))
{
- ImVec2 vWindowPos = GetWindowPos();
ImVec2 vWindowSize = GetWindowSize();
- float flSideSize = 140.f;
-
- PushClipRect({ 0, 0 }, { ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y }, false);
- RenderTwoToneBackground(H::Draw.Scale(flSideSize), F::Render.Background0, F::Render.Background1, F::Render.Background2, 0.f, false);
- PopClipRect();
-
ImVec2 vDrawPos = GetDrawPos();
auto pDrawList = GetWindowDrawList();
-
+ float flSize = H::Draw.Scale(140);
+ float flInset = H::Draw.Scale();
float flOffset = 0.f;
+
Bind_t tBind;
if (!F::Binds.GetBind(CurrentBind, &tBind))
CurrentBind = DEFAULT_BIND;
@@ -46,29 +41,39 @@ void CMenu::DrawMenu()
if (CurrentBind != DEFAULT_BIND) // bind
{
flOffset = H::Draw.Scale(60);
- pDrawList->AddRectFilled({ vDrawPos.x, vDrawPos.y + H::Draw.Scale(59) }, { vDrawPos.x + H::Draw.Scale(flSideSize - 1), vDrawPos.y + H::Draw.Scale(60) }, F::Render.Background2);
+ pDrawList->AddRectFilled({ vDrawPos.x, vDrawPos.y }, { vDrawPos.x + flSize - flInset, vDrawPos.y + flOffset - flInset }, F::Render.Background0, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopLeft);
+ pDrawList->AddRectFilled({ vDrawPos.x, vDrawPos.y + flOffset - flInset }, { vDrawPos.x + flSize - flInset, vDrawPos.y + flOffset }, F::Render.Background2);
+ pDrawList->AddRectFilled({ vDrawPos.x, vDrawPos.y + flOffset }, { vDrawPos.x + flSize - flInset, vDrawPos.y + vWindowSize.y }, F::Render.Background0, H::Draw.Scale(3), ImDrawFlags_RoundCornersBottomLeft);
SetCursorPos({ H::Draw.Scale(12), H::Draw.Scale(11) });
FText("Editing bind", 0, F::Render.FontRegular);
SetCursorPos({ H::Draw.Scale(12), H::Draw.Scale(35) });
PushStyleColor(ImGuiCol_Text, F::Render.Accent.Value);
- FText(TruncateText(tBind.m_sName, H::Draw.Scale(flSideSize - 28)).c_str(), 0, F::Render.FontRegular);
+ FText(TruncateText(tBind.m_sName, flSize - H::Draw.Scale(28)).c_str(), 0, F::Render.FontRegular);
PopStyleColor();
- SetCursorPos({ H::Draw.Scale(flSideSize - 31), H::Draw.Scale(6) });
+ SetCursorPos({ flSize - H::Draw.Scale(31), H::Draw.Scale(6) });
if (IconButton(ICON_MD_CANCEL))
CurrentBind = DEFAULT_BIND;
}
else if (!Vars::Menu::CheatTitle.Value.empty()) // title
{
flOffset = H::Draw.Scale(36);
- pDrawList->AddRectFilled({ vDrawPos.x, vDrawPos.y + H::Draw.Scale(35) }, { vDrawPos.x + H::Draw.Scale(flSideSize - 1), vDrawPos.y + H::Draw.Scale(36) }, F::Render.Background2);
-
+ pDrawList->AddRectFilled({ vDrawPos.x, vDrawPos.y }, { vDrawPos.x + flSize - flInset, vDrawPos.y + flOffset - flInset }, F::Render.Background0, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopLeft);
+ pDrawList->AddRectFilled({ vDrawPos.x, vDrawPos.y + flOffset - flInset }, { vDrawPos.x + flSize - flInset, vDrawPos.y + flOffset }, F::Render.Background2);
+ pDrawList->AddRectFilled({ vDrawPos.x, vDrawPos.y + flOffset }, { vDrawPos.x + flSize - flInset, vDrawPos.y + vWindowSize.y }, F::Render.Background0, H::Draw.Scale(3), ImDrawFlags_RoundCornersBottomLeft);
+
SetCursorPos({ H::Draw.Scale(12), H::Draw.Scale(11) });
PushStyleColor(ImGuiCol_Text, F::Render.Accent.Value);
- FText(TruncateText(Vars::Menu::CheatTitle.Value, H::Draw.Scale(flSideSize - 28), F::Render.FontBold).c_str(), 0, F::Render.FontBold);
+ FText(TruncateText(Vars::Menu::CheatTitle.Value, flSize - H::Draw.Scale(28), F::Render.FontBold).c_str(), 0, F::Render.FontBold);
PopStyleColor();
}
+ else
+ pDrawList->AddRectFilled({ vDrawPos.x, vDrawPos.y }, { vDrawPos.x + flSize - flInset, vDrawPos.y + vWindowSize.y }, F::Render.Background0, H::Draw.Scale(3), ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomLeft);
+
+ PushClipRect({ 0, 0 }, { ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y }, false);
+ RenderTwoToneBackground(flSize, {}, F::Render.Background1, F::Render.Background2, 0.f, false);
+ PopClipRect();
static int iTab = 0, iAimbotTab = 0, iVisualsTab = 0, iMiscTab = 0, iLogsTab = 0, iSettingsTab = 0;
PushFont(F::Render.FontBold);
@@ -81,7 +86,7 @@ void CMenu::DrawMenu()
{ "SETTINGS", "CONFIG", "BINDS", "MATERIALS", "EXTRA" }
},
{ &iTab, &iAimbotTab, &iVisualsTab, &iMiscTab, &iLogsTab, &iSettingsTab },
- { H::Draw.Scale(flSideSize - 16), H::Draw.Scale(36) },
+ { flSize - H::Draw.Scale(16), H::Draw.Scale(36) },
{ H::Draw.Scale(8), H::Draw.Scale(8) + flOffset },
FTabsEnum::Vertical | FTabsEnum::HorizontalIcons | FTabsEnum::AlignLeft | FTabsEnum::BarLeft,
{ { ICON_MD_PERSON }, { ICON_MD_VISIBILITY }, { ICON_MD_ARTICLE }, { ICON_MD_IMPORT_CONTACTS }, { ICON_MD_SETTINGS } },
@@ -102,10 +107,10 @@ void CMenu::DrawMenu()
if (bSearch && IsMouseReleased(ImGuiMouseButton_Left) && IsMouseWithin(vDrawPos.x, vDrawPos.y, H::Draw.Scale(140), vWindowSize.y - H::Draw.Scale(45)))
sSearch = "";
- SetCursorPos({ H::Draw.Scale(flSideSize), 0 });
+ SetCursorPos({ flSize, 0 });
PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
PushStyleVar(ImGuiStyleVar_WindowPadding, { H::Draw.Scale(8), H::Draw.Scale(8) });
- if (BeginChild("Page", { vWindowSize.x - H::Draw.Scale(flSideSize), vWindowSize.y }, ImGuiChildFlags_AlwaysUseWindowPadding))
+ if (BeginChild("Page", { vWindowSize.x - flSize, vWindowSize.y }, ImGuiChildFlags_AlwaysUseWindowPadding))
{
if (!bSearch)
{
@@ -135,7 +140,7 @@ void CMenu::MenuAimbot(int iTab)
switch (iTab)
{
- // General
+ // General
case 0:
{
if (BeginTable("AimbotTable", 2))
@@ -474,7 +479,7 @@ void CMenu::MenuVisuals(int iTab)
switch (iTab)
{
- // ESP
+ // ESP
case 0:
{
// fake angle/viewmodel visuals, pickup timers?
@@ -511,12 +516,12 @@ void CMenu::MenuVisuals(int iTab)
PopStyleColor();
auto fPositionToIndex = [](ImVec2 vPos)
- {
- int iIndex = floorf((vPos.y - GetCursorPosY() - H::Draw.Scale(4)) / H::Draw.Scale(36)) * 2
- + (vPos.x > GetWindowWidth() / 2 ? 1 : 0);
- iIndex = std::clamp(iIndex, 0, int(F::Groups.m_vGroups.size() - 1));
- return iIndex;
- };
+ {
+ int iIndex = floorf((vPos.y - GetCursorPosY() - H::Draw.Scale(4)) / H::Draw.Scale(36)) * 2
+ + (vPos.x > GetWindowWidth() / 2 ? 1 : 0);
+ iIndex = std::clamp(iIndex, 0, int(F::Groups.m_vGroups.size() - 1));
+ return iIndex;
+ };
static int iDragging = -1;
if (!IsMouseDown(ImGuiMouseButton_Left))
@@ -698,7 +703,7 @@ void CMenu::MenuVisuals(int iTab)
vValues.insert(vValues.end(), { ESPEnum::IntelReturnTime });
}
- PushTransparent(tGroup.m_iTargets && !(tGroup.m_iTargets& TargetsEnum::ESP));
+ PushTransparent(tGroup.m_iTargets && !(tGroup.m_iTargets & TargetsEnum::ESP));
{
FDropdown("Draw", &tGroup.m_iESP, vEntries, vValues, FDropdownEnum::Multi);
}
@@ -1015,7 +1020,7 @@ void CMenu::MenuMisc(int iTab)
switch (iTab)
{
- // Main
+ // Main
case 0:
{
if (BeginTable("MiscTable", 2))
@@ -1279,7 +1284,7 @@ void CMenu::MenuLogs(int iTab)
switch (iTab)
{
- // PlayerList
+ // PlayerList
case 0:
{
if (Section("Players"))
@@ -1301,309 +1306,309 @@ void CMenu::MenuLogs(int iTab)
}
auto fGetTeamColor = [&](int iTeam, bool bAlive)
- {
- switch (iTeam)
{
- case 3: return Color_t(100, 150, 200, bAlive ? 255 : 127).Lerp(Vars::Menu::Theme::Background.Value, 0.5f, LerpEnum::NoAlpha);
- case 2: return Color_t(255, 100, 100, bAlive ? 255 : 127).Lerp(Vars::Menu::Theme::Background.Value, 0.5f, LerpEnum::NoAlpha);
- }
- return Color_t(127, 127, 127, 255).Lerp(Vars::Menu::Theme::Background.Value, 0.5f, LerpEnum::NoAlpha);
- };
+ switch (iTeam)
+ {
+ case 3: return Color_t(100, 150, 200, bAlive ? 255 : 127).Lerp(Vars::Menu::Theme::Background.Value, 0.5f, LerpEnum::NoAlpha);
+ case 2: return Color_t(255, 100, 100, bAlive ? 255 : 127).Lerp(Vars::Menu::Theme::Background.Value, 0.5f, LerpEnum::NoAlpha);
+ }
+ return Color_t(127, 127, 127, 255).Lerp(Vars::Menu::Theme::Background.Value, 0.5f, LerpEnum::NoAlpha);
+ };
auto fDrawPlayer = [&](const ListPlayer& tPlayer, int x, int y)
- {
- ImVec2 vOriginalPos = { !x ? GetStyle().WindowPadding.x : GetWindowWidth() / 2 + GetStyle().WindowPadding.x / 2, H::Draw.Scale(35 + 36 * y) };
-
- // background
- float flWidth = GetWindowWidth() / 2 - GetStyle().WindowPadding.x * 1.5f;
- float flHeight = H::Draw.Scale(28);
- ImColor tColor = ColorToVec(fGetTeamColor(tPlayer.m_iTeam, tPlayer.m_bAlive));
- ImVec2 vDrawPos = GetDrawPos() + vOriginalPos;
- GetWindowDrawList()->AddRectFilled(vDrawPos, { vDrawPos.x + flWidth, vDrawPos.y + flHeight }, tColor, H::Draw.Scale(4));
-
- // text + icons
- int lOffset = H::Draw.Scale(10);
- if (tPlayer.m_bLocal || F::Spectate.GetTarget(true) == tPlayer.m_iUserID || tPlayer.m_bFriend || tPlayer.m_bParty)
{
- lOffset += H::Draw.Scale(19);
- SetCursorPos({ vOriginalPos.x + H::Draw.Scale(7), vOriginalPos.y + H::Draw.Scale(6) });
- if (tPlayer.m_bLocal)
- IconImage(ICON_MD_PERSON);
- else if (F::Spectate.GetTarget(true) == tPlayer.m_iUserID)
- IconImage(ICON_MD_VISIBILITY);
- else if (tPlayer.m_bFriend)
- IconImage(ICON_MD_GROUP);
- else if (tPlayer.m_bParty)
- IconImage(ICON_MD_GROUPS);
- }
- SetCursorPos({ vOriginalPos.x + lOffset, vOriginalPos.y + H::Draw.Scale(7) });
- auto sName = TruncateText(tPlayer.m_sName, flWidth / 2 - lOffset);
- FText(sName.c_str());
- lOffset += FCalcTextSize(sName.c_str()).x + H::Draw.Scale(8);
+ ImVec2 vOriginalPos = { !x ? GetStyle().WindowPadding.x : GetWindowWidth() / 2 + GetStyle().WindowPadding.x / 2, H::Draw.Scale(35 + 36 * y) };
- // buttons
- bool bPopup = false;
+ // background
+ float flWidth = GetWindowWidth() / 2 - GetStyle().WindowPadding.x * 1.5f;
+ float flHeight = H::Draw.Scale(28);
+ ImColor tColor = ColorToVec(fGetTeamColor(tPlayer.m_iTeam, tPlayer.m_bAlive));
+ ImVec2 vDrawPos = GetDrawPos() + vOriginalPos;
+ GetWindowDrawList()->AddRectFilled(vDrawPos, { vDrawPos.x + flWidth, vDrawPos.y + flHeight }, tColor, H::Draw.Scale(4));
- if (!tPlayer.m_bFake)
- {
- // tag bar
- SetCursorPos({ vOriginalPos.x + lOffset, vOriginalPos.y });
- if (BeginChild(std::format("TagBar{}", tPlayer.m_iUserID).c_str(), { flWidth - lOffset - H::Draw.Scale(4), flHeight }, ImGuiWindowFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoBackground))
+ // text + icons
+ int lOffset = H::Draw.Scale(10);
+ if (tPlayer.m_bLocal || F::Spectate.GetTarget(true) == tPlayer.m_iUserID || tPlayer.m_bFriend || tPlayer.m_bParty)
{
- std::vector vLabels = {};
- std::vector> vTags = {};
- if (int iParty = tPlayer.m_iParty)
+ lOffset += H::Draw.Scale(19);
+ SetCursorPos({ vOriginalPos.x + H::Draw.Scale(7), vOriginalPos.y + H::Draw.Scale(6) });
+ if (tPlayer.m_bLocal)
+ IconImage(ICON_MD_PERSON);
+ else if (F::Spectate.GetTarget(true) == tPlayer.m_iUserID)
+ IconImage(ICON_MD_VISIBILITY);
+ else if (tPlayer.m_bFriend)
+ IconImage(ICON_MD_GROUP);
+ else if (tPlayer.m_bParty)
+ IconImage(ICON_MD_GROUPS);
+ }
+ SetCursorPos({ vOriginalPos.x + lOffset, vOriginalPos.y + H::Draw.Scale(7) });
+ auto sName = TruncateText(tPlayer.m_sName, flWidth / 2 - lOffset);
+ FText(sName.c_str());
+ lOffset += FCalcTextSize(sName.c_str()).x + H::Draw.Scale(8);
+
+ // buttons
+ bool bPopup = false;
+
+ if (!tPlayer.m_bFake)
+ {
+ // tag bar
+ SetCursorPos({ vOriginalPos.x + lOffset, vOriginalPos.y });
+ if (BeginChild(std::format("TagBar{}", tPlayer.m_iUserID).c_str(), { flWidth - lOffset - H::Draw.Scale(4), flHeight }, ImGuiWindowFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoBackground))
{
- auto pTag = &F::PlayerUtils.m_vTags[F::PlayerUtils.TagToIndex(PARTY_TAG)];
- if (!--iParty)
+ std::vector vLabels = {};
+ std::vector> vTags = {};
+ if (int iParty = tPlayer.m_iParty)
+ {
+ auto pTag = &F::PlayerUtils.m_vTags[F::PlayerUtils.TagToIndex(PARTY_TAG)];
+ if (!--iParty)
+ vTags.emplace_back(pTag, 0);
+ else
+ vLabels.emplace_back(std::format("{}: {}", pTag->m_sName, iParty), pTag->m_tColor.HueShift(iParty * 360.f / iPartyCount));
+ }
+ if (tPlayer.m_bF2P)
+ {
+ auto pTag = &F::PlayerUtils.m_vTags[F::PlayerUtils.TagToIndex(F2P_TAG)];
vTags.emplace_back(pTag, 0);
- else
- vLabels.emplace_back(std::format("{}: {}", pTag->m_sName, iParty), pTag->m_tColor.HueShift(iParty * 360.f / iPartyCount));
- }
- if (tPlayer.m_bF2P)
- {
- auto pTag = &F::PlayerUtils.m_vTags[F::PlayerUtils.TagToIndex(F2P_TAG)];
- vTags.emplace_back(pTag, 0);
- }
- for (auto& iID : F::PlayerUtils.GetPlayerTags(tPlayer.m_uAccountID))
- {
- if (auto pTag = F::PlayerUtils.GetTag(iID))
- vTags.emplace_back(pTag, iID);
- }
-
- PushFont(F::Render.FontSmall);
- const auto vDrawPos = GetDrawPos();
- float flTagOffset = 0;
- auto fDrawTag = [&](PriorityLabel_t& tTag, int iID)
- {
- ImColor tTagColor = ColorToVec(tTag.m_tColor);
- float flTagWidth = FCalcTextSize(tTag.m_sName.c_str()).x + H::Draw.Scale(!iID ? 10 : 25);
- float flTagHeight = H::Draw.Scale(20);
- ImVec2 vTagPos = { flTagOffset, H::Draw.Scale(4) };
-
- GetWindowDrawList()->AddRectFilled(vDrawPos + vTagPos, { vDrawPos.x + vTagPos.x + flTagWidth, vDrawPos.y + vTagPos.y + flTagHeight }, tTagColor, H::Draw.Scale(4));
- SetCursorPos({ vTagPos.x + H::Draw.Scale(5), vTagPos.y + H::Draw.Scale(3) });
- TextColored(VecToColor(tColor).Blend(tTag.m_tColor).IsColorBright() ? ImVec4(0, 0, 0, 1) : ImVec4(1, 1, 1, 1), tTag.m_sName.c_str());
- if (iID)
+ }
+ for (auto& iID : F::PlayerUtils.GetPlayerTags(tPlayer.m_uAccountID))
{
- SetCursorPos({ vTagPos.x + flTagWidth - H::Draw.Scale(22), vTagPos.y - H::Draw.Scale(2) });
- if (IconButton(ICON_MD_CANCEL))
- F::PlayerUtils.RemoveTag(tPlayer.m_uAccountID, iID, true, tPlayer.m_sName.c_str());
+ if (auto pTag = F::PlayerUtils.GetTag(iID))
+ vTags.emplace_back(pTag, iID);
}
- flTagOffset += flTagWidth + H::Draw.Scale(4);
- };
-
- for (auto& tTag : vLabels)
- fDrawTag(tTag, 0);
- for (auto& [pTag, iID] : vTags)
- fDrawTag(*pTag, iID);
- PopFont();
- } EndChild();
-
- bPopup = IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right);
- }
- SetCursorPos(vOriginalPos);
- Button(std::format("##{}", tPlayer.m_iUserID).c_str(), { flWidth, flHeight });
- bPopup |= IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right);
-
- // popups
- if (bPopup)
- OpenPopup(std::format("RightClicked{}", tPlayer.m_iUserID).c_str());
-
- if (FBeginPopup(std::format("RightClicked{}", tPlayer.m_iUserID).c_str()))
- {
- PushStyleVar(ImGuiStyleVar_ItemSpacing, { H::Draw.Scale(8), H::Draw.Scale(8) });
-
- if (!tPlayer.m_bFake)
- {
- if (FSelectable("Profile"))
- I::SteamFriends->ActivateGameOverlayToUser("steamid", CSteamID(tPlayer.m_uAccountID, k_EUniversePublic, k_EAccountTypeIndividual));
- if (FSelectable("History"))
- I::SteamFriends->ActivateGameOverlayToWebPage(std::format("https://steamhistory.net/id/{}", CSteamID(tPlayer.m_uAccountID, k_EUniversePublic, k_EAccountTypeIndividual).ConvertToUint64()).c_str());
- }
-
- if (FSelectable(F::Spectate.GetTarget(true) == tPlayer.m_iUserID ? "Unspectate" : "Spectate"))
- F::Spectate.SetTarget(tPlayer.m_iUserID);
-
- if (!I::EngineClient->IsPlayingDemo() && FBeginMenu("Votekick"))
- {
- if (FSelectable("No reason"))
- I::ClientState->SendStringCmd(std::format("callvote Kick \"{} other\"", tPlayer.m_iUserID).c_str());
- if (FSelectable("Cheating"))
- I::ClientState->SendStringCmd(std::format("callvote Kick \"{} cheating\"", tPlayer.m_iUserID).c_str());
- if (FSelectable("Idle"))
- I::ClientState->SendStringCmd(std::format("callvote Kick \"{} idle\"", tPlayer.m_iUserID).c_str());
- if (FSelectable("Scamming"))
- I::ClientState->SendStringCmd(std::format("callvote Kick \"{} scamming\"", tPlayer.m_iUserID).c_str());
-
- ImGui::EndMenu();
- }
-
- if (!tPlayer.m_bFake)
- {
- if (FBeginMenu("Add tag"))
- {
- for (auto it = F::PlayerUtils.m_vTags.begin(); it != F::PlayerUtils.m_vTags.end(); it++)
- {
- int iID = std::distance(F::PlayerUtils.m_vTags.begin(), it);
- auto& tTag = *it;
- if (!tTag.m_bAssignable || F::PlayerUtils.HasTag(tPlayer.m_uAccountID, iID))
- continue;
-
- auto imColor = ColorToVec(tTag.m_tColor);
- PushStyleColor(ImGuiCol_Text, imColor);
- imColor.x /= 3; imColor.y /= 3; imColor.z /= 3;
- if (FSelectable(tTag.m_sName.c_str(), imColor))
- F::PlayerUtils.AddTag(tPlayer.m_uAccountID, iID, true, tPlayer.m_sName.c_str());
- PopStyleColor();
- }
-
- ImGui::EndMenu();
- }
- if (FBeginMenu("Alias"))
- {
- bool bHasAlias = F::PlayerUtils.m_mPlayerAliases.contains(tPlayer.m_uAccountID);
- static std::string sInput = "";
-
- bool bEnter = FInputText("Alias...", sInput, H::Draw.Scale(150), ImGuiInputTextFlags_EnterReturnsTrue);
- if (!IsItemFocused())
- sInput = bHasAlias ? F::PlayerUtils.m_mPlayerAliases[tPlayer.m_uAccountID] : "";
- if (bEnter)
- {
- if (sInput.empty() && bHasAlias)
+ PushFont(F::Render.FontSmall);
+ const auto vDrawPos = GetDrawPos();
+ float flTagOffset = 0;
+ auto fDrawTag = [&](PriorityLabel_t& tTag, int iID)
{
- F::Output.AliasChanged(tPlayer.m_sName.c_str(), "Removed", F::PlayerUtils.m_mPlayerAliases[tPlayer.m_uAccountID].c_str());
+ ImColor tTagColor = ColorToVec(tTag.m_tColor);
+ float flTagWidth = FCalcTextSize(tTag.m_sName.c_str()).x + H::Draw.Scale(!iID ? 10 : 25);
+ float flTagHeight = H::Draw.Scale(20);
+ ImVec2 vTagPos = { flTagOffset, H::Draw.Scale(4) };
- F::PlayerUtils.m_mPlayerAliases.erase(tPlayer.m_uAccountID);
- F::PlayerUtils.m_bSave = true;
- }
- else if (!sInput.empty())
- {
- F::PlayerUtils.m_mPlayerAliases[tPlayer.m_uAccountID] = sInput;
- F::PlayerUtils.m_bSave = true;
-
- F::Output.AliasChanged(tPlayer.m_sName.c_str(), bHasAlias ? "Changed" : "Added", sInput.c_str());
- }
- }
-
- ImGui::EndMenu();
- }
- }
-
- if (Vars::Resolver::Enabled.Value && !tPlayer.m_bLocal && !I::EngineClient->IsPlayingDemo())
- {
- if (FBeginMenu("Set yaw"))
- {
- static std::vector> vYaws = {
- { "Auto", 0.f },
- { "Forward", 0.f },
- { "Left", 90.f },
- { "Right", -90.f },
- { "Backwards", 180.f }
- };
- for (auto& [sYaw, flValue] : vYaws)
- {
- if (FSelectable(sYaw))
- {
- switch (FNV1A::Hash32(sYaw))
+ GetWindowDrawList()->AddRectFilled(vDrawPos + vTagPos, { vDrawPos.x + vTagPos.x + flTagWidth, vDrawPos.y + vTagPos.y + flTagHeight }, tTagColor, H::Draw.Scale(4));
+ SetCursorPos({ vTagPos.x + H::Draw.Scale(5), vTagPos.y + H::Draw.Scale(3) });
+ TextColored(VecToColor(tColor).Blend(tTag.m_tColor).IsColorBright() ? ImVec4(0, 0, 0, 1) : ImVec4(1, 1, 1, 1), tTag.m_sName.c_str());
+ if (iID)
{
- case FNV1A::Hash32Const("Auto"):
- F::Resolver.SetYaw(tPlayer.m_iUserID, 0.f, true);
- break;
- default:
- F::Resolver.SetYaw(tPlayer.m_iUserID, flValue);
+ SetCursorPos({ vTagPos.x + flTagWidth - H::Draw.Scale(22), vTagPos.y - H::Draw.Scale(2) });
+ if (IconButton(ICON_MD_CANCEL))
+ F::PlayerUtils.RemoveTag(tPlayer.m_uAccountID, iID, true, tPlayer.m_sName.c_str());
+ }
+
+ flTagOffset += flTagWidth + H::Draw.Scale(4);
+ };
+
+ for (auto& tTag : vLabels)
+ fDrawTag(tTag, 0);
+ for (auto& [pTag, iID] : vTags)
+ fDrawTag(*pTag, iID);
+ PopFont();
+ } EndChild();
+
+ bPopup = IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right);
+ }
+ SetCursorPos(vOriginalPos);
+ Button(std::format("##{}", tPlayer.m_iUserID).c_str(), { flWidth, flHeight });
+ bPopup |= IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right);
+
+ // popups
+ if (bPopup)
+ OpenPopup(std::format("RightClicked{}", tPlayer.m_iUserID).c_str());
+
+ if (FBeginPopup(std::format("RightClicked{}", tPlayer.m_iUserID).c_str()))
+ {
+ PushStyleVar(ImGuiStyleVar_ItemSpacing, { H::Draw.Scale(8), H::Draw.Scale(8) });
+
+ if (!tPlayer.m_bFake)
+ {
+ if (FSelectable("Profile"))
+ I::SteamFriends->ActivateGameOverlayToUser("steamid", CSteamID(tPlayer.m_uAccountID, k_EUniversePublic, k_EAccountTypeIndividual));
+ if (FSelectable("History"))
+ I::SteamFriends->ActivateGameOverlayToWebPage(std::format("https://steamhistory.net/id/{}", CSteamID(tPlayer.m_uAccountID, k_EUniversePublic, k_EAccountTypeIndividual).ConvertToUint64()).c_str());
+ }
+
+ if (FSelectable(F::Spectate.GetTarget(true) == tPlayer.m_iUserID ? "Unspectate" : "Spectate"))
+ F::Spectate.SetTarget(tPlayer.m_iUserID);
+
+ if (!I::EngineClient->IsPlayingDemo() && FBeginMenu("Votekick"))
+ {
+ if (FSelectable("No reason"))
+ I::ClientState->SendStringCmd(std::format("callvote Kick \"{} other\"", tPlayer.m_iUserID).c_str());
+ if (FSelectable("Cheating"))
+ I::ClientState->SendStringCmd(std::format("callvote Kick \"{} cheating\"", tPlayer.m_iUserID).c_str());
+ if (FSelectable("Idle"))
+ I::ClientState->SendStringCmd(std::format("callvote Kick \"{} idle\"", tPlayer.m_iUserID).c_str());
+ if (FSelectable("Scamming"))
+ I::ClientState->SendStringCmd(std::format("callvote Kick \"{} scamming\"", tPlayer.m_iUserID).c_str());
+
+ ImGui::EndMenu();
+ }
+
+ if (!tPlayer.m_bFake)
+ {
+ if (FBeginMenu("Add tag"))
+ {
+ for (auto it = F::PlayerUtils.m_vTags.begin(); it != F::PlayerUtils.m_vTags.end(); it++)
+ {
+ int iID = std::distance(F::PlayerUtils.m_vTags.begin(), it);
+ auto& tTag = *it;
+ if (!tTag.m_bAssignable || F::PlayerUtils.HasTag(tPlayer.m_uAccountID, iID))
+ continue;
+
+ auto imColor = ColorToVec(tTag.m_tColor);
+ PushStyleColor(ImGuiCol_Text, imColor);
+ imColor.x /= 3; imColor.y /= 3; imColor.z /= 3;
+ if (FSelectable(tTag.m_sName.c_str(), imColor))
+ F::PlayerUtils.AddTag(tPlayer.m_uAccountID, iID, true, tPlayer.m_sName.c_str());
+ PopStyleColor();
+ }
+
+ ImGui::EndMenu();
+ }
+ if (FBeginMenu("Alias"))
+ {
+ bool bHasAlias = F::PlayerUtils.m_mPlayerAliases.contains(tPlayer.m_uAccountID);
+ static std::string sInput = "";
+
+ bool bEnter = FInputText("Alias...", sInput, H::Draw.Scale(150), ImGuiInputTextFlags_EnterReturnsTrue);
+ if (!IsItemFocused())
+ sInput = bHasAlias ? F::PlayerUtils.m_mPlayerAliases[tPlayer.m_uAccountID] : "";
+ if (bEnter)
+ {
+ if (sInput.empty() && bHasAlias)
+ {
+ F::Output.AliasChanged(tPlayer.m_sName.c_str(), "Removed", F::PlayerUtils.m_mPlayerAliases[tPlayer.m_uAccountID].c_str());
+
+ F::PlayerUtils.m_mPlayerAliases.erase(tPlayer.m_uAccountID);
+ F::PlayerUtils.m_bSave = true;
+ }
+ else if (!sInput.empty())
+ {
+ F::PlayerUtils.m_mPlayerAliases[tPlayer.m_uAccountID] = sInput;
+ F::PlayerUtils.m_bSave = true;
+
+ F::Output.AliasChanged(tPlayer.m_sName.c_str(), bHasAlias ? "Changed" : "Added", sInput.c_str());
}
}
- }
- ImGui::EndMenu();
+ ImGui::EndMenu();
+ }
}
- if (FBeginMenu("Set pitch"))
+
+ if (Vars::Resolver::Enabled.Value && !tPlayer.m_bLocal && !I::EngineClient->IsPlayingDemo())
{
- static std::vector> vPitches = {
- { "Auto", 0.f },
- { "Up", -90.f },
- { "Down", 90.f },
- { "Zero", 0.f },
- { "Inverse", 0.f }
- };
- for (auto& [sPitch, flValue] : vPitches)
+ if (FBeginMenu("Set yaw"))
{
- if (FSelectable(sPitch))
+ static std::vector> vYaws = {
+ { "Auto", 0.f },
+ { "Forward", 0.f },
+ { "Left", 90.f },
+ { "Right", -90.f },
+ { "Backwards", 180.f }
+ };
+ for (auto& [sYaw, flValue] : vYaws)
{
- switch (FNV1A::Hash32(sPitch))
+ if (FSelectable(sYaw))
{
- case FNV1A::Hash32Const("Auto"):
- F::Resolver.SetPitch(tPlayer.m_iUserID, 0.f, false, true);
- break;
- case FNV1A::Hash32Const("Inverse"):
- F::Resolver.SetPitch(tPlayer.m_iUserID, 0.f, true);
- break;
- default:
- F::Resolver.SetPitch(tPlayer.m_iUserID, flValue);
+ switch (FNV1A::Hash32(sYaw))
+ {
+ case FNV1A::Hash32Const("Auto"):
+ F::Resolver.SetYaw(tPlayer.m_iUserID, 0.f, true);
+ break;
+ default:
+ F::Resolver.SetYaw(tPlayer.m_iUserID, flValue);
+ }
}
}
- }
- ImGui::EndMenu();
- }
- if (FBeginMenu("Set view"))
- {
- static std::vector> vPitches = {
- { "Offset from static view", true },
- { "Offset from view to local", false }
- };
- for (auto& [sPitch, bValue] : vPitches)
+ ImGui::EndMenu();
+ }
+ if (FBeginMenu("Set pitch"))
{
- if (FSelectable(sPitch))
- F::Resolver.SetView(tPlayer.m_iUserID, bValue);
- }
+ static std::vector> vPitches = {
+ { "Auto", 0.f },
+ { "Up", -90.f },
+ { "Down", 90.f },
+ { "Zero", 0.f },
+ { "Inverse", 0.f }
+ };
+ for (auto& [sPitch, flValue] : vPitches)
+ {
+ if (FSelectable(sPitch))
+ {
+ switch (FNV1A::Hash32(sPitch))
+ {
+ case FNV1A::Hash32Const("Auto"):
+ F::Resolver.SetPitch(tPlayer.m_iUserID, 0.f, false, true);
+ break;
+ case FNV1A::Hash32Const("Inverse"):
+ F::Resolver.SetPitch(tPlayer.m_iUserID, 0.f, true);
+ break;
+ default:
+ F::Resolver.SetPitch(tPlayer.m_iUserID, flValue);
+ }
+ }
+ }
- ImGui::EndMenu();
- }
- if (FBeginMenu("Set minwalk"))
- {
- static std::vector> vPitches = {
- { "Minwalk on", true },
- { "Minwalk off", false }
- };
- for (auto& [sPitch, bValue] : vPitches)
+ ImGui::EndMenu();
+ }
+ if (FBeginMenu("Set view"))
{
- if (FSelectable(sPitch))
- F::Resolver.SetMinwalk(tPlayer.m_iUserID, bValue);
+ static std::vector> vPitches = {
+ { "Offset from static view", true },
+ { "Offset from view to local", false }
+ };
+ for (auto& [sPitch, bValue] : vPitches)
+ {
+ if (FSelectable(sPitch))
+ F::Resolver.SetView(tPlayer.m_iUserID, bValue);
+ }
+
+ ImGui::EndMenu();
}
+ if (FBeginMenu("Set minwalk"))
+ {
+ static std::vector> vPitches = {
+ { "Minwalk on", true },
+ { "Minwalk off", false }
+ };
+ for (auto& [sPitch, bValue] : vPitches)
+ {
+ if (FSelectable(sPitch))
+ F::Resolver.SetMinwalk(tPlayer.m_iUserID, bValue);
+ }
- ImGui::EndMenu();
+ ImGui::EndMenu();
+ }
}
- }
- if (mParties.contains(tPlayer.m_iParty))
- {
- Divider(H::Draw.Scale(1), 0);
-
- TextColored(F::Render.Inactive.Value, "Partied:");
- for (auto& pPlayer2 : mParties[tPlayer.m_iParty])
- TextColored(F::Render.Inactive.Value, pPlayer2->m_sName.c_str());
- }
-
- if (tPlayer.m_iLevel != -2)
- {
- Divider(H::Draw.Scale(1), 0);
-
- std::string sLevel = "T? L?";
- if (tPlayer.m_iLevel != -1)
+ if (mParties.contains(tPlayer.m_iParty))
{
- int iTier = std::max(ceilf(tPlayer.m_iLevel / 150.f), 1.f);
- int iLevel = ((tPlayer.m_iLevel - 1) % 150) + 1;
- sLevel = std::format("T{} L{}", iTier, iLevel);
- }
- TextColored(F::Render.Inactive.Value, sLevel.c_str());
- }
+ Divider(H::Draw.Scale(1), 0);
- PopStyleVar();
- EndPopup();
- }
- };
+ TextColored(F::Render.Inactive.Value, "Partied:");
+ for (auto& pPlayer2 : mParties[tPlayer.m_iParty])
+ TextColored(F::Render.Inactive.Value, pPlayer2->m_sName.c_str());
+ }
+
+ if (tPlayer.m_iLevel != -2)
+ {
+ Divider(H::Draw.Scale(1), 0);
+
+ std::string sLevel = "T? L?";
+ if (tPlayer.m_iLevel != -1)
+ {
+ int iTier = std::max(ceilf(tPlayer.m_iLevel / 150.f), 1.f);
+ int iLevel = ((tPlayer.m_iLevel - 1) % 150) + 1;
+ sLevel = std::format("T{} L{}", iTier, iLevel);
+ }
+ TextColored(F::Render.Inactive.Value, sLevel.c_str());
+ }
+
+ PopStyleVar();
+ EndPopup();
+ }
+ };
// display players
std::vector vBlu, vRed, vOther;
@@ -1716,155 +1721,155 @@ void CMenu::MenuLogs(int iTab)
} EndChild();
auto fDrawTag = [](std::vector::iterator it, PriorityLabel_t& _tTag, int y)
- {
- int _iID = std::distance(F::PlayerUtils.m_vTags.begin(), it);
-
- ImVec2 vOriginalPos = { !_tTag.m_bLabel ? GetStyle().WindowPadding.x : GetWindowWidth() * 2 / 3 + GetStyle().WindowPadding.x / 2, H::Draw.Scale(96 + 36 * y) };
-
- // background
- float flWidth = GetWindowWidth() * (_tTag.m_bLabel ? 1.f / 3 : 2.f / 3) - GetStyle().WindowPadding.x * 1.5f;
- float flHeight = H::Draw.Scale(28);
- ImColor tColor = ColorToVec(_tTag.m_tColor.Lerp(Vars::Menu::Theme::Background.Value, 0.5f, LerpEnum::NoAlpha));
- ImVec2 vDrawPos = GetDrawPos() + vOriginalPos;
- if (iID != _iID)
- GetWindowDrawList()->AddRectFilled(vDrawPos, { vDrawPos.x + flWidth, vDrawPos.y + flHeight }, tColor, H::Draw.Scale(4));
- else
{
- ImColor tColor2 = { tColor.Value.x * 1.1f, tColor.Value.y * 1.1f, tColor.Value.z * 1.1f, tColor.Value.w };
- GetWindowDrawList()->AddRectFilled(vDrawPos, { vDrawPos.x + flWidth, vDrawPos.y + flHeight }, tColor2, H::Draw.Scale(4));
+ int _iID = std::distance(F::PlayerUtils.m_vTags.begin(), it);
- tColor2 = ColorToVec(_tTag.m_tColor.Lerp(Vars::Menu::Theme::Background.Value, 0.25f, LerpEnum::NoAlpha));
- float flInset = H::Draw.Scale(0.5f) - 0.5f;
- GetWindowDrawList()->AddRect({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x - flInset + flWidth, vDrawPos.y - flInset + flHeight }, tColor2, H::Draw.Scale(4), ImDrawFlags_None, H::Draw.Scale());
- }
+ ImVec2 vOriginalPos = { !_tTag.m_bLabel ? GetStyle().WindowPadding.x : GetWindowWidth() * 2 / 3 + GetStyle().WindowPadding.x / 2, H::Draw.Scale(96 + 36 * y) };
- // text
- SetCursorPos({ vOriginalPos.x + H::Draw.Scale(9), vOriginalPos.y + H::Draw.Scale(7) });
- FText(TruncateText(_tTag.m_sName, _tTag.m_bLabel ? flWidth - H::Draw.Scale(38) : flWidth / 2 - H::Draw.Scale(20)).c_str());
-
- if (!_tTag.m_bLabel)
- {
- SetCursorPos({ vOriginalPos.x + flWidth / 2, vOriginalPos.y + H::Draw.Scale(7) });
- FText(std::format("{}", _tTag.m_iPriority).c_str());
- }
-
- // buttons / icons
- bool bDelete = false;
- if (!_tTag.m_bLocked)
- {
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(26), vOriginalPos.y + H::Draw.Scale(2) });
- bDelete = IconButton(ICON_MD_DELETE);
- }
- else
- {
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(22), vOriginalPos.y + H::Draw.Scale(6) });
- switch (F::PlayerUtils.IndexToTag(_iID))
+ // background
+ float flWidth = GetWindowWidth() * (_tTag.m_bLabel ? 1.f / 3 : 2.f / 3) - GetStyle().WindowPadding.x * 1.5f;
+ float flHeight = H::Draw.Scale(28);
+ ImColor tColor = ColorToVec(_tTag.m_tColor.Lerp(Vars::Menu::Theme::Background.Value, 0.5f, LerpEnum::NoAlpha));
+ ImVec2 vDrawPos = GetDrawPos() + vOriginalPos;
+ if (iID != _iID)
+ GetWindowDrawList()->AddRectFilled(vDrawPos, { vDrawPos.x + flWidth, vDrawPos.y + flHeight }, tColor, H::Draw.Scale(4));
+ else
{
- //case DEFAULT_TAG: // no image
- case IGNORED_TAG: IconImage(ICON_MD_DO_NOT_DISTURB); break;
- case CHEATER_TAG: IconImage(ICON_MD_FLAG); break;
- case FRIEND_TAG: IconImage(ICON_MD_GROUP); break;
- case PARTY_TAG: IconImage(ICON_MD_GROUPS); break;
- case F2P_TAG: IconImage(ICON_MD_MONEY_OFF); break;
+ ImColor tColor2 = { tColor.Value.x * 1.1f, tColor.Value.y * 1.1f, tColor.Value.z * 1.1f, tColor.Value.w };
+ GetWindowDrawList()->AddRectFilled(vDrawPos, { vDrawPos.x + flWidth, vDrawPos.y + flHeight }, tColor2, H::Draw.Scale(4));
+
+ tColor2 = ColorToVec(_tTag.m_tColor.Lerp(Vars::Menu::Theme::Background.Value, 0.25f, LerpEnum::NoAlpha));
+ float flInset = H::Draw.Scale(0.5f) - 0.5f;
+ GetWindowDrawList()->AddRect({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x - flInset + flWidth, vDrawPos.y - flInset + flHeight }, tColor2, H::Draw.Scale(4), ImDrawFlags_None, H::Draw.Scale());
}
- }
- SetCursorPos(vOriginalPos);
- bool bClicked = Button(std::format("##{}", _tTag.m_sName).c_str(), { flWidth, flHeight });
- bool bPopup = IsItemClicked(ImGuiMouseButton_Right);
-
- if (bClicked)
- {
- iID = _iID;
- tTag.m_sName = _tTag.m_sName;
- tTag.m_tColor = _tTag.m_tColor;
- tTag.m_iPriority = _tTag.m_iPriority;
- tTag.m_bLabel = _tTag.m_bLabel;
- }
- else if (bPopup)
- OpenPopup(std::format("RightClicked{}", _iID).c_str());
- else if (bDelete)
- OpenPopup(std::format("DeleteTag{}", _iID).c_str());
-
- if (FBeginPopup(std::format("RightClicked{}", _iID).c_str()))
- {
- PushStyleVar(ImGuiStyleVar_ItemSpacing, { H::Draw.Scale(8), 0 });
-
- auto& _tTag2 = *it;
- bool bSave = false;
+ // text
+ SetCursorPos({ vOriginalPos.x + H::Draw.Scale(9), vOriginalPos.y + H::Draw.Scale(7) });
+ FText(TruncateText(_tTag.m_sName, _tTag.m_bLabel ? flWidth - H::Draw.Scale(38) : flWidth / 2 - H::Draw.Scale(20)).c_str());
+ if (!_tTag.m_bLabel)
{
- static std::string sInput = "";
+ SetCursorPos({ vOriginalPos.x + flWidth / 2, vOriginalPos.y + H::Draw.Scale(7) });
+ FText(std::format("{}", _tTag.m_iPriority).c_str());
+ }
- bool bEnter = FInputText("Name...", sInput, H::Draw.Scale(284), ImGuiInputTextFlags_EnterReturnsTrue);
- if (!IsItemFocused())
- sInput = _tTag2.m_sName;
- if (bEnter)
+ // buttons / icons
+ bool bDelete = false;
+ if (!_tTag.m_bLocked)
+ {
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(26), vOriginalPos.y + H::Draw.Scale(2) });
+ bDelete = IconButton(ICON_MD_DELETE);
+ }
+ else
+ {
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(22), vOriginalPos.y + H::Draw.Scale(6) });
+ switch (F::PlayerUtils.IndexToTag(_iID))
{
- _tTag2.m_sName = sInput;
- bSave = true;
+ //case DEFAULT_TAG: // no image
+ case IGNORED_TAG: IconImage(ICON_MD_DO_NOT_DISTURB); break;
+ case CHEATER_TAG: IconImage(ICON_MD_FLAG); break;
+ case FRIEND_TAG: IconImage(ICON_MD_GROUP); break;
+ case PARTY_TAG: IconImage(ICON_MD_GROUPS); break;
+ case F2P_TAG: IconImage(ICON_MD_MONEY_OFF); break;
}
}
- PushDisabled(_iID == DEFAULT_TAG || _iID == IGNORED_TAG);
+ SetCursorPos(vOriginalPos);
+ bool bClicked = Button(std::format("##{}", _tTag.m_sName).c_str(), { flWidth, flHeight });
+ bool bPopup = IsItemClicked(ImGuiMouseButton_Right);
+
+ if (bClicked)
{
- int iLabel = Disabled ? 0 : _tTag2.m_bLabel;
- if (FDropdown("Type##", &iLabel, { "Priority", "Label" }))
- bSave = true;
- _tTag2.m_bLabel = iLabel;
- if (Disabled)
- _tTag2.m_bLabel = false;
+ iID = _iID;
+ tTag.m_sName = _tTag.m_sName;
+ tTag.m_tColor = _tTag.m_tColor;
+ tTag.m_iPriority = _tTag.m_iPriority;
+ tTag.m_bLabel = _tTag.m_bLabel;
}
- PopDisabled();
- if (FSlider("Priority##", &_tTag2.m_iPriority, -10, 10))
- bSave = true;
+ else if (bPopup)
+ OpenPopup(std::format("RightClicked{}", _iID).c_str());
+ else if (bDelete)
+ OpenPopup(std::format("DeleteTag{}", _iID).c_str());
- if (bSave)
- F::PlayerUtils.m_bSave = true;
-
- PopStyleVar();
- EndPopup();
- }
- else if (FBeginPopupModal(std::format("DeleteTag{}", _iID).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
- {
- FText(std::format("Do you really want to delete '{}'?", _tTag.m_sName).c_str());
-
- if (FButton("Yes", FButtonEnum::Left))
+ if (FBeginPopup(std::format("RightClicked{}", _iID).c_str()))
{
- F::PlayerUtils.m_vTags.erase(it);
- F::PlayerUtils.m_bSave = F::PlayerUtils.m_bSave = true;
+ PushStyleVar(ImGuiStyleVar_ItemSpacing, { H::Draw.Scale(8), 0 });
+
+ auto& _tTag2 = *it;
+ bool bSave = false;
- for (auto& vTags : F::PlayerUtils.m_mPlayerTags | std::views::values)
{
- for (auto it = vTags.begin(); it != vTags.end();)
+ static std::string sInput = "";
+
+ bool bEnter = FInputText("Name...", sInput, H::Draw.Scale(284), ImGuiInputTextFlags_EnterReturnsTrue);
+ if (!IsItemFocused())
+ sInput = _tTag2.m_sName;
+ if (bEnter)
{
- if (_iID == *it)
- vTags.erase(it);
- else
- {
- if (_iID < *it)
- (*it)--;
- it++;
- }
+ _tTag2.m_sName = sInput;
+ bSave = true;
}
}
- if (iID == _iID)
+ PushDisabled(_iID == DEFAULT_TAG || _iID == IGNORED_TAG);
{
- iID = -1;
- tTag = {};
+ int iLabel = Disabled ? 0 : _tTag2.m_bLabel;
+ if (FDropdown("Type##", &iLabel, { "Priority", "Label" }))
+ bSave = true;
+ _tTag2.m_bLabel = iLabel;
+ if (Disabled)
+ _tTag2.m_bLabel = false;
}
- else if (iID > _iID)
- iID--;
+ PopDisabled();
+ if (FSlider("Priority##", &_tTag2.m_iPriority, -10, 10))
+ bSave = true;
- CloseCurrentPopup();
+ if (bSave)
+ F::PlayerUtils.m_bSave = true;
+
+ PopStyleVar();
+ EndPopup();
}
- if (FButton("No", FButtonEnum::Right | FButtonEnum::SameLine))
- CloseCurrentPopup();
+ else if (FBeginPopupModal(std::format("DeleteTag{}", _iID).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
+ {
+ FText(std::format("Do you really want to delete '{}'?", _tTag.m_sName).c_str());
- EndPopup();
- }
- };
+ if (FButton("Yes", FButtonEnum::Left))
+ {
+ F::PlayerUtils.m_vTags.erase(it);
+ F::PlayerUtils.m_bSave = F::PlayerUtils.m_bSave = true;
+
+ for (auto& vTags : F::PlayerUtils.m_mPlayerTags | std::views::values)
+ {
+ for (auto it = vTags.begin(); it != vTags.end();)
+ {
+ if (_iID == *it)
+ vTags.erase(it);
+ else
+ {
+ if (_iID < *it)
+ (*it)--;
+ it++;
+ }
+ }
+ }
+
+ if (iID == _iID)
+ {
+ iID = -1;
+ tTag = {};
+ }
+ else if (iID > _iID)
+ iID--;
+
+ CloseCurrentPopup();
+ }
+ if (FButton("No", FButtonEnum::Right | FButtonEnum::SameLine))
+ CloseCurrentPopup();
+
+ EndPopup();
+ }
+ };
PushStyleColor(ImGuiCol_Text, F::Render.Inactive.Value);
SetCursorPos({ H::Draw.Scale(13), H::Draw.Scale(80) }); FText("Priorities");
@@ -1883,27 +1888,27 @@ void CMenu::MenuLogs(int iTab)
}
std::sort(vPriorities.begin(), vPriorities.end(), [&](const auto& a, const auto& b) -> bool
- {
- // override for default tag
- if (std::distance(F::PlayerUtils.m_vTags.begin(), a.first) == DEFAULT_TAG)
- return true;
- if (std::distance(F::PlayerUtils.m_vTags.begin(), b.first) == DEFAULT_TAG)
- return false;
+ {
+ // override for default tag
+ if (std::distance(F::PlayerUtils.m_vTags.begin(), a.first) == DEFAULT_TAG)
+ return true;
+ if (std::distance(F::PlayerUtils.m_vTags.begin(), b.first) == DEFAULT_TAG)
+ return false;
- // sort by priority if unequal
- if (a.second.m_iPriority != b.second.m_iPriority)
- return a.second.m_iPriority > b.second.m_iPriority;
+ // sort by priority if unequal
+ if (a.second.m_iPriority != b.second.m_iPriority)
+ return a.second.m_iPriority > b.second.m_iPriority;
- return a.second.m_sName < b.second.m_sName;
- });
+ return a.second.m_sName < b.second.m_sName;
+ });
std::sort(vLabels.begin(), vLabels.end(), [&](const auto& a, const auto& b) -> bool
- {
- // sort by priority if unequal
- if (a.second.m_iPriority != b.second.m_iPriority)
- return a.second.m_iPriority > b.second.m_iPriority;
+ {
+ // sort by priority if unequal
+ if (a.second.m_iPriority != b.second.m_iPriority)
+ return a.second.m_iPriority > b.second.m_iPriority;
- return a.second.m_sName < b.second.m_sName;
- });
+ return a.second.m_sName < b.second.m_sName;
+ });
// display tags
int iPriorities = 0, iLabels = 0;
@@ -2331,7 +2336,7 @@ void CMenu::MenuSettings(int iTab)
switch (iTab)
{
- // Settings
+ // Settings
case 0:
{
if (BeginTable("ConfigSettingsTable", 2))
@@ -2349,152 +2354,152 @@ void CMenu::MenuSettings(int iTab)
*/
auto fDrawConfigs = [](std::string& sStaticName, bool bVisual = false)
- {
- auto& sPath = !bVisual ? F::Configs.m_sConfigPath : F::Configs.m_sVisualsPath;
- auto& sConfig = !bVisual ? F::Configs.m_sCurrentConfig : F::Configs.m_sCurrentVisuals;
- auto sType = !bVisual ? "Config" : "Visual";
- bool bNoSave = GetAsyncKeyState(VK_SHIFT) & 0x8000;
-
- FSDropdown("Name", &sStaticName, {}, FSDropdownEnum::AutoUpdate, -H::Draw.Unscale(FCalcTextSize("CREATE").x + FCalcTextSize("FOLDER").x) - 72);
- PushDisabled(sStaticName.empty());
{
- if (FButton("Create", FButtonEnum::Fit | FButtonEnum::SameLine, { 0, 40 }))
+ auto& sPath = !bVisual ? F::Configs.m_sConfigPath : F::Configs.m_sVisualsPath;
+ auto& sConfig = !bVisual ? F::Configs.m_sCurrentConfig : F::Configs.m_sCurrentVisuals;
+ auto sType = !bVisual ? "Config" : "Visual";
+ bool bNoSave = GetAsyncKeyState(VK_SHIFT) & 0x8000;
+
+ FSDropdown("Name", &sStaticName, {}, FSDropdownEnum::AutoUpdate, -H::Draw.Unscale(FCalcTextSize("CREATE").x + FCalcTextSize("FOLDER").x) - 72);
+ PushDisabled(sStaticName.empty());
{
- if (!std::filesystem::exists(sPath + sStaticName))
+ if (FButton("Create", FButtonEnum::Fit | FButtonEnum::SameLine, { 0, 40 }))
{
- if (!bVisual)
- F::Configs.SaveConfig(sStaticName);
- else
- F::Configs.SaveVisual(sStaticName);
+ if (!std::filesystem::exists(sPath + sStaticName))
+ {
+ if (!bVisual)
+ F::Configs.SaveConfig(sStaticName);
+ else
+ F::Configs.SaveVisual(sStaticName);
+ }
+ sStaticName.clear();
}
- sStaticName.clear();
}
- }
- PopDisabled();
- if (FButton("Folder", FButtonEnum::Fit | FButtonEnum::SameLine, { 0, 40 }))
- ShellExecuteA(NULL, NULL, sPath.c_str(), NULL, NULL, SW_SHOWNORMAL);
- vRowSizes.clear();
+ PopDisabled();
+ if (FButton("Folder", FButtonEnum::Fit | FButtonEnum::SameLine, { 0, 40 }))
+ ShellExecuteA(NULL, NULL, sPath.c_str(), NULL, NULL, SW_SHOWNORMAL);
+ vRowSizes.clear();
- std::vector> vConfigs = {};
- bool bDefaultFound = false;
- for (auto& tEntry : std::filesystem::directory_iterator(sPath))
- {
- if (!tEntry.is_regular_file() || tEntry.path().extension() != F::Configs.m_sConfigExtension)
- continue;
-
- std::string sName = tEntry.path().filename().string();
- sName.erase(sName.end() - F::Configs.m_sConfigExtension.size(), sName.end());
- if (FNV1A::Hash32(sName.c_str()) == FNV1A::Hash32Const("default"))
- bDefaultFound = true;
-
- vConfigs.emplace_back(tEntry, sName);
- }
- if (!bVisual)
- {
- if (!bDefaultFound)
- F::Configs.SaveConfig("default");
- std::sort(vConfigs.begin(), vConfigs.end(), [&](const auto& a, const auto& b) -> bool
+ std::vector> vConfigs = {};
+ bool bDefaultFound = false;
+ for (auto& tEntry : std::filesystem::directory_iterator(sPath))
{
- // override for default config
- if (FNV1A::Hash32(a.second.c_str()) == FNV1A::Hash32Const("default"))
- return true;
- if (FNV1A::Hash32(b.second.c_str()) == FNV1A::Hash32Const("default"))
- return false;
+ if (!tEntry.is_regular_file() || tEntry.path().extension() != F::Configs.m_sConfigExtension)
+ continue;
- return a.second < b.second;
- });
- }
+ std::string sName = tEntry.path().filename().string();
+ sName.erase(sName.end() - F::Configs.m_sConfigExtension.size(), sName.end());
+ if (FNV1A::Hash32(sName.c_str()) == FNV1A::Hash32Const("default"))
+ bDefaultFound = true;
- for (auto& [entry, sConfigName] : vConfigs)
- {
- bool bCurrentConfig = FNV1A::Hash32(sConfigName.c_str()) == FNV1A::Hash32(sConfig.c_str());
- ImVec2 vOriginalPos = GetCursorPos();
-
- SetCursorPos({ vOriginalPos.x + H::Draw.Scale(2), vOriginalPos.y + H::Draw.Scale(9) });
- bool bLoad = IconButton(bCurrentConfig ? ICON_MD_REFRESH : ICON_MD_DOWNLOAD);
- FTooltip(ICON_MD_ADD ICON_MD_FILE_UPLOAD_OFF, bNoSave && IsItemHovered(), 300.f, F::Render.IconFont);
-
- SetCursorPos({ H::Draw.Scale(43), vOriginalPos.y + H::Draw.Scale(14) });
- TextColored(bCurrentConfig ? F::Render.Active.Value : F::Render.Inactive.Value, TruncateText(sConfigName, GetWindowWidth() - GetStyle().WindowPadding.x * 2 - H::Draw.Scale(80)).c_str());
-
- int iOffset = 9;
- SetCursorPos({ GetWindowWidth() - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(9) });
- bool bDelete = IconButton(ICON_MD_DELETE);
-
- SetCursorPos({ GetWindowWidth() - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(9) });
- bool bSave = IconButton(ICON_MD_SAVE);
- FTooltip(ICON_MD_ADD ICON_MD_FILE_DOWNLOAD_OFF, bNoSave && IsItemHovered(), 300.f, F::Render.IconFont);
-
- if (bLoad)
- {
- if (!bVisual)
- F::Configs.LoadConfig(sConfigName);
- else
- F::Configs.LoadVisual(sConfigName);
+ vConfigs.emplace_back(tEntry, sName);
}
- else if (bSave)
+ if (!bVisual)
{
- if (!bCurrentConfig || !bVisual && !F::Configs.m_sCurrentVisuals.empty())
- OpenPopup(std::format("Save{}{}", sType, sConfigName).c_str());
- else if (!bVisual)
- F::Configs.SaveConfig(sConfigName);
- else
- F::Configs.SaveVisual(sConfigName);
+ if (!bDefaultFound)
+ F::Configs.SaveConfig("default");
+ std::sort(vConfigs.begin(), vConfigs.end(), [&](const auto& a, const auto& b) -> bool
+ {
+ // override for default config
+ if (FNV1A::Hash32(a.second.c_str()) == FNV1A::Hash32Const("default"))
+ return true;
+ if (FNV1A::Hash32(b.second.c_str()) == FNV1A::Hash32Const("default"))
+ return false;
+
+ return a.second < b.second;
+ });
}
- else if (bDelete)
- OpenPopup(std::format("Remove{}{}", sType, sConfigName).c_str());
- if (FBeginPopupModal(std::format("Save{}{}", sType, sConfigName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
+ for (auto& [entry, sConfigName] : vConfigs)
{
- FText(std::format("Do you really want to override '{}'?", sConfigName).c_str());
+ bool bCurrentConfig = FNV1A::Hash32(sConfigName.c_str()) == FNV1A::Hash32(sConfig.c_str());
+ ImVec2 vOriginalPos = GetCursorPos();
- if (FButton("Yes, override", FButtonEnum::Left))
+ SetCursorPos({ vOriginalPos.x + H::Draw.Scale(2), vOriginalPos.y + H::Draw.Scale(9) });
+ bool bLoad = IconButton(bCurrentConfig ? ICON_MD_REFRESH : ICON_MD_DOWNLOAD);
+ FTooltip(ICON_MD_ADD ICON_MD_FILE_UPLOAD_OFF, bNoSave && IsItemHovered(), 300.f, F::Render.IconFont);
+
+ SetCursorPos({ H::Draw.Scale(43), vOriginalPos.y + H::Draw.Scale(14) });
+ TextColored(bCurrentConfig ? F::Render.Active.Value : F::Render.Inactive.Value, TruncateText(sConfigName, GetWindowWidth() - GetStyle().WindowPadding.x * 2 - H::Draw.Scale(80)).c_str());
+
+ int iOffset = 9;
+ SetCursorPos({ GetWindowWidth() - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(9) });
+ bool bDelete = IconButton(ICON_MD_DELETE);
+
+ SetCursorPos({ GetWindowWidth() - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(9) });
+ bool bSave = IconButton(ICON_MD_SAVE);
+ FTooltip(ICON_MD_ADD ICON_MD_FILE_DOWNLOAD_OFF, bNoSave && IsItemHovered(), 300.f, F::Render.IconFont);
+
+ if (bLoad)
{
if (!bVisual)
+ F::Configs.LoadConfig(sConfigName);
+ else
+ F::Configs.LoadVisual(sConfigName);
+ }
+ else if (bSave)
+ {
+ if (!bCurrentConfig || !bVisual && !F::Configs.m_sCurrentVisuals.empty())
+ OpenPopup(std::format("Save{}{}", sType, sConfigName).c_str());
+ else if (!bVisual)
F::Configs.SaveConfig(sConfigName);
else
F::Configs.SaveVisual(sConfigName);
- CloseCurrentPopup();
}
- if (FButton("No", FButtonEnum::Right | FButtonEnum::SameLine))
- CloseCurrentPopup();
+ else if (bDelete)
+ OpenPopup(std::format("Remove{}{}", sType, sConfigName).c_str());
- EndPopup();
- }
- else if (FBeginPopupModal(std::format("Remove{}{}", sType, sConfigName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
- {
- FText(std::format("Do you really want to remove '{}'?", sConfigName).c_str());
-
- PushDisabled(!bVisual && FNV1A::Hash32(sConfigName.c_str()) == FNV1A::Hash32Const("default"));
+ if (FBeginPopupModal(std::format("Save{}{}", sType, sConfigName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
{
- if (FButton("Yes, delete", FButtonEnum::Fit))
+ FText(std::format("Do you really want to override '{}'?", sConfigName).c_str());
+
+ if (FButton("Yes, override", FButtonEnum::Left))
{
if (!bVisual)
- F::Configs.DeleteConfig(sConfigName);
+ F::Configs.SaveConfig(sConfigName);
else
- F::Configs.DeleteVisual(sConfigName);
+ F::Configs.SaveVisual(sConfigName);
CloseCurrentPopup();
}
+ if (FButton("No", FButtonEnum::Right | FButtonEnum::SameLine))
+ CloseCurrentPopup();
+
+ EndPopup();
}
- PopDisabled();
- if (FButton("Yes, reset", FButtonEnum::Fit | FButtonEnum::SameLine))
+ else if (FBeginPopupModal(std::format("Remove{}{}", sType, sConfigName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
{
- if (!bVisual)
- F::Configs.ResetConfig(sConfigName);
- else
- F::Configs.ResetVisual(sConfigName);
- CloseCurrentPopup();
+ FText(std::format("Do you really want to remove '{}'?", sConfigName).c_str());
+
+ PushDisabled(!bVisual && FNV1A::Hash32(sConfigName.c_str()) == FNV1A::Hash32Const("default"));
+ {
+ if (FButton("Yes, delete", FButtonEnum::Fit))
+ {
+ if (!bVisual)
+ F::Configs.DeleteConfig(sConfigName);
+ else
+ F::Configs.DeleteVisual(sConfigName);
+ CloseCurrentPopup();
+ }
+ }
+ PopDisabled();
+ if (FButton("Yes, reset", FButtonEnum::Fit | FButtonEnum::SameLine))
+ {
+ if (!bVisual)
+ F::Configs.ResetConfig(sConfigName);
+ else
+ F::Configs.ResetVisual(sConfigName);
+ CloseCurrentPopup();
+ }
+ if (FButton("No", FButtonEnum::Fit | FButtonEnum::SameLine))
+ CloseCurrentPopup();
+
+ EndPopup();
}
- if (FButton("No", FButtonEnum::Fit | FButtonEnum::SameLine))
- CloseCurrentPopup();
- EndPopup();
+ SetCursorPos(vOriginalPos); DebugDummy({ 0, H::Draw.Scale(28) });
}
-
- SetCursorPos(vOriginalPos); DebugDummy({ 0, H::Draw.Scale(28) });
- }
- DebugDummy({ 0, H::Draw.Scale(7) });
- };
+ DebugDummy({ 0, H::Draw.Scale(7) });
+ };
/* Column 1 */
TableNextColumn();
@@ -2618,38 +2623,38 @@ void CMenu::MenuSettings(int iTab)
PopStyleColor();
auto fNumberToIndex = [](int iNumber, int iLayer)
- {
- int iIndex = -1, i = -1;
-
- std::unordered_map mBinds = {};
- std::function fGetBinds = [&](int iParent)
{
- for (int _iBind = 0; _iBind < F::Binds.m_vBinds.size(); _iBind++)
- {
- auto& _tBind = F::Binds.m_vBinds[_iBind];
- if (iParent != _tBind.m_iParent || mBinds.contains(_iBind))
- continue;
+ int iIndex = -1, i = -1;
- mBinds[_iBind];
+ std::unordered_map mBinds = {};
+ std::function fGetBinds = [&](int iParent)
+ {
+ for (int _iBind = 0; _iBind < F::Binds.m_vBinds.size(); _iBind++)
+ {
+ auto& _tBind = F::Binds.m_vBinds[_iBind];
+ if (iParent != _tBind.m_iParent || mBinds.contains(_iBind))
+ continue;
- i++;
- //if (iParent == iLayer && iNumber >= i)
- if (iIndex == -1 && iParent == iLayer && iNumber <= i)
- iIndex = _iBind;
- fGetBinds(_iBind);
- }
+ mBinds[_iBind];
+
+ i++;
+ //if (iParent == iLayer && iNumber >= i)
+ if (iIndex == -1 && iParent == iLayer && iNumber <= i)
+ iIndex = _iBind;
+ fGetBinds(_iBind);
+ }
+ };
+ fGetBinds(DEFAULT_BIND);
+
+ return iIndex;
};
- fGetBinds(DEFAULT_BIND);
-
- return iIndex;
- };
auto fPositionToIndex = [&](ImVec2 vPos, int iLayer = DEFAULT_BIND)
- {
- int iIndex = floorf((vPos.y - GetCursorPosY() - H::Draw.Scale(4)) / H::Draw.Scale(36));
- iIndex = std::clamp(iIndex, 0, int(F::Binds.m_vBinds.size() - 1));
- iIndex = fNumberToIndex(iIndex, iLayer);
- return iIndex;
- };
+ {
+ int iIndex = floorf((vPos.y - GetCursorPosY() - H::Draw.Scale(4)) / H::Draw.Scale(36));
+ iIndex = std::clamp(iIndex, 0, int(F::Binds.m_vBinds.size() - 1));
+ iIndex = fNumberToIndex(iIndex, iLayer);
+ return iIndex;
+ };
static int iDragging = -1, iLayer = DEFAULT_BIND;
if (!IsMouseDown(ImGuiMouseButton_Left))
@@ -2666,239 +2671,239 @@ void CMenu::MenuSettings(int iTab)
std::unordered_map mBinds = {};
std::function fGetBinds = [&](int iParent, int x)
- {
- for (int _iBind = 0; _iBind < F::Binds.m_vBinds.size(); _iBind++)
{
- auto& _tBind = F::Binds.m_vBinds[_iBind];
- if (iParent != DEFAULT_BIND - 1 && iParent != _tBind.m_iParent || mBinds.contains(_iBind))
- continue;
-
- mBinds[_iBind];
-
- std::string sType; std::string sInfo;
- switch (_tBind.m_iType)
+ for (int _iBind = 0; _iBind < F::Binds.m_vBinds.size(); _iBind++)
{
- case BindEnum::Key:
- switch (_tBind.m_iInfo)
- {
- case BindEnum::KeyEnum::Hold: { sType = "hold"; break; }
- case BindEnum::KeyEnum::Toggle: { sType = "toggle"; break; }
- case BindEnum::KeyEnum::DoubleClick: { sType = "double"; break; }
- }
- sInfo = VK2STR(_tBind.m_iKey);
- break;
- case BindEnum::Class:
- sType = "class";
- switch (_tBind.m_iInfo)
- {
- case BindEnum::ClassEnum::Scout: { sInfo = "scout"; break; }
- case BindEnum::ClassEnum::Soldier: { sInfo = "soldier"; break; }
- case BindEnum::ClassEnum::Pyro: { sInfo = "pyro"; break; }
- case BindEnum::ClassEnum::Demoman: { sInfo = "demoman"; break; }
- case BindEnum::ClassEnum::Heavy: { sInfo = "heavy"; break; }
- case BindEnum::ClassEnum::Engineer: { sInfo = "engineer"; break; }
- case BindEnum::ClassEnum::Medic: { sInfo = "medic"; break; }
- case BindEnum::ClassEnum::Sniper: { sInfo = "sniper"; break; }
- case BindEnum::ClassEnum::Spy: { sInfo = "spy"; break; }
- }
- break;
- case BindEnum::WeaponType:
- sType = "weapon";
- switch (_tBind.m_iInfo)
- {
- case BindEnum::WeaponTypeEnum::Hitscan: { sInfo = "hitscan"; break; }
- case BindEnum::WeaponTypeEnum::Projectile: { sInfo = "projectile"; break; }
- case BindEnum::WeaponTypeEnum::Melee: { sInfo = "melee"; break; }
- case BindEnum::WeaponTypeEnum::Throwable: { sInfo = "throwable"; break; }
- }
- break;
- case BindEnum::ItemSlot:
- sType = "slot";
- sInfo = std::format("{}", _tBind.m_iInfo + 1);
- break;
- case BindEnum::Misc:
- switch (_tBind.m_iInfo)
- {
- case BindEnum::MiscEnum::Spectated:
- case BindEnum::MiscEnum::SpectatedFirst:
- case BindEnum::MiscEnum::SpectatedThird:
- sType = "spectated";
- switch (_tBind.m_iInfo)
- {
- case BindEnum::MiscEnum::Spectated: { sInfo = "any"; break; }
- case BindEnum::MiscEnum::SpectatedFirst: { sInfo = "1st"; break; }
- case BindEnum::MiscEnum::SpectatedThird: { sInfo = "3rd"; break; }
- }
- break;
- case BindEnum::MiscEnum::Zoomed:
- case BindEnum::MiscEnum::Aiming:
- sType = "cond";
- switch (_tBind.m_iInfo)
- {
- case BindEnum::MiscEnum::Zoomed: { sInfo = "zoomed"; break; }
- case BindEnum::MiscEnum::Aiming: { sInfo = "aiming"; break; }
- }
- break;
- }
- break;
- }
- if (_tBind.m_bNot && (_tBind.m_iType != BindEnum::Key || _tBind.m_iInfo == BindEnum::KeyEnum::Hold))
- sType = std::format("not {}", sType);
+ auto& _tBind = F::Binds.m_vBinds[_iBind];
+ if (iParent != DEFAULT_BIND - 1 && iParent != _tBind.m_iParent || mBinds.contains(_iBind))
+ continue;
- ImVec2 vOriginalPos = { H::Draw.Scale(8) + H::Draw.Scale(28) * std::min(x, 3), GetCursorPosY() + H::Draw.Scale(8) };
+ mBinds[_iBind];
- // background
- float flWidth = GetWindowWidth() - GetStyle().WindowPadding.x * 2 - H::Draw.Scale(28) * std::min(x, 3);
- float flHeight = H::Draw.Scale(28);
- ImVec2 vDrawPos = GetDrawPos() + vOriginalPos;
- if (iBind != _iBind)
- GetWindowDrawList()->AddRectFilled(vDrawPos, { vDrawPos.x + flWidth, vDrawPos.y + flHeight }, F::Render.Background1p5, H::Draw.Scale(4));
- else
- {
- ImColor tColor = F::Render.Background1p5L;
- GetWindowDrawList()->AddRectFilled(vDrawPos, { vDrawPos.x + flWidth, vDrawPos.y + flHeight }, tColor, H::Draw.Scale(4));
-
- tColor = ColorToVec((VecToColor(F::Render.Background1p5)).Lerp({ 127, 127, 127 }, 1.f / 9, LerpEnum::NoAlpha));
- float flInset = H::Draw.Scale(0.5f) - 0.5f;
- GetWindowDrawList()->AddRect({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x - flInset + flWidth, vDrawPos.y - flInset + flHeight }, tColor, H::Draw.Scale(4), ImDrawFlags_None, H::Draw.Scale());
- }
-
- // text
- if (x > 3)
- { // don't indent too much
- auto sText = std::format("-> {}", x);
- SetCursorPos({ vOriginalPos.x - FCalcTextSize(sText.c_str()).x - H::Draw.Scale(10), vOriginalPos.y + H::Draw.Scale(7) });
- FText(sText.c_str());
- }
-
- float flTextWidth = flWidth - H::Draw.Scale(127);
- PushTransparent(!F::Binds.WillBeEnabled(_iBind), true);
-
- SetCursorPos({ vOriginalPos.x + H::Draw.Scale(9), vOriginalPos.y + H::Draw.Scale(7) });
- FText(TruncateText(_tBind.m_sName, flTextWidth * (1.f / 3) - H::Draw.Scale(20)).c_str());
-
- SetCursorPos({ vOriginalPos.x + flTextWidth * (1.f / 3), vOriginalPos.y + H::Draw.Scale(7) });
- FText(sType.c_str());
-
- SetCursorPos({ vOriginalPos.x + flTextWidth * (2.f / 3), vOriginalPos.y + H::Draw.Scale(7) });
- FText(sInfo.c_str());
-
- // buttons
- int iOffset = 1;
-
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(2) });
- bool bDelete = IconButton(ICON_MD_DELETE);
-
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(2) });
- if (IconButton(ICON_MD_EDIT))
- CurrentBind = CurrentBind != _iBind ? _iBind : DEFAULT_BIND;
-
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(2) });
- if (IconButton(!_tBind.m_bNot ? ICON_MD_CODE : ICON_MD_CODE_OFF))
- _tBind.m_bNot = !_tBind.m_bNot;
-
- PushTransparent(Transparent || _tBind.m_iVisibility == BindVisibilityEnum::Hidden, true);
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(2) });
- if (IconButton(_tBind.m_iVisibility == BindVisibilityEnum::Always ? ICON_MD_VISIBILITY : ICON_MD_VISIBILITY_OFF))
- _tBind.m_iVisibility = (_tBind.m_iVisibility + 1) % 3;
- PopTransparent(1, 1);
-
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(2) });
- if (IconButton(_tBind.m_bEnabled ? ICON_MD_TOGGLE_ON : ICON_MD_TOGGLE_OFF))
- _tBind.m_bEnabled = !_tBind.m_bEnabled;
-
- SetCursorPos(vOriginalPos);
- bool bClicked = Button(std::format("##{}", _iBind).c_str(), { flWidth, flHeight });
- bool bPopup = IsItemClicked(ImGuiMouseButton_Right);
-
- PopTransparent(1, 1);
-
- if (bClicked)
- {
- if (!bParent)
- {
- iBind = _iBind;
- tBind = _tBind;
- }
- else
- {
- bParent = false;
- tBind.m_iParent = _iBind;
-
- // make sure bind can't be parented to itself or any of its children
- int _iBind2 = _iBind;
- Bind_t _tBind2;
- while (F::Binds.GetBind(_iBind2, &_tBind2))
- {
- if (_iBind2 == iBind)
- tBind.m_iParent = DEFAULT_BIND;
- _iBind2 = _tBind2.m_iParent;
- }
- }
- }
- else if (bPopup)
- OpenPopup(std::format("RightClicked{}", _iBind).c_str());
- else if (iDragging == -1 && IsItemHovered() && IsMouseDown(ImGuiMouseButton_Left))
- iDragging = _iBind, iLayer = iParent;
- else if (bDelete)
- {
- if (U::KeyHandler.Down(VK_SHIFT)) // allow user to quickly remove binds
- F::Binds.RemoveBind(_iBind);
- else
- OpenPopup(std::format("DeleteBind{}", _iBind).c_str());
- }
-
- if (FBeginPopup(std::format("RightClicked{}", _iBind).c_str()))
- {
- PushStyleVar(ImGuiStyleVar_ItemSpacing, { H::Draw.Scale(8), 0 });
-
- {
- static std::string sInput = "";
-
- bool bEnter = FInputText("Name...", sInput, H::Draw.Scale(284), ImGuiInputTextFlags_EnterReturnsTrue);
- if (!IsItemFocused())
- sInput = _tBind.m_sName;
- if (bEnter)
- _tBind.m_sName = sInput;
- }
-
- FDropdown("Type", &_tBind.m_iType, { "Key", "Class", "Weapon type", "Item slot", "Misc" }, {}, FDropdownEnum::Left);
+ std::string sType; std::string sInfo;
switch (_tBind.m_iType)
{
- case BindEnum::Key: FDropdown("Behavior", &_tBind.m_iInfo, { "Hold", "Toggle", "Double click" }, {}, FDropdownEnum::Right); break;
- case BindEnum::Class: FDropdown("Class", &_tBind.m_iInfo, { "Scout", "Soldier", "Pyro", "Demoman", "Heavy", "Engineer", "Medic", "Sniper", "Spy" }, {}, FDropdownEnum::Right); break;
- case BindEnum::WeaponType: FDropdown("Weapon type", &_tBind.m_iInfo, { "Hitscan", "Projectile", "Melee", "Throwable" }, {}, FDropdownEnum::Right); break;
- case BindEnum::ItemSlot: FDropdown("Item slot", &_tBind.m_iInfo, { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, {}, FDropdownEnum::Right); break;
- case BindEnum::Misc: FDropdown("Misc", &_tBind.m_iInfo, { "Spectated", "Spectated 1st", "Spectated 3rd", "##Divider", "Zoomed", "Aiming" }, {}, FDropdownEnum::Right); break;
+ case BindEnum::Key:
+ switch (_tBind.m_iInfo)
+ {
+ case BindEnum::KeyEnum::Hold: { sType = "hold"; break; }
+ case BindEnum::KeyEnum::Toggle: { sType = "toggle"; break; }
+ case BindEnum::KeyEnum::DoubleClick: { sType = "double"; break; }
+ }
+ sInfo = VK2STR(_tBind.m_iKey);
+ break;
+ case BindEnum::Class:
+ sType = "class";
+ switch (_tBind.m_iInfo)
+ {
+ case BindEnum::ClassEnum::Scout: { sInfo = "scout"; break; }
+ case BindEnum::ClassEnum::Soldier: { sInfo = "soldier"; break; }
+ case BindEnum::ClassEnum::Pyro: { sInfo = "pyro"; break; }
+ case BindEnum::ClassEnum::Demoman: { sInfo = "demoman"; break; }
+ case BindEnum::ClassEnum::Heavy: { sInfo = "heavy"; break; }
+ case BindEnum::ClassEnum::Engineer: { sInfo = "engineer"; break; }
+ case BindEnum::ClassEnum::Medic: { sInfo = "medic"; break; }
+ case BindEnum::ClassEnum::Sniper: { sInfo = "sniper"; break; }
+ case BindEnum::ClassEnum::Spy: { sInfo = "spy"; break; }
+ }
+ break;
+ case BindEnum::WeaponType:
+ sType = "weapon";
+ switch (_tBind.m_iInfo)
+ {
+ case BindEnum::WeaponTypeEnum::Hitscan: { sInfo = "hitscan"; break; }
+ case BindEnum::WeaponTypeEnum::Projectile: { sInfo = "projectile"; break; }
+ case BindEnum::WeaponTypeEnum::Melee: { sInfo = "melee"; break; }
+ case BindEnum::WeaponTypeEnum::Throwable: { sInfo = "throwable"; break; }
+ }
+ break;
+ case BindEnum::ItemSlot:
+ sType = "slot";
+ sInfo = std::format("{}", _tBind.m_iInfo + 1);
+ break;
+ case BindEnum::Misc:
+ switch (_tBind.m_iInfo)
+ {
+ case BindEnum::MiscEnum::Spectated:
+ case BindEnum::MiscEnum::SpectatedFirst:
+ case BindEnum::MiscEnum::SpectatedThird:
+ sType = "spectated";
+ switch (_tBind.m_iInfo)
+ {
+ case BindEnum::MiscEnum::Spectated: { sInfo = "any"; break; }
+ case BindEnum::MiscEnum::SpectatedFirst: { sInfo = "1st"; break; }
+ case BindEnum::MiscEnum::SpectatedThird: { sInfo = "3rd"; break; }
+ }
+ break;
+ case BindEnum::MiscEnum::Zoomed:
+ case BindEnum::MiscEnum::Aiming:
+ sType = "cond";
+ switch (_tBind.m_iInfo)
+ {
+ case BindEnum::MiscEnum::Zoomed: { sInfo = "zoomed"; break; }
+ case BindEnum::MiscEnum::Aiming: { sInfo = "aiming"; break; }
+ }
+ break;
+ }
+ break;
}
- if (_tBind.m_iType == BindEnum::Key)
- FKeybind("Key", _tBind.m_iKey);
+ if (_tBind.m_bNot && (_tBind.m_iType != BindEnum::Key || _tBind.m_iInfo == BindEnum::KeyEnum::Hold))
+ sType = std::format("not {}", sType);
- PopStyleVar();
- EndPopup();
- }
- else if (FBeginPopupModal(std::format("DeleteBind{}", _iBind).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
- {
- FText(std::format("Do you really want to delete '{}'{}?", _tBind.m_sName, F::Binds.HasChildren(_iBind) ? " and all of its children" : "").c_str());
+ ImVec2 vOriginalPos = { H::Draw.Scale(8) + H::Draw.Scale(28) * std::min(x, 3), GetCursorPosY() + H::Draw.Scale(8) };
- if (FButton("Yes", FButtonEnum::Left))
+ // background
+ float flWidth = GetWindowWidth() - GetStyle().WindowPadding.x * 2 - H::Draw.Scale(28) * std::min(x, 3);
+ float flHeight = H::Draw.Scale(28);
+ ImVec2 vDrawPos = GetDrawPos() + vOriginalPos;
+ if (iBind != _iBind)
+ GetWindowDrawList()->AddRectFilled(vDrawPos, { vDrawPos.x + flWidth, vDrawPos.y + flHeight }, F::Render.Background1p5, H::Draw.Scale(4));
+ else
{
- F::Binds.RemoveBind(_iBind);
- CloseCurrentPopup();
+ ImColor tColor = F::Render.Background1p5L;
+ GetWindowDrawList()->AddRectFilled(vDrawPos, { vDrawPos.x + flWidth, vDrawPos.y + flHeight }, tColor, H::Draw.Scale(4));
- iBind = DEFAULT_BIND;
- tBind = {};
+ tColor = ColorToVec((VecToColor(F::Render.Background1p5)).Lerp({ 127, 127, 127 }, 1.f / 9, LerpEnum::NoAlpha));
+ float flInset = H::Draw.Scale(0.5f) - 0.5f;
+ GetWindowDrawList()->AddRect({ vDrawPos.x + flInset, vDrawPos.y + flInset }, { vDrawPos.x - flInset + flWidth, vDrawPos.y - flInset + flHeight }, tColor, H::Draw.Scale(4), ImDrawFlags_None, H::Draw.Scale());
}
- if (FButton("No", FButtonEnum::Right | FButtonEnum::SameLine))
- CloseCurrentPopup();
- EndPopup();
+ // text
+ if (x > 3)
+ { // don't indent too much
+ auto sText = std::format("-> {}", x);
+ SetCursorPos({ vOriginalPos.x - FCalcTextSize(sText.c_str()).x - H::Draw.Scale(10), vOriginalPos.y + H::Draw.Scale(7) });
+ FText(sText.c_str());
+ }
+
+ float flTextWidth = flWidth - H::Draw.Scale(127);
+ PushTransparent(!F::Binds.WillBeEnabled(_iBind), true);
+
+ SetCursorPos({ vOriginalPos.x + H::Draw.Scale(9), vOriginalPos.y + H::Draw.Scale(7) });
+ FText(TruncateText(_tBind.m_sName, flTextWidth * (1.f / 3) - H::Draw.Scale(20)).c_str());
+
+ SetCursorPos({ vOriginalPos.x + flTextWidth * (1.f / 3), vOriginalPos.y + H::Draw.Scale(7) });
+ FText(sType.c_str());
+
+ SetCursorPos({ vOriginalPos.x + flTextWidth * (2.f / 3), vOriginalPos.y + H::Draw.Scale(7) });
+ FText(sInfo.c_str());
+
+ // buttons
+ int iOffset = 1;
+
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(2) });
+ bool bDelete = IconButton(ICON_MD_DELETE);
+
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(2) });
+ if (IconButton(ICON_MD_EDIT))
+ CurrentBind = CurrentBind != _iBind ? _iBind : DEFAULT_BIND;
+
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(2) });
+ if (IconButton(!_tBind.m_bNot ? ICON_MD_CODE : ICON_MD_CODE_OFF))
+ _tBind.m_bNot = !_tBind.m_bNot;
+
+ PushTransparent(Transparent || _tBind.m_iVisibility == BindVisibilityEnum::Hidden, true);
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(2) });
+ if (IconButton(_tBind.m_iVisibility == BindVisibilityEnum::Always ? ICON_MD_VISIBILITY : ICON_MD_VISIBILITY_OFF))
+ _tBind.m_iVisibility = (_tBind.m_iVisibility + 1) % 3;
+ PopTransparent(1, 1);
+
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(2) });
+ if (IconButton(_tBind.m_bEnabled ? ICON_MD_TOGGLE_ON : ICON_MD_TOGGLE_OFF))
+ _tBind.m_bEnabled = !_tBind.m_bEnabled;
+
+ SetCursorPos(vOriginalPos);
+ bool bClicked = Button(std::format("##{}", _iBind).c_str(), { flWidth, flHeight });
+ bool bPopup = IsItemClicked(ImGuiMouseButton_Right);
+
+ PopTransparent(1, 1);
+
+ if (bClicked)
+ {
+ if (!bParent)
+ {
+ iBind = _iBind;
+ tBind = _tBind;
+ }
+ else
+ {
+ bParent = false;
+ tBind.m_iParent = _iBind;
+
+ // make sure bind can't be parented to itself or any of its children
+ int _iBind2 = _iBind;
+ Bind_t _tBind2;
+ while (F::Binds.GetBind(_iBind2, &_tBind2))
+ {
+ if (_iBind2 == iBind)
+ tBind.m_iParent = DEFAULT_BIND;
+ _iBind2 = _tBind2.m_iParent;
+ }
+ }
+ }
+ else if (bPopup)
+ OpenPopup(std::format("RightClicked{}", _iBind).c_str());
+ else if (iDragging == -1 && IsItemHovered() && IsMouseDown(ImGuiMouseButton_Left))
+ iDragging = _iBind, iLayer = iParent;
+ else if (bDelete)
+ {
+ if (U::KeyHandler.Down(VK_SHIFT)) // allow user to quickly remove binds
+ F::Binds.RemoveBind(_iBind);
+ else
+ OpenPopup(std::format("DeleteBind{}", _iBind).c_str());
+ }
+
+ if (FBeginPopup(std::format("RightClicked{}", _iBind).c_str()))
+ {
+ PushStyleVar(ImGuiStyleVar_ItemSpacing, { H::Draw.Scale(8), 0 });
+
+ {
+ static std::string sInput = "";
+
+ bool bEnter = FInputText("Name...", sInput, H::Draw.Scale(284), ImGuiInputTextFlags_EnterReturnsTrue);
+ if (!IsItemFocused())
+ sInput = _tBind.m_sName;
+ if (bEnter)
+ _tBind.m_sName = sInput;
+ }
+
+ FDropdown("Type", &_tBind.m_iType, { "Key", "Class", "Weapon type", "Item slot", "Misc" }, {}, FDropdownEnum::Left);
+ switch (_tBind.m_iType)
+ {
+ case BindEnum::Key: FDropdown("Behavior", &_tBind.m_iInfo, { "Hold", "Toggle", "Double click" }, {}, FDropdownEnum::Right); break;
+ case BindEnum::Class: FDropdown("Class", &_tBind.m_iInfo, { "Scout", "Soldier", "Pyro", "Demoman", "Heavy", "Engineer", "Medic", "Sniper", "Spy" }, {}, FDropdownEnum::Right); break;
+ case BindEnum::WeaponType: FDropdown("Weapon type", &_tBind.m_iInfo, { "Hitscan", "Projectile", "Melee", "Throwable" }, {}, FDropdownEnum::Right); break;
+ case BindEnum::ItemSlot: FDropdown("Item slot", &_tBind.m_iInfo, { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, {}, FDropdownEnum::Right); break;
+ case BindEnum::Misc: FDropdown("Misc", &_tBind.m_iInfo, { "Spectated", "Spectated 1st", "Spectated 3rd", "##Divider", "Zoomed", "Aiming" }, {}, FDropdownEnum::Right); break;
+ }
+ if (_tBind.m_iType == BindEnum::Key)
+ FKeybind("Key", _tBind.m_iKey);
+
+ PopStyleVar();
+ EndPopup();
+ }
+ else if (FBeginPopupModal(std::format("DeleteBind{}", _iBind).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
+ {
+ FText(std::format("Do you really want to delete '{}'{}?", _tBind.m_sName, F::Binds.HasChildren(_iBind) ? " and all of its children" : "").c_str());
+
+ if (FButton("Yes", FButtonEnum::Left))
+ {
+ F::Binds.RemoveBind(_iBind);
+ CloseCurrentPopup();
+
+ iBind = DEFAULT_BIND;
+ tBind = {};
+ }
+ if (FButton("No", FButtonEnum::Right | FButtonEnum::SameLine))
+ CloseCurrentPopup();
+
+ EndPopup();
+ }
+
+ if (iParent != DEFAULT_BIND - 1)
+ fGetBinds(_iBind, x + 1);
}
-
- if (iParent != DEFAULT_BIND - 1)
- fGetBinds(_iBind, x + 1);
- }
- };
+ };
fGetBinds(DEFAULT_BIND, 0);
// this should ideally never happen, but failsafe
@@ -2965,21 +2970,21 @@ void CMenu::MenuSettings(int iTab)
vMaterials.push_back(tMaterial);
std::sort(vMaterials.begin(), vMaterials.end(), [&](const auto& a, const auto& b) -> bool
- {
- // override for none material
- if (FNV1A::Hash32(a.m_sName.c_str()) == FNV1A::Hash32Const("None"))
- return true;
- if (FNV1A::Hash32(b.m_sName.c_str()) == FNV1A::Hash32Const("None"))
- return false;
+ {
+ // override for none material
+ if (FNV1A::Hash32(a.m_sName.c_str()) == FNV1A::Hash32Const("None"))
+ return true;
+ if (FNV1A::Hash32(b.m_sName.c_str()) == FNV1A::Hash32Const("None"))
+ return false;
- // keep locked materials higher
- if (a.m_bLocked && !b.m_bLocked)
- return true;
- if (!a.m_bLocked && b.m_bLocked)
- return false;
+ // keep locked materials higher
+ if (a.m_bLocked && !b.m_bLocked)
+ return true;
+ if (!a.m_bLocked && b.m_bLocked)
+ return false;
- return a.m_sName < b.m_sName;
- });
+ return a.m_sName < b.m_sName;
+ });
for (auto& tMaterial : vMaterials)
{
@@ -3068,7 +3073,7 @@ void CMenu::MenuSettings(int iTab)
TextEditor.SetPaletteIndex(TextEditor::PaletteIndex::Punctuation, F::Render.Inactive);
TextEditor.SetPaletteIndex(TextEditor::PaletteIndex::ControlCharacter, ImColor(F::Render.Inactive.Value.x, F::Render.Inactive.Value.y, F::Render.Inactive.Value.z, 0.1f));
TextEditor.SetPaletteIndex(TextEditor::PaletteIndex::String, F::Render.Accent);
-
+
PushFont(F::Render.FontMono);
ImVec2 vDrawPos = GetDrawPos() + GetCursorPos();
TextEditor.Render("TextEditor");
@@ -3603,92 +3608,92 @@ void CMenu::DrawBinds()
std::vector vInfo;
std::function fGetBinds = [&](int iParent)
- {
- for (int iBind = 0; iBind < F::Binds.m_vBinds.size(); iBind++)
{
- auto& tBind = F::Binds.m_vBinds[iBind];
- if (iParent != tBind.m_iParent || !tBind.m_bEnabled && !m_bIsOpen)
- continue;
-
- if (tBind.m_iVisibility == BindVisibilityEnum::Always || tBind.m_iVisibility == BindVisibilityEnum::WhileActive && tBind.m_bActive || m_bIsOpen)
+ for (int iBind = 0; iBind < F::Binds.m_vBinds.size(); iBind++)
{
- std::string sType; std::string sInfo;
- switch (tBind.m_iType)
+ auto& tBind = F::Binds.m_vBinds[iBind];
+ if (iParent != tBind.m_iParent || !tBind.m_bEnabled && !m_bIsOpen)
+ continue;
+
+ if (tBind.m_iVisibility == BindVisibilityEnum::Always || tBind.m_iVisibility == BindVisibilityEnum::WhileActive && tBind.m_bActive || m_bIsOpen)
{
- case BindEnum::Key:
- switch (tBind.m_iInfo)
+ std::string sType; std::string sInfo;
+ switch (tBind.m_iType)
{
- case BindEnum::KeyEnum::Hold: { sType = "hold"; break; }
- case BindEnum::KeyEnum::Toggle: { sType = "toggle"; break; }
- case BindEnum::KeyEnum::DoubleClick: { sType = "double"; break; }
- }
- sInfo = VK2STR(tBind.m_iKey);
- break;
- case BindEnum::Class:
- sType = "class";
- switch (tBind.m_iInfo)
- {
- case BindEnum::ClassEnum::Scout: { sInfo = "scout"; break; }
- case BindEnum::ClassEnum::Soldier: { sInfo = "soldier"; break; }
- case BindEnum::ClassEnum::Pyro: { sInfo = "pyro"; break; }
- case BindEnum::ClassEnum::Demoman: { sInfo = "demoman"; break; }
- case BindEnum::ClassEnum::Heavy: { sInfo = "heavy"; break; }
- case BindEnum::ClassEnum::Engineer: { sInfo = "engineer"; break; }
- case BindEnum::ClassEnum::Medic: { sInfo = "medic"; break; }
- case BindEnum::ClassEnum::Sniper: { sInfo = "sniper"; break; }
- case BindEnum::ClassEnum::Spy: { sInfo = "spy"; break; }
- }
- break;
- case BindEnum::WeaponType:
- sType = "weapon";
- switch (tBind.m_iInfo)
- {
- case BindEnum::WeaponTypeEnum::Hitscan: { sInfo = "hitscan"; break; }
- case BindEnum::WeaponTypeEnum::Projectile: { sInfo = "projectile"; break; }
- case BindEnum::WeaponTypeEnum::Melee: { sInfo = "melee"; break; }
- case BindEnum::WeaponTypeEnum::Throwable: { sInfo = "throwable"; break; }
- }
- break;
- case BindEnum::ItemSlot:
- sType = "slot";
- sInfo = std::format("{}", tBind.m_iInfo + 1);
- break;
- case BindEnum::Misc:
- switch (tBind.m_iInfo)
- {
- case BindEnum::MiscEnum::Spectated:
- case BindEnum::MiscEnum::SpectatedFirst:
- case BindEnum::MiscEnum::SpectatedThird:
- sType = "spectated";
+ case BindEnum::Key:
switch (tBind.m_iInfo)
{
- case BindEnum::MiscEnum::Spectated: { sInfo = "any"; break; }
- case BindEnum::MiscEnum::SpectatedFirst: { sInfo = "1st"; break; }
- case BindEnum::MiscEnum::SpectatedThird: { sInfo = "3rd"; break; }
+ case BindEnum::KeyEnum::Hold: { sType = "hold"; break; }
+ case BindEnum::KeyEnum::Toggle: { sType = "toggle"; break; }
+ case BindEnum::KeyEnum::DoubleClick: { sType = "double"; break; }
+ }
+ sInfo = VK2STR(tBind.m_iKey);
+ break;
+ case BindEnum::Class:
+ sType = "class";
+ switch (tBind.m_iInfo)
+ {
+ case BindEnum::ClassEnum::Scout: { sInfo = "scout"; break; }
+ case BindEnum::ClassEnum::Soldier: { sInfo = "soldier"; break; }
+ case BindEnum::ClassEnum::Pyro: { sInfo = "pyro"; break; }
+ case BindEnum::ClassEnum::Demoman: { sInfo = "demoman"; break; }
+ case BindEnum::ClassEnum::Heavy: { sInfo = "heavy"; break; }
+ case BindEnum::ClassEnum::Engineer: { sInfo = "engineer"; break; }
+ case BindEnum::ClassEnum::Medic: { sInfo = "medic"; break; }
+ case BindEnum::ClassEnum::Sniper: { sInfo = "sniper"; break; }
+ case BindEnum::ClassEnum::Spy: { sInfo = "spy"; break; }
}
break;
- case BindEnum::MiscEnum::Zoomed:
- case BindEnum::MiscEnum::Aiming:
- sType = "cond";
+ case BindEnum::WeaponType:
+ sType = "weapon";
switch (tBind.m_iInfo)
{
- case BindEnum::MiscEnum::Zoomed: { sInfo = "zoomed"; break; }
- case BindEnum::MiscEnum::Aiming: { sInfo = "aiming"; break; }
+ case BindEnum::WeaponTypeEnum::Hitscan: { sInfo = "hitscan"; break; }
+ case BindEnum::WeaponTypeEnum::Projectile: { sInfo = "projectile"; break; }
+ case BindEnum::WeaponTypeEnum::Melee: { sInfo = "melee"; break; }
+ case BindEnum::WeaponTypeEnum::Throwable: { sInfo = "throwable"; break; }
+ }
+ break;
+ case BindEnum::ItemSlot:
+ sType = "slot";
+ sInfo = std::format("{}", tBind.m_iInfo + 1);
+ break;
+ case BindEnum::Misc:
+ switch (tBind.m_iInfo)
+ {
+ case BindEnum::MiscEnum::Spectated:
+ case BindEnum::MiscEnum::SpectatedFirst:
+ case BindEnum::MiscEnum::SpectatedThird:
+ sType = "spectated";
+ switch (tBind.m_iInfo)
+ {
+ case BindEnum::MiscEnum::Spectated: { sInfo = "any"; break; }
+ case BindEnum::MiscEnum::SpectatedFirst: { sInfo = "1st"; break; }
+ case BindEnum::MiscEnum::SpectatedThird: { sInfo = "3rd"; break; }
+ }
+ break;
+ case BindEnum::MiscEnum::Zoomed:
+ case BindEnum::MiscEnum::Aiming:
+ sType = "cond";
+ switch (tBind.m_iInfo)
+ {
+ case BindEnum::MiscEnum::Zoomed: { sInfo = "zoomed"; break; }
+ case BindEnum::MiscEnum::Aiming: { sInfo = "aiming"; break; }
+ }
+ break;
}
break;
}
- break;
+ if (tBind.m_bNot && (tBind.m_iType != BindEnum::Key || tBind.m_iInfo == BindEnum::KeyEnum::Hold))
+ sInfo = std::format("not {}", sInfo);
+
+ vInfo.emplace_back(tBind.m_sName.c_str(), sType, sInfo, iBind, tBind);
}
- if (tBind.m_bNot && (tBind.m_iType != BindEnum::Key || tBind.m_iInfo == BindEnum::KeyEnum::Hold))
- sInfo = std::format("not {}", sInfo);
- vInfo.emplace_back(tBind.m_sName.c_str(), sType, sInfo, iBind, tBind);
+ if (tBind.m_bActive || m_bIsOpen)
+ fGetBinds(iBind);
}
-
- if (tBind.m_bActive || m_bIsOpen)
- fGetBinds(iBind);
- }
- };
+ };
fGetBinds(DEFAULT_BIND);
if (vInfo.empty())
return;
@@ -3730,7 +3735,7 @@ void CMenu::DrawBinds()
if (Vars::Menu::BindWindowTitle.Value)
{
SetCursorPos({ H::Draw.Scale(8), H::Draw.Scale(6) });
- IconImage(ICON_MD_KEYBOARD);
+ IconImage(ICON_MD_KEYBOARD, F::Render.Accent);
PushFont(F::Render.FontLarge);
SetCursorPos({ H::Draw.Scale(30), H::Draw.Scale(7) });
FText("Binds");
diff --git a/Amalgam/src/Features/Misc/Misc.cpp b/Amalgam/src/Features/Misc/Misc.cpp
index 0bcc7cc9..de57cd75 100644
--- a/Amalgam/src/Features/Misc/Misc.cpp
+++ b/Amalgam/src/Features/Misc/Misc.cpp
@@ -140,7 +140,7 @@ void CMisc::AutoStrafe(CTFPlayer* pLocal, CUserCmd* pCmd)
break;
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);
pCmd->forwardmove = flCosRot * flForward - flSinRot * flSide;
diff --git a/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.cpp b/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.cpp
index 0ff8e22a..62738f65 100644
--- a/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.cpp
+++ b/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.cpp
@@ -23,7 +23,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
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 };
return true;
@@ -360,7 +360,9 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
if (!m_pEnv || !m_pObj)
return false;
- //set drag
+ m_pCurrent = &tProjInfo;
+
+ // set drag
{
float flDrag = 0.f;
Vec3 vDragBasis = {};
@@ -403,7 +405,7 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
break;
case FNV1A::Hash32Const("models/weapons/w_models/w_baseball.mdl"):
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 };
break;
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;
}
- //set position and velocity
+ // set position and velocity
{
Vec3 vVelocity, vAngularVelocity;
if (!bWorld)
@@ -478,7 +480,8 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
vAngularVelocity = { 600.f, float(SDK::RandomInt(-1200, 1200)), 0.f };
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;
case FNV1A::Hash32Const("models/workshop_partner/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl"):
vVelocity = vForward * 10 + vUp;
@@ -554,12 +557,11 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
m_pObj->SetVelocity(&vVelocity, &vAngularVelocity);
}
- //set m_pEnv params
+ // set m_pEnv params
{
float flMaxVelocity = 1000000.f;
float vMaxAngularVelocity = 1000000.f;
- //only pipes need k_flMaxVelocity and k_flMaxAngularVelocity
switch (tProjInfo.m_uType)
{
case FNV1A::Hash32Const("custom"):
@@ -585,7 +587,7 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
params.maxAngularVelocity = vMaxAngularVelocity;
m_pEnv->SetPerformanceSettings(¶ms);
- m_pEnv->SetAirDensity(2.f);
+ m_pEnv->SetAirDensity(AIR_DENSITY);
m_pEnv->SetGravity({ 0.f, 0.f, -(800.f * tProjInfo.m_flGravity) });
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)
diff --git a/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.h b/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.h
index 2020e6cb..42846b17 100644
--- a/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.h
+++ b/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.h
@@ -209,6 +209,7 @@ public:
IPhysicsEnvironment* m_pEnv = nullptr;
IPhysicsObject* m_pObj = nullptr;
+ ProjectileInfo* m_pCurrent = nullptr;
};
ADD_FEATURE(CProjectileSimulation, ProjSim);
\ No newline at end of file
diff --git a/Amalgam/src/Features/Visuals/OffscreenArrows/OffscreenArrows.cpp b/Amalgam/src/Features/Visuals/OffscreenArrows/OffscreenArrows.cpp
index d2aaabc9..1d589b88 100644
--- a/Amalgam/src/Features/Visuals/OffscreenArrows/OffscreenArrows.cpp
+++ b/Amalgam/src/Features/Visuals/OffscreenArrows/OffscreenArrows.cpp
@@ -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 });
- const float flDeg = DEG2RAD(vAngle.y);
+ const float flDeg = Math::Deg2Rad(vAngle.y);
const float flCos = cos(flDeg);
const float flSin = sin(flDeg);
diff --git a/Amalgam/src/Features/Visuals/Visuals.cpp b/Amalgam/src/Features/Visuals/Visuals.cpp
index 8e99aba1..dfe54213 100644
--- a/Amalgam/src/Features/Visuals/Visuals.cpp
+++ b/Amalgam/src/Features/Visuals/Visuals.cpp
@@ -28,7 +28,7 @@ static std::vector SplashTrace(Vec3 vOrigin, float flRadius, Vec3 vNormal
std::vector vPoints = {};
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)
{
CGameTrace trace = {};
diff --git a/Amalgam/src/Hooks/CM_TraceToDispTree.cpp b/Amalgam/src/Hooks/CM_TraceToDispTree.cpp
new file mode 100644
index 00000000..a830990c
--- /dev/null
+++ b/Amalgam/src/Hooks/CM_TraceToDispTree.cpp
@@ -0,0 +1,73 @@
+#include "../SDK/SDK.h"
+
+#include "../SDK/Definitions/Misc/TraceInfo.h"
+#include
+
+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 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);
+}
\ No newline at end of file
diff --git a/Amalgam/src/SDK/Definitions/Definitions.h b/Amalgam/src/SDK/Definitions/Definitions.h
index f9cee149..4ec127c5 100644
--- a/Amalgam/src/SDK/Definitions/Definitions.h
+++ b/Amalgam/src/SDK/Definitions/Definitions.h
@@ -198,6 +198,7 @@
#define TF_ROCKET_RADIUS (146.f)
#define TF_FLARE_DET_RADIUS (110.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_BURNING_FREQUENCY 0.5f
diff --git a/Amalgam/src/SDK/Definitions/Interfaces/VPhysics.h b/Amalgam/src/SDK/Definitions/Interfaces/VPhysics.h
index 87f2b5af..0b20ed24 100644
--- a/Amalgam/src/SDK/Definitions/Interfaces/VPhysics.h
+++ b/Amalgam/src/SDK/Definitions/Interfaces/VPhysics.h
@@ -2,6 +2,7 @@
#include "../Misc/IAppSystem.h"
#include "../Types.h"
+#define AIR_DENSITY 2
#define k_flMaxVelocity 2000.0f
#define k_flMaxAngularVelocity 360.0f * 10.0f
#define DEFAULT_MIN_FRICTION_MASS 10.0f
diff --git a/Amalgam/src/SDK/Definitions/Misc/BSPFlags.h b/Amalgam/src/SDK/Definitions/Misc/BSPFlags.h
index afaaedd1..01ed6619 100644
--- a/Amalgam/src/SDK/Definitions/Misc/BSPFlags.h
+++ b/Amalgam/src/SDK/Definitions/Misc/BSPFlags.h
@@ -55,6 +55,7 @@
#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans
#define CONTENTS_LADDER 0x20000000
#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
#define SURF_LIGHT 0x0001 // value will hold the light strength
diff --git a/Amalgam/src/SDK/Definitions/Misc/TraceInfo.h b/Amalgam/src/SDK/Definitions/Misc/TraceInfo.h
new file mode 100644
index 00000000..310fbdac
--- /dev/null
+++ b/Amalgam/src/SDK/Definitions/Misc/TraceInfo.h
@@ -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 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];
+};
\ No newline at end of file
diff --git a/Amalgam/src/SDK/Definitions/Types.h b/Amalgam/src/SDK/Definitions/Types.h
index 1483571d..5ba83ab3 100644
--- a/Amalgam/src/SDK/Definitions/Types.h
+++ b/Amalgam/src/SDK/Definitions/Types.h
@@ -1,5 +1,6 @@
#pragma once
#include
+#include
#include
#include
#include
@@ -9,15 +10,34 @@
#include