grappling hook projectile aim support

some reorganization
This commit is contained in:
rei-2
2026-06-23 14:55:43 -04:00
parent 71173d4b7d
commit 19edc51369
12 changed files with 213 additions and 153 deletions
+1
View File
@@ -962,6 +962,7 @@
<ClCompile Include="src\Hooks\CBaseAnimating_MaintainSequenceTransitions.cpp" />
<ClCompile Include="src\Hooks\CBaseAnimating_SetSequence.cpp" />
<ClCompile Include="src\Hooks\CBaseAnimating_SetupBones.cpp" />
<ClCompile Include="src\Hooks\CTFGrapplingHook_ItemPostFrame.cpp" />
<ClCompile Include="src\Hooks\CTFPlayer_UpdateClientSideAnimation.cpp" />
<ClCompile Include="src\Hooks\CBaseViewModel_Interpolate.cpp" />
<ClCompile Include="src\Hooks\CBaseEntity_EstimateAbsVelocity.cpp" />
+1
View File
@@ -208,6 +208,7 @@
<ClCompile Include="src\Hooks\CEngineClient_GetScreenAspectRatio.cpp" />
<ClCompile Include="src\Features\AntiCheatCompatibility\AntiCheatCompatibility.cpp" />
<ClCompile Include="src\Features\Debug\Debug.cpp" />
<ClCompile Include="src\Hooks\CTFGrapplingHook_ItemPostFrame.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Utils\UtlVector\UtlVector.h" />
+2
View File
@@ -1,3 +1,5 @@
#define no_inline __declspec(noinline)
#define VA_LIST(...) __VA_ARGS__
#define STRINGIFY(x) STRINGIFY2(x)
@@ -367,7 +367,9 @@ bool CAimbotGlobal::ShouldHoldAttack(CTFWeaponBase* pWeapon)
break;
[[fallthrough]];
case Vars::Aimbot::General::AimHoldsFireEnum::Always:
if (!F::Aimbot.m_bRunningSecondary && !G::CanPrimaryAttack && G::LastUserCmd->buttons & IN_ATTACK && Vars::Aimbot::General::AimType.Value && !pWeapon->IsInReload())
if (!(G::LastUserCmd->buttons & IN_ATTACK) || !Vars::Aimbot::General::AimType.Value || F::Aimbot.m_bRunningSecondary)
break;
if (!G::CanPrimaryAttack && !pWeapon->IsInReload() || pWeapon->GetWeaponID() == TF_WEAPON_GRAPPLINGHOOK && pWeapon->As<CTFGrapplingHook>()->m_hProjectile())
return true;
}
return false;
@@ -2035,12 +2035,27 @@ bool CAimbotProjectile::RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser
pCmd->buttons &= ~IN_ATTACK;
}
break;
case TF_WEAPON_GRAPPLINGHOOK:
break;
default:
pCmd->buttons |= IN_ATTACK;
}
}
F::Aimbot.m_bRan = G::Attacking = SDK::IsAttacking(pLocal, pWeapon, pCmd, true);
if (nWeaponID != TF_WEAPON_GRAPPLINGHOOK)
F::Aimbot.m_bRan = G::Attacking = SDK::IsAttacking(pLocal, pWeapon, pCmd, true);
else
{
Vec3 vOriginalAngles = pCmd->viewangles; int iOriginalButtons = pCmd->buttons;
pCmd->viewangles = tTarget.m_vAngleTo, pCmd->buttons |= IN_ATTACK;
F::Aimbot.m_bRan = G::Attacking = SDK::IsAttacking(pLocal, pWeapon, pCmd, true);
pCmd->viewangles = vOriginalAngles, pCmd->buttons = iOriginalButtons;
if (!G::Attacking)
continue;
if (Vars::Aimbot::General::AutoShoot.Value)
pCmd->buttons |= IN_ATTACK;
}
DrawVisuals(iResult, tTarget, m_vPlayerPath, m_vProjectilePath, m_vBoxes);
Aim(pCmd, tTarget.m_vAngleTo);
@@ -236,7 +236,7 @@ bool CMovementSimulation::Initialize(CBaseEntity* pEntity, MoveStorage& tMoveSto
// setup move data
SetupMoveData(tMoveStorage);
if (I::GameMovement->player = pPlayer, I::GameMovement->mv = &tMoveStorage.m_MoveData; I::GameMovement->CheckStuck())
if (CheckStuck(tMoveStorage))
{
tMoveStorage.m_bFailed = true;
return true;
@@ -319,6 +319,15 @@ void CMovementSimulation::SetupMoveData(MoveStorage& tMoveStorage)
tMoveStorage.m_bDirectMove = tMoveStorage.m_pPlayer->IsOnGround() || tMoveStorage.m_pPlayer->IsSwimming();
}
bool CMovementSimulation::CheckStuck(MoveStorage& tMoveStorage)
{
I::GameMovement->player = I::GameMovement->m_pTFPlayer = tMoveStorage.m_pPlayer, I::GameMovement->mv = &tMoveStorage.m_MoveData;
SetBounds(tMoveStorage.m_pPlayer);
bool bReturn = I::GameMovement->CheckStuck();
RestoreBounds(tMoveStorage.m_pPlayer);
return bReturn;
}
static inline float GetFrictionScale(float flVelocityXY, float flTurn, float flVelocityZ, float flMin = 50.f, float flMax = 150.f)
{
if (0.f >= flVelocityZ || flVelocityZ > 250.f)
@@ -46,6 +46,7 @@ private:
void Reset(MoveStorage& tMoveStorage);
void SetupMoveData(MoveStorage& tMoveStorage);
bool CheckStuck(MoveStorage& tMoveStorage);
void GetAverageYaw(MoveStorage& tMoveStorage, int iSamples);
bool StrafePrediction(MoveStorage& tMoveStorage, bool bHitchance = false);
+2 -102
View File
@@ -15,9 +15,7 @@
#include "../Features/Spectate/Spectate.h"
#include "../Features/AntiCheatCompatibility/AntiCheatCompatibility.h"
MAKE_SIGNATURE(IHasGenericMeter_GetMeterMultiplier, "client.dll", "F3 0F 10 81 ? ? ? ? C3 CC CC CC CC CC CC CC 48 85 D2", 0x0);
static inline void UpdateInfo(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
static no_inline void UpdateInfo(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
{
G::PSilentAngles = G::SilentAngles = G::Attacking = G::Throwing = false;
G::LastUserCmd = G::CurrentUserCmd ? G::CurrentUserCmd : pCmd;
@@ -27,105 +25,7 @@ static inline void UpdateInfo(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCm
if (!pWeapon)
return;
G::CanPrimaryAttack = G::CanSecondaryAttack = G::Reloading = false;
if (pWeapon->GetMaxClip1() != WEAPON_NOCLIP && !pWeapon->m_bReloadsSingly())
{ // dumb fix
float flOldCurtime = I::GlobalVars->curtime;
I::GlobalVars->curtime = TICKS_TO_TIME(pLocal->m_nTickBase());
pWeapon->CheckReload();
I::GlobalVars->curtime = flOldCurtime;
}
bool bCanAttack = pLocal->CanAttack();
{
static int iStaticItemDefinitionIndex = 0;
int iOldItemDefinitionIndex = iStaticItemDefinitionIndex;
int iNewItemDefinitionIndex = iStaticItemDefinitionIndex = pWeapon->m_iItemDefinitionIndex();
if (iNewItemDefinitionIndex != iOldItemDefinitionIndex || !bCanAttack || !pWeapon->m_iClip1())
F::Ticks.m_iWait = -1;
}
if (bCanAttack)
{
G::CanPrimaryAttack = pWeapon->CanPrimaryAttack();
G::CanSecondaryAttack = pWeapon->CanSecondaryAttack();
switch (pWeapon->GetWeaponID())
{
case TF_WEAPON_FLAME_BALL:
if (G::CanPrimaryAttack)
{
// do this, otherwise it will be a tick behind
float flFrametime = TICK_INTERVAL * 100;
float flMeterMult = S::IHasGenericMeter_GetMeterMultiplier.Call<float>(pWeapon->m_pMeter());
float flRate = SDK::AttribHookValue(1.f, "item_meter_charge_rate", pWeapon) - 1;
float flMult = SDK::AttribHookValue(1.f, "mult_item_meter_charge_rate", pWeapon);
float flTankPressure = pLocal->m_flTankPressure() + flFrametime * flMeterMult / (flRate * flMult);
if (G::CanPrimaryAttack && flTankPressure < 100.f)
G::CanPrimaryAttack = G::CanSecondaryAttack = false;
}
break;
case TF_WEAPON_MINIGUN:
{
int iState = pWeapon->As<CTFMinigun>()->m_iWeaponState();
if (iState != AC_STATE_FIRING && iState != AC_STATE_SPINNING || !pWeapon->HasPrimaryAmmoForShot())
G::CanPrimaryAttack = false;
break;
}
case TF_WEAPON_FLAREGUN_REVENGE:
if (pCmd->buttons & IN_ATTACK2)
G::CanPrimaryAttack = false;
break;
case TF_WEAPON_BAT_WOOD:
case TF_WEAPON_BAT_GIFTWRAP:
if (!pWeapon->HasPrimaryAmmoForShot())
G::CanSecondaryAttack = false;
break;
case TF_WEAPON_MEDIGUN:
case TF_WEAPON_BUILDER:
case TF_WEAPON_LASER_POINTER:
break;
case TF_WEAPON_PARTICLE_CANNON:
{
float flChargeBeginTime = pWeapon->As<CTFParticleCannon>()->m_flChargeBeginTime();
if (flChargeBeginTime > 0)
{
float flTotalChargeTime = TICKS_TO_TIME(pLocal->m_nTickBase()) - flChargeBeginTime;
if (flTotalChargeTime < TF_PARTICLE_MAX_CHARGE_TIME)
{
G::CanPrimaryAttack = G::CanSecondaryAttack = false;
break;
}
}
[[fallthrough]];
}
default:
if (pWeapon->GetSlot() != SLOT_MELEE)
{
bool bAmmo = pWeapon->HasPrimaryAmmoForShot();
bool bReload = pWeapon->IsInReload();
if (!bAmmo && pWeapon->m_iItemDefinitionIndex() != Soldier_m_TheBeggarsBazooka)
G::CanPrimaryAttack = G::CanSecondaryAttack = false;
if (bReload && bAmmo && !G::CanPrimaryAttack)
G::Reloading = true;
}
}
if (G::CanPrimaryAttack)
{
switch (pWeapon->GetWeaponID())
{
case TF_WEAPON_FLAMETHROWER:
case TF_WEAPON_FLAME_BALL:
case TF_WEAPON_FLAREGUN:
case TF_WEAPON_FLAREGUN_REVENGE:
if (pLocal->IsUnderwater())
G::CanPrimaryAttack = G::CanSecondaryAttack = false;
}
}
}
SDK::CanAttack(pLocal, pWeapon, pCmd, G::CanPrimaryAttack, G::CanSecondaryAttack, G::Reloading);
G::Attacking = SDK::IsAttacking(pLocal, pWeapon, pCmd);
G::PrimaryWeaponType = SDK::GetWeaponType(pWeapon, &G::SecondaryWeaponType);
G::CanHeadshot = pWeapon->CanHeadshot() || pWeapon->AmbassadorCanHeadshot(TICKS_TO_TIME(pLocal->m_nTickBase()));
@@ -0,0 +1,25 @@
#include "../SDK/SDK.h"
MAKE_SIGNATURE(CTFGrapplingHook_ItemPostFrame, "client.dll", "40 53 57 48 83 EC ? 48 8B D9 E8 ? ? ? ? 48 8B F8 48 85 C0 0F 84 ? ? ? ? 8B 88", 0x0);
MAKE_SIGNATURE(CTFGrapplingHook_PrimaryAttack, "client.dll", "48 89 5C 24 ? 48 89 7C 24 ? 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B D9 E8 ? ? ? ? 8B 93", 0x0);
MAKE_SIGNATURE(CTFGrapplingHook_ItemPostFrame_Fired, "client.dll", "40 38 35 ? ? ? ? 75 ? 48 8B 03", 0x0);
static bool s_bOriginalFired = false;
MAKE_HOOK(CTFGrapplingHook_ItemPostFrame, S::CTFGrapplingHook_ItemPostFrame(), void,
void* rcx)
{
static bool& bFired = *reinterpret_cast<bool*>(U::Memory.RelToAbs(S::CTFGrapplingHook_ItemPostFrame_Fired()));
s_bOriginalFired = bFired;
bFired = false; // this var breaks prediction for this weapon pretty hard otherwise
CALL_ORIGINAL(rcx);
}
MAKE_HOOK(CTFGrapplingHook_PrimaryAttack, S::CTFGrapplingHook_PrimaryAttack(), void,
void* rcx)
{
bool bOriginalFirstTimePredicted = I::Prediction->m_bFirstTimePredicted;
I::Prediction->m_bFirstTimePredicted = !s_bOriginalFired; // don't spam deny sound
CALL_ORIGINAL(rcx);
I::Prediction->m_bFirstTimePredicted = bOriginalFirstTimePredicted;
}
+4 -2
View File
@@ -2,6 +2,8 @@
#include "../Types.h"
#include <stdint.h>
class CKeyValuesGrowableStringTable;
enum types_t
{
TYPE_NONE = 0,
@@ -33,12 +35,12 @@ private:
char m_iDataType;
char m_bHasEscapeSequences;
char m_bEvaluateConditionals;
char unused[1];
char m_bUnknown;
KeyValues* m_pPeer;
KeyValues* m_pSub;
KeyValues* m_pChain;
void* m_pUnknown;
CKeyValuesGrowableStringTable* m_pGrowableStringTable;
public:
class AutoDelete
+139 -41
View File
@@ -3,10 +3,12 @@
#include "../Features/ImGui/Notifications/Notifications.h"
#include "../Features/ImGui/Menu/Menu.h"
#include "../Features/EnginePrediction/EnginePrediction.h"
#include "../Features/Ticks/Ticks.h"
#pragma warning (disable : 6385)
MAKE_SIGNATURE(CAttributeManager_AttribHookValue_Float, "client.dll", "4C 8B DC 49 89 5B ? 49 89 6B ? 56 57 41 54 41 56 41 57 48 83 EC ? 48 8B 3D ? ? ? ? 4C 8D 35", 0x0);
MAKE_SIGNATURE(IHasGenericMeter_GetMeterMultiplier, "client.dll", "F3 0F 10 81 ? ? ? ? C3 CC CC CC CC CC CC CC 48 85 D2", 0x0);
static BOOL CALLBACK TeamFortressWindow(HWND hWindow, LPARAM lParam)
{
@@ -418,6 +420,13 @@ bool SDK::PredictOrigin(Vec3& vOut, const Vec3& vOrigin, const Vec3& vVelocity,
return !trace.DidHit();
}
float SDK::GetGravity()
{
static auto sv_gravity = H::ConVars.FindVar("sv_gravity");
return sv_gravity->GetFloat();
}
bool SDK::IsLoopback()
{
auto pNetChan = I::EngineClient->GetNetChannelInfo();
@@ -437,6 +446,38 @@ int SDK::GetWinningTeam()
return 0;
}
const char* SDK::GetClassByIndex(const int nClass, bool bLower)
{
static const char* szClassesUpper[] = {
"Unknown", "Scout", "Sniper", "Soldier", "Demoman", "Medic", "Heavy", "Pyro", "Spy", "Engineer"
};
static const char* szClassesLower[] = {
"unknown", "scout", "sniper", "soldier", "demoman", "medic", "heavy", "pyro", "spy", "engineer"
};
if (!bLower)
return nClass < 10 && nClass > 0 ? szClassesUpper[nClass] : szClassesUpper[0];
else
return nClass < 10 && nClass > 0 ? szClassesLower[nClass] : szClassesLower[0];
}
float SDK::AttribHookValue(float value, const char* name, void* econent, void* buffer, bool isGlobalConstString)
{
return S::CAttributeManager_AttribHookValue_Float.Call<float>(value, name, econent, buffer, isGlobalConstString);
}
float SDK::MaxSpeed(CTFPlayer* pPlayer, bool bIncludeCrouch, bool bIgnoreSpecialAbility)
{
float flSpeed = pPlayer->CalculateMaxSpeed(bIgnoreSpecialAbility);
if (pPlayer->InCond(TF_COND_SPEED_BOOST) || pPlayer->InCond(TF_COND_HALLOWEEN_SPEED_BOOST))
flSpeed *= 1.35f;
if (bIncludeCrouch && pPlayer->IsDucking() && pPlayer->IsOnGround())
flSpeed /= 3;
return flSpeed;
}
EWeaponType SDK::GetWeaponType(CTFWeaponBase* pWeapon, EWeaponType* pSecondaryType)
{
if (pSecondaryType)
@@ -478,7 +519,6 @@ EWeaponType SDK::GetWeaponType(CTFWeaponBase* pWeapon, EWeaponType* pSecondaryTy
case TF_WEAPON_PDA_SPY_BUILD:
case TF_WEAPON_INVIS:
case TF_WEAPON_BUFF_ITEM:
case TF_WEAPON_GRAPPLINGHOOK:
case TF_WEAPON_ROCKETPACK:
return EWeaponType::UNKNOWN;
case TF_WEAPON_CLEAVER:
@@ -502,25 +542,107 @@ EWeaponType SDK::GetWeaponType(CTFWeaponBase* pWeapon, EWeaponType* pSecondaryTy
case TF_WEAPON_JAR_MILK:
case TF_WEAPON_JAR_GAS:
case TF_WEAPON_LUNCHBOX:
case TF_WEAPON_GRAPPLINGHOOK:
return EWeaponType::PROJECTILE;
}
return EWeaponType::HITSCAN;
}
const char* SDK::GetClassByIndex(const int nClass, bool bLower)
void SDK::CanAttack(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, const CUserCmd* pCmd, bool& bPrimary, bool& bSecondary, bool& bReloading)
{
static const char* szClassesUpper[] = {
"Unknown", "Scout", "Sniper", "Soldier", "Demoman", "Medic", "Heavy", "Pyro", "Spy", "Engineer"
};
static const char* szClassesLower[] = {
"unknown", "scout", "sniper", "soldier", "demoman", "medic", "heavy", "pyro", "spy", "engineer"
};
bPrimary = bSecondary = bReloading = false;
if (!bLower)
return nClass < 10 && nClass > 0 ? szClassesUpper[nClass] : szClassesUpper[0];
else
return nClass < 10 && nClass > 0 ? szClassesLower[nClass] : szClassesLower[0];
if (pWeapon->GetMaxClip1() != WEAPON_NOCLIP && !pWeapon->m_bReloadsSingly())
{ // dumb fix
float flOldCurtime = I::GlobalVars->curtime;
I::GlobalVars->curtime = TICKS_TO_TIME(pLocal->m_nTickBase());
pWeapon->CheckReload();
I::GlobalVars->curtime = flOldCurtime;
}
bool bCanAttack = pLocal->CanAttack();
{
static int iStaticItemDefinitionIndex = 0;
int iOldItemDefinitionIndex = iStaticItemDefinitionIndex;
int iNewItemDefinitionIndex = iStaticItemDefinitionIndex = pWeapon->m_iItemDefinitionIndex();
if (iNewItemDefinitionIndex != iOldItemDefinitionIndex || !bCanAttack || !pWeapon->m_iClip1())
F::Ticks.m_iWait = -1;
}
if (bCanAttack)
{
bPrimary = pWeapon->CanPrimaryAttack();
bSecondary = pWeapon->CanSecondaryAttack();
switch (pWeapon->GetWeaponID())
{
case TF_WEAPON_FLAME_BALL:
if (bPrimary)
{
// do this, otherwise it will be a tick behind
float flFrametime = TICK_INTERVAL * 100;
float flMeterMult = S::IHasGenericMeter_GetMeterMultiplier.Call<float>(pWeapon->m_pMeter());
float flRate = SDK::AttribHookValue(1.f, "item_meter_charge_rate", pWeapon) - 1;
float flMult = SDK::AttribHookValue(1.f, "mult_item_meter_charge_rate", pWeapon);
float flTankPressure = pLocal->m_flTankPressure() + flFrametime * flMeterMult / (flRate * flMult);
if (bPrimary && flTankPressure < 100.f)
bPrimary = bSecondary = false;
}
break;
case TF_WEAPON_MINIGUN:
if (int iState = pWeapon->As<CTFMinigun>()->m_iWeaponState(); iState != AC_STATE_FIRING && iState != AC_STATE_SPINNING || !pWeapon->HasPrimaryAmmoForShot())
bPrimary = false;
break;
case TF_WEAPON_FLAREGUN_REVENGE:
if (pCmd->buttons & IN_ATTACK2)
bPrimary = false;
break;
case TF_WEAPON_BAT_WOOD:
case TF_WEAPON_BAT_GIFTWRAP:
if (!pWeapon->HasPrimaryAmmoForShot())
bSecondary = false;
break;
case TF_WEAPON_MEDIGUN:
case TF_WEAPON_BUILDER:
case TF_WEAPON_LASER_POINTER:
break;
case TF_WEAPON_PARTICLE_CANNON:
if (float flChargeBeginTime = pWeapon->As<CTFParticleCannon>()->m_flChargeBeginTime(); flChargeBeginTime > 0)
{
float flTotalChargeTime = TICKS_TO_TIME(pLocal->m_nTickBase()) - flChargeBeginTime;
if (flTotalChargeTime < TF_PARTICLE_MAX_CHARGE_TIME)
{
bPrimary = bSecondary = false;
break;
}
}
[[fallthrough]];
default:
if (pWeapon->GetSlot() != SLOT_MELEE)
{
bool bAmmo = pWeapon->HasPrimaryAmmoForShot();
bool bReload = pWeapon->IsInReload();
if (!bAmmo && pWeapon->m_iItemDefinitionIndex() != Soldier_m_TheBeggarsBazooka)
bPrimary = bSecondary = false;
if (bReload && bAmmo && !bPrimary)
bReloading = true;
}
}
if (bPrimary)
{
switch (pWeapon->GetWeaponID())
{
case TF_WEAPON_FLAMETHROWER:
case TF_WEAPON_FLAME_BALL:
case TF_WEAPON_FLAREGUN:
case TF_WEAPON_FLAREGUN_REVENGE:
if (pLocal->IsUnderwater())
bPrimary = bSecondary = false;
}
}
}
}
int SDK::IsAttacking(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, const CUserCmd* pCmd, bool bTickBase)
@@ -621,14 +743,14 @@ int SDK::IsAttacking(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, const CUserCmd*
if (!G::CanPrimaryAttack || !(pCmd->buttons & IN_ATTACK) || pWeapon->As<CTFGrapplingHook>()->m_hProjectile())
return false;
Vec3 vPos, vAngle; GetProjectileFireSetup(pLocal, pCmd->viewangles, { 23.5f, -8.f, -3.f }, vPos, vAngle, false);
static auto tf_grapplinghook_max_distance = H::ConVars.FindVar("tf_grapplinghook_max_distance");
const float flGrappleDistance = tf_grapplinghook_max_distance->GetFloat();
Vec3 vPos, vAngle; GetProjectileFireSetup(pLocal, pCmd->viewangles, { 23.5f, -8.f, -3.f }, vPos, vAngle, 2000.f);
Vec3 vForward; Math::AngleVectors(vAngle, &vForward);
CGameTrace trace = {};
CTraceFilterHitscan filter = {};
filter.pSkip = pLocal;
static auto tf_grapplinghook_max_distance = H::ConVars.FindVar("tf_grapplinghook_max_distance");
const float flGrappleDistance = tf_grapplinghook_max_distance->GetFloat();
CTraceFilterWorldAndPropsOnly filter = {};
Trace(vPos, vPos + vForward * flGrappleDistance, MASK_SOLID, &filter, &trace);
return trace.DidHit() && !(trace.surface.flags & SURF_SKY);
}
@@ -694,30 +816,6 @@ int SDK::IsAttacking(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, const CUserCmd*
return G::CanPrimaryAttack && pCmd->buttons & IN_ATTACK ? 1 : G::Reloading && pCmd->buttons & IN_ATTACK ? 2 : 0;
}
float SDK::GetGravity()
{
static auto sv_gravity = H::ConVars.FindVar("sv_gravity");
return sv_gravity->GetFloat();
}
float SDK::MaxSpeed(CTFPlayer* pPlayer, bool bIncludeCrouch, bool bIgnoreSpecialAbility)
{
float flSpeed = pPlayer->CalculateMaxSpeed(bIgnoreSpecialAbility);
if (pPlayer->InCond(TF_COND_SPEED_BOOST) || pPlayer->InCond(TF_COND_HALLOWEEN_SPEED_BOOST))
flSpeed *= 1.35f;
if (bIncludeCrouch && pPlayer->IsDucking() && pPlayer->IsOnGround())
flSpeed /= 3;
return flSpeed;
}
float SDK::AttribHookValue(float value, const char* name, void* econent, void* buffer, bool isGlobalConstString)
{
return S::CAttributeManager_AttribHookValue_Float.Call<float>(value, name, econent, buffer, isGlobalConstString);
}
void SDK::FixMovement(CUserCmd* pCmd, const Vec3& vCurAngle, const Vec3& vTargetAngle)
{
bool bCurOOB = fabsf(Math::NormalizeAngle(vCurAngle.x)) > 90.f;
+9 -5
View File
@@ -23,6 +23,8 @@
#include <intrin.h>
#include <random>
#define no_inline __declspec(noinline)
#define VK_0 0x30
#define VK_1 0x31
#define VK_2 0x32
@@ -122,16 +124,18 @@ namespace SDK
Vec3 PredictOrigin(const Vec3& vOrigin, const Vec3& vVelocity, float flLatency, bool bTrace = true, const Vec3& vMins = {}, const Vec3& vMaxs = {}, unsigned int nMask = MASK_SOLID, float flNormal = 0.f);
bool PredictOrigin(Vec3& vOut, const Vec3& vOrigin, const Vec3& vVelocity, float flLatency, bool bTrace = true, const Vec3& vMins = {}, const Vec3& vMaxs = {}, unsigned int nMask = MASK_SOLID, float flNormal = 0.f);
float GetGravity();
bool IsLoopback();
int GetRoundState();
int GetWinningTeam();
EWeaponType GetWeaponType(CTFWeaponBase* pWeapon, EWeaponType* pSecondaryType = nullptr);
const char* GetClassByIndex(const int nClass, bool bLower = true);
int IsAttacking(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, const CUserCmd* pCmd, bool bTickBase = false);
float GetGravity();
float MaxSpeed(CTFPlayer* pPlayer, bool bIncludeCrouch = false, bool bIgnoreSpecialAbility = false);
const char* GetClassByIndex(const int nClass, bool bLower = true);
float AttribHookValue(float value, const char* name, void* econent, void* buffer = nullptr, bool isGlobalConstString = true);
float MaxSpeed(CTFPlayer* pPlayer, bool bIncludeCrouch = false, bool bIgnoreSpecialAbility = false);
EWeaponType GetWeaponType(CTFWeaponBase* pWeapon, EWeaponType* pSecondaryType = nullptr);
void CanAttack(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, const CUserCmd* pCmd, bool& bPrimary, bool& bSecondary, bool& bReloading);
int IsAttacking(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, const CUserCmd* pCmd, bool bTickBase = false);
void FixMovement(CUserCmd* pCmd, const Vec3& vCurAngle, const Vec3& vTargetAngle);
void FixMovement(CUserCmd* pCmd, const Vec3& vTargetAngle);