diff --git a/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp b/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp index 3e60edb7..e2030a10 100644 --- a/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp +++ b/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.cpp @@ -1361,7 +1361,7 @@ bool CAimbotProjectile::TestAngle(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Tar return bDidHit; } -int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon) +int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bVisuals) { //if (Vars::Aimbot::General::Ignore.Value & Vars::Aimbot::General::IgnoreEnum::Unsimulated && H::Entities.GetChoke(tTarget.m_pEntity->entindex()) > Vars::Aimbot::General::TickTolerance.Value) // return false; @@ -1515,10 +1515,13 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas iLowestPriority = iPriority; flLowestDist = flDist; vAngleTo = vAngles, vPredicted = tTarget.m_vPos, vTarget = vOriginalPoint; m_flTimeTo = vPoint.m_tSolution.m_flTime + m_tInfo.m_flLatency; + if (bVisuals) + { m_vPlayerPath = tStorage.m_vPath; m_vPlayerPath.push_back(tStorage.m_MoveData.m_vecAbsOrigin); m_vProjectilePath = vProjLines; } + } else switch (Vars::Aimbot::General::AimType.Value) { case Vars::Aimbot::General::AimTypeEnum::Smooth: @@ -1537,8 +1540,11 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas { iLowestSmoothPriority = iPriority; flLowestSmoothDist = flDist; vAngleTo = vAngles, vPredicted = tTarget.m_vPos; + if (bVisuals) + { m_vPlayerPath = tStorage.m_vPath; m_vPlayerPath.push_back(tStorage.m_MoveData.m_vecAbsOrigin); + } iReturn = 2; } } @@ -1558,7 +1564,7 @@ int CAimbotProjectile::CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBas bool bMain = iLowestPriority != std::numeric_limits::max(); bool bAny = bMain || iLowestSmoothPriority != std::numeric_limits::max(); - if (bAny && (Vars::Colors::BoundHitboxEdge.Value.a || Vars::Colors::BoundHitboxFace.Value.a || Vars::Colors::BoundHitboxEdgeIgnoreZ.Value.a || Vars::Colors::BoundHitboxFaceIgnoreZ.Value.a)) + if (bVisuals && bAny && (Vars::Colors::BoundHitboxEdge.Value.a || Vars::Colors::BoundHitboxFace.Value.a || Vars::Colors::BoundHitboxEdgeIgnoreZ.Value.a || Vars::Colors::BoundHitboxFaceIgnoreZ.Value.a)) { m_tInfo.m_vHull = m_tInfo.m_vHull.Max(1); float flProjectileTime = TICKS_TO_TIME(m_vProjectilePath.size()); @@ -1687,7 +1693,7 @@ static inline void CancelShot(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCm static inline void DrawVisuals(int iResult, Target_t& tTarget, std::vector& vPlayerPath, std::vector& vProjectilePath, std::vector& vBoxes) { - if (G::Attacking == 1 || !Vars::Aimbot::General::AutoShoot.Value || iResult != 1) + if (G::Attacking == 1 || iResult != 1 || !Vars::Aimbot::General::AutoShoot.Value || Vars::Debug::Info.Value) { bool bPlayerPath = Vars::Visuals::Simulation::PlayerPath.Value; bool bProjectilePath = Vars::Visuals::Simulation::ProjectilePath.Value && (G::Attacking == 1 || Vars::Debug::Info.Value) && iResult == 1; @@ -1749,18 +1755,18 @@ bool CAimbotProjectile::RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser || !F::AimbotGlobal.ShouldAim() && nWeaponID != TF_WEAPON_FLAMETHROWER) return false; - auto vTargets = SortTargets(pLocal, pWeapon); - if (vTargets.empty()) - return false; - if (Vars::Aimbot::Projectile::Modifiers.Value & Vars::Aimbot::Projectile::ModifiersEnum::ChargeWeapon && iRealAimType - && (nWeaponID == TF_WEAPON_COMPOUND_BOW || nWeaponID == TF_WEAPON_PIPEBOMBLAUNCHER)) + && (nWeaponID == TF_WEAPON_COMPOUND_BOW || nWeaponID == TF_WEAPON_PIPEBOMBLAUNCHER || nWeaponID == TF_WEAPON_CANNON && G::LastUserCmd->buttons & IN_ATTACK)) { pCmd->buttons |= IN_ATTACK; if (!G::CanPrimaryAttack && !G::Reloading && Vars::Aimbot::General::AimType.Value == Vars::Aimbot::General::AimTypeEnum::Silent) return false; } + auto vTargets = SortTargets(pLocal, pWeapon); + if (vTargets.empty()) + return false; + if (!G::AimTarget.m_iEntIndex) G::AimTarget = { vTargets.front().m_pEntity->entindex(), I::GlobalVars->tickcount, 0 }; @@ -1776,22 +1782,25 @@ bool CAimbotProjectile::RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser m_vPlayerPath.clear(); m_vProjectilePath.clear(); m_vBoxes.clear(); const int iResult = CanHit(tTarget, pLocal, pWeapon); - if (iResult != 1 && pWeapon->GetWeaponID() == TF_WEAPON_CANNON && Vars::Aimbot::Projectile::Modifiers.Value & Vars::Aimbot::Projectile::ModifiersEnum::ChargeWeapon && !(pCmd->buttons & IN_ATTACK)) + if (iResult != 1 && pWeapon->GetWeaponID() == TF_WEAPON_CANNON && Vars::Aimbot::Projectile::Modifiers.Value & Vars::Aimbot::Projectile::ModifiersEnum::ChargeWeapon + && !(G::OriginalCmd.buttons & (IN_ATTACK | IN_USE))) { + float flTime = m_flTimeTo - GRENADE_CHECK_INTERVAL; float flCharge = pWeapon->As()->m_flDetonateTime() > 0.f ? pWeapon->As()->m_flDetonateTime() - I::GlobalVars->curtime : 1.f; - flCharge = floorf(flCharge / 0.195f) * 0.195f; - if (flCharge < m_flTimeTo) + flCharge = floorf(flCharge / GRENADE_CHECK_INTERVAL) * GRENADE_CHECK_INTERVAL + F::ProjSim.GetDesync(); + if (flCharge < flTime) { if (pWeapon->As()->m_flDetonateTime() > 0.f) CancelShot(pLocal, pWeapon, pCmd, m_iLastTickCancel); } else { + pCmd->buttons |= IN_ATTACK; if (m_iLastTickCancel) pCmd->weaponselect = m_iLastTickCancel = 0; - pCmd->buttons |= IN_ATTACK; + G::OriginalCmd.buttons |= IN_USE; } } if (!iResult) continue; @@ -1823,10 +1832,23 @@ bool CAimbotProjectile::RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser if (m_iLastTickCancel) pCmd->weaponselect = m_iLastTickCancel = 0; if (Vars::Aimbot::Projectile::Modifiers.Value & Vars::Aimbot::Projectile::ModifiersEnum::ChargeWeapon) - { + { // rerun, if we won't hit in the future, fire + int iResult2 = 0; + float flCharge = pWeapon->As()->m_flDetonateTime() - I::GlobalVars->curtime; - flCharge = floorf(flCharge / 0.195f) * 0.195f; - if (flCharge < m_flTimeTo) + flCharge = floorf(flCharge / GRENADE_CHECK_INTERVAL) * GRENADE_CHECK_INTERVAL + F::ProjSim.GetDesync(); + if (flCharge > GRENADE_CHECK_INTERVAL) + { + auto tTarget2 = tTarget; + float flOldDetonateTime = pWeapon->As()->m_flDetonateTime(); + + pWeapon->As()->m_flDetonateTime() -= GRENADE_CHECK_INTERVAL; + iResult2 = CanHit(tTarget2, pLocal, pWeapon, false); + + pWeapon->As()->m_flDetonateTime() = flOldDetonateTime; + } + + if (iResult2 != 1) pCmd->buttons &= ~IN_ATTACK; } else diff --git a/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.h b/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.h index 07d09668..ad754843 100644 --- a/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.h +++ b/Amalgam/src/Features/Aimbot/AimbotProjectile/AimbotProjectile.h @@ -57,7 +57,7 @@ private: void CalculateAngle(const Vec3& vLocalPos, const Vec3& vTargetPos, int iSimTime, Solution_t& out, bool bAccuracy = true); bool TestAngle(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, Target_t& tTarget, Vec3& vPoint, Vec3& vAngles, int iSimTime, bool bSplash, bool* pHitSolid = nullptr, std::vector* pProjectilePath = nullptr); - int CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon); + int CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bVisuals = true); bool RunMain(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd); bool CanHit(Target_t& tTarget, CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CBaseEntity* pProjectile); diff --git a/Amalgam/src/Features/Players/PlayerUtils.cpp b/Amalgam/src/Features/Players/PlayerUtils.cpp index 3e1028a4..dee02359 100644 --- a/Amalgam/src/Features/Players/PlayerUtils.cpp +++ b/Amalgam/src/Features/Players/PlayerUtils.cpp @@ -426,6 +426,19 @@ const char* CPlayerlistUtils::GetPlayerName(uint32_t uAccountID, const char* sDe return sDefault; } +const char* CPlayerlistUtils::GetPlayerName(int iIndex) +{ + auto pResource = H::Entities.GetResource(); + return pResource && pResource->IsValid(iIndex) ? pResource->GetName(iIndex) : PLAYER_ERROR_NAME; +} + +const char* CPlayerlistUtils::GetPlayerName(uint32_t uAccountID) +{ + auto pResource = H::Entities.GetResource(); + int iIndex = GetIndex(uAccountID); + return pResource && pResource->IsValid(iIndex) ? pResource->GetName(iIndex) : PLAYER_ERROR_NAME; +} + void CPlayerlistUtils::Store() diff --git a/Amalgam/src/Features/Players/PlayerUtils.h b/Amalgam/src/Features/Players/PlayerUtils.h index 67542fc3..439e7675 100644 --- a/Amalgam/src/Features/Players/PlayerUtils.h +++ b/Amalgam/src/Features/Players/PlayerUtils.h @@ -117,6 +117,8 @@ public: int GetNameType(uint32_t uAccountID); const char* GetPlayerName(int iIndex, const char* sDefault, int* pType = nullptr); const char* GetPlayerName(uint32_t uAccountID, const char* sDefault, int* pType = nullptr); + const char* GetPlayerName(int iIndex); + const char* GetPlayerName(uint32_t uAccountID); std::vector& GetPlayerTags(uint32_t uAccountID) { return m_mPlayerTags.contains(uAccountID) ? m_mPlayerTags[uAccountID] : m_vDummy; } std::string* GetPlayerAlias(uint32_t uAccountID) { return m_mPlayerAliases.contains(uAccountID) ? &m_mPlayerAliases[uAccountID] : nullptr; } diff --git a/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.cpp b/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.cpp index fc3a94d0..248009cd 100644 --- a/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.cpp +++ b/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.cpp @@ -2,6 +2,7 @@ #include "../../EnginePrediction/EnginePrediction.h" #include "../../CritHack/CritHack.h" +#include "../../Backtrack/Backtrack.h" bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeapon, Vec3 vAngles, ProjectileInfo& tProjInfo, int iFlags, float flAutoCharge) { @@ -109,7 +110,7 @@ bool CProjectileSimulation::GetInfoMain(CTFPlayer* pPlayer, CTFWeaponBase* pWeap ? pWeapon->As()->m_flDetonateTime() > 0.f ? pWeapon->As()->m_flDetonateTime() - I::GlobalVars->curtime : flMortar : SDK::AttribHookValue(2.f, "fuse_mult", pWeapon); auto uType = bCannon ? FNV1A::Hash32Const("models/weapons/w_models/w_cannonball.mdl") : FNV1A::Hash32Const("models/weapons/w_models/w_grenade_grenadelauncher.mdl"); - tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 6.f, 6.f, 6.f }, flSpeed, 1.f, floorf(flLifetime / 0.195f + 1) * 0.195f }; + tProjInfo = { pPlayer, pWeapon, uType, vPos, vAngle, { 6.f, 6.f, 6.f }, flSpeed, 1.f, ceilf(flLifetime / GRENADE_CHECK_INTERVAL) * GRENADE_CHECK_INTERVAL + GetDesync() }; return true; } case TF_WEAPON_PIPEBOMBLAUNCHER: @@ -622,6 +623,11 @@ Vec3 CProjectileSimulation::GetVelocity() return vOut; } +float CProjectileSimulation::GetDesync() +{ + return I::GlobalVars->curtime - TICKS_TO_TIME(I::ClientState->m_ClockDriftMgr.m_nServerTick) - F::Backtrack.GetReal(); +} + void CProjectileSimulation::SetupTrace(CTraceFilterCollideable& filter, int& nMask, CTFWeaponBase* pWeapon, int nTick, bool bQuick) { switch (nTick) diff --git a/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.h b/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.h index f3abdb91..a0ddc65c 100644 --- a/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.h +++ b/Amalgam/src/Features/Simulation/ProjectileSimulation/ProjectileSimulation.h @@ -11,6 +11,8 @@ Enum(ProjSim, MaxSpeed = 1 << 5 // default projectile speeds to their maximum ) +#define GRENADE_CHECK_INTERVAL 0.195f + struct ProjectileInfo { CTFPlayer* m_pOwner = nullptr; @@ -60,6 +62,7 @@ public: void RunTick(ProjectileInfo& tProjInfo, bool bPath = true); Vec3 GetOrigin(); Vec3 GetVelocity(); + float GetDesync(); inline std::pair GetEntities(CBaseEntity* pProjectile) { diff --git a/Amalgam/src/Features/Visuals/Visuals.cpp b/Amalgam/src/Features/Visuals/Visuals.cpp index dd14fa3a..cc908812 100644 --- a/Amalgam/src/Features/Visuals/Visuals.cpp +++ b/Amalgam/src/Features/Visuals/Visuals.cpp @@ -286,16 +286,24 @@ void CVisuals::DrawAntiAim(CTFPlayer* pLocal) #define PAIR(x) { x, #x } void CVisuals::DrawDebugInfo(CTFPlayer* pLocal) { +#ifdef DEBUG_TEXT + if (!Vars::Debug::Info.Value && m_vDebugText.empty()) + return; +#else + if (!Vars::Debug::Info.Value) + return; +#endif + + int x = 10, y = 10; + const auto& fFont = H::Fonts.GetFont(FONT_INDICATORS); + const int nTall = fFont.m_nTall + H::Draw.Scale(1); + y -= nTall; + if (Vars::Debug::Info.Value) { auto pWeapon = H::Entities.GetWeapon(); auto pCmd = !I::EngineClient->IsPlayingDemo() ? G::LastUserCmd : I::Input->GetUserCmd(I::ClientState->lastoutgoingcommand); - int x = 10, y = 10; - const auto& fFont = H::Fonts.GetFont(FONT_INDICATORS); - const int nTall = fFont.m_nTall + H::Draw.Scale(1); - y -= nTall; - if (pCmd) { H::Draw.StringOutlined(fFont, x, y += nTall, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("View: ({:.3f}, {:.3f}, {:.3f})", pCmd->viewangles.x, pCmd->viewangles.y, pCmd->viewangles.z).c_str()); @@ -371,7 +379,8 @@ void CVisuals::DrawDebugInfo(CTFPlayer* pLocal) float flSecondaryAttack = pWeapon->m_flNextSecondaryAttack(); float flAttack = pLocal->m_flNextAttack(); - H::Draw.StringOutlined(fFont, x, y += nTall * 2, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("Weapon: {}, {}", pWeapon->GetSlot(), pWeapon->GetWeaponID()).c_str()); + y += nTall; + H::Draw.StringOutlined(fFont, x, y += nTall, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("Weapon: {}, {}", pWeapon->GetSlot(), pWeapon->GetWeaponID()).c_str()); H::Draw.StringOutlined(fFont, x, y += nTall, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("Attacking: {}", G::Attacking).c_str()); H::Draw.StringOutlined(fFont, x, y += nTall, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("CanPrimaryAttack: {} ([{:.3f} | {:.3f}] <= {:.3f})", G::CanPrimaryAttack, flPrimaryAttack, flAttack, flTime).c_str()); H::Draw.StringOutlined(fFont, x, y += nTall, Vars::Menu::Theme::Active.Value, Vars::Menu::Theme::Background.Value, ALIGN_TOPLEFT, std::format("CanSecondaryAttack: {} ([{:.3f} | {:.3f}] <= {:.3f})", G::CanSecondaryAttack, flSecondaryAttack, flAttack, flTime).c_str()); @@ -381,7 +390,30 @@ void CVisuals::DrawDebugInfo(CTFPlayer* pLocal) } */ } + +#ifdef DEBUG_TEXT + if (!m_vDebugText.empty()) + { + if (Vars::Debug::Info.Value) + y += nTall; + for (auto& [sString, tColor] : m_vDebugText) + 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 std::string& sString, Color_t tColor) +{ + m_vDebugText.emplace_back(sString, tColor); +} + +void CVisuals::ClearDebugText() +{ + m_vDebugText.clear(); +} +#endif + #undef PAIR diff --git a/Amalgam/src/Features/Visuals/Visuals.h b/Amalgam/src/Features/Visuals/Visuals.h index 5e872d8a..7fa0e4e8 100644 --- a/Amalgam/src/Features/Visuals/Visuals.h +++ b/Amalgam/src/Features/Visuals/Visuals.h @@ -3,6 +3,8 @@ #include +#define DEBUG_TEXT + struct Projectile_t { std::vector m_vPath = {}; @@ -35,6 +37,10 @@ private: std::vector m_vSightLines = {}; std::vector m_vPickups = {}; +#ifdef DEBUG_TEXT + std::vector> m_vDebugText = {}; +#endif + public: void Event(IGameEvent* pEvent, uint32_t uHash); void Store(); @@ -45,6 +51,11 @@ public: void DrawAntiAim(CTFPlayer* pLocal); void DrawDebugInfo(CTFPlayer* pLocal); +#ifdef DEBUG_TEXT + void AddDebugText(const std::string& sString, Color_t tColor = Vars::Menu::Theme::Active.Value); + void ClearDebugText(); +#endif + std::vector GetHitboxes(matrix3x4* aBones, CBaseAnimating* pEntity, std::vector vHitboxes = {}, int iTarget = -1); void DrawEffects(); void DrawHitboxes(int iStore = 0); diff --git a/Amalgam/src/SDK/Definitions/Main/CPlayerResource.h b/Amalgam/src/SDK/Definitions/Main/CPlayerResource.h index 9a921cb7..f2ade70f 100644 --- a/Amalgam/src/SDK/Definitions/Main/CPlayerResource.h +++ b/Amalgam/src/SDK/Definitions/Main/CPlayerResource.h @@ -21,6 +21,14 @@ public: NETVAR_ARRAY(m_iUserID, int, "CPlayerResource", "m_iUserID"); NETVAR_ARRAY_OFF(m_szName, const char*, "CPlayerResource", "m_iPing", -816); + + inline bool IsValid(int iIndex) + { + if (iIndex < 0 || iIndex > MAX_PLAYERS) + return false; + + return m_bValid(iIndex); + } inline bool IsFakePlayer(int iIndex, bool bPlayerInfo = false) { diff --git a/Amalgam/src/SDK/Vars.h b/Amalgam/src/SDK/Vars.h index d378d230..5a930dfa 100644 --- a/Amalgam/src/SDK/Vars.h +++ b/Amalgam/src/SDK/Vars.h @@ -324,7 +324,7 @@ namespace Vars VA_LIST("Auto", "##Divider", "Head", "Body", "Feet", "##Divider", "Bodyaim if lethal", "Prioritize feet"), Auto = 1 << 0, Head = 1 << 1, Body = 1 << 2, Feet = 1 << 3, BodyaimIfLethal = 1 << 4, PrioritizeFeet = 1 << 5); CVarEnum(Modifiers, VA_LIST("Modifiers", "Projectile modifiers"), 0b1010, DROPDOWN_MULTI, nullptr, - VA_LIST("Charge shot", "Cancel charge", "Use prime time"), + VA_LIST("Charge weapon", "Cancel charge", "Use prime time"), ChargeWeapon = 1 << 0, CancelCharge = 1 << 1, UsePrimeTime = 1 << 2); CVar(MaxSimulationTime, "Max simulation time", 2.f, SLIDER_MIN | SLIDER_PRECISION, 0.1f, 2.5f, 0.25f, "%gs"); CVar(HitChance, "Hit chance", 0.f, SLIDER_CLAMP | SLIDER_PRECISION, 0.f, 100.f, 10.f, "%g%%");