diff --git a/CMakeLists.txt b/CMakeLists.txt index 602eecf6..0b2faa42 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 "$") -endif() - add_subdirectory(src) add_subdirectory(include) add_subdirectory(external) diff --git a/build_names b/build_names index 04cd2951..5e199666 100755 --- a/build_names +++ b/build_names @@ -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 - diff --git a/data/menu/nullifiedcat/catbot.xml b/data/menu/nullifiedcat/catbot.xml index a8e78ecf..e873011d 100755 --- a/data/menu/nullifiedcat/catbot.xml +++ b/data/menu/nullifiedcat/catbot.xml @@ -61,9 +61,10 @@ + - + diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index e8dd5d4b..f7d4793d 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -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") diff --git a/include/core/netvars.hpp b/include/core/netvars.hpp index cee7796b..575aacd2 100755 --- a/include/core/netvars.hpp +++ b/include/core/netvars.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; diff --git a/include/hacks/Aimbot.hpp b/include/hacks/Aimbot.hpp index 51c0fe3f..c1f4f3c4 100644 --- a/include/hacks/Aimbot.hpp +++ b/include/hacks/Aimbot.hpp @@ -8,7 +8,6 @@ #pragma once #include "common.hpp" -#include "config.h" class ConVar; class IClientEntity; diff --git a/include/hacks/SeedPrediction.hpp b/include/hacks/SeedPrediction.hpp index add7124e..8484fb40 100644 --- a/include/hacks/SeedPrediction.hpp +++ b/include/hacks/SeedPrediction.hpp @@ -12,7 +12,7 @@ #pragma once namespace hacks::tf2::seedprediction { -extern settings::Bool prediction; +bool predon(); void handleFireBullets(C_TEFireBullets *); struct seedstruct { @@ -28,7 +28,7 @@ struct predictSeed2 { seedstruct base; int tickcount; - double resolution; + float resolution; bool operator<(const predictSeed2 &rhs) const { return tickcount < rhs.tickcount; @@ -37,7 +37,7 @@ struct predictSeed2 struct IntervalEdge { int pos; - double val; + float val; bool operator<(const IntervalEdge &rhs) const { return val < rhs.val; @@ -50,5 +50,5 @@ extern buf bases; extern buf2 rebased; extern buf3 intervals; void selectBase(); -double predictOffset(const seedstruct &entry, int targetTick, double clockRes); +float predictOffset(const seedstruct &entry, int targetTick, float clockRes); } // namespace hacks::tf2::seedprediction diff --git a/include/hooks/CMakeLists.txt b/include/hooks/CMakeLists.txt index 2151284f..9588f1d1 100755 --- a/include/hooks/CMakeLists.txt +++ b/include/hooks/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(cathook PRIVATE - "${CMAKE_CURRENT_LIST_DIR}/HookedMethods.hpp") + "${CMAKE_CURRENT_LIST_DIR}/HookedMethods.hpp" + "${CMAKE_CURRENT_LIST_DIR}/PreDataUpdate.hpp") target_include_directories(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}") \ No newline at end of file diff --git a/include/hooks/HookedMethods.hpp b/include/hooks/HookedMethods.hpp index 4e71a2ef..fe49f141 100644 --- a/include/hooks/HookedMethods.hpp +++ b/include/hooks/HookedMethods.hpp @@ -36,8 +36,6 @@ struct SDL_Window; &hooked_methods::original::name namespace hooked_methods { -// FireBullets -DECLARE_HOOKED_METHOD(PreDataUpdate, void, void *, int); // ClientMode DECLARE_HOOKED_METHOD(CreateMove, bool, void *, float, CUserCmd *); DECLARE_HOOKED_METHOD(LevelInit, void, void *, const char *); diff --git a/include/hooks/PreDataUpdate.hpp b/include/hooks/PreDataUpdate.hpp new file mode 100644 index 00000000..22626500 --- /dev/null +++ b/include/hooks/PreDataUpdate.hpp @@ -0,0 +1,10 @@ +// +// Created by bencat07 on 24.08.18. +// + +#pragma once +#include "HookedMethods.hpp" +namespace hooked_methods +{ +void CreateMove(); +} diff --git a/include/https_request.hpp b/include/https_request.hpp deleted file mode 100644 index b087a345..00000000 --- a/include/https_request.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * https_request.hpp - * - * Created on: Jul 23, 2017 - * Author: nullifiedcat - */ - -#pragma once - -#include -#include - -#include - -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 diff --git a/include/navparser.hpp b/include/navparser.hpp index 1cbbc524..b117f18d 100644 --- a/include/navparser.hpp +++ b/include/navparser.hpp @@ -3,6 +3,8 @@ #include "common.hpp" #include "micropather.h" #include "pwd.h" +#include +#include #if ENABLE_VISUALS #include #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, unsigned int> inactives; + std::unordered_map, std::pair, + boost::hash>> + inactives; - void reset() +public: + std::unordered_map sentryAreas; + +private: + std::vector sentries{}; + + bool vischeckConnection(std::pair &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 connection, Timer &timer, - bool &resetPather) - { - if (inactives.find(connection) == inactives.end()) - { - inactives[connection] = 0; - } - inactives[connection] = - inactives[connection] + - (std::chrono::duration_cast( - std::chrono::system_clock::now() - timer.last) - .count()); - if (inactives[connection] >= 5000) - resetPather = true; - } - void addTime(std::pair connection, Timer &timer, - bool &resetPather) + + std::pair VectorsToId(std::pair &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 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 connection) + bool IsIgnored(std::pair 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 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::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 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 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 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 pather; + // Maps already utilize dynamic allocation and we don't need a custom + // constructor + inactivityTracker inactiveTracker; + Vector GetClosestCornerToArea(CNavArea *CornerOf, CNavArea *Target) + { + std::array 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(stateStart); + CNavArea *end = static_cast(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 *adjacent) + { + CNavArea *area = static_cast(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(&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(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(this, size, 6, true); + } + + ~MAP() { - return inactives[connection]; } }; diff --git a/include/reclasses/CTFPartyClient.hpp b/include/reclasses/CTFPartyClient.hpp index b901eb30..731bcd25 100644 --- a/include/reclasses/CTFPartyClient.hpp +++ b/include/reclasses/CTFPartyClient.hpp @@ -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 diff --git a/include/reclasses/C_TEFireBullets.hpp b/include/reclasses/C_TEFireBullets.hpp index 0344b49b..3d87d6d2 100755 --- a/include/reclasses/C_TEFireBullets.hpp +++ b/include/reclasses/C_TEFireBullets.hpp @@ -6,11 +6,11 @@ */ #pragma once #include "reclasses.hpp" -class C_TEFireBullets : public C_BaseTempEntity +class C_TEFireBullets { public: C_TEFireBullets() = delete; - static C_BaseTempEntity *GTEFireBullets(); + static C_TEFireBullets *GTEFireBullets(); public: int m_iSeed(); diff --git a/include/reclasses/reclasses.hpp b/include/reclasses/reclasses.hpp index 45e15514..320dd084 100755 --- a/include/reclasses/reclasses.hpp +++ b/include/reclasses/reclasses.hpp @@ -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" diff --git a/include/settings/Key.hpp b/include/settings/Key.hpp index eb1e749b..0fb86b82 100644 --- a/include/settings/Key.hpp +++ b/include/settings/Key.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 \ No newline at end of file +} // namespace settings diff --git a/include/tfmm.hpp b/include/tfmm.hpp index fd7f252a..43236a2d 100644 --- a/include/tfmm.hpp +++ b/include/tfmm.hpp @@ -14,5 +14,6 @@ void startQueue(); void leaveQueue(); void disconnectAndAbandon(); void abandon(); +bool isMMBanned(); int getQueue(); } // namespace tfmm diff --git a/include/trace.hpp b/include/trace.hpp index bc3f47b2..5bdb9b0d 100644 --- a/include/trace.hpp +++ b/include/trace.hpp @@ -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 diff --git a/install-all b/install-all index c200a0b5..994cea56 100755 --- a/install-all +++ b/install-all @@ -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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 963d3daa..08b5b548 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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" diff --git a/src/core/netvars.cpp b/src/core/netvars.cpp index 9ac29553..ba451101 100644 --- a/src/core/netvars.cpp +++ b/src/core/netvars.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 = diff --git a/src/hack.cpp b/src/hack.cpp index 988edbc2..56ff1b4e 100644 --- a/src/hack.cpp +++ b/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() diff --git a/src/hacks/Aimbot.cpp b/src/hacks/Aimbot.cpp index ae4e89aa..425727b6 100644 --- a/src/hacks/Aimbot.cpp +++ b/src/hacks/Aimbot.cpp @@ -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; diff --git a/src/hacks/AutoJoin.cpp b/src/hacks/AutoJoin.cpp index 6c662090..de6829ef 100644 --- a/src/hacks/AutoJoin.cpp +++ b/src/hacks/AutoJoin.cpp @@ -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; diff --git a/src/hacks/CatBot.cpp b/src/hacks/CatBot.cpp index 0b670a80..edee64c5 100644 --- a/src/hacks/CatBot.cpp +++ b/src/hacks/CatBot.cpp @@ -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()) diff --git a/src/hacks/ESP.cpp b/src/hacks/ESP.cpp index 01443feb..76c50de0 100644 --- a/src/hacks/ESP.cpp +++ b/src/hacks/ESP.cpp @@ -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; diff --git a/src/hacks/LightESP.cpp b/src/hacks/LightESP.cpp index c05b16bd..51678356 100644 --- a/src/hacks/LightESP.cpp +++ b/src/hacks/LightESP.cpp @@ -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)) diff --git a/src/hacks/Misc.cpp b/src/hacks/Misc.cpp index 99b82b0b..2cb84178 100644 --- a/src/hacks/Misc.cpp +++ b/src/hacks/Misc.cpp @@ -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; diff --git a/src/hacks/NavBot.cpp b/src/hacks/NavBot.cpp index 78792fdd..1d3fd479 100644 --- a/src/hacks/NavBot.cpp +++ b/src/hacks/NavBot.cpp @@ -1,6 +1,7 @@ // // Created by bencat07 on 17.08.18. // +#include #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 preferred_sniper_spots; std::vector sniper_spots; +std::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 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 GetBuildings() +{ + float bestscr = FLT_MAX; + std::vector 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); } } } diff --git a/src/hacks/SeedPrediction.cpp b/src/hacks/SeedPrediction.cpp index 8566bd56..ead700ac 100644 --- a/src/hacks/SeedPrediction.cpp +++ b/src/hacks/SeedPrediction.cpp @@ -8,13 +8,17 @@ #include "common.hpp" #include "SeedPrediction.hpp" #include "reclasses.hpp" -constexpr double MIN_CLOCKRES = 0.25; -constexpr double MAX_CLOCKRES = 8192.5; -double clockRes; +constexpr float MIN_CLOCKRES = 0.25; +constexpr float MAX_CLOCKRES = 8192.5; +float clockRes; float seedFraction = 0.0f; namespace hacks::tf2::seedprediction { -settings::Bool prediction{ "seed-prediction.enable", "false" }; +static settings::Bool prediction{ "seed-prediction.enable", "false" }; +bool predon() +{ + return *prediction; +} buf bases{ 9999 }; buf2 rebased{ 9999 }; buf3 intervals{ 9999 }; @@ -27,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", diff --git a/src/hacks/Trigger.cpp b/src/hacks/Trigger.cpp index fe7c254c..be9bfe3e 100644 --- a/src/hacks/Trigger.cpp +++ b/src/hacks/Trigger.cpp @@ -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)) diff --git a/src/helpers.cpp b/src/helpers.cpp index 11e808b6..63a9bf4b 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -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) diff --git a/src/hooks/CreateMove.cpp b/src/hooks/CreateMove.cpp index e75e30ac..83a494e5 100644 --- a/src/hooks/CreateMove.cpp +++ b/src/hooks/CreateMove.cpp @@ -16,6 +16,7 @@ #include "NavBot.hpp" #include "HookedMethods.hpp" +#include "PreDataUpdate.hpp" static settings::Bool minigun_jump{ "misc.minigun-jump-tf2c", "false" }; static settings::Bool roll_speedhack{ "misc.roll-speedhack", "false" }; @@ -197,6 +198,8 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, ipc::UpdateServerAddress(); #endif } + hooked_methods::CreateMove(); + if (nolerp) { // current_user_cmd->tick_count += 1; diff --git a/src/hooks/LevelInit.cpp b/src/hooks/LevelInit.cpp index 978b7a01..ba5b3b74 100644 --- a/src/hooks/LevelInit.cpp +++ b/src/hooks/LevelInit.cpp @@ -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" }; diff --git a/src/hooks/PreDataUpdate.cpp b/src/hooks/PreDataUpdate.cpp index 3c2c23c1..6f19ce75 100644 --- a/src/hooks/PreDataUpdate.cpp +++ b/src/hooks/PreDataUpdate.cpp @@ -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 diff --git a/src/hooks/SendDatagram.cpp b/src/hooks/SendDatagram.cpp index e70bf1af..8a20b9aa 100644 --- a/src/hooks/SendDatagram.cpp +++ b/src/hooks/SendDatagram.cpp @@ -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; diff --git a/src/hooks/Shutdown.cpp b/src/hooks/Shutdown.cpp index ad18fd3f..80ad2fb4 100644 --- a/src/hooks/Shutdown.cpp +++ b/src/hooks/Shutdown.cpp @@ -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); } diff --git a/src/hooks/visual/PaintTraverse.cpp b/src/hooks/visual/PaintTraverse.cpp index 627dfa2c..23f65dfe 100644 --- a/src/hooks/visual/PaintTraverse.cpp +++ b/src/hooks/visual/PaintTraverse.cpp @@ -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) diff --git a/src/https_request.cpp b/src/https_request.cpp deleted file mode 100644 index 7da88bd4..00000000 --- a/src/https_request.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * https_request.cpp - * - * Created on: Jul 23, 2017 - * Author: nullifiedcat - */ - -#include -#include "https_request.hpp" - -#include -#include -#include - -#include - -#include -#include - -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 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 diff --git a/src/navparser.cpp b/src/navparser.cpp index 19b5d0d9..98940dcb 100644 --- a/src/navparser.cpp +++ b/src/navparser.cpp @@ -8,124 +8,67 @@ std::vector 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 threadingFinished; -// Todo fix -size_t FindInVector(size_t id) +static std::unique_ptr 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 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 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(stateStart); - CNavArea *end = static_cast(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 *adjacent) - { - CNavArea *area = static_cast(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(&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(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(this, size, 6, true); - } - - ~MAP() - { - } -}; - -static std::unique_ptr 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(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 findPath(Vector loc, Vector dest, int &id_loc, int &id_dest) int result = TF2MAP->pather->Solve(static_cast(&areas.at(id_loc)), static_cast(&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(0); @@ -285,8 +236,8 @@ static Timer lastJump{}; static std::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 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 diff --git a/src/online/Online.cpp b/src/online/Online.cpp index a9080929..6addb4a6 100644 --- a/src/online/Online.cpp +++ b/src/online/Online.cpp @@ -13,7 +13,6 @@ #undef null - #include #include #include diff --git a/src/reclasses/CTFPartyClient.cpp b/src/reclasses/CTFPartyClient.cpp old mode 100755 new mode 100644 index a326101b..ba230beb --- a/src/reclasses/CTFPartyClient.cpp +++ b/src/reclasses/CTFPartyClient.cpp @@ -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); +} diff --git a/src/reclasses/C_TEFireBullets.cpp b/src/reclasses/C_TEFireBullets.cpp old mode 100755 new mode 100644 index ece4991e..e6bfbc9c --- a/src/reclasses/C_TEFireBullets.cpp +++ b/src/reclasses/C_TEFireBullets.cpp @@ -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() diff --git a/src/settings/SettingCommands.cpp b/src/settings/SettingCommands.cpp index cdb501ee..cc28ca01 100755 --- a/src/settings/SettingCommands.cpp +++ b/src/settings/SettingCommands.cpp @@ -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 sorted{}; +static std::vector 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 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; -}); \ No newline at end of file + getAndSortAllConfigs(); + cat.cmd->m_bHasCompletionCallback = true; + cat.cmd->m_fnCompletionCallback = cat_completionCallback; + load.cmd->m_bHasCompletionCallback = true; + load.cmd->m_fnCompletionCallback = load_completionCallback; +}); diff --git a/src/settings/SettingsIO.cpp b/src/settings/SettingsIO.cpp index d688f508..eac465f1 100755 --- a/src/settings/SettingsIO.cpp +++ b/src/settings/SettingsIO.cpp @@ -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; @@ -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; } diff --git a/src/textmode.cpp b/src/textmode.cpp old mode 100755 new mode 100644 index 925fe849..63620d44 --- a/src/textmode.cpp +++ b/src/textmode.cpp @@ -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); diff --git a/src/tfmm.cpp b/src/tfmm.cpp index c4f9deb4..81617b0c 100644 --- a/src/tfmm.cpp +++ b/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!"); diff --git a/src/trace.cpp b/src/trace.cpp index f54885eb..384d7e69 100755 --- a/src/trace.cpp +++ b/src/trace.cpp @@ -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{}; diff --git a/src/visual/menu/GuiInterface.cpp b/src/visual/menu/GuiInterface.cpp index 3f18372d..2cc1e177 100755 --- a/src/visual/menu/GuiInterface.cpp +++ b/src/visual/menu/GuiInterface.cpp @@ -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; } } diff --git a/src/visual/menu/menu/objects/input/Checkbox.cpp b/src/visual/menu/menu/objects/input/Checkbox.cpp index 1b35c61f..ce1cca30 100755 --- a/src/visual/menu/menu/objects/input/Checkbox.cpp +++ b/src/visual/menu/menu/objects/input/Checkbox.cpp @@ -40,7 +40,7 @@ zerokernel::Checkbox::Checkbox(settings::Variable &option) void zerokernel::Checkbox::render() { - if (option) + if (option && *option) { renderBorder(*color_border); auto cb = bb.getContentBox();