From eeb4fe81dbe702e4860e4bb6776fdde061535be1 Mon Sep 17 00:00:00 2001
From: rei-2 <174158077+rei-2@users.noreply.github.com>
Date: Sat, 8 Feb 2025 21:09:37 -0500
Subject: [PATCH] hitbox accuracy improvement rework resolver some changes to
configs
---
Amalgam/Amalgam.vcxproj | 2 +
Amalgam/Amalgam.vcxproj.filters | 2 +
Amalgam/cpp.hint | 2 +-
.../Aimbot/AimbotHitscan/AimbotHitscan.cpp | 6 +-
.../Aimbot/AimbotMelee/AimbotMelee.cpp | 39 +-
Amalgam/src/Features/Backtrack/Backtrack.cpp | 9 +-
Amalgam/src/Features/Backtrack/Backtrack.h | 2 +-
Amalgam/src/Features/Configs/Configs.cpp | 124 +++-
Amalgam/src/Features/Configs/Configs.h | 14 +-
Amalgam/src/Features/CritHack/CritHack.cpp | 2 +-
Amalgam/src/Features/ImGui/Menu/Menu.cpp | 256 +++++---
.../NoSpreadHitscan/NoSpreadHitscan.cpp | 16 +-
.../NoSpreadHitscan/NoSpreadHitscan.h | 2 +-
Amalgam/src/Features/Players/PlayerUtils.h | 3 -
Amalgam/src/Features/Records/Records.cpp | 36 +-
Amalgam/src/Features/Records/Records.h | 7 +-
Amalgam/src/Features/Resolver/Resolver.cpp | 609 ++++++++++--------
Amalgam/src/Features/Resolver/Resolver.h | 68 +-
.../src/Hooks/CBaseAnimating_FrameAdvance.cpp | 2 +-
.../src/Hooks/CBaseAnimating_Interpolate.cpp | 8 +
...seAnimating_UpdateClientSideAnimations.cpp | 6 +-
Amalgam/src/Hooks/CBaseClient_Connect.cpp | 2 +-
Amalgam/src/Hooks/CBaseClient_Disconnect.cpp | 2 +-
.../src/Hooks/CBaseClient_SetUpdateRate.cpp | 2 +-
.../Hooks/CBaseEntity_EstimateAbsVelocity.cpp | 24 +
.../Hooks/CClientModeShared_CreateMove.cpp | 4 +-
.../CClientState_GetClientInterpAmount.cpp | 2 +-
.../CInterpolatedVarArrayBase_Interpolate.cpp | 2 +-
.../Hooks/CPhysicsObject_OutputDebugInfo.cpp | 2 +-
...nceTransitioner_CheckForSequenceChange.cpp | 2 +-
.../src/Hooks/CTFGameRules_ModifySentChat.cpp | 2 +-
Amalgam/src/Hooks/CTFMatchSummary_OnTick.cpp | 2 +-
...CTFPartyClient_BCanRequestToJoinPlayer.cpp | 2 +-
.../Hooks/CTFPlayer_BuildTransformations.cpp | 15 +
Amalgam/src/Hooks/CViewRender_LevelInit.cpp | 4 +-
.../CViewRender_PerformScreenSpaceEffects.cpp | 2 +-
Amalgam/src/Hooks/FX_FireBullets.cpp | 3 -
.../IBaseClientDLL_DispatchUserMessage.cpp | 48 +-
.../Hooks/IBaseClientDLL_FrameStageNotify.cpp | 53 +-
.../SDK/Definitions/Main/CBaseCombatWeapon.h | 2 +-
.../src/SDK/Definitions/Main/CBaseEntity.h | 2 +-
.../src/SDK/Definitions/Main/CBaseObject.h | 2 +-
.../src/SDK/Definitions/Main/CBasePlayer.h | 8 +-
.../src/SDK/Definitions/Main/CEconEntity.h | 2 +-
Amalgam/src/SDK/Definitions/Main/CTFPlayer.h | 2 +-
.../src/SDK/Definitions/Main/CTFWeaponBase.h | 26 +-
Amalgam/src/SDK/Vars.h | 18 +-
Amalgam/src/Utils/NetVars/NetVars.h | 2 +-
48 files changed, 920 insertions(+), 532 deletions(-)
create mode 100644 Amalgam/src/Hooks/CBaseEntity_EstimateAbsVelocity.cpp
create mode 100644 Amalgam/src/Hooks/CTFPlayer_BuildTransformations.cpp
diff --git a/Amalgam/Amalgam.vcxproj b/Amalgam/Amalgam.vcxproj
index 62b83070..e6d84913 100644
--- a/Amalgam/Amalgam.vcxproj
+++ b/Amalgam/Amalgam.vcxproj
@@ -884,8 +884,10 @@
+
+
diff --git a/Amalgam/Amalgam.vcxproj.filters b/Amalgam/Amalgam.vcxproj.filters
index f081baa1..0d290497 100644
--- a/Amalgam/Amalgam.vcxproj.filters
+++ b/Amalgam/Amalgam.vcxproj.filters
@@ -186,6 +186,8 @@
+
+
diff --git a/Amalgam/cpp.hint b/Amalgam/cpp.hint
index d02778d2..afdd0c42 100644
--- a/Amalgam/cpp.hint
+++ b/Amalgam/cpp.hint
@@ -55,7 +55,7 @@ namespace MAKE_INTERFACE_SCOPE \
}
#define VIRTUAL(name, type, fn, base, index) inline type name() \
{ \
- return reinterpret_cast(U::Memory.GetVFunc(base, index))(base); \
+ return reinterpret_cast(U::Memory.GetVFunc(base, index))(base); \
}
#define CONDGET(name, conditions, cond) inline bool name() \
{ \
diff --git a/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp b/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp
index 849b0b8c..51b06673 100644
--- a/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp
+++ b/Amalgam/src/Features/Aimbot/AimbotHitscan/AimbotHitscan.cpp
@@ -554,7 +554,7 @@ bool CAimbotHitscan::ShouldFire(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUser
return false;
break;
case TF_WEAPON_REVOLVER:
- if (!pWeapon->AmbassadorCanHeadshot())
+ if (SDK::AttribHookValue(0, "set_weapon_mode", pWeapon) == 1 && !pWeapon->AmbassadorCanHeadshot())
return false;
}
}
@@ -775,7 +775,7 @@ void CAimbotHitscan::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pC
if (G::Attacking == 1)
{
if (target.m_pEntity->IsPlayer())
- F::Resolver.Aimbot(target.m_pEntity->As(), target.m_nAimedHitbox == HITBOX_HEAD);
+ F::Resolver.HitscanRan(pLocal, target.m_pEntity->As(), pWeapon, target.m_nAimedHitbox);
if (target.m_bBacktrack)
pCmd->tick_count = TIME_TO_TICKS(target.m_tRecord.m_flSimTime) + TIME_TO_TICKS(F::Backtrack.m_flFakeInterp);
@@ -792,7 +792,7 @@ void CAimbotHitscan::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pC
{
Vec3 vEyePos = pLocal->GetShootPos();
float flDist = vEyePos.DistTo(target.m_vPos);
- Vec3 vForward; Math::AngleVectors(target.m_vAngleTo, &vForward);
+ Vec3 vForward; Math::AngleVectors(target.m_vAngleTo + pLocal->m_vecPunchAngle(), &vForward);
G::LineStorage.push_back({ { vEyePos, vEyePos + vForward * flDist }, I::GlobalVars->curtime + 5.f, Vars::Colors::Bullet.Value, true });
}
diff --git a/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp b/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp
index a82c2c2d..2bf113d0 100644
--- a/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp
+++ b/Amalgam/src/Features/Aimbot/AimbotMelee/AimbotMelee.cpp
@@ -169,7 +169,10 @@ void CAimbotMelee::SimulatePlayers(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, st
}
else
{
+ G::LineStorage.clear();
+ G::BoxStorage.clear();
G::PathStorage.clear();
+
if (Vars::Colors::PlayerPath.Value.a)
{
G::PathStorage.push_back({ localStorage.m_vPath, I::GlobalVars->curtime + 5.f, Vars::Colors::PlayerPath.Value, Vars::Visuals::Simulation::PlayerPath.Value });
@@ -505,28 +508,15 @@ void CAimbotMelee::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd
target.m_vAngleTo = Aim(G::CurrentUserCmd->viewangles, Math::CalcAngle(vEyePos, target.m_vPos));
}
- bool bPath = Vars::Visuals::Simulation::SwingLines.Value && Vars::Visuals::Simulation::PlayerPath.Value && pCmd->buttons & IN_ATTACK && pWeapon->m_flSmackTime() < 0.f && Vars::Aimbot::General::AutoShoot.Value && !Vars::Debug::Info.Value;
+ bool bPath = Vars::Visuals::Simulation::SwingLines.Value && Vars::Visuals::Simulation::PlayerPath.Value && Vars::Aimbot::General::AutoShoot.Value && !Vars::Debug::Info.Value;
bool bLine = Vars::Visuals::Bullet::Enabled.Value;
bool bBoxes = Vars::Visuals::Hitbox::Enabled.Value & Vars::Visuals::Hitbox::EnabledEnum::OnShot;
- if (G::Attacking == 1 && (bLine || bBoxes) || bPath)
+ if (pCmd->buttons & IN_ATTACK && pWeapon->m_flSmackTime() < 0.f && bPath)
{
G::LineStorage.clear();
G::BoxStorage.clear();
G::PathStorage.clear();
- if (bLine)
- {
- Vec3 vEyePos = pLocal->GetShootPos();
- float flDist = vEyePos.DistTo(target.m_vPos);
- Vec3 vForward; Math::AngleVectors(target.m_vAngleTo, &vForward);
-
- G::LineStorage.push_back({ { vEyePos, vEyePos + vForward * flDist }, I::GlobalVars->curtime + 5.f, Vars::Colors::Bullet.Value, true });
- }
- if (bBoxes)
- {
- auto vBoxes = F::Visuals.GetHitboxes(target.m_tRecord.m_BoneMatrix.m_aBones, target.m_pEntity->As());
- G::BoxStorage.insert(G::BoxStorage.end(), vBoxes.begin(), vBoxes.end());
- }
if (bPath)
{
if (Vars::Colors::PlayerPath.Value.a)
@@ -541,6 +531,25 @@ void CAimbotMelee::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd
}
}
}
+ if (G::Attacking == 1 && (bLine || bBoxes))
+ {
+ G::LineStorage.clear();
+ G::BoxStorage.clear();
+
+ if (bLine)
+ {
+ Vec3 vEyePos = pLocal->GetShootPos();
+ float flDist = vEyePos.DistTo(target.m_vPos);
+ Vec3 vForward; Math::AngleVectors(target.m_vAngleTo + pLocal->m_vecPunchAngle(), &vForward);
+
+ G::LineStorage.push_back({ { vEyePos, vEyePos + vForward * flDist }, I::GlobalVars->curtime + 5.f, Vars::Colors::Bullet.Value, true });
+ }
+ if (bBoxes)
+ {
+ auto vBoxes = F::Visuals.GetHitboxes(target.m_tRecord.m_BoneMatrix.m_aBones, target.m_pEntity->As());
+ G::BoxStorage.insert(G::BoxStorage.end(), vBoxes.begin(), vBoxes.end());
+ }
+ }
Aim(pCmd, target.m_vAngleTo);
break;
diff --git a/Amalgam/src/Features/Backtrack/Backtrack.cpp b/Amalgam/src/Features/Backtrack/Backtrack.cpp
index e1688759..ab28eed3 100644
--- a/Amalgam/src/Features/Backtrack/Backtrack.cpp
+++ b/Amalgam/src/Features/Backtrack/Backtrack.cpp
@@ -3,7 +3,7 @@
#include "../PacketManip/FakeLag/FakeLag.h"
#include "../TickHandler/TickHandler.h"
-void CBacktrack::Restart()
+void CBacktrack::Reset()
{
m_mRecords.clear();
m_dSequences.clear();
@@ -262,7 +262,7 @@ void CBacktrack::FrameStageNotify()
{
UpdateDatagram();
if (!I::EngineClient->IsInGame())
- return Restart();
+ return;
static auto sv_maxunlag = U::ConVars.FindVar("sv_maxunlag");
m_flMaxUnlag = sv_maxunlag ? sv_maxunlag->GetFloat() : 1.f;
@@ -278,7 +278,10 @@ void CBacktrack::Run(CUserCmd* pCmd)
void CBacktrack::ResolverUpdate(CBaseEntity* pEntity)
{
- m_mRecords[pEntity].clear(); // TODO: eventually remake records and rotate them or smthn idk, maybe just rotate them
+ if (!pEntity)
+ return;
+
+ m_mRecords[pEntity].clear();
}
void CBacktrack::ReportShot(int iIndex)
diff --git a/Amalgam/src/Features/Backtrack/Backtrack.h b/Amalgam/src/Features/Backtrack/Backtrack.h
index daebacd7..acad4f74 100644
--- a/Amalgam/src/Features/Backtrack/Backtrack.h
+++ b/Amalgam/src/Features/Backtrack/Backtrack.h
@@ -61,7 +61,7 @@ public:
void FrameStageNotify();
void Run(CUserCmd* pCmd);
- void Restart();
+ void Reset();
void SetLerp(IGameEvent* pEvent);
void ResolverUpdate(CBaseEntity* pEntity);
void ReportShot(int iIndex);
diff --git a/Amalgam/src/Features/Configs/Configs.cpp b/Amalgam/src/Features/Configs/Configs.cpp
index 50948515..5fc0a467 100644
--- a/Amalgam/src/Features/Configs/Configs.cpp
+++ b/Amalgam/src/Features/Configs/Configs.cpp
@@ -307,7 +307,7 @@ CConfigs::CConfigs()
}
#define LoadMain(type, tree) if (IsType(type)) LoadCond(type, tree)
-bool CConfigs::SaveConfig(const std::string& configName, bool bNotify)
+bool CConfigs::SaveConfig(const std::string& sConfigName, bool bNotify)
{
try
{
@@ -354,10 +354,10 @@ bool CConfigs::SaveConfig(const std::string& configName, bool bNotify)
}
writeTree.put_child("ConVars", varTree);
- write_json(sConfigPath + "\\" + configName + sConfigExtension, writeTree);
- sCurrentConfig = configName; sCurrentVisuals = "";
+ write_json(sConfigPath + "\\" + sConfigName + sConfigExtension, writeTree);
+ sCurrentConfig = sConfigName; sCurrentVisuals = "";
if (bNotify)
- F::Notifications.Add("Config " + configName + " saved");
+ F::Notifications.Add("Config " + sConfigName + " saved");
}
catch (...)
{
@@ -368,13 +368,13 @@ bool CConfigs::SaveConfig(const std::string& configName, bool bNotify)
return true;
}
-bool CConfigs::LoadConfig(const std::string& configName, bool bNotify)
+bool CConfigs::LoadConfig(const std::string& sConfigName, bool bNotify)
{
// Check if the config exists
- if (!std::filesystem::exists(sConfigPath + "\\" + configName + sConfigExtension))
+ if (!std::filesystem::exists(sConfigPath + "\\" + sConfigName + sConfigExtension))
{
// Save default config if one doesn't yet exist
- if (configName == std::string("default"))
+ if (sConfigName == std::string("default"))
SaveConfig("default", false);
return false;
@@ -386,7 +386,7 @@ bool CConfigs::LoadConfig(const std::string& configName, bool bNotify)
const bool bLoadNosave = GetAsyncKeyState(VK_SHIFT) & 0x8000;
boost::property_tree::ptree readTree;
- read_json(sConfigPath + "\\" + configName + sConfigExtension, readTree);
+ read_json(sConfigPath + "\\" + sConfigName + sConfigExtension, readTree);
bool bLegacy = false;
if (const auto condTree = readTree.get_child_optional("Binds"))
@@ -467,9 +467,9 @@ bool CConfigs::LoadConfig(const std::string& configName, bool bNotify)
H::Fonts.Reload(Vars::Menu::Scale.Map[DEFAULT_BIND]);
- sCurrentConfig = configName; sCurrentVisuals = "";
+ sCurrentConfig = sConfigName; sCurrentVisuals = "";
if (bNotify)
- F::Notifications.Add("Config " + configName + " loaded");
+ F::Notifications.Add("Config " + sConfigName + " loaded");
}
catch (...)
{
@@ -485,7 +485,7 @@ bool CConfigs::LoadConfig(const std::string& configName, bool bNotify)
#define LoadRegular(type, tree) LoadJson(tree, var->m_sName.c_str(), var->As()->Map[DEFAULT_BIND])
#define LoadMisc(type, tree) if (IsType(type)) LoadRegular(type, tree);
-bool CConfigs::SaveVisual(const std::string& configName, bool bNotify)
+bool CConfigs::SaveVisual(const std::string& sConfigName, bool bNotify)
{
try
{
@@ -511,9 +511,9 @@ bool CConfigs::SaveVisual(const std::string& configName, bool bNotify)
else SaveMisc(WindowBox_t, writeTree)
}
- write_json(sConfigPath + "\\Visuals\\" + configName + sConfigExtension, writeTree);
+ write_json(sConfigPath + "\\Visuals\\" + sConfigName + sConfigExtension, writeTree);
if (bNotify)
- F::Notifications.Add("Visual config " + configName + " saved");
+ F::Notifications.Add("Visual config " + sConfigName + " saved");
}
catch (...)
{
@@ -523,12 +523,12 @@ bool CConfigs::SaveVisual(const std::string& configName, bool bNotify)
return true;
}
-bool CConfigs::LoadVisual(const std::string& configName, bool bNotify)
+bool CConfigs::LoadVisual(const std::string& sConfigName, bool bNotify)
{
// Check if the visual config exists
- if (!std::filesystem::exists(sVisualsPath + "\\" + configName + sConfigExtension))
+ if (!std::filesystem::exists(sVisualsPath + "\\" + sConfigName + sConfigExtension))
{
- //if (configName == std::string("default"))
+ //if (sConfigName == std::string("default"))
// SaveVisual("default");
return false;
}
@@ -538,7 +538,7 @@ bool CConfigs::LoadVisual(const std::string& configName, bool bNotify)
const bool bLoadNosave = GetAsyncKeyState(VK_SHIFT) & 0x8000;
boost::property_tree::ptree readTree;
- read_json(sConfigPath + "\\Visuals\\" + configName + sConfigExtension, readTree);
+ read_json(sConfigPath + "\\Visuals\\" + sConfigName + sConfigExtension, readTree);
for (auto& var : g_Vars)
{
@@ -558,9 +558,9 @@ bool CConfigs::LoadVisual(const std::string& configName, bool bNotify)
else LoadMisc(WindowBox_t, readTree)
}
- sCurrentVisuals = configName;
+ sCurrentVisuals = sConfigName;
if (bNotify)
- F::Notifications.Add("Visual config " + configName + " loaded");
+ F::Notifications.Add("Visual config " + sConfigName + " loaded");
}
catch (...)
{
@@ -573,11 +573,46 @@ bool CConfigs::LoadVisual(const std::string& configName, bool bNotify)
#define ResetType(type) var->As()->Map = { { DEFAULT_BIND, var->As()->Default } };
#define ResetT(type) if (IsType(type)) ResetType(type)
-void CConfigs::RemoveConfig(const std::string& configName)
+void CConfigs::RemoveConfig(const std::string& sConfigName, bool bNotify)
{
- if (FNV1A::Hash32(configName.c_str()) != FNV1A::Hash32Const("default"))
- std::filesystem::remove(sConfigPath + "\\" + configName + sConfigExtension);
- else
+ try
+ {
+ if (FNV1A::Hash32(sConfigName.c_str()) != FNV1A::Hash32Const("default"))
+ {
+ std::filesystem::remove(sConfigPath + "\\" + sConfigName + sConfigExtension);
+
+ LoadConfig("default", false);
+
+ if (bNotify)
+ F::Notifications.Add("Config " + sConfigName + " deleted");
+ }
+ else
+ ResetConfig(sConfigName);
+ }
+ catch (...)
+ {
+ SDK::Output("RemoveConfig", "Failed", { 175, 150, 255, 255 });
+ }
+}
+
+void CConfigs::RemoveVisual(const std::string& sConfigName, bool bNotify)
+{
+ try
+ {
+ std::filesystem::remove(sVisualsPath + "\\" + sConfigName + sConfigExtension);
+
+ if (bNotify)
+ F::Notifications.Add("Visual config " + sConfigName + " deleted");
+ }
+ catch (...)
+ {
+ SDK::Output("RemoveVisual", "Failed", { 175, 150, 255, 255 });
+ }
+}
+
+void CConfigs::ResetConfig(const std::string& sConfigName, bool bNotify)
+{
+ try
{
const bool bLoadNosave = GetAsyncKeyState(VK_SHIFT) & 0x8000;
@@ -601,11 +636,48 @@ void CConfigs::RemoveConfig(const std::string& configName)
else ResetT(WindowBox_t)
}
- SaveConfig("default", false);
+ SaveConfig(sConfigName, false);
+
+ if (bNotify)
+ F::Notifications.Add("Config " + sConfigName + " reset");
+ }
+ catch (...)
+ {
+ SDK::Output("ResetConfig", "Failed", { 175, 150, 255, 255 });
}
}
-void CConfigs::RemoveVisual(const std::string& configName)
+void CConfigs::ResetVisual(const std::string& sConfigName, bool bNotify)
{
- std::filesystem::remove(sVisualsPath + "\\" + configName + sConfigExtension);
+ try
+ {
+ const bool bLoadNosave = GetAsyncKeyState(VK_SHIFT) & 0x8000;
+
+ for (auto& var : g_Vars)
+ {
+ if (!(var->m_iFlags & VISUAL) || !bLoadNosave && var->m_iFlags & NOSAVE)
+ continue;
+
+ ResetT(bool)
+ else ResetT(int)
+ else ResetT(float)
+ else ResetT(IntRange_t)
+ else ResetT(FloatRange_t)
+ else ResetT(std::string)
+ else ResetT(std::vector)
+ else ResetT(Color_t)
+ else ResetT(Gradient_t)
+ else ResetT(DragBox_t)
+ else ResetT(WindowBox_t)
+ }
+
+ SaveVisual(sConfigName, false);
+
+ if (bNotify)
+ F::Notifications.Add("Visual config " + sConfigName + " reset");
+ }
+ catch (...)
+ {
+ SDK::Output("ResetVisual", "Failed", { 175, 150, 255, 255 });
+ }
}
\ No newline at end of file
diff --git a/Amalgam/src/Features/Configs/Configs.h b/Amalgam/src/Features/Configs/Configs.h
index c64caf11..e0fcac4c 100644
--- a/Amalgam/src/Features/Configs/Configs.h
+++ b/Amalgam/src/Features/Configs/Configs.h
@@ -34,12 +34,14 @@ class CConfigs
public:
CConfigs();
- bool SaveConfig(const std::string& configName, bool bNotify = true);
- bool LoadConfig(const std::string& configName, bool bNotify = true);
- bool SaveVisual(const std::string& configName, bool bNotify = true);
- bool LoadVisual(const std::string& configName, bool bNotify = true);
- void RemoveConfig(const std::string& configName);
- void RemoveVisual(const std::string& configName);
+ bool SaveConfig(const std::string& sConfigName, bool bNotify = true);
+ bool LoadConfig(const std::string& sConfigName, bool bNotify = true);
+ bool SaveVisual(const std::string& sConfigName, bool bNotify = true);
+ bool LoadVisual(const std::string& sConfigName, bool bNotify = true);
+ void RemoveConfig(const std::string& sConfigName, bool bNotify = true);
+ void RemoveVisual(const std::string& sConfigName, bool bNotify = true);
+ void ResetConfig(const std::string& sConfigName, bool bNotify = true);
+ void ResetVisual(const std::string& sConfigName, bool bNotify = true);
boost::property_tree::ptree ColorToTree(const Color_t& color);
void TreeToColor(const boost::property_tree::ptree& tree, Color_t& out);
diff --git a/Amalgam/src/Features/CritHack/CritHack.cpp b/Amalgam/src/Features/CritHack/CritHack.cpp
index e2482671..3b53a3ff 100644
--- a/Amalgam/src/Features/CritHack/CritHack.cpp
+++ b/Amalgam/src/Features/CritHack/CritHack.cpp
@@ -288,7 +288,7 @@ void CCritHack::ResetWeapons(CTFPlayer* pLocal)
for (auto& [iSlot, _] : m_mStorage)
{
- if (m_mStorage.contains(iSlot) && !mWeapons.contains(iSlot))
+ if (!mWeapons.contains(iSlot))
m_mStorage.erase(iSlot);
}
}
diff --git a/Amalgam/src/Features/ImGui/Menu/Menu.cpp b/Amalgam/src/Features/ImGui/Menu/Menu.cpp
index 2a11ed95..de7a244a 100644
--- a/Amalgam/src/Features/ImGui/Menu/Menu.cpp
+++ b/Amalgam/src/Features/ImGui/Menu/Menu.cpp
@@ -362,9 +362,22 @@ void CMenu::MenuAimbot()
TableNextColumn();
if (Section("Resolver"))
{
- FToggle("Enabled", Vars::AntiHack::Resolver::Resolver, FToggle_Left);
- PushTransparent(!FGet(Vars::AntiHack::Resolver::Resolver));
- FToggle("Ignore in-air", Vars::AntiHack::Resolver::IgnoreAirborne, FToggle_Right);
+ FToggle("Enabled", Vars::AntiHack::Resolver::Enabled, FToggle_Left);
+ PushTransparent(!FGet(Vars::AntiHack::Resolver::Enabled));
+ FToggle("Auto resolve", Vars::AntiHack::Resolver::AutoResolve, FToggle_Right);
+ PushTransparent(Transparent || !FGet(Vars::AntiHack::Resolver::AutoResolve));
+ FToggle("Auto resolve cheaters only", Vars::AntiHack::Resolver::AutoResolveCheatersOnly, FToggle_Left);
+ FToggle("Auto resolve headshot only", Vars::AntiHack::Resolver::AutoResolveHeadshotOnly, FToggle_Right);
+ PushTransparent(Transparent || !FGet(Vars::AntiHack::Resolver::AutoResolveYawAmount));
+ FSlider("Auto resolve yaw", Vars::AntiHack::Resolver::AutoResolveYawAmount, -180.f, 180.f, 45.f, "%g", FSlider_Left | FSlider_Clamp | FSlider_Precision);
+ PopTransparent();
+ PushTransparent(Transparent || !FGet(Vars::AntiHack::Resolver::AutoResolvePitchAmount));
+ FSlider("Auto resolve pitch", Vars::AntiHack::Resolver::AutoResolvePitchAmount, -180.f, 180.f, 90.f, "%g", FSlider_Right | FSlider_Clamp);
+ PopTransparent();
+ PopTransparent();
+ FSlider("Cycle yaw", Vars::AntiHack::Resolver::CycleYaw, -180.f, 180.f, 45.f, "%g", FSlider_Left | FSlider_Clamp | FSlider_Precision);
+ FSlider("Cycle pitch", Vars::AntiHack::Resolver::CyclePitch, -180.f, 180.f, 90.f, "%g", FSlider_Right | FSlider_Clamp);
+ FToggle("Cycle minwalk", Vars::AntiHack::Resolver::CycleMinwalk);
PopTransparent();
} EndSection();
if (Section("Auto Peek"))
@@ -382,15 +395,15 @@ void CMenu::MenuAimbot()
{
PushTransparent(!FGet(Vars::CheaterDetection::Methods));
FDropdown("Detection methods", Vars::CheaterDetection::Methods, { "Invalid pitch", "Packet choking", "Aim flicking", "Duck Speed" }, {}, FDropdown_Multi);
- PushTransparent(!FGet(Vars::CheaterDetection::DetectionsRequired));
+ PushTransparent(Transparent || !FGet(Vars::CheaterDetection::DetectionsRequired));
FSlider("Detections required", Vars::CheaterDetection::DetectionsRequired, 0, 50, 1);
PopTransparent();
- PushTransparent(!(FGet(Vars::CheaterDetection::Methods) & Vars::CheaterDetection::MethodsEnum::PacketChoking));
+ PushTransparent(Transparent || !(FGet(Vars::CheaterDetection::Methods) & Vars::CheaterDetection::MethodsEnum::PacketChoking));
FSlider("Minimum choking", Vars::CheaterDetection::MinimumChoking, 4, 22, 1);
PopTransparent();
- PushTransparent(!(FGet(Vars::CheaterDetection::Methods) & Vars::CheaterDetection::MethodsEnum::AimFlicking));
+ PushTransparent(Transparent || !(FGet(Vars::CheaterDetection::Methods) & Vars::CheaterDetection::MethodsEnum::AimFlicking));
FSlider("Minimum flick angle", Vars::CheaterDetection::MinimumFlick, 10.f, 30.f, 1.f, "%.0f", FSlider_Left);
FSlider("Maximum noise", Vars::CheaterDetection::MaximumNoise, 1.f, 10.f, 1.f, "%.0f", FSlider_Right);
PopTransparent();
@@ -1170,7 +1183,7 @@ void CMenu::MenuLogs()
TableNextColumn();
if (Section("Logging"))
{
- FDropdown("Logs", Vars::Logging::Logs, { "Vote start", "Vote cast", "Class changes", "Damage", "Cheat detection", "Tags", "Aliases" }, {}, FDropdown_Multi);
+ FDropdown("Logs", Vars::Logging::Logs, { "Vote start", "Vote cast", "Class changes", "Damage", "Cheat detection", "Tags", "Aliases", "Resolver" }, {}, FDropdown_Multi);
FSlider("Notification time", Vars::Logging::Lifetime, 0.5f, 5.f, 0.5f, "%g");
} EndSection();
if (Section("Vote Start"))
@@ -1218,6 +1231,12 @@ void CMenu::MenuLogs()
FDropdown("Log to", Vars::Logging::Aliases::LogTo, { "Toasts", "Chat", "Party", "Console" }, { 1 << 0, 1 << 1, 1 << 2, 1 << 3 }, FDropdown_Multi);
PopTransparent();
} EndSection();
+ if (Section("Resolver"))
+ {
+ PushTransparent(!(FGet(Vars::Logging::Logs) & Vars::Logging::LogsEnum::Resolver));
+ FDropdown("Log to", Vars::Logging::Resolver::LogTo, { "Toasts", "Chat", "Party", "Console" }, { 1 << 0, 1 << 1, 1 << 2, 1 << 3 }, FDropdown_Multi);
+ PopTransparent();
+ } EndSection();
EndTable();
}
@@ -1276,44 +1295,66 @@ void CMenu::MenuSettings()
newName.clear();
}
+ std::vector> vConfigs = {};
+ bool bDefaultFound = false;
for (auto& entry : std::filesystem::directory_iterator(F::Configs.sConfigPath))
{
if (!entry.is_regular_file() || entry.path().extension() != F::Configs.sConfigExtension)
continue;
- std::string configName = entry.path().filename().string();
- configName.erase(configName.end() - F::Configs.sConfigExtension.size(), configName.end());
+ std::string sConfigName = entry.path().filename().string();
+ sConfigName.erase(sConfigName.end() - F::Configs.sConfigExtension.size(), sConfigName.end());
+ if (FNV1A::Hash32(sConfigName.c_str()) == FNV1A::Hash32Const("default"))
+ bDefaultFound = true;
- const auto current = GetCursorPos().y;
+ vConfigs.push_back({ entry, sConfigName });
+ }
+ if (!bDefaultFound)
+ F::Configs.SaveConfig("default");
+ std::sort(vConfigs.begin(), vConfigs.end(), [&](const auto& a, const auto& b) -> bool
+ {
+ // override for default config
+ if (FNV1A::Hash32(a.second.c_str()) == FNV1A::Hash32Const("default"))
+ return true;
+ if (FNV1A::Hash32(b.second.c_str()) == FNV1A::Hash32Const("default"))
+ return false;
- SetCursorPos({ H::Draw.Scale(14), current + H::Draw.Scale(11) });
- TextColored(configName == F::Configs.sCurrentConfig ? F::Render.Active.Value : F::Render.Inactive.Value, configName.c_str());
+ return a.second < b.second;
+ });
+
+ for (auto& [entry, sConfigName] : vConfigs)
+ {
+ bool bCurrentConfig = FNV1A::Hash32(sConfigName.c_str()) == FNV1A::Hash32(F::Configs.sCurrentConfig.c_str());
+ ImVec2 vOriginalPos = GetCursorPos();
+
+ SetCursorPos({ H::Draw.Scale(14), vOriginalPos.y + H::Draw.Scale(11) });
+ TextColored(bCurrentConfig ? F::Render.Active.Value : F::Render.Inactive.Value, sConfigName.c_str());
int iOffset = 0;
- SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, current + H::Draw.Scale(9) });
+ SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, vOriginalPos.y + H::Draw.Scale(9) });
if (IconButton(ICON_MD_DELETE))
- OpenPopup(std::format("Confirmation## DeleteConfig{}", configName).c_str());
+ OpenPopup(std::format("Confirmation## RemoveConfig{}", sConfigName).c_str());
- SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, current + H::Draw.Scale(9) });
+ SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, vOriginalPos.y + H::Draw.Scale(9) });
if (IconButton(ICON_MD_SAVE))
{
- if (configName != F::Configs.sCurrentConfig || F::Configs.sCurrentVisuals.length())
- OpenPopup(std::format("Confirmation## SaveConfig{}", configName).c_str());
+ if (!bCurrentConfig || F::Configs.sCurrentVisuals.length())
+ OpenPopup(std::format("Confirmation## SaveConfig{}", sConfigName).c_str());
else
- F::Configs.SaveConfig(configName);
+ F::Configs.SaveConfig(sConfigName);
}
- SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, current + H::Draw.Scale(9) });
+ SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, vOriginalPos.y + H::Draw.Scale(9) });
if (IconButton(ICON_MD_DOWNLOAD))
- F::Configs.LoadConfig(configName);
+ F::Configs.LoadConfig(sConfigName);
- if (BeginPopupModal(std::format("Confirmation## SaveConfig{}", configName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
+ if (BeginPopupModal(std::format("Confirmation## SaveConfig{}", sConfigName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
{
- FText(std::format("Do you really want to override '{}'?", configName).c_str());
+ FText(std::format("Do you really want to override '{}'?", sConfigName).c_str());
if (FButton("Yes, override", FButton_Left))
{
- F::Configs.SaveConfig(configName);
+ F::Configs.SaveConfig(sConfigName);
CloseCurrentPopup();
}
if (FButton("No", FButton_Right | FButton_SameLine))
@@ -1322,22 +1363,29 @@ void CMenu::MenuSettings()
EndPopup();
}
- if (BeginPopupModal(std::format("Confirmation## DeleteConfig{}", configName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
+ if (BeginPopupModal(std::format("Confirmation## RemoveConfig{}", sConfigName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
{
- FText(std::format("Do you really want to delete '{}'?", configName).c_str());
+ FText(std::format("Do you really want to remove '{}'?", sConfigName).c_str());
- if (FButton("Yes, delete", FButton_Left))
+ PushDisabled(FNV1A::Hash32(sConfigName.c_str()) == FNV1A::Hash32Const("default"));
+ if (FButton("Yes, delete", FButton_Fit))
{
- F::Configs.RemoveConfig(configName);
+ F::Configs.RemoveConfig(sConfigName);
CloseCurrentPopup();
}
- if (FButton("No", FButton_Right | FButton_SameLine))
+ PopDisabled();
+ if (FButton("Yes, reset", FButton_Fit | FButton_SameLine))
+ {
+ F::Configs.ResetConfig(sConfigName);
+ CloseCurrentPopup();
+ }
+ if (FButton("No", FButton_Fit | FButton_SameLine))
CloseCurrentPopup();
EndPopup();
}
- SetCursorPos({ H::Draw.Scale(6), current }); DebugDummy({ 0, H::Draw.Scale(28) });
+ SetCursorPos(vOriginalPos); DebugDummy({ 0, H::Draw.Scale(28) });
}
break;
}
@@ -1358,42 +1406,43 @@ void CMenu::MenuSettings()
if (!entry.is_regular_file() || entry.path().extension() != F::Configs.sConfigExtension)
continue;
- std::string configName = entry.path().filename().string();
- configName.erase(configName.end() - F::Configs.sConfigExtension.size(), configName.end());
+ std::string sConfigName = entry.path().filename().string();
+ sConfigName.erase(sConfigName.end() - F::Configs.sConfigExtension.size(), sConfigName.end());
+ bool bCurrentConfig = FNV1A::Hash32(sConfigName.c_str()) == FNV1A::Hash32(F::Configs.sCurrentVisuals.c_str());
ImVec2 vOriginalPos = GetCursorPos();
SetCursorPos({ H::Draw.Scale(14), vOriginalPos.y + H::Draw.Scale(11) });
- TextColored(configName == F::Configs.sCurrentVisuals ? F::Render.Active.Value : F::Render.Inactive.Value, configName.c_str());
+ TextColored(bCurrentConfig ? F::Render.Active.Value : F::Render.Inactive.Value, sConfigName.c_str());
int iOffset = 0;
SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, vOriginalPos.y + H::Draw.Scale(9) });
if (IconButton(ICON_MD_DELETE))
- OpenPopup(std::format("Confirmation## DeleteVisual{}", configName).c_str());
+ OpenPopup(std::format("Confirmation## DeleteVisual{}", sConfigName).c_str());
SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, vOriginalPos.y + H::Draw.Scale(9) });
if (IconButton(ICON_MD_SAVE))
{
- if (configName != F::Configs.sCurrentVisuals)
- OpenPopup(std::format("Confirmation## SaveVisual{}", configName).c_str());
+ if (!bCurrentConfig)
+ OpenPopup(std::format("Confirmation## SaveVisual{}", sConfigName).c_str());
else
- F::Configs.SaveVisual(configName);
+ F::Configs.SaveVisual(sConfigName);
}
SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, vOriginalPos.y + H::Draw.Scale(9) });
if (IconButton(ICON_MD_DOWNLOAD))
- F::Configs.LoadVisual(configName);
+ F::Configs.LoadVisual(sConfigName);
// Dialogs
{
// Save config dialog
- if (BeginPopupModal(std::format("Confirmation## SaveVisual{}", configName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
+ if (BeginPopupModal(std::format("Confirmation## SaveVisual{}", sConfigName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
{
- FText(std::format("Do you really want to override '{}'?", configName).c_str());
+ FText(std::format("Do you really want to override '{}'?", sConfigName).c_str());
if (FButton("Yes, override", FButton_Left))
{
- F::Configs.SaveVisual(configName);
+ F::Configs.SaveVisual(sConfigName);
CloseCurrentPopup();
}
if (FButton("No", FButton_Right | FButton_SameLine))
@@ -1403,13 +1452,13 @@ void CMenu::MenuSettings()
}
// Delete config dialog
- if (BeginPopupModal(std::format("Confirmation## DeleteVisual{}", configName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
+ if (BeginPopupModal(std::format("Confirmation## DeleteVisual{}", sConfigName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
{
- FText(std::format("Do you really want to delete '{}'?", configName).c_str());
+ FText(std::format("Do you really want to delete '{}'?", sConfigName).c_str());
if (FButton("Yes, delete", FButton_Left))
{
- F::Configs.RemoveVisual(configName);
+ F::Configs.RemoveVisual(sConfigName);
CloseCurrentPopup();
}
if (FButton("No", FButton_Right | FButton_SameLine))
@@ -1679,16 +1728,18 @@ void CMenu::MenuSettings()
FText(sInfo.c_str());
// buttons
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(22), vOriginalPos.y + H::Draw.Scale(5) });
+ int iOffset = -3;
+
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(5) });
bDelete = IconButton(ICON_MD_DELETE);
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(47), vOriginalPos.y + H::Draw.Scale(5) });
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(5) });
bEdit = IconButton(ICON_MD_EDIT);
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(72), vOriginalPos.y + H::Draw.Scale(5) });
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(5) });
bVisibility = IconButton(_tBind.Visible ? ICON_MD_VISIBILITY : ICON_MD_VISIBILITY_OFF);
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(97), vOriginalPos.y + H::Draw.Scale(5) });
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(5) });
bNot = IconButton(!_tBind.Not ? ICON_MD_CODE : ICON_MD_CODE_OFF);
SetCursorPos(vOriginalPos);
@@ -1769,7 +1820,7 @@ void CMenu::MenuSettings()
};
auto drawPlayer = [getTeamColor](const ListPlayer& player, int x, int y)
{
- bool bClicked = false, bAdd = false, bAlias = false, bPitch = false, bYaw = false;
+ bool bClicked = false, bAdd = false, bAlias = false, bPitch = false, bYaw = false, bMinwalk = false;
const Color_t teamColor = getTeamColor(player.m_iTeam, player.m_bAlive);
const ImColor imColor = ColorToVec(teamColor);
@@ -1813,29 +1864,36 @@ void CMenu::MenuSettings()
lOffset += FCalcTextSize(player.m_sName).x + H::Draw.Scale(8);
// buttons
+ int iOffset = 2;
+
if (!player.m_bFake)
{
- bool bResolver = Vars::AntiHack::Resolver::Resolver.Value && !player.m_bLocal;
-
// right
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(22), vOriginalPos.y + H::Draw.Scale(5) });
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 20), vOriginalPos.y + H::Draw.Scale(5) });
bAlias = IconButton(ICON_MD_EDIT);
- SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(42), vOriginalPos.y + H::Draw.Scale(5) });
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 20), vOriginalPos.y + H::Draw.Scale(5) });
bAdd = IconButton(ICON_MD_ADD);
+ }
- if (bResolver)
- {
- SetCursorPos({ vOriginalPos.x + flWidth - 62, vOriginalPos.y + 5 });
- bYaw = IconButton(ICON_MD_ARROW_FORWARD);
+ bool bResolver = Vars::AntiHack::Resolver::Enabled.Value && !player.m_bLocal;
+ if (bResolver)
+ {
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 20), vOriginalPos.y + 5 });
+ bMinwalk = IconButton(ICON_MD_DIRECTIONS_WALK);
- SetCursorPos({ vOriginalPos.x + flWidth - 82, vOriginalPos.y + 5 });
- bPitch = IconButton(ICON_MD_ARROW_UPWARD);
- }
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 20), vOriginalPos.y + 5 });
+ bYaw = IconButton(ICON_MD_ARROW_FORWARD);
+ SetCursorPos({ vOriginalPos.x + flWidth - H::Draw.Scale(iOffset += 20), vOriginalPos.y + 5 });
+ bPitch = IconButton(ICON_MD_ARROW_UPWARD);
+ }
+
+ if (!player.m_bFake)
+ {
// tag bar
SetCursorPos({ vOriginalPos.x + lOffset, vOriginalPos.y });
- if (BeginChild(std::format("TagBar{}", player.m_uFriendsID).c_str(), { flWidth - lOffset - H::Draw.Scale(bResolver ? 88 : 48), flHeight }, ImGuiWindowFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoBackground))
+ if (BeginChild(std::format("TagBar{}", player.m_uFriendsID).c_str(), { flWidth - lOffset - H::Draw.Scale(bResolver ? 108 : 48), flHeight }, ImGuiWindowFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoBackground))
{
PushFont(F::Render.FontSmall);
@@ -1885,10 +1943,12 @@ void CMenu::MenuSettings()
OpenPopup(std::format("Add{}", player.m_uFriendsID).c_str());
else if (bAlias)
OpenPopup(std::format("Alias{}", player.m_uFriendsID).c_str());
- else if (bPitch)
- OpenPopup(std::format("Pitch{}", player.m_uFriendsID).c_str());
else if (bYaw)
OpenPopup(std::format("Yaw{}", player.m_uFriendsID).c_str());
+ else if (bPitch)
+ OpenPopup(std::format("Pitch{}", player.m_uFriendsID).c_str());
+ else if (bMinwalk)
+ OpenPopup(std::format("Minwalk{}", player.m_uFriendsID).c_str());
// popups
if (BeginPopup(std::format("Clicked{}", player.m_uFriendsID).c_str()))
@@ -1973,27 +2033,79 @@ void CMenu::MenuSettings()
PopStyleVar();
EndPopup();
}
- else if (BeginPopup(std::format("Pitch{}", player.m_uFriendsID).c_str()))
+ else if (BeginPopup(std::format("Yaw{}", player.m_uFriendsID).c_str()))
{
PushStyleVar(ImGuiStyleVar_ItemSpacing, { H::Draw.Scale(8), H::Draw.Scale(8) });
- for (size_t i = 0; i < F::PlayerUtils.m_vListPitch.size(); i++)
+ static std::vector> vYaws = {
+ { "Auto", 0.f },
+ { "Forward", 0.f },
+ { "Left", 90.f },
+ { "Right", -90.f },
+ { "Backwards", 180.f }
+ };
+ for (auto& [sYaw, flValue] : vYaws)
{
- if (FSelectable(F::PlayerUtils.m_vListPitch[i]))
- F::Resolver.mResolverMode[player.m_uFriendsID].second = int(i);
+ if (FSelectable(sYaw.c_str()))
+ {
+ switch (FNV1A::Hash32(sYaw.c_str()))
+ {
+ case FNV1A::Hash32Const("Auto"):
+ F::Resolver.SetYaw(player.m_iUserID, 0.f, true);
+ break;
+ default:
+ F::Resolver.SetYaw(player.m_iUserID, flValue);
+ }
+ }
}
PopStyleVar();
EndPopup();
}
- else if (BeginPopup(std::format("Yaw{}", player.m_uFriendsID).c_str()))
+ else if (BeginPopup(std::format("Pitch{}", player.m_uFriendsID).c_str()))
{
PushStyleVar(ImGuiStyleVar_ItemSpacing, { H::Draw.Scale(8), H::Draw.Scale(8) });
- for (size_t i = 0; i < F::PlayerUtils.m_vListYaw.size(); i++)
+ static std::vector> vPitches = {
+ { "Auto", 0.f },
+ { "Up", -90.f },
+ { "Down", 90.f },
+ { "Zero", 0.f },
+ { "Inverse", 0.f }
+ };
+ for (auto& [sPitch, flValue] : vPitches)
{
- if (FSelectable(F::PlayerUtils.m_vListYaw[i]))
- F::Resolver.mResolverMode[player.m_uFriendsID].second = int(i);
+ if (FSelectable(sPitch.c_str()))
+ {
+ switch (FNV1A::Hash32(sPitch.c_str()))
+ {
+ case FNV1A::Hash32Const("Auto"):
+ F::Resolver.SetPitch(player.m_iUserID, 0.f, false, true);
+ break;
+ case FNV1A::Hash32Const("Inverse"):
+ F::Resolver.SetPitch(player.m_iUserID, 0.f, true);
+ break;
+ default:
+ F::Resolver.SetPitch(player.m_iUserID, flValue);
+ }
+ }
+ }
+
+ PopStyleVar();
+ EndPopup();
+ }
+ else if (BeginPopup(std::format("Minwalk{}", player.m_uFriendsID).c_str()))
+ {
+ PushStyleVar(ImGuiStyleVar_ItemSpacing, { H::Draw.Scale(8), H::Draw.Scale(8) });
+
+ static std::vector> vPitches = {
+ { "Minwalk on", true },
+ { "Minwalk off", false }
+ };
+ for (auto& [sPitch, bValue] : vPitches)
+ {
+ if (FSelectable(sPitch.c_str()))
+ F::Resolver.SetMinwalk(player.m_iUserID, bValue);
}
PopStyleVar();
@@ -2313,7 +2425,7 @@ void CMenu::MenuSettings()
int iOffset = 0;
if (!pair.m_bLocked)
{
- SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, vOriginalPos.y + H::Draw.Scale(9) });
+ SetCursorPos({ GetWindowWidth() - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(9) });
if (IconButton(ICON_MD_DELETE))
OpenPopup(std::format("Confirmation## DeleteMat{}", pair.m_sName).c_str());
if (BeginPopupModal(std::format("Confirmation## DeleteMat{}", pair.m_sName).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysUseWindowPadding))
@@ -2332,7 +2444,7 @@ void CMenu::MenuSettings()
}
}
- SetCursorPos({ GetWindowWidth() - H::Draw.Scale(++iOffset) * 25, vOriginalPos.y + H::Draw.Scale(9) });
+ SetCursorPos({ GetWindowWidth() - H::Draw.Scale(iOffset += 25), vOriginalPos.y + H::Draw.Scale(9) });
if (IconButton(ICON_MD_EDIT))
{
CurrentMaterial = pair.m_sName;
diff --git a/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.cpp b/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.cpp
index 889f50fb..66a728ac 100644
--- a/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.cpp
+++ b/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.cpp
@@ -4,6 +4,8 @@
#include
#include
+MAKE_SIGNATURE(CTFWeaponBaseGun_GetWeaponSpread, "client.dll", "48 89 5C 24 ? 57 48 83 EC ? 4C 63 91", 0x0);
+
void CNoSpreadHitscan::Reset()
{
m_bWaitingForPlayerPerf = false;
@@ -22,7 +24,7 @@ bool CNoSpreadHitscan::ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool
if (G::PrimaryWeaponType != EWeaponType::HITSCAN)
return false;
- if (pWeapon->GetWeaponSpread() <= 0.f)
+ if ((bCreateMove ? pWeapon->GetWeaponSpread() : S::CTFWeaponBaseGun_GetWeaponSpread.Call(pWeapon)) <= 0.f)
return false;
return bCreateMove ? G::Attacking == 1 : true;
@@ -77,19 +79,13 @@ void CNoSpreadHitscan::AskForPlayerPerf()
}
}
-bool CNoSpreadHitscan::ParsePlayerPerf(bf_read& msgData)
+bool CNoSpreadHitscan::ParsePlayerPerf(std::string sMsg)
{
if (!Vars::Aimbot::General::NoSpread.Value)
return false;
- char rawMsg[256]; msgData.ReadString(rawMsg, sizeof(rawMsg), true);
- msgData.Seek(0);
-
- std::string msg(rawMsg);
- msg.erase(msg.begin());
-
std::smatch matches = {};
- std::regex_match(msg, matches, std::regex(R"((\d+.\d+)\s\d+\s\d+\s\d+.\d+\s\d+.\d+\svel\s\d+.\d+)"));
+ std::regex_match(sMsg, matches, std::regex(R"((\d+.\d+)\s\d+\s\d+\s\d+.\d+\s\d+.\d+\svel\s\d+.\d+)"));
if (matches.size() == 2)
{
@@ -129,7 +125,7 @@ bool CNoSpreadHitscan::ParsePlayerPerf(bf_read& msgData)
return true;
}
- return std::regex_match(msg, std::regex(R"(\d+.\d+\s\d+\s\d+)"));
+ return std::regex_match(sMsg, std::regex(R"(\d+.\d+\s\d+\s\d+)"));
}
void CNoSpreadHitscan::Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd)
diff --git a/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.h b/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.h
index 3e53d52b..3607de31 100644
--- a/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.h
+++ b/Amalgam/src/Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.h
@@ -22,7 +22,7 @@ public:
bool ShouldRun(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, bool bCreateMove = false);
void AskForPlayerPerf();
- bool ParsePlayerPerf(bf_read& msgData);
+ bool ParsePlayerPerf(std::string sMsg);
void Run(CTFPlayer* pLocal, CTFWeaponBase* pWeapon, CUserCmd* pCmd);
void Draw(CTFPlayer* pLocal);
diff --git a/Amalgam/src/Features/Players/PlayerUtils.h b/Amalgam/src/Features/Players/PlayerUtils.h
index 12614399..20c515eb 100644
--- a/Amalgam/src/Features/Players/PlayerUtils.h
+++ b/Amalgam/src/Features/Players/PlayerUtils.h
@@ -99,9 +99,6 @@ public:
bool m_bSavePlayers = false;
bool m_bLoadTags = true;
bool m_bSaveTags = false;
-
- const std::vector m_vListPitch = { "None", "Up", "Down", "Zero", "Auto" };
- const std::vector m_vListYaw = { "None", "Forward", "Backward", "Left", "Right", "Invert", "Edge", "Auto" };
};
ADD_FEATURE(CPlayerlistUtils, PlayerUtils)
\ No newline at end of file
diff --git a/Amalgam/src/Features/Records/Records.cpp b/Amalgam/src/Features/Records/Records.cpp
index 625e0502..3b352647 100644
--- a/Amalgam/src/Features/Records/Records.cpp
+++ b/Amalgam/src/Features/Records/Records.cpp
@@ -187,13 +187,13 @@ void CRecords::UserMessage(bf_read& msgData)
}
// Cheat detection
-void CRecords::CheatDetection(std::string name, std::string action, std::string reason)
+void CRecords::CheatDetection(std::string sName, std::string sAction, std::string sReason)
{
if (!(Vars::Logging::Logs.Value & Vars::Logging::LogsEnum::CheatDetection))
return;
- std::string sOutput = std::format("{} {} for {}", (name), (action), (reason));
- std::string sChat = std::format("{}{}\x1 {} for {}{}", (yellow), (name), (action), (yellow), (reason));
+ std::string sOutput = std::format("{} {} for {}", (sName), (sAction), (sReason));
+ std::string sChat = std::format("{}{}\x1 {} for {}{}", (yellow), (sName), (sAction), (yellow), (sReason));
OutputInfo(Vars::Logging::CheatDetection::LogTo.Value, "Cheat Detection", sOutput, sChat);
}
@@ -286,4 +286,34 @@ void CRecords::AliasChanged(std::string sName, std::string sAction, std::string
std::string sOutput = std::format("{} {}'s alias {} \"{}\"", (sAction), (sName), (uHash == FNV1A::Hash32Const("Changed") ? "to" : "of"), (sAlias));
std::string sChat = std::format("{} {}{}\x1's alias {} \"{}{}\x1\"", (sAction), (yellow), (sName), (uHash == FNV1A::Hash32Const("Changed") ? "to" : "of"), (yellow), (sAlias));
OutputInfo(Vars::Logging::Tags::LogTo.Value, "Aliases", sOutput, sChat);
+}
+
+void CRecords::ReportResolver(int iIndex, std::string sAction, std::string sAxis, float flValue)
+{
+ ReportResolver(iIndex, sAction, sAxis, std::format("{}", flValue));
+}
+void CRecords::ReportResolver(int iIndex, std::string sAction, std::string sAxis, bool bValue)
+{
+ ReportResolver(iIndex, sAction, sAxis, std::format("{}", bValue));
+}
+void CRecords::ReportResolver(int iIndex, std::string sAction, std::string sAxis, std::string sValue)
+{
+ if (!(Vars::Logging::Logs.Value & Vars::Logging::LogsEnum::Resolver))
+ return;
+
+ PlayerInfo_t pi{};
+ if (!I::EngineClient->GetPlayerInfo(iIndex, &pi))
+ return;
+
+ auto sName = F::PlayerUtils.GetPlayerName(iIndex, pi.name);
+ std::string sOutput = std::format("{} {} of {} to {}", (sAction), (sAxis), (sName), (sValue));
+ std::string sChat = std::format("{} {}{}\x1 of {}{}\x1 to {}{}\x1", (sAction), (yellow), (sAxis), (yellow), (sName), (yellow), (sValue));
+ OutputInfo(Vars::Logging::Tags::LogTo.Value, "Resolver", sOutput, sChat);
+}
+void CRecords::ReportResolver(std::string sMessage)
+{
+ if (!(Vars::Logging::Logs.Value & Vars::Logging::LogsEnum::Resolver))
+ return;
+
+ OutputInfo(Vars::Logging::Tags::LogTo.Value, "Resolver", sMessage, sMessage);
}
\ No newline at end of file
diff --git a/Amalgam/src/Features/Records/Records.h b/Amalgam/src/Features/Records/Records.h
index 3fbf1407..2fedfaea 100644
--- a/Amalgam/src/Features/Records/Records.h
+++ b/Amalgam/src/Features/Records/Records.h
@@ -12,10 +12,15 @@ class CRecords
public:
void Event(IGameEvent* pEvent, uint32_t uHash, CTFPlayer* pLocal);
void UserMessage(bf_read& msgData);
- void CheatDetection(std::string name, std::string action, std::string reason);
+ void CheatDetection(std::string sName, std::string sAction, std::string sReason);
void TagsChanged(std::string sName, std::string sAction, std::string sColor, std::string sTag);
void AliasChanged(std::string sName, std::string sAction, std::string sAlias);
+
+ void ReportResolver(int iIndex, std::string sAction, std::string sAxis, float flValue);
+ void ReportResolver(int iIndex, std::string sAction, std::string sAxis, bool bValue);
+ void ReportResolver(int iIndex, std::string sAction, std::string sAxis, std::string sValue);
+ void ReportResolver(std::string sMessage);
};
ADD_FEATURE(CRecords, Records)
\ No newline at end of file
diff --git a/Amalgam/src/Features/Resolver/Resolver.cpp b/Amalgam/src/Features/Resolver/Resolver.cpp
index 6e60e16a..356103b6 100644
--- a/Amalgam/src/Features/Resolver/Resolver.cpp
+++ b/Amalgam/src/Features/Resolver/Resolver.cpp
@@ -1,316 +1,393 @@
#include "Resolver.h"
-#include "../PacketManip/AntiAim/AntiAim.h"
#include "../Backtrack/Backtrack.h"
+#include "../Players/PlayerUtils.h"
+#include "../TickHandler/TickHandler.h"
+#include "../Records/Records.h"
-static std::vector vYawRotations{ 0.0f, 180.0f, 90.0f, -90.0f};
-
-void PResolver::UpdateSniperDots()
+void CResolver::Reset()
{
- mSniperDots.clear();
+ m_mResolverData.clear();
+ m_mSniperDots.clear();
+
+ m_iWaitingForTarget = -1;
+ m_flWaitingForDamage = 0.f;
+ m_bWaitingForHeadshot = false;
+}
+
+void CResolver::StoreSniperDots(CTFPlayerResource* pResource)
+{
+ m_mSniperDots.clear();
for (auto& pEntity : H::Entities.GetGroup(EGroupType::MISC_DOTS))
{
if (auto pOwner = pEntity->m_hOwnerEntity().Get())
- mSniperDots[pOwner] = pEntity->m_vecOrigin();
+ {
+ int iUserID = pResource->GetUserID(pOwner->entindex());
+ m_mSniperDots[iUserID] = pEntity->m_vecOrigin();
+ }
}
}
-std::optional PResolver::GetPitchForSniperDot(CTFPlayer* pEntity)
+std::optional CResolver::GetPitchForSniperDot(CTFPlayer* pEntity, CTFPlayerResource* pResource)
{
- if (mSniperDots.contains(pEntity))
+ if (m_mSniperDots.contains(pEntity->entindex()))
{
- const Vec3 vOrigin = mSniperDots[pEntity];
- const Vec3 vEyeOrigin = pEntity->GetEyePosition();
+ int iUserID = pResource->GetUserID(pEntity->entindex());
+
+ const Vec3 vOrigin = m_mSniperDots[iUserID];
+ const Vec3 vEyeOrigin = pEntity->m_vecOrigin() + pEntity->GetViewOffset();
const Vec3 vDelta = vOrigin - vEyeOrigin;
- Vec3 vAngles;
- Math::VectorAngles(vDelta, vAngles);
+ Vec3 vAngles; Math::VectorAngles(vDelta, vAngles);
return vAngles.x;
}
+
return std::nullopt;
}
-std::optional PResolver::PredictBaseYaw(CTFPlayer* pLocal, CTFPlayer* pEntity)
+void CResolver::FrameStageNotify()
{
- if (I::GlobalVars->tickcount - mResolverData[pEntity].pLastFireAngles.first.first > 66 || !mResolverData[pEntity].pLastFireAngles.first.first)
- { // staleness & validity check
- if (!pLocal || !pLocal->IsAlive() || pLocal->IsAGhost())
- return std::nullopt;
- return Math::CalcAngle(pEntity->m_vecOrigin(), pLocal->m_vecOrigin()).y;
- }
-
- bool bFound = false;
- float flSmallestAngleTo = 0.f; float flSmallestFovTo = 360.f;
- for (auto pTarget : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
- {
- auto pPlayer = pTarget->As();
- if (pPlayer->IsDormant() || !pPlayer->IsAlive() || pPlayer->IsAGhost() || pPlayer->m_iTeamNum() == pEntity->m_iTeamNum())
- continue;
-
- const Vec3 vAngleTo = Math::CalcAngle(pEntity->m_vecOrigin(), pPlayer->m_vecOrigin());
- const float flFOVTo = Math::CalcFov(mResolverData[pEntity].pLastFireAngles.second, vAngleTo);
-
- if (flFOVTo < flSmallestFovTo)
- {
- bFound = true;
- flSmallestAngleTo = vAngleTo.y;
- flSmallestFovTo = flFOVTo;
- }
- }
-
- if (!bFound)
- return std::nullopt;
-
- return flSmallestAngleTo;
-}
-
-bool PResolver::ShouldRun(CTFPlayer* pLocal)
-{
- return Vars::AntiHack::Resolver::Resolver.Value && pLocal && pLocal->IsAlive() && !pLocal->IsAGhost() && G::PrimaryWeaponType == EWeaponType::HITSCAN;
-}
-
-bool PResolver::ShouldRunEntity(CTFPlayer* pEntity)
-{
- if (!pEntity->IsOnGround() && Vars::AntiHack::Resolver::IgnoreAirborne.Value)
- return false;
- if (!pEntity->IsAlive() || pEntity->IsAGhost() || pEntity->IsTaunting())
- return false;
-
- //if (pEntity->GetSimulationTime() == pEntity->GetOldSimulationTime())
- // return false; // last networked angles are the same as these, no need to change them
- return true;
-}
-
-bool PResolver::KeepOnShot(CTFPlayer* pEntity)
-{
- if (abs(I::GlobalVars->tickcount - mResolverData[pEntity].pLastFireAngles.first.first) < 2)
- return true;
- if (mResolverData[pEntity].pLastFireAngles.first.second)
- return true; // this person has not unchoked since shooting
- return false;
-}
-
-bool PResolver::IsOnShotPitchReliable(const float flPitch)
-{
- if (flPitch > 180)
- return flPitch > 273.f;
- else
- return flPitch < 87.f;
-}
-
-float PResolver::GetRealPitch(const float flPitch)
-{
- if (flPitch < 157.5f)
- return 89.f;
- else
- return -89.f;
-}
-
-void PResolver::SetAngles(const Vec3 vAngles, CTFPlayer* pEntity)
-{
- if (auto pAnimState = pEntity->GetAnimState())
- {
- pEntity->m_angEyeAnglesX() = vAngles.x;
- pAnimState->m_flCurrentFeetYaw = vAngles.y;
- pAnimState->m_flGoalFeetYaw = vAngles.y;
- pAnimState->Update(vAngles.y, vAngles.x);
- }
-}
-
-int PResolver::GetPitchMode(CTFPlayer* pEntity)
-{
- PlayerInfo_t pi{};
- if (!I::EngineClient->GetPlayerInfo(pEntity->entindex(), &pi))
- return 0;
- return mResolverMode[pi.friendsID].first;
-}
-
-int PResolver::GetYawMode(CTFPlayer* pEntity)
-{
- PlayerInfo_t pi{};
- if (!I::EngineClient->GetPlayerInfo(pEntity->entindex(), &pi))
- return 0;
- return mResolverMode[pi.friendsID].second;
-}
-
-void PResolver::OnDormancy(CTFPlayer* pEntity)
-{
- mResolverData[pEntity].pLastSniperPitch = {0, 0.f};
- mResolverData[pEntity].flPitchNoise = 0.f;
- mResolverData[pEntity].iPitchNoiseSteps = 0;
- mResolverData[pEntity].pLastFireAngles = {{0, false}, {}};
- mResolverData[pEntity].vOriginalAngles = {};
-}
-
-void PResolver::Aimbot(CTFPlayer* pEntity, const bool bHeadshot)
-{
- if (abs(I::GlobalVars->tickcount - pWaiting.first) < 66)
+ if (!Vars::AntiHack::Resolver::Enabled.Value || !I::EngineClient->IsInGame() || I::EngineClient->IsPlayingDemo())
return;
- auto pNetChan = I::EngineClient->GetNetChannelInfo();
- if (!pNetChan)
+ auto pResource = H::Entities.GetPR();
+ if (!pResource)
return;
- const int iDelay = 6 + TIME_TO_TICKS(G::Lerp + pNetChan->GetLatency(FLOW_INCOMING) + pNetChan->GetLatency(FLOW_OUTGOING));
- pWaiting = {I::GlobalVars->tickcount + iDelay, {pEntity, bHeadshot}};
-}
-
-void PResolver::FrameStageNotify(CTFPlayer* pLocal)
-{
- if (!ShouldRun(pLocal))
- return;
-
- UpdateSniperDots();
+ StoreSniperDots(pResource);
for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
{
auto pPlayer = pEntity->As();
- if (pPlayer->entindex() == I::EngineClient->GetLocalPlayer())
+ if (pPlayer->entindex() == I::EngineClient->GetLocalPlayer() || pPlayer->IsDormant() || !pPlayer->IsAlive() || pPlayer->IsAGhost())
continue;
- if (pPlayer->IsDormant())
- {
- OnDormancy(pPlayer);
- continue;
- }
+ int iUserID = pResource->GetUserID(pPlayer->entindex());
+ auto& tData = m_mResolverData[iUserID];
- mResolverData[pPlayer].vOriginalAngles = { pPlayer->m_angEyeAnglesX(), pPlayer->m_angEyeAnglesY() };
-
- if (abs(I::GlobalVars->tickcount - mResolverData[pPlayer].pLastFireAngles.first.first) >= 2)
- mResolverData[pPlayer].pLastFireAngles.first.second = !H::Entities.GetDeltaTime(pPlayer->entindex()) ? mResolverData[pPlayer].pLastFireAngles.first.second : false;
-
- if (!ShouldRunEntity(pPlayer))
- continue;
- if (KeepOnShot(pPlayer))
- {
- SetAngles(mResolverData[pPlayer].pLastFireAngles.second, pPlayer);
- continue;
- }
-
- Vec3 vAdjustedAngle = pPlayer->GetEyeAngles();
-
- if (std::optional flPitch = GetPitchForSniperDot(pPlayer))
- {
- vAdjustedAngle.x = flPitch.value();
-
- // get noise
- if (mResolverData[pPlayer].pLastSniperPitch.first)
- {
- const float flNoise = mResolverData[pPlayer].pLastSniperPitch.second - flPitch.value();
- mResolverData[pPlayer].flPitchNoise *= mResolverData[pPlayer].iPitchNoiseSteps;
- mResolverData[pPlayer].flPitchNoise += flNoise;
- mResolverData[pPlayer].iPitchNoiseSteps++;
- mResolverData[pPlayer].flPitchNoise /= mResolverData[pPlayer].iPitchNoiseSteps;
- }
-
- mResolverData[pPlayer].pLastSniperPitch = {I::GlobalVars->tickcount, flPitch.value()};
- }
- else if (I::GlobalVars->tickcount - mResolverData[pPlayer].pLastSniperPitch.first < 66 && mResolverData[pPlayer].flPitchNoise < 5.f)
- vAdjustedAngle.x = mResolverData[pPlayer].pLastSniperPitch.second;
+ if (tData.m_flYaw)
+ tData.m_bYaw = true;
else
+ tData.m_bYaw = false;
+
+ if (H::Entities.GetDeltaTime(pPlayer->entindex()) && fabsf(pPlayer->m_angEyeAnglesX()) == 90.f)
{
- switch (GetPitchMode(pPlayer))
- {
- case 0: break;
- case 1: vAdjustedAngle.x = -89.f; break; //up
- case 2: vAdjustedAngle.x = 89.f; break; //down
- case 3: vAdjustedAngle.x = 0.f; break; //zero
- case 4: //auto
- if (mResolverData[pPlayer].vOriginalAngles.x >= 90.f)
- vAdjustedAngle.x = -89.f;
- else if (mResolverData[pPlayer].vOriginalAngles.x <= -90.f)
- vAdjustedAngle.x = 89.f;
- break;
- }
+ if (auto flPitch = GetPitchForSniperDot(pPlayer, pResource))
+ tData.m_flPitch = flPitch.value();
+ else if (!tData.m_bFirstOOBPitch && tData.m_bAutoSetPitch || tData.m_bInversePitch)
+ tData.m_flPitch = -pPlayer->m_angEyeAnglesX(); // set to inverse by default
+ tData.m_bPitch = true, tData.m_bFirstOOBPitch = true;
}
-
- const int iYawMode = GetYawMode(pPlayer);
- if (iYawMode)
- {
- std::optional flTempYaw = PredictBaseYaw(pLocal, pPlayer);
- if (!flTempYaw) { flTempYaw = Math::CalcAngle(pPlayer->m_vecOrigin(), pLocal->m_vecOrigin()).y; }
-
- const float flBaseYaw = flTempYaw.value();
-
- switch (iYawMode)
- {
- case 0: break;
- case 1: vAdjustedAngle.y = flBaseYaw; break; //forward
- case 2: vAdjustedAngle.y = flBaseYaw + 180.f; break; //backwards
- case 3: vAdjustedAngle.y = flBaseYaw - 90.f; break; //side1
- case 4: vAdjustedAngle.y = flBaseYaw + 90.f; break; //side2
- case 5: vAdjustedAngle.y += 180.f; break; //invert
- case 6:{ //edge
- // TODO: Fix this. Resolver will always correct inversely to the player's pitch if we do not fix the logic here.
- const bool bEdge = vAdjustedAngle.x == 89 ? F::AntiAim.GetEdge(pPlayer, flBaseYaw, false) : !F::AntiAim.GetEdge(pPlayer, flBaseYaw, false);
- vAdjustedAngle.y = flBaseYaw + (bEdge ? 90.f : -90.f);
- break;
- }
- case 7:{ //auto
- vAdjustedAngle.y = vYawRotations[mResolverData[pPlayer].iYawIndex];
- break;
- }
- }
- }
-
- SetAngles(vAdjustedAngle, pPlayer);
+ else
+ tData.m_bPitch = false;
}
}
-void PResolver::CreateMove()
+void CResolver::CreateMove(CTFPlayer* pLocal)
{
- if (I::GlobalVars->tickcount > pWaiting.first && pWaiting.second.first)
- {
- mResolverData[pWaiting.second.first].iYawIndex++;
- if (mResolverData[pWaiting.second.first].iYawIndex > 3)
- mResolverData[pWaiting.second.first].iYawIndex = 0;
- pWaiting = {0, {nullptr, false}};
- F::Backtrack.ResolverUpdate(pWaiting.second.first);
- }
-}
-
-void PResolver::FXFireBullet(int iIndex, const Vec3 vAngles)
-{
- auto pEntity = I::ClientEntityList->GetClientEntity(iIndex);
- if (!pEntity)
+ if (!pLocal)
return;
- auto pPlayer = pEntity->As();
-
- Vec3 vAngAdjusted = vAngles;
- Vec3 vAngStore = vAngles;
-
- if (!IsOnShotPitchReliable(vAngles.x))
+ if (m_iWaitingForTarget != -1 && TICKS_TO_TIME(pLocal->m_nTickBase()) > m_flWaitingForDamage)
{
- float flAdjustedPitch = vAngles.x;
+ if (auto pTarget = I::ClientEntityList->GetClientEntity(I::EngineClient->GetPlayerForUserID(m_iWaitingForTarget))->As())
+ {
+ auto& tData = m_mResolverData[m_iWaitingForTarget];
- vAngStore.x += 360.f;
- vAngStore.x *= -1;
+ float& flYaw = tData.m_flYaw;
+ float& flPitch = tData.m_flPitch;
+ bool bAutoYaw = tData.m_bAutoSetYaw && Vars::AntiHack::Resolver::AutoResolveYawAmount.Value;
+ bool bAutoPitch = tData.m_bAutoSetPitch && Vars::AntiHack::Resolver::AutoResolvePitchAmount.Value;
- vAngAdjusted.x = GetRealPitch(flAdjustedPitch);
+ if (bAutoYaw)
+ {
+ flYaw += Vars::AntiHack::Resolver::AutoResolveYawAmount.Value;
+ flYaw = fmodf(flYaw + 180.f, 360.f);
+ flYaw += flYaw < 0 ? 180.f : -180.f;
- if (fabsf(flAdjustedPitch) > 89.f)
- vAngStore.y += 180; // account for likely yaw faking
- while (vAngStore.y > 360)
- vAngStore.y -= 360.f; // hacky fix for previous line
- vAngStore.x += 540; // (360+180)
- SDK::Output("Resolver", std::format("Recieved {:.1f} {:.1f}", vAngles.x, vAngles.y).c_str(), {0, 222, 255, 255});
- SDK::Output("Resolver", std::format("Adjusted {:.1f} {:.1f}", vAngAdjusted.x, vAngAdjusted.y).c_str(), {0, 222, 255, 255});
- SDK::Output("Resolver", std::format("Adjusted 2 {:.1f} {:.1f}", vAngStore.x, vAngStore.y).c_str(), {0, 222, 255, 255});
+ F::Backtrack.ResolverUpdate(pTarget);
+ F::Records.ReportResolver(I::EngineClient->GetPlayerForUserID(m_iWaitingForTarget), "Cycling", "yaw", flYaw);
+ }
+
+ if (bAutoPitch
+ && (!bAutoYaw || fabsf(flYaw) < fabsf(Vars::AntiHack::Resolver::AutoResolveYawAmount.Value / 2))
+ && fabsf(pTarget->m_angEyeAnglesX()) == 90.f && !m_mSniperDots.contains(m_iWaitingForTarget))
+ {
+ flPitch += tData.m_bAutoSetPitch && Vars::AntiHack::Resolver::AutoResolvePitchAmount.Value;
+ flPitch = fmodf(flPitch + 90.f, 180.f);
+ flPitch += flPitch < 0 ? 90.f : -90.f;
+
+ F::Backtrack.ResolverUpdate(pTarget);
+ F::Records.ReportResolver(I::EngineClient->GetPlayerForUserID(m_iWaitingForTarget), "Cycling", "pitch", flPitch);
+ }
+
+ m_iWaitingForTarget = -1;
+ m_flWaitingForDamage = 0.f;
+ m_bWaitingForHeadshot = false;
+ }
}
- mResolverData[pPlayer].pLastFireAngles = { { I::GlobalVars->tickcount, true }, vAngStore};
- SetAngles(vAngAdjusted, pPlayer);
-}
-
-void PResolver::OnPlayerHurt(IGameEvent* pEvent)
-{
- if (I::EngineClient->GetPlayerForUserID(pEvent->GetInt("attacker")) != I::EngineClient->GetLocalPlayer())
+ if (!Vars::AntiHack::Resolver::Enabled.Value)
return;
- if (I::ClientEntityList->GetClientEntity(I::EngineClient->GetPlayerForUserID(pEvent->GetInt("userid"))) == pWaiting.second.first)
- {
- if (pWaiting.second.second && G::CanHeadshot && !pEvent->GetBool("crit"))
- return;
- pWaiting = { 0, { nullptr, false } };
+ auto pResource = H::Entities.GetPR();
+ if (!pResource)
+ return;
+
+ auto getPlayerClosestToFOV = [&]()
+ {
+ CTFPlayer* pClosest = nullptr;
+ float flMinFOV = 180.f;
+
+ const Vec3 vLocalPos = F::Ticks.GetShootPos();
+ const Vec3 vLocalAngles = I::EngineClient->GetViewAngles();
+
+ for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
+ {
+ if (pEntity->entindex() == pLocal->entindex())
+ continue;
+
+ Vec3 vCurPos = pEntity->GetCenter();
+ Vec3 vCurAngleTo = Math::CalcAngle(vLocalPos, vCurPos);
+ float flCurFOVTo = Math::CalcFov(vLocalAngles, vCurAngleTo);
+
+ if (flCurFOVTo < flMinFOV)
+ {
+ pClosest = pEntity->As();
+ flMinFOV = flCurFOVTo;
+ }
+ }
+
+ return pClosest;
+ };
+
+ if (Vars::AntiHack::Resolver::CycleYaw.Value)
+ {
+ if (SDK::PlatFloatTime() > m_flLastYawCycle + 0.5f)
+ {
+ if (auto pTarget = getPlayerClosestToFOV())
+ {
+ int iUserID = pResource->GetUserID(pTarget->entindex());
+ auto& tData = m_mResolverData[iUserID];
+
+ float& flYaw = tData.m_flYaw;
+
+ flYaw += Vars::AntiHack::Resolver::CycleYaw.Value;
+ flYaw = fmodf(flYaw + 180.f, 360.f);
+ flYaw += flYaw < 0 ? 180.f : -180.f;
+
+ F::Backtrack.ResolverUpdate(pTarget);
+ F::Records.ReportResolver(pTarget->entindex(), "Cycling", "yaw", flYaw);
+ }
+
+ m_flLastYawCycle = SDK::PlatFloatTime();
+ }
}
+ else
+ m_flLastYawCycle = 0.f;
+
+ if (Vars::AntiHack::Resolver::CyclePitch.Value)
+ {
+ if (SDK::PlatFloatTime() > m_flLastPitchCycle + 0.5f)
+ {
+ if (auto pTarget = getPlayerClosestToFOV())
+ {
+ int iUserID = pResource->GetUserID(pTarget->entindex());
+ auto& tData = m_mResolverData[iUserID];
+
+ if (fabsf(pTarget->m_angEyeAnglesX()) != 90.f)
+ F::Records.ReportResolver("Target not using out of bounds pitch");
+
+ float& flPitch = tData.m_flPitch;
+
+ flPitch += Vars::AntiHack::Resolver::CyclePitch.Value;
+ flPitch = fmodf(flPitch + 90.f, 180.f);
+ flPitch += flPitch < 0 ? 90.f : -90.f;
+
+ F::Backtrack.ResolverUpdate(pTarget);
+ F::Records.ReportResolver(pTarget->entindex(), "Cycling", "pitch", flPitch);
+ }
+
+ m_flLastPitchCycle = SDK::PlatFloatTime();
+ }
+ }
+ else
+ m_flLastPitchCycle = 0.f;
+
+ if (Vars::AntiHack::Resolver::CycleMinwalk.Value)
+ {
+ if (SDK::PlatFloatTime() > m_flLastMinwalkCycle + 0.5f)
+ {
+ if (auto pTarget = getPlayerClosestToFOV())
+ {
+ int iUserID = pResource->GetUserID(pTarget->entindex());
+ auto& tData = m_mResolverData[iUserID];
+
+ bool& bMinwalk = tData.m_bMinwalk;
+ bMinwalk = !bMinwalk;
+
+ F::Backtrack.ResolverUpdate(pTarget);
+ F::Records.ReportResolver(pTarget->entindex(), "Cycling", "minwalk", bMinwalk);
+ }
+
+ m_flLastMinwalkCycle = SDK::PlatFloatTime();
+ }
+ }
+ else
+ m_flLastMinwalkCycle = 0.f;
+}
+
+void CResolver::HitscanRan(CTFPlayer* pLocal, CTFPlayer* pTarget, CTFWeaponBase* pWeapon, int iHitbox)
+{
+ if (!Vars::AntiHack::Resolver::Enabled.Value || !Vars::AntiHack::Resolver::AutoResolve.Value
+ || Vars::Aimbot::General::AimType.Value == Vars::Aimbot::General::AimTypeEnum::Smooth || pLocal->m_iTeamNum() == pTarget->m_iTeamNum())
+ return;
+
+ if (Vars::AntiHack::Resolver::AutoResolveCheatersOnly.Value && !F::PlayerUtils.HasTag(pTarget->entindex(), CHEATER_TAG))
+ return;
+
+ if (Vars::AntiHack::Resolver::AutoResolveHeadshotOnly.Value && (iHitbox != HITBOX_HEAD || !G::CanHeadshot))
+ return;
+
+ if (pWeapon->GetWeaponSpread())
+ {
+ // check for perfect bullet
+ const float flTimeSinceLastShot = (pLocal->m_nTickBase() * TICK_INTERVAL) - pWeapon->m_flLastFireTime();
+ if (flTimeSinceLastShot <= (pWeapon->GetBulletsPerShot() > 1 ? 0.25f : 1.25f))
+ return;
+ }
+
+ auto pResource = H::Entities.GetPR();
+ if (!pResource)
+ return;
+
+ m_iWaitingForTarget = pResource->GetUserID(pTarget->entindex());
+ m_flWaitingForDamage = I::GlobalVars->curtime + F::Backtrack.GetReal() + 0.1f;
+ if (iHitbox == HITBOX_HEAD && G::CanHeadshot)
+ {
+ // not dealing with ambassador's range check right now
+ switch (pWeapon->GetWeaponID())
+ {
+ case TF_WEAPON_SNIPERRIFLE:
+ case TF_WEAPON_SNIPERRIFLE_DECAP:
+ case TF_WEAPON_SNIPERRIFLE_CLASSIC:
+ m_bWaitingForHeadshot = true;
+ }
+ }
+}
+
+void CResolver::OnPlayerHurt(IGameEvent* pEvent)
+{
+ if (m_iWaitingForTarget == -1
+ || I::EngineClient->GetPlayerForUserID(pEvent->GetInt("attacker")) != I::EngineClient->GetLocalPlayer()
+ || pEvent->GetInt("userid") != m_iWaitingForTarget)
+ return;
+
+ if (m_bWaitingForHeadshot && !pEvent->GetBool("crit"))
+ return;
+
+ m_iWaitingForTarget = -1;
+ m_flWaitingForDamage = 0.f;
+ m_bWaitingForHeadshot = false;
+}
+
+void CResolver::SetYaw(int iUserID, float flValue, bool bAuto)
+{
+ auto& tData = m_mResolverData[iUserID];
+
+ if (bAuto)
+ {
+ tData.m_bAutoSetYaw = true;
+
+ F::Records.ReportResolver(I::EngineClient->GetPlayerForUserID(iUserID), "Set", "yaw", "auto");
+ }
+ else
+ {
+ tData.m_flYaw = flValue;
+ tData.m_bAutoSetYaw = false;
+
+ F::Records.ReportResolver(I::EngineClient->GetPlayerForUserID(iUserID), "Set", "yaw", flValue);
+ }
+
+ F::Backtrack.ResolverUpdate(I::ClientEntityList->GetClientEntity(I::EngineClient->GetPlayerForUserID(iUserID))->As());
+}
+
+void CResolver::SetPitch(int iUserID, float flValue, bool bInverse, bool bAuto)
+{
+ auto& tData = m_mResolverData[iUserID];
+
+ if (bAuto)
+ {
+ tData.m_bInversePitch = false;
+ tData.m_bAutoSetPitch = true;
+
+ F::Records.ReportResolver(I::EngineClient->GetPlayerForUserID(iUserID), "Set", "pitch", "auto");
+ }
+ else if (bInverse)
+ {
+ tData.m_bInversePitch = true;
+ tData.m_bAutoSetPitch = false;
+
+ F::Records.ReportResolver(I::EngineClient->GetPlayerForUserID(iUserID), "Set", "pitch", "inverse");
+ }
+ else
+ {
+ auto pPlayer = I::ClientEntityList->GetClientEntity(I::EngineClient->GetPlayerForUserID(iUserID))->As();
+ if (pPlayer && fabsf(pPlayer->m_angEyeAnglesX()) != 90.f)
+ F::Records.ReportResolver("Target not using out of bounds pitch");
+
+ tData.m_flPitch = flValue;
+ tData.m_bInversePitch = false;
+ tData.m_bAutoSetPitch = false;
+
+ F::Records.ReportResolver(I::EngineClient->GetPlayerForUserID(iUserID), "Set", "pitch", flValue);
+ }
+
+ F::Backtrack.ResolverUpdate(I::ClientEntityList->GetClientEntity(I::EngineClient->GetPlayerForUserID(iUserID))->As());
+}
+
+void CResolver::SetMinwalk(int iUserID, bool bValue)
+{
+ auto& tData = m_mResolverData[iUserID];
+
+ tData.m_bMinwalk = bValue;
+
+ F::Backtrack.ResolverUpdate(I::ClientEntityList->GetClientEntity(I::EngineClient->GetPlayerForUserID(iUserID))->As());
+ F::Records.ReportResolver(I::EngineClient->GetPlayerForUserID(iUserID), "Set", "minwalk", bValue);
+}
+
+bool CResolver::GetAngles(CTFPlayer* pPlayer, float* pYaw, float* pPitch, bool* pMinwalk, bool bFake)
+{
+ if (!Vars::AntiHack::Resolver::Enabled.Value)
+ return false;
+
+ if (pPlayer->entindex() == I::EngineClient->GetLocalPlayer() || pPlayer->IsDormant() || !pPlayer->IsAlive() || pPlayer->IsAGhost())
+ return false;
+
+ auto pResource = H::Entities.GetPR();
+ if (!pResource)
+ return false;
+
+ int iUserID = pResource->GetUserID(pPlayer->entindex());
+ auto& tData = m_mResolverData[iUserID];
+
+ bool bYaw = tData.m_bYaw, bPitch = tData.m_bPitch;
+
+ if (pYaw)
+ {
+ *pYaw = pPlayer->m_angEyeAnglesY();
+ if (bYaw && !bFake)
+ *pYaw += tData.m_flYaw;
+ }
+
+ if (pPitch)
+ {
+ *pPitch = pPlayer->m_angEyeAnglesX();
+ if (bPitch)
+ *pPitch = tData.m_flPitch;
+ }
+
+ if (pMinwalk)
+ *pMinwalk = tData.m_bMinwalk;
+
+ return bYaw || bPitch;
}
\ No newline at end of file
diff --git a/Amalgam/src/Features/Resolver/Resolver.h b/Amalgam/src/Features/Resolver/Resolver.h
index 06f8f694..5c27865b 100644
--- a/Amalgam/src/Features/Resolver/Resolver.h
+++ b/Amalgam/src/Features/Resolver/Resolver.h
@@ -3,51 +3,45 @@
struct ResolveData
{
- //config data
- bool bEnabled = false; // should we resolve this player
+ float m_flYaw = 0.f; // to be added
+ float m_flPitch = 0.f; // to be set, if pitch oob
- //bruteforce data
- int iYawIndex = 0;
+ bool m_bYaw = false;
+ bool m_bPitch = false;
+ bool m_bMinwalk = true;
- //logical data
- std::pair pLastSniperPitch = {0, 0.f};
- float flPitchNoise = 0.f; // noise around sniper dot pitch
- int iPitchNoiseSteps = 0;
-
- //historical data
- std::pair, Vec3> pLastFireAngles = { { 0, false }, {} };
- Vec2 vOriginalAngles = {0.f, 0.f};
+ bool m_bAutoSetYaw = true;
+ bool m_bAutoSetPitch = true;
+ bool m_bFirstOOBPitch = false;
+ bool m_bInversePitch = false;
};
-class PResolver
+class CResolver
{
- void UpdateSniperDots();
- std::optional GetPitchForSniperDot(CTFPlayer* pEntity);
-
- std::optional PredictBaseYaw(CTFPlayer* pLocal, CTFPlayer* pEntity);
-
- bool ShouldRun(CTFPlayer* pLocal);
- bool ShouldRunEntity(CTFPlayer* pEntity);
- bool KeepOnShot(CTFPlayer* pEntity);
- bool IsOnShotPitchReliable(const float flPitch);
- float GetRealPitch(const float flPitch);
- void SetAngles(const Vec3 vAngles, CTFPlayer* pEntity);
- int GetPitchMode(CTFPlayer* pEntity);
- int GetYawMode(CTFPlayer* pEntity);
- void OnDormancy(CTFPlayer* pEntity);
+ void StoreSniperDots(CTFPlayerResource* pResource);
+ std::optional GetPitchForSniperDot(CTFPlayer* pEntity, CTFPlayerResource* pResource);
- std::unordered_map mSniperDots;
- std::unordered_map mResolverData;
- std::pair> pWaiting = {0, {nullptr, false}};
+ std::unordered_map m_mResolverData;
+ std::unordered_map m_mSniperDots;
+
+ int m_iWaitingForTarget = -1;
+ float m_flWaitingForDamage = 0.f;
+ bool m_bWaitingForHeadshot = false;
+
+ float m_flLastYawCycle = 0.f;
+ float m_flLastPitchCycle = 0.f;
+ float m_flLastMinwalkCycle = 0.f;
public:
- void Aimbot(CTFPlayer* pEntity, const bool bHeadshot);
- void FrameStageNotify(CTFPlayer* pLocal);
- void CreateMove();
- void FXFireBullet(int iIndex, const Vec3 vAngles);
+ void FrameStageNotify();
+ void CreateMove(CTFPlayer* pLocal);
+ void HitscanRan(CTFPlayer* pLocal, CTFPlayer* pTarget, CTFWeaponBase* pWeapon, int iHitbox = HITBOX_MAX);
void OnPlayerHurt(IGameEvent* pEvent);
-
- std::unordered_map> mResolverMode;
+ void SetYaw(int iUserID, float flValue, bool bAuto = false);
+ void SetPitch(int iUserID, float flValue, bool bInverse = false, bool bAuto = false);
+ void SetMinwalk(int iUserID, bool bValue);
+ bool GetAngles(CTFPlayer* pPlayer, float* pYaw = nullptr, float* pPitch = nullptr, bool* pMinwalk = nullptr, bool bFake = false);
+ void Reset();
};
-ADD_FEATURE(PResolver, Resolver)
\ No newline at end of file
+ADD_FEATURE(CResolver, Resolver)
\ No newline at end of file
diff --git a/Amalgam/src/Hooks/CBaseAnimating_FrameAdvance.cpp b/Amalgam/src/Hooks/CBaseAnimating_FrameAdvance.cpp
index 96c1b6c1..9c578439 100644
--- a/Amalgam/src/Hooks/CBaseAnimating_FrameAdvance.cpp
+++ b/Amalgam/src/Hooks/CBaseAnimating_FrameAdvance.cpp
@@ -4,7 +4,7 @@
static std::unordered_map> pAnimatingInfo;
-MAKE_HOOK(CBaseAnimating_FrameAdvance, S::CBaseAnimating_FrameAdvance(), float, __fastcall,
+MAKE_HOOK(CBaseAnimating_FrameAdvance, S::CBaseAnimating_FrameAdvance(), float,
void* rcx, float flInterval)
{
if (!Vars::Visuals::Removals::Interpolation.Value || rcx == H::Entities.GetLocal())
diff --git a/Amalgam/src/Hooks/CBaseAnimating_Interpolate.cpp b/Amalgam/src/Hooks/CBaseAnimating_Interpolate.cpp
index 2749d2d3..4cb9c66f 100644
--- a/Amalgam/src/Hooks/CBaseAnimating_Interpolate.cpp
+++ b/Amalgam/src/Hooks/CBaseAnimating_Interpolate.cpp
@@ -1,6 +1,7 @@
#include "../SDK/SDK.h"
#include "../Features/TickHandler/TickHandler.h"
+#include "../Features/Resolver/Resolver.h"
MAKE_SIGNATURE(CBaseAnimating_Interpolate, "client.dll", "48 8B C4 48 89 70 ? F3 0F 11 48", 0x0);
@@ -10,5 +11,12 @@ MAKE_HOOK(CBaseAnimating_Interpolate, S::CBaseAnimating_Interpolate(), bool,
if (rcx == H::Entities.GetLocal() ? F::Ticks.m_bRecharge : Vars::Visuals::Removals::Interpolation.Value)
return true;
+ /*
+ // fixes weird stupid flickering with the resolver, but completely disables interpolation
+ if anyone knows of a better solution let me know. doesn't seem to cause nonvisual issues so i'm leaving this commented out for now
+ if (F::Resolver.GetAngles(reinterpret_cast(rcx)))
+ return true;
+ */
+
return CALL_ORIGINAL(rcx, currentTime);
}
\ No newline at end of file
diff --git a/Amalgam/src/Hooks/CBaseAnimating_UpdateClientSideAnimations.cpp b/Amalgam/src/Hooks/CBaseAnimating_UpdateClientSideAnimations.cpp
index a40aa506..1ea6cfbf 100644
--- a/Amalgam/src/Hooks/CBaseAnimating_UpdateClientSideAnimations.cpp
+++ b/Amalgam/src/Hooks/CBaseAnimating_UpdateClientSideAnimations.cpp
@@ -1,12 +1,16 @@
#include "../SDK/SDK.h"
+#include "../Features/Resolver/Resolver.h"
+
MAKE_SIGNATURE(CBaseAnimating_UpdateClientSideAnimation, "client.dll", "48 89 5C 24 ? 57 48 83 EC ? 48 8B D9 E8 ? ? ? ? 48 8B F8 48 85 C0 74 ? 48 8B 00 48 8B CF FF 90 ? ? ? ? 84 C0 75 ? 33 FF 48 3B DF", 0x0);
MAKE_HOOK(CBaseAnimating_UpdateClientSideAnimation, S::CBaseAnimating_UpdateClientSideAnimation(), void,
void* rcx)
{
auto pLocal = H::Entities.GetLocal();
- if (Vars::Visuals::Removals::Interpolation.Value && !G::UpdatingAnims || rcx == pLocal && !pLocal->InCond(TF_COND_HALLOWEEN_KART) && !I::EngineClient->IsPlayingDemo())
+ auto pPlayer = reinterpret_cast(rcx);
+ if ((Vars::Visuals::Removals::Interpolation.Value || F::Resolver.GetAngles(pPlayer)) && !G::UpdatingAnims
+ || pPlayer == pLocal && !pLocal->InCond(TF_COND_HALLOWEEN_KART) && !I::EngineClient->IsPlayingDemo())
return;
CALL_ORIGINAL(rcx);
diff --git a/Amalgam/src/Hooks/CBaseClient_Connect.cpp b/Amalgam/src/Hooks/CBaseClient_Connect.cpp
index 7410e627..8443aba0 100644
--- a/Amalgam/src/Hooks/CBaseClient_Connect.cpp
+++ b/Amalgam/src/Hooks/CBaseClient_Connect.cpp
@@ -4,7 +4,7 @@
MAKE_SIGNATURE(CBaseClient_Connect, "engine.dll", "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC ? 48 8B D9 49 8B E9 48 8D 0D", 0x0);
-MAKE_HOOK(CBaseClient_Connect, S::CBaseClient_Connect(), void, __fastcall,
+MAKE_HOOK(CBaseClient_Connect, S::CBaseClient_Connect(), void,
void* rcx, const char* szName, int nUserID, INetChannel* pNetChannel, bool bFakePlayer, int clientChallenge)
{
F::Materials.ReloadMaterials();
diff --git a/Amalgam/src/Hooks/CBaseClient_Disconnect.cpp b/Amalgam/src/Hooks/CBaseClient_Disconnect.cpp
index 40df2d12..a59058df 100644
--- a/Amalgam/src/Hooks/CBaseClient_Disconnect.cpp
+++ b/Amalgam/src/Hooks/CBaseClient_Disconnect.cpp
@@ -4,7 +4,7 @@
MAKE_SIGNATURE(CBaseClient_Disconnect, "engine.dll", "48 8B C4 48 89 50 ? 4C 89 40 ? 4C 89 48 ? 57 48 81 EC ? ? ? ? 83 B9 ? ? ? ? ? 48 8B F9 0F 84 ? ? ? ? 48 89 58", 0x0);
-MAKE_HOOK(CBaseClient_Disconnect, S::CBaseClient_Disconnect(), void, __fastcall,
+MAKE_HOOK(CBaseClient_Disconnect, S::CBaseClient_Disconnect(), void,
void* rcx, const char* fmt, ...)
{
F::Materials.UnloadMaterials();
diff --git a/Amalgam/src/Hooks/CBaseClient_SetUpdateRate.cpp b/Amalgam/src/Hooks/CBaseClient_SetUpdateRate.cpp
index 808bc653..43854666 100644
--- a/Amalgam/src/Hooks/CBaseClient_SetUpdateRate.cpp
+++ b/Amalgam/src/Hooks/CBaseClient_SetUpdateRate.cpp
@@ -2,7 +2,7 @@
MAKE_SIGNATURE(CBaseClient_SetUpdateRate, "engine.dll", "83 FA ? 7D ? BA ? ? ? ? EB ? B8", 0x0);
-MAKE_HOOK(CBaseClient_SetUpdateRate, S::CBaseClient_SetUpdateRate(), void, __fastcall,
+MAKE_HOOK(CBaseClient_SetUpdateRate, S::CBaseClient_SetUpdateRate(), void,
void* rcx, int updaterate, bool bForce)
{
return CALL_ORIGINAL(rcx, 67, bForce); // seems localhost only
diff --git a/Amalgam/src/Hooks/CBaseEntity_EstimateAbsVelocity.cpp b/Amalgam/src/Hooks/CBaseEntity_EstimateAbsVelocity.cpp
new file mode 100644
index 00000000..01d498c2
--- /dev/null
+++ b/Amalgam/src/Hooks/CBaseEntity_EstimateAbsVelocity.cpp
@@ -0,0 +1,24 @@
+#include "../SDK/SDK.h"
+
+#include "../Features/Resolver/Resolver.h"
+
+MAKE_HOOK(CBaseEntity_EstimateAbsVelocity, S::CBaseEntity_EstimateAbsVelocity(), void,
+ void* rcx, Vector& vel)
+{
+ auto pPlayer = reinterpret_cast(rcx);
+ if (pPlayer->IsPlayer() && pPlayer->entindex() != I::EngineClient->GetLocalPlayer())
+ {
+ vel = pPlayer->m_vecVelocity();
+
+ if (pPlayer->IsOnGround() && vel.Length2DSqr() < 2.f)
+ {
+ bool bMinwalk;
+ if (F::Resolver.GetAngles(pPlayer, nullptr, nullptr, &bMinwalk) && bMinwalk)
+ vel = { 1.f, 1.f, 0.f };
+ }
+
+ return;
+ }
+
+ CALL_ORIGINAL(rcx, vel);
+}
\ No newline at end of file
diff --git a/Amalgam/src/Hooks/CClientModeShared_CreateMove.cpp b/Amalgam/src/Hooks/CClientModeShared_CreateMove.cpp
index 95f98f84..06bbc258 100644
--- a/Amalgam/src/Hooks/CClientModeShared_CreateMove.cpp
+++ b/Amalgam/src/Hooks/CClientModeShared_CreateMove.cpp
@@ -143,7 +143,7 @@ MAKE_HOOK(CClientModeShared_CreateMove, U::Memory.GetVFunc(I::ClientModeShared,
G::Attacking = SDK::IsAttacking(pLocal, pWeapon, pCmd);
G::PrimaryWeaponType = SDK::GetWeaponType(pWeapon, &G::SecondaryWeaponType);
- G::CanHeadshot = pWeapon->CanHeadShot();
+ G::CanHeadshot = pWeapon->CanHeadShot() || pWeapon->AmbassadorCanHeadshot(TICKS_TO_TIME(pLocal->m_nTickBase()));
}
// Run Features
@@ -160,7 +160,7 @@ MAKE_HOOK(CClientModeShared_CreateMove, U::Memory.GetVFunc(I::ClientModeShared,
F::CritHack.Run(pLocal, pWeapon, pCmd);
F::NoSpread.Run(pLocal, pWeapon, pCmd);
F::Misc.RunPost(pLocal, pCmd, *pSendPacket);
- F::Resolver.CreateMove();
+ F::Resolver.CreateMove(pLocal);
F::Visuals.CreateMove(pLocal, pWeapon);
{
diff --git a/Amalgam/src/Hooks/CClientState_GetClientInterpAmount.cpp b/Amalgam/src/Hooks/CClientState_GetClientInterpAmount.cpp
index 3e9d5fc8..8f477cd4 100644
--- a/Amalgam/src/Hooks/CClientState_GetClientInterpAmount.cpp
+++ b/Amalgam/src/Hooks/CClientState_GetClientInterpAmount.cpp
@@ -6,5 +6,5 @@ MAKE_HOOK(CClientState_GetClientInterpAmount, S::CClientState_GetClientInterpAmo
CClientState* rcx)
{
G::Lerp = CALL_ORIGINAL(rcx);
- return 0.f; //Vars::Visuals::Removals::Interpolation.Value ? 0.f : G::Lerp
+ return 0.f;
}
\ No newline at end of file
diff --git a/Amalgam/src/Hooks/CInterpolatedVarArrayBase_Interpolate.cpp b/Amalgam/src/Hooks/CInterpolatedVarArrayBase_Interpolate.cpp
index b3ff6d23..e868d481 100644
--- a/Amalgam/src/Hooks/CInterpolatedVarArrayBase_Interpolate.cpp
+++ b/Amalgam/src/Hooks/CInterpolatedVarArrayBase_Interpolate.cpp
@@ -4,7 +4,7 @@
MAKE_SIGNATURE(CInterpolatedVarArrayBase_Interpolate, "client.dll", "48 8B C4 55 56 57 48 8D 68 ? 48 81 EC ? ? ? ? 0F 29 78", 0x0);
-MAKE_HOOK(CInterpolatedVarArrayBase_Interpolate, S::CInterpolatedVarArrayBase_Interpolate(), int, __fastcall,
+MAKE_HOOK(CInterpolatedVarArrayBase_Interpolate, S::CInterpolatedVarArrayBase_Interpolate(), int,
void* rcx, float currentTime, float interpolation_amount)
{
return Vars::Visuals::Removals::Interpolation.Value ? 1 : CALL_ORIGINAL(rcx, currentTime, interpolation_amount);
diff --git a/Amalgam/src/Hooks/CPhysicsObject_OutputDebugInfo.cpp b/Amalgam/src/Hooks/CPhysicsObject_OutputDebugInfo.cpp
index f52fd999..befa2f77 100644
--- a/Amalgam/src/Hooks/CPhysicsObject_OutputDebugInfo.cpp
+++ b/Amalgam/src/Hooks/CPhysicsObject_OutputDebugInfo.cpp
@@ -3,7 +3,7 @@
MAKE_SIGNATURE(CPhysicsObject_OutputDebugInfo, "vphysics.dll", "48 8B C4 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 68", 0x0);
// physics_debug_entity !picker
-MAKE_HOOK(CPhysicsObject_OutputDebugInfo, S::CPhysicsObject_OutputDebugInfo(), void, __fastcall,
+MAKE_HOOK(CPhysicsObject_OutputDebugInfo, S::CPhysicsObject_OutputDebugInfo(), void,
void* rcx)
{
//CALL_ORIGINAL(rcx);
diff --git a/Amalgam/src/Hooks/CSequenceTransitioner_CheckForSequenceChange.cpp b/Amalgam/src/Hooks/CSequenceTransitioner_CheckForSequenceChange.cpp
index 8def907e..f783958e 100644
--- a/Amalgam/src/Hooks/CSequenceTransitioner_CheckForSequenceChange.cpp
+++ b/Amalgam/src/Hooks/CSequenceTransitioner_CheckForSequenceChange.cpp
@@ -4,7 +4,7 @@
MAKE_SIGNATURE(CSequenceTransitioner_CheckForSequenceChange, "client.dll", "48 85 D2 0F 84 ? ? ? ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24", 0x0);
-MAKE_HOOK(CSequenceTransitioner_CheckForSequenceChange, S::CSequenceTransitioner_CheckForSequenceChange(), void, __fastcall,
+MAKE_HOOK(CSequenceTransitioner_CheckForSequenceChange, S::CSequenceTransitioner_CheckForSequenceChange(), void,
void* rcx, CStudioHdr* hdr, int nCurSequence, bool bForceNewSequence, bool bInterpolate)
{
CALL_ORIGINAL(rcx, hdr, nCurSequence, bForceNewSequence, Vars::Visuals::Removals::Interpolation.Value ? false : bInterpolate);
diff --git a/Amalgam/src/Hooks/CTFGameRules_ModifySentChat.cpp b/Amalgam/src/Hooks/CTFGameRules_ModifySentChat.cpp
index 2f65eb78..26e5e228 100644
--- a/Amalgam/src/Hooks/CTFGameRules_ModifySentChat.cpp
+++ b/Amalgam/src/Hooks/CTFGameRules_ModifySentChat.cpp
@@ -8,7 +8,7 @@ struct s_CTFGameRules
bool m_bPlayingMedieval;
};
-MAKE_HOOK(CTFGameRules_ModifySentChat, S::CTFGameRules_ModifySentChat(), void, __fastcall,
+MAKE_HOOK(CTFGameRules_ModifySentChat, S::CTFGameRules_ModifySentChat(), void,
void* rcx, char* pBuf, int iBufSize)
{
if (Vars::Misc::MedievalChat.Value > 0)
diff --git a/Amalgam/src/Hooks/CTFMatchSummary_OnTick.cpp b/Amalgam/src/Hooks/CTFMatchSummary_OnTick.cpp
index ff45292b..172d3946 100644
--- a/Amalgam/src/Hooks/CTFMatchSummary_OnTick.cpp
+++ b/Amalgam/src/Hooks/CTFMatchSummary_OnTick.cpp
@@ -5,7 +5,7 @@
MAKE_SIGNATURE(CTFMatchSummary_OnTick, "client.dll", "55 8B EC 83 EC ? 53 57 8B F9 E8 ? ? ? ? E8", 0x0);
// Credits: mfed
-MAKE_HOOK(CTFMatchSummary_OnTick, S::CTFMatchSummary_OnTick(), int, __fastcall,
+MAKE_HOOK(CTFMatchSummary_OnTick, S::CTFMatchSummary_OnTick(), int,
void* rcx)
{
if (!reinterpret_cast(rcx) + 750) { return CALL_ORIGINAL(rcx); } // m_iCurrentState == MS_STATE_INITIAL
diff --git a/Amalgam/src/Hooks/CTFPartyClient_BCanRequestToJoinPlayer.cpp b/Amalgam/src/Hooks/CTFPartyClient_BCanRequestToJoinPlayer.cpp
index 13f95af2..1fd82119 100644
--- a/Amalgam/src/Hooks/CTFPartyClient_BCanRequestToJoinPlayer.cpp
+++ b/Amalgam/src/Hooks/CTFPartyClient_BCanRequestToJoinPlayer.cpp
@@ -4,7 +4,7 @@
MAKE_SIGNATURE(CTFPartyClient_BCanRequestToJoinPlayer, "client.dll", "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 56 41 57 48 83 EC ? 48 8B E9 48 89 54 24 ? 48 8B 49", 0x0);
-MAKE_HOOK(CTFPartyClient_BCanRequestToJoinPlayer, S::CTFPartyClient_BCanRequestToJoinPlayer(), bool, __fastcall,
+MAKE_HOOK(CTFPartyClient_BCanRequestToJoinPlayer, S::CTFPartyClient_BCanRequestToJoinPlayer(), bool,
CTFPartyClient* rcx, int64 targetPlayer)
{
return true;
diff --git a/Amalgam/src/Hooks/CTFPlayer_BuildTransformations.cpp b/Amalgam/src/Hooks/CTFPlayer_BuildTransformations.cpp
new file mode 100644
index 00000000..0b58fec1
--- /dev/null
+++ b/Amalgam/src/Hooks/CTFPlayer_BuildTransformations.cpp
@@ -0,0 +1,15 @@
+#include "../SDK/SDK.h"
+
+MAKE_SIGNATURE(CTFPlayer_BuildTransformations, "client.dll", "48 8B C4 48 89 58 ? 48 89 68 ? 57 41 54", 0x0);
+
+MAKE_HOOK(CTFPlayer_BuildTransformations, S::CTFPlayer_BuildTransformations(), void,
+ void* rcx, CStudioHdr* hdr, Vector* pos, Quaternion q[], const matrix3x4& cameraTransform, int boneMask, void* boneComputed)
+{
+ auto pPlayer = reinterpret_cast(rcx);
+ auto iOriginal = pPlayer->m_fFlags();
+ pPlayer->m_fFlags() &= ~FL_DUCKING;
+
+ CALL_ORIGINAL(rcx, hdr, pos, q, cameraTransform, boneMask, boneComputed);
+
+ pPlayer->m_fFlags() = iOriginal;
+}
\ No newline at end of file
diff --git a/Amalgam/src/Hooks/CViewRender_LevelInit.cpp b/Amalgam/src/Hooks/CViewRender_LevelInit.cpp
index 5f93e58f..7812b3b8 100644
--- a/Amalgam/src/Hooks/CViewRender_LevelInit.cpp
+++ b/Amalgam/src/Hooks/CViewRender_LevelInit.cpp
@@ -5,6 +5,7 @@
#include "../Features/Backtrack/Backtrack.h"
#include "../Features/CheaterDetection/CheaterDetection.h"
#include "../Features/NoSpread/NoSpreadHitscan/NoSpreadHitscan.h"
+#include "../Features/Resolver/Resolver.h"
#include "../Features/TickHandler/TickHandler.h"
MAKE_HOOK(CViewRender_LevelInit, U::Memory.GetVFunc(I::ViewRender, 1), void,
@@ -13,7 +14,8 @@ MAKE_HOOK(CViewRender_LevelInit, U::Memory.GetVFunc(I::ViewRender, 1), void,
F::Materials.ReloadMaterials();
F::Visuals.OverrideWorldTextures();
- F::Backtrack.Restart();
+ F::Backtrack.Reset();
+ F::Resolver.Reset();
F::Ticks.Reset();
F::NoSpreadHitscan.Reset();
F::CheaterDetection.Reset();
diff --git a/Amalgam/src/Hooks/CViewRender_PerformScreenSpaceEffects.cpp b/Amalgam/src/Hooks/CViewRender_PerformScreenSpaceEffects.cpp
index a2a0ee47..f3c0cffe 100644
--- a/Amalgam/src/Hooks/CViewRender_PerformScreenSpaceEffects.cpp
+++ b/Amalgam/src/Hooks/CViewRender_PerformScreenSpaceEffects.cpp
@@ -4,7 +4,7 @@
MAKE_SIGNATURE(CViewRender_PerformScreenSpaceEffects, "client.dll", "55 8B EC 83 EC ? 8B 0D ? ? ? ? 53 56 57 33 F6 33 FF 89 75 ? 89 7D ? 8B 01 85 C0 74 ? 68 ? ? ? ? 68 ? ? ? ? 68 ? ? ? ? 68 ? ? ? ? 68 ? ? ? ? 57 57 57 57 8D 4D ? 51 50 8B 40 ? FF D0 8B 7D ? 83 C4 ? 8B 75 ? 8B 0D ? ? ? ? 8B 19 8B 0D", 0x0);
-MAKE_HOOK(CViewRender_PerformScreenSpaceEffects, S::CViewRender_PerformScreenSpaceEffects(), void, __fastcall,
+MAKE_HOOK(CViewRender_PerformScreenSpaceEffects, S::CViewRender_PerformScreenSpaceEffects(), void,
void* rcx, int x, int y, int w, int h)
{
// Do nothing.
diff --git a/Amalgam/src/Hooks/FX_FireBullets.cpp b/Amalgam/src/Hooks/FX_FireBullets.cpp
index ffd82c7f..cd0166be 100644
--- a/Amalgam/src/Hooks/FX_FireBullets.cpp
+++ b/Amalgam/src/Hooks/FX_FireBullets.cpp
@@ -14,10 +14,7 @@ MAKE_HOOK(FX_FireBullets, S::FX_FireBullets(), void,
const auto dwRetAddr = uintptr_t(_ReturnAddress());
if (iPlayer != I::EngineClient->GetLocalPlayer())
- {
F::Backtrack.ReportShot(iPlayer);
- F::Resolver.FXFireBullet(iPlayer, vecAngles);
- }
else if (Vars::Aimbot::General::NoSpread.Value && dwRetAddr == dwDesired)
iSeed = F::NoSpreadHitscan.m_iSeed;
diff --git a/Amalgam/src/Hooks/IBaseClientDLL_DispatchUserMessage.cpp b/Amalgam/src/Hooks/IBaseClientDLL_DispatchUserMessage.cpp
index a0678d51..493934a7 100644
--- a/Amalgam/src/Hooks/IBaseClientDLL_DispatchUserMessage.cpp
+++ b/Amalgam/src/Hooks/IBaseClientDLL_DispatchUserMessage.cpp
@@ -7,6 +7,8 @@
#include "../Features/Aimbot/AutoHeal/AutoHeal.h"
#include
#include
+//#include
+//#include
MAKE_HOOK(IBaseClientDLL_DispatchUserMessage, U::Memory.GetVFunc(I::BaseClientDLL, 36), bool,
void* rcx, UserMessageType type, bf_read& msgData)
@@ -33,20 +35,48 @@ MAKE_HOOK(IBaseClientDLL_DispatchUserMessage, U::Memory.GetVFunc(I::BaseClientDL
break;
}
case TextMsg:
- if (F::NoSpreadHitscan.ParsePlayerPerf(msgData))
- return true;
-
- if (Vars::Misc::Automation::AntiAutobalance.Value && bufData && msgData.GetNumBitsLeft() > 35)
+ {
+ char rawMsg[256]; msgData.ReadString(rawMsg, sizeof(rawMsg), true);
+ msgData.Seek(0);
+ std::string sMsg = rawMsg;
+ if (!sMsg.empty())
{
- std::string sMsg = bufData;
- if (!sMsg.empty())
+ sMsg.erase(sMsg.begin());
+
+ if (F::NoSpreadHitscan.ParsePlayerPerf(sMsg))
+ return true;
+
+ /*
+ if (sMsg.find("[BoxAngles] ") == 0)
{
- sMsg.erase(0, 1);
- if (FNV1A::Hash32(sMsg.c_str()) == FNV1A::Hash32Const("#TF_Autobalance_TeamChangePending"))
- I::EngineClient->ClientCmd_Unrestricted("retry");
+ try
+ {
+ sMsg.replace(0, strlen("[BoxAngles] "), "");
+ std::vector vValues = {};
+ boost::split(vValues, sMsg, boost::is_any_of(" "));
+ if (vValues.size() != 17)
+ return true;
+
+ Vec3 vOrigin = { std::stof(vValues[0]), std::stof(vValues[1]), std::stof(vValues[2]) };
+ Vec3 vMins = { std::stof(vValues[3]), std::stof(vValues[4]), std::stof(vValues[5]) };
+ Vec3 vMaxs = { std::stof(vValues[6]), std::stof(vValues[7]), std::stof(vValues[8]) };
+ Vec3 vAngles = { std::stof(vValues[9]), std::stof(vValues[10]), std::stof(vValues[11]) };
+ Color_t tColor = { byte(std::stoi(vValues[12])), byte(std::stoi(vValues[13])), byte(std::stoi(vValues[14])), byte(255 - std::stoi(vValues[15])) };
+ float flDuration = std::stof(vValues[16]);
+
+ G::BoxStorage.push_back({ vOrigin, vMins, vMaxs, vAngles, I::GlobalVars->curtime + flDuration, tColor, { 0, 0, 0, 0 } });
+ }
+ catch (...) {}
+
+ return true;
}
+ */
+
+ if (Vars::Misc::Automation::AntiAutobalance.Value && FNV1A::Hash32(sMsg.c_str()) == FNV1A::Hash32Const("#TF_Autobalance_TeamChangePending"))
+ I::EngineClient->ClientCmd_Unrestricted("retry");
}
break;
+ }
case VGUIMenu:
if (Vars::Visuals::Removals::MOTD.Value && bufData
&& FNV1A::Hash32(bufData) == FNV1A::Hash32Const("info"))
diff --git a/Amalgam/src/Hooks/IBaseClientDLL_FrameStageNotify.cpp b/Amalgam/src/Hooks/IBaseClientDLL_FrameStageNotify.cpp
index 31654bea..83e3057b 100644
--- a/Amalgam/src/Hooks/IBaseClientDLL_FrameStageNotify.cpp
+++ b/Amalgam/src/Hooks/IBaseClientDLL_FrameStageNotify.cpp
@@ -15,18 +15,6 @@
MAKE_HOOK(IBaseClientDLL_FrameStageNotify, U::Memory.GetVFunc(I::BaseClientDLL, 35), void,
void* rcx, ClientFrameStage_t curStage)
{
- switch (curStage)
- {
- case FRAME_RENDER_START:
- {
- if (auto pLocal = H::Entities.GetLocal())
- F::Resolver.FrameStageNotify(pLocal);
- // CRASH: Exception thrown at 0x00007FFCD004E223 (client.dll) in tf_win64.exe: 0xC0000005: Access violation reading location 0x0000025800000000.
- // CRASH: Exception thrown at 0x00007FFC5A09EED0 (client.dll) in tf_win64.exe: 0xC0000005: Access violation reading location 0x000001F636472562.
- // crashes likely not fsn related
- }
- }
-
CALL_ORIGINAL(rcx, curStage);
switch (curStage)
@@ -40,6 +28,7 @@ MAKE_HOOK(IBaseClientDLL_FrameStageNotify, U::Memory.GetVFunc(I::BaseClientDLL,
{
H::Entities.Store();
F::PlayerUtils.UpdatePlayers();
+ F::Resolver.FrameStageNotify();
for (int n = 1; n <= I::EngineClient->GetMaxClients(); n++)
{
@@ -57,26 +46,40 @@ MAKE_HOOK(IBaseClientDLL_FrameStageNotify, U::Memory.GetVFunc(I::BaseClientDLL,
G::VelocityMap[n].clear();
}
- if (Vars::Visuals::Removals::Interpolation.Value)
+ for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
{
- for (auto& pEntity : H::Entities.GetGroup(EGroupType::PLAYERS_ALL))
- {
- auto pPlayer = pEntity->As();
- if (pPlayer->entindex() == I::EngineClient->GetLocalPlayer() && !I::EngineClient->IsPlayingDemo() || pPlayer->IsDormant() || !pPlayer->IsAlive())
- continue; // local player managed in CPrediction_RunCommand
+ auto pPlayer = pEntity->As();
+ if (pPlayer->entindex() == I::EngineClient->GetLocalPlayer() && !I::EngineClient->IsPlayingDemo() || pPlayer->IsDormant() || !pPlayer->IsAlive())
+ continue; // local player managed in CreateMove
- if (auto iDeltaTicks = TIME_TO_TICKS(H::Entities.GetDeltaTime(pPlayer->entindex())))
+ bool bResolver = F::Resolver.GetAngles(pPlayer);
+ if (!(Vars::Visuals::Removals::Interpolation.Value || bResolver))
+ continue;
+
+ if (int iDeltaTicks = TIME_TO_TICKS(H::Entities.GetDeltaTime(pPlayer->entindex())))
+ {
+ float flOldFrameTime = I::GlobalVars->frametime;
+ I::GlobalVars->frametime = I::Prediction->m_bEnginePaused ? 0.f : TICK_INTERVAL;
+ for (int i = 0; i < iDeltaTicks; i++)
{
- float flOldFrameTime = I::GlobalVars->frametime;
- I::GlobalVars->frametime = I::Prediction->m_bEnginePaused ? 0.f : TICK_INTERVAL;
- for (int i = 0; i < iDeltaTicks; i++)
+ G::UpdatingAnims = true;
+
+ if (bResolver)
{
- G::UpdatingAnims = true;
+ float flYaw, flPitch;
+ F::Resolver.GetAngles(pPlayer, &flYaw, &flPitch, nullptr, i + 1 == iDeltaTicks);
+
+ float flOriginalYaw = pPlayer->m_angEyeAnglesY(), flOriginalPitch = pPlayer->m_angEyeAnglesX();
+ pPlayer->m_angEyeAnglesY() = flYaw, pPlayer->m_angEyeAnglesX() = flPitch;
pPlayer->UpdateClientSideAnimation();
- G::UpdatingAnims = false;
+ pPlayer->m_angEyeAnglesY() = flOriginalYaw, pPlayer->m_angEyeAnglesX() = flOriginalPitch;
}
- I::GlobalVars->frametime = flOldFrameTime;
+ else
+ pPlayer->UpdateClientSideAnimation();
+
+ G::UpdatingAnims = false;
}
+ I::GlobalVars->frametime = flOldFrameTime;
}
}
diff --git a/Amalgam/src/SDK/Definitions/Main/CBaseCombatWeapon.h b/Amalgam/src/SDK/Definitions/Main/CBaseCombatWeapon.h
index 1995e392..cbbf575f 100644
--- a/Amalgam/src/SDK/Definitions/Main/CBaseCombatWeapon.h
+++ b/Amalgam/src/SDK/Definitions/Main/CBaseCombatWeapon.h
@@ -24,7 +24,7 @@ public:
NETVAR_OFF(m_bInReload, bool, "CBaseCombatWeapon", "m_flNextPrimaryAttack", 12);
- VIRTUAL(GetName, const char*, const char*(*)(void*), this, 332);
+ VIRTUAL(GetName, const char*, void*, this, 332);
inline bool HasAmmo()
{
diff --git a/Amalgam/src/SDK/Definitions/Main/CBaseEntity.h b/Amalgam/src/SDK/Definitions/Main/CBaseEntity.h
index b3a1df2f..471d2e34 100644
--- a/Amalgam/src/SDK/Definitions/Main/CBaseEntity.h
+++ b/Amalgam/src/SDK/Definitions/Main/CBaseEntity.h
@@ -92,7 +92,7 @@ public:
NETVAR_OFF(m_flOldSimulationTime, float, "CBaseEntity", "m_flSimulationTime", 4);
NETVAR_OFF(m_Particles, CParticleProperty*, "CBaseEntity", "m_flElasticity", -56);
- VIRTUAL(UpdateVisibility, void, void(*)(CBaseEntity*), this, 91);
+ VIRTUAL(UpdateVisibility, void, CBaseEntity*, this, 91);
inline Vec3 GetCenter()
{
diff --git a/Amalgam/src/SDK/Definitions/Main/CBaseObject.h b/Amalgam/src/SDK/Definitions/Main/CBaseObject.h
index b37c0699..e38a9ef8 100644
--- a/Amalgam/src/SDK/Definitions/Main/CBaseObject.h
+++ b/Amalgam/src/SDK/Definitions/Main/CBaseObject.h
@@ -31,7 +31,7 @@ public:
NETVAR(m_bWasMapPlaced, bool, "CBaseObject", "m_bWasMapPlaced");
NETVAR(m_bPlasmaDisable, bool, "CBaseObject", "m_bPlasmaDisable");
- VIRTUAL(GetNumBuildPoints, int, int(*)(void*), IHasBuildPoints(), 0);
+ VIRTUAL(GetNumBuildPoints, int, void*, IHasBuildPoints(), 0);
inline void* IHasBuildPoints()
{
diff --git a/Amalgam/src/SDK/Definitions/Main/CBasePlayer.h b/Amalgam/src/SDK/Definitions/Main/CBasePlayer.h
index 193dfa06..98e6d57a 100644
--- a/Amalgam/src/SDK/Definitions/Main/CBasePlayer.h
+++ b/Amalgam/src/SDK/Definitions/Main/CBasePlayer.h
@@ -83,10 +83,10 @@ public:
CONDGET(IsInWater, m_fFlags(), FL_INWATER);
CONDGET(IsDucking, m_fFlags(), FL_DUCKING);
- VIRTUAL(PreThink, void, void(*)(void*), this, 261);
- VIRTUAL(Think, void, void(*)(void*), this, 121);
- VIRTUAL(PostThink, void, void(*)(void*), this, 262);
- VIRTUAL(GetRenderedWeaponModel, CBaseAnimating*, CBaseAnimating*(*)(void*), this, 251);
+ VIRTUAL(PreThink, void, void*, this, 261);
+ VIRTUAL(Think, void, void*, this, 121);
+ VIRTUAL(PostThink, void, void*, this, 262);
+ VIRTUAL(GetRenderedWeaponModel, CBaseAnimating*, void*, this, 251);
inline void SelectItem(const char* ptr, int subtype)
{
diff --git a/Amalgam/src/SDK/Definitions/Main/CEconEntity.h b/Amalgam/src/SDK/Definitions/Main/CEconEntity.h
index 6f3401d1..30835305 100644
--- a/Amalgam/src/SDK/Definitions/Main/CEconEntity.h
+++ b/Amalgam/src/SDK/Definitions/Main/CEconEntity.h
@@ -6,5 +6,5 @@ class CEconEntity : public CBaseAnimating
public:
NETVAR(m_iItemDefinitionIndex, int, "CEconEntity", "m_iItemDefinitionIndex");
- VIRTUAL(UpdateAttachmentModels, void, void(*)(void*), this, 212);
+ VIRTUAL(UpdateAttachmentModels, void, void*, this, 212);
};
\ No newline at end of file
diff --git a/Amalgam/src/SDK/Definitions/Main/CTFPlayer.h b/Amalgam/src/SDK/Definitions/Main/CTFPlayer.h
index 3a848cae..2569b149 100644
--- a/Amalgam/src/SDK/Definitions/Main/CTFPlayer.h
+++ b/Amalgam/src/SDK/Definitions/Main/CTFPlayer.h
@@ -198,7 +198,7 @@ public:
NETVAR_OFF(m_bStunNeedsFadeOut, bool, "CTFPlayer", "m_hItem", -188);
NETVAR_OFF(m_bTauntForceMoveForward, bool, "CTFPlayer", "m_bAllowMoveDuringTaunt", 1);
- VIRTUAL(GetMaxHealth, int, int(*)(void*), this, 107);
+ VIRTUAL(GetMaxHealth, int, void*, this, 107);
inline Vec3 GetEyeAngles()
{
diff --git a/Amalgam/src/SDK/Definitions/Main/CTFWeaponBase.h b/Amalgam/src/SDK/Definitions/Main/CTFWeaponBase.h
index 25e963c4..fa4fa913 100644
--- a/Amalgam/src/SDK/Definitions/Main/CTFWeaponBase.h
+++ b/Amalgam/src/SDK/Definitions/Main/CTFWeaponBase.h
@@ -8,7 +8,6 @@ MAKE_SIGNATURE(CTFWeaponBase_UpdateAllViewmodelAddons, "client.dll", "48 89 5C 2
MAKE_SIGNATURE(CTFWeaponBaseMelee_CalcIsAttackCriticalHelper, "client.dll", "40 57 48 83 EC ? 48 8B 05 ? ? ? ? 48 8B F9 83 78 ? ? 75", 0x0);
MAKE_SIGNATURE(CTFWeaponBase_CalcIsAttackCriticalHelper, "client.dll", "48 89 5C 24 ? 55 56 57 48 81 EC ? ? ? ? 0F 29 74 24", 0x0);
MAKE_SIGNATURE(CTFWeaponBase_GetAppropriateWorldOrViewModel, "client.dll", "48 89 5C 24 ? 57 48 83 EC ? 48 8B D9 E8 ? ? ? ? 48 8B C8 C7 44 24 ? ? ? ? ? 4C 8D 0D ? ? ? ? 33 D2 4C 8D 05 ? ? ? ? E8 ? ? ? ? 48 8B F8 48 85 C0 74 ? 48 8B CB", 0x0);
-MAKE_SIGNATURE(CTFWeaponBaseGun_GetWeaponSpread, "client.dll", "48 89 5C 24 ? 57 48 83 EC ? 4C 63 91", 0x0);
MAKE_SIGNATURE(CTFWeaponBase_IncrementAmmo, "client.dll", "48 89 5C 24 ? 56 48 83 EC ? 48 8B D9 E8 ? ? ? ? 48 8B C8", 0x0);
//credits: KGB (all weapon info stuff below)
@@ -202,11 +201,12 @@ public:
return reinterpret_cast(uintptr_t(this) + nOffset);
};
- VIRTUAL(GetSlot, int, int(*)(void*), this, 330);
- VIRTUAL(GetWeaponID, int, int(*)(void*), this, 381);
- VIRTUAL(GetDamageType, int, int(*)(void*), this, 382);
- VIRTUAL(IsEnergyWeapon, bool, bool(*)(void*), this, 432);
- VIRTUAL(AreRandomCritsEnabled, bool, bool(*)(void*), this, 402);
+ VIRTUAL(GetSlot, int, void*, this, 330);
+ VIRTUAL(GetWeaponID, int, void*, this, 381);
+ VIRTUAL(GetDamageType, int, void*, this, 382);
+ VIRTUAL(IsEnergyWeapon, bool, void*, this, 432);
+ VIRTUAL(AreRandomCritsEnabled, bool, void*, this, 402);
+ VIRTUAL(GetWeaponSpread, float, void*, this, 467);
OFFSET(m_iWeaponMode, int, 996);
@@ -335,12 +335,11 @@ public:
return GetDamageType() & DMG_USE_HITLOCATIONS && CanFireCriticalShot(true);
}
- inline bool AmbassadorCanHeadshot()
+ inline bool AmbassadorCanHeadshot(float flCurTime = I::GlobalVars->curtime)
{
- if (GetClassID() == ETFClassID::CTFRevolver && SDK::AttribHookValue(0, "set_weapon_mode", this) == 1
- && I::GlobalVars->curtime - m_flLastFireTime() <= 1.f)
- return false;
- return true;
+ if (GetClassID() == ETFClassID::CTFRevolver && SDK::AttribHookValue(0, "set_weapon_mode", this) == 1)
+ return flCurTime - m_flLastFireTime() > 1.f;
+ return false;
}
inline void GetProjectileFireSetup(void* pPlayer, Vector vecOffset, Vector* vecSrc, QAngle* angForward, bool bHitTeammates = true, float flEndDist = 2000.f)
@@ -385,11 +384,6 @@ public:
return S::CTFWeaponBase_GetAppropriateWorldOrViewModel.Call(this);
}
- inline float GetWeaponSpread()
- {
- return S::CTFWeaponBaseGun_GetWeaponSpread.Call(this);
- }
-
inline void IncrementAmmo()
{
return S::CTFWeaponBase_IncrementAmmo.Call(this);
diff --git a/Amalgam/src/SDK/Vars.h b/Amalgam/src/SDK/Vars.h
index 8ad35dca..83e3b1c5 100644
--- a/Amalgam/src/SDK/Vars.h
+++ b/Amalgam/src/SDK/Vars.h
@@ -288,9 +288,15 @@ namespace Vars
SUBNAMESPACE_END(AntiAim)
SUBNAMESPACE_BEGIN(Resolver)
- CVar(Resolver, false)
- CVar(AutoResolveCheaters, false)
- CVar(IgnoreAirborne, false)
+ CVar(Enabled, false)
+ CVar(AutoResolve, false)
+ CVar(AutoResolveCheatersOnly, false)
+ CVar(AutoResolveHeadshotOnly, false)
+ CVar(AutoResolveYawAmount, 90.f)
+ CVar(AutoResolvePitchAmount, 90.f)
+ CVar(CycleYaw, 0.f)
+ CVar(CyclePitch, 0.f)
+ CVar(CycleMinwalk, false)
SUBNAMESPACE_END(Resolver)
NAMESPACE_END(AntiHack)
@@ -821,7 +827,7 @@ namespace Vars
NAMESPACE_END(Colors)
NAMESPACE_BEGIN(Logging)
- CVarEnum(Logs, 0b0000011, NONE, VoteStart = 1 << 0, VoteCast = 1 << 1, ClassChanges = 1 << 2, Damage = 1 << 3, CheatDetection = 1 << 4, Tags = 1 << 5, Aliases = 1 << 6)
+ CVarEnum(Logs, 0b0000011, NONE, VoteStart = 1 << 0, VoteCast = 1 << 1, ClassChanges = 1 << 2, Damage = 1 << 3, CheatDetection = 1 << 4, Tags = 1 << 5, Aliases = 1 << 6, Resolver = 1 << 7)
Enum(LogTo, Toasts = 1 << 0, Chat = 1 << 1, Party = 1 << 2, Console = 1 << 3)
CVar(Lifetime, 5.f, VISUAL)
@@ -852,6 +858,10 @@ namespace Vars
SUBNAMESPACE_BEGIN(Aliases)
CVar(LogTo, 0b0001)
SUBNAMESPACE_END(Aliases)
+
+ SUBNAMESPACE_BEGIN(Resolver)
+ CVar(LogTo, 0b0001)
+ SUBNAMESPACE_END(Resolver)
NAMESPACE_END(Logging)
NAMESPACE_BEGIN(Debug)
diff --git a/Amalgam/src/Utils/NetVars/NetVars.h b/Amalgam/src/Utils/NetVars/NetVars.h
index 0a0f28df..9a241c5a 100644
--- a/Amalgam/src/Utils/NetVars/NetVars.h
+++ b/Amalgam/src/Utils/NetVars/NetVars.h
@@ -31,7 +31,7 @@ ADD_FEATURE_CUSTOM(CNetVars, NetVars, U);
#define VIRTUAL(name, type, fn, base, index) inline type name() \
{ \
- return reinterpret_cast(U::Memory.GetVFunc(base, index))(base); \
+ return reinterpret_cast(U::Memory.GetVFunc(base, index))(base); \
}
#define CONDGET(name, conditions, cond) inline bool name() \