diff --git a/src/chatlog.cpp b/src/chatlog.cpp index c508eb15..b36be63a 100644 --- a/src/chatlog.cpp +++ b/src/chatlog.cpp @@ -12,6 +12,7 @@ namespace chatlog { CatVar enabled(CV_SWITCH, "chat_log", "0", "Chat log", "Log chat to file"); CatVar message_template(CV_STRING, "chat_log_template", "[U:1:%u] %n: %m", "Log template", "%u - SteamID\n%n - name\n%m - message"); +CatVar dont_log_spam(CV_SWITCH, "chat_log_nospam", "1", "No Spam", "Don't log your messages if spam is active"); class RAIILog { public: @@ -41,6 +42,8 @@ void LogMessage(int eid, std::string message) { if (!enabled) { return; } + if (dont_log_spam && hacks::shared::spam::spam_source and eid == g_IEngine->GetLocalPlayer()) + return; player_info_s info; if (not g_IEngine->GetPlayerInfo(eid, &info)) return; diff --git a/src/hacks/AutoBackstab.cpp b/src/hacks/AutoBackstab.cpp index 01a39736..ea55bce7 100644 --- a/src/hacks/AutoBackstab.cpp +++ b/src/hacks/AutoBackstab.cpp @@ -20,7 +20,7 @@ void CreateMove() { IClientEntity* weapon = RAW_ENT(LOCAL_W); typedef bool(*IsBehindAndFacingTarget_t)(IClientEntity*, IClientEntity*); - static auto IsBehindAndFacingTarget_addr = gSignatures.GetClientSignature("55 89 E5 57 56 53 83 EC 5C 8B 45 08 8B 75 0C 89 04 24 E8 E9 0F FD FF 85 C0 89 C3 74 0F 8B 00 89 1C 24 FF 90 E0 02 00 00 84 C0 75 14"); + static auto IsBehindAndFacingTarget_addr = gSignatures.GetClientSignature("55 89 E5 57 56 53 83 EC 5C 8B 45 08 8B 75 0C 89 04 24 E8 ? ? ? ? 85 C0 89 C3 74 0F 8B 00 89 1C 24 FF 90 E0 02 00 00 84 C0"); static auto IsBehindAndFacingTarget = reinterpret_cast(IsBehindAndFacingTarget_addr); // 515 = DoSwingTrace diff --git a/src/hacks/AutoJoin.cpp b/src/hacks/AutoJoin.cpp new file mode 100644 index 00000000..d2d25163 --- /dev/null +++ b/src/hacks/AutoJoin.cpp @@ -0,0 +1,73 @@ +/* + * AutoJoin.cpp + * + * Created on: Jul 28, 2017 + * Author: nullifiedcat + */ + +#include "../common.h" +#include "../hack.h" +#include "../copypasted/CSignature.h" + +namespace hacks { namespace shared { namespace autojoin { + +CatEnum classes_enum({ "DISABLED", "SCOUT", "SNIPER", "SOLDIER", "DEMOMAN", "MEDIC", "HEAVY", "PYRO", "SPY", "ENGINEER" }); +CatVar autojoin_team(CV_SWITCH, "autojoin_team", "0", "AutoJoin", "Automatically joins a team"); +CatVar preferred_class(classes_enum, "autojoin_class", "0", "AutoJoin class", "You will pick a class automatically"); + +CatVar auto_queue(CV_SWITCH, "autoqueue", "0", "AutoQueue", "Automatically queue in casual matches"); + +const std::string classnames[] = { + "scout", "sniper", "soldier", "demoman", "medic", "heavyweapons", "pyro", "spy", "engineer" +}; + +CatCommand debug_startsearch("debug_startsearch", "DEBUG StartSearch", []() { + logging::Info("%d", g_TFGCClientSystem->RequestSelectWizardStep(4)); +}); + +CatCommand debug_readytosearch("debug_gcstate", "DEBUG GCState", []() { + logging::Info("%d", g_TFGCClientSystem->GetState()); +}); +CatCommand debug_abandon("debug_abandon", "DEBUG Abandon", []() { + g_TFGCClientSystem->SendExitMatchmaking(true); +}); +bool UnassignedTeam() { + return !g_pLocalPlayer->team or (g_pLocalPlayer->team == TEAM_SPEC); +} + +bool UnassignedClass() { + return g_pLocalPlayer->clazz != int(preferred_class); +} + +void UpdateSearch() { + if (!auto_queue) return; + if (g_IEngine->IsInGame()) return; + static auto last_check = std::chrono::system_clock::now(); + auto s = std::chrono::duration_cast(std::chrono::system_clock::now() - last_check).count(); + if (s < 4) return; + + if (g_TFGCClientSystem->GetState() == 6) { + logging::Info("Sending MM request"); + g_TFGCClientSystem->RequestSelectWizardStep(4); + } + + last_check = std::chrono::system_clock::now(); +} + +void Update() { + static auto last_check = std::chrono::system_clock::now(); + auto ms = std::chrono::duration_cast(std::chrono::system_clock::now() - last_check).count(); + + if (ms < 500) { + return; + } + + if (autojoin_team and UnassignedTeam()) { + hack::ExecuteCommand("jointeam auto"); + } else if (preferred_class and UnassignedClass()) { + if (int(preferred_class) < 10) + g_IEngine->ExecuteClientCmd(format("join_class ", classnames[int(preferred_class) - 1]).c_str()); + } +} + +}}} diff --git a/src/hacks/AutoJoin.hpp b/src/hacks/AutoJoin.hpp new file mode 100644 index 00000000..8bab3d30 --- /dev/null +++ b/src/hacks/AutoJoin.hpp @@ -0,0 +1,15 @@ +/* + * AutoJoin.hpp + * + * Created on: Jul 28, 2017 + * Author: nullifiedcat + */ + +#pragma once + +namespace hacks { namespace shared { namespace autojoin { + +void Update(); +void UpdateSearch(); + +}}} diff --git a/src/hacks/Bunnyhop.cpp b/src/hacks/Bunnyhop.cpp index e2256c03..92ffc498 100644 --- a/src/hacks/Bunnyhop.cpp +++ b/src/hacks/Bunnyhop.cpp @@ -21,6 +21,7 @@ int iTicksLastJump = 0; void CreateMove() { // Check user settings if bhop is enabled if (!enabled) return; + if (!g_pUserCmd) return; // Check if there is usercommands if (!g_pUserCmd->command_number) return; diff --git a/src/hacks/Spam.h b/src/hacks/Spam.h index 948b1a3e..8b94c7a4 100644 --- a/src/hacks/Spam.h +++ b/src/hacks/Spam.h @@ -21,7 +21,7 @@ extern const std::vector builtin_nonecore; extern const std::vector builtin_lmaobox; extern const std::vector builtin_lithium; -extern CatVar enabled; +extern CatVar spam_source; extern CatVar filename; extern CatCommand reload; diff --git a/src/hacks/Walkbot.cpp b/src/hacks/Walkbot.cpp index e2926b9b..a63c803d 100644 --- a/src/hacks/Walkbot.cpp +++ b/src/hacks/Walkbot.cpp @@ -6,7 +6,7 @@ */ #include "../common.h" - +#include "../hack.h" #include #include @@ -25,7 +25,7 @@ index_t CreateNode(const Vector& xyz); void DeleteNode(index_t node); float distance_2d(Vector& xyz); void Save(std::string filename); -void Load(std::string filename); +bool Load(std::string filename); enum ENodeFlags { NF_GOOD = (1 << 0), @@ -265,7 +265,7 @@ void Save(std::string filename) { } } -void Load(std::string filename) { +bool Load(std::string filename) { { DIR* walkbot_dir = opendir("cathook/walkbot"); if (!walkbot_dir) { @@ -277,19 +277,22 @@ void Load(std::string filename) { { DIR* level_dir = opendir(path.c_str()); if (!level_dir) { - logging::Info("Walkbot directory for %s doesn't exist, creating one!", GetLevelName()); + logging::Info("Walkbot directory for %s doesn't exist, creating one!", GetLevelName().c_str()); mkdir(path.c_str(), S_IRWXU | S_IRWXG); } else closedir(level_dir); } try { std::ifstream file(format(path, "/", filename), std::ios::in | std::ios::binary); + if (!file) { + return false; + } walkbot_header_s header; BINARY_FILE_READ(file, header); // FIXME magic number: 1 if (header.version != VERSION) { logging::Info("Outdated/corrupted walkbot file! Cannot load this."); file.close(); - return; + return false; } if (header.author_length > 64 or header.map_length > 512 or (not header.author_length or not header.map_length)) { logging::Info("Corrupted author/level data"); @@ -306,15 +309,17 @@ void Load(std::string filename) { logging::Info("Reading %i entries...", header.node_count); if (header.node_count > 32768) { logging::Info("Read %d nodes, max is %d. Aborting.", header.node_count, 32768); - return; + return false; } state::nodes.resize(header.node_count); file.read(reinterpret_cast(state::nodes.data()), sizeof(walkbot_node_s) * header.node_count); file.close(); logging::Info("Reading successful! Result: %i entries.", state::nodes.size()); + return true; } catch (std::exception& e) { logging::Info("Reading unsuccessful: %s", e.what()); } + return false; } static CatCommand save("wb_save", "Save", [](const CCommand& args) { @@ -354,6 +359,8 @@ CatVar spawn_distance(CV_FLOAT, "wb_node_spawn_distance", "54", "Node spawn dist CatVar max_distance(CV_FLOAT, "wb_replay_max_distance", "100", "Max distance to node when replaying"); CatVar reach_distance(CV_FLOAT, "wb_replay_reach_distance", "32", "Distance where bot can be considered 'stepping' on the node"); CatVar draw_connection_flags(CV_SWITCH, "wb_connection_flags", "1", "Connection flags"); +CatVar force_slot(CV_INT, "wb_force_slot", "1", "Force slot", "Walkbot will always select weapon in this slot"); +CatVar leave_if_empty(CV_SWITCH, "wb_leave_if_empty", "0", "Leave if no walkbot", "Leave game if there is no walkbot map"); CatCommand c_start_recording("wb_record", "Start recording", []() { state::state = WB_RECORDING; }); CatCommand c_start_editing("wb_edit", "Start editing", []() { state::state = WB_EDITING; }); @@ -681,6 +688,22 @@ index_t SelectNextNode() { bool free_move_used = false; +void UpdateSlot() { + static auto last_check = std::chrono::system_clock::now(); + auto ms = std::chrono::duration_cast(std::chrono::system_clock::now() - last_check).count(); + + if (CE_GOOD(LOCAL_E) && CE_GOOD(LOCAL_W) && !g_pLocalPlayer->life_state && ms > 1000) { + IClientEntity* weapon = RAW_ENT(LOCAL_W); + // IsBaseCombatWeapon() + if (vfunc(weapon, 190, 0)(weapon)) { + int slot = vfunc(weapon, 395, 0)(weapon); + if (slot != int(force_slot) - 1) { + hack::ExecuteCommand(format("slot", int(force_slot))); + } + } + } +} + void UpdateWalker() { free_move_used = false; if (free_move) { @@ -891,6 +914,12 @@ void Draw() { DrawPath(); } +void OnLevelInit() { + if (leave_if_empty && state::state == WB_REPLAYING) { + nodes.clear(); + } +} + void Move() { if (state::state == WB_DISABLED) return; switch (state::state) { @@ -904,6 +933,25 @@ void Move() { UpdateClosestNode(); } break; case WB_REPLAYING: { + if (leave_if_empty) { + if (nodes.size() == 0) { + Load("default"); + if (nodes.size() == 0) { + static auto last_abandon = std::chrono::system_clock::from_time_t(0); + auto s = std::chrono::duration_cast(std::chrono::system_clock::now() - last_abandon).count(); + + if (s < 3) { + return; + } + logging::Info("No map file, shutting down"); + g_TFGCClientSystem->SendExitMatchmaking(true); + last_abandon = std::chrono::system_clock::now(); + } + } + } + if (nodes.size() == 0) return; + if (force_slot) + UpdateSlot(); UpdateWalker(); } break; } diff --git a/src/hacks/Walkbot.hpp b/src/hacks/Walkbot.hpp index 59c0e526..9494b69f 100644 --- a/src/hacks/Walkbot.hpp +++ b/src/hacks/Walkbot.hpp @@ -12,5 +12,6 @@ namespace hacks { namespace shared { namespace walkbot { void Initialize(); void Draw(); void Move(); +void OnLevelInit(); }}} diff --git a/src/hacks/hacklist.h b/src/hacks/hacklist.h index 8dcaffbb..adf99b14 100644 --- a/src/hacks/hacklist.h +++ b/src/hacks/hacklist.h @@ -19,6 +19,7 @@ #include "ESP.h" #include "LagExploit.hpp" #include "Walkbot.hpp" +#include "AutoJoin.hpp" #include "AntiBackstab.hpp" #include "AutoBackstab.hpp" #include "FollowBot.h" diff --git a/src/hooks/CreateMove.cpp b/src/hooks/CreateMove.cpp index eb8b2d94..2bc9f64e 100644 --- a/src/hooks/CreateMove.cpp +++ b/src/hooks/CreateMove.cpp @@ -204,6 +204,9 @@ bool CreateMove_hook(void* thisptr, float inputSample, CUserCmd* cmd) { SAFE_CALL(g_pLocalPlayer->Update()); } g_Settings.bInvalid = false; + + hacks::shared::autojoin::Update(); + #ifdef IPC_ENABLED static int team_joining_state = 0; static float last_jointeam_try = 0; @@ -271,6 +274,10 @@ bool CreateMove_hook(void* thisptr, float inputSample, CUserCmd* cmd) { PROF_SECTION(CM_walkbot); SAFE_CALL(hacks::shared::walkbot::Move()); } + // Walkbot can leave game. + if (!g_IEngine->IsInGame()) { + return ret; + } IF_GAME (IsTF()) { PROF_SECTION(CM_uberspam); SAFE_CALL(hacks::tf::uberspam::CreateMove()); diff --git a/src/hooks/PaintTraverse.cpp b/src/hooks/PaintTraverse.cpp index 4c5a07b4..1978ec0d 100644 --- a/src/hooks/PaintTraverse.cpp +++ b/src/hooks/PaintTraverse.cpp @@ -87,6 +87,8 @@ void PaintTraverse_hook(void* _this, unsigned int vp, bool fr, bool ar) { PROF_SECTION(PT_total); + hacks::shared::autojoin::UpdateSearch(); + if (vp == panel_top) draw_flag = true; if (!cathook) return; diff --git a/src/hooks/others.cpp b/src/hooks/others.cpp index 16cb0298..eac55913 100644 --- a/src/hooks/others.cpp +++ b/src/hooks/others.cpp @@ -459,6 +459,7 @@ void LevelInit_hook(void* _this, const char* newmap) { chat_stack::Reset(); hacks::shared::anticheat::ResetEverything(); original(_this, newmap); + hacks::shared::walkbot::OnLevelInit(); } void LevelShutdown_hook(void* _this) { diff --git a/src/interfaces.cpp b/src/interfaces.cpp index c4db0b3d..37668f27 100644 --- a/src/interfaces.cpp +++ b/src/interfaces.cpp @@ -49,6 +49,7 @@ IMaterialSystem* g_IMaterialSystemHL = nullptr; IMoveHelperServer* g_IMoveHelperServer = nullptr; CBaseClientState* g_IBaseClientState = nullptr; IGameEventManager* g_IGameEventManager = nullptr; +TFGCClientSystem* g_TFGCClientSystem = nullptr; CHud* g_CHUD = nullptr; template @@ -141,5 +142,14 @@ void CreateInterfaces() { g_CHUD = *reinterpret_cast(hud_sig); logging::Info("HUD 0x%08x 0x%08x", hud_sig, g_CHUD); } + IF_GAME (IsTF2()) { + uintptr_t gcsystem_sig = gSignatures.GetClientSignature("E8 ? ? ? ? C7 44 24 04 04 00 00 00 89 04 24 E8 ? ? ? ? E9 17 FF FF FF") + 1; + typedef TFGCClientSystem*(*func_t)(void); + logging::Info("GCSystem = 0x%08x", gcsystem_sig); + uintptr_t gcc_p = *(uintptr_t*)(gcsystem_sig); + func_t get_gc = (gcc_p + gcsystem_sig + 4); + logging::Info("GTFGCClientSystem() = 0x%08x", get_gc); + g_TFGCClientSystem = get_gc(); + } } diff --git a/src/interfaces.h b/src/interfaces.h index 801a8412..1407c5c3 100644 --- a/src/interfaces.h +++ b/src/interfaces.h @@ -51,7 +51,9 @@ class IMoveHelperServer; class CBaseClientState; class CHud; class IGameEventManager; +class TFGCClientSystem; +extern TFGCClientSystem* g_TFGCClientSystem; extern CHud* g_CHUD; extern ISteamClient* g_ISteamClient; extern ISteamFriends* g_ISteamFriends; diff --git a/src/sdk.h b/src/sdk.h index 40780b28..b66be2a8 100644 --- a/src/sdk.h +++ b/src/sdk.h @@ -54,6 +54,7 @@ #include #include +#include "sdk/TFGCClientSystem.hpp" #include "sdk/in_buttons.h" #include "sdk/imaterialsystemfixed.h" #include "sdk/ScreenSpaceEffects.h" diff --git a/src/sdk/TFGCClientSystem.cpp b/src/sdk/TFGCClientSystem.cpp new file mode 100644 index 00000000..56644b4d --- /dev/null +++ b/src/sdk/TFGCClientSystem.cpp @@ -0,0 +1,31 @@ +/* + * TFGCClientSystem.cpp + * + * Created on: Jul 28, 2017 + * Author: nullifiedcat + */ + +#include "../copypasted/CSignature.h" +#include "TFGCClientSystem.hpp" +#include "../logging.h" + + +int TFGCClientSystem::RequestSelectWizardStep(int type) { + static uintptr_t RequestSelectWizardStep_loc = gSignatures.GetClientSignature("55 89 E5 57 56 53 83 EC 1C 8B 5D 08 8B 75 0C 89 1C 24 E8 ? ? ? ? 84 C0 75 0D 83 C4 1C 5B 5E 5F 5D C3 90 8D 74 26 00 89 1C 24 E8 ? ? ? ? 85 C0"); + typedef int(*RequestSelectWizardStep_t)(TFGCClientSystem*, int); + static RequestSelectWizardStep_t RequestSelectWizardStep_fn = (RequestSelectWizardStep_t)RequestSelectWizardStep_loc; + return RequestSelectWizardStep_fn(this, 4); +} + +int TFGCClientSystem::GetState() { + return *(int*)((uintptr_t)this + 1136); +} + +/* 55 89 E5 57 56 8D 75 C8 53 81 EC 8C 00 00 00 8B 45 0C C7 04 24 ? ? ? ? 8B 5D 08 89 45 A4 0F B6 C0 89 44 24 04 E8 ? ? ? ? C7 44 24 04 91 18 00 00 89 34 24 E8 ? ? ? ? A1 ? ? ? ? */ +int TFGCClientSystem::SendExitMatchmaking(bool abandon) { + static uintptr_t SendExitMatchmaking_loc = gSignatures.GetClientSignature("55 89 E5 57 56 8D 75 C8 53 81 EC 8C 00 00 00 8B 45 0C C7 04 24 ? ? ? ? 8B 5D 08 89 45 A4 0F B6 C0 89 44"); + typedef int(*SendExitMatchmaking_t)(TFGCClientSystem*, char); + static SendExitMatchmaking_t SendExitMatchmaking_fn = (SendExitMatchmaking_t)SendExitMatchmaking_loc; + logging::Info("Calling 0x%08x", SendExitMatchmaking_fn); + return SendExitMatchmaking_fn(this, abandon); +} diff --git a/src/sdk/TFGCClientSystem.hpp b/src/sdk/TFGCClientSystem.hpp new file mode 100644 index 00000000..c49b063d --- /dev/null +++ b/src/sdk/TFGCClientSystem.hpp @@ -0,0 +1,17 @@ +/* + * TFGCClientSystem.hpp + * + * Created on: Jul 28, 2017 + * Author: nullifiedcat + */ + +#pragma once + +class TFGCClientSystem { +public: + int RequestSelectWizardStep(int type); + int GetState(); + /* 55 89 E5 57 56 8D 75 C8 53 81 EC 8C 00 00 00 8B 45 0C C7 04 24 ? ? ? ? 8B 5D 08 89 45 A4 0F B6 C0 89 44 24 04 E8 ? ? ? ? C7 44 24 04 91 18 00 00 89 34 24 E8 ? ? ? ? A1 ? ? ? ? */ + int SendExitMatchmaking(bool abandon); +}; +