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() \