commit
8e62ac5cf6
@ -1,6 +1,5 @@
|
||||
# Current dependencies:
|
||||
# Git
|
||||
# OpenSSL (maybe should be removed, only used by backpack.tf esp)
|
||||
# SDL2
|
||||
# GLEW
|
||||
|
||||
@ -40,7 +39,6 @@ if(NOT EnableVisuals)
|
||||
endif()
|
||||
|
||||
find_package(Git REQUIRED)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
# cat packages
|
||||
|
||||
@ -87,7 +85,11 @@ endif()
|
||||
configure_file(include/config.h.in ${CMAKE_SOURCE_DIR}/include/config.h @ONLY)
|
||||
configure_file(include/version.h.in ${CMAKE_SOURCE_DIR}/include/version.h @ONLY)
|
||||
|
||||
set_target_properties(cathook PROPERTIES COMPILE_FLAGS "-m32 -msse -msse2 -msse3 -fexceptions" LINK_FLAGS "-m32 -fno-gnu-unique -fexceptions -DNDEBUG")
|
||||
#set_target_properties(cathook PROPERTIES COMPILE_FLAGS "-m32 -msse -msse2 -msse3 -fexceptions" LINK_FLAGS "-m32 -fno-gnu-unique -fexceptions -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS "-m32 -msse -msse2 -msse3 -fexceptions -fno-gnu-unique -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
|
||||
|
||||
|
||||
target_compile_definitions(cathook PRIVATE
|
||||
_GLIBCXX_USE_CXX11_ABI=0
|
||||
@ -128,13 +130,6 @@ add_custom_target(data
|
||||
target_link_libraries(cathook ${ValveLibraryTier0} ${ValveLibraryVStdLib} ssl)
|
||||
set_target_properties(cathook PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
# Strip
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
message("Stripping info from library")
|
||||
add_custom_command(TARGET cathook POST_BUILD
|
||||
COMMAND strip --strip-all "$<TARGET_FILE:cathook>")
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(external)
|
||||
|
@ -23,4 +23,3 @@ libtinfo.so.5.9.4.2
|
||||
libudev.so.1.6.6.4.7
|
||||
libwrap.so.0.7.6.1.5
|
||||
libz.so.1.2.1.1.2.4
|
||||
|
||||
|
@ -61,9 +61,10 @@
|
||||
<AutoVariable width="fill" target="navbot.enable" label="Enable NavBot"/>
|
||||
<AutoVariable width="fill" target="navbot.spy-mode" label="Enable Spy Mode"/>
|
||||
<AutoVariable width="fill" target="navbot.heavy-mode" label="Enable Heavy Mode"/>
|
||||
<AutoVariable width="fill" target="navbot.engi-mode" label="Enable Engie Mode"/>
|
||||
<AutoVariable width="fill" target="navbot.primary-only" label="Best Weapon only"/>
|
||||
</List>
|
||||
<Box name="Nav FollowBot" width="content" height="content" padding="12 6 6 6" y="90">
|
||||
<Box name="Nav FollowBot" width="content" height="content" padding="12 6 6 6" y="100">
|
||||
<List width="170">
|
||||
<AutoVariable width="fill" target="navbot.medbot" label="Enable Nav Followbot"/>
|
||||
<AutoVariable width="fill" target="navbot.roaming" label="Roaming"/>
|
||||
|
@ -18,7 +18,6 @@ target_sources(cathook PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}/hitrate.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/hooks.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/hoovy.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/https_request.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/init.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/ipc.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/itemtypes.hpp"
|
||||
@ -38,7 +37,7 @@ target_sources(cathook PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}/velocity.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/votelogger.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/MiscTemporary.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/navparser.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/navparser.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Options.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/PlayerTools.hpp")
|
||||
|
||||
|
@ -63,6 +63,14 @@ public:
|
||||
offset_t hActiveWeapon;
|
||||
offset_t flChargedDamage;
|
||||
offset_t iUpgradeLevel;
|
||||
offset_t m_hBuilder;
|
||||
offset_t m_iObjectType;
|
||||
offset_t m_bBuilding;
|
||||
offset_t m_iTeleState;
|
||||
offset_t m_flTeleRechargeTime;
|
||||
offset_t m_flTeleCurrentRechargeDuration;
|
||||
offset_t m_iTeleTimesUsed;
|
||||
offset_t m_flTeleYawToExit;
|
||||
offset_t iPipeType;
|
||||
offset_t iBuildingHealth;
|
||||
offset_t iBuildingMaxHealth;
|
||||
|
@ -8,7 +8,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
#include "config.h"
|
||||
|
||||
class ConVar;
|
||||
class IClientEntity;
|
||||
|
@ -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
|
||||
|
@ -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}")
|
@ -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 *);
|
||||
|
10
include/hooks/PreDataUpdate.hpp
Normal file
10
include/hooks/PreDataUpdate.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by bencat07 on 24.08.18.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include "HookedMethods.hpp"
|
||||
namespace hooked_methods
|
||||
{
|
||||
void CreateMove();
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* https_request.hpp
|
||||
*
|
||||
* Created on: Jul 23, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace https
|
||||
{
|
||||
|
||||
extern SSL_CTX *ssl_context;
|
||||
|
||||
class RAII_HTTPS_Socket
|
||||
{
|
||||
public:
|
||||
RAII_HTTPS_Socket(const std::string &host);
|
||||
~RAII_HTTPS_Socket();
|
||||
|
||||
bool ssl_connect();
|
||||
void ssl_die();
|
||||
|
||||
std::string get(const std::string &path);
|
||||
|
||||
const std::string hostname_;
|
||||
|
||||
hostent *host_{ nullptr };
|
||||
sockaddr_in addr_{};
|
||||
int sock_{ -1 };
|
||||
SSL *connection_{ nullptr };
|
||||
};
|
||||
|
||||
void initialize();
|
||||
} // namespace https
|
@ -3,6 +3,8 @@
|
||||
#include "common.hpp"
|
||||
#include "micropather.h"
|
||||
#include "pwd.h"
|
||||
#include <thread>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#if ENABLE_VISUALS
|
||||
#include <glez/draw.hpp>
|
||||
#endif
|
||||
@ -23,32 +25,37 @@ bool Prepare();
|
||||
void CreateMove();
|
||||
void Draw();
|
||||
|
||||
struct inactivityTracker
|
||||
int FindInVector(size_t id);
|
||||
int FindNearestValid(Vector vec);
|
||||
|
||||
class inactivityTracker
|
||||
{
|
||||
// Map for storing inactivity per connection
|
||||
std::map<std::pair<int, int>, unsigned int> inactives;
|
||||
std::unordered_map<std::pair<int, int>, std::pair<int, unsigned int>,
|
||||
boost::hash<std::pair<int, int>>>
|
||||
inactives;
|
||||
|
||||
void reset()
|
||||
public:
|
||||
std::unordered_map<int, bool> sentryAreas;
|
||||
|
||||
private:
|
||||
std::vector<Vector> sentries{};
|
||||
|
||||
bool vischeckConnection(std::pair<int, int> &connection)
|
||||
{
|
||||
// inactives.clear();
|
||||
int id0 = FindInVector(connection.first);
|
||||
int id1 = FindInVector(connection.second);
|
||||
if (id0 == -1 || id1 == -1)
|
||||
return false;
|
||||
Vector begin = areas.at(id0).m_center;
|
||||
Vector end = areas.at(id1).m_center;
|
||||
begin.z += 72;
|
||||
end.z += 72;
|
||||
bool result = IsVectorVisible(begin, end, false);
|
||||
return result;
|
||||
}
|
||||
void addTime(std::pair<int, int> connection, Timer &timer,
|
||||
bool &resetPather)
|
||||
{
|
||||
if (inactives.find(connection) == inactives.end())
|
||||
{
|
||||
inactives[connection] = 0;
|
||||
}
|
||||
inactives[connection] =
|
||||
inactives[connection] +
|
||||
(std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now() - timer.last)
|
||||
.count());
|
||||
if (inactives[connection] >= 5000)
|
||||
resetPather = true;
|
||||
}
|
||||
void addTime(std::pair<Vector, Vector> connection, Timer &timer,
|
||||
bool &resetPather)
|
||||
|
||||
std::pair<int, int> VectorsToId(std::pair<Vector, Vector> &connection)
|
||||
{
|
||||
CNavArea *currnode = nullptr;
|
||||
for (size_t i = 0; i < areas.size(); i++)
|
||||
@ -60,7 +67,7 @@ struct inactivityTracker
|
||||
}
|
||||
}
|
||||
if (!currnode)
|
||||
return;
|
||||
return { -1, -1 };
|
||||
|
||||
CNavArea *nextnode = nullptr;
|
||||
for (size_t i = 0; i < areas.size(); i++)
|
||||
@ -72,21 +79,259 @@ struct inactivityTracker
|
||||
}
|
||||
}
|
||||
if (!nextnode)
|
||||
return;
|
||||
return { -1, -1 };
|
||||
|
||||
for (auto i : currnode->m_connections)
|
||||
{
|
||||
if (i.area->m_id == nextnode->m_id)
|
||||
{
|
||||
addTime(std::pair{ currnode->m_id, nextnode->m_id }, timer,
|
||||
resetPather);
|
||||
return;
|
||||
return { currnode->m_id, nextnode->m_id };
|
||||
}
|
||||
}
|
||||
return { -1, -1 };
|
||||
}
|
||||
|
||||
int VectorToID(Vector vec)
|
||||
{
|
||||
CNavArea *currnode = nullptr;
|
||||
for (size_t i = 0; i < areas.size(); i++)
|
||||
{
|
||||
if (areas.at(i).m_center == vec)
|
||||
{
|
||||
currnode = &areas.at(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!currnode)
|
||||
return -1;
|
||||
return currnode->m_id;
|
||||
}
|
||||
|
||||
public:
|
||||
void reset()
|
||||
{
|
||||
for (auto i : inactives)
|
||||
{
|
||||
// What is this tf
|
||||
i.second.second = 0;
|
||||
}
|
||||
}
|
||||
bool ShouldCancelPath(std::vector<Vector> crumbs)
|
||||
{
|
||||
for (auto crumb : crumbs)
|
||||
{
|
||||
int id = VectorToID(crumb);
|
||||
if (id == -1)
|
||||
continue;
|
||||
if (sentryAreas[id])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void updateSentries()
|
||||
{
|
||||
sentryAreas.clear();
|
||||
sentries.clear();
|
||||
for (int i = 0; i < HIGHEST_ENTITY; i++)
|
||||
{
|
||||
CachedEntity *ent = ENTITY(i);
|
||||
if (CE_BAD(ent) ||
|
||||
ent->m_iClassID() != CL_CLASS(CObjectSentrygun) ||
|
||||
ent->m_iTeam() == LOCAL_E->m_iTeam())
|
||||
continue;
|
||||
Vector sentryloc = GetBuildingPosition(ent);
|
||||
sentries.push_back(sentryloc);
|
||||
for (auto i : areas)
|
||||
{
|
||||
Vector area = i.m_center;
|
||||
area.z += 83.0f;
|
||||
if (area.DistTo(sentryloc) > 1100.0f)
|
||||
continue;
|
||||
if (!IsVectorVisible(area, sentryloc, true))
|
||||
continue;
|
||||
sentryAreas[i.m_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int getTime(std::pair<int, int> connection)
|
||||
bool IsIgnored(std::pair<int, int> connection)
|
||||
{
|
||||
if (sentryAreas[connection.first] || sentryAreas[connection.second])
|
||||
{
|
||||
logging::Info("Ignored a connection due to sentry gun coverage");
|
||||
return true;
|
||||
}
|
||||
if (inactives.find(connection) == inactives.end())
|
||||
return false;
|
||||
auto &pair = inactives.at(connection);
|
||||
if (pair.second >= 5000)
|
||||
{
|
||||
pair.first = 1;
|
||||
return true;
|
||||
}
|
||||
if (pair.first == 2 && !vischeckConnection(connection))
|
||||
{
|
||||
logging::Info(
|
||||
"Ignored a connection due to type 2 connection type.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AddTime(std::pair<int, int> connection, Timer &timer,
|
||||
bool &resetPather)
|
||||
{
|
||||
if (inactives.find(connection) == inactives.end())
|
||||
{
|
||||
inactives[connection] = { 0, 0 };
|
||||
}
|
||||
auto &pair = inactives.at(connection);
|
||||
|
||||
unsigned int newTime =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now() - timer.last)
|
||||
.count();
|
||||
if (pair.first == 2 && !vischeckConnection(connection))
|
||||
newTime = (newTime > 2500 ? 2500 : newTime);
|
||||
pair.second = pair.second + newTime;
|
||||
if (pair.second >= 5000)
|
||||
resetPather = true;
|
||||
}
|
||||
void AddTime(std::pair<Vector, Vector> connection, Timer &timer,
|
||||
bool &resetPather)
|
||||
{
|
||||
auto pair = VectorsToId(connection);
|
||||
if (pair.first == -1 || pair.second == -1)
|
||||
return;
|
||||
AddTime(pair, timer, resetPather);
|
||||
}
|
||||
bool CheckType2(std::pair<int, int> connection)
|
||||
{
|
||||
// Fix calls vischeckConnection too often
|
||||
if (inactives.find(connection) == inactives.end())
|
||||
{
|
||||
inactives[connection] = { 0, 0 };
|
||||
}
|
||||
auto pair = inactives.at(connection);
|
||||
switch (pair.first)
|
||||
{
|
||||
case 0:
|
||||
if (!vischeckConnection(connection))
|
||||
{
|
||||
inactives[connection].first = 2;
|
||||
return true;
|
||||
}
|
||||
case 1:
|
||||
case 2:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool CheckType2(std::pair<Vector, Vector> connection)
|
||||
{
|
||||
auto pair = VectorsToId(connection);
|
||||
if (pair.first == -1 || pair.second == -1)
|
||||
return false;
|
||||
return CheckType2(pair);
|
||||
}
|
||||
}; // namespace nav
|
||||
|
||||
struct MAP : public micropather::Graph
|
||||
{
|
||||
std::unique_ptr<micropather::MicroPather> pather;
|
||||
// Maps already utilize dynamic allocation and we don't need a custom
|
||||
// constructor
|
||||
inactivityTracker inactiveTracker;
|
||||
Vector GetClosestCornerToArea(CNavArea *CornerOf, CNavArea *Target)
|
||||
{
|
||||
std::array<Vector, 4> corners;
|
||||
corners.at(0) = CornerOf->m_nwCorner; // NW
|
||||
corners.at(1) = CornerOf->m_seCorner; // SE
|
||||
corners.at(2) = Vector{ CornerOf->m_seCorner.x, CornerOf->m_nwCorner.y,
|
||||
CornerOf->m_nwCorner.z }; // NE
|
||||
corners.at(3) = Vector{ CornerOf->m_nwCorner.x, CornerOf->m_seCorner.y,
|
||||
CornerOf->m_seCorner.z }; // SW
|
||||
|
||||
Vector bestVec{};
|
||||
float bestDist = FLT_MAX;
|
||||
|
||||
for (size_t i = 0; i < corners.size(); i++)
|
||||
{
|
||||
float dist = corners.at(i).DistTo(Target->m_center);
|
||||
if (dist < bestDist)
|
||||
{
|
||||
bestVec = corners.at(i);
|
||||
bestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
Vector bestVec2{};
|
||||
float bestDist2 = FLT_MAX;
|
||||
|
||||
for (size_t i = 0; i < corners.size(); i++)
|
||||
{
|
||||
if (corners.at(i) == bestVec2)
|
||||
continue;
|
||||
float dist = corners.at(i).DistTo(Target->m_center);
|
||||
if (dist < bestDist2)
|
||||
{
|
||||
bestVec2 = corners.at(i);
|
||||
bestDist2 = dist;
|
||||
}
|
||||
}
|
||||
return (bestVec + bestVec2) / 2;
|
||||
}
|
||||
|
||||
float GetZBetweenAreas(CNavArea *start, CNavArea *end)
|
||||
{
|
||||
float z1 = GetClosestCornerToArea(start, end).z;
|
||||
float z2 = GetClosestCornerToArea(end, start).z;
|
||||
|
||||
return z2 - z1;
|
||||
}
|
||||
// Function required by MicroPather for getting an estimated cost
|
||||
float LeastCostEstimate(void *stateStart, void *stateEnd)
|
||||
{
|
||||
CNavArea *start = static_cast<CNavArea *>(stateStart);
|
||||
CNavArea *end = static_cast<CNavArea *>(stateEnd);
|
||||
float dist = start->m_center.DistTo(end->m_center);
|
||||
return dist;
|
||||
}
|
||||
// Function required by MicroPather to retrieve neighbours and their
|
||||
// associated costs.
|
||||
void AdjacentCost(void *state, MP_VECTOR<micropather::StateCost> *adjacent)
|
||||
{
|
||||
CNavArea *area = static_cast<CNavArea *>(state);
|
||||
auto &neighbours = area->m_connections;
|
||||
for (auto i : neighbours)
|
||||
{
|
||||
if (GetZBetweenAreas(area, i.area) > 42)
|
||||
continue;
|
||||
if (inactiveTracker.IsIgnored(
|
||||
std::pair{ area->m_id, i.area->m_id }))
|
||||
continue;
|
||||
int id = FindInVector(i.area->m_id);
|
||||
if (id == -1)
|
||||
return;
|
||||
micropather::StateCost cost;
|
||||
cost.state = static_cast<void *>(&areas.at(id));
|
||||
cost.cost = area->m_center.DistTo(i.area->m_center);
|
||||
adjacent->push_back(cost);
|
||||
}
|
||||
}
|
||||
void PrintStateInfo(void *state)
|
||||
{
|
||||
CNavArea *area = static_cast<CNavArea *>(state);
|
||||
logging::Info(format(area->m_center.x, " ", area->m_center.y, " ",
|
||||
area->m_center.z)
|
||||
.c_str());
|
||||
}
|
||||
MAP(size_t size)
|
||||
{
|
||||
pather =
|
||||
std::make_unique<micropather::MicroPather>(this, size, 6, true);
|
||||
}
|
||||
|
||||
~MAP()
|
||||
{
|
||||
return inactives[connection];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "reclasses.hpp"
|
||||
namespace re
|
||||
{
|
||||
|
||||
@ -26,4 +26,14 @@ public:
|
||||
int BRequestJoinPlayer(CSteamID steamid);
|
||||
static bool BInQueue(CTFPartyClient *this_);
|
||||
};
|
||||
class ITFMatchGroupDescription
|
||||
{
|
||||
public:
|
||||
char pad0[4];
|
||||
int m_iID;
|
||||
char pad1[63];
|
||||
bool m_bForceCompetitiveSettings;
|
||||
};
|
||||
|
||||
ITFMatchGroupDescription *GetMatchGroupDescription(int &idx);
|
||||
} // namespace re
|
||||
|
@ -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();
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "common.hpp"
|
||||
|
||||
#include "C_BaseEntity.hpp"
|
||||
#include "ITFGroupMatchCriteria.hpp"
|
||||
#include "CTFPlayerShared.hpp"
|
||||
#include "C_BasePlayer.hpp"
|
||||
#include "C_BaseCombatWeapon.hpp"
|
||||
|
@ -57,24 +57,26 @@ public:
|
||||
setInternal(key);
|
||||
}
|
||||
|
||||
Variable &operator=(const std::string &string)
|
||||
// Variable & causes segfault with gcc optimizations + these dont even
|
||||
// return anything
|
||||
void operator=(const std::string &string)
|
||||
{
|
||||
fromString(string);
|
||||
}
|
||||
|
||||
Variable &reset()
|
||||
void reset()
|
||||
{
|
||||
setInternal(Key{});
|
||||
}
|
||||
|
||||
Variable &key(SDL_Scancode key)
|
||||
void key(SDL_Scancode key)
|
||||
{
|
||||
Key k{};
|
||||
k.scan = key;
|
||||
setInternal(k);
|
||||
}
|
||||
|
||||
Variable &mouse(int mouse_key)
|
||||
void mouse(int mouse_key)
|
||||
{
|
||||
Key k{};
|
||||
k.mouse = mouse_key;
|
||||
@ -139,4 +141,4 @@ protected:
|
||||
std::string string{};
|
||||
Key value{};
|
||||
};
|
||||
} // namespace settings
|
||||
} // namespace settings
|
||||
|
@ -14,5 +14,6 @@ void startQueue();
|
||||
void leaveQueue();
|
||||
void disconnectAndAbandon();
|
||||
void abandon();
|
||||
bool isMMBanned();
|
||||
int getQueue();
|
||||
} // namespace tfmm
|
||||
|
@ -42,6 +42,19 @@ public:
|
||||
virtual TraceType_t GetTraceType() const;
|
||||
};
|
||||
|
||||
class FilterNoEntity : public ITraceFilter
|
||||
{
|
||||
public:
|
||||
IClientEntity *m_pSelf;
|
||||
|
||||
public:
|
||||
virtual ~FilterNoEntity();
|
||||
FilterNoEntity();
|
||||
virtual bool ShouldHitEntity(IHandleEntity *entity, int mask);
|
||||
void SetSelf(IClientEntity *self);
|
||||
virtual TraceType_t GetTraceType() const;
|
||||
};
|
||||
|
||||
class FilterPenetration : public ITraceFilter
|
||||
{
|
||||
public:
|
||||
@ -59,5 +72,6 @@ public:
|
||||
|
||||
extern FilterDefault filter_default;
|
||||
extern FilterNoPlayer filter_no_player;
|
||||
extern FilterNoEntity filter_no_entity;
|
||||
extern FilterPenetration filter_penetration;
|
||||
} // namespace trace
|
||||
|
@ -11,11 +11,11 @@ rm ../install-all # remove install file
|
||||
# Install base Dependencies
|
||||
#
|
||||
if [ -f "/etc/arch-release" ]; then
|
||||
sudo pacman -S --needed --noconfirm boost cmake make lib32-openssl lib32-libpng gcc gdb lib32-sdl2 lib32-glew freetype2 rsync
|
||||
sudo pacman -S --needed --noconfirm boost cmake make lib32-libpng gcc gdb lib32-sdl2 lib32-glew freetype2 rsync
|
||||
else
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
|
||||
sudo apt update
|
||||
sudo apt install build-essential git gcc-multilib g++-multilib software-properties-common gcc-snapshot g++-7-multilib gcc-7 g++-7 libssl-dev:i386 libboost-all-dev libc6-dev:i386 gdb libsdl2-dev libglew-dev:i386 libglew-dev libfreetype6-dev libfreetype6-dev:i386 cmake libpng-dev libssl-dev cmake gcc-multilib g++-multilib -y
|
||||
sudo apt install build-essential git gcc-multilib g++-multilib software-properties-common gcc-snapshot g++-7-multilib gcc-7 g++-7 libboost-all-dev libc6-dev:i386 gdb libsdl2-dev libglew-dev:i386 libglew-dev libfreetype6-dev libfreetype6-dev:i386 cmake libpng-dev cmake gcc-multilib g++-multilib -y
|
||||
fi
|
||||
#
|
||||
# Update cathook
|
||||
|
@ -13,7 +13,6 @@ target_sources(cathook PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}/hitrate.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/hooks.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/hoovy.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/https_request.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/ipc.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/itemtypes.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/localplayer.cpp"
|
||||
|
@ -120,6 +120,20 @@ void NetVars::Init()
|
||||
"DT_TFSniperRifle", "SniperRifleLocalData", "m_flChargedDamage");
|
||||
this->iUpgradeLevel =
|
||||
gNetvars.get_offset("DT_BaseObject", "m_iUpgradeLevel");
|
||||
this->m_hBuilder = gNetvars.get_offset("DT_BaseObject", "m_hBuilder");
|
||||
this->m_bBuilding = gNetvars.get_offset("DT_BaseObject", "m_hBuilding");
|
||||
this->m_iObjectType =
|
||||
gNetvars.get_offset("DT_BaseObject", "m_iObjectType");
|
||||
this->m_iTeleState =
|
||||
gNetvars.get_offset("DT_ObjectTeleporter", "m_iState");
|
||||
this->m_flTeleRechargeTime =
|
||||
gNetvars.get_offset("DT_ObjectTeleporter", "m_flRechargeTime");
|
||||
this->m_flTeleCurrentRechargeDuration = gNetvars.get_offset(
|
||||
"DT_ObjectTeleporter", "m_flCurrentRechargeDuration");
|
||||
this->m_iTeleTimesUsed =
|
||||
gNetvars.get_offset("DT_ObjectTeleporter", "m_iTimesUsed");
|
||||
this->m_flTeleYawToExit =
|
||||
gNetvars.get_offset("DT_ObjectTeleporter", "m_flYawToExit");
|
||||
this->iPipeType =
|
||||
gNetvars.get_offset("DT_TFProjectile_Pipebomb", "m_iType");
|
||||
this->iBuildingHealth =
|
||||
|
11
src/hack.cpp
11
src/hack.cpp
@ -403,6 +403,17 @@ free(logname);*/
|
||||
logging::Info("Initializer stack done");
|
||||
|
||||
hack::initialized = true;
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
re::ITFMatchGroupDescription *desc = re::GetMatchGroupDescription(i);
|
||||
if (!desc || desc->m_iID > 9) // ID's over 9 are invalid
|
||||
continue;
|
||||
if (desc->m_bForceCompetitiveSettings)
|
||||
{
|
||||
desc->m_bForceCompetitiveSettings = false;
|
||||
logging::Info("Bypassed force competitive cvars!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hack::Think()
|
||||
|
@ -353,7 +353,7 @@ CachedEntity *RetrieveBestTarget(bool aimkey_state)
|
||||
target_last = nullptr;
|
||||
target_eid = -1;
|
||||
|
||||
float target_highest_score, scr;
|
||||
float target_highest_score, scr = 0.0f;
|
||||
CachedEntity *ent;
|
||||
CachedEntity *target_highest_ent = 0;
|
||||
target_highest_score = -256;
|
||||
|
@ -79,26 +79,46 @@ void updateSearch()
|
||||
}
|
||||
}*/
|
||||
if (!auto_queue)
|
||||
{
|
||||
#if not ENABLE_VISUALS
|
||||
req_timer.update();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (g_IEngine->IsInGame())
|
||||
return;
|
||||
|
||||
static uintptr_t addr =
|
||||
gSignatures.GetClientSignature("C7 04 24 ? ? ? ? 8D 7D ? 31 F6");
|
||||
static uintptr_t offset0 = uintptr_t(*(uintptr_t *) (addr + 0x3));
|
||||
static uintptr_t offset1 = gSignatures.GetClientSignature(
|
||||
"55 89 E5 83 EC ? 8B 45 ? 8B 80 ? ? ? ? 85 C0 74 ? C7 44 24 ? ? ? ? ? "
|
||||
"89 04 24 E8 ? ? ? ? 85 C0 74 ? 8B 40");
|
||||
typedef int (*GetPendingInvites_t)(uintptr_t);
|
||||
GetPendingInvites_t GetPendingInvites = GetPendingInvites_t(offset1);
|
||||
int invites = GetPendingInvites(offset0);
|
||||
re::CTFGCClientSystem *gc = re::CTFGCClientSystem::GTFGCClientSystem();
|
||||
re::CTFPartyClient *pc = re::CTFPartyClient::GTFPartyClient();
|
||||
if (current_user_cmd && gc && gc->BConnectedToMatchServer(false) &&
|
||||
gc->BHaveLiveMatch())
|
||||
{
|
||||
#if not ENABLE_VISUALS
|
||||
req_timer.update();
|
||||
#endif
|
||||
tfmm::leaveQueue();
|
||||
}
|
||||
if (gc && !gc->BConnectedToMatchServer(false) &&
|
||||
queuetime.test_and_set(10 * 1000 * 60) && !gc->BHaveLiveMatch())
|
||||
tfmm::leaveQueue();
|
||||
if (gc && !gc->BConnectedToMatchServer(false) && !gc->BHaveLiveMatch())
|
||||
if (gc && !gc->BConnectedToMatchServer(false) && !gc->BHaveLiveMatch() &&
|
||||
!invites)
|
||||
if (!(pc && pc->BInQueueForMatchGroup(tfmm::getQueue())))
|
||||
{
|
||||
logging::Info("Starting queue");
|
||||
logging::Info("Starting queue, Invites %d", invites);
|
||||
tfmm::startQueue();
|
||||
}
|
||||
#if LAGBOT_MODE
|
||||
if (req_timer.test_and_set(1800000))
|
||||
#if not ENABLE_VISUALS
|
||||
if (req_timer.test_and_set(600000))
|
||||
{
|
||||
logging::Info("Stuck in queue, segfaulting");
|
||||
*(int *) nullptr;
|
||||
|
@ -118,7 +118,8 @@ void update_catbot_list()
|
||||
strcasestr(info.name, "zCat") ||
|
||||
strcasestr(info.name, "lagger bot") ||
|
||||
strcasestr(info.name, "zLag-bot") ||
|
||||
strcasestr(info.name, "crash-bot"))
|
||||
strcasestr(info.name, "crash-bot") ||
|
||||
strcasestr(info.name, "reichstagbot"))
|
||||
{
|
||||
if (human_detecting_map.find(info.friendsID) ==
|
||||
human_detecting_map.end())
|
||||
|
@ -351,7 +351,7 @@ void _FASTCALL emoji(CachedEntity *ent)
|
||||
if (emoji_esp_scaling && (size < *emoji_min_size))
|
||||
size = *emoji_min_size;
|
||||
player_info_s info{};
|
||||
unsigned int steamID;
|
||||
unsigned int steamID = 0;
|
||||
unsigned int steamidarray[32]{};
|
||||
bool hascall = false;
|
||||
steamidarray[0] = 479487126;
|
||||
|
@ -61,7 +61,7 @@ void draw()
|
||||
Vector out;
|
||||
if (draw::WorldToScreen(hitp[i], out))
|
||||
{
|
||||
float size;
|
||||
float size = 0.0f;
|
||||
Vector pout, pout2;
|
||||
if (draw::WorldToScreen(minp[i], pout) &&
|
||||
draw::WorldToScreen(maxp[i], pout2))
|
||||
|
@ -233,9 +233,13 @@ void CreateMove()
|
||||
}
|
||||
|
||||
#if ENABLE_VISUALS
|
||||
|
||||
// Timer ussr{};
|
||||
void DrawText()
|
||||
{
|
||||
/*if (ussr.test_and_set(207000))
|
||||
{
|
||||
g_ISurface->PlaySound()
|
||||
}*/
|
||||
if (god_mode)
|
||||
for (int i = 0; i < 40000; i++)
|
||||
{
|
||||
@ -255,7 +259,7 @@ void DrawText()
|
||||
{
|
||||
// Get Color and set opacity to %50
|
||||
colors::rgba_t gaybow = colors::FromHSL(
|
||||
fabs(sin((g_GlobalVars->curtime / 2.0f) + (i / 1.41241))) *
|
||||
fabs(sin((g_GlobalVars->curtime / 2.0f) + (i / 1.41241f))) *
|
||||
360.0f,
|
||||
0.85f, 0.9f);
|
||||
gaybow.a = .5;
|
||||
|
@ -1,6 +1,7 @@
|
||||
//
|
||||
// Created by bencat07 on 17.08.18.
|
||||
//
|
||||
#include <hacks/Backtrack.hpp>
|
||||
#include "common.hpp"
|
||||
#include "navparser.hpp"
|
||||
#include "FollowBot.hpp"
|
||||
@ -11,8 +12,11 @@ namespace hacks::tf2::NavBot
|
||||
static settings::Bool enable("navbot.enable", "false");
|
||||
static settings::Bool spy_mode("navbot.spy-mode", "false");
|
||||
static settings::Bool heavy_mode("navbot.heavy-mode", "false");
|
||||
static settings::Bool engi_mode("navbot.engi-mode", "false");
|
||||
static settings::Bool primary_only("navbot.primary-only", "true");
|
||||
|
||||
static settings::Bool target_sentry{ "navbot.target-sentry", "true" };
|
||||
static settings::Bool take_tele{ "navbot.take-teleporters", "true" };
|
||||
static settings::Bool enable_fb{ "navbot.medbot", "false" };
|
||||
static settings::Bool roambot{ "navbot.roaming", "true" };
|
||||
static settings::Float follow_activation{ "navbot.max-range", "1000" };
|
||||
@ -46,9 +50,7 @@ void checkAFK()
|
||||
if (CE_BAD(entity))
|
||||
continue;
|
||||
if (!CE_VECTOR(entity, netvar.vVelocity).IsZero(60.0f))
|
||||
{
|
||||
afkTicks[i].update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +58,9 @@ bool HasLowAmmo()
|
||||
{
|
||||
int *weapon_list =
|
||||
(int *) ((unsigned) (RAW_ENT(LOCAL_E)) + netvar.hMyWeapons);
|
||||
if (g_pLocalPlayer->holding_sniper_rifle &&
|
||||
CE_INT(LOCAL_E, netvar.m_iAmmo + 4) <= 5)
|
||||
return true;
|
||||
for (int i = 0; weapon_list[i]; i++)
|
||||
{
|
||||
int handle = weapon_list[i];
|
||||
@ -63,10 +68,9 @@ bool HasLowAmmo()
|
||||
if (eid >= 32 && eid <= HIGHEST_ENTITY)
|
||||
{
|
||||
IClientEntity *weapon = g_IEntityList->GetClientEntity(eid);
|
||||
if (weapon and
|
||||
re::C_BaseCombatWeapon::IsBaseCombatWeapon(weapon) and
|
||||
re::C_TFWeaponBase::UsesPrimaryAmmo(weapon) and
|
||||
not re::C_TFWeaponBase::HasPrimaryAmmo(weapon))
|
||||
if (weapon and re::C_BaseCombatWeapon::IsBaseCombatWeapon(weapon) &&
|
||||
re::C_TFWeaponBase::UsesPrimaryAmmo(weapon) &&
|
||||
!re::C_TFWeaponBase::HasPrimaryAmmo(weapon))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -78,6 +82,24 @@ bool HasLowHealth()
|
||||
return float(LOCAL_E->m_iHealth()) / float(LOCAL_E->m_iMaxHealth()) < 0.64;
|
||||
}
|
||||
|
||||
CachedEntity *nearestSentry()
|
||||
{
|
||||
float bestscr = FLT_MAX;
|
||||
CachedEntity *bestent = nullptr;
|
||||
for (int i = 0; i < HIGHEST_ENTITY; i++)
|
||||
{
|
||||
CachedEntity *ent = ENTITY(i);
|
||||
if (CE_BAD(ent) || ent->m_iClassID() != CL_CLASS(CObjectSentrygun) ||
|
||||
ent->m_iTeam() == LOCAL_E->m_iTeam())
|
||||
continue;
|
||||
if (ent->m_flDistance() < bestscr)
|
||||
{
|
||||
bestscr = ent->m_flDistance();
|
||||
bestent = ent;
|
||||
}
|
||||
}
|
||||
return bestent;
|
||||
}
|
||||
CachedEntity *nearestHealth()
|
||||
{
|
||||
float bestscr = FLT_MAX;
|
||||
@ -120,52 +142,82 @@ CachedEntity *nearestAmmo()
|
||||
}
|
||||
return bestent;
|
||||
}
|
||||
int last_tar = -1;
|
||||
CachedEntity *NearestEnemy()
|
||||
{
|
||||
float bestscr = FLT_MAX;
|
||||
CachedEntity *bestent = nullptr;
|
||||
for (int i = 0; i < g_IEngine->GetMaxClients(); i++)
|
||||
if (last_tar != -1 && CE_GOOD(ENTITY(last_tar)))
|
||||
return ENTITY(last_tar);
|
||||
else
|
||||
last_tar = -1;
|
||||
if (last_tar == -1 || nav::ReadyForCommands)
|
||||
{
|
||||
CachedEntity *ent = ENTITY(i);
|
||||
if (CE_BAD(ent) || ent->m_Type() != ENTITY_PLAYER)
|
||||
continue;
|
||||
if (ent == LOCAL_E || !ent->m_bAlivePlayer() ||
|
||||
ent->m_iTeam() == LOCAL_E->m_iTeam())
|
||||
continue;
|
||||
float scr = ent->m_flDistance();
|
||||
if (g_pPlayerResource->GetClass(ent) == tf_engineer)
|
||||
scr *= 5.0f;
|
||||
if (g_pPlayerResource->GetClass(ent) == tf_pyro)
|
||||
scr *= 7.0f;
|
||||
if (scr < bestscr)
|
||||
float bestscr = FLT_MAX;
|
||||
CachedEntity *bestent = nullptr;
|
||||
for (int i = 0; i < g_IEngine->GetMaxClients(); i++)
|
||||
{
|
||||
bestscr = scr;
|
||||
bestent = ent;
|
||||
CachedEntity *ent = ENTITY(i);
|
||||
if (CE_BAD(ent) || ent->m_Type() != ENTITY_PLAYER)
|
||||
continue;
|
||||
if (ent == LOCAL_E || !ent->m_bAlivePlayer() ||
|
||||
ent->m_iTeam() == LOCAL_E->m_iTeam())
|
||||
continue;
|
||||
float scr = ent->m_flDistance();
|
||||
if (g_pPlayerResource->GetClass(ent) == tf_engineer)
|
||||
scr *= 5.0f;
|
||||
if (g_pPlayerResource->GetClass(ent) == tf_pyro)
|
||||
scr *= 7.0f;
|
||||
if (scr < bestscr)
|
||||
{
|
||||
bestscr = scr;
|
||||
bestent = ent;
|
||||
}
|
||||
}
|
||||
if (CE_BAD(bestent))
|
||||
last_tar = -1;
|
||||
else
|
||||
last_tar = bestent->m_IDX;
|
||||
return bestent;
|
||||
}
|
||||
return bestent;
|
||||
return nullptr;
|
||||
}
|
||||
Timer cdr{};
|
||||
Timer cd2{};
|
||||
Timer cd3{};
|
||||
Timer engi_spot_cd{};
|
||||
std::vector<Vector> preferred_sniper_spots;
|
||||
std::vector<Vector> sniper_spots;
|
||||
std::vector<Vector> nest_spots;
|
||||
void Init()
|
||||
{
|
||||
sniper_spots.clear();
|
||||
preferred_sniper_spots.clear();
|
||||
nest_spots.clear();
|
||||
for (auto area : nav::areas)
|
||||
{
|
||||
if (area.m_attributeFlags & NAV_MESH_NO_HOSTAGES)
|
||||
preferred_sniper_spots.push_back(area.m_center);
|
||||
if (area.m_attributeFlags & NAV_MESH_RUN)
|
||||
nest_spots.push_back(area.m_center);
|
||||
for (auto hide : area.m_hidingSpots)
|
||||
if (hide.IsGoodSniperSpot() || hide.IsIdealSniperSpot() ||
|
||||
hide.IsExposed())
|
||||
sniper_spots.push_back(hide.m_pos);
|
||||
logging::Info("%d", sniper_spots.size());
|
||||
}
|
||||
logging::Info("Sniper spots: %d, Manual Sniper Spots: %d, Sentry Spots: %d",
|
||||
sniper_spots.size(), preferred_sniper_spots.size(),
|
||||
nest_spots.size());
|
||||
}
|
||||
|
||||
std::unordered_map<int, int> priority_spots;
|
||||
void initonce()
|
||||
{
|
||||
for (int i = 0; i < afkTicks.size(); i++)
|
||||
afkTicks[i].update();
|
||||
priority_spots.clear();
|
||||
cdr.update();
|
||||
cd2.update();
|
||||
cd3.update();
|
||||
engi_spot_cd.update();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -182,7 +234,7 @@ void UpdateSlot()
|
||||
{
|
||||
int slot = re::C_BaseCombatWeapon::GetSlot(weapon);
|
||||
int newslot = 1;
|
||||
if (spy_mode)
|
||||
if (spy_mode || engi_mode)
|
||||
newslot = 3;
|
||||
if (slot != newslot - 1)
|
||||
g_IEngine->ClientCmd_Unrestricted(
|
||||
@ -190,6 +242,174 @@ void UpdateSlot()
|
||||
}
|
||||
}
|
||||
}
|
||||
enum BuildingNum
|
||||
{
|
||||
DISPENSER = 0,
|
||||
TELEPORT_ENT,
|
||||
SENTRY,
|
||||
TELEPORT_EXT,
|
||||
};
|
||||
std::vector<int> GetBuildings()
|
||||
{
|
||||
float bestscr = FLT_MAX;
|
||||
std::vector<int> buildings;
|
||||
for (int i = 0; i < HIGHEST_ENTITY; i++)
|
||||
{
|
||||
CachedEntity *ent = ENTITY(i);
|
||||
if (CE_BAD(ent))
|
||||
continue;
|
||||
if (ent->m_Type() != ENTITY_BUILDING)
|
||||
continue;
|
||||
if ((CE_INT(ent, netvar.m_hBuilder) & 0xFFF) !=
|
||||
g_pLocalPlayer->entity_idx)
|
||||
continue;
|
||||
if (ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin()) < bestscr)
|
||||
{
|
||||
buildings.push_back(i);
|
||||
bestscr = ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin());
|
||||
}
|
||||
}
|
||||
return buildings;
|
||||
}
|
||||
int cost[4] = { 100, 50, 130, 50 };
|
||||
int GetBestBuilding(int metal)
|
||||
{
|
||||
bool hasSentry = false;
|
||||
bool hasDispenser = false;
|
||||
if (!GetBuildings().empty())
|
||||
for (auto build : GetBuildings())
|
||||
{
|
||||
CachedEntity *building = ENTITY(build);
|
||||
if (building->m_iClassID() == CL_CLASS(CObjectSentrygun))
|
||||
hasSentry = true;
|
||||
if (building->m_iClassID() == CL_CLASS(CObjectDispenser))
|
||||
hasDispenser = true;
|
||||
}
|
||||
if (metal >= cost[SENTRY] && !hasSentry)
|
||||
return SENTRY;
|
||||
else if (metal >= cost[DISPENSER] && !hasDispenser)
|
||||
return DISPENSER;
|
||||
if (hasSentry && hasDispenser)
|
||||
return 3;
|
||||
return -1;
|
||||
}
|
||||
int GetClosestBuilding()
|
||||
{
|
||||
float bestscr = FLT_MAX;
|
||||
int BestBuilding = -1;
|
||||
for (int i = 0; i < HIGHEST_ENTITY; i++)
|
||||
{
|
||||
CachedEntity *ent = ENTITY(i);
|
||||
if (CE_BAD(ent))
|
||||
continue;
|
||||
if (ent->m_Type() != ENTITY_BUILDING)
|
||||
continue;
|
||||
if ((CE_INT(ent, netvar.m_hBuilder) & 0xFFF) !=
|
||||
g_pLocalPlayer->entity_idx)
|
||||
continue;
|
||||
if (ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin()) < bestscr)
|
||||
{
|
||||
BestBuilding = i;
|
||||
bestscr = ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin());
|
||||
}
|
||||
}
|
||||
return BestBuilding;
|
||||
}
|
||||
int GetClosestTeleporter()
|
||||
{
|
||||
float bestscr = FLT_MAX;
|
||||
int BestBuilding = -1;
|
||||
for (int i = 0; i < HIGHEST_ENTITY; i++)
|
||||
{
|
||||
CachedEntity *ent = ENTITY(i);
|
||||
if (CE_BAD(ent))
|
||||
continue;
|
||||
if (ent->m_iClassID() != CL_CLASS(CObjectTeleporter))
|
||||
continue;
|
||||
if (ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin()) < bestscr)
|
||||
{
|
||||
BestBuilding = i;
|
||||
bestscr = ent->m_vecOrigin().DistTo(LOCAL_E->m_vecOrigin());
|
||||
}
|
||||
}
|
||||
return BestBuilding;
|
||||
}
|
||||
bool NavToSentry(int priority)
|
||||
{
|
||||
CachedEntity *Sentry = nearestSentry();
|
||||
if (CE_BAD(Sentry))
|
||||
return false;
|
||||
int num = nav::FindNearestValid(GetBuildingPosition(Sentry));
|
||||
if (num == -1)
|
||||
return false;
|
||||
auto area = nav::areas[num];
|
||||
if (nav::NavTo(area.m_center, false, true, priority))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool NavToSniperSpot(int priority)
|
||||
{
|
||||
Vector random_spot{};
|
||||
if (!sniper_spots.size() && !preferred_sniper_spots.size())
|
||||
return false;
|
||||
bool use_preferred = !preferred_sniper_spots.empty();
|
||||
auto snip_spot = use_preferred ? preferred_sniper_spots : sniper_spots;
|
||||
bool toret = false;
|
||||
|
||||
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;
|
||||
}
|
||||
CatCommand debug_tele("navbot_debug", "debug", []() {
|
||||
int idx = GetClosestBuilding();
|
||||
if (idx == -1)
|
||||
return;
|
||||
CachedEntity *ent = ENTITY(idx);
|
||||
if (CE_BAD(ent))
|
||||
return;
|
||||
logging::Info(
|
||||
"%d %d %d %f %f %d %f %f %f", CE_INT(ent, netvar.m_iObjectType),
|
||||
CE_INT(ent, netvar.m_bBuilding), CE_INT(ent, netvar.m_iTeleState),
|
||||
CE_FLOAT(ent, netvar.m_flTeleRechargeTime),
|
||||
CE_FLOAT(ent, netvar.m_flTeleCurrentRechargeDuration),
|
||||
CE_INT(ent, netvar.m_iTeleTimesUsed),
|
||||
CE_FLOAT(ent, netvar.m_flTeleYawToExit), g_GlobalVars->curtime,
|
||||
g_GlobalVars->curtime * g_GlobalVars->interval_per_tick);
|
||||
});
|
||||
int follow_target = 0;
|
||||
void CreateMove()
|
||||
{
|
||||
@ -203,56 +423,219 @@ void CreateMove()
|
||||
{
|
||||
CachedEntity *med = nearestHealth();
|
||||
if (CE_GOOD(med))
|
||||
{
|
||||
nav::NavTo(med->m_vecOrigin(), true, true, 7);
|
||||
}
|
||||
}
|
||||
if (HasLowAmmo() && cdr.test_and_set(5000))
|
||||
{
|
||||
CachedEntity *ammo = nearestAmmo();
|
||||
if (CE_GOOD(ammo))
|
||||
{
|
||||
nav::NavTo(ammo->m_vecOrigin(), true, true, 6);
|
||||
}
|
||||
if ((!HasLowHealth() && nav::priority == 7) ||
|
||||
(!HasLowAmmo() && nav::priority == 6))
|
||||
nav::clearInstructions();
|
||||
static int waittime = (spy_mode || heavy_mode || engi_mode) ? 100 : 2000;
|
||||
if (*take_tele)
|
||||
{
|
||||
int idx = GetClosestTeleporter();
|
||||
if (idx != -1)
|
||||
{
|
||||
CachedEntity *ent = ENTITY(idx);
|
||||
if (CE_GOOD(ent) && ent->m_flDistance() < 300.0f)
|
||||
if (CE_FLOAT(ent, netvar.m_flTeleYawToExit) &&
|
||||
CE_FLOAT(ent, netvar.m_flTeleRechargeTime) <
|
||||
g_GlobalVars->curtime)
|
||||
{
|
||||
waittime = 1000;
|
||||
cd3.update();
|
||||
nav::NavTo(GetBuildingPosition(ent), false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (enable)
|
||||
{
|
||||
if (!nav::ReadyForCommands && !spy_mode && !heavy_mode)
|
||||
if (!nav::ReadyForCommands && !spy_mode && !heavy_mode && !engi_mode)
|
||||
cd3.update();
|
||||
bool isready = (spy_mode || heavy_mode) ? 1 : nav::ReadyForCommands;
|
||||
int waittime = (spy_mode || heavy_mode) ? 100 : 5000;
|
||||
if (target_sentry && NavToSentry(3))
|
||||
return;
|
||||
bool isready = (spy_mode || heavy_mode || engi_mode)
|
||||
? true
|
||||
: nav::ReadyForCommands;
|
||||
if (isready && cd3.test_and_set(waittime))
|
||||
{
|
||||
if (!spy_mode && !heavy_mode)
|
||||
waittime = (spy_mode || heavy_mode || engi_mode) ? 100 : 2000;
|
||||
if (!spy_mode && !heavy_mode && !engi_mode)
|
||||
{
|
||||
cd3.update();
|
||||
Vector random_spot;
|
||||
if (cd2.test_and_set(5000))
|
||||
Init();
|
||||
if (!sniper_spots.size())
|
||||
return;
|
||||
int rng = rand() % sniper_spots.size();
|
||||
random_spot = sniper_spots.at(rng);
|
||||
if (random_spot.z)
|
||||
nav::NavTo(random_spot, true, true);
|
||||
if (!NavToSniperSpot(5))
|
||||
waittime = 1;
|
||||
}
|
||||
else if (cdr.check(5000))
|
||||
else if (!engi_mode)
|
||||
{
|
||||
CachedEntity *tar = NearestEnemy();
|
||||
if (CE_BAD(tar))
|
||||
if (CE_BAD(tar) && last_tar == -1 && nav::ReadyForCommands)
|
||||
{
|
||||
Vector random_spot;
|
||||
if (cd2.test_and_set(5000))
|
||||
Init();
|
||||
if (!sniper_spots.size())
|
||||
return;
|
||||
int rng = rand() % sniper_spots.size();
|
||||
random_spot = sniper_spots.at(rng);
|
||||
if (random_spot.z)
|
||||
nav::NavTo(random_spot, false);
|
||||
return;
|
||||
if (!NavToSniperSpot(4))
|
||||
waittime = 1;
|
||||
}
|
||||
nav::NavTo(tar->m_vecOrigin(), false);
|
||||
if (CE_GOOD(tar))
|
||||
{
|
||||
if (!spy_mode ||
|
||||
!hacks::shared::backtrack::isBacktrackEnabled)
|
||||
{
|
||||
if (!nav::NavTo(tar->m_vecOrigin(), false))
|
||||
last_tar = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto i : hacks::shared::backtrack::headPositions
|
||||
[tar->m_IDX])
|
||||
{
|
||||
if (!hacks::shared::backtrack::ValidTick(i, tar))
|
||||
continue;
|
||||
nav::NavTo(i.entorigin, false, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Engi Mode
|
||||
else
|
||||
{
|
||||
// Init things
|
||||
if (cd2.test_and_set(5000))
|
||||
Init();
|
||||
// If No spots set just return
|
||||
if (nest_spots.empty())
|
||||
return;
|
||||
// Get Metal (offset of MAX metal is +8 and current metal +12)
|
||||
int metal = CE_INT(LOCAL_E, netvar.m_iAmmo + 12);
|
||||
// Best spot storage
|
||||
static Vector best_spot{};
|
||||
// Get Best spot based on distance
|
||||
if (engi_spot_cd.test_and_set(10000))
|
||||
{
|
||||
float bestscr = FLT_MAX;
|
||||
for (auto spot : nest_spots)
|
||||
{
|
||||
if (spot.DistTo(LOCAL_E->m_vecOrigin()) < bestscr)
|
||||
{
|
||||
bestscr = spot.DistTo(LOCAL_E->m_vecOrigin());
|
||||
best_spot = spot;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nav::priority == 1)
|
||||
{
|
||||
CachedEntity *ammo = nearestAmmo();
|
||||
if (CE_GOOD(ammo))
|
||||
{
|
||||
nav::NavTo(ammo->m_vecOrigin(), false, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If Near The best spot and ready for commands
|
||||
if (best_spot.DistTo(LOCAL_E->m_vecOrigin()) < 200.0f &&
|
||||
(nav::ReadyForCommands || nav::priority == 1))
|
||||
{
|
||||
// Get the closest Building
|
||||
int ClosestBuilding = GetClosestBuilding();
|
||||
// If A Building was found
|
||||
if (ClosestBuilding != -1)
|
||||
{
|
||||
CachedEntity *ent = ENTITY(ClosestBuilding);
|
||||
// If we have more than 25 metal and the building is
|
||||
// damaged or not fully upgraded hit it with the wrench
|
||||
if (metal > 25 &&
|
||||
(CE_INT(ent, netvar.iUpgradeLevel) < 3 ||
|
||||
CE_INT(ent, netvar.iBuildingHealth) <
|
||||
CE_INT(ent, netvar.iBuildingMaxHealth)))
|
||||
{
|
||||
auto collide = RAW_ENT(ent)->GetCollideable();
|
||||
Vector min =
|
||||
ent->m_vecOrigin() + collide->OBBMins();
|
||||
Vector max =
|
||||
ent->m_vecOrigin() + collide->OBBMaxs();
|
||||
// Distance check
|
||||
if (min.DistTo(g_pLocalPlayer->v_Eye) >
|
||||
re::C_TFWeaponBaseMelee::GetSwingRange(
|
||||
RAW_ENT(LOCAL_W)) &&
|
||||
max.DistTo(g_pLocalPlayer->v_Eye) >
|
||||
re::C_TFWeaponBaseMelee::GetSwingRange(
|
||||
RAW_ENT(LOCAL_W)) &&
|
||||
GetBuildingPosition(ent).DistTo(
|
||||
g_pLocalPlayer->v_Eye) >
|
||||
re::C_TFWeaponBaseMelee::GetSwingRange(
|
||||
RAW_ENT(LOCAL_W)))
|
||||
{
|
||||
float minf = min.DistTo(g_pLocalPlayer->v_Eye);
|
||||
float maxf = max.DistTo(g_pLocalPlayer->v_Eye);
|
||||
float center = GetBuildingPosition(ent).DistTo(
|
||||
g_pLocalPlayer->v_Eye);
|
||||
float closest =
|
||||
fminf(minf, fminf(maxf, center));
|
||||
Vector tonav =
|
||||
(minf == closest)
|
||||
? min
|
||||
: (maxf == closest)
|
||||
? max
|
||||
: GetBuildingPosition(ent);
|
||||
nav::NavTo(tonav, false, false);
|
||||
}
|
||||
Vector tr = GetBuildingPosition(ent) -
|
||||
g_pLocalPlayer->v_Eye;
|
||||
Vector angles;
|
||||
VectorAngles(tr, angles);
|
||||
// Clamping is important
|
||||
fClampAngle(angles);
|
||||
current_user_cmd->viewangles = angles;
|
||||
current_user_cmd->buttons |= IN_ATTACK;
|
||||
g_pLocalPlayer->bUseSilentAngles = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Get A building, Sentry > Dispenser
|
||||
int tobuild = GetBestBuilding(metal);
|
||||
// If not enough metal then Find ammo
|
||||
if (tobuild == -1)
|
||||
{
|
||||
CachedEntity *ammo = nearestAmmo();
|
||||
if (CE_GOOD(ammo))
|
||||
{
|
||||
nav::NavTo(ammo->m_vecOrigin(), false, true);
|
||||
return;
|
||||
}
|
||||
// Ammo is dormant, go and find it!
|
||||
else if (sniper_spots.size() && nav::ReadyForCommands)
|
||||
{
|
||||
if (cd2.test_and_set(5000))
|
||||
Init();
|
||||
if (!NavToSniperSpot(1))
|
||||
waittime = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Build Building
|
||||
else if (tobuild != 3)
|
||||
{
|
||||
// Make ENgi look slightly down
|
||||
current_user_cmd->viewangles.x = 20.0f;
|
||||
// Build buildings in a 360° angle around player
|
||||
current_user_cmd->viewangles.y = 90.0f * (tobuild + 1);
|
||||
// Build new one
|
||||
g_IEngine->ServerCmd(format("build ", tobuild).c_str(),
|
||||
true);
|
||||
current_user_cmd->buttons |= IN_ATTACK;
|
||||
g_pLocalPlayer->bUseSilentAngles = true;
|
||||
}
|
||||
}
|
||||
// If not near best spot then navigate to it
|
||||
else if (nav::ReadyForCommands)
|
||||
nav::NavTo(best_spot, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,8 +31,8 @@ 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);
|
||||
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
|
||||
selectBase();
|
||||
@ -53,10 +57,10 @@ void selectBase()
|
||||
// and check if they are close to each other (by looking for largest gap
|
||||
// between).
|
||||
|
||||
int bestGap = 0;
|
||||
double newClockRes = 1.0;
|
||||
int bestGap = 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,22 @@ 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 +127,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 +136,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 +151,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) +
|
||||
INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo();
|
||||
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,15 +165,15 @@ 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) +
|
||||
INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo();
|
||||
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);
|
||||
int seed = predictSeed(selected, tick, clockRes, SeedOffset);
|
||||
float 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",
|
||||
|
@ -115,8 +115,9 @@ void CreateMove()
|
||||
CachedEntity *ent = FindEntInSight(EffectiveTargetingRange());
|
||||
|
||||
// Check if can backtrack, shoot if we can
|
||||
if (!CanBacktrack() || hacks::shared::backtrack::isBacktrackEnabled)
|
||||
return;
|
||||
if (hacks::shared::backtrack::isBacktrackEnabled)
|
||||
if (!CanBacktrack())
|
||||
return;
|
||||
|
||||
// Check if dormant or null to prevent crashes
|
||||
if (CE_BAD(ent))
|
||||
|
@ -1107,19 +1107,29 @@ netvar.iHealth));
|
||||
|
||||
bool IsVectorVisible(Vector origin, Vector target, bool enviroment_only)
|
||||
{
|
||||
trace_t trace_visible;
|
||||
Ray_t ray;
|
||||
|
||||
trace::filter_no_player.SetSelf(RAW_ENT(g_pLocalPlayer->entity));
|
||||
ray.Init(origin, target);
|
||||
if (!enviroment_only)
|
||||
{
|
||||
trace_t trace_visible;
|
||||
Ray_t ray;
|
||||
|
||||
trace::filter_no_player.SetSelf(RAW_ENT(g_pLocalPlayer->entity));
|
||||
ray.Init(origin, target);
|
||||
g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_no_player,
|
||||
&trace_visible);
|
||||
return (trace_visible.fraction == 1.0f);
|
||||
}
|
||||
else
|
||||
g_ITrace->TraceRay(ray, 0x4200400B, &trace::filter_no_player,
|
||||
&trace_visible);
|
||||
{
|
||||
trace_t trace_visible;
|
||||
Ray_t ray;
|
||||
|
||||
return (trace_visible.fraction == 1.0f);
|
||||
trace::filter_no_entity.SetSelf(RAW_ENT(g_pLocalPlayer->entity));
|
||||
ray.Init(origin, target);
|
||||
g_ITrace->TraceRay(ray, MASK_SHOT_HULL, &trace::filter_no_entity,
|
||||
&trace_visible);
|
||||
return (trace_visible.fraction == 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void WhatIAmLookingAt(int *result_eindex, Vector *result_pos)
|
||||
|
@ -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;
|
||||
|
@ -11,9 +11,6 @@
|
||||
#include "HookedMethods.hpp"
|
||||
#include "MiscTemporary.hpp"
|
||||
#include "navparser.hpp"
|
||||
#if !LAGBOT_MODE
|
||||
#include "hacks/Backtrack.hpp"
|
||||
#endif
|
||||
|
||||
static settings::Bool halloween_mode{ "misc.force-halloween", "false" };
|
||||
static settings::Int skybox_changer{ "misc.skybox-override", "0" };
|
||||
|
@ -6,12 +6,36 @@
|
||||
*/
|
||||
#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);
|
||||
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
|
||||
|
@ -11,8 +11,8 @@ namespace hooked_methods
|
||||
DEFINE_HOOKED_METHOD(SendDatagram, int, INetChannel *ch, bf_write *buf)
|
||||
{
|
||||
#if !LAGBOT_MODE
|
||||
int in;
|
||||
int state;
|
||||
int in = 0;
|
||||
int state = 0;
|
||||
if (CE_GOOD(LOCAL_E))
|
||||
{
|
||||
in = ch->m_nInSequenceNr;
|
||||
|
@ -21,11 +21,11 @@ DEFINE_HOOKED_METHOD(Shutdown, void, INetChannel *this_, const char *reason)
|
||||
// This is a INetChannel hook - it SHOULDN'T be static because netchannel
|
||||
// changes.
|
||||
logging::Info("Disconnect: %s", reason);
|
||||
if (strstr(reason, "banned"))
|
||||
if (strstr(reason, "banned") || strstr(reason, "Generic_Kicked"))
|
||||
{
|
||||
if (die_if_vac)
|
||||
{
|
||||
logging::Info("VAC banned");
|
||||
logging::Info("VAC/Matchmaking banned");
|
||||
*(int *) 0 = 0;
|
||||
exit(1);
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ and no [])", [](const CCommand &args) {
|
||||
bool replaced = false;
|
||||
namespace hooked_methods
|
||||
{
|
||||
|
||||
Timer checkmmban{};
|
||||
DEFINE_HOOKED_METHOD(PaintTraverse, void, vgui::IPanel *this_,
|
||||
unsigned int panel, bool force, bool allow_force)
|
||||
{
|
||||
@ -96,21 +96,28 @@ DEFINE_HOOKED_METHOD(PaintTraverse, void, vgui::IPanel *this_,
|
||||
if (switcherido && spamdur && !joinspam.check(spamdur * 1000))
|
||||
{
|
||||
auto gc = re::CTFGCClientSystem::GTFGCClientSystem();
|
||||
if (!gc)
|
||||
goto label1;
|
||||
gc->JoinMMMatch();
|
||||
if (gc)
|
||||
gc->JoinMMMatch();
|
||||
}
|
||||
else if (!joinspam.check(spamdur * 1000) && spamdur)
|
||||
{
|
||||
INetChannel *ch = (INetChannel *) g_IEngine->GetNetChannelInfo();
|
||||
if (!ch)
|
||||
goto label1;
|
||||
ch->Shutdown("");
|
||||
if (ch)
|
||||
ch->Shutdown("");
|
||||
}
|
||||
}
|
||||
label1:
|
||||
scndwait++;
|
||||
switcherido = !switcherido;
|
||||
#if not ENABLE_VISUALS
|
||||
if (checkmmban.test_and_set(1000))
|
||||
{
|
||||
if (tfmm::isMMBanned())
|
||||
{
|
||||
*(int *) nullptr = 0;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*static bool replacedparty = false;
|
||||
static int callcnt = 0;
|
||||
if (party_bypass && !replacedparty && callcnt < 5)
|
||||
|
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* https_request.cpp
|
||||
*
|
||||
* Created on: Jul 23, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#include <core/logging.hpp>
|
||||
#include "https_request.hpp"
|
||||
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
namespace https
|
||||
{
|
||||
|
||||
SSL_CTX *ssl_context;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
RAII_HTTPS_Socket::RAII_HTTPS_Socket(const std::string &host) : hostname_(host)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
logging::Info("Initializing SSL");
|
||||
initialize();
|
||||
}
|
||||
sock_ = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock_ < 0)
|
||||
{
|
||||
throw std::runtime_error("Socket creation error");
|
||||
}
|
||||
host_ = gethostbyname(hostname_.c_str());
|
||||
if (not host_)
|
||||
{
|
||||
throw std::runtime_error("Could not resolve hostname: " + host);
|
||||
}
|
||||
memset(&addr_, 0, sizeof(addr_));
|
||||
addr_.sin_family = AF_INET;
|
||||
addr_.sin_port = htons(443);
|
||||
memcpy(&addr_.sin_addr.s_addr, host_->h_addr, host_->h_length);
|
||||
if (connect(sock_, (sockaddr *) &addr_, sizeof(addr_)) < 0)
|
||||
{
|
||||
close(sock_);
|
||||
sock_ = -1;
|
||||
throw std::runtime_error("Couldn't connect to host");
|
||||
}
|
||||
ssl_connect();
|
||||
}
|
||||
|
||||
RAII_HTTPS_Socket::~RAII_HTTPS_Socket()
|
||||
{
|
||||
ssl_die();
|
||||
if (sock_ >= 0)
|
||||
close(sock_);
|
||||
}
|
||||
|
||||
bool RAII_HTTPS_Socket::ssl_connect()
|
||||
{
|
||||
connection_ = SSL_new(ssl_context);
|
||||
SSL_set_fd(connection_, sock_);
|
||||
int ret = SSL_connect(connection_);
|
||||
if (ret != 1)
|
||||
{
|
||||
logging::Info("SSL connection error: %d, %d, %x\n", ret,
|
||||
SSL_get_error(connection_, ret), ERR_get_error());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RAII_HTTPS_Socket::ssl_die()
|
||||
{
|
||||
if (connection_)
|
||||
{
|
||||
SSL_free(connection_);
|
||||
connection_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::string RAII_HTTPS_Socket::get(const std::string &path)
|
||||
{
|
||||
constexpr size_t rq_size = 1024 * 8;
|
||||
constexpr size_t rs_size = 1024 * 1024;
|
||||
|
||||
std::unique_ptr<char> buffer_rq(new char[rq_size]),
|
||||
buffer_rs(new char[rs_size]);
|
||||
|
||||
memset(buffer_rq.get(), 0, rq_size);
|
||||
int rq_length = snprintf(buffer_rq.get(), rq_size,
|
||||
"GET %s HTTP/1.0\r\nHost: %s\r\n\r\n",
|
||||
path.c_str(), hostname_.c_str());
|
||||
int sent = 0;
|
||||
int chunk = 0;
|
||||
do
|
||||
{
|
||||
chunk =
|
||||
SSL_write(connection_, buffer_rq.get() + sent, rq_length - sent);
|
||||
if (chunk < 0)
|
||||
{
|
||||
throw std::runtime_error("Error writing to Secure Socket: " +
|
||||
std::to_string(ERR_get_error()));
|
||||
}
|
||||
else if (chunk == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
sent += chunk;
|
||||
} while (sent < rq_length);
|
||||
|
||||
memset(buffer_rs.get(), 0, rs_size);
|
||||
int total = rs_size - 1;
|
||||
int received = 0;
|
||||
do
|
||||
{
|
||||
chunk =
|
||||
SSL_read(connection_, buffer_rs.get() + received, total - received);
|
||||
if (chunk < 0)
|
||||
throw std::runtime_error("Error reading from socket");
|
||||
if (chunk == 0)
|
||||
break;
|
||||
received += chunk;
|
||||
} while (received < total);
|
||||
|
||||
if (received == total)
|
||||
throw std::runtime_error("Response too large");
|
||||
|
||||
return std::string(buffer_rs.get());
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
ssl_context = SSL_CTX_new(SSLv23_client_method());
|
||||
initialized = true;
|
||||
}
|
||||
} // namespace https
|
@ -8,124 +8,67 @@ std::vector<CNavArea> areas;
|
||||
bool init = false;
|
||||
static bool pathfinding = true;
|
||||
bool ReadyForCommands = false;
|
||||
inactivityTracker inactiveTracker;
|
||||
static settings::Bool enabled{ "misc.pathing", "true" };
|
||||
static settings::Bool draw{ "misc.pathing.draw", "false" };
|
||||
static std::atomic<bool> threadingFinished;
|
||||
|
||||
// Todo fix
|
||||
size_t FindInVector(size_t id)
|
||||
static std::unique_ptr<MAP> TF2MAP;
|
||||
|
||||
// Function to get place in Vector by connection ID
|
||||
// Todo: find an alternative for this, maybe a map for storing ptrs to the
|
||||
// std::vector?
|
||||
int FindInVector(size_t id)
|
||||
{
|
||||
for (size_t i = 0; i < areas.size(); i++)
|
||||
for (int i = 0; i < areas.size(); i++)
|
||||
{
|
||||
if (areas.at(i).m_id == id)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct MAP : public micropather::Graph
|
||||
static int bestarea = -1;
|
||||
Timer reselect{};
|
||||
int FindNearestValid(Vector vec)
|
||||
{
|
||||
std::unique_ptr<micropather::MicroPather> pather;
|
||||
// Function to check if a connection is ignored
|
||||
bool IsIgnored(size_t currState, size_t connectionID)
|
||||
if (reselect.test_and_set(500))
|
||||
{
|
||||
if (inactiveTracker.getTime({ currState, connectionID }) >= 5000)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
Vector GetClosestCornerToArea(CNavArea *CornerOf, CNavArea *Target)
|
||||
{
|
||||
std::array<Vector, 4> corners;
|
||||
corners.at(0) = CornerOf->m_nwCorner; // NW
|
||||
corners.at(1) = CornerOf->m_seCorner; // SE
|
||||
corners.at(2) = Vector{ CornerOf->m_seCorner.x, CornerOf->m_nwCorner.y,
|
||||
CornerOf->m_nwCorner.z }; // NE
|
||||
corners.at(3) = Vector{ CornerOf->m_nwCorner.x, CornerOf->m_seCorner.y,
|
||||
CornerOf->m_seCorner.z }; // SW
|
||||
|
||||
Vector bestVec;
|
||||
float bestDist = FLT_MAX;
|
||||
|
||||
for (size_t i = 0; i < corners.size(); i++)
|
||||
float bestscr = FLT_MAX;
|
||||
if (bestarea != -1)
|
||||
{
|
||||
float dist = corners.at(i).DistTo(Target->m_center);
|
||||
if (dist < bestDist)
|
||||
bool success = false;
|
||||
Vector area = areas[bestarea].m_center;
|
||||
area.z += 72.0f;
|
||||
if (!TF2MAP->inactiveTracker.sentryAreas[bestarea])
|
||||
{
|
||||
bestVec = corners.at(i);
|
||||
bestDist = dist;
|
||||
float scr = area.DistTo(vec);
|
||||
if (scr < 2000.0f)
|
||||
if (IsVectorVisible(vec, area, false))
|
||||
success = true;
|
||||
}
|
||||
if (!success)
|
||||
bestarea = -1;
|
||||
}
|
||||
|
||||
Vector bestVec2;
|
||||
float bestDist2 = FLT_MAX;
|
||||
|
||||
for (size_t i = 0; i < corners.size(); i++)
|
||||
{
|
||||
if (corners.at(i) == bestVec2)
|
||||
continue;
|
||||
float dist = corners.at(i).DistTo(Target->m_center);
|
||||
if (dist < bestDist2)
|
||||
else
|
||||
for (int ar = 0; ar < areas.size(); ar++)
|
||||
{
|
||||
bestVec2 = corners.at(i);
|
||||
bestDist2 = dist;
|
||||
Vector area = areas[ar].m_center;
|
||||
area.z += 72.0f;
|
||||
if (TF2MAP->inactiveTracker.sentryAreas[ar])
|
||||
continue;
|
||||
float scr = area.DistTo(vec);
|
||||
if (scr > 2000.0f)
|
||||
continue;
|
||||
if (scr > bestscr)
|
||||
continue;
|
||||
if (IsVectorVisible(vec, area, false))
|
||||
{
|
||||
bestscr = scr;
|
||||
bestarea = ar;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (bestVec + bestVec2) / 2;
|
||||
}
|
||||
|
||||
float GetZBetweenAreas(CNavArea *start, CNavArea *end)
|
||||
{
|
||||
float z1 = GetClosestCornerToArea(start, end).z;
|
||||
float z2 = GetClosestCornerToArea(end, start).z;
|
||||
|
||||
return z2 - z1;
|
||||
}
|
||||
// Function required by MicroPather for getting an estimated cost
|
||||
float LeastCostEstimate(void *stateStart, void *stateEnd)
|
||||
{
|
||||
CNavArea *start = static_cast<CNavArea *>(stateStart);
|
||||
CNavArea *end = static_cast<CNavArea *>(stateEnd);
|
||||
float dist = start->m_center.DistTo(end->m_center);
|
||||
return dist;
|
||||
}
|
||||
// Function required by MicroPather to retrieve neighbours and their
|
||||
// associated costs.
|
||||
void AdjacentCost(void *state, MP_VECTOR<micropather::StateCost> *adjacent)
|
||||
{
|
||||
CNavArea *area = static_cast<CNavArea *>(state);
|
||||
auto &neighbours = area->m_connections;
|
||||
for (auto i : neighbours)
|
||||
{
|
||||
if (GetZBetweenAreas(area, i.area) > 42)
|
||||
continue;
|
||||
if (IsIgnored(area->m_id, i.area->m_id))
|
||||
continue;
|
||||
micropather::StateCost cost;
|
||||
cost.state =
|
||||
static_cast<void *>(&areas.at(FindInVector(i.area->m_id)));
|
||||
cost.cost = area->m_center.DistTo(i.area->m_center);
|
||||
adjacent->push_back(cost);
|
||||
}
|
||||
}
|
||||
void PrintStateInfo(void *state)
|
||||
{
|
||||
CNavArea *area = static_cast<CNavArea *>(state);
|
||||
logging::Info(format(area->m_center.x, " ", area->m_center.y, " ",
|
||||
area->m_center.z)
|
||||
.c_str());
|
||||
}
|
||||
MAP(size_t size)
|
||||
{
|
||||
pather =
|
||||
std::make_unique<micropather::MicroPather>(this, size, 6, true);
|
||||
}
|
||||
|
||||
~MAP()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static std::unique_ptr<MAP> TF2MAP;
|
||||
|
||||
return bestarea;
|
||||
}
|
||||
void Init()
|
||||
{
|
||||
// Get NavFile location
|
||||
@ -160,8 +103,11 @@ void Init()
|
||||
size = 7000;
|
||||
// Initiate "Map", contains micropather object
|
||||
TF2MAP = std::make_unique<MAP>(size);
|
||||
TF2MAP->inactiveTracker.reset();
|
||||
}
|
||||
pathfinding = true;
|
||||
if (!areas.empty())
|
||||
pathfinding = true;
|
||||
threadingFinished.store(true);
|
||||
}
|
||||
|
||||
static std::string lastmap;
|
||||
@ -172,6 +118,7 @@ bool Prepare()
|
||||
return false;
|
||||
if (!init)
|
||||
{
|
||||
// Don't reinit if same map
|
||||
if (lastmap == g_IEngine->GetLevelName())
|
||||
{
|
||||
init = true;
|
||||
@ -181,10 +128,14 @@ bool Prepare()
|
||||
lastmap = g_IEngine->GetLevelName();
|
||||
pathfinding = false;
|
||||
init = true;
|
||||
Init();
|
||||
threadingFinished.store(false);
|
||||
// Parsing CNavFile takes time, run it in a seperate thread
|
||||
std::thread initer(Init);
|
||||
// We need to either detach or join to avoid std::terminate
|
||||
initer.detach();
|
||||
}
|
||||
}
|
||||
if (!pathfinding)
|
||||
if (!pathfinding || !threadingFinished.load())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -206,7 +157,7 @@ int findClosestNavSquare(Vector vec)
|
||||
// Make sure we're not stuck on the same area for too long
|
||||
if (std::count(findClosestNavSquare_localAreas.begin(),
|
||||
findClosestNavSquare_localAreas.end(), i) < 3)
|
||||
overlapping.push_back({ i, &areas.at(i) });
|
||||
overlapping.emplace_back(i, &areas.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,7 +213,7 @@ std::vector<Vector> findPath(Vector loc, Vector dest, int &id_loc, int &id_dest)
|
||||
int result = TF2MAP->pather->Solve(static_cast<void *>(&areas.at(id_loc)),
|
||||
static_cast<void *>(&areas.at(id_dest)),
|
||||
&pathNodes, &cost);
|
||||
logging::Info(format(result).c_str());
|
||||
logging::Info(format("Pathing: Pather result: ", result).c_str());
|
||||
// If no result found, return empty Vector
|
||||
if (result == micropather::MicroPather::NO_SOLUTION)
|
||||
return std::vector<Vector>(0);
|
||||
@ -285,8 +236,8 @@ static Timer lastJump{};
|
||||
static std::vector<Vector> crumbs;
|
||||
// Bot will keep trying to get to the target even if it fails a few times
|
||||
static bool ensureArrival;
|
||||
// Priority value for current instructions, only higher priority can overwrite
|
||||
// itlocalAreas
|
||||
// Priority value for current instructions, only higher or equal priorites can
|
||||
// overwrite it
|
||||
int priority = 0;
|
||||
static Vector lastArea = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
@ -303,20 +254,24 @@ bool NavTo(Vector dest, bool navToLocalCenter, bool persistent,
|
||||
// Only allow instructions to overwrite others if their priority is higher
|
||||
if (instructionPriority < priority)
|
||||
return false;
|
||||
int locNav, tarNav;
|
||||
int locNav = 0, tarNav = 0;
|
||||
auto path = findPath(g_pLocalPlayer->v_Origin, dest, locNav, tarNav);
|
||||
if (path.empty())
|
||||
return false;
|
||||
if (!crumbs.empty())
|
||||
{
|
||||
bool reset = false;
|
||||
inactiveTracker.addTime({ lastArea, crumbs.at(0) }, inactivity, reset);
|
||||
TF2MAP->inactiveTracker.AddTime({ lastArea, crumbs.at(0) }, inactivity,
|
||||
reset);
|
||||
if (reset)
|
||||
TF2MAP->pather->Reset();
|
||||
}
|
||||
crumbs.clear();
|
||||
crumbs = std::move(path);
|
||||
if (!navToLocalCenter)
|
||||
if (crumbs.empty())
|
||||
return false;
|
||||
lastArea = crumbs.at(0);
|
||||
if (!navToLocalCenter && crumbs.size() > 1)
|
||||
crumbs.erase(crumbs.begin());
|
||||
ensureArrival = persistent;
|
||||
findClosestNavSquare_localAreas.clear();
|
||||
@ -331,21 +286,49 @@ void clearInstructions()
|
||||
}
|
||||
|
||||
static Timer ignoreReset{};
|
||||
static Timer patherReset{};
|
||||
static Timer sentryUpdate{};
|
||||
static Timer sentryCheck{};
|
||||
// Function for removing ignores
|
||||
void clearIgnores()
|
||||
void ignoreManagerCM()
|
||||
{
|
||||
if (ignoreReset.test_and_set(180000))
|
||||
if (!TF2MAP || !TF2MAP->pather)
|
||||
return;
|
||||
if (ignoreReset.test_and_set(120000))
|
||||
TF2MAP->inactiveTracker.reset();
|
||||
if (patherReset.test_and_set(30000))
|
||||
TF2MAP->pather->Reset();
|
||||
if (sentryUpdate.test_and_set(1000))
|
||||
TF2MAP->inactiveTracker.updateSentries();
|
||||
}
|
||||
|
||||
void Repath()
|
||||
{
|
||||
if (ensureArrival)
|
||||
{
|
||||
inactiveTracker.reset();
|
||||
if (TF2MAP && TF2MAP->pather)
|
||||
TF2MAP->pather->Reset();
|
||||
logging::Info("Pathing: NavBot inactive for too long. Ignoring "
|
||||
"connection and finding another path...");
|
||||
// Throwaway int
|
||||
int i1 = 0, i2 = 0;
|
||||
// Find a new path
|
||||
TF2MAP->pather->Reset();
|
||||
crumbs = findPath(g_pLocalPlayer->v_Origin, crumbs.back(), i1, i2);
|
||||
}
|
||||
else
|
||||
{
|
||||
logging::Info(
|
||||
"Pathing: NavBot inactive for too long. Canceling tasks and "
|
||||
"ignoring connection...");
|
||||
// Wait for new instructions
|
||||
TF2MAP->pather->Reset();
|
||||
crumbs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Main movement function, gets path from NavTo
|
||||
void CreateMove()
|
||||
{
|
||||
if (!enabled)
|
||||
if (!enabled || !threadingFinished.load())
|
||||
return;
|
||||
if (CE_BAD(LOCAL_E))
|
||||
return;
|
||||
@ -355,7 +338,7 @@ void CreateMove()
|
||||
crumbs.clear();
|
||||
return;
|
||||
}
|
||||
clearIgnores();
|
||||
ignoreManagerCM();
|
||||
// Crumbs empty, prepare for next instruction
|
||||
if (crumbs.empty())
|
||||
{
|
||||
@ -380,30 +363,35 @@ void CreateMove()
|
||||
if (crumbs.at(0).z - g_pLocalPlayer->v_Origin.z > 18 &&
|
||||
lastJump.test_and_set(200))
|
||||
current_user_cmd->buttons |= IN_JUMP;
|
||||
// Check if were dealing with a type 2 connection
|
||||
if (inactivity.check(3000) &&
|
||||
TF2MAP->inactiveTracker.CheckType2({ lastArea, crumbs.at(0) }))
|
||||
{
|
||||
logging::Info("Pathing: Type 2 connection detected!");
|
||||
TF2MAP->pather->Reset();
|
||||
Repath();
|
||||
inactivity.update();
|
||||
return;
|
||||
}
|
||||
// Check for new sentries
|
||||
if (sentryCheck.test_and_set(1000) &&
|
||||
TF2MAP->inactiveTracker.ShouldCancelPath(crumbs))
|
||||
{
|
||||
logging::Info("Pathing: New Sentry found!");
|
||||
TF2MAP->pather->Reset();
|
||||
Repath();
|
||||
return;
|
||||
}
|
||||
// If inactive for too long
|
||||
if (inactivity.check(5000))
|
||||
{
|
||||
// Ignore connection
|
||||
bool i3 = false;
|
||||
inactiveTracker.addTime({ lastArea, crumbs.at(0) }, inactivity, i3);
|
||||
if (i3)
|
||||
bool resetPather = false;
|
||||
TF2MAP->inactiveTracker.AddTime({ lastArea, crumbs.at(0) }, inactivity,
|
||||
resetPather);
|
||||
if (resetPather)
|
||||
TF2MAP->pather->Reset();
|
||||
if (ensureArrival)
|
||||
{
|
||||
logging::Info("Pathing: NavBot inactive for too long. Ignoring "
|
||||
"connection and finding another path...");
|
||||
// Find a new path
|
||||
int i1, i2;
|
||||
crumbs = findPath(g_pLocalPlayer->v_Origin, crumbs.back(), i1, i2);
|
||||
}
|
||||
else
|
||||
{
|
||||
logging::Info(
|
||||
"Pathing: NavBot inactive for too long. Canceling tasks and "
|
||||
"ignoring connection...");
|
||||
// Wait for new instructions
|
||||
crumbs.clear();
|
||||
}
|
||||
Repath();
|
||||
inactivity.update();
|
||||
return;
|
||||
}
|
||||
@ -431,7 +419,7 @@ void Draw()
|
||||
draw::WorldToScreen(crumbs[i + 1], wts2))
|
||||
{
|
||||
glez::draw::line(wts1.x, wts1.y, wts2.x - wts1.x, wts2.y - wts1.y,
|
||||
colors::white, 0.1f);
|
||||
colors::white, 0.3f);
|
||||
}
|
||||
}
|
||||
Vector wts;
|
||||
@ -458,7 +446,7 @@ CatCommand navprint("nav_print", "Debug nav print", [](const CCommand &args) {
|
||||
});
|
||||
|
||||
CatCommand navfind("nav_find", "Debug nav find", [](const CCommand &args) {
|
||||
int i1, i2;
|
||||
int i1 = 0, i2 = 0;
|
||||
std::vector<Vector> path = findPath(g_pLocalPlayer->v_Origin, loc, i1, i2);
|
||||
if (path.empty())
|
||||
{
|
||||
@ -484,4 +472,18 @@ CatCommand navpath("nav_path", "Debug nav path", [](const CCommand &args) {
|
||||
}
|
||||
});
|
||||
|
||||
// Clang format pls
|
||||
CatCommand navpathnolocal("nav_path_nolocal", "Debug nav path",
|
||||
[](const CCommand &args) {
|
||||
if (NavTo(loc, false, true, 50 + priority))
|
||||
{
|
||||
logging::Info(
|
||||
"Pathing: Success! Walking to path...");
|
||||
}
|
||||
else
|
||||
{
|
||||
logging::Info("Pathing: Failed!");
|
||||
}
|
||||
});
|
||||
|
||||
} // namespace nav
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#undef null
|
||||
|
||||
|
||||
#include <co/OnlineService.hpp>
|
||||
#include <fstream>
|
||||
#include <init.hpp>
|
||||
|
10
src/reclasses/CTFPartyClient.cpp
Executable file → Normal file
10
src/reclasses/CTFPartyClient.cpp
Executable file → Normal file
@ -119,3 +119,13 @@ int re::CTFPartyClient::BRequestJoinPlayer(CSteamID steamid)
|
||||
BRequestJoinPlayer_t(addr);
|
||||
return BRequestJoinPlayer_fn(this, steamid, false);
|
||||
}
|
||||
re::ITFMatchGroupDescription *re::GetMatchGroupDescription(int &idx)
|
||||
{
|
||||
typedef re::ITFMatchGroupDescription *(*GetMatchGroupDescription_t)(int &);
|
||||
static uintptr_t addr =
|
||||
gSignatures.GetClientSignature("55 89 E5 8B 45 08 8B 00 83 F8 FF");
|
||||
static GetMatchGroupDescription_t GetMatchGroupDescription_fn =
|
||||
GetMatchGroupDescription_t(addr);
|
||||
|
||||
return GetMatchGroupDescription_fn(idx);
|
||||
}
|
||||
|
12
src/reclasses/C_TEFireBullets.cpp
Executable file → Normal file
12
src/reclasses/C_TEFireBullets.cpp
Executable file → Normal file
@ -5,15 +5,15 @@
|
||||
* Author: bencat07
|
||||
*/
|
||||
#include "reclasses.hpp"
|
||||
#pragma once
|
||||
#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;
|
||||
(gSignatures.GetClientSignature("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()
|
||||
|
@ -11,6 +11,8 @@
|
||||
Created on 29.07.18.
|
||||
*/
|
||||
|
||||
static void getAndSortAllConfigs();
|
||||
|
||||
static CatCommand cat("cat", "", [](const CCommand &args) {
|
||||
if (args.ArgC() < 3)
|
||||
{
|
||||
@ -69,6 +71,8 @@ static CatCommand save("save", "", [](const CCommand &args) {
|
||||
writer.saveTo(
|
||||
std::string(DATA_PATH "/configs/") + args.Arg(1) + ".conf", false);
|
||||
}
|
||||
getAndSortAllConfigs();
|
||||
closedir(config_directory);
|
||||
});
|
||||
|
||||
static CatCommand load("load", "", [](const CCommand &args) {
|
||||
@ -84,21 +88,50 @@ static CatCommand load("load", "", [](const CCommand &args) {
|
||||
}
|
||||
});
|
||||
|
||||
static std::vector<std::string> sorted{};
|
||||
static std::vector<std::string> sortedVariables{};
|
||||
|
||||
static void getAndSortAllVariables()
|
||||
{
|
||||
for (auto &v : settings::Manager::instance().registered)
|
||||
{
|
||||
sorted.push_back(v.first);
|
||||
sortedVariables.push_back(v.first);
|
||||
}
|
||||
|
||||
std::sort(sorted.begin(), sorted.end());
|
||||
std::sort(sortedVariables.begin(), sortedVariables.end());
|
||||
|
||||
logging::Info("Sorted %u variables\n", sorted.size());
|
||||
logging::Info("Sorted %u variables\n", sortedVariables.size());
|
||||
}
|
||||
|
||||
static int completionCallback(
|
||||
static std::vector<std::string> sortedConfigs{};
|
||||
|
||||
static void getAndSortAllConfigs()
|
||||
{
|
||||
DIR *config_directory = opendir(DATA_PATH "/configs");
|
||||
if (!config_directory)
|
||||
{
|
||||
logging::Info("Config directoy does not exist.");
|
||||
closedir(config_directory);
|
||||
return;
|
||||
}
|
||||
sortedConfigs.clear();
|
||||
|
||||
struct dirent *ent;
|
||||
while ((ent = readdir(config_directory)))
|
||||
{
|
||||
std::string s(ent->d_name);
|
||||
s = s.substr(0, s.find_last_of("."));
|
||||
logging::Info(s.c_str());
|
||||
sortedConfigs.push_back(s);
|
||||
}
|
||||
std::sort(sortedConfigs.begin(), sortedConfigs.end());
|
||||
sortedConfigs.erase(sortedConfigs.begin());
|
||||
sortedConfigs.erase(sortedConfigs.begin());
|
||||
|
||||
closedir(config_directory);
|
||||
logging::Info("Sorted %u config files\n", sortedConfigs.size());
|
||||
}
|
||||
|
||||
static int cat_completionCallback(
|
||||
const char *c_partial,
|
||||
char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])
|
||||
{
|
||||
@ -144,7 +177,7 @@ static int completionCallback(
|
||||
return count;
|
||||
}
|
||||
|
||||
for (const auto &s : sorted)
|
||||
for (const auto &s : sortedVariables)
|
||||
{
|
||||
if (s.find(parts[1]) == 0)
|
||||
{
|
||||
@ -162,8 +195,52 @@ static int completionCallback(
|
||||
return count;
|
||||
}
|
||||
|
||||
static int load_completionCallback(
|
||||
const char *c_partial,
|
||||
char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])
|
||||
{
|
||||
std::string partial = c_partial;
|
||||
std::string parts[2]{};
|
||||
auto j = 0u;
|
||||
auto f = false;
|
||||
int count = 0;
|
||||
|
||||
for (auto i = 0u; i < partial.size() && j < 3; ++i)
|
||||
{
|
||||
auto space = (bool) isspace(partial[i]);
|
||||
if (!space)
|
||||
{
|
||||
if (j)
|
||||
parts[j - 1].push_back(partial[i]);
|
||||
f = true;
|
||||
}
|
||||
|
||||
if (i == partial.size() - 1 || (f && space))
|
||||
{
|
||||
if (space)
|
||||
++j;
|
||||
f = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &s : sortedConfigs)
|
||||
{
|
||||
if (s.find(parts[0]) == 0)
|
||||
{
|
||||
snprintf(commands[count++], COMMAND_COMPLETION_ITEM_LENGTH - 1,
|
||||
"cat_load %s", s.c_str());
|
||||
if (count == COMMAND_COMPLETION_MAXITEMS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static InitRoutine init([]() {
|
||||
getAndSortAllVariables();
|
||||
cat.cmd->m_bHasCompletionCallback = true;
|
||||
cat.cmd->m_fnCompletionCallback = completionCallback;
|
||||
});
|
||||
getAndSortAllConfigs();
|
||||
cat.cmd->m_bHasCompletionCallback = true;
|
||||
cat.cmd->m_fnCompletionCallback = cat_completionCallback;
|
||||
load.cmd->m_bHasCompletionCallback = true;
|
||||
load.cmd->m_fnCompletionCallback = load_completionCallback;
|
||||
});
|
||||
|
@ -17,7 +17,7 @@ bool settings::SettingsWriter::saveTo(std::string path, bool only_changed)
|
||||
|
||||
stream.open(path, std::ios::out);
|
||||
|
||||
if (stream.bad())
|
||||
if (stream.bad() || !stream.is_open())
|
||||
return false;
|
||||
|
||||
using pair_type = std::pair<std::string, settings::IVariable *>;
|
||||
@ -33,12 +33,10 @@ bool settings::SettingsWriter::saveTo(std::string path, bool only_changed)
|
||||
[](const pair_type &a, const pair_type &b) -> bool {
|
||||
return a.first.compare(b.first) < 0;
|
||||
});
|
||||
|
||||
for (auto &v : all_registered)
|
||||
{
|
||||
write(v.first, v.second);
|
||||
}
|
||||
|
||||
if (!v.first.empty())
|
||||
write(v.first, v.second);
|
||||
stream.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
4
src/textmode.cpp
Executable file → Normal file
4
src/textmode.cpp
Executable file → Normal file
@ -21,8 +21,8 @@ void EXPOSED_Epic_VACBypass_1337_DoNotSteal_xXx_$1_xXx_MLG()
|
||||
static unsigned char patch[] = { 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x18, 0xB8,
|
||||
0x01, 0x00, 0x00, 0x00, 0xC9, 0xC3 };
|
||||
uintptr_t Host_IsSecureServerAllowed_addr = gSignatures.GetEngineSignature(
|
||||
"55 89 E5 83 EC 18 E8 ? ? ? ? 8B 10 C7 44 24 04 ? ? ? ? 89 04 24 FF 52 "
|
||||
"2C 85 C0 74 11");
|
||||
"55 89 E5 83 EC ? E8 ? ? ? ? 8B 10 C7 44 24 ? ? ? ? ? 89 04 24 FF 52 ? "
|
||||
"85 C0 74 ? C6 05");
|
||||
// +0x21 = allowSecureServers
|
||||
// logging::Info("1337 VAC bypass: 0x%08x",
|
||||
// Host_IsSecureServerAllowed_addr);
|
||||
|
13
src/tfmm.cpp
13
src/tfmm.cpp
@ -32,7 +32,17 @@ CatCommand get_state("mm_state", "Get party state", []() {
|
||||
|
||||
namespace tfmm
|
||||
{
|
||||
|
||||
int queuecount = 0;
|
||||
bool isMMBanned()
|
||||
{
|
||||
auto client = re::CTFPartyClient::GTFPartyClient();
|
||||
if (!client || (client->BInQueueForMatchGroup(7) && queuecount < 10))
|
||||
{
|
||||
queuecount = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
int getQueue()
|
||||
{
|
||||
return *queue;
|
||||
@ -47,6 +57,7 @@ void startQueue()
|
||||
client->LoadSavedCasualCriteria();
|
||||
client->RequestQueueForMatch((int) queue);
|
||||
hacks::shared::autojoin::resetQueueTimer();
|
||||
queuecount++;
|
||||
}
|
||||
else
|
||||
logging::Info("queue_start: CTFPartyClient == null!");
|
||||
|
@ -42,6 +42,8 @@ bool trace::FilterDefault::ShouldHitEntity(IHandleEntity *handle, int mask)
|
||||
switch (clazz->m_ClassID)
|
||||
{
|
||||
// TODO magic numbers: invisible entity ids
|
||||
case 246:
|
||||
case 248:
|
||||
case 64:
|
||||
case 225:
|
||||
case 55:
|
||||
@ -79,7 +81,6 @@ void trace::FilterNoPlayer::SetSelf(IClientEntity *self)
|
||||
|
||||
bool trace::FilterNoPlayer::ShouldHitEntity(IHandleEntity *handle, int mask)
|
||||
{
|
||||
return false;
|
||||
IClientEntity *entity;
|
||||
ClientClass *clazz;
|
||||
|
||||
@ -91,6 +92,8 @@ bool trace::FilterNoPlayer::ShouldHitEntity(IHandleEntity *handle, int mask)
|
||||
switch (clazz->m_ClassID)
|
||||
{
|
||||
// TODO magic numbers: invisible entity ids
|
||||
case 248:
|
||||
case 246:
|
||||
case 64:
|
||||
case 225:
|
||||
case 55:
|
||||
@ -107,7 +110,34 @@ TraceType_t trace::FilterNoPlayer::GetTraceType() const
|
||||
{
|
||||
return TRACE_EVERYTHING;
|
||||
}
|
||||
/* No-Entity filter */
|
||||
|
||||
trace::FilterNoEntity::FilterNoEntity()
|
||||
{
|
||||
m_pSelf = nullptr;
|
||||
}
|
||||
|
||||
trace::FilterNoEntity::~FilterNoEntity(){};
|
||||
|
||||
void trace::FilterNoEntity::SetSelf(IClientEntity *self)
|
||||
{
|
||||
if (self == nullptr)
|
||||
{
|
||||
logging::Info("nullptr in FilterNoPlayer::SetSelf");
|
||||
return;
|
||||
}
|
||||
m_pSelf = self;
|
||||
}
|
||||
|
||||
bool trace::FilterNoEntity::ShouldHitEntity(IHandleEntity *handle, int mask)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TraceType_t trace::FilterNoEntity::GetTraceType() const
|
||||
{
|
||||
return TRACE_EVERYTHING;
|
||||
}
|
||||
/* Penetration Filter */
|
||||
|
||||
trace::FilterPenetration::FilterPenetration()
|
||||
@ -169,4 +199,5 @@ void trace::FilterPenetration::Reset()
|
||||
|
||||
trace::FilterDefault trace::filter_default{};
|
||||
trace::FilterNoPlayer trace::filter_no_player{};
|
||||
trace::FilterNoEntity trace::filter_no_entity{};
|
||||
trace::FilterPenetration trace::filter_penetration{};
|
||||
|
@ -156,6 +156,16 @@ bool gui::handleSdlEvent(SDL_Event *event)
|
||||
logging::Info("GUI open button pressed");
|
||||
zerokernel::Menu::instance->setInGame(
|
||||
!zerokernel::Menu::instance->isInGame());
|
||||
if (!zerokernel::Menu::instance->isInGame())
|
||||
{
|
||||
g_ISurface->UnlockCursor();
|
||||
g_ISurface->SetCursorAlwaysVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ISurface->LockCursor();
|
||||
g_ISurface->SetCursorAlwaysVisible(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ zerokernel::Checkbox::Checkbox(settings::Variable<bool> &option)
|
||||
|
||||
void zerokernel::Checkbox::render()
|
||||
{
|
||||
if (option)
|
||||
if (option && *option)
|
||||
{
|
||||
renderBorder(*color_border);
|
||||
auto cb = bb.getContentBox();
|
||||
|
Reference in New Issue
Block a user