Merge pull request #562 from nullworks/newui

Newui
This commit is contained in:
LightCat 2018-08-28 15:22:55 +02:00 committed by GitHub
commit 8e62ac5cf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 1246 additions and 530 deletions

View File

@ -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)

View File

@ -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

View File

@ -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"/>

View File

@ -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")

View File

@ -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;

View File

@ -8,7 +8,6 @@
#pragma once
#include "common.hpp"
#include "config.h"
class ConVar;
class IClientEntity;

View File

@ -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

View File

@ -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}")

View File

@ -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 *);

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

@ -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

View File

@ -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];
}
};

View File

@ -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

View File

@ -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();

View File

@ -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"

View File

@ -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

View File

@ -14,5 +14,6 @@ void startQueue();
void leaveQueue();
void disconnectAndAbandon();
void abandon();
bool isMMBanned();
int getQueue();
} // namespace tfmm

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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 =

View File

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

View File

@ -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;

View File

@ -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;

View File

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

View File

@ -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;

View File

@ -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))

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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",

View File

@ -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))

View File

@ -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)

View File

@ -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;

View File

@ -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" };

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -13,7 +13,6 @@
#undef null
#include <co/OnlineService.hpp>
#include <fstream>
#include <init.hpp>

10
src/reclasses/CTFPartyClient.cpp Executable file → Normal file
View 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
View 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()

View File

@ -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;
});

View File

@ -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
View 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);

View File

@ -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!");

View File

@ -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{};

View File

@ -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;
}
}

View File

@ -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();