Fix crash

This commit is contained in:
LightCat 2018-08-24 20:48:11 +02:00
parent 634be68319
commit 8460b06876
12 changed files with 125 additions and 74 deletions

View File

@ -12,7 +12,7 @@
#pragma once #pragma once
namespace hacks::tf2::seedprediction namespace hacks::tf2::seedprediction
{ {
extern settings::Bool prediction; bool predon();
void handleFireBullets(C_TEFireBullets *); void handleFireBullets(C_TEFireBullets *);
struct seedstruct struct seedstruct
{ {
@ -28,7 +28,7 @@ struct predictSeed2
{ {
seedstruct base; seedstruct base;
int tickcount; int tickcount;
double resolution; float resolution;
bool operator<(const predictSeed2 &rhs) const bool operator<(const predictSeed2 &rhs) const
{ {
return tickcount < rhs.tickcount; return tickcount < rhs.tickcount;
@ -37,7 +37,7 @@ struct predictSeed2
struct IntervalEdge struct IntervalEdge
{ {
int pos; int pos;
double val; float val;
bool operator<(const IntervalEdge &rhs) const bool operator<(const IntervalEdge &rhs) const
{ {
return val < rhs.val; return val < rhs.val;
@ -50,5 +50,5 @@ extern buf bases;
extern buf2 rebased; extern buf2 rebased;
extern buf3 intervals; extern buf3 intervals;
void selectBase(); void selectBase();
double predictOffset(const seedstruct &entry, int targetTick, double clockRes); float predictOffset(const seedstruct &entry, int targetTick, float clockRes);
} // namespace hacks::tf2::seedprediction } // namespace hacks::tf2::seedprediction

View File

@ -1,4 +1,5 @@
target_sources(cathook PRIVATE 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}") target_include_directories(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}")

View File

@ -36,8 +36,6 @@ struct SDL_Window;
&hooked_methods::original::name &hooked_methods::original::name
namespace hooked_methods namespace hooked_methods
{ {
// FireBullets
DECLARE_HOOKED_METHOD(PreDataUpdate, void, void *, int);
// ClientMode // ClientMode
DECLARE_HOOKED_METHOD(CreateMove, bool, void *, float, CUserCmd *); DECLARE_HOOKED_METHOD(CreateMove, bool, void *, float, CUserCmd *);
DECLARE_HOOKED_METHOD(LevelInit, void, void *, const char *); DECLARE_HOOKED_METHOD(LevelInit, void, void *, const char *);

View File

@ -0,0 +1,10 @@
//
// Created by bencat07 on 24.08.18.
//
#pragma once
#include "HookedMethods.hpp"
namespace hooked_methods
{
void CreateMove();
}

View File

@ -34,7 +34,7 @@ class inactivityTracker
boost::hash<std::pair<int, int>>> boost::hash<std::pair<int, int>>>
inactives; inactives;
std::unordered_map<int, bool> sentryAreas; std::unordered_map<int, bool> sentryAreas;
std::vector<Vector> sentries; std::vector<Vector> sentries{};
bool vischeckConnection(std::pair<int, int> &connection) bool vischeckConnection(std::pair<int, int> &connection)
{ {

View File

@ -6,11 +6,11 @@
*/ */
#pragma once #pragma once
#include "reclasses.hpp" #include "reclasses.hpp"
class C_TEFireBullets : public C_BaseTempEntity class C_TEFireBullets
{ {
public: public:
C_TEFireBullets() = delete; C_TEFireBullets() = delete;
static C_BaseTempEntity *GTEFireBullets(); static C_TEFireBullets *GTEFireBullets();
public: public:
int m_iSeed(); int m_iSeed();

View File

@ -295,27 +295,29 @@ int GetClosestBuilding()
bool NavToSniperSpot(int priority) bool NavToSniperSpot(int priority)
{ {
Vector random_spot; Vector random_spot{};
if (!sniper_spots.size() && !preferred_sniper_spots.size()) if (!sniper_spots.size() && !preferred_sniper_spots.size())
return false; return false;
auto snip_spot = preferred_sniper_spots.size() bool use_preferred = !preferred_sniper_spots.empty();
auto snip_spot = use_preferred
? preferred_sniper_spots ? preferred_sniper_spots
: sniper_spots; : sniper_spots;
bool toret = false;
if (use_preferred)
{
int best_spot = -1; int best_spot = -1;
float maxscr = FLT_MAX; float maxscr = FLT_MAX;
int lowest_priority = 9999; int lowest_priority = 9999;
for (int i = 0; i < snip_spot.size();i++) for (int i = 0; i < snip_spot.size(); i++)
{ {
if ((priority_spots[i] < lowest_priority)) if ((priority_spots[i] < lowest_priority))
lowest_priority = priority_spots[i]; lowest_priority = priority_spots[i];
} }
for (int i = 0; i < snip_spot.size();i++) for (int i = 0; i < snip_spot.size(); i++) {
{
if ((priority_spots[i] > lowest_priority)) if ((priority_spots[i] > lowest_priority))
continue; continue;
float scr = snip_spot[i].DistTo(g_pLocalPlayer->v_Eye); float scr = snip_spot[i].DistTo(g_pLocalPlayer->v_Eye);
if (scr < maxscr) if (scr < maxscr) {
{
maxscr = scr; maxscr = scr;
best_spot = i; best_spot = i;
} }
@ -324,10 +326,17 @@ bool NavToSniperSpot(int priority)
if (best_spot == -1) if (best_spot == -1)
return false; return false;
random_spot = snip_spot.at(best_spot); random_spot = snip_spot.at(best_spot);
bool toret = false;
if (random_spot.z) if (random_spot.z)
toret = nav::NavTo(random_spot, false, true, priority); toret = nav::NavTo(random_spot, false, true, priority);
priority_spots[best_spot]++; 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; return toret;
} }
int follow_target = 0; int follow_target = 0;
@ -359,7 +368,7 @@ void CreateMove()
if (!nav::ReadyForCommands && !spy_mode && !heavy_mode && !engi_mode) if (!nav::ReadyForCommands && !spy_mode && !heavy_mode && !engi_mode)
cd3.update(); cd3.update();
bool isready = 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; static int waittime = (spy_mode || heavy_mode || engi_mode) ? 100 : 2000;
if (isready && cd3.test_and_set(waittime)) if (isready && cd3.test_and_set(waittime))
{ {

View File

@ -8,13 +8,17 @@
#include "common.hpp" #include "common.hpp"
#include "SeedPrediction.hpp" #include "SeedPrediction.hpp"
#include "reclasses.hpp" #include "reclasses.hpp"
constexpr double MIN_CLOCKRES = 0.25; constexpr float MIN_CLOCKRES = 0.25;
constexpr double MAX_CLOCKRES = 8192.5; constexpr float MAX_CLOCKRES = 8192.5;
double clockRes; float clockRes;
float seedFraction = 0.0f; float seedFraction = 0.0f;
namespace hacks::tf2::seedprediction 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 }; buf bases{ 9999 };
buf2 rebased{ 9999 }; buf2 rebased{ 9999 };
buf3 intervals{ 9999 }; buf3 intervals{ 9999 };
@ -27,7 +31,7 @@ void handleFireBullets(C_TEFireBullets *ent)
if (g_IEngine->IsInGame()) if (g_IEngine->IsInGame())
{ {
INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo(); 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); (ch ? ch->GetLatency(MAX_FLOWS) / 2 : 0.0f);
bases.push_back(seedstruct{ g_GlobalVars->tickcount, ent->m_iSeed(), bases.push_back(seedstruct{ g_GlobalVars->tickcount, ent->m_iSeed(),
time }); // It's circular buffer time }); // It's circular buffer
@ -54,9 +58,9 @@ void selectBase()
// between). // between).
int bestGap = 0; 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(); rebased.clear();
for (seedstruct &base : bases) for (seedstruct &base : bases)
@ -93,21 +97,21 @@ void selectBase()
// interpret them as intervals of size 1 and find offset which covers most // interpret them as intervals of size 1 and find offset which covers most
// of them. // of them.
double maxDisp = 5.0 / clockRes; float maxDisp = 5.0 / clockRes;
intervals.clear(); intervals.clear();
for (seedstruct &base : bases) for (seedstruct &base : bases)
{ {
double disp = double(base.seed) - double(selected.seed); float disp = float(base.seed) - float(selected.seed);
disp = disp =
fmod(disp - predictOffset(selected, base.tickcount, clockRes), 256); 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( intervals.push_back(
{ 1, disp - 0.5 }); // Actually "interval ends", not "intervals" { 1, disp - 0.5f }); // Actually "interval ends", not "intervals"
intervals.push_back({ -1, disp + 0.5 }); intervals.push_back({ -1, disp + 0.5f });
} }
} }
@ -122,7 +126,7 @@ void selectBase()
if (curChance > bestChance) if (curChance > bestChance)
{ {
bestChance = curChance; 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); 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) * return (1000.0f * g_GlobalVars->interval_per_tick / clockRes) *
double(targetTick - entry.tickcount); float(targetTick - entry.tickcount);
} }
int predictSeed(const seedstruct &entry, int targetTick, double clockRes, int predictSeed(const seedstruct &entry, int targetTick, float clockRes,
double SeedOffset) float SeedOffset)
{ {
return (entry.seed + return (entry.seed +
int(roundeven(predictOffset(entry, targetTick, clockRes)) + int(roundeven(predictOffset(entry, targetTick, clockRes)) +
@ -146,12 +150,12 @@ int predictSeed(const seedstruct &entry, int targetTick, double clockRes,
256; 256;
} }
int predictTick(double targetTime) int predictTick(float targetTime)
{ {
INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo(); INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo();
double ping = ch ? ch->GetLatency(MAX_FLOWS) / 2 : 0.0f; float ping = ch ? ch->GetLatency(MAX_FLOWS) / 2 : 0.0f;
double deltaTime = targetTime - selected.time + ping; float deltaTime = targetTime - selected.time + ping;
return int(double(selected.tickcount) + return int(float(selected.tickcount) +
deltaTime / g_GlobalVars->interval_per_tick + 0.7); deltaTime / g_GlobalVars->interval_per_tick + 0.7);
} }
@ -160,14 +164,14 @@ int predictTick()
return predictTick(g_GlobalVars->curtime * g_GlobalVars->interval_per_tick); return predictTick(g_GlobalVars->curtime * g_GlobalVars->interval_per_tick);
} }
int predictSeed(double targetTime) int predictSeed(float targetTime)
{ {
INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo(); INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo();
double ping = ch ? ch->GetLatency(MAX_FLOWS) / 2 : 0.0f; float ping = ch ? ch->GetLatency(MAX_FLOWS) / 2 : 0.0f;
double deltaTime = targetTime - selected.time + ping; float deltaTime = targetTime - selected.time + ping;
int tick = int(double(selected.tickcount) + int tick = int(float(selected.tickcount) +
deltaTime / g_GlobalVars->interval_per_tick + 0.7); 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); int seed = predictSeed(selected, tick, clockRes, SeedOffset);
logging::Info("seedpred-pred", logging::Info("seedpred-pred",

View File

@ -16,6 +16,7 @@
#include "NavBot.hpp" #include "NavBot.hpp"
#include "HookedMethods.hpp" #include "HookedMethods.hpp"
#include "PreDataUpdate.hpp"
static settings::Bool minigun_jump{ "misc.minigun-jump-tf2c", "false" }; static settings::Bool minigun_jump{ "misc.minigun-jump-tf2c", "false" };
static settings::Bool roll_speedhack{ "misc.roll-speedhack", "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(); ipc::UpdateServerAddress();
#endif #endif
} }
hooked_methods::CreateMove();
if (nolerp) if (nolerp)
{ {
// current_user_cmd->tick_count += 1; // current_user_cmd->tick_count += 1;

View File

@ -6,12 +6,34 @@
*/ */
#include "HookedMethods.hpp" #include "HookedMethods.hpp"
#include "SeedPrediction.hpp" #include "SeedPrediction.hpp"
#include "PreDataUpdate.hpp"
namespace hooked_methods 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); hacks::tf2::seedprediction::handleFireBullets((C_TEFireBullets *) _this);
original::PreDataUpdate(_this, ok); ((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()
{
if (hacks::tf2::seedprediction::predon() && CE_GOOD(LOCAL_E))
tryPatchLocalPlayerPreData();
} }
} // namespace hooked_methods } // namespace hooked_methods

View File

@ -225,6 +225,8 @@ bool NavTo(Vector dest, bool navToLocalCenter, bool persistent,
} }
crumbs.clear(); crumbs.clear();
crumbs = std::move(path); crumbs = std::move(path);
if (crumbs.empty())
return false;
lastArea = crumbs.at(0); lastArea = crumbs.at(0);
if (!navToLocalCenter && crumbs.size() > 1) if (!navToLocalCenter && crumbs.size() > 1)
crumbs.erase(crumbs.begin()); crumbs.erase(crumbs.begin());
@ -334,6 +336,7 @@ void CreateMove()
logging::Info("Pathing: New Sentry found!"); logging::Info("Pathing: New Sentry found!");
TF2MAP->pather->Reset(); TF2MAP->pather->Reset();
Repath(); Repath();
return;
} }
// If inactive for too long // If inactive for too long
if (inactivity.check(5000)) if (inactivity.check(5000))

View File

@ -5,14 +5,15 @@
* Author: bencat07 * Author: bencat07
*/ */
#include "reclasses.hpp" #include "reclasses.hpp"
#include "C_TEFireBullets.hpp"
C_BaseTempEntity *C_TEFireBullets::GTEFireBullets() C_TEFireBullets *C_TEFireBullets::GTEFireBullets()
{ {
static uintptr_t fireaddr = static uintptr_t fireaddr =
(gSignatures.GetClientSignature( (gSignatures.GetClientSignature(
"C7 40 ? ? ? ? ? C7 40 ? ? ? ? ? A3 ? ? ? ? 89 50") - "55 B8 ? ? ? ? 89 E5 5D C3 8D B6 00 00 00 00 55 89 E5 56 53 83 EC ? C7 45") +
0x4); 0x2);
C_BaseTempEntity *fire = *(C_BaseTempEntity **) fireaddr; C_TEFireBullets *fire = *(C_TEFireBullets **) fireaddr;
return fire; return fire;
} }
int C_TEFireBullets::m_iSeed() int C_TEFireBullets::m_iSeed()