improve face splash

do projectile sim for nondrag projectiles directly without vphysics
fixes
This commit is contained in:
rei-2
2026-04-24 17:20:08 -04:00
parent be74d8dc90
commit fa40bbcc91
40 changed files with 4934 additions and 315 deletions
+10
View File
@@ -1260,6 +1260,7 @@
<ClInclude Include="src\Features\World\World.h" />
<ClInclude Include="src\Hooks\Direct3DDevice9.h" />
<ClInclude Include="src\SDK\Definitions\Interfaces\CCollisionBSPData.h" />
<ClInclude Include="src\SDK\Definitions\Interfaces\CMDLCache.h" />
<ClInclude Include="src\SDK\Definitions\Interfaces\CStaticPropMgr.h" />
<ClInclude Include="src\SDK\Definitions\Interfaces\CTFGameRules.h" />
<ClInclude Include="src\SDK\Definitions\Interfaces\CTFGCClientSystem.h" />
@@ -1293,6 +1294,7 @@
<ClInclude Include="src\SDK\Definitions\Main\ICollideable.h" />
<ClInclude Include="src\SDK\Definitions\Main\Ray.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CByteSwap.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CDefaultDataCacheClient.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CDiscardableArray.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CInterpolatedVar.h" />
<ClInclude Include="src\SDK\Definitions\Main\CModel.h" />
@@ -1308,11 +1310,18 @@
<ClInclude Include="src\SDK\Definitions\Misc\BSPFlags.h" />
<ClInclude Include="src\SDK\Definitions\Interfaces\IMoveHelper.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CRangeValidatedArray.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlBlockMemory.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlBuffer.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlCharConversion.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlDict.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlFixedMemory.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlIntrusiveList.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlLinkedList.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlMap.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlMemory.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlObjectReference.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlRBTree.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlShared.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlString.h" />
<ClInclude Include="src\SDK\Definitions\Misc\dt_send.h" />
<ClInclude Include="src\SDK\Definitions\Main\IDispInfo.h" />
@@ -1320,6 +1329,7 @@
<ClInclude Include="src\SDK\Definitions\Misc\IMDLCache.h" />
<ClInclude Include="src\SDK\Definitions\Misc\IPrediction.h" />
<ClInclude Include="src\SDK\Definitions\Interfaces\ISpatialPartition.h" />
<ClInclude Include="src\SDK\Definitions\Misc\IStudioDataCache.h" />
<ClInclude Include="src\SDK\Definitions\Misc\ServerClass.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CSmartPtr.h" />
<ClInclude Include="src\SDK\Definitions\Misc\TraceInfo.h" />
+10
View File
@@ -611,6 +611,16 @@
<ClInclude Include="src\SDK\Definitions\Interfaces\CDispCollTree.h" />
<ClInclude Include="src\SDK\Definitions\Misc\TraceInfo.h" />
<ClInclude Include="src\Utils\Math\BaseMath.h" />
<ClInclude Include="src\SDK\Definitions\Misc\IStudioDataCache.h" />
<ClInclude Include="src\SDK\Definitions\Interfaces\CMDLCache.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CDefaultDataCacheClient.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlDict.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlMap.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlRBTree.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlFixedMemory.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlBlockMemory.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlLinkedList.h" />
<ClInclude Include="src\SDK\Definitions\Misc\CUtlShared.h" />
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
@@ -379,11 +379,11 @@ int CAimbotMelee::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pW
Vec3 vTraceEnd = m_vEyePos + vForward * flRange;
SDK::TraceHull(m_vEyePos, vTraceEnd, {}, {}, MASK_SOLID, &filter, &trace);
bool bReturn = trace.m_pEnt && trace.m_pEnt == tTarget.m_pEntity;
bool bReturn = trace.m_pEnt == tTarget.m_pEntity;
if (!bReturn)
{
SDK::TraceHull(m_vEyePos, vTraceEnd, vSwingMins, vSwingMaxs, MASK_SOLID, &filter, &trace);
bReturn = trace.m_pEnt && trace.m_pEnt == tTarget.m_pEntity;
bReturn = trace.m_pEnt == tTarget.m_pEntity;
}
if (bReturn && Vars::Aimbot::Melee::AutoBackstab.Value && pWeapon->GetWeaponID() == TF_WEAPON_KNIFE)
@@ -411,7 +411,7 @@ int CAimbotMelee::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pW
vTraceEnd = m_vEyePos + vForward * flRange;
SDK::TraceHull(m_vEyePos, vTraceEnd, vSwingMins, vSwingMaxs, MASK_SOLID, &filter, &trace);
if (trace.m_pEnt && trace.m_pEnt == tTarget.m_pEntity)
if (trace.m_pEnt == tTarget.m_pEntity)
return 2;
}
}
@@ -16,6 +16,9 @@
#ifdef SPLASH_DEBUG5
static std::map<std::string, int> s_mTraceCount = {};
#endif
#ifdef SPLASH_DEBUG2
//#include "../../Visuals/Visuals.h"
#endif
static inline std::vector<Target_t> GetTargets(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
{
@@ -270,6 +273,16 @@ static inline float ArmTime(CTFWeaponBase* pWeapon)
return 0.f;
}
static inline bool ShouldLob(Info_t& tInfo)
{
return tInfo.m_flGravity && Vars::Aimbot::Projectile::Modifiers.Value & Vars::Aimbot::Projectile::ModifiersEnum::LobAngles;
}
static inline bool ShouldLob(MoveStorage& tMoveStorage, Info_t& tInfo)
{
return tInfo.m_bIgnoreTiming && (tMoveStorage.m_bFailed || tMoveStorage.m_pPlayer->IsOnGround());
}
static inline bool AirSplash(CTFWeaponBase* pWeapon)
{
if (!(Vars::Aimbot::Projectile::Modifiers.Value & Vars::Aimbot::Projectile::ModifiersEnum::AirSplash))
@@ -349,7 +362,7 @@ Directs_t CAimbotProjectile::GetDirects()
auto& tTarget = *m_tInfo.m_pTarget;
uint8_t iFlags = PointFlagsEnum::Regular;
if (m_tInfo.m_flGravity && Vars::Aimbot::Projectile::Modifiers.Value & Vars::Aimbot::Projectile::ModifiersEnum::LobAngles)
if (ShouldLob(m_tInfo))
iFlags |= PointFlagsEnum::Lob;
const Vec3 vMins = tTarget.m_pEntity->m_vecMins(), vMaxs = tTarget.m_pEntity->m_vecMaxs();
@@ -418,37 +431,36 @@ Splashes_t CAimbotProjectile::GetSplashes()
return vSplashes;
vSplashes.push_back(PointFlagsEnum::Regular);
if (m_tInfo.m_flGravity && Vars::Aimbot::Projectile::Modifiers.Value & Vars::Aimbot::Projectile::ModifiersEnum::LobAngles)
if (ShouldLob(m_tInfo))
vSplashes.push_back(PointFlagsEnum::Lob);
return vSplashes;
}
static inline std::vector<Vec3> ComputePoints(float flRadius, int iSamples, bool bSphere)
static inline std::vector<Vec3> ComputePoints(float flRadius, int iSamples)
{
std::vector<Vec3> vPoints = { { Vec3(0.f, 0.f, -1.f) * flRadius } };
if (!iSamples)
return vPoints;
if (bSphere)
vPoints.reserve(iSamples + 1);
float flRotateX = Vars::Aimbot::Projectile::SplashRotateX.Value < 0.f ? SDK::StdRandomFloat(0.f, 360.f) : Vars::Aimbot::Projectile::SplashRotateX.Value;
float flRotateY = Vars::Aimbot::Projectile::SplashRotateY.Value < 0.f ? SDK::StdRandomFloat(0.f, 360.f) : Vars::Aimbot::Projectile::SplashRotateY.Value;
float a = Math::PI * (3.f - sqrtf(5.f));
for (int n = 0; n < iSamples; n++)
{
vPoints.reserve(iSamples + 1);
float t = a * n;
float y = 1 - (n / (iSamples - 1.f)) * 2;
float r = sqrtf(1 - powf(y, 2));
float x = cosf(t) * r;
float z = sinf(t) * r;
float flRotateX = Vars::Aimbot::Projectile::SplashRotateX.Value < 0.f ? SDK::StdRandomFloat(0.f, 360.f) : Vars::Aimbot::Projectile::SplashRotateX.Value;
float flRotateY = Vars::Aimbot::Projectile::SplashRotateY.Value < 0.f ? SDK::StdRandomFloat(0.f, 360.f) : Vars::Aimbot::Projectile::SplashRotateY.Value;
Vec3 vPoint = Vec3(x, y, z) * flRadius;
vPoint = Math::RotatePoint(vPoint, {}, { flRotateX, flRotateY });
float a = Math::PI * (3.f - sqrtf(5.f));
for (int n = 0; n < iSamples; n++)
{
float t = a * n;
float y = 1 - (n / (iSamples - 1.f)) * 2;
float r = sqrtf(1 - powf(y, 2));
float x = cosf(t) * r;
float z = sinf(t) * r;
Vec3 vPoint = Vec3(x, y, z) * flRadius;
vPoint = Math::RotatePoint(vPoint, {}, { flRotateX, flRotateY });
vPoints.push_back(vPoint);
}
vPoints.push_back(vPoint);
}
return vPoints;
@@ -520,53 +532,111 @@ static inline void HandleTrace(const Vec3& vPoint, std::vector<Setup_t>& vPoints
}
static float s_flTotal = 0.f;
static inline void HandleFace(const Face_t& tFace, std::vector<Setup_t>& vPoints, float flDensity, float flRadius, float flCutoff, const Vec3& vTargetEye, const Vec3& vTargetCenter, Info_t& tInfo, CGameTrace& trace, ITraceFilter& filter)
static inline void HandleFace(Face_t& tFace, std::vector<Setup_t>& vPoints, float flDensity, float flRadius, float flCutoff, const Vec3& vTargetEye, const Vec3& vTargetCenter, const Vec3& vTargetOrigin, Info_t& tInfo, CGameTrace& trace, ITraceFilter& filter)
{
float flRadiusSqr = powf(flRadius, 2);
float flRadius2Sqr = flRadiusSqr * 4;
int nMask = MASK_SHOT;
if (F::ProjSim.m_pObj->m_dragCoefficient && F::ProjSim.m_pObj->m_angDragBasis)
nMask |= CONTENTS_DISPSOLID;
int nMask = F::ProjSim.m_bPhysics ? MASK_SHOT | CONTENTS_DISPSOLID : MASK_SHOT;
for (int i = 0; ++i < tFace.m_vVertices.size() - 1;)
std::vector<Vec3> vVertices, vEpsilon;
if (tFace.m_iType != FaceTypeEnum::Prop)
vVertices = tFace.m_vVertices;
else
Math::ExpandPolygon(vVertices, tFace.m_vVertices, tFace.m_vNormal, SDK::StdRandomFloat(0.f, DIST_EPSILON), &vTargetEye);
for (int i = 0, n = int(tFace.m_vVertices.size()), o = SDK::StdRandomInt(0, n - 1); ++i < n - 1;)
{
const Vec3& vVertex1 = tFace.m_vVertices[0], &vVertex2 = tFace.m_vVertices[i], &vVertex3 = tFace.m_vVertices[i + 1];
Vec3& vVertex1 = tFace.m_vVertices[o], &vVertex2 = tFace.m_vVertices[(o + i) % n], &vVertex3 = tFace.m_vVertices[(o + i + 1) % n];
Vec3 vDir21 = vVertex2 - vVertex1, vDir31 = vVertex3 - vVertex1;
float flArea = vDir21.Cross(vDir31).Length() / 2;
float flSamples = flDensity * flArea / flRadius2Sqr;
int iSamples = flSamples < flCutoff ? fmodf(s_flTotal += flSamples, flCutoff) < flSamples : ceilf(flSamples);
int iSamples = flSamples > flCutoff ? ceilf(flSamples) : fmodf(s_flTotal += flSamples, flCutoff) < flSamples;
if (!iSamples)
continue;
#if defined(SPLASH_DEBUG2) && defined(WORLD_DEBUG)
if (iSamples)
F::World.DrawFace({ { vVertex1, vVertex2, vVertex3 }, tFace.m_vNormal }, DrawTypeEnum::Edges | DrawTypeEnum::Faces);
// don't particularly like the hacky random epsilons
int iFaceClosest = SDK::StdRandomInt(iSamples < 2 ? 0 : iSamples < 4 ? 1 : 2, iSamples < 2 ? 1 : 2);
//int iEdgeClosest = SDK::StdRandomInt(iSamples < 8 ? 0 : iSamples < 16 ? 1 : 2, iSamples < 8 ? 1 : 2); // eats up a bit too much performance for my liking
int iEdgeRandom = SDK::StdRandomInt(iSamples < 8 ? 0 : iSamples < 16 ? 1 : 2, iSamples < 3 ? 0 : iSamples < 12 ? 1 : 2);
iEdgeRandom += iFaceClosest; //iEdgeClosest += iFaceClosest, iEdgeRandom += iEdgeClosest; //, iSamples += iEdgeRandom;
#ifdef SPLASH_DEBUG2
Color_t tColor = { byte(SDK::StdRandomInt(0, 255)), byte(SDK::StdRandomInt(0, 255)), byte(SDK::StdRandomInt(0, 255)) };
#ifdef WORLD_DEBUG
F::World.DrawFace({ { vVertex1, vVertex2, vVertex3 }, tFace.m_vNormal, tFace.m_iType }, DrawTypeEnum::Edges | DrawTypeEnum::Faces, tColor);
#endif
for (int i = 0; i < iSamples; i++)
#ifdef DEBUG_TEXT
F::Visuals.AddDebugText(std::format("{}:{}:{}"/*:{}"*/, iFaceClosest, /*iEdgeClosest,*/ iEdgeRandom, iSamples), (vVertex1 + vVertex2 + vVertex3) / 3, tColor);
#endif
#endif
for (int s = 0; s < iSamples; s++)
{
float flRandom1 = SDK::StdRandomFloat(), flRandom2 = SDK::StdRandomFloat();
if (flRandom1 + flRandom2 > 1)
flRandom1 = 1 - flRandom1, flRandom2 = 1 - flRandom2;
Vec3 vPoint = vVertex1 + vDir21 * flRandom1 + vDir31 * flRandom2 + tFace.m_vNormal * (tInfo.m_vHull + CALC_EPSILON);
Vec3 vPoint, vNormal = tFace.m_vNormal; bool bInside = true;
if (s < iFaceClosest) // closest point
{
float flEpsilon = s == 0 && (tFace.m_iType == FaceTypeEnum::BoxBrush || iFaceClosest != 1 || SDK::StdRandomBool()) ? CALC_EPSILON : DIST_EPSILON;
vPoint = Math::ClosestPointOnTriangle(vTargetOrigin, vVertex1, vVertex2, vVertex3, &bInside);
vPoint += { SDK::StdRandomFloat(-flEpsilon, flEpsilon), SDK::StdRandomFloat(-flEpsilon, flEpsilon), SDK::StdRandomFloat(-flEpsilon, flEpsilon) };
}
//else if (s < iEdgeClosest) // closest point on edge
//{
// float flEpsilon = SDK::StdRandomBool() ? CALC_EPSILON : DIST_EPSILON; bInside = false;
// switch (SDK::StdRandomInt(0, 2))
// {
// case 0: vPoint = Math::ClosestPointOnLine(vTargetOrigin, vVertex1, vVertex2); break;
// case 1: vPoint = Math::ClosestPointOnLine(vTargetOrigin, vVertex2, vVertex3); break;
// case 2: vPoint = Math::ClosestPointOnLine(vTargetOrigin, vVertex3, vVertex1); break;
// }
// vPoint += { SDK::StdRandomFloat(-flEpsilon, flEpsilon), SDK::StdRandomFloat(-flEpsilon, flEpsilon), SDK::StdRandomFloat(-flEpsilon, flEpsilon) };
//}
else if (s < iEdgeRandom) // random point on edge
{
float flEpsilon = SDK::StdRandomBool() ? CALC_EPSILON : DIST_EPSILON; bInside = false;
switch (SDK::StdRandomInt(0, 2))
{
case 0: vPoint = vVertex1.Lerp(vVertex2, SDK::StdRandomFloat()); break;
case 1: vPoint = vVertex2.Lerp(vVertex3, SDK::StdRandomFloat()); break;
case 2: vPoint = vVertex3.Lerp(vVertex1, SDK::StdRandomFloat()); break;
}
vPoint += { SDK::StdRandomFloat(-flEpsilon, flEpsilon), SDK::StdRandomFloat(-flEpsilon, flEpsilon), SDK::StdRandomFloat(-flEpsilon, flEpsilon) };
}
else // random point on face
{
float flRandom1 = SDK::StdRandomFloat(), flRandom2 = SDK::StdRandomFloat();
if (flRandom1 + flRandom2 > 1)
flRandom1 = 1 - flRandom1, flRandom2 = 1 - flRandom2;
vPoint = vVertex1 + vDir21 * flRandom1 + vDir31 * flRandom2;
}
vPoint += vNormal * (tInfo.m_vHull + CALC_EPSILON);
if (vPoint.DistToSqr(vTargetCenter) > flRadiusSqr)
continue;
if (!bInside)
{
if (vEpsilon.empty())
Math::ExpandPolygon(vEpsilon = vVertices, tFace.m_vNormal, -DIST_EPSILON);
Math::ClosestPointOnPolygon(vPoint, vEpsilon, vNormal, &bInside);
if (tFace.m_iType == FaceTypeEnum::Prop && !bInside)
vPoint += tFace.m_vNormal * SDK::StdRandomFloat(0.f, DIST_EPSILON);
}
#ifdef SPLASH_DEBUG5
s_mTraceCount[__FUNCTION__": point contents"]++;
if (bInside) s_mTraceCount[__FUNCTION__": point contents"]++;
#endif
if (I::EngineTrace->GetPointContents(vPoint) & MASK_SOLID)
if (bInside && I::EngineTrace->GetPointContents(vPoint) & MASK_SOLID)
continue;
if (tFace.m_iType == FaceTypeEnum::Prop)
vPoint += tFace.m_vNormal * DIST_EPSILON;
int nSubMask = nMask;
if (!bInside)
vNormal = (vTargetEye - vPoint).Normalized(), nSubMask &= ~CONTENTS_MOVEABLE;
SDK::Trace(vPoint + tFace.m_vNormal * tInfo.m_flNormalOffset, vTargetEye, nMask, &filter, &trace);
SDK::Trace(vPoint + vNormal * tInfo.m_flNormalOffset, vTargetEye, nSubMask, &filter, &trace);
#ifdef SPLASH_DEBUG5
s_mTraceCount[__FUNCTION__": vispos"]++;
#endif
#ifdef SPLASH_DEBUG2
DrawTrace(!trace.DidHit(), Vars::Colors::IndicatorMisc.Value, trace);
DrawTrace(trace.fraction == 1.f, Vars::Colors::IndicatorMisc.Value, trace);
#endif
if (trace.fraction != 1.f)
continue;
@@ -594,7 +664,7 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Setup_t>& v
if (pAngle)
{
Vec3 vForward, vRight, vUp; Math::AngleVectors(*pAngle, &vForward, &vRight, &vUp);
Vec3 vShootPos = m_tInfo.m_vLocalEye + (vForward * m_tInfo.m_vOffset.x) + (vRight * m_tInfo.m_vOffset.y) + (vUp * m_tInfo.m_vOffset.z);
Vec3 vShootPos = m_tInfo.m_vLocalEye + vForward * m_tInfo.m_vOffset.x + vRight * m_tInfo.m_vOffset.y + vUp * m_tInfo.m_vOffset.z;
vForward = (vShootPos - vPoint).Normalized();
return vForward.Dot(vNormal) > 0;
}
@@ -606,9 +676,10 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Setup_t>& v
};
// Trace
int iPoints = !m_tInfo.m_flGravity ? Vars::Aimbot::Projectile::SplashPointsDirect.Value : Vars::Aimbot::Projectile::SplashPointsArc.Value;
int iPoints = Vars::Aimbot::Projectile::SplashMode.Value == Vars::Aimbot::Projectile::SplashModeEnum::Face && !bAirSplash ? 0
: !m_tInfo.m_flGravity ? Vars::Aimbot::Projectile::SplashPointsDirect.Value : Vars::Aimbot::Projectile::SplashPointsArc.Value;
{
auto vPoints = ComputePoints(flRadius, iPoints, Vars::Aimbot::Projectile::SplashMode.Value == Vars::Aimbot::Projectile::SplashModeEnum::Trace || bAirSplash);
auto vPoints = ComputePoints(flRadius, iPoints);
for (int i = 0; i < vPoints.size(); i++)
{
@@ -626,7 +697,7 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Setup_t>& v
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 * powf(tPoint.m_tSolution.m_flTime, 2)) / 2);
vPoint -= Vec3(0, 0, m_tInfo.m_flGravity * 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);
@@ -655,8 +726,8 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Setup_t>& v
}
// Face
float flDensity = !m_tInfo.m_flGravity ? Vars::Aimbot::Projectile::SplashDensityDirect.Value : Vars::Aimbot::Projectile::SplashDensityArc.Value;
if (Vars::Aimbot::Projectile::SplashMode.Value == Vars::Aimbot::Projectile::SplashModeEnum::Face && flDensity)
if (float flDensity = !m_tInfo.m_flGravity ? Vars::Aimbot::Projectile::SplashDensityDirect.Value : Vars::Aimbot::Projectile::SplashDensityArc.Value;
Vars::Aimbot::Projectile::SplashMode.Value == Vars::Aimbot::Projectile::SplashModeEnum::Face && flDensity)
{
Vec3 vMins = vTargetCenter - flRadius, vMaxs = vTargetCenter + flRadius;
@@ -664,14 +735,14 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Setup_t>& v
{
Vec3 vPoint = std::reduce(vVertices.begin(), vVertices.end()) / vVertices.size(), vAngle;
if (!m_tInfo.m_flGravity)
vAngle = Math::CalcAngle(m_tInfo.m_vLocalEye, trace.endpos);
vAngle = Math::CalcAngle(m_tInfo.m_vLocalEye, vPoint);
else
{
Point_t tPoint = { vPoint, {} };
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 * powf(tPoint.m_tSolution.m_flTime, 2)) / 2);
vPoint -= Vec3(0, 0, m_tInfo.m_flGravity * 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);
@@ -686,7 +757,7 @@ void CAimbotProjectile::SetupSplashPoints(Vec3& vOrigin, std::vector<Setup_t>& v
float flCutoff = Vars::Aimbot::Projectile::SplashSamplesCutoff.Value * powf(vFaces.size(), 2); s_flTotal = SDK::StdRandomFloat();
for (auto& tFace : vFaces)
{
HandleFace(tFace, vSplashPoints, flDensity, flRadius, flCutoff, vTargetEye, vTargetCenter, m_tInfo, trace, filter);
HandleFace(tFace, vSplashPoints, flDensity, flRadius, flCutoff, vTargetEye, vTargetCenter, vOrigin, m_tInfo, trace, filter);
//#if defined(SPLASH_DEBUG2) && defined(WORLD_DEBUG)
// F::World.DrawFace(tFace, DrawTypeEnum::Edges | DrawTypeEnum::Faces);
//#endif
@@ -720,7 +791,7 @@ std::vector<Point_t> CAimbotProjectile::GetSplashPoints(Vec3 vOrigin, std::vecto
flRadiusAirSqr = powf(m_tInfo.m_flRadius * Math::RemapVal(TICKS_TO_TIME(iSimTime), flLiveTime, flLiveTime + flRampTime, flAirdetRadius, 1.f), 2);
}
bool bLob = iFlags & CalculateFlagsEnum::LobAngle;
int iTolerance = m_tInfo.m_bIgnoreTiming && bLob ? std::numeric_limits<int>::max() : !m_tInfo.m_iArmTime ? 0 : -1;
int iTolerance = m_tInfo.m_bIgnoreTiming && bLob ? std::numeric_limits<int>::max() : m_tInfo.m_iArmTime ? -1 : 0;
int iLimit = !bFirst ? m_tInfo.m_iSplashRestrict : std::max(m_tInfo.m_iSplashRestrict, Vars::Aimbot::Projectile::SplashRestrictFirst.Value);
bool bSort = !bLob || !m_tInfo.m_bIgnoreTiming;
@@ -787,20 +858,20 @@ static inline Vec3 PullPoint(const Vec3& vPoint, Vec3 vLocalPos, Info_t& tInfo,
{
auto fHeightenLocalPos = [&]()
{ // basic trajectory pass
const float flGrav = tInfo.m_flGravity * 800.f;
float flGrav = tInfo.m_flGravity;
if (!flGrav)
return vPoint;
const Vec3 vDelta = vTargetPos - vLocalPos;
const float flDist = vDelta.Length2D();
Vec3 vDelta = vTargetPos - vLocalPos;
float flDist = vDelta.Length2D();
const float flRoot = powf(tInfo.m_flVelocity, 4) - flGrav * (flGrav * powf(flDist, 2) + 2.f * vDelta.z * powf(tInfo.m_flVelocity, 2));
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((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 * powf(flTime, 2)) / 2);
return vLocalPos + Vec3(0, 0, flGrav * powf(flTime, 2) / 2);
};
vLocalPos = fHeightenLocalPos();
@@ -821,7 +892,7 @@ static inline float GetDrag(float flVelocity, ProjectileInfo* pInfo, int iFlags)
{
auto fGetDrag = [&](std::function<float()> fGetTypeDrag)
{
if (!F::ProjSim.m_pObj->m_dragCoefficient || !F::ProjSim.m_pObj->m_dragBasis)
if (!F::ProjSim.m_bPhysics)
return 0.f;
if (Vars::Aimbot::Projectile::DragOverride.Value)
@@ -902,7 +973,7 @@ static inline float GetDrag(float flVelocity, ProjectileInfo* pInfo, int iFlags)
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;
float flGrav = tInfo.m_flGravity;
Vec3 vDelta = vTargetPos - vLocalPos;
float flDist = vDelta.Length2D();
float flDrag = GetDrag(flVelocity, F::ProjSim.m_pCurrent, iFlags);
@@ -960,7 +1031,7 @@ void CAimbotProjectile::CalculateAngle(const Vec3& vLocalPos, const Vec3& vTarge
float flPitch, flYaw;
{ // basic trajectory pass
//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);
//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))
{
tOut.m_iCalculated = CalculateResultEnum::Bad;
@@ -1134,7 +1205,7 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
#ifdef SPLASH_DEBUG4
Vec3 vHull = m_tProjInfo.m_vHull.Max(1);
G::BoxStorage.emplace_back(vPoint, -vHull, vHull, Vec3(), I::GlobalVars->curtime + 5.f, Color_t(255, 0, 0), Color_t(0, 0, 0, 0));
G::BoxStorage.emplace_back(vPoint, -vHull, vHull, Vec3(), I::GlobalVars->curtime + 5.f, Color_t(0, 0, 0), Color_t(0, 0, 0, 0));
#endif
if (!m_tProjInfo.m_flGravity)
@@ -1146,7 +1217,7 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
#ifdef SPLASH_DEBUG4
G::LineStorage.emplace_back(std::pair<Vec3, Vec3>(m_tProjInfo.m_vPos, trace.endpos), I::GlobalVars->curtime + 5.f, Color_t(0, 0, 0));
#endif
if (trace.fraction < 0.999f && trace.m_pEnt != tTarget.m_pEntity)
if (Math::FullFraction(m_tProjInfo.m_vPos, vPoint, trace) < 0.999f && trace.m_pEnt != tTarget.m_pEntity)
return false;
}
@@ -1157,7 +1228,7 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
bool bDidHit = false;
Vec3 vNew = F::ProjSim.GetOrigin();
int iTimingTolerance = TIME_TO_TICKS(m_tInfo.m_flBoundsTime);
float flRadiusSqr = powf(m_tProjInfo.m_flVelocity * TICK_INTERVAL + m_tProjInfo.m_vHull.z, 2);
float flRadiusSqr = iType != PointTypeEnum::Direct ? powf(m_tProjInfo.m_flVelocity * TICK_INTERVAL + m_tProjInfo.m_vHull.z, 2) : std::numeric_limits<float>::max();
uint8_t iTraceInterval = iFlags == PointFlagsEnum::Lob ? Vars::Aimbot::Projectile::LobTraceInterval.Value
: iType != PointTypeEnum::Direct ? Vars::Aimbot::Projectile::SplashTraceInterval.Value
: Vars::Aimbot::Projectile::DirectTraceInterval.Value;
@@ -1192,10 +1263,9 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
{
case PointTypeEnum::Direct:
case PointTypeEnum::Geometry:
bHit = trace.DidHit();
break;
bHit = trace.DidHit(); break;
case PointTypeEnum::Air:
bHit = trace.endpos.DistToSqr(vPoint) < flRadiusSqr || trace.DidHit();
bHit = trace.endpos.DistToSqr(vPoint) < flRadiusSqr || trace.DidHit(); break;
}
if (bHit)
@@ -1204,24 +1274,22 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
switch (iType)
{
case PointTypeEnum::Direct:
bTarget = trace.m_pEnt == tTarget.m_pEntity, bValid = bTarget && iSimTime - n < iTimingTolerance;
break;
bTarget = trace.m_pEnt == tTarget.m_pEntity, bValid = bTarget && iSimTime - n < iTimingTolerance; break;
case PointTypeEnum::Geometry:
bValid = trace.endpos.DistToSqr(vPoint) < flRadiusSqr;
break;
bValid = trace.endpos.DistToSqr(vPoint) < flRadiusSqr; break;
case PointTypeEnum::Air:
bValid = !trace.DidHit();
break;
bValid = !trace.DidHit(); break;
}
if (bValid && iType != PointTypeEnum::Direct)
{
CGameTrace eyeTrace = {};
SDK::Trace(trace.endpos + m_tInfo.m_flNormalOffset * trace.plane.normal, tTarget.m_vPos + m_tInfo.m_vTargetEye, MASK_SHOT, &filter, &eyeTrace);
SDK::Trace(trace.endpos + trace.plane.normal * m_tInfo.m_flNormalOffset, tTarget.m_vPos + m_tInfo.m_vTargetEye, MASK_SHOT, &filter, &eyeTrace);
bValid = eyeTrace.fraction == 1.f;
#ifdef SPLASH_DEBUG5
s_mTraceCount[__FUNCTION__": splash eye trace"]++;
#endif
#ifdef SPLASH_DEBUG4
//G::LineStorage.emplace_back(std::pair<Vec3, Vec3>(trace.endpos, trace.endpos + trace.plane.normal * m_tInfo.m_flNormalOffset), I::GlobalVars->curtime + 5.f, Color_t(255, 0, 255));
G::LineStorage.emplace_back(std::pair<Vec3, Vec3>(eyeTrace.startpos, eyeTrace.endpos), I::GlobalVars->curtime + 5.f, Color_t(255, 0, 255));
G::BoxStorage.emplace_back(trace.endpos + m_tInfo.m_flNormalOffset * trace.plane.normal, -vHull, vHull, Vec3(), I::GlobalVars->curtime + 5.f, Color_t(255, 0, 255), Color_t(0, 0, 0, 0));
#endif
@@ -1230,17 +1298,8 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
#ifdef SPLASH_DEBUG4
if (bValid)
G::BoxStorage.emplace_back(vPoint, -vHull, vHull, Vec3(), I::GlobalVars->curtime + 5.f, Color_t(0, 255, 0), Color_t(0, 0, 0, 0));
else if (bTarget)
G::BoxStorage.emplace_back(vPoint, -vHull, vHull, Vec3(), I::GlobalVars->curtime + 5.f, Color_t(0, 0, 255), Color_t(0, 0, 0, 0));
else
{
G::BoxStorage.emplace_back(vPoint, -vHull, vHull, Vec3(), I::GlobalVars->curtime + 5.f, Color_t(127, 0, 255), Color_t(0, 0, 0, 0));
if (iType != PointTypeEnum::Direct)
{
G::BoxStorage.emplace_back(trace.endpos, Vec3::Get(-1), Vec3::Get(1), Vec3(), I::GlobalVars->curtime + 5.f, Color_t(0, 0, 0), Color_t(0, 0, 0, 0));
G::BoxStorage.emplace_back(vPoint, Vec3::Get(-1), Vec3::Get(1), Vec3(), I::GlobalVars->curtime + 5.f, Color_t(255, 255, 255), Color_t(0, 0, 0, 0));
}
}
G::BoxStorage.emplace_back(vPoint, -vHull, vHull, Vec3(), I::GlobalVars->curtime + 5.f, Color_t(255, 0, 0), Color_t(0, 0, 0, 0));
#endif
if (bValid)
@@ -1272,7 +1331,7 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
Vec3 vOffset = tOriginal.m_vOrigin - tTarget.m_vPos;
Vec3 vPos = trace.endpos + F::ProjSim.GetVelocity().Normalized() * 16 + vOffset;
float flClosest = std::numeric_limits<float>::max(); int iClosest = -1;
float flLowestDistance = std::numeric_limits<float>::max(); int iClosest = -1;
for (int nHitbox = 0; nHitbox < pSet->numhitboxes; ++nHitbox)
{
auto pBox = pSet->pHitbox(nHitbox);
@@ -1280,12 +1339,9 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
Vec3 vCenter; Math::VectorTransform({}, aBones[pBox->bone], vCenter);
const float flDist = vPos.DistToSqr(vCenter);
if (flDist < flClosest)
{
flClosest = flDist;
iClosest = nHitbox;
}
const float flDistance = vPos.DistToSqr(vCenter);
if (flDistance < flLowestDistance)
iClosest = nHitbox, flLowestDistance = flDistance;
}
if (iClosest != HITBOX_HEAD)
break;
@@ -1300,7 +1356,6 @@ bool CAimbotProjectile::TestAngle(const Vec3& vPoint, const Vec3& vAngles, int i
filter.pSkip = tTarget.m_pEntity;
filter.iPlayer = PLAYER_NONE;
filter.bMisc = false;
flRadiusSqr = std::numeric_limits<float>::max();
continue;
}
else
@@ -1329,7 +1384,7 @@ bool CAimbotProjectile::HandlePoint(const Vec3& vOrigin, int iSimTime, float flP
m_tInfo.m_pTarget->m_vPos = vOrigin;
int iOriginalSimTime = iSimTime;
if (m_tInfo.m_iArmTime || m_tInfo.m_bIgnoreTiming && iFlags == PointFlagsEnum::Lob)
if (m_tInfo.m_iArmTime && iType == PointTypeEnum::Geometry || m_tInfo.m_bIgnoreTiming && iFlags == PointFlagsEnum::Lob)
{
if (flTime > m_tProjInfo.m_flLifetime)
return false;
@@ -1344,7 +1399,7 @@ bool CAimbotProjectile::HandlePoint(const Vec3& vOrigin, int iSimTime, float flP
bReturn = m_iResult = true;
m_flTimeTo = flTime + m_tInfo.m_flLatency;
}
else if (m_iResult != 1 && !m_tInfo.m_pProjectile)
else if (!m_iResult && !m_tInfo.m_pProjectile)
{
switch (Vars::Aimbot::General::AimType.Value)
{
@@ -1381,7 +1436,7 @@ bool CAimbotProjectile::HandlePoint(const Vec3& vOrigin, int iSimTime, float flP
}
}
return bReturn;
return bReturn && m_iResult == 1;
}
bool CAimbotProjectile::HandleDirect(DirectHistory_t& mDirectHistory)
@@ -1487,7 +1542,7 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas
m_tInfo.m_vHull = m_tProjInfo.m_vHull.Min(3);
m_tInfo.m_vOffset = m_tProjInfo.m_vPos - m_tInfo.m_vLocalEye; m_tInfo.m_vOffset.y *= -1;
m_tInfo.m_flOffsetTime = m_tInfo.m_vOffset.Length() / m_tInfo.m_flVelocity; // silly
m_tInfo.m_flOffsetTime = m_tInfo.m_vOffset.Length() / m_tInfo.m_flVelocity;
m_tInfo.m_flGravity = m_tProjInfo.m_flGravity;
m_tInfo.m_iSplashRestrict = !m_tInfo.m_flGravity ? Vars::Aimbot::Projectile::SplashRestrictDirect.Value : Vars::Aimbot::Projectile::SplashRestrictArc.Value;
@@ -1544,7 +1599,16 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas
iFlags |= CalculateFlagsEnum::LobAngle;
int iTolerance = m_tInfo.m_bIgnoreTiming && iType == PointFlagsEnum::Lob ? std::numeric_limits<int>::max() : -1;
Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, vPoint, i, tSolution, iFlags, iTolerance);
Solution_t tSolution;
switch (iType)
{
case PointFlagsEnum::Lob:
if (ShouldLob(m_tMoveStorage, m_tInfo))
goto end;
tSolution.m_iCalculated = CalculateResultEnum::Bad; break;
default: end:
CalculateAngle(m_tInfo.m_vLocalEye, vPoint, i, tSolution, iFlags, iTolerance);
}
switch (tSolution.m_iCalculated)
{
case CalculateResultEnum::Good:
@@ -1560,7 +1624,7 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas
for (auto it = vSplashes.begin(); it != vSplashes.end();)
{
uint8_t iFlags = CalculateFlagsEnum::AccountDrag;
if (!m_tInfo.m_bIgnoreTiming && *it == PointFlagsEnum::Lob)
if (*it == PointFlagsEnum::Lob && !m_tInfo.m_bIgnoreTiming)
iFlags |= CalculateFlagsEnum::LobAngle;
Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, tTarget.m_vPos, i, tSolution, iFlags);
@@ -1581,6 +1645,11 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas
it = vSplashes.erase(it);
continue;
}
if (*it == PointFlagsEnum::Lob && !ShouldLob(m_tMoveStorage, m_tInfo))
{
++it;
continue;
}
mSplashHistory[*it].emplace_back(History_t(tTarget.m_vPos, i), fabsf(flTimeTo));
++it;
@@ -1841,6 +1910,9 @@ bool CAimbotProjectile::RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser
#endif
#if defined(SPLASH_DEBUG2) && defined(WORLD_DEBUG)
G::TriangleStorage.clear();
#endif
#if defined(SPLASH_DEBUG2) && defined(DEBUG_TEXT)
F::Visuals.ClearDebugText();
#endif
for (auto& tTarget : vTargets)
{
@@ -2026,7 +2098,7 @@ bool CAimbotProjectile::TestAngle(CBaseEntity* pProjectile, const Vec3& vPoint,
Vec3 vPos = vPoint;
if (m_tInfo.m_flGravity)
vPos += Vec3(0, 0, (m_tInfo.m_flGravity * 800.f * pow(TICKS_TO_TIME(iSimTime), 2)) / 2);
vPos += Vec3(0, 0, m_tInfo.m_flGravity * pow(TICKS_TO_TIME(iSimTime), 2) / 2);
Vec3 vForward = (vPos - m_tProjInfo.m_vPos).Normalized();
m_tProjInfo.m_vAng = Math::VectorAngles(vForward);
@@ -2037,7 +2109,7 @@ bool CAimbotProjectile::TestAngle(CBaseEntity* pProjectile, const Vec3& vPoint,
return false;
SDK::Trace(vEyePos, trace.endpos, MASK_SOLID, &filter, &trace);
if (trace.fraction < 0.999f)
if (Math::FullFraction(vEyePos, trace.endpos, trace) < 0.999f)
return false;
if (!F::AutoAirblast.CanAirblastEntity(pLocal, pWeapon, pProjectile, vAngles))
@@ -2055,7 +2127,7 @@ bool CAimbotProjectile::TestAngle(CBaseEntity* pProjectile, const Vec3& vPoint,
if (!m_tProjInfo.m_flGravity)
{
SDK::TraceHull(m_tProjInfo.m_vPos, vPoint, -m_tProjInfo.m_vHull, m_tProjInfo.m_vHull, nMask, &filter, &trace);
if (trace.fraction < 0.999f && trace.m_pEnt != tTarget.m_pEntity)
if (Math::FullFraction(m_tProjInfo.m_vPos, vPoint, trace) < 0.999f && trace.m_pEnt != tTarget.m_pEntity)
return false;
}
@@ -2091,10 +2163,9 @@ bool CAimbotProjectile::TestAngle(CBaseEntity* pProjectile, const Vec3& vPoint,
{
case PointTypeEnum::Direct:
case PointTypeEnum::Geometry:
bHit = trace.DidHit();
break;
bHit = trace.DidHit(); break;
case PointTypeEnum::Air:
bHit = trace.endpos.DistToSqr(vPoint) < flRadiusSqr || trace.DidHit();
bHit = trace.endpos.DistToSqr(vPoint) < flRadiusSqr || trace.DidHit(); break;
}
if (bHit)
@@ -2103,33 +2174,17 @@ bool CAimbotProjectile::TestAngle(CBaseEntity* pProjectile, const Vec3& vPoint,
switch (iType)
{
case PointTypeEnum::Direct:
bTarget = trace.m_pEnt == tTarget.m_pEntity, bValid = bTarget && iSimTime - n < iTimingTolerance;
break;
bTarget = trace.m_pEnt == tTarget.m_pEntity, bValid = bTarget && iSimTime - n < iTimingTolerance; break;
case PointTypeEnum::Geometry:
bValid = trace.endpos.DistToSqr(vPoint) < flRadiusSqr;
break;
bValid = trace.endpos.DistToSqr(vPoint) < flRadiusSqr; break;
case PointTypeEnum::Air:
bValid = !trace.DidHit();
break;
bValid = !trace.DidHit(); break;
}
if (bValid && iType != PointTypeEnum::Direct)
{
bValid = SDK::VisPosWorld(nullptr, tTarget.m_pEntity, trace.endpos, vPoint, nMask);
if (bValid)
{
Vec3 vFrom = trace.endpos;
switch (pProjectile->GetClassID())
{
case ETFClassID::CTFProjectile_Rocket:
case ETFClassID::CTFProjectile_SentryRocket:
case ETFClassID::CTFProjectile_EnergyBall:
vFrom += trace.plane.normal;
}
CGameTrace eyeTrace = {};
SDK::Trace(vFrom, tTarget.m_vPos + tTarget.m_pEntity->As<CTFPlayer>()->GetViewOffset(), MASK_SHOT, &filter, &eyeTrace);
bValid = eyeTrace.fraction == 1.f;
}
CGameTrace eyeTrace = {};
SDK::Trace(trace.endpos + trace.plane.normal * m_tInfo.m_flNormalOffset, tTarget.m_vPos + m_tInfo.m_vTargetEye, MASK_SHOT, &filter, &eyeTrace);
bValid = eyeTrace.fraction == 1.f;
}
if (bValid)
@@ -2244,7 +2299,16 @@ bool CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBa
iFlags |= CalculateFlagsEnum::LobAngle;
int iTolerance = m_tInfo.m_bIgnoreTiming && iType == PointFlagsEnum::Lob ? std::numeric_limits<int>::max() : -1;
Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, vPoint, i, tSolution, iFlags, iTolerance);
Solution_t tSolution;
switch (iType)
{
case PointFlagsEnum::Lob:
if (ShouldLob(m_tMoveStorage, m_tInfo))
goto end;
tSolution.m_iCalculated = CalculateResultEnum::Bad; break;
default: end:
CalculateAngle(m_tInfo.m_vLocalEye, vPoint, i, tSolution, iFlags, iTolerance);
}
switch (tSolution.m_iCalculated)
{
case CalculateResultEnum::Good:
@@ -2260,7 +2324,7 @@ bool CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBa
for (auto it = vSplashes.begin(); it != vSplashes.end();)
{
uint8_t iFlags = CalculateFlagsEnum::AccountDrag;
if (!m_tInfo.m_bIgnoreTiming && *it == PointFlagsEnum::Lob)
if (*it == PointFlagsEnum::Lob && !m_tInfo.m_bIgnoreTiming)
iFlags |= CalculateFlagsEnum::LobAngle;
Solution_t tSolution; CalculateAngle(m_tInfo.m_vLocalEye, tTarget.m_vPos, i, tSolution, iFlags);
@@ -2281,6 +2345,11 @@ bool CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBa
it = vSplashes.erase(it);
continue;
}
if (*it == PointFlagsEnum::Lob && !ShouldLob(m_tMoveStorage, m_tInfo))
{
++it;
continue;
}
mSplashHistory[*it].emplace_back(History_t(tTarget.m_vPos, i), fabsf(flTimeTo));
++it;
@@ -2,7 +2,6 @@
#include "../../../SDK/SDK.h"
#include "../AimbotGlobal/AimbotGlobal.h"
#include <optional>
class CAutoDetonate
{
+7
View File
@@ -3362,6 +3362,13 @@ void CMenu::MenuSettings(int iTab)
{
FDropdown(Vars::World::Faces, FDropdownEnum::Left);
FDropdown(Vars::World::Draw, FDropdownEnum::Right);
FSlider(Vars::World::Offset, FSliderEnum::Left);
FSlider(Vars::World::Resize, FSliderEnum::Right);
FColorPicker(Vars::World::BoxBrush, FColorPickerEnum::Left);
FColorPicker(Vars::World::PlaneBrush, FColorPickerEnum::Right);
FColorPicker(Vars::World::Displacement, FColorPickerEnum::Left);
FColorPicker(Vars::World::Prop, FColorPickerEnum::Right);
FColorPicker(Vars::World::Entity, FColorPickerEnum::Left);
} EndSection();
#endif
#ifdef DEBUG_HOOKS
@@ -39,7 +39,8 @@ void CNoSpreadProjectile::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCm
switch (pWeapon->GetWeaponID())
{
case TF_WEAPON_COMPOUND_BOW:
if (I::GlobalVars->curtime - pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime() > TF_ARROW_MAX_CHARGE_TIME)
if (pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime() > 0.f
&& I::GlobalVars->curtime - pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime() > TF_ARROW_MAX_CHARGE_TIME)
{
vAngAdd.x -= float(SDK::RandomInt()) / VALVE_RAND_MAX * 12.f - 6.f;
vAngAdd.y -= float(SDK::RandomInt()) / VALVE_RAND_MAX * 12.f - 6.f;
-1
View File
@@ -1,6 +1,5 @@
#pragma once
#include "../../SDK/SDK.h"
#include <optional>
struct ResolveData
{
@@ -228,54 +228,13 @@ bool CMovementSimulation::Initialize(CBaseEntity* pEntity, MoveStorage& tMoveSto
tMoveStorage.m_bBunnyHop = true;
// setup move data
if (!SetupMoveData(tMoveStorage))
{
tMoveStorage.m_bFailed = true;
return false;
}
const int iStrafeSamples = tMoveStorage.m_bDirectMove
? Vars::Aimbot::Projectile::GroundSamples.Value
: Vars::Aimbot::Projectile::AirSamples.Value;
SetupMoveData(tMoveStorage);
// calculate strafe if desired
bool bCalculated = bStrafe ? StrafePrediction(tMoveStorage, iStrafeSamples) : false;
// really hope this doesn't work like shit
if (bHitchance && bCalculated && !pPlayer->m_vecVelocity().IsZero() && Vars::Aimbot::Projectile::HitChance.Value)
if (bStrafe)
{
const auto& vRecords = m_mRecords[pPlayer->entindex()];
const auto iSamples = vRecords.size();
float flCurrentChance = 1.f, flAverageYaw = 0.f;
for (size_t i = 0; i < iSamples; i++)
if (!StrafePrediction(tMoveStorage, bHitchance))
{
if (vRecords.size() <= i + 2)
break;
const auto& pRecord1 = vRecords[i], &pRecord2 = vRecords[i + 1];
const float flYaw1 = Math::VectorAngles(pRecord1.m_vDirection).y, flYaw2 = Math::VectorAngles(pRecord2.m_vDirection).y;
const float flTime1 = pRecord1.m_flSimTime, flTime2 = pRecord2.m_flSimTime;
const int iTicks = std::max(TIME_TO_TICKS(flTime1 - flTime2), 1);
float flYaw = Math::NormalizeAngle(flYaw1 - flYaw2) / iTicks;
flAverageYaw += flYaw;
if (tMoveStorage.m_MoveData.m_flMaxSpeed)
flYaw *= std::clamp(pRecord1.m_vVelocity.Length2D() / tMoveStorage.m_MoveData.m_flMaxSpeed, 0.f, 1.f);
if ((i + 1) % iStrafeSamples == 0 || i == iSamples - 1)
{
flAverageYaw /= i % iStrafeSamples + 1;
if (fabsf(tMoveStorage.m_flAverageYaw - flAverageYaw) > 0.5f)
flCurrentChance -= 1.f / ((iSamples - 1) / float(iStrafeSamples) + 1);
flAverageYaw = 0.f;
}
}
if (flCurrentChance < Vars::Aimbot::Projectile::HitChance.Value / 100)
{
SDK::Output("MovementSimulation", std::format("Hitchance ({}% < {}%)", flCurrentChance * 100, Vars::Aimbot::Projectile::HitChance.Value).c_str(), { 80, 200, 120 }, Vars::Debug::Logging.Value);
tMoveStorage.m_bFailed = true;
return false;
}
@@ -288,11 +247,8 @@ bool CMovementSimulation::Initialize(CBaseEntity* pEntity, MoveStorage& tMoveSto
return true;
}
bool CMovementSimulation::SetupMoveData(MoveStorage& tMoveStorage)
void CMovementSimulation::SetupMoveData(MoveStorage& tMoveStorage)
{
if (!tMoveStorage.m_pPlayer)
return false;
tMoveStorage.m_MoveData.m_bFirstRunOfFunctions = false;
tMoveStorage.m_MoveData.m_bGameCodeMovedPlayer = false;
tMoveStorage.m_MoveData.m_nPlayerHandle = reinterpret_cast<IHandleEntity*>(tMoveStorage.m_pPlayer)->GetRefEHandle();
@@ -346,8 +302,6 @@ bool CMovementSimulation::SetupMoveData(MoveStorage& tMoveStorage)
tMoveStorage.m_flPredictedSimTime = tMoveStorage.m_flSimTime + tMoveStorage.m_flPredictedDelta;
tMoveStorage.m_vPredictedOrigin = tMoveStorage.m_MoveData.m_vecAbsOrigin;
tMoveStorage.m_bDirectMove = tMoveStorage.m_pPlayer->IsOnGround() || tMoveStorage.m_pPlayer->IsSwimming();
return true;
}
static inline float GetGravity()
@@ -527,14 +481,57 @@ void CMovementSimulation::GetAverageYaw(MoveStorage& tMoveStorage, int iSamples)
SDK::Output("MovementSimulation", std::format("flAverageYaw calculated to {} from {} ({}){}", flAverageYaw, iTicks, iMinimum, bLocal ? " (local)" : "").c_str(), { 100, 255, 150 }, Vars::Debug::Logging.Value);
}
bool CMovementSimulation::StrafePrediction(MoveStorage& tMoveStorage, int iSamples)
bool CMovementSimulation::StrafePrediction(MoveStorage& tMoveStorage, bool bHitchance)
{
if (tMoveStorage.m_bDirectMove
? !(Vars::Aimbot::Projectile::StrafePrediction.Value & Vars::Aimbot::Projectile::StrafePredictionEnum::Ground)
: !(Vars::Aimbot::Projectile::StrafePrediction.Value & Vars::Aimbot::Projectile::StrafePredictionEnum::Air))
return false;
return true;
const int iStrafeSamples = tMoveStorage.m_bDirectMove
? Vars::Aimbot::Projectile::GroundSamples.Value
: Vars::Aimbot::Projectile::AirSamples.Value;
GetAverageYaw(tMoveStorage, iStrafeSamples);
// really hope this doesn't work like shit
if (bHitchance && !tMoveStorage.m_pPlayer->m_vecVelocity().IsZero() && Vars::Aimbot::Projectile::HitChance.Value)
{
const auto& vRecords = m_mRecords[tMoveStorage.m_pPlayer->entindex()];
const auto iSamples = vRecords.size();
float flCurrentChance = 1.f, flAverageYaw = 0.f;
for (size_t i = 0; i < iSamples; i++)
{
if (vRecords.size() <= i + 2)
break;
const auto& pRecord1 = vRecords[i], & pRecord2 = vRecords[i + 1];
const float flYaw1 = Math::VectorAngles(pRecord1.m_vDirection).y, flYaw2 = Math::VectorAngles(pRecord2.m_vDirection).y;
const float flTime1 = pRecord1.m_flSimTime, flTime2 = pRecord2.m_flSimTime;
const int iTicks = std::max(TIME_TO_TICKS(flTime1 - flTime2), 1);
float flYaw = Math::NormalizeAngle(flYaw1 - flYaw2) / iTicks;
flAverageYaw += flYaw;
if (tMoveStorage.m_MoveData.m_flMaxSpeed)
flYaw *= std::clamp(pRecord1.m_vVelocity.Length2D() / tMoveStorage.m_MoveData.m_flMaxSpeed, 0.f, 1.f);
if ((i + 1) % iStrafeSamples == 0 || i == iSamples - 1)
{
flAverageYaw /= i % iStrafeSamples + 1;
if (fabsf(tMoveStorage.m_flAverageYaw - flAverageYaw) > 0.5f)
flCurrentChance -= 1.f / ((iSamples - 1) / float(iStrafeSamples) + 1);
flAverageYaw = 0.f;
}
}
if (flCurrentChance < Vars::Aimbot::Projectile::HitChance.Value / 100)
{
SDK::Output("MovementSimulation", std::format("Hitchance ({}% < {}%)", flCurrentChance * 100, Vars::Aimbot::Projectile::HitChance.Value).c_str(), { 80, 200, 120 }, Vars::Debug::Logging.Value);
return false;
}
}
GetAverageYaw(tMoveStorage, iSamples);
return true;
}
@@ -44,9 +44,9 @@ private:
void Store(MoveStorage& tMoveStorage);
void Reset(MoveStorage& tMoveStorage);
bool SetupMoveData(MoveStorage& tMoveStorage);
void SetupMoveData(MoveStorage& tMoveStorage);
void GetAverageYaw(MoveStorage& tMoveStorage, int iSamples);
bool StrafePrediction(MoveStorage& tMoveStorage, int iSamples);
bool StrafePrediction(MoveStorage& tMoveStorage, bool bHitchance = false);
void SetBounds(CTFPlayer* pPlayer);
void RestoreBounds(CTFPlayer* pPlayer);
@@ -11,7 +11,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
return false;
static auto sv_gravity = H::ConVars.FindVar("sv_gravity");
float flGravity = sv_gravity->GetFloat() / 800.f;
float flGravity = sv_gravity->GetFloat(); // vphysics projectiles affected by server start gravity
bool bDucking = pPlayer->m_fFlags() & FL_DUCKING;
bool bRedirect = iFlags & ProjSimEnum::Redirect;
@@ -118,7 +118,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, vHull, flSpeed, 0.f };
return true;
}
case TF_WEAPON_GRENADELAUNCHER: // vphysics projectiles affected by server start gravity
case TF_WEAPON_GRENADELAUNCHER:
case TF_WEAPON_CANNON:
{
bool bCannon = pWeapon->GetWeaponID() == TF_WEAPON_CANNON;
@@ -133,7 +133,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
? pWeapon->As<CTFGrenadeLauncher>()->m_flDetonateTime() > 0.f ? pWeapon->As<CTFGrenadeLauncher>()->m_flDetonateTime() - I::GlobalVars->curtime : flMortar
: SDK::AttribHookValue(2.f, "fuse_mult", pWeapon);
flLifeTime = ceilf(flLifeTime / GRENADE_CHECK_INTERVAL) * GRENADE_CHECK_INTERVAL + GetDesync();
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, vHull, flSpeed, 1.f, flLifeTime };
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, vHull, flSpeed, DEFAULT_GRAVITY, flLifeTime };
return true;
}
case TF_WEAPON_PIPEBOMBLAUNCHER:
@@ -145,7 +145,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
? SDK::AttribHookValue(4.f, "stickybomb_charge_rate", pWeapon) * flAutoCharge
: (pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime() > 0.f ? I::GlobalVars->curtime - pWeapon->As<CTFPipebombLauncher>()->m_flChargeBeginTime() : 0.f);
float flSpeed = SDK::AttribHookValue(bMaxSpeed ? 2400.f : Math::RemapVal(flCharge, 0.f, SDK::AttribHookValue(4.f, "stickybomb_charge_rate", pWeapon), 900.f, 2400.f), "mult_projectile_range", pWeapon);
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 4.f, 4.f, 4.f }, flSpeed, 1.f };
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 5.f, 5.f, 5.f }, flSpeed, DEFAULT_GRAVITY };
return true;
}
case TF_WEAPON_FLAREGUN:
@@ -238,7 +238,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
SDK::GetProjectileFireSetup(pPlayer, vAngles, { 16.f, 8.f, -6.f }, vPos, vAngle, 0.f, 0.f, bInterp);
auto uType = FNV1A::Hash32Const("models/workshop_partner/weapons/c_models/c_sd_cleaver/c_sd_cleaver.mdl");
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 1.f, 1.f, 10.f } /*weird, probably still inaccurate*/, 3000.f, 1.f, 2.2f };
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 1.f, 1.f, 10.f } /*weird, probably still inaccurate*/, 3000.f, DEFAULT_GRAVITY, 2.2f };
return true;
}
case TF_WEAPON_BAT_WOOD:
@@ -252,7 +252,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
auto uType = bWrapAssassin ? FNV1A::Hash32Const("models/weapons/c_models/c_xms_festive_ornament.mdl") : FNV1A::Hash32Const("models/weapons/w_models/w_baseball.mdl");
Vec3 vForward; Math::AngleVectors(vAngle, &vForward);
vPos = (bInterp ? pPlayer->GetAbsOrigin() : pPlayer->m_vecOrigin()) + (Vec3(0, 0, 50) + vForward * 32.f) * pPlayer->m_flModelScale(); // why?
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 3.f, 3.f, 3.f }, tf_scout_stunball_base_speed->GetFloat(), 1.f, bWrapAssassin ? 2.3f : 100.f };
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 3.f, 3.f, 3.f }, tf_scout_stunball_base_speed->GetFloat(), DEFAULT_GRAVITY, bWrapAssassin ? 2.3f : 100.f };
return true;
}
case TF_WEAPON_JAR:
@@ -267,7 +267,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
case Sniper_s_TheSelfAwareBeautyMark: uType = FNV1A::Hash32Const("models/weapons/c_models/c_breadmonster/c_breadmonster.mdl"); break;
case Scout_s_MutatedMilk: uType = FNV1A::Hash32Const("models/weapons/c_models/c_breadmonster/c_breadmonster_milk.mdl"); break;
}
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 3.f, 3.f, 3.f }, 1000.f, 1.f, 2.2f };
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 3.f, 3.f, 3.f }, 1000.f, DEFAULT_GRAVITY, 2.2f };
return true;
}
case TF_WEAPON_JAR_GAS:
@@ -275,7 +275,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
SDK::GetProjectileFireSetup(pPlayer, vAngles, { 16.f, 8.f, -6.f }, vPos, vAngle, 0.f, 0.f, bInterp);
auto uType = FNV1A::Hash32Const("models/weapons/c_models/c_gascan/c_gascan.mdl");
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 3.f, 3.f, 3.f }, 2000.f, 1.f, 2.2f };
tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 3.f, 3.f, 3.f }, 2000.f, DEFAULT_GRAVITY, 2.2f };
return true;
}
case TF_WEAPON_GRAPPLINGHOOK:
@@ -325,7 +325,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap
return false;
}
bool CProjectileSimulation::GetInfo(CTFPlayer* pPlayer, CTFWeaponBase* pWeapon, Vec3 vAngles, ProjectileInfo& tProjInfo, int iFlags, float flAutoCharge)
bool CProjectileSimulation::GetInfo(CTFPlayer* pPlayer, CTFWeaponBase* pWeapon, const Vec3& vAngles, ProjectileInfo& tProjInfo, int iFlags, float flAutoCharge)
{
bool bInitCheck = iFlags & ProjSimEnum::InitCheck;
bool bInterp = iFlags & ProjSimEnum::Interp;
@@ -479,6 +479,7 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
m_pObj->m_dragBasis = vDragBasis;
m_pObj->m_angDragBasis = vAngDragBasis;
m_bPhysics = m_pObj->m_dragCoefficient && m_pObj->m_dragBasis;
}
// set position and velocity
@@ -586,11 +587,19 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
}
}
if (bSimulate && !F::ProjSim.m_pObj->IsDragEnabled() && m_pObj->m_dragBasis.IsZero()) // don't include vphysics projectiles
vVelocity.z += 400.f * tProjInfo.m_flGravity * TICK_INTERVAL; // i don't know why this makes it more accurate but it does
if (bSimulate && !m_bPhysics)
vVelocity.z += tProjInfo.m_flGravity * TICK_INTERVAL / 2;
m_pObj->SetPosition(tProjInfo.m_vPos, tProjInfo.m_vAng, true);
m_pObj->SetVelocity(&vVelocity, &vAngularVelocity);
if (m_bPhysics)
{
m_pObj->SetPosition(tProjInfo.m_vPos, tProjInfo.m_vAng, true);
m_pObj->SetVelocity(&vVelocity, &vAngularVelocity);
}
else
{
m_tObj.m_vOrigin = tProjInfo.m_vPos;
m_tObj.m_vVelocity = vVelocity;
}
}
// set m_pEnv params
@@ -624,7 +633,7 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
m_pEnv->SetPerformanceSettings(&params);
m_pEnv->SetAirDensity(AIR_DENSITY);
m_pEnv->SetGravity({ 0.f, 0.f, -(800.f * tProjInfo.m_flGravity) });
m_pEnv->SetGravity({ 0.f, 0.f, -tProjInfo.m_flGravity });
m_pEnv->ResetSimulationClock();
}
@@ -632,7 +641,8 @@ bool CProjectileSimulation::Initialize(ProjectileInfo& tProjInfo, bool bSimulate
if (tProjInfo.m_uType == FNV1A::Hash32Const("custom"))
tProjInfo.m_uType = FNV1A::Hash32(Vars::Visuals::Trajectory::Type.Value.c_str());
RunTick(tProjInfo, false); // simulate an initial time because dumb
if (m_bPhysics)
RunTick(tProjInfo, false); // simulate an initial time because dumb
return true;
}
@@ -642,15 +652,27 @@ void CProjectileSimulation::RunTick(ProjectileInfo& tProjInfo, bool bPath) // bu
if (bPath)
tProjInfo.m_vPath.push_back(GetOrigin());
m_pEnv->Simulate(TICK_INTERVAL);
if (m_bPhysics)
m_pEnv->Simulate(TICK_INTERVAL);
else
{
Vec3& vOrigin = m_tObj.m_vOrigin;
Vec3& vVelocity = m_tObj.m_vVelocity;
if (tProjInfo.m_flGravity)
vVelocity.z -= tProjInfo.m_flGravity * TICK_INTERVAL;
vOrigin += vVelocity * TICK_INTERVAL;
}
/* // params.maxVelocity limits velocity uniformly
Vec3 vVelocity, vAngular;
m_pObj->GetVelocity(&vVelocity, &vAngular);
static auto sv_maxvelocity = H::ConVars.FindVar("sv_maxvelocity");
const float flMaxVel = sv_maxvelocity->GetFloat();
vVelocity = { std::clamp(vVelocity.x, -flMaxVel, flMaxVel), std::clamp(vVelocity.y, -flMaxVel, flMaxVel), std::clamp(vVelocity.z, -flMaxVel, flMaxVel) };
m_pObj->SetVelocity(&vVelocity, &vAngular);
Vec3 vVelocity;
m_pObj->GetVelocity(&vVelocity, nullptr);
float flMaxVel = sv_maxvelocity->GetFloat();
vVelocity = vVelocity.Clamp(-flMaxVel, flMaxVel);
m_pObj->SetVelocity(&vVelocity, nullptr);
*/
}
@@ -659,8 +681,10 @@ Vec3 CProjectileSimulation::GetOrigin()
if (!m_pObj)
return {};
Vec3 vOut;
m_pObj->GetPosition(&vOut, nullptr);
if (!m_bPhysics)
return m_tObj.m_vOrigin;
Vec3 vOut; m_pObj->GetPosition(&vOut, nullptr);
return vOut;
}
@@ -669,8 +693,10 @@ Vec3 CProjectileSimulation::GetVelocity()
if (!m_pObj)
return {};
Vec3 vOut;
m_pObj->GetVelocity(&vOut, nullptr);
if (!m_bPhysics)
return m_tObj.m_vVelocity;
Vec3 vOut; m_pObj->GetVelocity(&vOut, nullptr);
return vOut;
}
@@ -12,6 +12,7 @@ Enum(ProjSim,
CorrectRandomAngles = 1 << 6 // or do, position matters
)
#define DEFAULT_GRAVITY 800.f
#define GRENADE_CHECK_INTERVAL 0.195f
struct ProjectileInfo
@@ -30,7 +31,13 @@ struct ProjectileInfo
std::vector<Vec3> m_vPath = {};
int m_iFlags = 0;
uint8_t m_iFlags = 0;
};
struct PhysicsObject_t
{
Vec3 m_vOrigin = {};
Vec3 m_vVelocity = {};
};
class CProjectileSimulation
@@ -53,7 +60,7 @@ private:
};
public:
bool GetInfo(CTFPlayer* pPlayer, CTFWeaponBase* pWeapon, Vec3 vAngles, ProjectileInfo& tProjInfo, int iFlags = ProjSimEnum::Redirect | ProjSimEnum::InitCheck, float flAutoCharge = -1.f);
bool GetInfo(CTFPlayer* pPlayer, CTFWeaponBase* pWeapon, const Vec3& vAngles, ProjectileInfo& tProjInfo, int iFlags = ProjSimEnum::Redirect | ProjSimEnum::InitCheck, float flAutoCharge = -1.f);
void SetupTrace(CTraceFilterCollideable& filter, int& nMask, CTFWeaponBase* pWeapon, int nTick = 0, bool bInterp = false);
void GetInfo(CBaseEntity* pProjectile, ProjectileInfo& tProjInfo);
@@ -165,7 +172,7 @@ public:
float flReturn = 0.f;
static auto sv_gravity = H::ConVars.FindVar("sv_gravity");
float flGravity = sv_gravity->GetFloat() / 800.f;
float flGravity = sv_gravity->GetFloat();
switch (pProjectile->GetClassID())
{
case ETFClassID::CBaseGrenade:
@@ -191,7 +198,7 @@ public:
case ETFClassID::CTFProjectile_ThrowableBreadMonster:
case ETFClassID::CTFProjectile_ThrowableBrick:
case ETFClassID::CTFProjectile_ThrowableRepel:
flReturn = 1.f;
flReturn = DEFAULT_GRAVITY;
break;
case ETFClassID::CTFProjectile_HealingBolt:
flReturn = 0.2f * flGravity;
@@ -209,7 +216,11 @@ public:
}
IPhysicsEnvironment* m_pEnv = nullptr;
IPhysicsObject* m_pObj = nullptr;
PhysicsObject_t m_tObj = {};
bool m_bPhysics = false;
ProjectileInfo* m_pCurrent = nullptr;
};
+36 -6
View File
@@ -374,7 +374,7 @@ void CVisuals::DrawDebugInfo(CTFPlayer* pLocal)
Vec3 vOrigin = pLocal->m_vecOrigin();
H::Draw.StringOutlined(fFont, x, y += nTall * 2, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("Origin: ({:.3f}, {:.3f}, {:.3f})", vOrigin.x, vOrigin.y, vOrigin.z).c_str());
Vec3 vVelocity = pLocal->m_vecVelocity();
H::Draw.StringOutlined(fFont, x, y += nTall, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("Velocity: {:.3f} ({:.3f}, {:.3f}, {:.3f})", vVelocity.Length(), vVelocity.x, vVelocity.y, vVelocity.z).c_str());
H::Draw.StringOutlined(fFont, x, y += nTall, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("Velocity: {:.3f}, {:.3f} ({:.3f}, {:.3f}, {:.3f})", vVelocity.Length(), vVelocity.Length2D(), vVelocity.x, vVelocity.y, vVelocity.z).c_str());
H::Draw.StringOutlined(fFont, x, y += nTall, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("Tickbase: {}", pLocal->m_nTickBase()).c_str());
//H::Draw.StringOutlined(fFont, x, y += nTall, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("Choke: {}, {}", G::Choking, I::ClientState->chokedcommands).c_str());
//H::Draw.StringOutlined(fFont, x, y += nTall, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("Ticks: {}, {}", F::Ticks.m_iShiftedTicks, F::Ticks.m_iShiftedGoal).c_str());
@@ -406,16 +406,41 @@ void CVisuals::DrawDebugInfo(CTFPlayer* pLocal)
{
if (Vars::Debug::Info.Value)
y += nTall;
for (auto& [sString, tColor] : m_vDebugText)
for (auto& [sString, tColor, vPosition2D, vPosition3D] : m_vDebugText)
{
if (vPosition3D)
{
if (Vec3 vScreen; SDK::W2S(*vPosition3D, vScreen))
H::Draw.StringOutlined(fFont, vScreen.x, vScreen.y, tColor, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, sString.c_str());
}
else if (vPosition2D)
H::Draw.StringOutlined(fFont, vPosition2D->x, vPosition2D->y, tColor, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, sString.c_str());
else
H::Draw.StringOutlined(fFont, x, y += nTall, tColor, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, sString.c_str());
}
}
#endif
}
#ifdef DEBUG_TEXT
void CVisuals::AddDebugText(const DebugText_t& sText)
{
m_vDebugText.push_back(sText);
}
void CVisuals::AddDebugText(const std::string& sString, Color_t tColor)
{
m_vDebugText.emplace_back(sString, tColor);
m_vDebugText.emplace_back(sString, tColor, std::nullopt, std::nullopt);
}
void CVisuals::AddDebugText(const std::string& sString, const Vec2& vPosition, Color_t tColor)
{
m_vDebugText.emplace_back(sString, tColor, vPosition, std::nullopt);
}
void CVisuals::AddDebugText(const std::string& sString, const Vec3& vPosition, Color_t tColor)
{
m_vDebugText.emplace_back(sString, tColor, std::nullopt, vPosition);
}
void CVisuals::ClearDebugText()
@@ -863,7 +888,6 @@ void CVisuals::Store()
if (!F::Groups.GetGroup(pEntity, pGroup, false) || !(pGroup->m_iTrajectory & TrajectoryEnum::Enabled))
continue;
bool bContains = m_mProjectiles.contains(pEntity);
Projectile_t& tProjectile = m_mProjectiles[pEntity];
mProjectiles[pEntity];
@@ -947,7 +971,7 @@ void CVisuals::Store()
}
}
for (auto& [pEntity, tProjectile] : m_mProjectiles)
for (auto& pEntity : m_mProjectiles | std::views::keys)
{
if (!mProjectiles.contains(pEntity))
m_mProjectiles.erase(pEntity);
@@ -1212,11 +1236,17 @@ void CVisuals::CreateMove(CTFPlayer* pLocal, CTFWeaponBase* pWeapon)
{
for (auto& tFace : vFaces)
{
if (Vars::World::Offset.Value)
Math::OffsetPolygon(tFace.m_vVertices, tFace.m_vNormal, Vars::World::Offset.Value);
if (Vars::World::Resize.Value)
Math::ExpandPolygon(tFace.m_vVertices, tFace.m_vNormal, Vars::World::Resize.Value);
F::World.DrawFace(tFace, Vars::World::Draw.Value);
/*
for (int i = 0; ++i < tFace.m_vVertices.size() - 1;)
{
const Vec3& vVertex1 = tFace.m_vVertices[0], & vVertex2 = tFace.m_vVertices[i], & vVertex3 = tFace.m_vVertices[i + 1];
const Vec3& vVertex1 = tFace.m_vVertices[0], &vVertex2 = tFace.m_vVertices[i], &vVertex3 = tFace.m_vVertices[i + 1];
Vec3 vDir21 = vVertex2 - vVertex1, vDir31 = vVertex3 - vVertex1;
float flArea = vDir21.Cross(vDir31).Length() / 2;
+14 -3
View File
@@ -1,8 +1,6 @@
#pragma once
#include "../../SDK/SDK.h"
#include <map>
//#define DEBUG_TEXT
struct Projectile_t
@@ -30,6 +28,16 @@ struct PickupData_t
Vec3 m_vLocation;
};
#ifdef DEBUG_TEXT
struct DebugText_t
{
std::string m_sText = "";
Color_t m_tColor = {};
std::optional<Vec2> vPosition2D = std::nullopt;
std::optional<Vec3> vPosition3D = std::nullopt;
};
#endif
class CVisuals
{
private:
@@ -38,7 +46,7 @@ private:
std::vector<PickupData_t> m_vPickups = {};
#ifdef DEBUG_TEXT
std::vector<std::pair<std::string, Color_t>> m_vDebugText = {};
std::vector<DebugText_t> m_vDebugText = {};
#endif
public:
@@ -52,7 +60,10 @@ public:
void DrawDebugInfo(CTFPlayer* pLocal);
#ifdef DEBUG_TEXT
void AddDebugText(const DebugText_t& sText);
void AddDebugText(const std::string& sString, Color_t tColor = Vars::Menu::Theme::Active.Value);
void AddDebugText(const std::string& sString, const Vec2& vPosition, Color_t tColor = Vars::Menu::Theme::Active.Value);
void AddDebugText(const std::string& sString, const Vec3& vPosition, Color_t tColor = Vars::Menu::Theme::Active.Value);
void ClearDebugText();
#endif
+28 -12
View File
@@ -125,7 +125,7 @@ static inline void GetFacesForConvex(CPhysConvex* pConvex, std::vector<Face_t>&
if (CPhysConvex* pConvex2 = I::PhysicsCollision->ConvexFromPlanes(reinterpret_cast<float*>(vPlanes.data()), int(vPlanes.size()), 0.f))
{
GetFacesForConvex(pConvex2, vFaces);
GetFacesForConvex(pConvex2, vFaces, 0.f, iType);
I::PhysicsCollision->ConvexFree(pConvex2);
}
}
@@ -265,11 +265,14 @@ void CWorld::CacheProps()
m_iNeedsCache &= ~FaceTypeEnum::Prop;
CUtlVector<ICollideable*> vProps; I::StaticPropMgr->GetAllStaticProps(&vProps);
for (int i = 0; i < vProps.Count(); i++)
for (int i = I::MDLCache->m_MDLDict.First(); i != I::MDLCache->m_MDLDict.InvalidIndex(); i = I::MDLCache->m_MDLDict.Next(i))
{
vcollide_t* pCollide = I::ModelInfoClient->GetVCollide(vProps[i]->GetCollisionModel());
if (!pCollide || m_mFaceCache.contains(pCollide))
studiodata_t* pStudioData = I::MDLCache->m_MDLDict[i];
if (!pStudioData)
continue;
vcollide_t* pCollide = &pStudioData->m_VCollisionData;
if (m_mFaceCache.contains(pCollide))
continue;
for (int iSolid = 0; iSolid < pCollide->solidCount; iSolid++)
@@ -474,7 +477,7 @@ std::vector<Face_t> CWorld::GetFacesInAABB(const Vec3& vMins, const Vec3& vMaxs,
vcollide_t* pCollide = I::ModelInfoClient->GetVCollide(pCollideable->GetCollisionModel());
if (!m_mFaceCache.contains(pCollide))
continue;
continue; // cache as well?
auto& vCache = m_mFaceCache[pCollide];
for (auto& tFace : vCache)
@@ -503,8 +506,21 @@ std::vector<Face_t> CWorld::GetFacesInAABB(const Vec3& vMins, const Vec3& vMaxs,
}
#ifdef WORLD_DEBUG
void CWorld::DrawFace(const Face_t& tFace, int iFlags)
void CWorld::DrawFace(const Face_t& tFace, int iFlags, std::optional<Color_t> tColor)
{
if (!tColor)
{
switch (tFace.m_iType)
{
case FaceTypeEnum::BoxBrush: tColor = Vars::World::BoxBrush.Value; break;
case FaceTypeEnum::PlaneBrush: tColor = Vars::World::PlaneBrush.Value; break;
case FaceTypeEnum::Displacement: tColor = Vars::World::Displacement.Value; break;
case FaceTypeEnum::Prop: tColor = Vars::World::Prop.Value; break;
case FaceTypeEnum::Entity: tColor = Vars::World::Entity.Value; break;
default: tColor = { 255, 255, 255 }; break;
}
}
if (iFlags & (DrawTypeEnum::Points | DrawTypeEnum::Edges))
{
for (int i = 0; i < tFace.m_vVertices.size(); i++)
@@ -512,9 +528,9 @@ void CWorld::DrawFace(const Face_t& tFace, int iFlags)
const Vec3& vVertex1 = tFace.m_vVertices[i], &vVertex2 = tFace.m_vVertices[(i + 1) % tFace.m_vVertices.size()];
if (iFlags & DrawTypeEnum::Points)
G::BoxStorage.emplace_back(vVertex1, Vec3::Get(-1), Vec3::Get(1), Vec3(0, 0, 0), I::GlobalVars->curtime + 60.f, Color_t(255, 0, 0), Color_t(0, 0, 0, 0), true);
G::BoxStorage.emplace_back(vVertex1, Vec3::Get(-1), Vec3::Get(1), Vec3(0, 0, 0), I::GlobalVars->curtime + 60.f, *tColor, Color_t(0, 0, 0, 0), true);
if (iFlags & DrawTypeEnum::Edges)
G::LineStorage.emplace_back(std::pair<Vec3, Vec3>(vVertex1, vVertex2), I::GlobalVars->curtime + 60.f, Color_t(255, 0, 0), true);
G::LineStorage.emplace_back(std::pair<Vec3, Vec3>(vVertex1, vVertex2), I::GlobalVars->curtime + 60.f, *tColor, true);
}
}
@@ -523,14 +539,14 @@ void CWorld::DrawFace(const Face_t& tFace, int iFlags)
for (int i = 0; ++i < tFace.m_vVertices.size() - 1;)
{
const Vec3& vVertex1 = tFace.m_vVertices[0], &vVertex2 = tFace.m_vVertices[i], &vVertex3 = tFace.m_vVertices[i + 1];
G::TriangleStorage.emplace_back(std::array<Vec3, 3>({ vVertex1, vVertex2, vVertex3 }), I::GlobalVars->curtime + 60.f, Color_t(255, 0, 0, 50), true);
G::TriangleStorage.emplace_back(std::array<Vec3, 3>({ vVertex1, vVertex2, vVertex3 }), I::GlobalVars->curtime + 60.f, tColor->Alpha(50), true);
}
}
if (iFlags & DrawTypeEnum::Normals)
{
G::LineStorage.emplace_back(std::pair<Vec3, Vec3>(tFace.m_vVertices[0], tFace.m_vVertices[0] + tFace.m_vNormal * 10), I::GlobalVars->curtime + 60.f, Color_t(255, 255, 0), true);
G::BoxStorage.emplace_back(tFace.m_vVertices[0] + tFace.m_vNormal * 10, Vec3::Get(-1), Vec3::Get(1), Vec3(), I::GlobalVars->curtime + 60.f, Color_t(255, 255, 0), Color_t(0, 0, 0, 0), true);
G::LineStorage.emplace_back(std::pair<Vec3, Vec3>(tFace.m_vVertices[0], tFace.m_vVertices[0] + tFace.m_vNormal * 10), I::GlobalVars->curtime + 60.f, tColor->Inverse(), true);
G::BoxStorage.emplace_back(tFace.m_vVertices[0] + tFace.m_vNormal * 10, Vec3::Get(-1), Vec3::Get(1), Vec3(), I::GlobalVars->curtime + 60.f, tColor->Inverse(), Color_t(0, 0, 0, 0), true);
}
}
#endif
+10 -4
View File
@@ -2,9 +2,6 @@
#include "../../SDK/SDK.h"
#include <functional>
#define DIST_EPSILON 0.03125f
#define CALC_EPSILON 0.001f
//#define WORLD_DEBUG
Enum(FaceType, None = 0, BoxBrush = 1 << 0, PlaneBrush = 1 << 1, Displacement = 1 << 2, Prop = 1 << 3, Entity = 1 << 4, All = BoxBrush | PlaneBrush | Displacement | Prop | Entity, Cache = BoxBrush | PlaneBrush | Prop | Entity)
@@ -17,6 +14,15 @@ namespace Vars {
"BoxBrush", "PlaneBrush", "Displacement", "Prop", "Entity");
CVarValues(Draw, "Draw", 0b0110, NOSAVE | DEBUGVAR | DROPDOWN_MULTI, nullptr,
"Points", "Edges", "Faces", "Normals");
CVar(Offset, "Offset", 0.f, NOSAVE | DEBUGVAR | SLIDER_MIN | SLIDER_PRECISION, 0.f, 1.f, DIST_EPSILON);
CVar(Resize, "Resize", 0.f, NOSAVE | DEBUGVAR | SLIDER_MIN | SLIDER_PRECISION, 0.f, 1.f, DIST_EPSILON);
CVar(BoxBrush, "BoxBrush", Color_t(255, 0, 0, 255), NOSAVE | DEBUGVAR);
CVar(PlaneBrush, "PlaneBrush", Color_t(0, 255, 0, 255), NOSAVE | DEBUGVAR);
CVar(Displacement, "Displacement", Color_t(0, 0, 255, 255), NOSAVE | DEBUGVAR);
CVar(Prop, "Prop", Color_t(255, 0, 255, 255), NOSAVE | DEBUGVAR);
CVar(Entity, "Entity", Color_t(255, 255, 0, 255), NOSAVE | DEBUGVAR);
NAMESPACE_END(World)
}
#endif
@@ -93,7 +99,7 @@ public:
void SetNormalValidCallback(NormalValidCallback* pCallback = nullptr);
#ifdef WORLD_DEBUG
void DrawFace(const Face_t& tFace, int iFlags = DrawTypeEnum::Points | DrawTypeEnum::Edges | DrawTypeEnum::Faces | DrawTypeEnum::Normals);
void DrawFace(const Face_t& tFace, int iFlags = DrawTypeEnum::Points | DrawTypeEnum::Edges | DrawTypeEnum::Faces | DrawTypeEnum::Normals, std::optional<Color_t> tColor = std::nullopt);
#endif
};
@@ -14,7 +14,7 @@ MAKE_HOOK(CClientModeShared_DoPostScreenSpaceEffects, U::Memory.GetVirtual(I::Cl
{
DEBUG_RETURN(CClientModeShared_DoPostScreenSpaceEffects, rcx, pSetup);
if (SDK::CleanScreenshot())
if (SDK::CleanScreenshot() || G::Unload)
return CALL_ORIGINAL(rcx, pSetup);
F::Visuals.ProjectileTrace(H::Entities.GetLocal(), H::Entities.GetWeapon());
-1
View File
@@ -1,7 +1,6 @@
#include "../SDK/SDK.h"
#include "../SDK/Definitions/Misc/TraceInfo.h"
#include <optional>
MAKE_SIGNATURE(CM_TraceToDispTree_True, "engine.dll", "48 8B C4 48 89 58 ? 48 89 70 ? 57 48 81 EC ? ? ? ? F3 0F 10 01", 0x0);
MAKE_SIGNATURE(CM_TraceToDispTree_False, "engine.dll", "48 8B C4 48 89 58 ? 48 89 70 ? 57 48 83 EC ? F3 0F 10 01", 0x0);
@@ -3,7 +3,7 @@
#include "../Features/World/World.h"
MAKE_SIGNATURE(CModelLoader_Map_LoadModel, "engine.dll", "48 8B C4 48 89 58 ? 48 89 50 ? 48 89 48 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? FF 05", 0x0);
MAKE_SIGNATURE(CStaticPropMgr_LevelInit, "engine.dll", "40 57 48 81 EC ? ? ? ? 80 B9", 0x0);
MAKE_SIGNATURE(R_LevelInit, "engine.dll", "48 83 EC ? 48 8D 0D ? ? ? ? FF 15 ? ? ? ? 48 8D 0D ? ? ? ? FF 15", 0x0);
MAKE_SIGNATURE(CM_FreeMap, "engine.dll", "48 8D 0D ? ? ? ? E9 ? ? ? ? CC CC CC CC 48 89 5C 24 ? 57 48 83 EC ? 45 33 C9", 0x0);
MAKE_HOOK(CModelLoader_Map_LoadModel, S::CModelLoader_Map_LoadModel(), void,
@@ -18,12 +18,12 @@ MAKE_HOOK(CModelLoader_Map_LoadModel, S::CModelLoader_Map_LoadModel(), void,
F::World.CacheEntities();
}
MAKE_HOOK(CStaticPropMgr_LevelInit, S::CStaticPropMgr_LevelInit(), void,
void* rcx)
MAKE_HOOK(R_LevelInit, S::R_LevelInit(), void,
)
{
DEBUG_RETURN(CStaticPropMgr_LevelInit, rcx);
DEBUG_RETURN(R_LevelInit);
CALL_ORIGINAL(rcx);
CALL_ORIGINAL();
F::World.CacheProps();
}
+1
View File
@@ -9,6 +9,7 @@
#include "Interfaces/CGlobalVarsBase.h"
#include "Interfaces/CHLClient.h"
#include "Interfaces/CHLTVCamera.h"
#include "Interfaces/CMDLCache.h"
#include "Interfaces/CStaticPropMgr.h"
#include "Interfaces/CTFGameRules.h"
#include "Interfaces/CTFGCClientSystem.h"
@@ -0,0 +1,118 @@
#pragma once
#include "../Misc/IMDLCache.h"
#include "../Misc/IStudioDataCache.h"
#include "../Misc/CDefaultDataCacheClient.h"
#include "../Misc/VCollide.h"
#include "../Misc/Studio.h"
#include "../Misc/CUtlDict.h"
#include "../Misc/CUtlLinkedList.h"
class IDataCacheSection;
typedef void* DataCacheHandle_t;
struct studiodata_t
{
DataCacheHandle_t m_MDLCache;
vcollide_t m_VCollisionData;
studiohwdata_t m_HardwareData;
#if defined( USE_HARDWARE_CACHE )
DataCacheHandle_t m_HardwareDataCache;
#endif
unsigned short m_nFlags;
short m_nRefCount;
virtualmodel_t* m_pVirtualModel;
int m_nAnimBlockCount;
DataCacheHandle_t* m_pAnimBlock;
unsigned long* m_iFakeAnimBlockStall;
DataCacheHandle_t m_VertexCache;
bool m_VertexDataIsCompressed;
int m_nAutoplaySequenceCount;
unsigned short* m_pAutoplaySequenceList;
void* m_pUserData;
};
struct AsyncInfo_t
{
FSAsyncControl_t hControl;
MDLHandle_t hModel;
MDLCacheDataType_t type;
int iAnimBlock;
};
class CThreadFastMutex
{
public:
volatile uint32 m_ownerID;
int m_depth;
};
class CMDLCache : public CTier3AppSystem<IMDLCache>, public IStudioDataCache, public CDefaultDataCacheClient
{
typedef CTier3AppSystem<IMDLCache> BaseClass;
public:
virtual bool Connect(CreateInterfaceFn factory) = 0;
virtual void Disconnect() = 0;
virtual void* QueryInterface(const char* pInterfaceName) = 0;
virtual InitReturnVal_t Init() = 0;
virtual void Shutdown() = 0;
virtual MDLHandle_t FindMDL(const char* pMDLRelativePath) = 0;
virtual int AddRef(MDLHandle_t handle) = 0;
virtual int Release(MDLHandle_t handle) = 0;
virtual int GetRef(MDLHandle_t handle) = 0;
virtual void MarkAsLoaded(MDLHandle_t handle) = 0;
virtual studiohdr_t* GetStudioHdr(MDLHandle_t handle) = 0;
virtual studiohwdata_t* GetHardwareData(MDLHandle_t handle) = 0;
virtual vcollide_t* GetVCollide(MDLHandle_t handle) = 0;
virtual vcollide_t* GetVCollideEx(MDLHandle_t handle, bool synchronousLoad = true) = 0;
virtual unsigned char* GetAnimBlock(MDLHandle_t handle, int nBlock) = 0;
virtual virtualmodel_t* GetVirtualModel(MDLHandle_t handle) = 0;
virtual virtualmodel_t* GetVirtualModelFast(const studiohdr_t* pStudioHdr, MDLHandle_t handle) = 0;
virtual int GetAutoplayList(MDLHandle_t handle, unsigned short** pOut) = 0;
virtual void TouchAllData(MDLHandle_t handle) = 0;
virtual void SetUserData(MDLHandle_t handle, void* pData) = 0;
virtual void* GetUserData(MDLHandle_t handle) = 0;
virtual bool IsErrorModel(MDLHandle_t handle) = 0;
virtual void SetCacheNotify(IMDLCacheNotify* pNotify) = 0;
virtual vertexFileHeader_t* GetVertexData(MDLHandle_t handle) = 0;
virtual void Flush(MDLCacheFlush_t nFlushFlags = MDLCACHE_FLUSH_ALL) = 0;
virtual void Flush(MDLHandle_t handle, int nFlushFlags = MDLCACHE_FLUSH_ALL) = 0;
virtual const char* GetModelName(MDLHandle_t handle) = 0;
virtual void BeginLock() = 0;
virtual void EndLock() = 0;
virtual int* GetFrameUnlockCounterPtrOLD() = 0;
virtual int* GetFrameUnlockCounterPtr(MDLCacheDataType_t type) = 0;
virtual void FinishPendingLoads() = 0;
virtual bool GetVCollideSize(MDLHandle_t handle, int* pVCollideSize) = 0;
virtual void BeginMapLoad() = 0;
virtual void EndMapLoad() = 0;
virtual void InitPreloadData(bool rebuild) = 0;
virtual void ShutdownPreloadData() = 0;
virtual bool IsDataLoaded(MDLHandle_t handle, MDLCacheDataType_t type) = 0;
virtual studiohdr_t* LockStudioHdr(MDLHandle_t handle) = 0;
virtual void UnlockStudioHdr(MDLHandle_t handle) = 0;
virtual bool PreloadModel(MDLHandle_t handle) = 0;
virtual void ResetErrorModelStatus(MDLHandle_t handle) = 0;
virtual void MarkFrame() = 0;
virtual bool HandleCacheNotification(const DataCacheNotification_t& notification) = 0;
virtual bool GetItemName(DataCacheClientID_t clientId, const void* pItem, char* pDest, unsigned nMaxLen) = 0;
virtual bool GetAsyncLoad(MDLCacheDataType_t type) = 0;
virtual bool SetAsyncLoad(MDLCacheDataType_t type, bool bAsync) = 0;
public:
IDataCacheSection* m_pModelCacheSection;
IDataCacheSection* m_pMeshCacheSection;
IDataCacheSection* m_pAnimBlockCacheSection;
int m_nModelCacheFrameLocks;
int m_nMeshCacheFrameLocks;
CUtlDict<studiodata_t*, MDLHandle_t> m_MDLDict;
IMDLCacheNotify* m_pCacheNotify;
CUtlFixedLinkedList<AsyncInfo_t> m_PendingAsyncs;
CThreadFastMutex m_QueuedLoadingMutex;
CThreadFastMutex m_AsyncMutex;
bool m_bLostVideoMemory : 1;
bool m_bConnected : 1;
bool m_bInitialized : 1;
};
MAKE_INTERFACE_VERSION(CMDLCache, MDLCache, "datacache.dll", "MDLCache004");
@@ -16,7 +16,6 @@ struct studiomeshdata_t;
struct LightDesc_t;
struct studiohwdata_t;
struct Ray_t;
struct vertexFileHeader_t;
struct FlashlightState_t;
struct FileHeader_t;
typedef unsigned short MDLHandle_t;
@@ -175,13 +174,6 @@ struct model_array_instance_t
matrix3x4 modelToWorld;
};
class IStudioDataCache : public IAppSystem
{
public:
virtual bool VerifyHeaders(studiohdr_t* pStudioHdr) = 0;
virtual vertexFileHeader_t* CacheVertexData(studiohdr_t* pStudioHdr) = 0;
};
class IStudioRender : public IAppSystem
{
public:
@@ -0,0 +1,55 @@
#pragma once
#include "BaseTypes.h"
typedef uint32 DataCacheClientID_t;
enum DataCacheNotificationType_t
{
DC_NONE,
DC_AGE_DISCARD,
DC_FLUSH_DISCARD,
DC_REMOVED,
DC_RELOCATE,
DC_PRINT_INF0,
};
struct DataCacheNotification_t
{
DataCacheNotificationType_t type;
const char* pszSectionName;
DataCacheClientID_t clientId;
const void* pItemData;
unsigned nItemSize;
};
class IDataCacheClient
{
public:
virtual bool HandleCacheNotification(const DataCacheNotification_t& notification) = 0;
virtual bool GetItemName(DataCacheClientID_t clientId, const void* pItem, char* pDest, unsigned nMaxLen) = 0;
};
//-------------------------------------
class CDefaultDataCacheClient : public IDataCacheClient
{
public:
virtual bool HandleCacheNotification(const DataCacheNotification_t& notification)
{
switch (notification.type)
{
case DC_AGE_DISCARD:
case DC_FLUSH_DISCARD:
case DC_REMOVED:
default:
//Assert(0);
return false;
}
return false;
}
virtual bool GetItemName(DataCacheClientID_t clientId, const void* pItem, char* pDest, unsigned nMaxLen)
{
return false;
}
};
@@ -0,0 +1,332 @@
#pragma once
#pragma warning (push)
#pragma warning (disable:4100)
#pragma warning (disable:4514)
#ifdef UTBLOCKLMEMORY_TRACK
#define UTLBLOCKMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlBlockMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
#define UTLBLOCKMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlBlockMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
#else
#define UTLBLOCKMEMORY_TRACK_ALLOC() ((void)0)
#define UTLBLOCKMEMORY_TRACK_FREE() ((void)0)
#endif
__forceinline uint SmallestPowerOfTwoGreaterOrEqual(uint x)
{
x -= 1;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;
}
template< class T, class I >
class CUtlBlockMemory
{
public:
// constructor, destructor
CUtlBlockMemory(int nGrowSize = 0, int nInitSize = 0);
~CUtlBlockMemory();
// Set the size by which the memory grows - round up to the next power of 2
void Init(int nGrowSize = 0, int nInitSize = 0);
// here to match CUtlMemory, but only used by ResetDbgInfo, so it can just return NULL
T* Base() { return NULL; }
const T* Base() const { return NULL; }
class Iterator_t
{
public:
Iterator_t(I i) : index(i) {}
I index;
bool operator==(const Iterator_t it) const { return index == it.index; }
bool operator!=(const Iterator_t it) const { return index != it.index; }
};
Iterator_t First() const { return Iterator_t(IsIdxValid(0) ? 0 : InvalidIndex()); }
Iterator_t Next(const Iterator_t& it) const { return Iterator_t(IsIdxValid(it.index + 1) ? it.index + 1 : InvalidIndex()); }
I GetIndex(const Iterator_t& it) const { return it.index; }
bool IsIdxAfter(I i, const Iterator_t& it) const { return i > it.index; }
bool IsValidIterator(const Iterator_t& it) const { return IsIdxValid(it.index); }
Iterator_t InvalidIterator() const { return Iterator_t(InvalidIndex()); }
// element access
T& operator[](I i);
const T& operator[](I i) const;
T& Element(I i);
const T& Element(I i) const;
// Can we use this index?
bool IsIdxValid(I i) const;
static I InvalidIndex() { return (I)-1; }
void Swap(CUtlBlockMemory< T, I >& mem);
// Size
int NumAllocated() const;
int Count() const { return NumAllocated(); }
// Grows memory by max(num,growsize) rounded up to the next power of 2, and returns the allocation index/ptr
void Grow(int num = 1);
// Makes sure we've got at least this much memory
void EnsureCapacity(int num);
// Memory deallocation
void Purge();
// Purge all but the given number of elements
void Purge(int numElements);
protected:
int Index(int major, int minor) const { return (major << m_nIndexShift) | minor; }
int MajorIndex(int i) const { return i >> m_nIndexShift; }
int MinorIndex(int i) const { return i & m_nIndexMask; }
void ChangeSize(int nBlocks);
int NumElementsInBlock() const { return m_nIndexMask + 1; }
T** m_pMemory;
int m_nBlocks;
int m_nIndexMask : 27;
int m_nIndexShift : 5;
};
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
template< class T, class I >
CUtlBlockMemory<T, I>::CUtlBlockMemory(int nGrowSize, int nInitAllocationCount)
: m_pMemory(0), m_nBlocks(0), m_nIndexMask(0), m_nIndexShift(0)
{
Init(nGrowSize, nInitAllocationCount);
}
template< class T, class I >
CUtlBlockMemory<T, I>::~CUtlBlockMemory()
{
Purge();
}
//-----------------------------------------------------------------------------
// Fast swap
//-----------------------------------------------------------------------------
template< class T, class I >
void CUtlBlockMemory<T, I>::Swap(CUtlBlockMemory< T, I >& mem)
{
std::swap(m_pMemory, mem.m_pMemory);
std::swap(m_nBlocks, mem.m_nBlocks);
std::swap(m_nIndexMask, mem.m_nIndexMask);
std::swap(m_nIndexShift, mem.m_nIndexShift);
}
//-----------------------------------------------------------------------------
// Set the size by which the memory grows - round up to the next power of 2
//-----------------------------------------------------------------------------
template< class T, class I >
void CUtlBlockMemory<T, I>::Init(int nGrowSize /* = 0 */, int nInitSize /* = 0 */)
{
Purge();
if (nGrowSize == 0)
{
// default grow size is smallest size s.t. c++ allocation overhead is ~6% of block size
nGrowSize = (127 + sizeof(T)) / sizeof(T);
}
nGrowSize = SmallestPowerOfTwoGreaterOrEqual(nGrowSize);
m_nIndexMask = nGrowSize - 1;
m_nIndexShift = 0;
while (nGrowSize > 1)
{
nGrowSize >>= 1;
++m_nIndexShift;
}
//Assert(m_nIndexMask + 1 == (1 << m_nIndexShift));
Grow(nInitSize);
}
//-----------------------------------------------------------------------------
// element access
//-----------------------------------------------------------------------------
template< class T, class I >
inline T& CUtlBlockMemory<T, I>::operator[](I i)
{
//Assert(IsIdxValid(i));
T* pBlock = m_pMemory[MajorIndex(i)];
return pBlock[MinorIndex(i)];
}
template< class T, class I >
inline const T& CUtlBlockMemory<T, I>::operator[](I i) const
{
//Assert(IsIdxValid(i));
const T* pBlock = m_pMemory[MajorIndex(i)];
return pBlock[MinorIndex(i)];
}
template< class T, class I >
inline T& CUtlBlockMemory<T, I>::Element(I i)
{
//Assert(IsIdxValid(i));
T* pBlock = m_pMemory[MajorIndex(i)];
return pBlock[MinorIndex(i)];
}
template< class T, class I >
inline const T& CUtlBlockMemory<T, I>::Element(I i) const
{
//Assert(IsIdxValid(i));
const T* pBlock = m_pMemory[MajorIndex(i)];
return pBlock[MinorIndex(i)];
}
//-----------------------------------------------------------------------------
// Size
//-----------------------------------------------------------------------------
template< class T, class I >
inline int CUtlBlockMemory<T, I>::NumAllocated() const
{
return m_nBlocks * NumElementsInBlock();
}
//-----------------------------------------------------------------------------
// Is element index valid?
//-----------------------------------------------------------------------------
template< class T, class I >
inline bool CUtlBlockMemory<T, I>::IsIdxValid(I i) const
{
return (i >= 0) && (MajorIndex(i) < m_nBlocks);
}
template< class T, class I >
void CUtlBlockMemory<T, I>::Grow(int num)
{
if (num <= 0)
return;
int nBlockSize = NumElementsInBlock();
int nBlocks = (num + nBlockSize - 1) / nBlockSize;
ChangeSize(m_nBlocks + nBlocks);
}
template< class T, class I >
void CUtlBlockMemory<T, I>::ChangeSize(int nBlocks)
{
UTLBLOCKMEMORY_TRACK_FREE(); // this must stay before the recalculation of m_nBlocks, since it implicitly uses the old value
int nBlocksOld = m_nBlocks;
m_nBlocks = nBlocks;
UTLBLOCKMEMORY_TRACK_ALLOC(); // this must stay after the recalculation of m_nBlocks, since it implicitly uses the new value
if (m_pMemory)
{
// free old blocks if shrinking
// Only possible if m_pMemory is non-NULL (and avoids PVS-Studio warning)
for (int i = m_nBlocks; i < nBlocksOld; ++i)
{
UTLBLOCKMEMORY_TRACK_FREE();
free((void*)m_pMemory[i]);
}
MEM_ALLOC_CREDIT_CLASS();
m_pMemory = (T**)realloc(m_pMemory, m_nBlocks * sizeof(T*));
//Assert(m_pMemory);
}
else
{
MEM_ALLOC_CREDIT_CLASS();
m_pMemory = (T**)malloc(m_nBlocks * sizeof(T*));
//Assert(m_pMemory);
}
if (!m_pMemory)
{
//Error("CUtlBlockMemory overflow!\n");
}
// allocate new blocks if growing
int nBlockSize = NumElementsInBlock();
for (int i = nBlocksOld; i < m_nBlocks; ++i)
{
MEM_ALLOC_CREDIT_CLASS();
m_pMemory[i] = (T*)malloc(nBlockSize * sizeof(T));
//Assert(m_pMemory[i]);
}
}
//-----------------------------------------------------------------------------
// Makes sure we've got at least this much memory
//-----------------------------------------------------------------------------
template< class T, class I >
inline void CUtlBlockMemory<T, I>::EnsureCapacity(int num)
{
Grow(num - NumAllocated());
}
//-----------------------------------------------------------------------------
// Memory deallocation
//-----------------------------------------------------------------------------
template< class T, class I >
void CUtlBlockMemory<T, I>::Purge()
{
if (!m_pMemory)
return;
for (int i = 0; i < m_nBlocks; ++i)
{
UTLBLOCKMEMORY_TRACK_FREE();
free((void*)m_pMemory[i]);
}
m_nBlocks = 0;
UTLBLOCKMEMORY_TRACK_FREE();
free((void*)m_pMemory);
m_pMemory = 0;
}
template< class T, class I >
void CUtlBlockMemory<T, I>::Purge(int numElements)
{
//Assert(numElements >= 0);
int nAllocated = NumAllocated();
if (numElements > nAllocated)
{
// Ensure this isn't a grow request in disguise.
//Assert(numElements <= nAllocated);
return;
}
if (numElements <= 0)
{
Purge();
return;
}
int nBlockSize = NumElementsInBlock();
int nBlocksOld = m_nBlocks;
int nBlocks = (numElements + nBlockSize - 1) / nBlockSize;
// If the number of blocks is the same as the allocated number of blocks, we are done.
if (nBlocks == m_nBlocks)
return;
ChangeSize(nBlocks);
}
#pragma warning (pop)
+327
View File
@@ -0,0 +1,327 @@
#pragma once
#include "CUtlMap.h"
enum EDictCompareType
{
k_eDictCompareTypeCaseSensitive = 0,
k_eDictCompareTypeCaseInsensitive = 1,
k_eDictCompareTypeFilenames
};
#define FOR_EACH_DICT( dictName, iteratorName ) \
for( int iteratorName=dictName.First(); iteratorName != dictName.InvalidIndex(); iteratorName = dictName.Next( iteratorName ) )
#define FOR_EACH_DICT_FAST( dictName, iteratorName ) \
for ( int iteratorName = 0; iteratorName < dictName.MaxElement(); ++iteratorName ) if ( !dictName.IsValidIndex( iteratorName ) ) continue; else
template <class T, class I = int >
class CUtlDict
{
public:
// constructor, destructor
// Left at growSize = 0, the memory will first allocate 1 element and double in size
// at each increment.
CUtlDict(int compareType = k_eDictCompareTypeCaseInsensitive, int growSize = 0, int initSize = 0);
~CUtlDict();
void EnsureCapacity(int);
// gets particular elements
T& Element(I i);
const T& Element(I i) const;
T& operator[](I i);
const T& operator[](I i) const;
// gets element names
char* GetElementName(I i);
char const* GetElementName(I i) const;
void SetElementName(I i, char const* pName);
// Number of elements
unsigned int Count() const;
// Number of allocated slots
I MaxElement() const;
// Checks if a node is valid and in the tree
bool IsValidIndex(I i) const;
// Invalid index
static I InvalidIndex();
// Insert method (inserts in order)
I Insert(const char* pName, const T& element);
I Insert(const char* pName);
// Find method
I Find(const char* pName) const;
bool HasElement(const char* pName) const;
// Remove methods
void RemoveAt(I i);
void Remove(const char* pName);
void RemoveAll();
// Purge memory
void Purge();
void PurgeAndDeleteElements(); // Call delete on each element.
// Iteration methods
I First() const;
I Next(I i) const;
// Nested typedefs, for code that might need
// to fish out the index type from a given dict
typedef I IndexType_t;
protected:
typedef CUtlMap<const char*, T, I> DictElementMap_t;
DictElementMap_t m_Elements;
};
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
template <class T, class I>
CUtlDict<T, I>::CUtlDict(int compareType, int growSize, int initSize) : m_Elements(growSize, initSize)
{
if (compareType == k_eDictCompareTypeFilenames)
{
m_Elements.SetLessFunc(CaselessStringLessThanIgnoreSlashes);
}
else if (compareType == k_eDictCompareTypeCaseInsensitive)
{
m_Elements.SetLessFunc(CaselessStringLessThan);
}
else
{
m_Elements.SetLessFunc(StringLessThan);
}
}
template <class T, class I>
CUtlDict<T, I>::~CUtlDict()
{
Purge();
}
template <class T, class I>
inline void CUtlDict<T, I>::EnsureCapacity(int num)
{
return m_Elements.EnsureCapacity(num);
}
//-----------------------------------------------------------------------------
// gets particular elements
//-----------------------------------------------------------------------------
template <class T, class I>
inline T& CUtlDict<T, I>::Element(I i)
{
return m_Elements[i];
}
template <class T, class I>
inline const T& CUtlDict<T, I>::Element(I i) const
{
return m_Elements[i];
}
//-----------------------------------------------------------------------------
// gets element names
//-----------------------------------------------------------------------------
template <class T, class I>
inline char* CUtlDict<T, I>::GetElementName(I i)
{
return (char*)m_Elements.Key(i);
}
template <class T, class I>
inline char const* CUtlDict<T, I>::GetElementName(I i) const
{
return m_Elements.Key(i);
}
template <class T, class I>
inline T& CUtlDict<T, I>::operator[](I i)
{
return Element(i);
}
template <class T, class I>
inline const T& CUtlDict<T, I>::operator[](I i) const
{
return Element(i);
}
template <class T, class I>
inline void CUtlDict<T, I>::SetElementName(I i, char const* pName)
{
MEM_ALLOC_CREDIT_CLASS();
// TODO: This makes a copy of the old element
// TODO: This relies on the rb tree putting the most recently
// removed element at the head of the insert list
free((void*)m_Elements.Key(i));
m_Elements.Reinsert(strdup(pName), i);
}
//-----------------------------------------------------------------------------
// Num elements
//-----------------------------------------------------------------------------
template <class T, class I>
inline unsigned int CUtlDict<T, I>::Count() const
{
return m_Elements.Count();
}
//-----------------------------------------------------------------------------
// Number of allocated slots
//-----------------------------------------------------------------------------
template <class T, class I>
inline I CUtlDict<T, I>::MaxElement() const
{
return m_Elements.MaxElement();
}
//-----------------------------------------------------------------------------
// Checks if a node is valid and in the tree
//-----------------------------------------------------------------------------
template <class T, class I>
inline bool CUtlDict<T, I>::IsValidIndex(I i) const
{
return m_Elements.IsValidIndex(i);
}
//-----------------------------------------------------------------------------
// Invalid index
//-----------------------------------------------------------------------------
template <class T, class I>
inline I CUtlDict<T, I>::InvalidIndex()
{
return DictElementMap_t::InvalidIndex();
}
//-----------------------------------------------------------------------------
// Delete a node from the tree
//-----------------------------------------------------------------------------
template <class T, class I>
void CUtlDict<T, I>::RemoveAt(I elem)
{
free((void*)m_Elements.Key(elem));
m_Elements.RemoveAt(elem);
}
//-----------------------------------------------------------------------------
// remove a node in the tree
//-----------------------------------------------------------------------------
template <class T, class I> void CUtlDict<T, I>::Remove(const char* search)
{
I node = Find(search);
if (node != InvalidIndex())
{
RemoveAt(node);
}
}
//-----------------------------------------------------------------------------
// Removes all nodes from the tree
//-----------------------------------------------------------------------------
template <class T, class I>
void CUtlDict<T, I>::RemoveAll()
{
typename DictElementMap_t::IndexType_t index = m_Elements.FirstInorder();
while (index != m_Elements.InvalidIndex())
{
free((void*)m_Elements.Key(index));
index = m_Elements.NextInorder(index);
}
m_Elements.RemoveAll();
}
template <class T, class I>
void CUtlDict<T, I>::Purge()
{
RemoveAll();
}
template <class T, class I>
void CUtlDict<T, I>::PurgeAndDeleteElements()
{
// Delete all the elements.
I index = m_Elements.FirstInorder();
while (index != m_Elements.InvalidIndex())
{
free((void*)m_Elements.Key(index));
delete m_Elements[index];
index = m_Elements.NextInorder(index);
}
m_Elements.RemoveAll();
}
//-----------------------------------------------------------------------------
// inserts a node into the tree
//-----------------------------------------------------------------------------
template <class T, class I>
I CUtlDict<T, I>::Insert(const char* pName, const T& element)
{
MEM_ALLOC_CREDIT_CLASS();
return m_Elements.Insert(strdup(pName), element);
}
template <class T, class I>
I CUtlDict<T, I>::Insert(const char* pName)
{
MEM_ALLOC_CREDIT_CLASS();
return m_Elements.Insert(strdup(pName));
}
//-----------------------------------------------------------------------------
// finds a node in the tree
//-----------------------------------------------------------------------------
template <class T, class I>
I CUtlDict<T, I>::Find(const char* pName) const
{
MEM_ALLOC_CREDIT_CLASS();
if (pName)
return m_Elements.Find(pName);
else
return InvalidIndex();
}
//-----------------------------------------------------------------------------
// returns true if we already have this node
//-----------------------------------------------------------------------------
template <class T, class I>
bool CUtlDict<T, I>::HasElement(const char* pName) const
{
if (pName)
return m_Elements.IsValidIndex(m_Elements.Find(pName));
else
return false;
}
//-----------------------------------------------------------------------------
// Iteration methods
//-----------------------------------------------------------------------------
template <class T, class I>
I CUtlDict<T, I>::First() const
{
return m_Elements.FirstInorder();
}
template <class T, class I>
I CUtlDict<T, I>::Next(I i) const
{
return m_Elements.NextInorder(i);
}
@@ -0,0 +1,327 @@
#pragma once
#include "../Steam/SteamTypes.h"
#pragma warning (push)
#pragma warning (disable:4100)
#pragma warning (disable:4514)
#ifdef UTLFIXEDMEMORY_TRACK
#define UTLFIXEDMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlFixedMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
#define UTLFIXEDMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlFixedMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
#else
#define UTLFIXEDMEMORY_TRACK_ALLOC() ((void)0)
#define UTLFIXEDMEMORY_TRACK_FREE() ((void)0)
#endif
template< class T >
class CUtlFixedMemory
{
public:
// constructor, destructor
CUtlFixedMemory(int nGrowSize = 0, int nInitSize = 0);
~CUtlFixedMemory();
// Set the size by which the memory grows
void Init(int nGrowSize = 0, int nInitSize = 0);
// here to match CUtlMemory, but only used by ResetDbgInfo, so it can just return NULL
T* Base() { return NULL; }
const T* Base() const { return NULL; }
protected:
struct BlockHeader_t;
public:
class Iterator_t
{
public:
Iterator_t(BlockHeader_t* p, int i) : m_pBlockHeader(p), m_nIndex(i) {}
BlockHeader_t* m_pBlockHeader;
intp m_nIndex;
bool operator==(const Iterator_t it) const { return m_pBlockHeader == it.m_pBlockHeader && m_nIndex == it.m_nIndex; }
bool operator!=(const Iterator_t it) const { return m_pBlockHeader != it.m_pBlockHeader || m_nIndex != it.m_nIndex; }
};
Iterator_t First() const { return m_pBlocks ? Iterator_t(m_pBlocks, 0) : InvalidIterator(); }
Iterator_t Next(const Iterator_t& it) const
{
//Assert(IsValidIterator(it));
if (!IsValidIterator(it))
return InvalidIterator();
BlockHeader_t* RESTRICT pHeader = it.m_pBlockHeader;
if (it.m_nIndex + 1 < pHeader->m_nBlockSize)
return Iterator_t(pHeader, it.m_nIndex + 1);
return pHeader->m_pNext ? Iterator_t(pHeader->m_pNext, 0) : InvalidIterator();
}
intp GetIndex(const Iterator_t& it) const
{
//Assert(IsValidIterator(it));
if (!IsValidIterator(it))
return InvalidIndex();
return (intp)(HeaderToBlock(it.m_pBlockHeader) + it.m_nIndex);
}
bool IsIdxAfter(intp i, const Iterator_t& it) const
{
//Assert(IsValidIterator(it));
if (!IsValidIterator(it))
return false;
if (IsInBlock(i, it.m_pBlockHeader))
return i > GetIndex(it);
for (BlockHeader_t* RESTRICT pbh = it.m_pBlockHeader->m_pNext; pbh; pbh = pbh->m_pNext)
{
if (IsInBlock(i, pbh))
return true;
}
return false;
}
bool IsValidIterator(const Iterator_t& it) const { return it.m_pBlockHeader && it.m_nIndex >= 0 && it.m_nIndex < it.m_pBlockHeader->m_nBlockSize; }
Iterator_t InvalidIterator() const { return Iterator_t(NULL, INVALID_INDEX); }
// element access
T& operator[](intp i);
const T& operator[](intp i) const;
T& Element(intp i);
const T& Element(intp i) const;
// Can we use this index?
bool IsIdxValid(intp i) const;
// Specify the invalid ('null') index that we'll only return on failure
static const intp INVALID_INDEX = 0; // For use with COMPILE_TIME_ASSERT
static intp InvalidIndex() { return INVALID_INDEX; }
// Size
int NumAllocated() const;
int Count() const { return NumAllocated(); }
// Grows memory by max(num,growsize), and returns the allocation index/ptr
void Grow(int num = 1);
// Makes sure we've got at least this much memory
void EnsureCapacity(int num);
// Memory deallocation
void Purge();
protected:
// Fast swap - WARNING: Swap invalidates all ptr-based indices!!!
void Swap(CUtlFixedMemory< T >& mem);
bool IsInBlock(intp i, BlockHeader_t* pBlockHeader) const
{
T* p = (T*)i;
const T* p0 = HeaderToBlock(pBlockHeader);
return p >= p0 && p < p0 + pBlockHeader->m_nBlockSize;
}
struct BlockHeader_t
{
BlockHeader_t* m_pNext;
intp m_nBlockSize;
};
const T* HeaderToBlock(const BlockHeader_t* pHeader) const { return (T*)(pHeader + 1); }
const BlockHeader_t* BlockToHeader(const T* pBlock) const { return (BlockHeader_t*)(pBlock)-1; }
BlockHeader_t* m_pBlocks;
int m_nAllocationCount;
int m_nGrowSize;
};
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
template< class T >
CUtlFixedMemory<T>::CUtlFixedMemory(int nGrowSize, int nInitAllocationCount)
: m_pBlocks(0), m_nAllocationCount(0), m_nGrowSize(0)
{
Init(nGrowSize, nInitAllocationCount);
}
template< class T >
CUtlFixedMemory<T>::~CUtlFixedMemory()
{
Purge();
}
//-----------------------------------------------------------------------------
// Fast swap - WARNING: Swap invalidates all ptr-based indices!!!
//-----------------------------------------------------------------------------
template< class T >
void CUtlFixedMemory<T>::Swap(CUtlFixedMemory< T >& mem)
{
V_swap(m_pBlocks, mem.m_pBlocks);
V_swap(m_nAllocationCount, mem.m_nAllocationCount);
V_swap(m_nGrowSize, mem.m_nGrowSize);
}
//-----------------------------------------------------------------------------
// Set the size by which the memory grows - round up to the next power of 2
//-----------------------------------------------------------------------------
template< class T >
void CUtlFixedMemory<T>::Init(int nGrowSize /* = 0 */, int nInitSize /* = 0 */)
{
Purge();
m_nGrowSize = nGrowSize;
Grow(nInitSize);
}
//-----------------------------------------------------------------------------
// element access
//-----------------------------------------------------------------------------
template< class T >
inline T& CUtlFixedMemory<T>::operator[](intp i)
{
//Assert(IsIdxValid(i));
return *(T*)i;
}
template< class T >
inline const T& CUtlFixedMemory<T>::operator[](intp i) const
{
//Assert(IsIdxValid(i));
return *(T*)i;
}
template< class T >
inline T& CUtlFixedMemory<T>::Element(intp i)
{
//Assert(IsIdxValid(i));
return *(T*)i;
}
template< class T >
inline const T& CUtlFixedMemory<T>::Element(intp i) const
{
//Assert(IsIdxValid(i));
return *(T*)i;
}
//-----------------------------------------------------------------------------
// Size
//-----------------------------------------------------------------------------
template< class T >
inline int CUtlFixedMemory<T>::NumAllocated() const
{
return m_nAllocationCount;
}
//-----------------------------------------------------------------------------
// Is element index valid?
//-----------------------------------------------------------------------------
template< class T >
inline bool CUtlFixedMemory<T>::IsIdxValid(intp i) const
{
#ifdef _DEBUG
for (BlockHeader_t* pbh = m_pBlocks; pbh; pbh = pbh->m_pNext)
{
if (IsInBlock(i, pbh))
return true;
}
return false;
#else
return i != InvalidIndex();
#endif
}
template< class T >
void CUtlFixedMemory<T>::Grow(int num)
{
if (num <= 0)
return;
int nBlockSize = m_nGrowSize;
if (nBlockSize == 0)
{
if (m_nAllocationCount)
{
nBlockSize = m_nAllocationCount;
}
else
{
// Compute an allocation which is at least as big as a cache line...
nBlockSize = (31 + sizeof(T)) / sizeof(T);
//Assert(nBlockSize);
}
}
if (nBlockSize < num)
{
int n = (num + nBlockSize - 1) / nBlockSize;
//Assert(n * nBlockSize >= num);
//Assert((n - 1) * nBlockSize < num);
nBlockSize *= n;
}
m_nAllocationCount += nBlockSize;
MEM_ALLOC_CREDIT_CLASS();
BlockHeader_t* RESTRICT pBlockHeader = (BlockHeader_t*)malloc(sizeof(BlockHeader_t) + nBlockSize * sizeof(T));
if (!pBlockHeader)
{
//Error("CUtlFixedMemory overflow!\n");
}
pBlockHeader->m_pNext = NULL;
pBlockHeader->m_nBlockSize = nBlockSize;
if (!m_pBlocks)
{
m_pBlocks = pBlockHeader;
}
else
{
#if 1 // IsIdxAfter assumes that newly allocated blocks are at the end
BlockHeader_t* RESTRICT pbh = m_pBlocks;
while (pbh->m_pNext)
{
pbh = pbh->m_pNext;
}
pbh->m_pNext = pBlockHeader;
#else
pBlockHeader = m_pBlocks;
pBlockHeader->m_pNext = m_pBlocks;
#endif
}
}
//-----------------------------------------------------------------------------
// Makes sure we've got at least this much memory
//-----------------------------------------------------------------------------
template< class T >
inline void CUtlFixedMemory<T>::EnsureCapacity(int num)
{
Grow(num - NumAllocated());
}
//-----------------------------------------------------------------------------
// Memory deallocation
//-----------------------------------------------------------------------------
template< class T >
void CUtlFixedMemory<T>::Purge()
{
if (!m_pBlocks)
return;
for (BlockHeader_t* pbh = m_pBlocks; pbh; )
{
BlockHeader_t* pFree = pbh;
pbh = pbh->m_pNext;
free(pFree);
}
m_pBlocks = NULL;
m_nAllocationCount = 0;
}
#pragma warning (pop)
File diff suppressed because it is too large Load Diff
+227
View File
@@ -0,0 +1,227 @@
#pragma once
#include "CUtlRBTree.h"
#define FOR_EACH_MAP( mapName, iteratorName ) \
for ( int iteratorName = (mapName).FirstInorder(); (mapName).IsUtlMap && iteratorName != (mapName).InvalidIndex(); iteratorName = (mapName).NextInorder( iteratorName ) )
#define FOR_EACH_MAP_FAST( mapName, iteratorName ) \
for ( int iteratorName = 0; (mapName).IsUtlMap && iteratorName < (mapName).MaxElement(); ++iteratorName ) if ( !(mapName).IsValidIndex( iteratorName ) ) continue; else
struct base_utlmap_t
{
public:
// This enum exists so that FOR_EACH_MAP and FOR_EACH_MAP_FAST cannot accidentally
// be used on a type that is not a CUtlMap. If the code compiles then all is well.
// The check for IsUtlMap being true should be free.
// Using an enum rather than a static const bool ensures that this trick works even
// with optimizations disabled on gcc.
enum CompileTimeCheck
{
IsUtlMap = 1
};
};
template <typename K, typename T, typename I = unsigned short>
class CUtlMap : public base_utlmap_t
{
public:
typedef K KeyType_t;
typedef T ElemType_t;
typedef I IndexType_t;
// Less func typedef
// Returns true if the first parameter is "less" than the second
typedef bool (*LessFunc_t)(const KeyType_t&, const KeyType_t&);
// constructor, destructor
// Left at growSize = 0, the memory will first allocate 1 element and double in size
// at each increment.
// LessFunc_t is required, but may be set after the constructor using SetLessFunc() below
CUtlMap(int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0)
: m_Tree(growSize, initSize, CKeyLess(lessfunc))
{
}
CUtlMap(LessFunc_t lessfunc)
: m_Tree(CKeyLess(lessfunc))
{
}
void EnsureCapacity(int num) { m_Tree.EnsureCapacity(num); }
// gets particular elements
ElemType_t& Element(IndexType_t i) { return m_Tree.Element(i).elem; }
const ElemType_t& Element(IndexType_t i) const { return m_Tree.Element(i).elem; }
ElemType_t& operator[](IndexType_t i) { return m_Tree.Element(i).elem; }
const ElemType_t& operator[](IndexType_t i) const { return m_Tree.Element(i).elem; }
KeyType_t& Key(IndexType_t i) { return m_Tree.Element(i).key; }
const KeyType_t& Key(IndexType_t i) const { return m_Tree.Element(i).key; }
// Num elements
unsigned int Count() const { return m_Tree.Count(); }
// Max "size" of the vector
IndexType_t MaxElement() const { return m_Tree.MaxElement(); }
// Checks if a node is valid and in the map
bool IsValidIndex(IndexType_t i) const { return m_Tree.IsValidIndex(i); }
// Checks if the map as a whole is valid
bool IsValid() const { return m_Tree.IsValid(); }
// Invalid index
static IndexType_t InvalidIndex() { return CTree::InvalidIndex(); }
// Sets the less func
void SetLessFunc(LessFunc_t func)
{
m_Tree.SetLessFunc(CKeyLess(func));
}
// Insert method (inserts in order)
IndexType_t Insert(const KeyType_t& key, const ElemType_t& insert)
{
Node_t node;
node.key = key;
node.elem = insert;
return m_Tree.Insert(node);
}
IndexType_t Insert(const KeyType_t& key)
{
Node_t node;
node.key = key;
return m_Tree.Insert(node);
}
// Find method
IndexType_t Find(const KeyType_t& key) const
{
Node_t dummyNode;
dummyNode.key = key;
return m_Tree.Find(dummyNode);
}
// Remove methods
void RemoveAt(IndexType_t i) { m_Tree.RemoveAt(i); }
bool Remove(const KeyType_t& key)
{
Node_t dummyNode;
dummyNode.key = key;
return m_Tree.Remove(dummyNode);
}
void RemoveAll() { m_Tree.RemoveAll(); }
void Purge() { m_Tree.Purge(); }
// Purges the list and calls delete on each element in it.
void PurgeAndDeleteElements();
// Iteration
IndexType_t FirstInorder() const { return m_Tree.FirstInorder(); }
IndexType_t NextInorder(IndexType_t i) const { return m_Tree.NextInorder(i); }
IndexType_t PrevInorder(IndexType_t i) const { return m_Tree.PrevInorder(i); }
IndexType_t LastInorder() const { return m_Tree.LastInorder(); }
// If you change the search key, this can be used to reinsert the
// element into the map.
void Reinsert(const KeyType_t& key, IndexType_t i)
{
m_Tree[i].key = key;
m_Tree.Reinsert(i);
}
IndexType_t InsertOrReplace(const KeyType_t& key, const ElemType_t& insert)
{
IndexType_t i = Find(key);
if (i != InvalidIndex())
{
Element(i) = insert;
return i;
}
return Insert(key, insert);
}
void Swap(CUtlMap< K, T, I >& that)
{
m_Tree.Swap(that.m_Tree);
}
struct Node_t
{
Node_t()
{
}
Node_t(const Node_t& from)
: key(from.key),
elem(from.elem)
{
}
KeyType_t key;
ElemType_t elem;
};
class CKeyLess
{
public:
CKeyLess(LessFunc_t lessFunc) : m_LessFunc(lessFunc) {}
bool operator!() const
{
return !m_LessFunc;
}
bool operator()(const Node_t& left, const Node_t& right) const
{
return m_LessFunc(left.key, right.key);
}
LessFunc_t m_LessFunc;
};
typedef CUtlRBTree<Node_t, I, CKeyLess> CTree;
CTree* AccessTree() { return &m_Tree; }
protected:
CTree m_Tree;
};
//-----------------------------------------------------------------------------
// Purges the list and calls delete on each element in it.
template< typename K, typename T, typename I >
inline void CUtlMap<K, T, I>::PurgeAndDeleteElements()
{
for (I i = 0; i < MaxElement(); ++i)
{
if (!IsValidIndex(i))
continue;
delete Element(i);
}
Purge();
}
//-----------------------------------------------------------------------------
// This is horrible and slow and meant to be used only when you're dealing with really
// non-time/memory-critical code and desperately want to copy a whole map element-by-element
// for whatever reason.
template < typename K, typename T, typename I >
void DeepCopyMap(const CUtlMap<K, T, I>& pmapIn, CUtlMap<K, T, I>* out_pmapOut)
{
Assert(out_pmapOut);
out_pmapOut->Purge();
FOR_EACH_MAP_FAST(pmapIn, i)
{
out_pmapOut->Insert(pmapIn.Key(i), pmapIn.Element(i));
}
}
@@ -1,4 +1,5 @@
#pragma once
#include "CUtlShared.h"
#include "../Interfaces/IMemAlloc.h"
#pragma warning (push)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,21 @@
#pragma once
#define COMPILE_TIME_ASSERT( pred ) static_assert( pred, "Compile time assert constraint is not true: " #pred )
template <class T>
inline void Construct(T* pMemory)
{
::new(pMemory) T;
}
template <class T>
inline void CopyConstruct(T* pMemory, T const& src)
{
::new(pMemory) T(src);
}
template <class T>
inline void Destruct(T* pMemory)
{
pMemory->~T();
}
+5 -16
View File
@@ -1,5 +1,6 @@
#pragma once
#include "CUtlMemory.h"
#include "CUtlShared.h"
#include <stdlib.h>
#include <cassert>
@@ -8,23 +9,11 @@
#pragma warning (disable : 4514)
#pragma warning (disable : 26495)
template <class T>
inline void Construct(T* pMemory)
{
::new(pMemory) T;
}
#define FOR_EACH_VEC( vecName, iteratorName ) \
for ( int iteratorName = 0; (vecName).IsUtlVector && iteratorName < (vecName).Count(); iteratorName++ )
template <class T>
inline void CopyConstruct(T* pMemory, T const& src)
{
::new(pMemory) T(src);
}
template <class T>
inline void Destruct(T* pMemory)
{
pMemory->~T();
}
#define FOR_EACH_VEC_BACK( vecName, iteratorName ) \
for ( int iteratorName = (vecName).Count()-1; (vecName).IsUtlVector && iteratorName >= 0; iteratorName-- )
template<class T, class A = CUtlMemory<T>>
class CUtlVector
@@ -16,4 +16,40 @@ public:
virtual void* QueryInterface(const char* pInterfaceName) = 0;
virtual InitReturnVal_t Init() = 0;
virtual void Shutdown() = 0;
};
template <class IInterface>
class CBaseAppSystem : public IInterface
{
public:
virtual bool Connect(CreateInterfaceFn factory) = 0;
virtual void Disconnect() = 0;
virtual void* QueryInterface(const char* pInterfaceName) = 0;
virtual InitReturnVal_t Init() = 0;
virtual void Shutdown() = 0;
};
template <class IInterface>
class CTier0AppSystem : public CBaseAppSystem<IInterface>
{
public:
bool m_bIsPrimaryAppSystem;
};
template <class IInterface, int ConVarFlag = 0>
class CTier1AppSystem : public CTier0AppSystem<IInterface>
{
typedef CTier0AppSystem<IInterface> BaseClass;
};
template <class IInterface, int ConVarFlag = 0>
class CTier2AppSystem : public CTier1AppSystem<IInterface, ConVarFlag>
{
typedef CTier1AppSystem<IInterface, ConVarFlag> BaseClass;
};
template<class IInterface, int ConVarFlag = 0>
class CTier3AppSystem : public CTier2AppSystem<IInterface, ConVarFlag>
{
typedef CTier2AppSystem<IInterface, ConVarFlag> BaseClass;
};
@@ -0,0 +1,12 @@
#pragma once
#include "IAppSystem.h"
struct studiohdr_t;
struct vertexFileHeader_t;
class IStudioDataCache : public IAppSystem
{
public:
virtual bool VerifyHeaders(studiohdr_t* pStudioHdr) = 0;
virtual vertexFileHeader_t* CacheVertexData(studiohdr_t* pStudioHdr) = 0;
};
+2 -10
View File
@@ -2,13 +2,10 @@
#include "BaseTypes.h"
#include <cstring>
#ifndef BITVEC_H
#define BITVEC_H
#define FORCEINLINE_TEMPLATE __forceinline
#define COMPILE_TIME_ASSERT( pred ) static_assert( pred, "Compile time assert constraint is not true: " #pred )
#define Plat_FastMemset memset
#define PAD_NUMBER(number, boundary) \
( ((number) + ((boundary)-1)) / (boundary) ) * (boundary)
#define PAD_NUMBER(number, boundary) ( ((number) + ((boundary)-1)) / (boundary) ) * (boundary)
class CBitVecAccessor
{
@@ -1422,9 +1419,4 @@ inline void CBitVecAccessor::operator=(int val)
inline CBitVecAccessor::operator uint32()
{
return m_pDWords[m_iBit >> 5] & (1 << (m_iBit & 31));
}
//=============================================================================
#endif // BITVEC_H
}
+6
View File
@@ -9,6 +9,7 @@
#include <unordered_map>
#include <map>
#include <ranges>
#include <optional>
class Vec2
{
@@ -1035,6 +1036,11 @@ struct Color_t
return { r, g, b, to };
}
inline Color_t Inverse() const
{
return Color_t(255 - r, 255 - g, 255 - b, a);
}
inline float Brightness(float flRed = 0.299f, float flGreen = 0.587f, float flBlue = 0.114f) const
{
return r * flRed + g * flGreen + b * flBlue;
@@ -25,18 +25,18 @@ bool CTraceFilterHitscan::ShouldHitEntity(IHandleEntity* pHandleEntity, int nCon
case ETFClassID::CFuncAreaPortalWindow:
case ETFClassID::CFuncRespawnRoomVisualizer:
case ETFClassID::CTFReviveMarker: return false;
case ETFClassID::CTFMedigunShield: return pEntity->m_iTeamNum() != iTeam;
case ETFClassID::CTFMedigunShield: return !(nContentsMask & CONTENTS_PLAYERCLIP) && pEntity->m_iTeamNum() != iTeam;
case ETFClassID::CTFPlayer:
case ETFClassID::CBaseObject:
case ETFClassID::CObjectSentrygun:
case ETFClassID::CObjectDispenser:
case ETFClassID::CObjectTeleporter:
if (iType != SKIP_CHECK && (iWeapon == WEAPON_INCLUDE ? bWeapon : !bWeapon))
return iType == FORCE_HIT ? true : false;
case ETFClassID::CObjectTeleporter:
if (!(nContentsMask & CONTENTS_MOVEABLE)) return false;
if (iType != SKIP_CHECK && (iWeapon == WEAPON_INCLUDE ? bWeapon : !bWeapon)) return iType == FORCE_HIT ? true : false;
return pEntity->m_iTeamNum() != iTeam;
}
return true;
return nContentsMask & CONTENTS_SOLID;
}
TraceType_t CTraceFilterHitscan::GetTraceType() const
{
@@ -62,44 +62,36 @@ bool CTraceFilterCollideable::ShouldHitEntity(IHandleEntity* pHandleEntity, int
switch (pEntity->GetClassID())
{
case ETFClassID::CBaseEntity:
case ETFClassID::CBaseEntity: return nContentsMask & CONTENTS_SOLID;
case ETFClassID::CFunc_LOD:
case ETFClassID::CBaseDoor:
case ETFClassID::CDynamicProp:
case ETFClassID::CPhysicsProp:
case ETFClassID::CPhysicsPropMultiplayer:
case ETFClassID::CFunc_LOD:
case ETFClassID::CObjectCartDispenser:
case ETFClassID::CFuncTrackTrain:
case ETFClassID::CFuncConveyor:
case ETFClassID::CTFGenericBomb:
case ETFClassID::CTFPumpkinBomb: return true;
case ETFClassID::CFuncRespawnRoomVisualizer:
if (nContentsMask & CONTENTS_PLAYERCLIP)
return pEntity->m_iTeamNum() != iTeam;
break;
case ETFClassID::CTFMedigunShield:
if (!(nContentsMask & CONTENTS_PLAYERCLIP))
return pEntity->m_iTeamNum() != iTeam;
break;
case ETFClassID::CTFPumpkinBomb: return nContentsMask & CONTENTS_MOVEABLE;
case ETFClassID::CFuncRespawnRoomVisualizer: return nContentsMask & CONTENTS_PLAYERCLIP && pEntity->m_iTeamNum() != iTeam;
case ETFClassID::CTFMedigunShield: return !(nContentsMask & CONTENTS_PLAYERCLIP) && pEntity->m_iTeamNum() != iTeam;
case ETFClassID::CTFPlayer:
if (iPlayer == PLAYER_ALL)
return true;
if (iPlayer == PLAYER_NONE)
return false;
if (iType != SKIP_CHECK && (iWeapon == WEAPON_INCLUDE ? bWeapon : !bWeapon))
return iType == FORCE_HIT ? true : false;
if (!(nContentsMask & CONTENTS_MONSTER)) return false;
if (iPlayer == PLAYER_ALL) return true;
if (iPlayer == PLAYER_NONE) return false;
if (iType != SKIP_CHECK && (iWeapon == WEAPON_INCLUDE ? bWeapon : !bWeapon)) return iType == FORCE_HIT ? true : false;
return pEntity->m_iTeamNum() != iTeam;
case ETFClassID::CBaseObject:
case ETFClassID::CObjectSentrygun:
case ETFClassID::CObjectDispenser: return iObject == OBJECT_ALL ? true : iObject == OBJECT_NONE ? false : pEntity->m_iTeamNum() != iTeam;
case ETFClassID::CObjectTeleporter: return true;
case ETFClassID::CObjectDispenser: return nContentsMask & CONTENTS_MOVEABLE && (iObject == OBJECT_ALL ? true : iObject == OBJECT_NONE ? false : pEntity->m_iTeamNum() != iTeam);
case ETFClassID::CObjectTeleporter: return nContentsMask & CONTENTS_MOVEABLE;
//case ETFClassID::CTFBaseBoss:
//case ETFClassID::CTFTankBoss:
//case ETFClassID::CMerasmus:
//case ETFClassID::CEyeballBoss:
//case ETFClassID::CHeadlessHatman:
//case ETFClassID::CZombie: return bMisc;
case ETFClassID::CTFGrenadePipebombProjectile: return bMisc && pEntity->As<CTFGrenadePipebombProjectile>()->m_iType() == TF_GL_MODE_REMOTE_DETONATE;
//case ETFClassID::CZombie: return nContentsMask & CONTENTS_MONSTER && bMisc;
case ETFClassID::CTFGrenadePipebombProjectile: return nContentsMask & CONTENTS_MOVEABLE && bMisc && pEntity->As<CTFGrenadePipebombProjectile>()->m_iType() == TF_GL_MODE_REMOTE_DETONATE;
}
return false;
@@ -114,22 +106,22 @@ bool CTraceFilterWorldAndPropsOnly::ShouldHitEntity(IHandleEntity* pHandleEntity
if (!pHandleEntity || pHandleEntity == pSkip)
return false;
if (pHandleEntity->GetRefEHandle().GetSerialNumber() == (1 << 15))
return pHandleEntity->GetRefEHandle().GetEntryIndex() != iTeam; // just use team variable since cliententitylist can give us nullptrs for some props for whatever reason
return nContentsMask & CONTENTS_SOLID && pHandleEntity->GetRefEHandle().GetEntryIndex() != iTeam; // team variable since cliententitylist can give nullptrs
auto pEntity = reinterpret_cast<CBaseEntity*>(pHandleEntity);
if (iTeam == -1) iTeam = pSkip ? pSkip->m_iTeamNum() : 0;
switch (pEntity->GetClassID())
{
case ETFClassID::CBaseEntity:
case ETFClassID::CBaseEntity: return nContentsMask & CONTENTS_SOLID;
case ETFClassID::CFunc_LOD:
case ETFClassID::CBaseDoor:
case ETFClassID::CDynamicProp:
case ETFClassID::CPhysicsProp:
case ETFClassID::CPhysicsPropMultiplayer:
case ETFClassID::CFunc_LOD:
case ETFClassID::CObjectCartDispenser:
case ETFClassID::CFuncTrackTrain:
case ETFClassID::CFuncConveyor: return true;
case ETFClassID::CFuncConveyor: return nContentsMask & CONTENTS_MOVEABLE;
case ETFClassID::CFuncRespawnRoomVisualizer: return nContentsMask & CONTENTS_PLAYERCLIP && pEntity->m_iTeamNum() != iTeam;
}
+4
View File
@@ -155,6 +155,10 @@ bool SDK::IsGameWindowInFocus()
return hWindow == GetForegroundWindow() || !hWindow;
}
bool SDK::StdRandomBool()
{
return StdRandomInt(0, 1);
}
int SDK::StdRandomInt(int iMin, int iMax)
{
std::uniform_int_distribution<int> iDistribution(iMin, iMax);
+1
View File
@@ -88,6 +88,7 @@ namespace SDK
bool IsGameWindowInFocus();
inline std::default_random_engine Random = {};
bool StdRandomBool();
int StdRandomInt(int iMin = 0, int iMax = VALVE_RAND_MAX);
float StdRandomFloat(float flMin = 0.f, float flMax = 1.f);
+160
View File
@@ -1,12 +1,16 @@
#pragma once
#include "BaseMath.h"
#include "../../SDK/Definitions/Types.h"
#include "../Hash/FNV1A.h"
#undef min
#undef max
#define FLT_COMPARE(x, y) (fabsf(x - y) <= FLT_EPSILON * fmaxf(1.f, fmaxf(fabsf(x), fabsf(y))))
#define DIST_EPSILON 0.03125f
#define CALC_EPSILON 0.001f
namespace Math
{
inline void ClampAngles(Vec3& v)
@@ -387,4 +391,160 @@ namespace Math
mOut[2][2] = mIn1[2][0] * mIn2[0][2] + mIn1[2][1] * mIn2[1][2] + mIn1[2][2] * mIn2[2][2];
mOut[2][3] = mIn1[2][0] * mIn2[0][3] + mIn1[2][1] * mIn2[1][3] + mIn1[2][2] * mIn2[2][3] + mIn1[2][3];
}
inline void OffsetPolygon(std::vector<Vec3>& vVertices, const Vec3& vNormal, float flOffset)
{
for (auto& vVertex : vVertices)
vVertex += vNormal * flOffset;
}
inline void ExpandPolygon(std::vector<Vec3>& vOldVertices, std::vector<Vec3>& vNewVertices, const Vec3& vNormal, float flOffset, const Vec3* pTarget = nullptr)
{
Vec3 vForward = (vNewVertices.front() - vNewVertices.back()).Normalized();
Vec3 vRight = vForward.Cross(vNormal).Normalized();
vOldVertices = vNewVertices;
for (int i = 0, n = int(vNewVertices.size()); i < n; i++)
{
Vec3& vVertex1 = vOldVertices[i], &vVertex2 = vOldVertices[(i + 1) % n], &vVertex3 = vOldVertices[(i + 2) % n];
Vec2 vPoint1 = { vVertex1.Dot(vForward), vVertex1.Dot(vRight) };
Vec2 vPoint2 = { vVertex2.Dot(vForward), vVertex2.Dot(vRight) };
Vec2 vPoint3 = { vVertex3.Dot(vForward), vVertex3.Dot(vRight) };
Vec2 vDelta21 = vPoint2 - vPoint1;
Vec2 vDelta32 = vPoint3 - vPoint2;
Vec2 vNormal1 = Vec2(vDelta21.y, -vDelta21.x).Normalized();
Vec2 vNormal2 = Vec2(vDelta32.y, -vDelta32.x).Normalized();
Vec2 vBisect = Vec2(vNormal1.x + vNormal2.x, vNormal1.y + vNormal2.y).Normalized();
float flDistance = flOffset / vNormal1.Dot(vBisect);
vBisect *= flDistance;
if (!pTarget)
vNewVertices[(i + 1) % n] += vForward * vBisect.x + vRight * vBisect.y;
else
{
Vec3 vToTarget = *pTarget - vVertex2;
if (Vec3 vDisplacementX = vForward * vBisect.x; vDisplacementX.Dot(vToTarget) > 0.f)
vNewVertices[(i + 1) % n] += vDisplacementX;
if (Vec3 vDisplacementY = vRight * vBisect.y; vDisplacementY.Dot(vToTarget) > 0.f)
vNewVertices[(i + 1) % n] += vDisplacementY;
}
}
}
inline void ExpandPolygon(std::vector<Vec3>& vVertices, const Vec3& vNormal, float flOffset, const Vec3* pTarget = nullptr)
{
std::vector<Vec3> vTemporary;
ExpandPolygon(vTemporary, vVertices, vNormal, flOffset, pTarget);
}
inline Vec3 ClosestPointOnLine(const Vec3& vPoint, const Vec3& vPoint1, const Vec3& vPoint2)
{
Vec3 vDelta = vPoint2 - vPoint1;
float flRatio = std::clamp((vPoint - vPoint1).Dot(vDelta) / vDelta.Dot(vDelta), 0.f, 1.f);
return vPoint1 + vDelta * flRatio;
}
inline Vec3 ClosestPointOnTriangle(const Vec3& vPoint, const Vec3& vPoint1, const Vec3& vPoint2, const Vec3& vPoint3, bool* pInside = nullptr)
{
Vec3 vDelta21 = vPoint2 - vPoint1;
Vec3 vDelta31 = vPoint3 - vPoint1;
if (pInside) *pInside = false;
Vec3 vDeltaPT = vPoint - vPoint1;
float flDot1 = vDelta21.Dot(vDeltaPT);
float flDot2 = vDelta31.Dot(vDeltaPT);
if (flDot1 <= 0 && flDot2 <= 0)
return vPoint1;
vDeltaPT = vPoint - vPoint2;
float flDot3 = vDelta21.Dot(vDeltaPT);
float flDot4 = vDelta31.Dot(vDeltaPT);
if (flDot3 >= 0 && flDot4 <= flDot3)
return vPoint2;
vDeltaPT = vPoint - vPoint3;
float flDot5 = vDelta21.Dot(vDeltaPT);
float flDot6 = vDelta31.Dot(vDeltaPT);
if (flDot6 >= 0 && flDot5 <= flDot6)
return vPoint3;
float flSideC = flDot1 * flDot4 - flDot3 * flDot2;
if (flSideC <= 0 && flDot1 >= 0 && flDot3 <= 0)
{
float flRatio = flDot1 / (flDot1 - flDot3);
return vPoint1 + vDelta21 * flRatio;
}
float flSideB = flDot5 * flDot2 - flDot1 * flDot6;
if (flSideB <= 0 && flDot2 >= 0 && flDot6 <= 0)
{
float flRatio = flDot2 / (flDot2 - flDot6);
return vPoint1 + vDelta31 * flRatio;
}
float flSideA = flDot3 * flDot6 - flDot5 * flDot4;
if (flSideA <= 0 && (flDot4 - flDot3) >= 0 && (flDot5 - flDot6) >= 0)
{
float flRatio = (flDot4 - flDot3) / (flDot4 - flDot3 + flDot5 - flDot6);
return vPoint2 + (vPoint3 - vPoint2) * flRatio;
}
float flDenominator = 1 / (flSideA + flSideB + flSideC);
float flV = flSideB * flDenominator;
float flW = flSideC * flDenominator;
if (pInside) *pInside = true;
return vPoint1 + vDelta21 * flV + vDelta31 * flW;
}
inline Vec3 ClosestPointOnPolygon(const Vec3& vPoint, const std::vector<Vec3>& vVertices, const Vec3& vNormal, bool* pInside = nullptr)
{
float flDot = vNormal.Dot(vPoint - vVertices.front());
Vec3 vProjection = vPoint - flDot * vNormal;
for (int i = 0, n = int(vVertices.size()); i < n; i++)
{
const Vec3& vVertex1 = vVertices[i], &vVertex2 = vVertices[(i + 1) % n];
Vec3 vEdge = vVertex2 - vVertex1;
Vec3 vToProjection = vProjection - vVertex1;
if (vToProjection.Cross(vEdge).Dot(vNormal) < 0)
goto outside;
}
if (pInside) *pInside = true;
return vProjection;
outside:
float flLowestDistance = std::numeric_limits<float>::max();
for (int i = 0, n = int(vVertices.size()); i < n; i++)
{
const Vec3& vVertex1 = vVertices[i], &vVertex2 = vVertices[(i + 1) % n];
Vec3 vLine = ClosestPointOnLine(vPoint, vVertex1, vVertex2);
float flDistance = vLine.DistToSqr(vPoint);
if (flDistance < flLowestDistance)
vProjection = vLine, flLowestDistance = flDistance;
}
if (pInside) *pInside = false;
return vProjection;
}
// note: not clamped
inline float FullFraction(const Vec3& vDir, const CGameTrace& trace)
{
if (!trace.DidHit() || FNV1A::Hash32(trace.surface.name) == FNV1A::Hash32Const("**displacement**"))
return trace.fraction;
float flFractionEpsilon = DIST_EPSILON / vDir.Dot(trace.plane.normal);
return trace.fraction - flFractionEpsilon;
}
inline float FullFraction(const Vec3& vStart, const Vec3& vEnd, const CGameTrace& trace)
{
return FullFraction(vEnd - vStart, trace);
}
}