From c39a988f073530b371e70a0efef69d66f8e6d863 Mon Sep 17 00:00:00 2001 From: LightCat Date: Sat, 21 Jul 2018 17:12:34 +0200 Subject: [PATCH 1/2] Updates (#531) * Improvements and fixes * Fix backtrack issues * Backtrack fix V2 * FB: Autojump, AFK and canReachVector improvements * Fix undef. behaviour/crash when sending msg to chat * Autounzoom fix Fixed autounzoom having a fixed unzoom time instead of a dynamic time. --- include/helpers.hpp | 1 - src/hacks/Aimbot.cpp | 9 +++--- src/hacks/Backtrack.cpp | 5 +-- src/hacks/FollowBot.cpp | 27 +++++++++------- src/helpers.cpp | 68 +++++++++++------------------------------ 5 files changed, 38 insertions(+), 72 deletions(-) diff --git a/include/helpers.hpp b/include/helpers.hpp index 3adc393d..68d474f9 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -82,7 +82,6 @@ Vector VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, float vectorMax(Vector i); Vector vectorAbs(Vector i); bool canReachVector(Vector loc, Vector dest = { 0, 0, 0 }); -bool isJumping(Vector vec); bool LineIntersectsBox(Vector &bmin, Vector &bmax, Vector &lmin, Vector &lmax); diff --git a/src/hacks/Aimbot.cpp b/src/hacks/Aimbot.cpp index 11222a44..3927addc 100644 --- a/src/hacks/Aimbot.cpp +++ b/src/hacks/Aimbot.cpp @@ -173,6 +173,8 @@ float cur_proj_grav{ 0.0f }; // If slow aimbot allows autoshoot bool slow_can_shoot = false; bool projectileAimbotRequired; +// Keep track of our zoom time +Timer zoomTime{}; // This array will store calculated projectile/hitscan predictions // for current frame, to avoid performing them again @@ -253,13 +255,9 @@ void CreateMove() // Auto-Unzoom if (auto_unzoom) { - if (g_pLocalPlayer->holding_sniper_rifle) + if (g_pLocalPlayer->holding_sniper_rifle && g_pLocalPlayer->bZoomed && zoomTime.check(3000)) { - if (g_pLocalPlayer->bZoomed) - { - if (g_GlobalVars->curtime - g_pLocalPlayer->flZoomBegin > 5.0f) g_pUserCmd->buttons |= IN_ATTACK2; - } } } // We do this as we need to pass whether the aimkey allows aiming to both @@ -277,6 +275,7 @@ void CreateMove() { if (g_pLocalPlayer->holding_sniper_rifle) { + zoomTime.update(); if (not g_pLocalPlayer->bZoomed) { g_pUserCmd->buttons |= IN_ATTACK2; diff --git a/src/hacks/Backtrack.cpp b/src/hacks/Backtrack.cpp index a9c44646..3c76bc03 100644 --- a/src/hacks/Backtrack.cpp +++ b/src/hacks/Backtrack.cpp @@ -9,10 +9,6 @@ #include "hacks/Backtrack.hpp" #include #include -bool IsMelee() -{ - return GetWeaponMode() == weapon_melee; -} namespace hacks::shared::backtrack { CatVar enable(CV_SWITCH, "backtrack", "0", "Enable backtrack", @@ -108,6 +104,7 @@ void Run() float bestFov = 99999; BestTick = 0; iBestTarget = -1; + bool IsMelee = GetWeaponMode() == weapon_melee; float prev_distance = 9999; diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index c2041a1c..ea0b2915 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -64,9 +64,10 @@ static const int crumb_limit = 64; // limit // Followed entity, externed for highlight color int follow_target = 0; -bool inited; +static bool inited; Timer lastTaunt{}; // time since taunt was last executed, used to avoid kicks +Timer lastJump{}; std::array afkTicks; // for how many ms the player hasn't been moving void checkAFK() @@ -76,7 +77,7 @@ void checkAFK() auto entity = ENTITY(i); if (CE_BAD(entity)) continue; - if (!CE_VECTOR(entity, netvar.vVelocity).IsZero(5.0f)) + if (!CE_VECTOR(entity, netvar.vVelocity).IsZero(60.0f)) { afkTicks[i].update(); } @@ -321,12 +322,6 @@ void WorldTick() } } - // if(!checkPath()) //wip do not merge if you see this - // { - // follow_target = 0; - // return; - // } - // Update timer on new target static Timer idle_time{}; if (breadcrumbs.empty()) @@ -346,7 +341,7 @@ void WorldTick() // New crumbs, we add one if its empty so we have something to follow if ((breadcrumbs.empty() || tar_orig.DistTo(breadcrumbs.at(breadcrumbs.size() - 1)) > 40.0F) && - DistanceToGround(ENTITY(follow_target)) < 30) + DistanceToGround(ENTITY(follow_target)) < 45) breadcrumbs.push_back(tar_orig); // Prune old and close crumbs that we wont need anymore, update idle timer @@ -372,14 +367,24 @@ void WorldTick() if (dist_to_target > (float) follow_distance) { // Check for jump - if (autojump && (idle_time.check(2000) || isJumping(breadcrumbs[0]))) + if (autojump && lastJump.check(1000) && (idle_time.check(2000) || DistanceToGround({breadcrumbs[0].x,breadcrumbs[0].y,breadcrumbs[0].z + 5}) > 47)) + { g_pUserCmd->buttons |= IN_JUMP; - // Check for idle + lastJump.update(); + } + // Check if still moving. 70 HU = Sniper Zoomed Speed + if (idle_time.check(3000) && CE_VECTOR(g_pLocalPlayer->entity, netvar.vVelocity).IsZero(60.0f)) + { + follow_target = 0; + return; + } + // Basic idle check if (idle_time.test_and_set(5000)) { follow_target = 0; return; } + static float last_slot_check = 0.0f; if (g_GlobalVars->curtime < last_slot_check) last_slot_check = 0.0f; diff --git a/src/helpers.cpp b/src/helpers.cpp index 005c9a90..159da748 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -192,17 +192,11 @@ bool canReachVector(Vector loc, Vector dest) int maxiterations = floor(dest.DistTo(loc)) / 40; for (int i = 0; i < maxiterations; i++) { + // math to get the next vector 40.0f in the direction of dest Vector vec = loc + dist / vectorMax(vectorAbs(dist)) * 40.0f * (i + 1); - trace_t trace; - Ray_t ray; - Vector down = vec; - down.z = down.z - 50; - ray.Init(vec, down); - g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, - &trace); - if (!(trace.startpos.DistTo(trace.endpos) <= 45)) + if (DistanceToGround({vec.x,vec.y,vec.z + 5}) >= 40) return false; for (int j = 0; j < 4; j++) @@ -224,13 +218,13 @@ bool canReachVector(Vector loc, Vector dest) directionalLoc.y = directionalLoc.y - 40; break; } - trace_t trace2; - Ray_t ray2; - ray2.Init(vec, directionalLoc); - g_ITrace->TraceRay(ray2, 0x4200400B, &trace::filter_no_player, - &trace2); + trace_t trace; + Ray_t ray; + ray.Init(vec, directionalLoc); + g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, + &trace); // distance of trace < than 26 - if (trace2.startpos.DistTo(trace2.endpos) < 26.0f) + if (trace.startpos.DistTo(trace.endpos) < 26.0f) return false; } } @@ -238,17 +232,11 @@ bool canReachVector(Vector loc, Vector dest) else { // check if the vector is too high above ground - trace_t trace; - Ray_t ray; - Vector down = loc; - down.z = down.z - 50; - ray.Init(loc, down); - g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, &trace); - // higher to avoid small false positives, player can jump 42 hu - // according to + // higher to avoid small false positives, player can jump 42 hu according to // the tf2 wiki - if (!(trace.startpos.DistTo(trace.endpos) <= 45)) + if (DistanceToGround({loc.x,loc.y,loc.z + 5}) >= 40) return false; + // check if there is enough space arround the vector for a player to fit // for loop for all 4 directions for (int i = 0; i < 4; i++) @@ -270,39 +258,18 @@ bool canReachVector(Vector loc, Vector dest) directionalLoc.y = directionalLoc.y - 40; break; } - trace_t trace2; - Ray_t ray2; - ray2.Init(loc, directionalLoc); - g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, - &trace2); + trace_t trace; + Ray_t ray; + ray.Init(loc, directionalLoc); + g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, &trace); // distance of trace < than 26 - if (trace2.startpos.DistTo(trace2.endpos) < 26.0f) + if (trace.startpos.DistTo(trace.endpos) < 26.0f) return false; } } return true; } -// returns if the player is currently jumping/falling. -bool isJumping(Vector vec) -{ - // check if the vector is too high above ground - trace_t trace; - Ray_t ray; - Vector down = vec; - Vector loc = vec; - down.z = down.z - 50; - loc.z = loc.z + 5; - ray.Init(vec, down); - // trace::filter_no_player.SetSelf(RAW_ENT(g_pLocalPlayer->entity)); - g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, &trace); - // lower to avoid small false negatives, player can jump 42 hu according to - // the tf2 wiki, higher because loc.z = loc.z + 5; - if (trace.startpos.DistTo(trace.endpos) > 45) - return true; - return false; -} - std::string GetLevelName() { @@ -1245,8 +1212,7 @@ void PrintChat(const char *fmt, ...) va_end(list); std::unique_ptr str(strfmt("\x07%06X[\x07%06XCAT\x07%06X]\x01 %s", 0x5e3252, 0xba3d9a, 0x5e3252, - buf.get()) - .get()); + buf.get()).release()); // FIXME DEBUG LOG logging::Info("%s", str.get()); chat->Printf(str.get()); From 2ff82514320887a509f39fbfdff29113b8dee0b1 Mon Sep 17 00:00:00 2001 From: LightCat Date: Sat, 28 Jul 2018 17:03:13 +0200 Subject: [PATCH 2/2] Lag big update before new GUI (#534) * Improvements and fixes * Fix backtrack issues * Backtrack fix V2 * FB: Autojump, AFK and canReachVector improvements * Fix undef. behaviour/crash when sending msg to chat * Autounzoom fix Fixed autounzoom having a fixed unzoom time instead of a dynamic time. * Abuse circleci tf * WIP * MOre wallcheck stuff * press a to be gay today * M0r3 W411CH3CK 57uff * More big changes, unused Predict seed code that's to be used on the local player's C_TEFireBullets Temp Entity and more * Update config.yml --- attach-libnamed.sh | 6 - include/common.hpp | 2 - include/core/offsets.hpp | 4 + include/core/sdk.hpp | 3 +- include/globals.h | 13 +- include/hacks/CMakeLists.txt | 1 + include/hacks/SeedPrediction.hpp | 52 ++++++++ include/hacks/hacklist.hpp | 1 + include/helpers.hpp | 7 +- include/hooks.hpp | 1 + include/hooks/HookedMethods.hpp | 5 +- include/online/Online.hpp | 4 +- include/reclasses/CMakeLists.txt | 1 + include/reclasses/CTFPartyClient.hpp | 1 + include/reclasses/C_TEFireBullets.hpp | 20 +++ include/reclasses/reclasses.hpp | 1 + include/sdk/CMakeLists.txt | 1 + include/sdk/c_basetempentity.h | 105 ++++++++++++++++ include/tfmm.hpp | 2 + include/visual/CMakeLists.txt | 2 +- src/hacks/Achievement.cpp | 7 +- src/hacks/Aimbot.cpp | 21 ++-- src/hacks/AutoBackstab.cpp | 136 +++++++++++++++++++-- src/hacks/AutoJoin.cpp | 15 +-- src/hacks/Backtrack.cpp | 21 ++-- src/hacks/CMakeLists.txt | 1 + src/hacks/CatBot.cpp | 30 ++--- src/hacks/FollowBot.cpp | 106 +++++++++++++--- src/hacks/SeedPrediction.cpp | 153 +++++++++++++++++++++++ src/hacks/Trigger.cpp | 9 +- src/helpers.cpp | 169 ++++++++++++++++++++++++-- src/hitrate.cpp | 39 +++++- src/hooks.cpp | 1 + src/hooks/CMakeLists.txt | 1 + src/hooks/CreateMove.cpp | 101 ++++++++++++++- src/hooks/LevelInit.cpp | 2 + src/hooks/PreDataUpdate.cpp | 20 +++ src/hooks/SendDatagram.cpp | 3 - src/hooks/visual/FrameStageNotify.cpp | 38 ++---- src/hooks/visual/PaintTraverse.cpp | 2 +- src/reclasses/CMakeLists.txt | 1 + src/reclasses/CTFPartyClient.cpp | 10 ++ src/reclasses/C_TEFireBullets.cpp | 34 ++++++ src/tfmm.cpp | 12 +- 44 files changed, 1016 insertions(+), 148 deletions(-) mode change 100755 => 100644 include/globals.h create mode 100644 include/hacks/SeedPrediction.hpp create mode 100644 include/reclasses/C_TEFireBullets.hpp create mode 100644 include/sdk/c_basetempentity.h create mode 100644 src/hacks/SeedPrediction.cpp create mode 100644 src/hooks/PreDataUpdate.cpp create mode 100644 src/reclasses/C_TEFireBullets.cpp diff --git a/attach-libnamed.sh b/attach-libnamed.sh index ac1e0f1b..ed33e5c5 100755 --- a/attach-libnamed.sh +++ b/attach-libnamed.sh @@ -50,9 +50,6 @@ sudo cp "bin/libcathook.so" "/lib/i386-linux-gnu/${FILENAME}" echo loading "$FILENAME" to "$proc" -sudo killall -19 steam -sudo killall -19 steamwebhelper - sudo gdb -n -q -batch \ -ex "attach $proc" \ -ex "set \$dlopen = (void*(*)(char*, int)) dlopen" \ @@ -64,6 +61,3 @@ sudo gdb -n -q -batch \ -ex "quit" sudo rm "/lib/i386-linux-gnu/${FILENAME}" - -sudo killall -18 steamwebhelper -sudo killall -18 steam diff --git a/include/common.hpp b/include/common.hpp index 4e4b3212..1e18c9cd 100755 --- a/include/common.hpp +++ b/include/common.hpp @@ -50,7 +50,6 @@ #include #if ENABLE_VISUALS - #include #include "visual/fidgetspinner.hpp" #include @@ -58,7 +57,6 @@ #include #include #include "visual/menu/compatlayer.hpp" - #endif #include "core/profiler.hpp" diff --git a/include/core/offsets.hpp b/include/core/offsets.hpp index c6d2a1c3..fbb2ae9c 100644 --- a/include/core/offsets.hpp +++ b/include/core/offsets.hpp @@ -162,6 +162,10 @@ struct offsets { return PlatformOffset(2, undefined, undefined); } + static constexpr uint32_t PreDataUpdate() + { + return PlatformOffset(14, undefined, undefined); + } static constexpr uint32_t Paint() { return PlatformOffset(14, undefined, undefined); diff --git a/include/core/sdk.hpp b/include/core/sdk.hpp index 3cc1ad41..c2a58ee6 100755 --- a/include/core/sdk.hpp +++ b/include/core/sdk.hpp @@ -55,6 +55,7 @@ #include #include +#include "sdk/c_basetempentity.h" #include "sdk/in_buttons.h" #include "sdk/imaterialsystemfixed.h" #include "sdk/ScreenSpaceEffects.h" @@ -64,4 +65,4 @@ #include "sdk/CGameRules.h" #undef private -#undef protected \ No newline at end of file +#undef protected diff --git a/include/globals.h b/include/globals.h old mode 100755 new mode 100644 index 801e09cf..033c5f31 --- a/include/globals.h +++ b/include/globals.h @@ -6,9 +6,8 @@ */ #pragma once - +#include #include - class Vector; class ConVar; class CatVar; @@ -38,14 +37,20 @@ extern char *disconnect_reason_newlined; extern CatVar disconnect_reason; extern time_t time_injected; - +struct brutestruct +{ + int brutenum[32]; + Vector last_angles[32]; + std::deque choke[32]; + float lastsimtime; +}; class GlobalSettings { public: void Init(); bool bInvalid{ true }; bool is_create_move{ false }; - Vector last_angles; + brutestruct brute; }; class CUserCmd; diff --git a/include/hacks/CMakeLists.txt b/include/hacks/CMakeLists.txt index 0b807d88..05602927 100644 --- a/include/hacks/CMakeLists.txt +++ b/include/hacks/CMakeLists.txt @@ -1,6 +1,7 @@ target_sources(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}/AutoJoin.hpp" "${CMAKE_CURRENT_LIST_DIR}/CatBot.hpp" + "${CMAKE_CURRENT_LIST_DIR}/SeedPrediction.hpp" "${CMAKE_CURRENT_LIST_DIR}/Spam.hpp") if(NOT LagbotMode) target_sources(cathook PRIVATE diff --git a/include/hacks/SeedPrediction.hpp b/include/hacks/SeedPrediction.hpp new file mode 100644 index 00000000..8d4e303e --- /dev/null +++ b/include/hacks/SeedPrediction.hpp @@ -0,0 +1,52 @@ +/* + * SeedPrediction.hpp + * + * Created on: Jul 27, 2018 + * Author: bencat07 + */ +#include +#include "reclasses.hpp" +#include "C_TEFireBullets.hpp" +#include "common.hpp" +#pragma once +namespace hacks::tf2::seedprediction +{ + void handleFireBullets(C_TEFireBullets *); + struct seedstruct + { + int tickcount; + int seed; + float time; + bool operator<(const seedstruct &rhs) const + { + return tickcount < rhs.tickcount; + } + }; + struct predictSeed2 + { + seedstruct base; + int tickcount; + double resolution; + bool operator<(const predictSeed2 &rhs) const + { + return tickcount < rhs.tickcount; + } + }; + struct IntervalEdge + { + int pos; + double val; + bool operator<(const IntervalEdge &rhs) const + { + return val < rhs.val; + } + }; + typedef boost::circular_buffer buf; + typedef boost::circular_buffer buf2; + typedef boost::circular_buffer buf3; + extern buf bases; + extern buf2 rebased; + extern buf3 intervals; + void selectBase(); + double predictOffset(const seedstruct& entry, int targetTick, double clockRes); +} diff --git a/include/hacks/hacklist.hpp b/include/hacks/hacklist.hpp index 6be90786..17be958d 100755 --- a/include/hacks/hacklist.hpp +++ b/include/hacks/hacklist.hpp @@ -30,6 +30,7 @@ #include "AutoDeadringer.hpp" #include "Bunnyhop.hpp" #include "LagExploit.hpp" +#include "SeedPrediction.hpp" #endif #if ENABLE_VISUALS #include "Radar.hpp" diff --git a/include/helpers.hpp b/include/helpers.hpp index 68d474f9..c8bf44a1 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -77,8 +77,11 @@ bool IsEntityVectorVisible(CachedEntity *entity, Vector endpos); bool VisCheckEntFromEnt(CachedEntity *startEnt, CachedEntity *endEnt); bool VisCheckEntFromEntVector(Vector startVector, CachedEntity *startEnt, CachedEntity *endEnt); -Vector VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, - bool checkWalkable); +Vector VischeckCorner(CachedEntity *player, CachedEntity *target, float maxdist, + bool checkWalkable); +std::pair VischeckWall(CachedEntity *player, + CachedEntity *target, float maxdist, + bool checkWalkable); float vectorMax(Vector i); Vector vectorAbs(Vector i); bool canReachVector(Vector loc, Vector dest = { 0, 0, 0 }); diff --git a/include/hooks.hpp b/include/hooks.hpp index 8a5abded..ae7d1f2c 100644 --- a/include/hooks.hpp +++ b/include/hooks.hpp @@ -60,6 +60,7 @@ extern VMTHook clientmode4; extern VMTHook client; extern VMTHook engine; extern VMTHook netchannel; +extern VMTHook firebullets; extern VMTHook clientdll; extern VMTHook matsurface; extern VMTHook studiorender; diff --git a/include/hooks/HookedMethods.hpp b/include/hooks/HookedMethods.hpp index 871f50b9..9754e416 100644 --- a/include/hooks/HookedMethods.hpp +++ b/include/hooks/HookedMethods.hpp @@ -7,7 +7,7 @@ #pragma once #include "common.hpp" - +#include "SeedPrediction.hpp" #if ENABLE_VISUALS union SDL_Event; struct SDL_Window; @@ -34,9 +34,10 @@ struct SDL_Window; #define HOOK_ARGS(name) \ hooked_methods::methods::name, offsets::name(), \ &hooked_methods::original::name - namespace hooked_methods { +// FireBullets +DECLARE_HOOKED_METHOD(PreDataUpdate, void, void *, int); // ClientMode DECLARE_HOOKED_METHOD(CreateMove, bool, void *, float, CUserCmd *); DECLARE_HOOKED_METHOD(LevelInit, void, void *, const char *); diff --git a/include/online/Online.hpp b/include/online/Online.hpp index 3876af8d..95f91d72 100644 --- a/include/online/Online.hpp +++ b/include/online/Online.hpp @@ -23,11 +23,9 @@ struct user_data bool has_software{ false }; bool no_target{ false }; bool is_developer{}; -#if ENABLE_VISUALS bool has_color{ false }; colors::rgba_t color{}; bool rainbow{ false }; -#endif }; /* @@ -36,4 +34,4 @@ struct user_data void update(); user_data *getUserData(unsigned steamId); -} \ No newline at end of file +} diff --git a/include/reclasses/CMakeLists.txt b/include/reclasses/CMakeLists.txt index 39381075..69054cae 100644 --- a/include/reclasses/CMakeLists.txt +++ b/include/reclasses/CMakeLists.txt @@ -3,6 +3,7 @@ target_sources(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}/C_BaseEntity.hpp" "${CMAKE_CURRENT_LIST_DIR}/C_BasePlayer.hpp" "${CMAKE_CURRENT_LIST_DIR}/C_MannVsMachineStats.hpp" + "${CMAKE_CURRENT_LIST_DIR}/C_TEFireBullets.hpp" "${CMAKE_CURRENT_LIST_DIR}/CTFGCClientSystem.hpp" "${CMAKE_CURRENT_LIST_DIR}/CTFInventoryManager.hpp" "${CMAKE_CURRENT_LIST_DIR}/CTFPartyClient.hpp" diff --git a/include/reclasses/CTFPartyClient.hpp b/include/reclasses/CTFPartyClient.hpp index 7b32678c..77eb23da 100755 --- a/include/reclasses/CTFPartyClient.hpp +++ b/include/reclasses/CTFPartyClient.hpp @@ -20,6 +20,7 @@ public: static ITFGroupMatchCriteria *MutLocalGroupCriteria(CTFPartyClient *client); static bool BCanQueueForStandby(CTFPartyClient *this_); char RequestQueueForMatch(int type); + bool BInQueueForMatchGroup(int type); char RequestLeaveForMatch(int type); int BInvitePlayerToParty(CSteamID steamid); int BRequestJoinPlayer(CSteamID steamid); diff --git a/include/reclasses/C_TEFireBullets.hpp b/include/reclasses/C_TEFireBullets.hpp new file mode 100644 index 00000000..5d0cbb2a --- /dev/null +++ b/include/reclasses/C_TEFireBullets.hpp @@ -0,0 +1,20 @@ +/* + * C_TEFireBullets.h + * + * Created on: Jul 27, 2018 + * Author: bencat07 + */ +#pragma once +#include "reclasses.hpp" +class C_TEFireBullets : public C_BaseTempEntity +{ +public: + C_TEFireBullets() = delete; + static C_TEFireBullets *GTEFireBullets(); + +public: + int m_iSeed(); + int m_iWeaponID(); + int m_iPlayer(); + float m_flSpread(); +}; diff --git a/include/reclasses/reclasses.hpp b/include/reclasses/reclasses.hpp index 58e037e1..45e15514 100755 --- a/include/reclasses/reclasses.hpp +++ b/include/reclasses/reclasses.hpp @@ -22,5 +22,6 @@ #include "ITFGroupMatchCriteria.hpp" #include "CTFPartyClient.hpp" +#include "C_TEFireBullets.hpp" #include "C_MannVsMachineStats.hpp" #include "CTFInventoryManager.hpp" diff --git a/include/sdk/CMakeLists.txt b/include/sdk/CMakeLists.txt index bb75e6ee..a6b416e7 100644 --- a/include/sdk/CMakeLists.txt +++ b/include/sdk/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(cathook PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/c_basetempentity.h" "${CMAKE_CURRENT_LIST_DIR}/CGameRules.h" "${CMAKE_CURRENT_LIST_DIR}/HUD.h" "${CMAKE_CURRENT_LIST_DIR}/igamemovement.h" diff --git a/include/sdk/c_basetempentity.h b/include/sdk/c_basetempentity.h new file mode 100644 index 00000000..e41f48cc --- /dev/null +++ b/include/sdk/c_basetempentity.h @@ -0,0 +1,105 @@ +/* + * c_basetempentity.h + * + * Created on: Jul 27, 2018 + * Author: bencat07 + */ + +#pragma once +#include "client_class.h" +#include "iclientnetworkable.h" +class C_BaseTempEntity : public IClientUnknown, public IClientNetworkable + +{ +public: + typedef C_BaseTempEntity ThisClass; + DECLARE_CLIENTCLASS(); + + C_BaseTempEntity( void ); + virtual ~C_BaseTempEntity( void ); + + +// IClientUnknown implementation. +public: + + virtual void SetRefEHandle( const CBaseHandle &handle ) { Assert( false ); } + virtual const CBaseHandle& GetRefEHandle() const { return *((CBaseHandle*)0); } + + virtual IClientUnknown* GetIClientUnknown() { return this; } + virtual ICollideable* GetCollideable() { return 0; } + virtual IClientNetworkable* GetClientNetworkable() { return this; } + virtual IClientRenderable* GetClientRenderable() { return 0; } + virtual IClientEntity* GetIClientEntity() { return 0; } + virtual C_BaseEntity* GetBaseEntity() { return 0; } + virtual IClientThinkable* GetClientThinkable() { return 0; } + + +// IClientNetworkable overrides. +public: + + virtual void Release(); + virtual void NotifyShouldTransmit( ShouldTransmitState_t state ); + virtual void PreDataUpdate( DataUpdateType_t updateType ); + virtual void PostDataUpdate( DataUpdateType_t updateType ); + virtual void OnDataUnchangedInPVS( void ) { } + virtual void OnPreDataChanged( DataUpdateType_t updateType ); + virtual void OnDataChanged( DataUpdateType_t updateType ); + virtual void SetDormant( bool bDormant ); + virtual bool IsDormant( void ); + virtual int entindex( void ) const; + virtual void ReceiveMessage( int classID, bf_read &msg ); + virtual void* GetDataTableBasePtr(); + virtual void SetDestroyedOnRecreateEntities( void ); + +public: + + // Dummy for CNetworkVars. + void NetworkStateChanged() {} + void NetworkStateChanged( void *pVar ) {} + + virtual bool Init(int entnum, int iSerialNum); + + virtual void Precache( void ); + + // For dynamic entities, return true to allow destruction + virtual bool ShouldDestroy( void ) { return false; }; + + C_BaseTempEntity *GetNext( void ); + + // Get list of tempentities + static C_BaseTempEntity *GetList( void ); + + C_BaseTempEntity *GetNextDynamic( void ); + + // Determine the color modulation amount + void GetColorModulation( float* color ) + { + assert(color); + color[0] = color[1] = color[2] = 1.0f; + } + + // Should this object be able to have shadows cast onto it? + virtual bool ShouldReceiveProjectedTextures( int flags ) { return false; } + +// Static members +public: + // List of dynamically allocated temp entis + static C_BaseTempEntity *GetDynamicList(); + + // Called at startup to allow temp entities to precache any models/sounds that they need + static void PrecacheTempEnts( void ); + + static void ClearDynamicTempEnts( void ); + + static void CheckDynamicTempEnts( void ); + +private: + + // Next in chain + C_BaseTempEntity *m_pNext; + C_BaseTempEntity *m_pNextDynamic; + + // TEs add themselves to this list for the executable. + static C_BaseTempEntity *s_pTempEntities; + static C_BaseTempEntity *s_pDynamicEntities; +}; diff --git a/include/tfmm.hpp b/include/tfmm.hpp index b786a79b..12d2c724 100755 --- a/include/tfmm.hpp +++ b/include/tfmm.hpp @@ -14,4 +14,6 @@ void queue_start(); void queue_leave(); void dcandabandon(); void abandon(); +extern CatVar queue; +extern CatEnum queue_mode; } diff --git a/include/visual/CMakeLists.txt b/include/visual/CMakeLists.txt index aba446af..d8ca8c2d 100644 --- a/include/visual/CMakeLists.txt +++ b/include/visual/CMakeLists.txt @@ -12,4 +12,4 @@ if(EnableGUI) add_subdirectory(menu) endif() -target_include_directories(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}") \ No newline at end of file +target_include_directories(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}") diff --git a/src/hacks/Achievement.cpp b/src/hacks/Achievement.cpp index 11545eb4..63c6411d 100644 --- a/src/hacks/Achievement.cpp +++ b/src/hacks/Achievement.cpp @@ -93,18 +93,17 @@ CatCommand lock_single("achievement_lock_single", "Locks single achievement by INDEX!", [](const CCommand &args) { char *out = nullptr; - int index = strtol(args.Arg(1), &out, 10); + int index = atoi(args.Arg(1)); if (out == args.Arg(1)) { logging::Info("NaN achievement INDEX!"); return; } - IAchievement *ach = - g_IAchievementMgr->GetAchievementByIndex(index); + IAchievement *ach = reinterpret_cast(g_IAchievementMgr->GetAchievementByIndex(index)); if (ach) { g_ISteamUserStats->RequestCurrentStats(); - g_ISteamUserStats->ClearAchievement(ach->GetName()); + g_ISteamUserStats->ClearAchievement(g_IAchievementMgr->GetAchievementByIndex(index)->GetName()); g_ISteamUserStats->StoreStats(); g_ISteamUserStats->RequestCurrentStats(); } diff --git a/src/hacks/Aimbot.cpp b/src/hacks/Aimbot.cpp index 3927addc..0ccad26b 100644 --- a/src/hacks/Aimbot.cpp +++ b/src/hacks/Aimbot.cpp @@ -198,11 +198,11 @@ bool BacktrackAimbot() if (iBestTarget == -1) return true; int tickcnt = 0; - + int tickus = (float(hacks::shared::backtrack::latency) > 800.0f || float(hacks::shared::backtrack::latency) < 200.0f) ? 12 : 24; for (auto i : hacks::shared::backtrack::headPositions[iBestTarget]) { bool good_tick = false; - for (int j = 0; j < 12; ++j) + for (int j = 0; j < tickus; ++j) if (tickcnt == hacks::shared::backtrack::sorted_ticks[j].tick && hacks::shared::backtrack::sorted_ticks[j].tickcount != INT_MAX) good_tick = true; @@ -220,10 +220,10 @@ bool BacktrackAimbot() if (CE_BAD(tar)) continue; // target_eid = tar->m_IDX; - Vector &angles = NET_VECTOR(tar, netvar.m_angEyeAngles); - float &simtime = NET_FLOAT(tar, netvar.m_flSimulationTime); - angles.y = i.viewangles; - simtime = i.simtime; + Vector &angles = NET_VECTOR(RAW_ENT(tar), netvar.m_angEyeAngles); + float &simtime = CE_FLOAT(tar, netvar.m_flSimulationTime); + angles.y = i.viewangles; + simtime = i.simtime; g_pUserCmd->tick_count = i.tickcount; Vector tr = (i.hitboxpos - g_pLocalPlayer->v_Eye); Vector angles2; @@ -255,9 +255,10 @@ void CreateMove() // Auto-Unzoom if (auto_unzoom) { - if (g_pLocalPlayer->holding_sniper_rifle && g_pLocalPlayer->bZoomed && zoomTime.check(3000)) + if (g_pLocalPlayer->holding_sniper_rifle && g_pLocalPlayer->bZoomed && + zoomTime.check(3000)) { - g_pUserCmd->buttons |= IN_ATTACK2; + g_pUserCmd->buttons |= IN_ATTACK2; } } // We do this as we need to pass whether the aimkey allows aiming to both @@ -509,6 +510,7 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state) // We dont have a target currently so we must find one, reset statuses foundTarget = false; target_last = nullptr; + target_eid = -1; float target_highest_score, scr; CachedEntity *ent; @@ -561,6 +563,9 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state) // Save the ent for future use with target lock target_last = target_highest_ent; + if (CE_GOOD(target_last)) + target_eid = target_last->m_IDX; + return target_highest_ent; } diff --git a/src/hacks/AutoBackstab.cpp b/src/hacks/AutoBackstab.cpp index ff1ecff0..16455995 100644 --- a/src/hacks/AutoBackstab.cpp +++ b/src/hacks/AutoBackstab.cpp @@ -7,7 +7,6 @@ #include "common.hpp" #include "hacks/Backtrack.hpp" - namespace hacks::tf2::autobackstab { @@ -23,23 +22,133 @@ const Vector GetWorldSpaceCenter(CachedEntity *ent) static CatVar enabled(CV_SWITCH, "autobackstab", "0", "Auto Backstab", "Does not depend on triggerbot!"); -static CatVar value(CV_INT, "autobackstab_range", "75.0f", - "Set Detection Distance to this much"); +static CatVar silent(CV_SWITCH, "autobackstab_silent", "1", "Silent"); bool found; +std::pair GetHitboxBounds(CachedEntity *it, int hitbox) +{ + std::pair result(it->hitboxes.GetHitbox(hitbox)->min,it->hitboxes.GetHitbox(hitbox)->max); + return result; +} // TODO improve +bool CanBackstab(CachedEntity *tar, Vector Local_ang) +{ + if (CE_BAD(tar)) + return false; + // Get the forward view vector of the target, ignore Z + Vector vecVictimForward = NET_VECTOR(RAW_ENT(tar), netvar.m_angEyeAngles); + vecVictimForward.z = 0.0f; + vecVictimForward.NormalizeInPlace(); + + // Get a vector from my origin to my targets origin + Vector vecToTarget; + vecToTarget = GetWorldSpaceCenter(tar) - GetWorldSpaceCenter(LOCAL_E); + vecToTarget.z = 0.0f; + vecToTarget.NormalizeInPlace(); + + // Get a forward vector of the attacker. + Vector vecOwnerForward = Local_ang; + vecOwnerForward.z = 0.0f; + vecOwnerForward.NormalizeInPlace(); + + float flDotOwner = DotProduct(vecOwnerForward, vecToTarget); + float flDotVictim = DotProduct(vecVictimForward, vecToTarget); + + // Make sure they're actually facing the target. + // This needs to be done because lag compensation can place target slightly + // behind the attacker. + if (flDotOwner > 0.5) + return (flDotVictim > -0.1); + return false; +} void CreateMove() { if (!enabled) return; - if (!CE_GOOD(LOCAL_E)) + if (!CE_GOOD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer() || !CE_GOOD(LOCAL_W)) return; if (!LOCAL_E->m_bAlivePlayer()) return; if (g_pLocalPlayer->weapon()->m_iClassID() != CL_CLASS(CTFKnife)) return; - if (!hacks::shared::backtrack::enable && - CE_BYTE(g_pLocalPlayer->weapon(), netvar.m_bReadyToBackstab)) - g_pUserCmd->buttons |= IN_ATTACK; + int eid = -1; + Vector endpos; + ICollideable *p = RAW_ENT(LOCAL_E)->GetCollideable(); + const Vector &max1 = p->OBBMaxs() + RAW_ENT(LOCAL_E)->GetAbsOrigin(); + const Vector &min1 = p->OBBMins() + RAW_ENT(LOCAL_E)->GetAbsOrigin(); + WhatIAmLookingAt(&eid, &endpos); + + CachedEntity *target = nullptr; + if (eid > -1) + target = ENTITY(eid); + if (CE_GOOD(target) && target != LOCAL_E && + target->m_iTeam() != LOCAL_E->m_iTeam() && target->m_bAlivePlayer() && + target->m_Type() == ENTITY_PLAYER && + !hacks::shared::backtrack::enable && + CanBackstab(target, g_pLocalPlayer->v_OrigViewangles)) + { + float swingrange = + re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)); + const Vector &max2 = GetHitboxBounds(target, 1).second + + Vector(swingrange, swingrange, swingrange); + const Vector &min2 = GetHitboxBounds(target, 1).first - + Vector(swingrange, swingrange, swingrange); + if ((min1.x <= max2.x && max1.x >= min2.x) && + (min1.y <= max2.y && max1.y >= min2.y) && + (min1.z <= max2.z && max1.z >= min2.z)) + g_pUserCmd->buttons |= IN_ATTACK; + } + else if (!hacks::shared::backtrack::enable) + { + CachedEntity *tar = nullptr; + float bestscr = 9999.9f; + int bestent = -1; + for (int i = 0; i < g_IEngine->GetMaxClients(); i++) + { + CachedEntity *tmp = ENTITY(i); + if (CE_BAD(tmp)) + continue; + if (tmp == LOCAL_E) + continue; + if (tmp->m_iTeam() == LOCAL_E->m_iTeam()) + continue; + if (!tmp->m_bAlivePlayer()) + continue; + if (tmp->m_Type() != ENTITY_PLAYER) + continue; + float swingrange = + re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)); + ICollideable *c = RAW_ENT(tmp)->GetCollideable(); + const Vector &max2 = c->OBBMaxs() + tmp->m_vecOrigin() + + Vector(swingrange, swingrange, swingrange); + const Vector &min2 = c->OBBMins() + tmp->m_vecOrigin() - + Vector(swingrange, swingrange, swingrange); + if ((min1.x <= max2.x && max1.x >= min2.x) && + (min1.y <= max2.y && max1.y >= min2.y) && + (min1.z <= max2.z && max1.z >= min2.z) && + bestscr > tmp->m_flDistance()) + { + bestent = tmp->m_IDX; + bestscr = tmp->m_flDistance(); + } + } + if (bestent > -1) + tar = ENTITY(bestent); + if (CE_BAD(tar)) + return; + Vector eyeang = g_pLocalPlayer->v_OrigViewangles; + for (float i = -180.0f; i < 180.0f; i += 30.0f) + { + eyeang.y = i; + if (CanBackstab(tar, eyeang)) + { + g_pUserCmd->viewangles.y = eyeang.y; + g_pUserCmd->buttons |= IN_ATTACK; + if (silent) + g_pLocalPlayer->bUseSilentAngles = true; + } + break; + } + } else { if (!hacks::shared::backtrack::enable) @@ -48,10 +157,11 @@ void CreateMove() return; int iBestTarget = hacks::shared::backtrack::iBestTarget; int tickcnt = 0; + int tickus = (float(hacks::shared::backtrack::latency) > 800.0f || float(hacks::shared::backtrack::latency) < 200.0f) ? 12 : 24; for (auto i : hacks::shared::backtrack::headPositions[iBestTarget]) { bool good_tick = false; - for (int j = 0; j < 12; ++j) + for (int j = 0; j < tickus; ++j) if (tickcnt == hacks::shared::backtrack::sorted_ticks[j].tick && hacks::shared::backtrack::sorted_ticks[j].tickcount != INT_MAX) @@ -70,10 +180,12 @@ void CreateMove() // ok just in case if (CE_BAD(tar)) continue; - Vector &angles = NET_VECTOR(tar, netvar.m_angEyeAngles); - float &simtime = NET_FLOAT(tar, netvar.m_flSimulationTime); - angles.y = i.viewangles; - simtime = i.simtime; + Vector &angles = + NET_VECTOR(RAW_ENT(tar), netvar.m_angEyeAngles); + float &simtime = + NET_FLOAT(RAW_ENT(tar), netvar.m_flSimulationTime); + angles.y = i.viewangles; + simtime = i.simtime; g_pUserCmd->tick_count = i.tickcount; g_pUserCmd->buttons |= IN_ATTACK; break; diff --git a/src/hacks/AutoJoin.cpp b/src/hacks/AutoJoin.cpp index 6ec40044..4427fa79 100644 --- a/src/hacks/AutoJoin.cpp +++ b/src/hacks/AutoJoin.cpp @@ -91,18 +91,19 @@ void UpdateSearch() return; re::CTFGCClientSystem *gc = re::CTFGCClientSystem::GTFGCClientSystem(); + re::CTFPartyClient *pc = re::CTFPartyClient::GTFPartyClient(); if (g_pUserCmd && gc && gc->BConnectedToMatchServer(false) && gc->BHaveLiveMatch()) tfmm::queue_leave(); - if (!gc->BConnectedToMatchServer(false) && + if (gc && !gc->BConnectedToMatchServer(false) && queuetime.test_and_set(10 * 1000 * 60) && !gc->BHaveLiveMatch()) tfmm::queue_leave(); - if (gc && !gc->BConnectedToMatchServer(false) && !gc->BHaveLiveMatch() && - autoqueue_timer.test_and_set(1000 * 30)) - { - logging::Info("Starting queue"); - tfmm::queue_start(); - } + if (gc && !gc->BConnectedToMatchServer(false) && !gc->BHaveLiveMatch()) + if (!(pc && pc->BInQueueForMatchGroup(int(tfmm::queue)))) + { + logging::Info("Starting queue"); + tfmm::queue_start(); + } #if LAGBOT_MODE if (req_timer.test_and_set(1800000)) { diff --git a/src/hacks/Backtrack.cpp b/src/hacks/Backtrack.cpp index 3c76bc03..32a0d392 100644 --- a/src/hacks/Backtrack.cpp +++ b/src/hacks/Backtrack.cpp @@ -104,7 +104,7 @@ void Run() float bestFov = 99999; BestTick = 0; iBestTarget = -1; - bool IsMelee = GetWeaponMode() == weapon_melee; + bool IsMelee = GetWeaponMode() == weapon_melee; float prev_distance = 9999; @@ -136,6 +136,7 @@ void Run() float simtime = CE_FLOAT(pEntity, netvar.m_flSimulationTime); Vector hitbox_spine = pEntity->hitboxes.GetHitbox(3)->center; Vector ent_orig = pEntity->InternalEntity()->GetAbsOrigin(); + auto hdr = g_IModelInfo->GetStudiomodel(RAW_ENT(pEntity)->GetModel()); headPositions[i][cmd->command_number % ticks] = BacktrackData{ cmd->tick_count, hitboxpos, min, max, hitbox_spine, viewangles, simtime, ent_orig }; @@ -160,7 +161,7 @@ void Run() float bestFOV = 180.0f; float distance, prev_distance_ticks = 9999; - for (int i = 0; i < 12; ++i) + for (int i = 0; i < ticks; ++i) sorted_ticks[i] = BestTickData{ INT_MAX, i }; for (int t = 0; t < ticks; ++t) { @@ -169,10 +170,12 @@ void Run() BestTickData{ headPositions[iBestTarget][t].tickcount, t }; } std::sort(sorted_ticks, sorted_ticks + ticks); + int tickus = (float(latency) > 800.0f || float(latency) < 200.0f) ? 12 : 24; for (int t = 0; t < ticks; ++t) { bool good_tick = false; - for (int i = 0; i < 12; ++i) + + for (int i = 0; i < tickus; ++i) if (t == sorted_ticks[i].tick && sorted_ticks[i].tickcount != INT_MAX && sorted_ticks[i].tickcount) @@ -207,10 +210,10 @@ void Run() return; auto i = headPositions[iBestTarget][bestTick]; cmd->tick_count = i.tickcount; - Vector &angles = NET_VECTOR(tar, netvar.m_angEyeAngles); - float &simtime = NET_FLOAT(tar, netvar.m_flSimulationTime); - angles.y = i.viewangles; - simtime = i.simtime; + Vector &angles = NET_VECTOR(RAW_ENT(tar), netvar.m_angEyeAngles); + float &simtime = NET_FLOAT(RAW_ENT(tar), netvar.m_flSimulationTime); + angles.y = i.viewangles; + simtime = i.simtime; } } } @@ -223,12 +226,14 @@ void Draw() return; if (!shouldDrawBt) return; + int tickus = (float(latency) > 800.0f || float(latency) < 200.0f) ? 12 : 24; for (int i = 0; i < g_IEngine->GetMaxClients(); i++) { for (int j = 0; j < ticks; j++) { bool good_tick = false; - for (int i = 0; i < 12; ++i) + + for (int i = 0; i < tickus; ++i) if (j == sorted_ticks[i].tick) good_tick = true; if (!good_tick) diff --git a/src/hacks/CMakeLists.txt b/src/hacks/CMakeLists.txt index f55f0e2f..de1aa694 100644 --- a/src/hacks/CMakeLists.txt +++ b/src/hacks/CMakeLists.txt @@ -1,6 +1,7 @@ target_sources(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}/AutoJoin.cpp" "${CMAKE_CURRENT_LIST_DIR}/CatBot.cpp" + "${CMAKE_CURRENT_LIST_DIR}/SeedPrediction.cpp" "${CMAKE_CURRENT_LIST_DIR}/Spam.cpp") if(NOT LagbotMode) target_sources(cathook PRIVATE diff --git a/src/hacks/CatBot.cpp b/src/hacks/CatBot.cpp index 49039be1..332a387a 100644 --- a/src/hacks/CatBot.cpp +++ b/src/hacks/CatBot.cpp @@ -221,7 +221,7 @@ void smart_crouch() { bool foundtar = false; static bool crouch = false; - if (crouchcdr.test_and_set(1000)) + if (crouchcdr.test_and_set(2000)) { for (int i = 0; i < g_IEngine->GetMaxClients(); i++) { @@ -233,24 +233,26 @@ void smart_crouch() playerlist::AccessData(ent).state == playerlist::k_EState::IPC || should_ignore_player(ent)) - continue; + continue; bool failedvis = false; for (int j = -1; j < 18; j++) - if (IsEntityVisible(ent, j)) - failedvis = true; + if (IsEntityVisible(ent, j)) + failedvis = true; if (failedvis) - continue; + continue; for (int j = 0; j < 18; j++) { - if (!LOCAL_E->hitboxes.GetHitbox(j)) - continue; - if (!IsVectorVisible(ent->hitboxes.GetHitbox(0)->center, LOCAL_E->hitboxes.GetHitbox(j)->center) && !IsVectorVisible(ent->hitboxes.GetHitbox(0)->center, LOCAL_E->hitboxes.GetHitbox(j)->min) && !IsVectorVisible(ent->hitboxes.GetHitbox(0)->center, LOCAL_E->hitboxes.GetHitbox(j)->max)) - continue; - else - { - foundtar = true; - crouch = true; - } + if (!LOCAL_E->hitboxes.GetHitbox(j)) + continue; + if (!IsVectorVisible(ent->hitboxes.GetHitbox(0)->center, + LOCAL_E->hitboxes.GetHitbox(j)->center) && + !IsVectorVisible(ent->hitboxes.GetHitbox(0)->center, + LOCAL_E->hitboxes.GetHitbox(j)->min) && + !IsVectorVisible(ent->hitboxes.GetHitbox(0)->center, + LOCAL_E->hitboxes.GetHitbox(j)->max)) + continue; + foundtar = true; + crouch = true; } } if (!foundtar && crouch) diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index ea0b2915..5ea3d2f9 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -35,8 +35,7 @@ CatCommand follow_steam("fb_steam", "Follow Steam Id", steamid = 0x0; return; } - unsigned tempid = atol(args.Arg(1)); - steamid = *(unsigned int *) &tempid; + steamid = atol(args.Arg(1)); }); static CatVar mimic_slot(CV_SWITCH, "fb_mimic_slot", "0", "Mimic weapon slot", @@ -55,7 +54,7 @@ static CatVar afktime( CV_INT, "fb_afk_time", "15000", "Max AFK Time", "Max time in ms spent standing still before player gets declared afk"); static CatVar corneractivate( - CV_SWITCH, "fb_activation_corners", "1", "Activate arround corners", + CV_SWITCH, "fb_activation_corners", "1", "Activate around corners", "Try to find an activation path to an entity behind a corner."); // Something to store breadcrumbs created by followed players @@ -118,6 +117,43 @@ void addCrumbs(CachedEntity *target, Vector corner = g_pLocalPlayer->v_Origin) corner + dist / vectorMax(vectorAbs(dist)) * 40.0f * (i + 1)); } } + +void addCrumbPair(CachedEntity *player1, CachedEntity *player2, + std::pair corners) +{ + Vector corner1 = corners.first; + Vector corner2 = corners.second; + + { + Vector dist = corner1 - player1->m_vecOrigin(); + int maxiterations = floor(corner1.DistTo(player1->m_vecOrigin())) / 40; + for (int i = 0; i < maxiterations; i++) + { + breadcrumbs.push_back(player1->m_vecOrigin() + + dist / vectorMax(vectorAbs(dist)) * 40.0f * + (i + 1)); + } + } + { + Vector dist = corner2 - corner1; + int maxiterations = floor(corner2.DistTo(corner1)) / 40; + for (int i = 0; i < maxiterations; i++) + { + breadcrumbs.push_back( + corner1 + dist / vectorMax(vectorAbs(dist)) * 40.0f * (i + 1)); + } + } + { + Vector dist = player2->m_vecOrigin() - corner2; + int maxiterations = floor(corner2.DistTo(player2->m_vecOrigin())) / 40; + for (int i = 0; i < maxiterations; i++) + { + breadcrumbs.push_back( + corner2 + dist / vectorMax(vectorAbs(dist)) * 40.0f * (i + 1)); + } + } +} + int ClassPriority(CachedEntity *ent) { switch (g_pPlayerResource->GetClass(ent)) @@ -144,6 +180,8 @@ int ClassPriority(CachedEntity *ent) return 0; } } +Timer waittime{}; +int lastent = 0; void WorldTick() { if (!followbot) @@ -198,13 +236,27 @@ void WorldTick() continue; if (corneractivate) { - Vector indirectOrigin = - VischeckWall(LOCAL_E, entity, 250, - true); // get the corner location that the - // future target is visible from - if (!indirectOrigin.z) // if we couldn't find it, exit + Vector indirectOrigin = VischeckCorner( + LOCAL_E, entity, float(follow_activation) / 2, + true); // get the corner location that the + // future target is visible from + std::pair corners; + if (!indirectOrigin.z && + entity->m_IDX == lastent) // if we couldn't find it, run + // wallcheck instead + { + corners = VischeckWall(LOCAL_E, entity, + float(follow_activation) / 2, true); + if (!corners.first.z || !corners.second.z) + continue; + // addCrumbs(LOCAL_E, corners.first); + // addCrumbs(entity, corners.second); + addCrumbPair(LOCAL_E, entity, corners); + } + if (indirectOrigin.z) + addCrumbs(entity, indirectOrigin); + else if (!indirectOrigin.z && !corners.first.z) continue; - addCrumbs(entity, indirectOrigin); } else { @@ -266,9 +318,7 @@ void WorldTick() if (follow_target && ENTITY(follow_target)->m_flDistance() < entity->m_flDistance()) // favor closer entitys - { continue; - } // check if new target has a higher priority than current target if (ClassPriority(ENTITY(follow_target)) >= ClassPriority(ENTITY(i))) @@ -277,12 +327,25 @@ void WorldTick() if (corneractivate) { Vector indirectOrigin = - VischeckWall(LOCAL_E, entity, 250, - true); // get the corner location that the - // future target is visible from - if (!indirectOrigin.z) // if we couldn't find it, exit + VischeckCorner(LOCAL_E, entity, 250, + true); // get the corner location that the + // future target is visible from + std::pair corners; + corners.first.z = 0; + corners.second.z = 0; + if (!indirectOrigin.z && + entity->m_IDX == lastent) // if we couldn't find it, run + // wallcheck instead + { + corners = VischeckWall(LOCAL_E, entity, 250, true); + if (!corners.first.z || !corners.second.z) + continue; + addCrumbPair(LOCAL_E, entity, corners); + } + if (indirectOrigin.z) + addCrumbs(entity, indirectOrigin); + else if (!indirectOrigin.z && !corners.first.z) continue; - addCrumbs(entity, indirectOrigin); } else { @@ -295,6 +358,9 @@ void WorldTick() afkTicks[i].update(); // set afk time to 0 } } + lastent++; + if (lastent > g_IEngine->GetMaxClients()) + lastent = 0; // last check for entity before we continue if (!follow_target) return; @@ -367,13 +433,17 @@ void WorldTick() if (dist_to_target > (float) follow_distance) { // Check for jump - if (autojump && lastJump.check(1000) && (idle_time.check(2000) || DistanceToGround({breadcrumbs[0].x,breadcrumbs[0].y,breadcrumbs[0].z + 5}) > 47)) + if (autojump && lastJump.check(1000) && + (idle_time.check(2000) || + DistanceToGround({ breadcrumbs[0].x, breadcrumbs[0].y, + breadcrumbs[0].z + 5 }) > 47)) { g_pUserCmd->buttons |= IN_JUMP; lastJump.update(); } // Check if still moving. 70 HU = Sniper Zoomed Speed - if (idle_time.check(3000) && CE_VECTOR(g_pLocalPlayer->entity, netvar.vVelocity).IsZero(60.0f)) + if (idle_time.check(3000) && + CE_VECTOR(g_pLocalPlayer->entity, netvar.vVelocity).IsZero(60.0f)) { follow_target = 0; return; diff --git a/src/hacks/SeedPrediction.cpp b/src/hacks/SeedPrediction.cpp new file mode 100644 index 00000000..a9276610 --- /dev/null +++ b/src/hacks/SeedPrediction.cpp @@ -0,0 +1,153 @@ +/* + * SeedPrediction.cpp + * + * Created on: Jul 27, 2018 + * Author: bencat07 + */ +#include "common.hpp" +#include "SeedPrediction.hpp" +#include "reclasses.hpp" +constexpr double MIN_CLOCKRES = 0.25; +constexpr double MAX_CLOCKRES = 8192.5; +double clockRes; +float seedFraction = 0.0f; +//static CatVar enableSeedPrediction(CV_SWITCH, "seed_prediction", "1", "Seed Predcition", "Enable Seed prediction"); +namespace hacks::tf2::seedprediction +{ + buf bases{9999}; + buf2 rebased{9999}; + buf3 intervals{9999}; + seedstruct selected{9999}; + // Server sends us seeds when other players are shooting. + // Needs to be called in appropriate hook (not PostDataUpdate) since PostDataUpdate for TempEntities gives inaccurate tickcount + void handleFireBullets(C_TEFireBullets* ent) { + if (g_IEngine->IsInGame()) { + INetChannel *ch = (INetChannel *)g_IEngine->GetNetChannelInfo(); + double time = g_GlobalVars->curtime * g_GlobalVars->interval_per_tick - (ch ? ch->GetLatency(MAX_FLOWS) / 2 : 0.0f); + bases.push_back(seedstruct{ g_GlobalVars->tickcount, ent->m_iSeed(), time }); // It's circular buffer + selectBase(); + } + } + + void selectBase() { + if (bases.size() <= 1) { + return; + } + + int total = bases.size(); + selected = bases[bases.size()-1]; + seedFraction = 0.0; + + // Algorithmic approach to estimate server time offset + + // 1. Find clock resolution + // For each reasonable precision value "rebase" seeds to the same tick + // and check if they are close to each other (by looking for largest gap between). + + int bestGap = 0; + double newClockRes = 1.0; + + for (double res = MIN_CLOCKRES; res < MAX_CLOCKRES+1.0; res *= 2.0) { + rebased.clear(); + for (seedstruct& base : bases) { + rebased.push_back(predictSeed2{base, selected.tickcount, res}); + } + + std::sort(rebased.begin(), rebased.end()); + int gap = 0; + + for (int i = 0; i < rebased.size(); i++) { + int left = rebased[i].tickcount; + int right = rebased[i+1 < rebased.size() ? i+1 : 0].tickcount; + gap = max(gap, (right - left) % 256); + } + + gap = (gap > 0 ? gap : 256); + if (bestGap < gap) { + bestGap = gap; + newClockRes = res; + } + } + + if (total >= 5) { + clockRes = newClockRes; + } + + // 2. Find seed fraction offset + // Estimate time more precisely: "rebase" seeds to same tick (keep fraction part), + // interpret them as intervals of size 1 and find offset which covers most of them. + + double maxDisp = 5.0 / clockRes; + intervals.clear(); + + for (seedstruct& base : bases) { + double disp = double(base.seed) - double(selected.seed); + disp = fmod(disp - predictOffset(selected, base.tickcount, clockRes), 256); + disp = (disp > 128.0 ? disp - 256.0 : disp); + + if (abs(disp) < max(1.2, maxDisp)) { + intervals.push_back({ 1, disp - 0.5 }); // Actually "interval ends", not "intervals" + intervals.push_back({ -1, disp + 0.5 }); + } + } + + int curChance = 0, bestChance = 0; + sort(intervals.begin(), intervals.end()); + + for (int i = 0; i+1 < intervals.size(); i++) { + IntervalEdge& inter = intervals[i]; + curChance += inter.val; + + if (curChance > bestChance) { + bestChance = curChance; + seedFraction = (inter.pos + intervals[i+1].pos) / 2; + } + } + + logging::Info("seedpred-stats", "Seed prediction: res = %.3f, chance = %d%%\n", clockRes, bestChance*100/total); + } + + double predictOffset(const seedstruct& entry, int targetTick, double clockRes) { + return (1000.0 * g_GlobalVars->interval_per_tick / clockRes) * double(targetTick-entry.tickcount); + } + + int predictSeed(const seedstruct& entry, int targetTick, double clockRes, double SeedOffset) { + return (entry.seed + int(roundeven(predictOffset(entry, targetTick, clockRes)) + SeedOffset)) % 256; + } + + int predictTick(double targetTime) { + INetChannel *ch = (INetChannel *)g_IEngine->GetNetChannelInfo(); + double ping = ch ? ch->GetLatency(MAX_FLOWS) / 2 : 0.0f; + double deltaTime = targetTime - selected.time + ping; + return int(double(selected.tickcount) + deltaTime / g_GlobalVars->interval_per_tick + 0.7); + } + + int predictTick() { + return predictTick(g_GlobalVars->curtime * g_GlobalVars->interval_per_tick); + } + + int predictSeed(double targetTime) { + INetChannel *ch = (INetChannel *)g_IEngine->GetNetChannelInfo(); + double ping = ch ? ch->GetLatency(MAX_FLOWS) / 2 : 0.0f; + double deltaTime = targetTime - selected.time + ping; + int tick = int(double(selected.tickcount) + deltaTime / g_GlobalVars->interval_per_tick + 0.7); + double SeedOffset = predictOffset(selected, tick, clockRes); + int seed = predictSeed(selected, tick, clockRes, SeedOffset); + + logging::Info("seedpred-pred", "Last shot: guessed server tick = %d, guessed seed = %03d\n", tick, seed); + return seed; + } + + int predictSeed() { + return predictSeed(g_GlobalVars->curtime * g_GlobalVars->interval_per_tick); + } + + void reset() { + logging::Info("seedpred-stats", "Seed prediction: reset\n"); + if (!bases.empty()) { + bases.clear(); + clockRes = 2.0; + } + } +} + diff --git a/src/hacks/Trigger.cpp b/src/hacks/Trigger.cpp index 27f9df2d..b62a7695 100644 --- a/src/hacks/Trigger.cpp +++ b/src/hacks/Trigger.cpp @@ -82,10 +82,11 @@ bool CanBacktrack() { int target = hacks::shared::backtrack::iBestTarget; int tickcnt = 0; + int tickus = (float(hacks::shared::backtrack::latency) > 800.0f || float(hacks::shared::backtrack::latency) < 200.0f) ? 12 : 24; for (auto i : hacks::shared::backtrack::headPositions[target]) { bool good_tick = false; - for (int j = 0; j < 12; ++j) + for (int j = 0; j < tickus; ++j) if (tickcnt == hacks::shared::backtrack::sorted_ticks[j].tick && hacks::shared::backtrack::sorted_ticks[j].tickcount != INT_MAX) good_tick = true; @@ -125,9 +126,9 @@ bool CanBacktrack() // ok just in case if (CE_BAD(tar)) continue; - Vector &angles = NET_VECTOR(tar, netvar.m_angEyeAngles); - float &simtime = NET_FLOAT(tar, netvar.m_flSimulationTime); - angles.y = i.viewangles; + Vector &angles = NET_VECTOR(RAW_ENT(tar), netvar.m_angEyeAngles); + float &simtime = NET_FLOAT(RAW_ENT(tar), netvar.m_flSimulationTime); + angles.y = i.viewangles; g_pUserCmd->tick_count = i.tickcount; g_pUserCmd->buttons |= IN_ATTACK; return false; diff --git a/src/helpers.cpp b/src/helpers.cpp index 159da748..676e2a6a 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -108,8 +108,8 @@ void WalkTo(const Vector &vector) // Function to get the corner location that a vischeck to an entity is possible // from -Vector VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, - bool checkWalkable) +Vector VischeckCorner(CachedEntity *player, CachedEntity *target, float maxdist, + bool checkWalkable) { int maxiterations = maxdist / 40; Vector origin = player->m_vecOrigin(); @@ -123,7 +123,7 @@ Vector VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, return origin; } - for (int i = 0; i < 4; i++) // for loop for all 4 directions + for (int i = 0; i < 8; i++) // for loop for all 4 directions { // 40 * maxiterations = range in HU for (int j = 0; j < maxiterations; j++) @@ -144,6 +144,22 @@ Vector VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, case 3: virtualOrigin.y = virtualOrigin.y - 40 * (j + 1); break; + case 4: + virtualOrigin.x = virtualOrigin.x + 20 * (j + 1); + virtualOrigin.y = virtualOrigin.y + 20 * (j + 1); + break; + case 5: + virtualOrigin.x = virtualOrigin.x - 20 * (j + 1); + virtualOrigin.y = virtualOrigin.y - 20 * (j + 1); + break; + case 6: + virtualOrigin.x = virtualOrigin.x - 20 * (j + 1); + virtualOrigin.y = virtualOrigin.y + 20 * (j + 1); + break; + case 7: + virtualOrigin.x = virtualOrigin.x + 20 * (j + 1); + virtualOrigin.y = virtualOrigin.y - 20 * (j + 1); + break; } // check if player can see the players virtualOrigin if (!IsVectorVisible(origin, virtualOrigin, true)) @@ -165,6 +181,136 @@ Vector VischeckWall(CachedEntity *player, CachedEntity *target, float maxdist, return { 0, 0, 0 }; } +// return Two Corners that connect perfectly to ent and local player +std::pair VischeckWall(CachedEntity *player, + CachedEntity *target, float maxdist, + bool checkWalkable) +{ + int maxiterations = maxdist / 40; + Vector origin = player->m_vecOrigin(); + + // if we can see an entity, we don't need to run calculations + if (VisCheckEntFromEnt(player, target)) + { + std::pair orig(origin, target->m_vecOrigin()); + if (!checkWalkable) + return orig; + else if (canReachVector(origin, target->m_vecOrigin())) + return orig; + } + + for (int i = 0; i < 8; i++) // for loop for all 4 directions + { + // 40 * maxiterations = range in HU + for (int j = 0; j < maxiterations; j++) + { + Vector virtualOrigin = origin; + // what direction to go in + switch (i) + { + case 0: + virtualOrigin.x = virtualOrigin.x + 40 * (j + 1); + break; + case 1: + virtualOrigin.x = virtualOrigin.x - 40 * (j + 1); + break; + case 2: + virtualOrigin.y = virtualOrigin.y + 40 * (j + 1); + break; + case 3: + virtualOrigin.y = virtualOrigin.y - 40 * (j + 1); + break; + case 4: + virtualOrigin.x = virtualOrigin.x + 20 * (j + 1); + virtualOrigin.y = virtualOrigin.y + 20 * (j + 1); + break; + case 5: + virtualOrigin.x = virtualOrigin.x - 20 * (j + 1); + virtualOrigin.y = virtualOrigin.y - 20 * (j + 1); + break; + case 6: + virtualOrigin.x = virtualOrigin.x - 20 * (j + 1); + virtualOrigin.y = virtualOrigin.y + 20 * (j + 1); + break; + case 7: + virtualOrigin.x = virtualOrigin.x + 20 * (j + 1); + virtualOrigin.y = virtualOrigin.y - 20 * (j + 1); + break; + } + // check if player can see the players virtualOrigin + if (!IsVectorVisible(origin, virtualOrigin, true)) + continue; + for (int i = 0; i < 8; i++) // for loop for all 4 directions + { + // 40 * maxiterations = range in HU + for (int j = 0; j < maxiterations; j++) + { + Vector virtualOrigin2 = target->m_vecOrigin(); + // what direction to go in + switch (i) + { + case 0: + virtualOrigin2.x = virtualOrigin2.x + 40 * (j + 1); + break; + case 1: + virtualOrigin2.x = virtualOrigin2.x - 40 * (j + 1); + break; + case 2: + virtualOrigin2.y = virtualOrigin2.y + 40 * (j + 1); + break; + case 3: + virtualOrigin2.y = virtualOrigin2.y - 40 * (j + 1); + break; + case 4: + virtualOrigin2.x = virtualOrigin2.x + 20 * (j + 1); + virtualOrigin2.y = virtualOrigin2.y + 20 * (j + 1); + break; + case 5: + virtualOrigin2.x = virtualOrigin2.x - 20 * (j + 1); + virtualOrigin2.y = virtualOrigin2.y - 20 * (j + 1); + break; + case 6: + virtualOrigin2.x = virtualOrigin2.x - 20 * (j + 1); + virtualOrigin2.y = virtualOrigin2.y + 20 * (j + 1); + break; + case 7: + virtualOrigin2.x = virtualOrigin2.x + 20 * (j + 1); + virtualOrigin2.y = virtualOrigin2.y - 20 * (j + 1); + break; + } + // check if the virtualOrigin2 can see the target + // if + // (!VisCheckEntFromEntVector(virtualOrigin2, + // player, target)) + // continue; + // if (!IsVectorVisible(virtualOrigin, + // virtualOrigin2, true)) + // continue; + // if (!IsVectorVisible(virtualOrigin2, + // target->m_vecOrigin(), true)) + // continue; + if (!IsVectorVisible(virtualOrigin, virtualOrigin2, true)) + continue; + if (!IsVectorVisible(virtualOrigin2, target->m_vecOrigin())) + continue; + std::pair toret(virtualOrigin, + virtualOrigin2); + if (!checkWalkable) + return toret; + // check if the location is accessible + if (!canReachVector(origin, virtualOrigin) || + !canReachVector(virtualOrigin2, virtualOrigin)) + continue; + if (canReachVector(virtualOrigin2, target->m_vecOrigin())) + return toret; + } + } + } + } + // if we didn't find anything, return an empty Vector + return { { 0, 0, 0 }, { 0, 0, 0 } }; +} + // Returns a vectors max value. For example: {123,-150, 125} = 125 float vectorMax(Vector i) { @@ -196,7 +342,7 @@ bool canReachVector(Vector loc, Vector dest) Vector vec = loc + dist / vectorMax(vectorAbs(dist)) * 40.0f * (i + 1); - if (DistanceToGround({vec.x,vec.y,vec.z + 5}) >= 40) + if (DistanceToGround({ vec.x, vec.y, vec.z + 5 }) >= 40) return false; for (int j = 0; j < 4; j++) @@ -232,9 +378,10 @@ bool canReachVector(Vector loc, Vector dest) else { // check if the vector is too high above ground - // higher to avoid small false positives, player can jump 42 hu according to + // higher to avoid small false positives, player can jump 42 hu + // according to // the tf2 wiki - if (DistanceToGround({loc.x,loc.y,loc.z + 5}) >= 40) + if (DistanceToGround({ loc.x, loc.y, loc.z + 5 }) >= 40) return false; // check if there is enough space arround the vector for a player to fit @@ -261,7 +408,8 @@ bool canReachVector(Vector loc, Vector dest) trace_t trace; Ray_t ray; ray.Init(loc, directionalLoc); - g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, &trace); + g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player, + &trace); // distance of trace < than 26 if (trace.startpos.DistTo(trace.endpos) < 26.0f) return false; @@ -616,8 +764,8 @@ bool IsEntityVectorVisible(CachedEntity *entity, Vector endpos) g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_default, &trace_object); } - return (trace_object.fraction >= 0.99f || - (((IClientEntity *) trace_object.m_pEnt)) == RAW_ENT(entity)); + return (((IClientEntity *) trace_object.m_pEnt) == RAW_ENT(entity) || + trace_object.fraction >= 0.99f); } // For when you need to vis check something that isnt the local player @@ -1212,7 +1360,8 @@ void PrintChat(const char *fmt, ...) va_end(list); std::unique_ptr str(strfmt("\x07%06X[\x07%06XCAT\x07%06X]\x01 %s", 0x5e3252, 0xba3d9a, 0x5e3252, - buf.get()).release()); + buf.get()) + .release()); // FIXME DEBUG LOG logging::Info("%s", str.get()); chat->Printf(str.get()); diff --git a/src/hitrate.cpp b/src/hitrate.cpp index cb6438d6..d4035afa 100644 --- a/src/hitrate.cpp +++ b/src/hitrate.cpp @@ -60,7 +60,9 @@ CatCommand debug_ammo("debug_ammo", "Debug ammo", []() { logging::Info("%d %d", i, CE_INT(LOCAL_E, netvar.m_iAmmo + i * 4)); } }); -std::deque entstocheck{}; +bool brutesoon[32]; +int lasthits = 0; +std::array xd{}; void Update() { CachedEntity *weapon = LOCAL_W; @@ -84,10 +86,41 @@ void Update() // ONLY tracks primary ammo int ammo = CE_INT(LOCAL_E, netvar.m_iAmmo + 4); + INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo(); + static bool firstcall = true; + for (int i = 0; i < 32; i++) + { + if (firstcall) + xd[i].update(); + firstcall = false; + if (ch && + xd[i].check(ch->GetLatency(MAX_FLOWS) * 1000.0f + 100.0f) && + brutesoon[i]) + { + if (lasthits == count_hits) + { + logging::Info("Increased Brutenum of ent %d", i); + g_Settings.brute.brutenum[i]++; + } + brutesoon[i] = false; + lasthits = count_hits; + } + } if (lastweapon) { + if (ammo < lastammo) { + if (hacks::shared::aimbot::target_eid > -1) + { + if (ch && + xd[hacks::shared::aimbot::target_eid].check( + ch->GetLatency(MAX_FLOWS) * 1000.0f + 110.0f)) + { + xd[hacks::shared::aimbot::target_eid].update(); + brutesoon[hacks::shared::aimbot::target_eid] = true; + } + } // for (auto i : entstocheck) //{ OnShot(); @@ -131,7 +164,7 @@ class HurtListener : public IGameEventListener public: virtual void FireGameEvent(KeyValues *event) { - if (strcmp("player_hurt", event->GetName()) || + if (strcmp("player_hurt", event->GetName()) && strcmp("player_death", event->GetName())) return; if (g_IEngine->GetPlayerForUserID(event->GetInt("attacker")) == @@ -142,7 +175,7 @@ public: LOCAL_W->m_iClassID() == CL_CLASS(CTFSniperRifleDecap))) OnHit(strcmp("player_death", event->GetName()) ? event->GetBool("crit") - : false); + : true); } } }; diff --git a/src/hooks.cpp b/src/hooks.cpp index f7a75978..7e0214ea 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -103,6 +103,7 @@ VMTHook client{}; VMTHook engine{}; VMTHook ctfpartyclient; VMTHook netchannel{}; +VMTHook firebullets{}; VMTHook clientdll{}; VMTHook matsurface{}; VMTHook studiorender{}; diff --git a/src/hooks/CMakeLists.txt b/src/hooks/CMakeLists.txt index 768848a0..f2b1d82a 100644 --- a/src/hooks/CMakeLists.txt +++ b/src/hooks/CMakeLists.txt @@ -10,6 +10,7 @@ target_sources(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}/nographics.cpp" "${CMAKE_CURRENT_LIST_DIR}/others.cpp" "${CMAKE_CURRENT_LIST_DIR}/Paint.cpp" + "${CMAKE_CURRENT_LIST_DIR}/PreDataUpdate.cpp" "${CMAKE_CURRENT_LIST_DIR}/SendNetMsg.cpp" "${CMAKE_CURRENT_LIST_DIR}/Shutdown.cpp" "${CMAKE_CURRENT_LIST_DIR}/FireEvent.cpp" diff --git a/src/hooks/CreateMove.cpp b/src/hooks/CreateMove.cpp index 346a3a3b..6ec84a01 100644 --- a/src/hooks/CreateMove.cpp +++ b/src/hooks/CreateMove.cpp @@ -93,9 +93,14 @@ const char *cmds[7] = { "use", "voicecommand", "spec_next", "spec_prev", "spec_player", "invprev", "invnext" }; namespace hooked_methods { + DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, CUserCmd *cmd) { +#define TICK_INTERVAL (g_GlobalVars->interval_per_tick) +#define TIME_TO_TICKS(dt) ((int) (0.5f + (float) (dt) / TICK_INTERVAL)) +#define TICKS_TO_TIME(t) (TICK_INTERVAL * (t)) +#define ROUND_TO_TICKS(t) (TICK_INTERVAL * TIME_TO_TICKS(t)) uintptr_t **fp; __asm__("mov %%ebp, %0" : "=r"(fp)); bSendPackets = reinterpret_cast(**fp - 8); @@ -163,6 +168,78 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, curtime_old = g_GlobalVars->curtime; hacks::tf2::global::runcfg(); + static IClientEntity *enti; + if (resolver && cathook && CE_GOOD(LOCAL_E)) + { + for (int i = 0; i < g_IEngine->GetMaxClients(); i++) + { + if (i == g_IEngine->GetLocalPlayer()) + continue; + enti = g_IEntityList->GetClientEntity(i); + if (enti && !enti->IsDormant() && + !NET_BYTE(enti, netvar.iLifeState)) + { + float quotat = 0; + float quotaf = 0; + if (!g_Settings.brute.choke[i].empty()) + for (auto it : g_Settings.brute.choke[i]) + { + if (it) + quotat++; + else + quotaf++; + } + float quota = quotat / quotaf; + Vector &angles = NET_VECTOR(enti, netvar.m_angEyeAngles); + static bool brutepitch = false; + if (g_Settings.brute.brutenum[i] > 5) + { + g_Settings.brute.brutenum[i] = 0; + brutepitch = !brutepitch; + } + angles.y = fmod(angles.y + 180.0f, 360.0f); + if (angles.y < 0) + angles.y += 360.0f; + angles.y -= 180.0f; + if (quota < 0.8f) + switch (g_Settings.brute.brutenum[i]) + { + case 0: + break; + case 1: + angles.y += 180.0f; + break; + case 2: + angles.y -= 90.0f; + break; + case 3: + angles.y += 90.0f; + break; + case 4: + angles.y -= 180.0f; + break; + case 5: + angles.y = 0.0f; + break; + } + if (brutepitch || quota < 0.8f) + switch (g_Settings.brute.brutenum[i] % 4) + { + case 0: + break; + case 1: + angles.x = -89.0f; + break; + case 2: + angles.x = 89.0f; + break; + case 3: + angles.x = 0.0f; + break; + } + } + } + } if (nolerp) { // g_pUserCmd->tick_count += 1; @@ -512,7 +589,29 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, (cmd->buttons & IN_ATTACK || !(hacks::shared::antiaim::enabled && float(hacks::shared::antiaim::yaw_mode) >= 9 && !*bSendPackets))) - g_Settings.last_angles = cmd->viewangles; + g_Settings.brute.last_angles[LOCAL_E->m_IDX] = cmd->viewangles; + for (int i = 0; i < g_IEngine->GetMaxClients(); i++) + { + + CachedEntity *ent = ENTITY(i); + if (CE_GOOD(LOCAL_E)) + if (ent == LOCAL_E) + continue; + if (CE_BAD(ent) || !ent->m_bAlivePlayer()) + continue; + INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo(); + if (NET_FLOAT(RAW_ENT(ent), netvar.m_flSimulationTime) <= 1.5f) + continue; + float latency = ch->GetAvgLatency(MAX_FLOWS); + g_Settings.brute.choke[i].push_back( + NET_FLOAT(RAW_ENT(ent), netvar.m_flSimulationTime) == + g_Settings.brute.lastsimtime); + g_Settings.brute.last_angles[ent->m_IDX] = + NET_VECTOR(RAW_ENT(ent), netvar.m_angEyeAngles); + if (!g_Settings.brute.choke[i].empty() && + g_Settings.brute.choke[i].size() > 20) + g_Settings.brute.choke[i].pop_front(); + } } #endif int nextdata = 0; diff --git a/src/hooks/LevelInit.cpp b/src/hooks/LevelInit.cpp index 45b4bdd9..0144d155 100644 --- a/src/hooks/LevelInit.cpp +++ b/src/hooks/LevelInit.cpp @@ -107,6 +107,8 @@ DEFINE_HOOKED_METHOD(LevelInit, void, void *this_, const char *name) logging::Info("Loaded Skybox: %s", succ ? "true" : "false"); ConVar *holiday = g_ICvar->FindVar("tf_forced_holiday"); + for (int i = 0; i < 32; i++) + g_Settings.brute.brutenum[i] = 0; if (halloween_mode) holiday->SetValue(2); else if (holiday->m_nValue == 2) diff --git a/src/hooks/PreDataUpdate.cpp b/src/hooks/PreDataUpdate.cpp new file mode 100644 index 00000000..8304ccfc --- /dev/null +++ b/src/hooks/PreDataUpdate.cpp @@ -0,0 +1,20 @@ +/* + * PreDataUpdate.cpp + * + * Created on: Jul 27, 2018 + * Author: bencat07 + */ +#include "HookedMethods.hpp" +#include "SeedPrediction.hpp" + +namespace hooked_methods +{ +DEFINE_HOOKED_METHOD(PreDataUpdate, void, void *_this, int ok) +{ + hacks::tf2::seedprediction::handleFireBullets((C_TEFireBullets *)_this); + original::PreDataUpdate(_this, ok); +} +} + + + diff --git a/src/hooks/SendDatagram.cpp b/src/hooks/SendDatagram.cpp index 5a857fc2..f5da49c7 100644 --- a/src/hooks/SendDatagram.cpp +++ b/src/hooks/SendDatagram.cpp @@ -11,9 +11,6 @@ namespace hooked_methods DEFINE_HOOKED_METHOD(SendDatagram, int, INetChannel *ch, bf_write *buf) { #if not LAGBOT_MODE - if (!hacks::shared::backtrack::enable || - (float) hacks::shared::backtrack::latency <= 200.0f) - return original::SendDatagram(ch, buf); int in = ch->m_nInSequenceNr; auto state = ch->m_nInReliableState; diff --git a/src/hooks/visual/FrameStageNotify.cpp b/src/hooks/visual/FrameStageNotify.cpp index 42e50d53..5dc5710e 100644 --- a/src/hooks/visual/FrameStageNotify.cpp +++ b/src/hooks/visual/FrameStageNotify.cpp @@ -13,7 +13,8 @@ static CatVar nightmode(CV_FLOAT, "nightmode", "0", "Enable nightmode", ""); namespace hooked_methods { - +#include "reclasses.hpp" +#include "C_TEFireBullets.hpp" DEFINE_HOOKED_METHOD(FrameStageNotify, void, void *this_, ClientFrameStage_t stage) { @@ -61,7 +62,6 @@ DEFINE_HOOKED_METHOD(FrameStageNotify, void, void *this_, } OldNightmode = nightmode; } - static IClientEntity *ent; PROF_SECTION(FrameStageNotify_TOTAL); @@ -71,29 +71,6 @@ DEFINE_HOOKED_METHOD(FrameStageNotify, void, void *this_, PROF_SECTION(FSN_skinchanger); hacks::tf2::skinchanger::FrameStageNotify(stage); } - if (resolver && cathook && !g_Settings.bInvalid && - stage == FRAME_NET_UPDATE_POSTDATAUPDATE_START) - { - PROF_SECTION(FSN_resolver); - for (int i = 1; i < 32 && i < HIGHEST_ENTITY; i++) - { - if (i == g_IEngine->GetLocalPlayer()) - continue; - ent = g_IEntityList->GetClientEntity(i); - if (ent && !ent->IsDormant() && !NET_BYTE(ent, netvar.iLifeState)) - { - Vector &angles = NET_VECTOR(ent, netvar.m_angEyeAngles); - if (angles.x >= 90) - angles.x = -89; - if (angles.x <= -90) - angles.x = 89; - angles.y = fmod(angles.y + 180.0f, 360.0f); - if (angles.y < 0) - angles.y += 360.0f; - angles.y -= 180.0f; - } - } - } if (cathook && stage == FRAME_RENDER_START) { INetChannel *ch; @@ -110,6 +87,13 @@ DEFINE_HOOKED_METHOD(FrameStageNotify, void, void *this_, ipc::UpdateServerAddress(); #endif } + C_TEFireBullets *fire = C_TEFireBullets::GTEFireBullets(); + if (fire && !hooks::IsHooked((void *)fire)) + { + hooks::firebullets.Set(fire); + hooks::firebullets.HookMethod(HOOK_ARGS(PreDataUpdate)); + hooks::firebullets.Apply(); + } } if (cathook && !g_Settings.bInvalid && stage == FRAME_RENDER_START) { @@ -128,9 +112,9 @@ DEFINE_HOOKED_METHOD(FrameStageNotify, void, void *this_, if (CE_GOOD(g_pLocalPlayer->entity)) { CE_FLOAT(g_pLocalPlayer->entity, netvar.deadflag + 4) = - g_Settings.last_angles.x; + g_Settings.brute.last_angles[LOCAL_E->m_IDX].x; CE_FLOAT(g_pLocalPlayer->entity, netvar.deadflag + 8) = - g_Settings.last_angles.y; + g_Settings.brute.last_angles[LOCAL_E->m_IDX].y; } } } diff --git a/src/hooks/visual/PaintTraverse.cpp b/src/hooks/visual/PaintTraverse.cpp index fb694da5..08e8aa6a 100644 --- a/src/hooks/visual/PaintTraverse.cpp +++ b/src/hooks/visual/PaintTraverse.cpp @@ -123,7 +123,7 @@ DEFINE_HOOKED_METHOD(PaintTraverse, void, vgui::IPanel *this_, } label1: scndwait++; - switcherido = !switcherido; + switcherido = !switcherido; /*static bool replacedparty = false; static int callcnt = 0; if (party_bypass && !replacedparty && callcnt < 5) diff --git a/src/reclasses/CMakeLists.txt b/src/reclasses/CMakeLists.txt index 0739d958..166e19df 100644 --- a/src/reclasses/CMakeLists.txt +++ b/src/reclasses/CMakeLists.txt @@ -4,4 +4,5 @@ target_sources(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}/CTFPartyClient.cpp" "${CMAKE_CURRENT_LIST_DIR}/CTFParty.cpp" "${CMAKE_CURRENT_LIST_DIR}/CTFGCClientSystem.cpp" + "${CMAKE_CURRENT_LIST_DIR}/C_TEFireBullets.cpp" "${CMAKE_CURRENT_LIST_DIR}/ITFGroupMatchCriteria.cpp") \ No newline at end of file diff --git a/src/reclasses/CTFPartyClient.cpp b/src/reclasses/CTFPartyClient.cpp index 1bbd9458..a326101b 100644 --- a/src/reclasses/CTFPartyClient.cpp +++ b/src/reclasses/CTFPartyClient.cpp @@ -78,6 +78,16 @@ char re::CTFPartyClient::RequestQueueForMatch(int type) return RequestQueueForMatch_fn(this, type); } +bool re::CTFPartyClient::BInQueueForMatchGroup(int type) +{ + typedef bool (*BInQueueForMatchGroup_t)(re::CTFPartyClient *, int); + static uintptr_t addr = gSignatures.GetClientSignature( + "55 89 E5 56 53 8B 5D ? 8B 75 ? 89 D8 E8 ? ? ? ? 84 C0 74 ? 8B 4E"); + static BInQueueForMatchGroup_t BInQueueForMatchGroup_fn = + BInQueueForMatchGroup_t(addr); + + return BInQueueForMatchGroup_fn(this, type); +} char re::CTFPartyClient::RequestLeaveForMatch(int type) { typedef char (*RequestLeaveForMatch_t)(re::CTFPartyClient *, int); diff --git a/src/reclasses/C_TEFireBullets.cpp b/src/reclasses/C_TEFireBullets.cpp new file mode 100644 index 00000000..571949cd --- /dev/null +++ b/src/reclasses/C_TEFireBullets.cpp @@ -0,0 +1,34 @@ +/* + * C_TEFireBullets.cpp + * + * Created on: Jul 27, 2018 + * Author: bencat07 + */ +#include "reclasses.hpp" +#pragma once + +C_TEFireBullets *C_TEFireBullets::GTEFireBullets() +{ + typedef C_TEFireBullets *(*GTEFireBullets_t)(); + static uintptr_t addr1 = gSignatures.GetClientSignature("55 B8 ? ? ? ? 89 E5 5D C3 8D B6 00 00 00 00 55 89 E5 56 53 83 EC ? C7 45"); + GTEFireBullets_t GTEFireBullets_fn = GTEFireBullets_t(addr1); + + return GTEFireBullets_fn(); +} +int C_TEFireBullets::m_iSeed() +{ + return int(unsigned(this) + 0x34); +} +int C_TEFireBullets::m_iWeaponID() +{ + return int(unsigned(this) + 0x2c); +} +int C_TEFireBullets::m_iPlayer() +{ + return int(unsigned(this) + 0x10); +} +float C_TEFireBullets::m_flSpread() +{ + return float(unsigned(this) + 0x38); +} + diff --git a/src/tfmm.cpp b/src/tfmm.cpp index 4758e158..63eb8827 100644 --- a/src/tfmm.cpp +++ b/src/tfmm.cpp @@ -13,12 +13,6 @@ CatCommand cmd_queue_start("mm_queue_casual", "Start casual queue", CatCommand cmd_abandon("mm_abandon", "Abandon match", []() { tfmm::abandon(); }); -static CatEnum queue_mode({ "MvmPractice", "MvmMannup", "LadderMatch6v6", - "LadderMatch9v9", "LadderMatch12v12", - "CasualMatch6v6", "CasualMatch9v9", - "CasualMatch12v12", "CompetitiveEventMatch12v12" }); -static CatVar queue(queue_mode, "autoqueue_mode", "7", - "Autoqueue for this mode", ""); CatCommand get_state("mm_state", "Get party state", []() { re::CTFParty *party = re::CTFParty::GetParty(); @@ -32,7 +26,11 @@ CatCommand get_state("mm_state", "Get party state", []() { namespace tfmm { - +CatEnum queue_mode({ "MvmPractice", "MvmMannup", "LadderMatch6v6", + "LadderMatch9v9", "LadderMatch12v12", "CasualMatch6v6", + "CasualMatch9v9", "CasualMatch12v12", + "CompetitiveEventMatch12v12" }); +CatVar queue(queue_mode, "autoqueue_mode", "7", "Autoqueue for this mode", ""); void queue_start() { re::CTFPartyClient *client = re::CTFPartyClient::GTFPartyClient();