From 8460b06876d977659ba0f98583bd2300fef04fc4 Mon Sep 17 00:00:00 2001 From: LightCat Date: Fri, 24 Aug 2018 20:48:11 +0200 Subject: [PATCH] Fix crash --- include/hacks/SeedPrediction.hpp | 8 ++-- include/hooks/CMakeLists.txt | 3 +- include/hooks/HookedMethods.hpp | 2 - include/hooks/PreDataUpdate.hpp | 10 ++++ include/navparser.hpp | 2 +- include/reclasses/C_TEFireBullets.hpp | 4 +- src/hacks/NavBot.cpp | 67 +++++++++++++++------------ src/hacks/SeedPrediction.cpp | 60 +++++++++++++----------- src/hooks/CreateMove.cpp | 3 ++ src/hooks/PreDataUpdate.cpp | 28 +++++++++-- src/navparser.cpp | 3 ++ src/reclasses/C_TEFireBullets.cpp | 9 ++-- 12 files changed, 125 insertions(+), 74 deletions(-) create mode 100644 include/hooks/PreDataUpdate.hpp diff --git a/include/hacks/SeedPrediction.hpp b/include/hacks/SeedPrediction.hpp index add7124e..8484fb40 100644 --- a/include/hacks/SeedPrediction.hpp +++ b/include/hacks/SeedPrediction.hpp @@ -12,7 +12,7 @@ #pragma once namespace hacks::tf2::seedprediction { -extern settings::Bool prediction; +bool predon(); void handleFireBullets(C_TEFireBullets *); struct seedstruct { @@ -28,7 +28,7 @@ struct predictSeed2 { seedstruct base; int tickcount; - double resolution; + float resolution; bool operator<(const predictSeed2 &rhs) const { return tickcount < rhs.tickcount; @@ -37,7 +37,7 @@ struct predictSeed2 struct IntervalEdge { int pos; - double val; + float val; bool operator<(const IntervalEdge &rhs) const { return val < rhs.val; @@ -50,5 +50,5 @@ extern buf bases; extern buf2 rebased; extern buf3 intervals; void selectBase(); -double predictOffset(const seedstruct &entry, int targetTick, double clockRes); +float predictOffset(const seedstruct &entry, int targetTick, float clockRes); } // namespace hacks::tf2::seedprediction diff --git a/include/hooks/CMakeLists.txt b/include/hooks/CMakeLists.txt index 2151284f..9588f1d1 100755 --- a/include/hooks/CMakeLists.txt +++ b/include/hooks/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(cathook PRIVATE - "${CMAKE_CURRENT_LIST_DIR}/HookedMethods.hpp") + "${CMAKE_CURRENT_LIST_DIR}/HookedMethods.hpp" + "${CMAKE_CURRENT_LIST_DIR}/PreDataUpdate.hpp") target_include_directories(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}") \ No newline at end of file diff --git a/include/hooks/HookedMethods.hpp b/include/hooks/HookedMethods.hpp index 4e71a2ef..fe49f141 100644 --- a/include/hooks/HookedMethods.hpp +++ b/include/hooks/HookedMethods.hpp @@ -36,8 +36,6 @@ struct SDL_Window; &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/hooks/PreDataUpdate.hpp b/include/hooks/PreDataUpdate.hpp new file mode 100644 index 00000000..ddf6fdf5 --- /dev/null +++ b/include/hooks/PreDataUpdate.hpp @@ -0,0 +1,10 @@ +// +// Created by bencat07 on 24.08.18. +// + +#pragma once +#include "HookedMethods.hpp" +namespace hooked_methods +{ + void CreateMove(); +} diff --git a/include/navparser.hpp b/include/navparser.hpp index afa010e9..28951982 100644 --- a/include/navparser.hpp +++ b/include/navparser.hpp @@ -34,7 +34,7 @@ class inactivityTracker boost::hash>> inactives; std::unordered_map sentryAreas; - std::vector sentries; + std::vector sentries{}; bool vischeckConnection(std::pair &connection) { diff --git a/include/reclasses/C_TEFireBullets.hpp b/include/reclasses/C_TEFireBullets.hpp index 0344b49b..3d87d6d2 100755 --- a/include/reclasses/C_TEFireBullets.hpp +++ b/include/reclasses/C_TEFireBullets.hpp @@ -6,11 +6,11 @@ */ #pragma once #include "reclasses.hpp" -class C_TEFireBullets : public C_BaseTempEntity +class C_TEFireBullets { public: C_TEFireBullets() = delete; - static C_BaseTempEntity *GTEFireBullets(); + static C_TEFireBullets *GTEFireBullets(); public: int m_iSeed(); diff --git a/src/hacks/NavBot.cpp b/src/hacks/NavBot.cpp index e4ffa29d..9ecaf141 100644 --- a/src/hacks/NavBot.cpp +++ b/src/hacks/NavBot.cpp @@ -295,39 +295,48 @@ int GetClosestBuilding() bool NavToSniperSpot(int priority) { - Vector random_spot; + Vector random_spot{}; if (!sniper_spots.size() && !preferred_sniper_spots.size()) return false; - auto snip_spot = preferred_sniper_spots.size() + bool use_preferred = !preferred_sniper_spots.empty(); + auto snip_spot = use_preferred ? preferred_sniper_spots : sniper_spots; - int best_spot = -1; - float maxscr = FLT_MAX; - int lowest_priority = 9999; - for (int i = 0; i < snip_spot.size();i++) - { - if ((priority_spots[i] < lowest_priority)) - lowest_priority = priority_spots[i]; - } - for (int i = 0; i < snip_spot.size();i++) - { - if ((priority_spots[i] > lowest_priority)) - continue; - float scr = snip_spot[i].DistTo(g_pLocalPlayer->v_Eye); - if (scr < maxscr) - { - maxscr = scr; - best_spot = i; - } - } - - if (best_spot == -1) - return false; - random_spot = snip_spot.at(best_spot); bool toret = false; - if (random_spot.z) - toret = nav::NavTo(random_spot, false, true, priority); - priority_spots[best_spot]++; + if (use_preferred) + { + int best_spot = -1; + float maxscr = FLT_MAX; + int lowest_priority = 9999; + for (int i = 0; i < snip_spot.size(); i++) + { + if ((priority_spots[i] < lowest_priority)) + lowest_priority = priority_spots[i]; + } + for (int i = 0; i < snip_spot.size(); i++) { + if ((priority_spots[i] > lowest_priority)) + continue; + float scr = snip_spot[i].DistTo(g_pLocalPlayer->v_Eye); + if (scr < maxscr) { + maxscr = scr; + best_spot = i; + } + } + + if (best_spot == -1) + return false; + random_spot = snip_spot.at(best_spot); + if (random_spot.z) + toret = nav::NavTo(random_spot, false, true, priority); + priority_spots[best_spot]++; + } + else if (!snip_spot.empty()) + { + int rng = rand() % snip_spot.size(); + random_spot = snip_spot.at(rng); + if (random_spot.z) + toret = nav::NavTo(random_spot, false, true, priority); + } return toret; } int follow_target = 0; @@ -359,7 +368,7 @@ void CreateMove() if (!nav::ReadyForCommands && !spy_mode && !heavy_mode && !engi_mode) cd3.update(); bool isready = - (spy_mode || heavy_mode || engi_mode) ? 1 : nav::ReadyForCommands; + (spy_mode || heavy_mode || engi_mode) ? true : nav::ReadyForCommands; static int waittime = (spy_mode || heavy_mode || engi_mode) ? 100 : 2000; if (isready && cd3.test_and_set(waittime)) { diff --git a/src/hacks/SeedPrediction.cpp b/src/hacks/SeedPrediction.cpp index 8566bd56..1ac86b02 100644 --- a/src/hacks/SeedPrediction.cpp +++ b/src/hacks/SeedPrediction.cpp @@ -8,13 +8,17 @@ #include "common.hpp" #include "SeedPrediction.hpp" #include "reclasses.hpp" -constexpr double MIN_CLOCKRES = 0.25; -constexpr double MAX_CLOCKRES = 8192.5; -double clockRes; +constexpr float MIN_CLOCKRES = 0.25; +constexpr float MAX_CLOCKRES = 8192.5; +float clockRes; float seedFraction = 0.0f; namespace hacks::tf2::seedprediction { -settings::Bool prediction{ "seed-prediction.enable", "false" }; +static settings::Bool prediction{ "seed-prediction.enable", "false" }; +bool predon() +{ + return *prediction; +} buf bases{ 9999 }; buf2 rebased{ 9999 }; buf3 intervals{ 9999 }; @@ -27,7 +31,7 @@ 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 - + float 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 @@ -54,9 +58,9 @@ void selectBase() // between). int bestGap = 0; - double newClockRes = 1.0; + float newClockRes = 1.0; - for (double res = MIN_CLOCKRES; res < MAX_CLOCKRES + 1.0; res *= 2.0) + for (float res = MIN_CLOCKRES; res < MAX_CLOCKRES + 1.0; res *= 2.0) { rebased.clear(); for (seedstruct &base : bases) @@ -93,21 +97,21 @@ void selectBase() // interpret them as intervals of size 1 and find offset which covers most // of them. - double maxDisp = 5.0 / clockRes; + float maxDisp = 5.0 / clockRes; intervals.clear(); for (seedstruct &base : bases) { - double disp = double(base.seed) - double(selected.seed); + float disp = float(base.seed) - float(selected.seed); disp = fmod(disp - predictOffset(selected, base.tickcount, clockRes), 256); - disp = (disp > 128.0 ? disp - 256.0 : disp); + disp = (disp > 128.0f ? disp - 256.0f : disp); - if (abs(disp) < max(1.2, maxDisp)) + if (abs(disp) < fmaxf(1.2, maxDisp)) { intervals.push_back( - { 1, disp - 0.5 }); // Actually "interval ends", not "intervals" - intervals.push_back({ -1, disp + 0.5 }); + { 1, disp - 0.5f }); // Actually "interval ends", not "intervals" + intervals.push_back({ -1, disp + 0.5f }); } } @@ -122,7 +126,7 @@ void selectBase() if (curChance > bestChance) { bestChance = curChance; - seedFraction = (inter.pos + intervals[i + 1].pos) / 2; + seedFraction = (inter.pos + intervals[i + 1].pos) / 2.0f; } } @@ -131,14 +135,14 @@ void selectBase() bestChance * 100 / total); } -double predictOffset(const seedstruct &entry, int targetTick, double clockRes) +float predictOffset(const seedstruct &entry, int targetTick, float clockRes) { - return (1000.0 * g_GlobalVars->interval_per_tick / clockRes) * - double(targetTick - entry.tickcount); + return (1000.0f * g_GlobalVars->interval_per_tick / clockRes) * + float(targetTick - entry.tickcount); } -int predictSeed(const seedstruct &entry, int targetTick, double clockRes, - double SeedOffset) +int predictSeed(const seedstruct &entry, int targetTick, float clockRes, + float SeedOffset) { return (entry.seed + int(roundeven(predictOffset(entry, targetTick, clockRes)) + @@ -146,12 +150,12 @@ int predictSeed(const seedstruct &entry, int targetTick, double clockRes, 256; } -int predictTick(double targetTime) +int predictTick(float 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) + + float ping = ch ? ch->GetLatency(MAX_FLOWS) / 2 : 0.0f; + float deltaTime = targetTime - selected.time + ping; + return int(float(selected.tickcount) + deltaTime / g_GlobalVars->interval_per_tick + 0.7); } @@ -160,14 +164,14 @@ int predictTick() return predictTick(g_GlobalVars->curtime * g_GlobalVars->interval_per_tick); } -int predictSeed(double targetTime) +int predictSeed(float 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) + + float ping = ch ? ch->GetLatency(MAX_FLOWS) / 2 : 0.0f; + float deltaTime = targetTime - selected.time + ping; + int tick = int(float(selected.tickcount) + deltaTime / g_GlobalVars->interval_per_tick + 0.7); - double SeedOffset = predictOffset(selected, tick, clockRes); + float SeedOffset = predictOffset(selected, tick, clockRes); int seed = predictSeed(selected, tick, clockRes, SeedOffset); logging::Info("seedpred-pred", diff --git a/src/hooks/CreateMove.cpp b/src/hooks/CreateMove.cpp index e75e30ac..83a494e5 100644 --- a/src/hooks/CreateMove.cpp +++ b/src/hooks/CreateMove.cpp @@ -16,6 +16,7 @@ #include "NavBot.hpp" #include "HookedMethods.hpp" +#include "PreDataUpdate.hpp" static settings::Bool minigun_jump{ "misc.minigun-jump-tf2c", "false" }; static settings::Bool roll_speedhack{ "misc.roll-speedhack", "false" }; @@ -197,6 +198,8 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, ipc::UpdateServerAddress(); #endif } + hooked_methods::CreateMove(); + if (nolerp) { // current_user_cmd->tick_count += 1; diff --git a/src/hooks/PreDataUpdate.cpp b/src/hooks/PreDataUpdate.cpp index 3c2c23c1..41ffa1e8 100644 --- a/src/hooks/PreDataUpdate.cpp +++ b/src/hooks/PreDataUpdate.cpp @@ -6,12 +6,34 @@ */ #include "HookedMethods.hpp" #include "SeedPrediction.hpp" +#include "PreDataUpdate.hpp" namespace hooked_methods { -DEFINE_HOOKED_METHOD(PreDataUpdate, void, void *_this, int ok) + static void *PreData_Original = nullptr; + void PreDataUpdate(void *_this, int ok) + { + hacks::tf2::seedprediction::handleFireBullets((C_TEFireBullets *) _this); + ((bool (*)(C_TEFireBullets *, int)) PreData_Original)((C_TEFireBullets *)_this, ok); + + } + static void tryPatchLocalPlayerPreData() + { + // Patching C_TEFireBullets + void **vtable = *(void ***) (C_TEFireBullets::GTEFireBullets()); + if (vtable[offsets::PreDataUpdate()] != PreDataUpdate) + { + logging::Info("0x%08X, 0x%08X", unsigned(C_TEFireBullets::GTEFireBullets()), unsigned(vtable[offsets::PreDataUpdate()])); + PreData_Original = vtable[offsets::PreDataUpdate()]; + void *page = (void *) ((uintptr_t) vtable & ~0xFFF); + mprotect(page, 0xFFF, PROT_READ | PROT_WRITE | PROT_EXEC); + vtable[offsets::PreDataUpdate()] = (void *) PreDataUpdate; + mprotect(page, 0xFFF, PROT_READ | PROT_EXEC); + } + } +void CreateMove() { - hacks::tf2::seedprediction::handleFireBullets((C_TEFireBullets *) _this); - original::PreDataUpdate(_this, ok); + if (hacks::tf2::seedprediction::predon() && CE_GOOD(LOCAL_E)) + tryPatchLocalPlayerPreData(); } } // namespace hooked_methods diff --git a/src/navparser.cpp b/src/navparser.cpp index 46a38e97..2f5686c8 100644 --- a/src/navparser.cpp +++ b/src/navparser.cpp @@ -225,6 +225,8 @@ bool NavTo(Vector dest, bool navToLocalCenter, bool persistent, } crumbs.clear(); crumbs = std::move(path); + if (crumbs.empty()) + return false; lastArea = crumbs.at(0); if (!navToLocalCenter && crumbs.size() > 1) crumbs.erase(crumbs.begin()); @@ -334,6 +336,7 @@ void CreateMove() logging::Info("Pathing: New Sentry found!"); TF2MAP->pather->Reset(); Repath(); + return; } // If inactive for too long if (inactivity.check(5000)) diff --git a/src/reclasses/C_TEFireBullets.cpp b/src/reclasses/C_TEFireBullets.cpp index fee3b9ae..c59b4150 100755 --- a/src/reclasses/C_TEFireBullets.cpp +++ b/src/reclasses/C_TEFireBullets.cpp @@ -5,14 +5,15 @@ * Author: bencat07 */ #include "reclasses.hpp" +#include "C_TEFireBullets.hpp" -C_BaseTempEntity *C_TEFireBullets::GTEFireBullets() +C_TEFireBullets *C_TEFireBullets::GTEFireBullets() { static uintptr_t fireaddr = (gSignatures.GetClientSignature( - "C7 40 ? ? ? ? ? C7 40 ? ? ? ? ? A3 ? ? ? ? 89 50") - - 0x4); - C_BaseTempEntity *fire = *(C_BaseTempEntity **) fireaddr; + "55 B8 ? ? ? ? 89 E5 5D C3 8D B6 00 00 00 00 55 89 E5 56 53 83 EC ? C7 45") + + 0x2); + C_TEFireBullets *fire = *(C_TEFireBullets **) fireaddr; return fire; } int C_TEFireBullets::m_iSeed()