From 6b7512d27db66b05e343ee77e2a474a1d0b33604 Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sat, 23 Jun 2018 14:33:49 +0300 Subject: [PATCH 01/18] add co-library --- .gitmodules | 3 ++ CMakeLists.txt | 2 + external/co-library | 1 + include/CMakeLists.txt | 1 + include/online/CMakeLists.txt | 2 + include/online/Online.hpp | 39 ++++++++++++++++ src/CMakeLists.txt | 1 + src/online/CMakeLists.txt | 2 + src/online/Online.cpp | 84 +++++++++++++++++++++++++++++++++++ 9 files changed, 135 insertions(+) create mode 160000 external/co-library create mode 100644 include/online/CMakeLists.txt create mode 100644 include/online/Online.hpp create mode 100644 src/online/CMakeLists.txt create mode 100644 src/online/Online.cpp diff --git a/.gitmodules b/.gitmodules index 9ec01a35..7d352beb 100755 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "ucccccp"] path = external/ucccccp url = https://github.com/nullworks/ucccccp.git +[submodule "external/co-library"] + path = external/co-library + url = git@gitcat:nullworks/co-library.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 5468a864..3f645c55 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,8 @@ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_BUILD_TYPE_VALUES}) cmake_minimum_required(VERSION 3.0) project(cathook VERSION 0.0.1) + +set(CMAKE_CXX_STANDARD 17) add_library(cathook SHARED "") set(GameSpecific 1 CACHE BOOL "Build for specific target game (As opposed to universal, but slower, lib)") diff --git a/external/co-library b/external/co-library new file mode 160000 index 00000000..2ef3cc54 --- /dev/null +++ b/external/co-library @@ -0,0 +1 @@ +Subproject commit 2ef3cc54de653472e5d5c422b5a86e263a75f606 diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 744abdef..d9dd893b 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -50,6 +50,7 @@ add_subdirectory(hacks) add_subdirectory(hooks) add_subdirectory(reclasses) add_subdirectory(sdk) +add_subdirectory(online) if(EnableVisuals) add_subdirectory(visual) diff --git a/include/online/CMakeLists.txt b/include/online/CMakeLists.txt new file mode 100644 index 00000000..a08e5342 --- /dev/null +++ b/include/online/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(cathook PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/Online.hpp") \ No newline at end of file diff --git a/include/online/Online.hpp b/include/online/Online.hpp new file mode 100644 index 00000000..b05eac2f --- /dev/null +++ b/include/online/Online.hpp @@ -0,0 +1,39 @@ +/* + Created on 23.06.18. +*/ + +#pragma once + +#include +#include +#include +#include + +namespace online +{ + +struct user_data +{ + bool is_anonymous{ false }; + bool is_using_friendly_software{ false }; + std::string username{}; + std::vector shown_roles{}; +#if ENABLE_VISUALS + colors::rgba_t color{}; + bool rainbow{ false }; +#endif +}; + +/* + * Initialize everything, login if key is saved + */ +void init(); + +/* + * Identify unidentified users, send online status, etc + */ +void update(); + +user_data *getUserData(unsigned steamId); + +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 944a3379..40ab4493 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -41,6 +41,7 @@ add_subdirectory(hacks) add_subdirectory(hooks) add_subdirectory(reclasses) add_subdirectory(sdk) +add_subdirectory(online) if(EnableVisuals) add_subdirectory(visual) diff --git a/src/online/CMakeLists.txt b/src/online/CMakeLists.txt new file mode 100644 index 00000000..ecbbb1c2 --- /dev/null +++ b/src/online/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(cathook PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/Online.cpp") \ No newline at end of file diff --git a/src/online/Online.cpp b/src/online/Online.cpp new file mode 100644 index 00000000..17f2e484 --- /dev/null +++ b/src/online/Online.cpp @@ -0,0 +1,84 @@ +/* + Created on 23.06.18. +*/ + +#include + +#include +#include +#include +#include + +namespace online +{ + +static std::unordered_map> data{}; +static std::unordered_map identify_queue{}; +static Timer identify_timer{}; +static bool identify_stale{ false }; + +// INTERNAL METHODS + +void queueUserForIdentification(unsigned steamId) +{ + + identify_queue.insert(steamId); + identify_timer.update(); + identify_stale = true; +} + +void processIdentifyResponse() +{ + +} + +void sendIdentifyRequest() +{ + std::vector steamIds{}; + auto it = identify_queue.begin(); + // Create a list of up to 32 steamId's + for (int i = 0; i < 32 && it != identify_queue.end(); ++i, ++it) + { + if (!it->second) + it->second = true; + steamIds.push_back(it->first); + } + +} + +// EXTERNAL METHODS + +void init() +{ + +} + +void update() +{ + // Only send a request after 3 seconds passed since last unknown steamId was added to the queue + if (identify_stale && identify_timer.check(3000)) + { + sendIdentifyRequest(); + identify_stale = false; + } +} + +user_data *getUserData(unsigned steamId) +{ + auto it = data.find(steamId); + // User not identified + if (it == data.end()) + { + // Queue user for identification + if (identify_queue.find(steamId) == identify_queue.end()) + queueUserForIdentification(steamId); + return nullptr; + } + // SteamID belongs to online user + if (it->second.has_value()) + return &*it->second; + // SteamID does not belong to online user + return nullptr; +} + +} \ No newline at end of file From 7262f1f4fcf26bf96d782ccf23ee8dc4f7dbc5c1 Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sat, 23 Jun 2018 16:31:12 +0200 Subject: [PATCH 02/18] FollowBot is better now + changed AutoUber --- src/hacks/AutoHeal.cpp | 14 +++++++++-- src/hacks/FollowBot.cpp | 50 +++++++++++++++++++++++++++++--------- src/visual/EffectChams.cpp | 8 +----- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/src/hacks/AutoHeal.cpp b/src/hacks/AutoHeal.cpp index ec665eed..d733697d 100644 --- a/src/hacks/AutoHeal.cpp +++ b/src/hacks/AutoHeal.cpp @@ -28,7 +28,7 @@ int m_iNewTarget{ 0 }; static CatVar pop_uber_auto(CV_SWITCH, "autoheal_uber", "1", "AutoUber", "Use ubercharge automatically"); static CatVar - pop_uber_percent(CV_FLOAT, "autoheal_uber_health", "30", + pop_uber_percent(CV_FLOAT, "autoheal_uber_health", "0", "Pop uber if health% <", "When under a percentage of health, use ubercharge"); static CatVar share_uber( @@ -355,9 +355,17 @@ bool IsPopped() bool ShouldChargePlayer(int idx) { CachedEntity *target = ENTITY(idx); + const int health = target->m_iHealth(); + if (float(pop_uber_percent) > 0) + { + const float pophealth = target->m_iMaxHealth() * (float(pop_uber_percent) / 100); + if (health < pophealth) + return true; + } + else + { const float damage_accum_duration = g_GlobalVars->curtime - data[idx].accum_damage_start; - const int health = target->m_iHealth(); if (!data[idx].accum_damage_start) return false; if (health > 30 && data[idx].accum_damage < 45) @@ -370,6 +378,8 @@ bool ShouldChargePlayer(int idx) if (health < 30 && data[idx].accum_damage > 10) return true; return false; + } + return false; } bool ShouldPop() diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index 424101cb..2dfcdbdc 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace hacks { @@ -51,12 +52,16 @@ static CatVar sync_taunt(CV_SWITCH, "fb_sync_taunt", "0", "Synced taunt", "Taunt when follow target does"); static CatVar change(CV_SWITCH, "fb_switch", "1", "Change followbot target", "Always change roaming target when possible"); +static CatVar autojump(CV_SWITCH, "fb_autojump", "1", "Autojump", + "Automatically jump if stuck"); + // Something to store breadcrumbs created by followed players static std::vector breadcrumbs; static const int crumb_limit = 64; // limit // Followed entity, externed for highlight color int follow_target = 0; +long int lasttaunt; void WorldTick() { @@ -159,22 +164,36 @@ void WorldTick() if (!follow_target) return; - // If the player is close enough, we dont need to follow the path CachedEntity *followtar = ENTITY(follow_target); // wtf is this needed if (CE_BAD(followtar)) return; - auto tar_orig = followtar->m_vecOrigin(); - auto loc_orig = LOCAL_E->m_vecOrigin(); - auto dist_to_target = loc_orig.DistTo(tar_orig); - if (dist_to_target < 30) - breadcrumbs.clear(); - // Update timer on new target static Timer idle_time{}; if (breadcrumbs.empty()) idle_time.update(); + // If the player is close enough, we dont need to follow the path + auto tar_orig = followtar->m_vecOrigin(); + auto loc_orig = LOCAL_E->m_vecOrigin(); + auto dist_to_target = loc_orig.DistTo(tar_orig); + if (roambot) + { + if ((dist_to_target < (float)follow_distance) && VisCheckEntFromEnt(LOCAL_E, followtar)) + { + breadcrumbs.clear(); + idle_time.update(); + } + } + else + { + if (dist_to_target < 30) + { + breadcrumbs.clear(); + idle_time.update(); + } + } + // New crumbs, we add one if its empty so we have something to follow if ((breadcrumbs.empty() || tar_orig.DistTo(breadcrumbs.at(breadcrumbs.size() - 1)) > 40.0F) && @@ -189,20 +208,29 @@ void WorldTick() breadcrumbs.erase(breadcrumbs.begin()); } + //moved because its worthless otherwise + if (sync_taunt && HasCondition(followtar)) { + //std::time_t time = std::time(nullptr); + long int t = static_cast (std::time(nullptr)); + if (!(t == lasttaunt)) + { + lasttaunt = t; + g_IEngine->ClientCmd("taunt"); + } + } + // Follow the crumbs when too far away, or just starting to follow if (dist_to_target > (float) follow_distance) { // Check for idle - if (idle_time.check(3000) || - (breadcrumbs.size() > 1 && LOCAL_E->m_vecVelocity.IsZero(5.0f))) + if (autojump && (idle_time.check(3000) || + (breadcrumbs.size() > 1 && LOCAL_E->m_vecVelocity.IsZero(5.0f)))) g_pUserCmd->buttons |= IN_JUMP; if (idle_time.test_and_set(5000)) { follow_target = 0; return; } - if (sync_taunt && HasCondition(ENTITY(follow_target))) - g_IEngine->ClientCmd("taunt"); static float last_slot_check = 0.0f; if (g_GlobalVars->curtime < last_slot_check) last_slot_check = 0.0f; diff --git a/src/visual/EffectChams.cpp b/src/visual/EffectChams.cpp index 55dec1e0..5ca3625a 100644 --- a/src/visual/EffectChams.cpp +++ b/src/visual/EffectChams.cpp @@ -222,8 +222,6 @@ rgba_t EffectChams::ChamsColor(IClientEntity *entity) bool EffectChams::ShouldRenderChams(IClientEntity *entity) { - if (!enable) - return false; if (entity->entindex() < 0) return false; CachedEntity *ent = ENTITY(entity->entindex()); @@ -366,11 +364,7 @@ void EffectChams::Render(int x, int y, int w, int h) BeginRenderChams(); for (int i = 1; i < HIGHEST_ENTITY; i++) { - IClientEntity *ent = g_IEntityList->GetClientEntity(i); - if (ent && !ent->IsDormant()) - { - RenderChams(i); - } + RenderChams(i); } EndRenderChams(); } From df59f6b2c04e49f7ce0ae017f7dfb5da6e806177 Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sat, 23 Jun 2018 17:56:01 +0300 Subject: [PATCH 03/18] Cathook:Online:tm: - alpha --- CMakeLists.txt | 6 ++ include/online/Online.hpp | 9 +- include/visual/colors.hpp | 2 + src/hack.cpp | 13 +-- src/hacks/ESP.cpp | 22 ++++- src/hooks/Paint.cpp | 2 + src/online/Online.cpp | 196 ++++++++++++++++++++++++++++++++++++-- src/visual/colors.cpp | 40 ++++++++ 8 files changed, 268 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f645c55..ce8916c5 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ set(Textmode 0 CACHE BOOL "Various textmode-only features for bots") set(EnableTextmodeStdin 0 CACHE BOOL "Textmode Stdin -> Console bridge (EXPERIMENTAL)") set(EnableWarnings 1 CACHE BOOL "Enable compile warnings") set(EnableNullGraphics 0 CACHE BOOL "Enable experimental textmode hooks (CRASHES)") +set(EnableOnlineFeatures 1 CACHE BOOL "Enable online features (WIP)") if(NOT EnableVisuals) set(EnableGUI 0) @@ -64,6 +65,11 @@ if(EnableIPC) target_link_libraries(cathook SimpleIPC) endif() +if(EnableOnlineFeatures) + add_subdirectory(external/co-library) + target_link_libraries(cathook co-library) +endif() + if(EnableVisuals) add_subdirectory(external/libglez) target_include_directories(cathook PRIVATE include/visual) diff --git a/include/online/Online.hpp b/include/online/Online.hpp index b05eac2f..59396549 100644 --- a/include/online/Online.hpp +++ b/include/online/Online.hpp @@ -16,19 +16,18 @@ struct user_data { bool is_anonymous{ false }; bool is_using_friendly_software{ false }; + bool is_steamid_verified{ false }; std::string username{}; std::vector shown_roles{}; + std::string software_name{}; + bool has_software{ false }; #if ENABLE_VISUALS + bool has_color{ false }; colors::rgba_t color{}; bool rainbow{ false }; #endif }; -/* - * Initialize everything, login if key is saved - */ -void init(); - /* * Identify unidentified users, send online status, etc */ diff --git a/include/visual/colors.hpp b/include/visual/colors.hpp index 416e2575..03a36226 100755 --- a/include/visual/colors.hpp +++ b/include/visual/colors.hpp @@ -48,6 +48,8 @@ struct rgba_t constexpr rgba_t(float _r, float _g, float _b, float _a = 1.0f) : r(_r), g(_g), b(_b), a(_a){}; + explicit rgba_t(const char hex[6]); + constexpr operator glez::rgba() const { return *reinterpret_cast(this); diff --git a/src/hack.cpp b/src/hack.cpp index 2416049c..1d203214 100644 --- a/src/hack.cpp +++ b/src/hack.cpp @@ -532,6 +532,13 @@ free(logname);*/ #if ENABLE_VISUALS hacks::shared::esp::Init(); #endif +#if not ENABLE_VISUALS + hack::command_stack().push("exec cat_autoexec_textmode"); +#endif + hack::command_stack().push("exec cat_autoexec"); + hack::command_stack().push("cat_killsay_reload"); + hack::command_stack().push("cat_spam_reload"); + logging::Info("Clearing initializer stack"); while (!init_stack().empty()) { @@ -540,12 +547,6 @@ free(logname);*/ } logging::Info("Initializer stack done"); -#if not ENABLE_VISUALS - hack::command_stack().push("exec cat_autoexec_textmode"); -#endif - hack::command_stack().push("exec cat_autoexec"); - hack::command_stack().push("cat_killsay_reload"); - hack::command_stack().push("cat_spam_reload"); hack::initialized = true; } diff --git a/src/hacks/ESP.cpp b/src/hacks/ESP.cpp index 1f886bf3..23eea7c1 100644 --- a/src/hacks/ESP.cpp +++ b/src/hacks/ESP.cpp @@ -7,6 +7,7 @@ #include #include +#include #include "common.hpp" namespace hacks @@ -150,6 +151,11 @@ static CatVar entity_model(CV_SWITCH, "esp_model_name", "0", "Model name ESP", static CatVar entity_id(CV_SWITCH, "esp_entity_id", "1", "Entity ID", "Used with Entity ESP. Shows entityID"); +// Online +static CatVar online(CV_SWITCH, "esp_online", "1", "Show online info", "Username, etc"); +static CatVar online_roles(CV_SWITCH, "esp_online_roles", "1", "Show online roles", "Admin, developer, etc"); +static CatVar online_software(CV_SWITCH, "esp_online_software", "1", "Show software", "cathook, lmaobox, etc"); + // CatVar draw_hitbox(CV_SWITCH, "esp_hitbox", "1", "Draw Hitbox"); // Unknown @@ -1155,10 +1161,12 @@ void _FASTCALL ProcessEntity(CachedEntity *ent) if (!g_IEngine->GetPlayerInfo(ent->m_IDX, &info)) return; + online::user_data *data = online ? online::getUserData(info.friendsID) : nullptr; + // TODO, check if u can just use "ent->m_bEnemy()" instead of m_iTeam // Legit mode handling if (legit && ent->m_iTeam() != g_pLocalPlayer->team && - playerlist::IsDefault(info.friendsID)) + playerlist::IsDefault(info.friendsID) && !(data)) { if (IsPlayerInvisible(ent)) return; // Invis check @@ -1170,6 +1178,18 @@ void _FASTCALL ProcessEntity(CachedEntity *ent) // return; } + if (data) + { + AddEntityString(ent, "CO: " + data->username, colors::yellow); + if (data->is_steamid_verified) + AddEntityString(ent, "Verified SteamID", colors::green); + if (online_roles) + for (auto& s: data->shown_roles) + AddEntityString(ent, s, colors::orange); + if (online_software && data->has_software) + AddEntityString(ent, "Software: " + data->software_name); + } + // Powerup handling if (powerup_esp) { diff --git a/src/hooks/Paint.cpp b/src/hooks/Paint.cpp index 6e1fc4a7..5fd4d6cb 100644 --- a/src/hooks/Paint.cpp +++ b/src/hooks/Paint.cpp @@ -6,6 +6,7 @@ */ #include +#include #include "common.hpp" #include "hitrate.hpp" #include "hack.hpp" @@ -31,6 +32,7 @@ DEFINE_HOOKED_METHOD(Paint, void, IEngineVGui *this_, PaintMode_t mode) { hitrate::Update(); } + online::update(); #if ENABLE_IPC static Timer nametimer{}; if (nametimer.test_and_set(1000 * 10)) diff --git a/src/online/Online.cpp b/src/online/Online.cpp index 17f2e484..e3acbd7d 100644 --- a/src/online/Online.cpp +++ b/src/online/Online.cpp @@ -3,33 +3,159 @@ */ #include +#include #include #include #include #include +#undef null + +#include +#include +#include +#include + namespace online { +void saveApiKey(); +void claimSteamId(); + +static co::OnlineService cathookOnlineService{}; static std::unordered_map> data{}; static std::unordered_map identify_queue{}; static Timer identify_timer{}; static bool identify_stale{ false }; +static std::string api_key{}; + +static CatVar enable(CV_SWITCH, "online", "1", "Enable online features"); +static CatCommand login("online_login", "Login", [](const CCommand& args) { + if (args.ArgC() != 2) + { + logging::Info("\nUsage: online_login \nKey will be saved in your data folder"); + return; + } + std::string key(args.Arg(1)); + try + { + cathookOnlineService.login(key, [key](co::ApiCallResult result, std::optional me) { + if (result == co::ApiCallResult::OK) + { + logging::Info("[CO] Successfully logged in. Welcome, %s", me->username.c_str()); + api_key = key; + saveApiKey(); + claimSteamId(); + } + else + { + logging::Info("[CO] There was an error logging in: code %d", result); + } + }); + } catch (std::exception& ex) { + logging::Info("[CO] Exception: %s", ex.what()); + } +}); +static CatCommand flush("online_flush_cache", "Flush player cache", [](const CCommand& args) { + data.clear(); + identify_queue.clear(); + identify_stale = true; +}); +static CatVar host(CV_STRING, "online_host", "localhost:8000", "Online host"); // INTERNAL METHODS +void claimSteamId() +{ + auto id = g_ISteamUser->GetSteamID(); + logging::Info("[CO] Claiming SteamID %u", id.GetAccountID()); + cathookOnlineService.gameStartup(id.GetAccountID()); +} + +bool tryLoadApiKey() +{ + std::ifstream keyfile(DATA_PATH "/api_key", std::ios::in); + if (keyfile) + { + keyfile >> api_key; + if (!api_key.empty()) + return true; + } + return false; +} + +void saveApiKey() +{ + std::ofstream keyfile(DATA_PATH "/api_key", std::ios::out); + if (!keyfile) + { + logging::Info("[CO] Something went wrong while saving API key"); + return; + } + keyfile << api_key << '\n'; +} + void queueUserForIdentification(unsigned steamId) { - identify_queue.insert(steamId); + identify_queue[steamId] = false; identify_timer.update(); identify_stale = true; } -void processIdentifyResponse() +void markSteamIdNonOnline(unsigned id) { + logging::Info("[CO] %u - not online", id); + data[id] = std::nullopt; +} +void processOnlineIdentity(unsigned id, co::identified_user& user) +{ + logging::Info("[CO] %u - online", id); + user_data udata{}; + udata.username = user.username; + udata.is_anonymous = (user.username == "anonymous"); + udata.is_steamid_verified = user.steamid_verified; + for (auto& i: user.roles) + { + if (i.display_name.has_value()) + udata.shown_roles.push_back(*i.display_name); +#if ENABLE_VISUALS + if (i.name == "owner") + udata.rainbow = true; +#endif + } +#if ENABLE_VISUALS + if (user.color.has_value()) + { + udata.has_color = true; + udata.color = colors::rgba_t(user.color->c_str()); + } +#endif + if (user.uses_software.has_value()) + { + udata.has_software = true; + udata.is_using_friendly_software = user.uses_software->friendly; + udata.software_name = user.uses_software->name; + } + data[id] = std::move(udata); +} + +void processIdentifyResponse(std::vector input, co::identified_group& group) +{ + logging::Info("[CO] Processing identify response containing %u / %u entries", group.users.size(), input.size()); + for (auto i: input) + { + auto u = group.users.find(i); + if (u == group.users.end()) + markSteamIdNonOnline(i); + else + processOnlineIdentity(i, (*u).second); + + identify_queue.erase(i); + logging::Info("[CO] Removed %u from identify queue, left %u\n", i, identify_queue.size()); + } } void sendIdentifyRequest() @@ -40,31 +166,81 @@ void sendIdentifyRequest() for (int i = 0; i < 32 && it != identify_queue.end(); ++i, ++it) { if (!it->second) + { it->second = true; - steamIds.push_back(it->first); + steamIds.push_back(it->first); + } } - + logging::Info("[CO] Sending identify request for %u players", steamIds.size()); + cathookOnlineService.userIdentify(steamIds, (std::function)>)[steamIds](co::ApiCallResult result, std::optional group) { + if (result == co::ApiCallResult::OK) + { + processIdentifyResponse(steamIds, *group); + } + else + { + logging::Info("[CO] Something went wrong while identifying %u players: code %d", steamIds.size(), result); + for (auto i: steamIds) + { + identify_queue[i] = false; + } + identify_stale = true; + } + }); } +InitRoutine init([]() { + cathookOnlineService.setErrorHandler((std::function)[](std::string error) { + logging::Info("[CO] Error: %s", error.c_str()); + }); + host.InstallChangeCallback([](IConVar *var, const char *pszOldValue, float flOldValue) { + logging::Info("[CO] Host = %s", host.GetString()); + cathookOnlineService.setHost(host.GetString()); + }); + if (tryLoadApiKey()) + { + logging::Info("[CO] API key loaded successfully"); + cathookOnlineService.login(api_key, [](co::ApiCallResult result, std::optional me) { + if (result == co::ApiCallResult::OK) + { + logging::Info("[CO] Successfully logged in. Welcome, %s", me->username.c_str()); + claimSteamId(); + } + else + { + logging::Info("[CO] There was an error logging in: code %d", result); + } + }); + } +}); + // EXTERNAL METHODS -void init() -{ - -} - void update() { + if (!enable) + return; // Only send a request after 3 seconds passed since last unknown steamId was added to the queue - if (identify_stale && identify_timer.check(3000)) + if (!api_key.empty() && identify_stale && identify_timer.check(3000)) { sendIdentifyRequest(); identify_stale = false; } + try { + cathookOnlineService.processPendingCalls(); + } catch (std::exception& ex) { + logging::Info("[CO] Exception: %s", ex.what()); + } } user_data *getUserData(unsigned steamId) { + if (!enable) + return nullptr; + + if (!steamId) + return nullptr; + auto it = data.find(steamId); // User not identified if (it == data.end()) diff --git a/src/visual/colors.cpp b/src/visual/colors.cpp index ea4a2555..7cdf78d1 100644 --- a/src/visual/colors.cpp +++ b/src/visual/colors.cpp @@ -5,6 +5,7 @@ * Author: nullifiedcat */ +#include #include "common.hpp" static CatVar user_red_blue(CV_INT, "esp_color_red_b", "0", "Red Team: Blue", @@ -133,6 +134,18 @@ rgba_t colors::EntityF(CachedEntity *ent) plclr = playerlist::Color(ent); if (plclr.a) result = plclr; + player_info_s pinfo{}; + if (g_IEngine->GetPlayerInfo(ent->m_IDX, &pinfo)) + { + auto data = online::getUserData(pinfo.friendsID); + if (data) + { + if (data->rainbow) + result = RainbowCurrent(); + else if (data->has_color) + result = data->color; + } + } } } @@ -144,3 +157,30 @@ rgba_t colors::RainbowCurrent() return colors::FromHSL(fabs(sin(g_GlobalVars->curtime / 2.0f)) * 360.0f, 0.85f, 0.9f); } + +static unsigned char hexToChar(char i) +{ + if (i >= '0' && i <= '9') + return i - '0'; + if (i >= 'a' && i <= 'f') + return i - 'a' + 10; + if (i >= 'A' && i <= 'F') + return i - 'A' + 10; + return 0; +} + +static unsigned int hexToByte(char hi, char lo) +{ + return (hexToChar(hi) << 4) | (hexToChar(lo)); +} + +colors::rgba_t::rgba_t(const char hex[6]) +{ + auto ri = hexToByte(hex[0], hex[1]); + auto gi = hexToByte(hex[2], hex[3]); + auto bi = hexToByte(hex[4], hex[5]); + r = float(ri) / 255.0f; + g = float(gi) / 255.0f; + b = float(bi) / 255.0f; + a = 1.0f; +} From d4c9340133c702cff6b35f5029c1153bebe10f94 Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sat, 23 Jun 2018 17:57:16 +0300 Subject: [PATCH 04/18] submodule --- external/co-library | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/co-library b/external/co-library index 2ef3cc54..05a59668 160000 --- a/external/co-library +++ b/external/co-library @@ -1 +1 @@ -Subproject commit 2ef3cc54de653472e5d5c422b5a86e263a75f606 +Subproject commit 05a5966889f7b7f71429bc16f292ef844f843ed3 From 89d457c40678e0d1edc9ec107501be9dac048bac Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sat, 23 Jun 2018 20:33:02 +0300 Subject: [PATCH 05/18] PlayerTools - global ignore settings, etc --- include/CMakeLists.txt | 3 +- include/PlayerTools.hpp | 44 ++++++++++ include/globals.h | 1 - include/hoovy.hpp | 2 + include/online/Online.hpp | 2 + include/visual/colors.hpp | 10 +++ src/CMakeLists.txt | 3 +- src/PlayerTools.cpp | 161 ++++++++++++++++++++++++++++++++++++ src/hacks/Aimbot.cpp | 23 ++---- src/hacks/AutoDetonator.cpp | 10 +-- src/hacks/AutoSticky.cpp | 6 +- src/hacks/ESP.cpp | 4 +- src/hacks/Trigger.cpp | 19 ++--- src/online/Online.cpp | 7 +- src/visual/colors.cpp | 20 ++--- 15 files changed, 255 insertions(+), 60 deletions(-) create mode 100644 include/PlayerTools.hpp create mode 100644 src/PlayerTools.cpp diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index d9dd893b..588f81d7 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -39,7 +39,8 @@ 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}/Options.hpp") + "${CMAKE_CURRENT_LIST_DIR}/Options.hpp" + "${CMAKE_CURRENT_LIST_DIR}/PlayerTools.hpp") target_include_directories(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}") diff --git a/include/PlayerTools.hpp b/include/PlayerTools.hpp new file mode 100644 index 00000000..4e991551 --- /dev/null +++ b/include/PlayerTools.hpp @@ -0,0 +1,44 @@ +/* + Created on 23.06.18. +*/ + +#pragma once + +#include "config.h" +#include + +#if ENABLE_VISUALS +#include +#endif + +class CachedEntity; + +namespace player_tools +{ + +enum class IgnoreReason +{ + DO_NOT_IGNORE, + IS_HOOVY, + IS_TAUNTING, + LOCAL_PLAYER_LIST, + ONLINE_NO_TARGET, + ONLINE_FRIENDLY_SOFTWARE, + DEVELOPER, + OTHER +}; + +IgnoreReason shouldTargetSteamId(unsigned id); +IgnoreReason shouldTarget(CachedEntity *player); + +bool shouldAlwaysRenderEspSteamId(unsigned id); +bool shouldAlwaysRenderEsp(CachedEntity *entity); + +#if ENABLE_VISUALS +std::optional forceEspColorSteamId(unsigned id); +std::optional forceEspColor(CachedEntity *entity); +#endif + +void onKilledBy(CachedEntity *entity); + +} \ No newline at end of file diff --git a/include/globals.h b/include/globals.h index b626eeaf..801e09cf 100755 --- a/include/globals.h +++ b/include/globals.h @@ -23,7 +23,6 @@ extern ConVar *cl_interpolate; extern CatVar event_log; extern CatVar cathook; // Master switch -extern CatVar ignore_taunting; extern bool *bSendPackets; extern CatVar show_antiaim; extern CatVar force_thirdperson; diff --git a/include/hoovy.hpp b/include/hoovy.hpp index f0d7eb34..b9b52259 100755 --- a/include/hoovy.hpp +++ b/include/hoovy.hpp @@ -7,5 +7,7 @@ #pragma once +class CachedEntity; + void UpdateHoovyList(); bool IsHoovy(CachedEntity *entity); diff --git a/include/online/Online.hpp b/include/online/Online.hpp index 59396549..1049fd7e 100644 --- a/include/online/Online.hpp +++ b/include/online/Online.hpp @@ -21,6 +21,8 @@ struct user_data std::vector shown_roles{}; std::string software_name{}; bool has_software{ false }; + bool no_target{ false }; + bool is_developer{}; #if ENABLE_VISUALS bool has_color{ false }; colors::rgba_t color{}; diff --git a/include/visual/colors.hpp b/include/visual/colors.hpp index 03a36226..094d0034 100755 --- a/include/visual/colors.hpp +++ b/include/visual/colors.hpp @@ -78,6 +78,16 @@ struct rgba_t } }; +constexpr bool operator==(const rgba_t& lhs, const rgba_t& rhs) +{ + return rhs.r == lhs.r && rhs.g == lhs.g && rhs.b == lhs.b && rhs.a == lhs.a; +} + +constexpr bool operator!=(const rgba_t& lhs, const rgba_t& rhs) +{ + return !(lhs == rhs); +} + constexpr rgba_t FromRGBA8(float r, float g, float b, float a) { return rgba_t{ r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 40ab4493..291c9552 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,7 +32,8 @@ target_sources(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}/velocity.cpp" "${CMAKE_CURRENT_LIST_DIR}/votelogger.cpp" "${CMAKE_CURRENT_LIST_DIR}/MiscTemporary.cpp" - "${CMAKE_CURRENT_LIST_DIR}/Options.cpp") + "${CMAKE_CURRENT_LIST_DIR}/Options.cpp" + "${CMAKE_CURRENT_LIST_DIR}/PlayerTools.cpp") add_subdirectory(core) add_subdirectory(classinfo) diff --git a/src/PlayerTools.cpp b/src/PlayerTools.cpp new file mode 100644 index 00000000..6cb973a6 --- /dev/null +++ b/src/PlayerTools.cpp @@ -0,0 +1,161 @@ +/* + Created on 23.06.18. +*/ + +#include +#include +#include +#include +#include +#include "PlayerTools.hpp" +#include "entitycache.hpp" + +static std::unordered_map betrayal_list{}; + +static CatCommand forgive_all("pt_forgive_all", "Clear betrayal list", []() { + betrayal_list.clear(); +}); + +namespace settings +{ + +static CatVar online_notarget(CV_SWITCH, "pt_ignore_notarget", "1", "Ignore notarget", "Ignore online players with notarget role"); +static CatVar hoovy(CV_SWITCH, "pt_ignore_hoovy", "1", "Ignore hoovy"); +static CatVar online_friendly_software(CV_SWITCH, "pt_ignore_friendly_software", "1", "Ignore friendly software", "Ignore CO-compatible software"); +static CatVar online_only_verified(CV_SWITCH, "pt_ignore_only_verified", "0", "Only ignore verified", "If online checks are enabled, only apply ignore if SteamID is verified (not recommended right now)"); +static CatVar online_anonymous(CV_SWITCH, "pt_ignore_anonymous", "1", "Ignore anonymous", "Apply ignore checks to anonymous accounts too"); +static CatVar betrayal_limit(CV_INT, "pt_betrayal_limit", "3", "Betrayal limit", "Stop ignoring a player after N kills while you ignored them"); +static CatVar taunting(CV_SWITCH, "pt_ignore_taunting", "1", "Ignore taunting", "Don't shoot taunting players"); + +} + +namespace player_tools +{ + +IgnoreReason shouldTargetSteamId(unsigned id) +{ + if (id == 0) + return IgnoreReason::DO_NOT_IGNORE; + + if (settings::betrayal_limit) + { + if (betrayal_list[id] > int(settings::betrayal_limit)) + return IgnoreReason::DO_NOT_IGNORE; + } + + auto& pl = playerlist::AccessData(id); + if (playerlist::IsFriendly(pl.state)) + return IgnoreReason::LOCAL_PLAYER_LIST; + + auto *co = online::getUserData(id); + if (co) + { + bool check_verified = !settings::online_only_verified || co->is_steamid_verified; + bool check_anonymous = settings::online_anonymous || !co->is_anonymous; + + if (check_verified && check_anonymous) + { + if (settings::online_notarget && co->no_target) + return IgnoreReason::ONLINE_NO_TARGET; + if (settings::online_friendly_software && co->is_using_friendly_software) + return IgnoreReason::ONLINE_FRIENDLY_SOFTWARE; + } + // Always check developer status, no exceptions + if (co->is_developer) + return IgnoreReason::DEVELOPER; + } + + return IgnoreReason::DO_NOT_IGNORE; +} +IgnoreReason shouldTarget(CachedEntity *entity) +{ + if (entity->m_Type() == ENTITY_PLAYER) + { + if (settings::hoovy && IsHoovy(entity)) + return IgnoreReason::IS_HOOVY; + if (settings::taunting && HasCondition(entity)) + return IgnoreReason::IS_TAUNTING; + + return shouldTargetSteamId(entity->player_info.friendsID); + } + + return IgnoreReason::DO_NOT_IGNORE; +} + +bool shouldAlwaysRenderEspSteamId(unsigned id) +{ + if (id == 0) + return false; + + auto& pl = playerlist::AccessData(id); + if (pl.state != playerlist::k_EState::DEFAULT) + return true; + + auto *co = online::getUserData(id); + if (co) + return true; + + return false; +} +bool shouldAlwaysRenderEsp(CachedEntity *entity) +{ + if (entity->m_Type() == ENTITY_PLAYER) + { + return shouldAlwaysRenderEspSteamId(entity->player_info.friendsID); + } + + return false; +} + +#if ENABLE_VISUALS +std::optional forceEspColorSteamId(unsigned id) +{ + if (id == 0) + return std::nullopt; + + auto pl = playerlist::Color(id); + if (pl != colors::empty) + return std::optional{ pl }; + + auto *co = online::getUserData(id); + if (co) + { + if (co->rainbow) + return std::optional{ colors::RainbowCurrent() }; + if (co->has_color) + return std::optional{ co->color }; + } + + return std::nullopt; +} +std::optional forceEspColor(CachedEntity *entity) +{ + if (entity->m_Type() == ENTITY_PLAYER) + { + return forceEspColorSteamId(entity->player_info.friendsID); + } + + return std::nullopt; +} +#endif + +void onKilledBy(unsigned id) +{ + auto reason = shouldTargetSteamId(id); + if (reason != IgnoreReason::DO_NOT_IGNORE) + { + // We ignored the gamer, but they still shot us + if (betrayal_list.find(id) == betrayal_list.end()) + betrayal_list[id] = 0; + betrayal_list[id]++; + } +} + +void onKilledBy(CachedEntity *entity) +{ + onKilledBy(entity->player_info.friendsID); +} + + + +} \ No newline at end of file diff --git a/src/hacks/Aimbot.cpp b/src/hacks/Aimbot.cpp index e39f98e5..b0407019 100644 --- a/src/hacks/Aimbot.cpp +++ b/src/hacks/Aimbot.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "common.hpp" namespace hacks @@ -64,8 +65,6 @@ static CatVar static CatVar ignore_vaccinator( CV_SWITCH, "aimbot_ignore_vaccinator", "1", "Ignore Vaccinator", "Hitscan weapons won't fire if enemy is vaccinated against bullets"); -static CatVar ignore_hoovy(CV_SWITCH, "aimbot_ignore_hoovy", "0", - "Ignore Hoovies", "Aimbot won't attack hoovies"); static CatVar ignore_cloak(CV_SWITCH, "aimbot_ignore_cloak", "1", "Ignore cloaked", "Don't aim at invisible enemies"); static CatVar ignore_deadringer(CV_SWITCH, "aimbot_ignore_deadringer", "1", @@ -578,8 +577,10 @@ bool IsTargetStateGood(CachedEntity *entity) } } - // Taunting - if (ignore_taunting && HasCondition(entity)) + // Some global checks + if (player_tools::shouldTarget(entity) != player_tools::IgnoreReason::DO_NOT_IGNORE) + return false; + if (hacks::shared::catbot::should_ignore_player(entity)) return false; // Invulnerable players, ex: uber, bonk if (IsPlayerInvulnerable(entity)) @@ -609,19 +610,7 @@ bool IsTargetStateGood(CachedEntity *entity) HasCondition(entity)) return false; } - // Friendly player - if (playerlist::IsFriendly(playerlist::AccessData(entity).state)) - return false; - IF_GAME(IsTF()) - { - // Hoovys - if (ignore_hoovy && IsHoovy(entity)) - { - return false; - } - } - if (hacks::shared::catbot::should_ignore_player(entity)) - return false; + // Preform hitbox prediction int hitbox = BestHitbox(entity); AimbotCalculatedData_s &cd = calculated_data_array[entity->m_IDX]; diff --git a/src/hacks/AutoDetonator.cpp b/src/hacks/AutoDetonator.cpp index 5ca87539..a420adbe 100644 --- a/src/hacks/AutoDetonator.cpp +++ b/src/hacks/AutoDetonator.cpp @@ -5,6 +5,7 @@ * Author: nullifiedcat & Lighty */ +#include #include "common.hpp" namespace hacks @@ -57,19 +58,16 @@ bool IsTarget(CachedEntity *ent) // Dont detonate on dead players if (!ent->m_bAlivePlayer()) return false; - // Dont detonate on friendly players - if (playerlist::IsFriendly(playerlist::AccessData(ent).state)) - return false; + // Global checks + if (player_tools::shouldTarget(ent) != player_tools::IgnoreReason::DO_NOT_IGNORE) + return false; IF_GAME(IsTF()) { // Dont target invulnerable players, ex: uber, bonk if (IsPlayerInvulnerable(ent)) return false; - // If settings allow, ignore taunting players - if (ignore_taunting && HasCondition(ent)) - return false; // If settings allow, dont target cloaked players if (legit && IsPlayerInvisible(ent)) diff --git a/src/hacks/AutoSticky.cpp b/src/hacks/AutoSticky.cpp index 65360dc1..7165cd53 100644 --- a/src/hacks/AutoSticky.cpp +++ b/src/hacks/AutoSticky.cpp @@ -7,6 +7,7 @@ #include "common.hpp" #include +#include namespace hacks { @@ -62,8 +63,9 @@ bool IsTarget(CachedEntity *ent) // Dont detonate on dead players if (!ent->m_bAlivePlayer()) return false; - // Dont detonate on friendly players - if (playerlist::IsFriendly(playerlist::AccessData(ent).state)) + + // Global checks + if (player_tools::shouldTarget(ent) != player_tools::IgnoreReason::DO_NOT_IGNORE) return false; IF_GAME(IsTF()) diff --git a/src/hacks/ESP.cpp b/src/hacks/ESP.cpp index 23eea7c1..e474a038 100644 --- a/src/hacks/ESP.cpp +++ b/src/hacks/ESP.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "common.hpp" namespace hacks @@ -1199,8 +1200,7 @@ void _FASTCALL ProcessEntity(CachedEntity *ent) } // Dont understand reasoning for this check - if (ent->m_bEnemy() || teammates || - !playerlist::IsDefault(info.friendsID)) + if (ent->m_bEnemy() || teammates || player_tools::shouldAlwaysRenderEsp(ent)) { // Playername diff --git a/src/hacks/Trigger.cpp b/src/hacks/Trigger.cpp index 12248732..bf8b9485 100644 --- a/src/hacks/Trigger.cpp +++ b/src/hacks/Trigger.cpp @@ -9,6 +9,7 @@ #include #include "common.hpp" #include +#include namespace hacks { @@ -276,6 +277,10 @@ bool IsTargetStateGood(CachedEntity *entity) if (!entity->m_bEnemy() && !teammates) return false; + // Global checks + if (player_tools::shouldTarget(entity) != player_tools::IgnoreReason::DO_NOT_IGNORE) + return false; + IF_GAME(IsTF()) { // If settings allow waiting for charge, and current charge cant @@ -295,9 +300,6 @@ bool IsTargetStateGood(CachedEntity *entity) return false; } } - // If settings allow, ignore taunting players - if (ignore_taunting && HasCondition(entity)) - return false; // Dont target invulnerable players, ex: uber, bonk if (IsPlayerInvulnerable(entity)) return false; @@ -311,17 +313,6 @@ bool IsTargetStateGood(CachedEntity *entity) HasCondition(entity)) return false; } - // Dont target players marked as friendly - if (playerlist::IsFriendly(playerlist::AccessData(entity).state)) - return false; - IF_GAME(IsTF()) - { - // If settings allow, ignore hoovys - if (ignore_hoovy && IsHoovy(entity)) - { - return false; - } - } // Head hitbox detection if (HeadPreferable(entity)) diff --git a/src/online/Online.cpp b/src/online/Online.cpp index e3acbd7d..93c89e24 100644 --- a/src/online/Online.cpp +++ b/src/online/Online.cpp @@ -121,10 +121,15 @@ void processOnlineIdentity(unsigned id, co::identified_user& user) { if (i.display_name.has_value()) udata.shown_roles.push_back(*i.display_name); + if (i.name == "notarget") + udata.no_target = true; + if (i.name == "owner" || i.name == "contributor") + { + udata.is_developer = true; #if ENABLE_VISUALS - if (i.name == "owner") udata.rainbow = true; #endif + } } #if ENABLE_VISUALS if (user.color.has_value()) diff --git a/src/visual/colors.cpp b/src/visual/colors.cpp index 7cdf78d1..0dd6badc 100644 --- a/src/visual/colors.cpp +++ b/src/visual/colors.cpp @@ -6,6 +6,7 @@ */ #include +#include #include "common.hpp" static CatVar user_red_blue(CV_INT, "esp_color_red_b", "0", "Red Team: Blue", @@ -131,21 +132,10 @@ rgba_t colors::EntityF(CachedEntity *ent) else if (ent->m_iTeam() == TEAM_RED) result = red_v; } - plclr = playerlist::Color(ent); - if (plclr.a) - result = plclr; - player_info_s pinfo{}; - if (g_IEngine->GetPlayerInfo(ent->m_IDX, &pinfo)) - { - auto data = online::getUserData(pinfo.friendsID); - if (data) - { - if (data->rainbow) - result = RainbowCurrent(); - else if (data->has_color) - result = data->color; - } - } + + auto o = player_tools::forceEspColor(ent); + if (o.has_value()) + return *o; } } From 65f596ba812a50e6cb0e7c3e6a8e6da5e4b4901e Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sat, 23 Jun 2018 20:42:13 +0300 Subject: [PATCH 06/18] software --- src/globals.cpp | 2 -- src/hacks/ESP.cpp | 7 ++++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/globals.cpp b/src/globals.cpp index a0999d5a..d9f80a15 100755 --- a/src/globals.cpp +++ b/src/globals.cpp @@ -33,8 +33,6 @@ CatVar force_name(CV_STRING, "name", "", "Force name"); CatVar cathook(CV_SWITCH, "enabled", "1", "CatHook enabled", "Disabling this completely disables cathook (can be re-enabled)"); -CatVar ignore_taunting(CV_SWITCH, "ignore_taunting", "1", "Ignore taunting", - "Aimbot/Triggerbot won't attack taunting enemies"); // CatVar send_packets(CV_SWITCH, "sendpackets", "1", "Send packets", "Internal // use"); CatVar show_antiaim(CV_SWITCH, "thirdperson_angles", "1", "Real TP angles", diff --git a/src/hacks/ESP.cpp b/src/hacks/ESP.cpp index e474a038..79ee82fe 100644 --- a/src/hacks/ESP.cpp +++ b/src/hacks/ESP.cpp @@ -1188,7 +1188,12 @@ void _FASTCALL ProcessEntity(CachedEntity *ent) for (auto& s: data->shown_roles) AddEntityString(ent, s, colors::orange); if (online_software && data->has_software) - AddEntityString(ent, "Software: " + data->software_name); + { + if (data->is_using_friendly_software) + AddEntityString(ent, "Software: " + data->software_name); + else + AddEntityString(ent, "Software: " + data->software_name, colors::red); + } } // Powerup handling From 1ad0582cafbff1c2033622dc52435ceeccbdc096 Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sat, 23 Jun 2018 22:36:04 +0200 Subject: [PATCH 07/18] Followbot disguise/invisible --- include/visual/EffectChams.hpp | 4 ++-- src/hacks/FollowBot.cpp | 10 ++++++++++ src/visual/EffectChams.cpp | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/visual/EffectChams.hpp b/include/visual/EffectChams.hpp index d94fc032..2bfe231f 100644 --- a/include/visual/EffectChams.hpp +++ b/include/visual/EffectChams.hpp @@ -36,7 +36,7 @@ public: void SetEntityColor(CachedEntity *ent, rgba_t color); rgba_t ChamsColor(IClientEntity *entity); bool ShouldRenderChams(IClientEntity *entity); - void RenderChams(int idx); + void RenderChams(IClientEntity *entity); void BeginRenderChams(); void EndRenderChams(); void RenderChamsRecursive(IClientEntity *entity); @@ -54,4 +54,4 @@ public: extern EffectChams g_EffectChams; extern CScreenSpaceEffectRegistration *g_pEffectChams; -} \ No newline at end of file +} diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index 2dfcdbdc..6edd27a7 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -131,6 +131,10 @@ void WorldTick() continue; if (entity == LOCAL_E) // Follow self lol continue; + if (entity->m_bEnemy()) + continue; + if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity)) + continue; if (!entity->m_bAlivePlayer()) // Dont follow dead players continue; if (follow_activation && @@ -168,6 +172,12 @@ void WorldTick() // wtf is this needed if (CE_BAD(followtar)) return; + // Check if we are following a disguised/spy + if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity)) + { + follow_target = 0; + return; + } // Update timer on new target static Timer idle_time{}; if (breadcrumbs.empty()) diff --git a/src/visual/EffectChams.cpp b/src/visual/EffectChams.cpp index 5ca3625a..02a7da55 100644 --- a/src/visual/EffectChams.cpp +++ b/src/visual/EffectChams.cpp @@ -318,6 +318,7 @@ void EffectChams::RenderChamsRecursive(IClientEntity *entity) } void EffectChams::RenderChams(int idx) +void EffectChams::RenderChams(IClientEntity *entity) { CMatRenderContextPtr ptr(GET_RENDER_CONTEXT); IClientEntity *entity = g_IEntityList->GetClientEntity(idx); @@ -365,6 +366,7 @@ void EffectChams::Render(int x, int y, int w, int h) for (int i = 1; i < HIGHEST_ENTITY; i++) { RenderChams(i); + RenderChams(entity); } EndRenderChams(); } From c2d700841f284395803ed41a34c1f227b40bc6eb Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sun, 24 Jun 2018 15:40:02 +0300 Subject: [PATCH 08/18] update online --- external/co-library | 2 +- src/online/Online.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/external/co-library b/external/co-library index 05a59668..77334e8e 160000 --- a/external/co-library +++ b/external/co-library @@ -1 +1 @@ -Subproject commit 05a5966889f7b7f71429bc16f292ef844f843ed3 +Subproject commit 77334e8eaf26f91b5ff9f3198b7dd4e2b3a43b5c diff --git a/src/online/Online.cpp b/src/online/Online.cpp index 93c89e24..368640bc 100644 --- a/src/online/Online.cpp +++ b/src/online/Online.cpp @@ -226,7 +226,7 @@ void update() if (!enable) return; // Only send a request after 3 seconds passed since last unknown steamId was added to the queue - if (!api_key.empty() && identify_stale && identify_timer.check(3000)) + if (!api_key.empty() && identify_stale && identify_timer.check(3000) && !identify_queue.empty()) { sendIdentifyRequest(); identify_stale = false; From d987e5f31bef0d1de99b6e4e0f672dfba307b274 Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sun, 24 Jun 2018 15:43:58 +0300 Subject: [PATCH 09/18] fix online --- external/co-library | 2 +- src/online/Online.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/external/co-library b/external/co-library index 77334e8e..c951cc8a 160000 --- a/external/co-library +++ b/external/co-library @@ -1 +1 @@ -Subproject commit 77334e8eaf26f91b5ff9f3198b7dd4e2b3a43b5c +Subproject commit c951cc8a125becc0f28c9ba3eaf0c48adfb14d7a diff --git a/src/online/Online.cpp b/src/online/Online.cpp index 368640bc..c60e212d 100644 --- a/src/online/Online.cpp +++ b/src/online/Online.cpp @@ -117,7 +117,7 @@ void processOnlineIdentity(unsigned id, co::identified_user& user) udata.username = user.username; udata.is_anonymous = (user.username == "anonymous"); udata.is_steamid_verified = user.steamid_verified; - for (auto& i: user.roles) + for (auto& i: user.groups) { if (i.display_name.has_value()) udata.shown_roles.push_back(*i.display_name); @@ -147,7 +147,7 @@ void processOnlineIdentity(unsigned id, co::identified_user& user) data[id] = std::move(udata); } -void processIdentifyResponse(std::vector input, co::identified_group& group) +void processIdentifyResponse(std::vector input, co::identified_user_group& group) { logging::Info("[CO] Processing identify response containing %u / %u entries", group.users.size(), input.size()); for (auto i: input) @@ -177,7 +177,7 @@ void sendIdentifyRequest() } } logging::Info("[CO] Sending identify request for %u players", steamIds.size()); - cathookOnlineService.userIdentify(steamIds, (std::function)>)[steamIds](co::ApiCallResult result, std::optional group) { + cathookOnlineService.userIdentify(steamIds, (std::function)>)[steamIds](co::ApiCallResult result, std::optional group) { if (result == co::ApiCallResult::OK) { processIdentifyResponse(steamIds, *group); From 1043c163b5a924d466f0dcb9898cffb9c06dcb6e Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sun, 24 Jun 2018 15:45:13 +0300 Subject: [PATCH 10/18] fix gitmodules --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 7d352beb..84ae995f 100755 --- a/.gitmodules +++ b/.gitmodules @@ -15,4 +15,4 @@ url = https://github.com/nullworks/ucccccp.git [submodule "external/co-library"] path = external/co-library - url = git@gitcat:nullworks/co-library.git + url = https://github.com/nullworks/co-library.git From b6066eb27601f0b47fb9f071aadc31e1035cc2e7 Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sun, 24 Jun 2018 16:02:52 +0300 Subject: [PATCH 11/18] update --- external/co-library | 2 +- include/online/Online.hpp | 2 +- src/hacks/ESP.cpp | 6 +++--- src/online/Online.cpp | 41 ++++++++++++++++++++++++++------------- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/external/co-library b/external/co-library index c951cc8a..393948a6 160000 --- a/external/co-library +++ b/external/co-library @@ -1 +1 @@ -Subproject commit c951cc8a125becc0f28c9ba3eaf0c48adfb14d7a +Subproject commit 393948a6bf7ee4a62f5a3bd82d94c05d4bc405aa diff --git a/include/online/Online.hpp b/include/online/Online.hpp index 1049fd7e..de384892 100644 --- a/include/online/Online.hpp +++ b/include/online/Online.hpp @@ -18,7 +18,7 @@ struct user_data bool is_using_friendly_software{ false }; bool is_steamid_verified{ false }; std::string username{}; - std::vector shown_roles{}; + std::vector shown_groups{}; std::string software_name{}; bool has_software{ false }; bool no_target{ false }; diff --git a/src/hacks/ESP.cpp b/src/hacks/ESP.cpp index 79ee82fe..cfda5d2d 100644 --- a/src/hacks/ESP.cpp +++ b/src/hacks/ESP.cpp @@ -154,7 +154,7 @@ static CatVar entity_id(CV_SWITCH, "esp_entity_id", "1", "Entity ID", // Online static CatVar online(CV_SWITCH, "esp_online", "1", "Show online info", "Username, etc"); -static CatVar online_roles(CV_SWITCH, "esp_online_roles", "1", "Show online roles", "Admin, developer, etc"); +static CatVar online_groups(CV_SWITCH, "esp_online_groups", "1", "Show online groups", "Admin, developer, etc"); static CatVar online_software(CV_SWITCH, "esp_online_software", "1", "Show software", "cathook, lmaobox, etc"); // CatVar draw_hitbox(CV_SWITCH, "esp_hitbox", "1", "Draw Hitbox"); @@ -1184,8 +1184,8 @@ void _FASTCALL ProcessEntity(CachedEntity *ent) AddEntityString(ent, "CO: " + data->username, colors::yellow); if (data->is_steamid_verified) AddEntityString(ent, "Verified SteamID", colors::green); - if (online_roles) - for (auto& s: data->shown_roles) + if (online_groups) + for (auto& s: data->shown_groups) AddEntityString(ent, s, colors::orange); if (online_software && data->has_software) { diff --git a/src/online/Online.cpp b/src/online/Online.cpp index c60e212d..4838a876 100644 --- a/src/online/Online.cpp +++ b/src/online/Online.cpp @@ -70,7 +70,11 @@ void claimSteamId() { auto id = g_ISteamUser->GetSteamID(); logging::Info("[CO] Claiming SteamID %u", id.GetAccountID()); - cathookOnlineService.gameStartup(id.GetAccountID()); + try { + cathookOnlineService.gameStartup(id.GetAccountID()); + } catch (std::exception& ex) { + logging::Info("[CO] Exception: %s", ex.what()); + } } bool tryLoadApiKey() @@ -120,7 +124,7 @@ void processOnlineIdentity(unsigned id, co::identified_user& user) for (auto& i: user.groups) { if (i.display_name.has_value()) - udata.shown_roles.push_back(*i.display_name); + udata.shown_groups.push_back(*i.display_name); if (i.name == "notarget") udata.no_target = true; if (i.name == "owner" || i.name == "contributor") @@ -200,22 +204,31 @@ InitRoutine init([]() { }); host.InstallChangeCallback([](IConVar *var, const char *pszOldValue, float flOldValue) { logging::Info("[CO] Host = %s", host.GetString()); - cathookOnlineService.setHost(host.GetString()); + try { + cathookOnlineService.setHost(host.GetString()); + } catch (std::exception& ex) + { + logging::Info("[CO] Error: %s", ex.what()); + } }); if (tryLoadApiKey()) { logging::Info("[CO] API key loaded successfully"); - cathookOnlineService.login(api_key, [](co::ApiCallResult result, std::optional me) { - if (result == co::ApiCallResult::OK) - { - logging::Info("[CO] Successfully logged in. Welcome, %s", me->username.c_str()); - claimSteamId(); - } - else - { - logging::Info("[CO] There was an error logging in: code %d", result); - } - }); + try { + cathookOnlineService.login(api_key, [](co::ApiCallResult result, std::optional me) { + if (result == co::ApiCallResult::OK) + { + logging::Info("[CO] Successfully logged in. Welcome, %s", me->username.c_str()); + claimSteamId(); + } + else + { + logging::Info("[CO] There was an error logging in: code %d", result); + } + }); + } catch (std::exception& ex) { + logging::Info("[CO] Exception: %s", ex.what()); + } } }); From 751210d34cb932885a234b94aa6b59d210cf76c1 Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sun, 24 Jun 2018 16:32:01 +0300 Subject: [PATCH 12/18] fix --- src/online/Online.cpp | 79 ++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/src/online/Online.cpp b/src/online/Online.cpp index 4838a876..1290fa4c 100644 --- a/src/online/Online.cpp +++ b/src/online/Online.cpp @@ -20,7 +20,7 @@ namespace online { -void saveApiKey(); +void saveApiKeyAndHost(std::string host); void claimSteamId(); static co::OnlineService cathookOnlineService{}; @@ -32,20 +32,29 @@ static std::string api_key{}; static CatVar enable(CV_SWITCH, "online", "1", "Enable online features"); static CatCommand login("online_login", "Login", [](const CCommand& args) { - if (args.ArgC() != 2) + if (args.ArgC() != 3) { - logging::Info("\nUsage: online_login \nKey will be saved in your data folder"); + logging::Info("\nUsage: online_login \"\"\nKey will be saved in your data folder"); + return; + } + std::string host(args.Arg(2)); + logging::Info("[CO] Host = %s", host.c_str()); + try { + cathookOnlineService.setHost(host); + } catch (std::exception& ex) + { + logging::Info("[CO] Error setting host: %s", ex.what()); return; } std::string key(args.Arg(1)); try { - cathookOnlineService.login(key, [key](co::ApiCallResult result, std::optional me) { + cathookOnlineService.login(key, [key, host](co::ApiCallResult result, std::optional me) { if (result == co::ApiCallResult::OK) { logging::Info("[CO] Successfully logged in. Welcome, %s", me->username.c_str()); api_key = key; - saveApiKey(); + saveApiKeyAndHost(host); claimSteamId(); } else @@ -62,7 +71,6 @@ static CatCommand flush("online_flush_cache", "Flush player cache", [](const CCo identify_queue.clear(); identify_stale = true; }); -static CatVar host(CV_STRING, "online_host", "localhost:8000", "Online host"); // INTERNAL METHODS @@ -77,19 +85,27 @@ void claimSteamId() } } -bool tryLoadApiKey() +bool tryLoadApiKeyAndHost() { std::ifstream keyfile(DATA_PATH "/api_key", std::ios::in); if (keyfile) { - keyfile >> api_key; - if (!api_key.empty()) + std::string host{}; + keyfile >> api_key >> host; + if (!api_key.empty() && !host.empty()) + { + try { + cathookOnlineService.setHost(host); + } catch (std::exception& ex) { + logging::Info("Error while setting host: %s", ex.what()); + } return true; + } } return false; } -void saveApiKey() +void saveApiKeyAndHost(std::string host) { std::ofstream keyfile(DATA_PATH "/api_key", std::ios::out); if (!keyfile) @@ -97,7 +113,7 @@ void saveApiKey() logging::Info("[CO] Something went wrong while saving API key"); return; } - keyfile << api_key << '\n'; + keyfile << api_key << '\n' << host << '\n'; } void queueUserForIdentification(unsigned steamId) @@ -181,37 +197,32 @@ void sendIdentifyRequest() } } logging::Info("[CO] Sending identify request for %u players", steamIds.size()); - cathookOnlineService.userIdentify(steamIds, (std::function)>)[steamIds](co::ApiCallResult result, std::optional group) { - if (result == co::ApiCallResult::OK) - { - processIdentifyResponse(steamIds, *group); - } - else - { - logging::Info("[CO] Something went wrong while identifying %u players: code %d", steamIds.size(), result); - for (auto i: steamIds) + try { + cathookOnlineService.userIdentify(steamIds, (std::function)>)[steamIds](co::ApiCallResult result, std::optional group) { + if (result == co::ApiCallResult::OK) { - identify_queue[i] = false; + processIdentifyResponse(steamIds, *group); } - identify_stale = true; - } - }); + else + { + logging::Info("[CO] Something went wrong while identifying %u players: code %d", steamIds.size(), result); + for (auto i: steamIds) + { + identify_queue[i] = false; + } + identify_stale = true; + } + }); + } catch (std::exception& ex) { + logging::Info("[CO] Exception: %s", ex.what()); + } } InitRoutine init([]() { cathookOnlineService.setErrorHandler((std::function)[](std::string error) { logging::Info("[CO] Error: %s", error.c_str()); }); - host.InstallChangeCallback([](IConVar *var, const char *pszOldValue, float flOldValue) { - logging::Info("[CO] Host = %s", host.GetString()); - try { - cathookOnlineService.setHost(host.GetString()); - } catch (std::exception& ex) - { - logging::Info("[CO] Error: %s", ex.what()); - } - }); - if (tryLoadApiKey()) + if (tryLoadApiKeyAndHost()) { logging::Info("[CO] API key loaded successfully"); try { From d6a91320031224b41c76f22d61437c51935c5929 Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sun, 24 Jun 2018 16:16:41 +0200 Subject: [PATCH 13/18] AFK check --- src/hacks/FollowBot.cpp | 37 ++++++++++++++++++++++++++++++++----- src/visual/EffectChams.cpp | 13 +++++-------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index 6edd27a7..bd4505f8 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -50,10 +50,12 @@ static CatVar always_medigun(CV_SWITCH, "fb_always_medigun", "0", "Always Medigun", "Always use medigun"); static CatVar sync_taunt(CV_SWITCH, "fb_sync_taunt", "0", "Synced taunt", "Taunt when follow target does"); -static CatVar change(CV_SWITCH, "fb_switch", "1", "Change followbot target", +static CatVar change(CV_SWITCH, "fb_switch", "0", "Change followbot target", "Always change roaming target when possible"); static CatVar autojump(CV_SWITCH, "fb_autojump", "1", "Autojump", "Automatically jump if stuck"); +static CatVar afk(CV_SWITCH, "fb_afk", "1", "Switch target if AFK", + "Automatically switch target if the target is afk"); // Something to store breadcrumbs created by followed players static std::vector breadcrumbs; @@ -61,7 +63,10 @@ static const int crumb_limit = 64; // limit // Followed entity, externed for highlight color int follow_target = 0; -long int lasttaunt; + +long int lasttaunt; //time since epoch when "taunt" was last executed +int lasttarget; //target we should not follow again +int tickswasted; //how many createmove ticks we have wasted because a target is afk void WorldTick() { @@ -133,6 +138,8 @@ void WorldTick() continue; if (entity->m_bEnemy()) continue; + if (i == lasttarget) //don't follow target that was determined afk + continue; if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity)) continue; if (!entity->m_bAlivePlayer()) // Dont follow dead players @@ -162,6 +169,7 @@ void WorldTick() continue; // ooooo, a target follow_target = entity->m_IDX; + tickswasted = 0; //set afk ticks to 0 } } // last check for entity before we continue @@ -173,11 +181,31 @@ void WorldTick() if (CE_BAD(followtar)) return; // Check if we are following a disguised/spy - if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity)) + if (IsPlayerDisguised(followtar) || IsPlayerInvisible(followtar)) { follow_target = 0; return; } + //check if player is afk + if (afk) + { + if (CE_VECTOR(followtar, netvar.vVelocity).IsZero(1.0f)) + { + tickswasted = tickswasted + 1; + if (tickswasted >= 990) + { + lasttarget = follow_target; + follow_target = 0; + return; + } + } + else + { + tickswasted = 0; + } + + } + // Update timer on new target static Timer idle_time{}; if (breadcrumbs.empty()) @@ -233,8 +261,7 @@ void WorldTick() if (dist_to_target > (float) follow_distance) { // Check for idle - if (autojump && (idle_time.check(3000) || - (breadcrumbs.size() > 1 && LOCAL_E->m_vecVelocity.IsZero(5.0f)))) + if (autojump && idle_time.check(3000)) g_pUserCmd->buttons |= IN_JUMP; if (idle_time.test_and_set(5000)) { diff --git a/src/visual/EffectChams.cpp b/src/visual/EffectChams.cpp index 02a7da55..eb13fcea 100644 --- a/src/visual/EffectChams.cpp +++ b/src/visual/EffectChams.cpp @@ -222,11 +222,11 @@ rgba_t EffectChams::ChamsColor(IClientEntity *entity) bool EffectChams::ShouldRenderChams(IClientEntity *entity) { + if (!enable) + return false; if (entity->entindex() < 0) return false; CachedEntity *ent = ENTITY(entity->entindex()); - if (CE_BAD(ent)) - return false; if (ent->m_IDX == LOCAL_E->m_IDX && !chamsself) return false; switch (ent->m_Type()) @@ -317,13 +317,9 @@ void EffectChams::RenderChamsRecursive(IClientEntity *entity) } } -void EffectChams::RenderChams(int idx) void EffectChams::RenderChams(IClientEntity *entity) { CMatRenderContextPtr ptr(GET_RENDER_CONTEXT); - IClientEntity *entity = g_IEntityList->GetClientEntity(idx); - if (entity && !entity->IsDormant()) - { if (ShouldRenderChams(entity)) { rgba_t color = ChamsColor(entity); @@ -347,7 +343,6 @@ void EffectChams::RenderChams(IClientEntity *entity) g_IVModelRender->ForcedMaterialOverride(flat ? mat_unlit : mat_lit); RenderChamsRecursive(entity); - } } } } @@ -365,7 +360,9 @@ void EffectChams::Render(int x, int y, int w, int h) BeginRenderChams(); for (int i = 1; i < HIGHEST_ENTITY; i++) { - RenderChams(i); + IClientEntity *entity = g_IEntityList->GetClientEntity(i); + if (!entity || entity->IsDormant() || CE_BAD(ENTITY(i))) + return; RenderChams(entity); } EndRenderChams(); From 78da831c11d3bc3ae1f8efd853e12ecaa033363b Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sun, 24 Jun 2018 18:38:19 +0300 Subject: [PATCH 14/18] dont override custom color --- src/PlayerTools.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PlayerTools.cpp b/src/PlayerTools.cpp index 6cb973a6..4a508b43 100644 --- a/src/PlayerTools.cpp +++ b/src/PlayerTools.cpp @@ -120,10 +120,10 @@ std::optional forceEspColorSteamId(unsigned id) auto *co = online::getUserData(id); if (co) { - if (co->rainbow) - return std::optional{ colors::RainbowCurrent() }; if (co->has_color) return std::optional{ co->color }; + if (co->rainbow) + return std::optional{ colors::RainbowCurrent() }; } return std::nullopt; From 5a7be4e1c472eabbb052ba8c2ebb370121d4f180 Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sun, 24 Jun 2018 20:29:05 +0200 Subject: [PATCH 15/18] Better afk check & better breadcrumb clearing --- src/hacks/FollowBot.cpp | 65 ++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index 9523f602..a8f02cb6 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -51,7 +51,10 @@ static CatVar change(CV_SWITCH, "fb_switch", "0", "Change followbot target", static CatVar autojump(CV_SWITCH, "fb_autojump", "1", "Autojump", "Automatically jump if stuck"); static CatVar afk(CV_SWITCH, "fb_afk", "1", "Switch target if AFK", - "Automatically switch target if the target is afk"); + "Automatically switch target if the target is afk"); +static CatVar afktime(CV_INT, "fb_afk_time", "990", "Max AFK Time", + "Max ticks (66 * time in seconds) spent standing still " + "until a player is declared afk."); // Something to store breadcrumbs created by followed players static std::vector breadcrumbs; @@ -60,9 +63,26 @@ static const int crumb_limit = 64; // limit // Followed entity, externed for highlight color int follow_target = 0; -long int lasttaunt; //time since epoch when "taunt" was last executed -int lasttarget; //target we should not follow again -int tickswasted; //how many createmove ticks we have wasted because a target is afk +static long int lasttaunt; //time since epoch when "taunt" was last executed +std::array afkticks; //for how many createmove ticks the player hasn't been moving + +void checkAFK() +{ + for (int i = 0; i < g_GlobalVars->maxClients; i++) + { + auto entity = ENTITY(i); + if (CE_BAD(entity)) + continue; + if (CE_VECTOR(entity, netvar.vVelocity).IsZero(5.0f)) + { + afkticks[i] = afkticks[i] + 1; + } + else + { + afkticks[i] = 0; + } + } +} void WorldTick() { @@ -79,6 +99,9 @@ void WorldTick() return; } + if (afk) + checkAFK(); + // Still good check if (follow_target) { @@ -134,7 +157,7 @@ void WorldTick() continue; if (entity->m_bEnemy()) continue; - if (i == lasttarget) //don't follow target that was determined afk + if (afk && afkticks[i] >= int(afktime)) //don't follow target that was determined afk continue; if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity)) continue; @@ -164,8 +187,8 @@ void WorldTick() entity->m_flDistance()) // favor closer entitys continue; // ooooo, a target - follow_target = entity->m_IDX; - tickswasted = 0; //set afk ticks to 0 + follow_target = i; + afkticks[i] = 0; //set afk ticks to 0 } } // last check for entity before we continue @@ -182,22 +205,13 @@ void WorldTick() follow_target = 0; return; } - //check if player is afk + //check if target is afk if (afk) { - if (CE_VECTOR(followtar, netvar.vVelocity).IsZero(1.0f)) + if (afkticks[follow_target] >= 990) { - tickswasted = tickswasted + 1; - if (tickswasted >= 990) - { - lasttarget = follow_target; - follow_target = 0; - return; - } - } - else - { - tickswasted = 0; + follow_target = 0; + return; } } @@ -215,7 +229,6 @@ void WorldTick() { if ((dist_to_target < (float)follow_distance) && VisCheckEntFromEnt(LOCAL_E, followtar)) { - breadcrumbs.clear(); idle_time.update(); } } @@ -242,6 +255,16 @@ void WorldTick() breadcrumbs.erase(breadcrumbs.begin()); } + for (int i = 0; i < breadcrumbs.size(); i++) + { + if (loc_orig.DistTo(breadcrumbs.at(i)) < 60.f) + { + idle_time.update(); + for (int i2 = 0; i2 <= i; i2++) + breadcrumbs.erase(breadcrumbs.begin()); + } + } + //moved because its worthless otherwise if (sync_taunt && HasCondition(followtar)) { //std::time_t time = std::time(nullptr); From 11505574cd4e7acc778891269aa5580e27a2175f Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sun, 24 Jun 2018 21:14:19 +0200 Subject: [PATCH 16/18] improvements tm --- src/hacks/FollowBot.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index a8f02cb6..1a63814a 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -24,7 +24,7 @@ static CatVar draw_crumb(CV_SWITCH, "fb_draw", "1", "Draw crumbs", "Self explanitory"); static CatVar follow_distance(CV_INT, "fb_distance", "175", "Follow Distance", "How close the bots should stay to the target"); -static CatVar follow_activation(CV_INT, "fb_activation", "175", +static CatVar follow_activation(CV_INT, "fb_activation", "1000", "Activation Distance", "How close a player should be until the " "followbot will pick them as a target"); @@ -75,11 +75,11 @@ void checkAFK() continue; if (CE_VECTOR(entity, netvar.vVelocity).IsZero(5.0f)) { - afkticks[i] = afkticks[i] + 1; + afkTicks[i] = afkTicks[i] + 1; } else { - afkticks[i] = 0; + afkTicks[i] = 0; } } } @@ -157,7 +157,7 @@ void WorldTick() continue; if (entity->m_bEnemy()) continue; - if (afk && afkticks[i] >= int(afktime)) //don't follow target that was determined afk + if (afk && afkTicks[i] >= int(afktime)) //don't follow target that was determined afk continue; if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity)) continue; @@ -188,7 +188,7 @@ void WorldTick() continue; // ooooo, a target follow_target = i; - afkticks[i] = 0; //set afk ticks to 0 + afkTicks[i] = 0; //set afk ticks to 0 } } // last check for entity before we continue @@ -208,7 +208,7 @@ void WorldTick() //check if target is afk if (afk) { - if (afkticks[follow_target] >= 990) + if (afkTicks[follow_target] >= int(afktime)) { follow_target = 0; return; @@ -260,7 +260,7 @@ void WorldTick() if (loc_orig.DistTo(breadcrumbs.at(i)) < 60.f) { idle_time.update(); - for (int i2 = 0; i2 <= i; i2++) + for (int j = 0; j <= i; j++) breadcrumbs.erase(breadcrumbs.begin()); } } From f734e4534436446041a3f849ef58948e1632a6b1 Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sun, 24 Jun 2018 21:38:59 +0200 Subject: [PATCH 17/18] just use timers tf --- src/hacks/FollowBot.cpp | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index 1a63814a..df8e2c2a 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -52,9 +52,9 @@ static CatVar autojump(CV_SWITCH, "fb_autojump", "1", "Autojump", "Automatically jump if stuck"); static CatVar afk(CV_SWITCH, "fb_afk", "1", "Switch target if AFK", "Automatically switch target if the target is afk"); -static CatVar afktime(CV_INT, "fb_afk_time", "990", "Max AFK Time", - "Max ticks (66 * time in seconds) spent standing still " - "until a player is declared afk."); +static CatVar afktime( + CV_INT, "fb_afk_time", "15000", "Max AFK Time", + "Max time in ms spent standing still before player gets declared afk"); // Something to store breadcrumbs created by followed players static std::vector breadcrumbs; @@ -62,9 +62,10 @@ static const int crumb_limit = 64; // limit // Followed entity, externed for highlight color int follow_target = 0; +bool inited; -static long int lasttaunt; //time since epoch when "taunt" was last executed -std::array afkticks; //for how many createmove ticks the player hasn't been moving +Timer lastTaunt{}; //time since taunt was last executed, used to avoid kicks +std::array afkTicks; //for how many ms the player hasn't been moving void checkAFK() { @@ -73,17 +74,22 @@ void checkAFK() auto entity = ENTITY(i); if (CE_BAD(entity)) continue; - if (CE_VECTOR(entity, netvar.vVelocity).IsZero(5.0f)) + if (!CE_VECTOR(entity, netvar.vVelocity).IsZero(5.0f)) { - afkTicks[i] = afkTicks[i] + 1; - } - else - { - afkTicks[i] = 0; + afkTicks[i].update(); } } } +void init() +{ + for (int i; i < afkTicks.size(); i++) + { + afkTicks[i].update(); + } + inited = true; +} + void WorldTick() { if (!followbot) @@ -91,6 +97,8 @@ void WorldTick() follow_target = 0; return; } + if (!inited) + init(); // We need a local player to control if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer()) @@ -157,7 +165,7 @@ void WorldTick() continue; if (entity->m_bEnemy()) continue; - if (afk && afkTicks[i] >= int(afktime)) //don't follow target that was determined afk + if (afk && afkTicks[i].check(int(afktime))) //don't follow target that was determined afk continue; if (IsPlayerDisguised(entity) || IsPlayerInvisible(entity)) continue; @@ -188,7 +196,7 @@ void WorldTick() continue; // ooooo, a target follow_target = i; - afkTicks[i] = 0; //set afk ticks to 0 + afkTicks[i].update(); //set afk time to 0 } } // last check for entity before we continue @@ -208,7 +216,7 @@ void WorldTick() //check if target is afk if (afk) { - if (afkTicks[follow_target] >= int(afktime)) + if (afkTicks[follow_target].check(int(afktime))) { follow_target = 0; return; @@ -267,11 +275,8 @@ void WorldTick() //moved because its worthless otherwise if (sync_taunt && HasCondition(followtar)) { - //std::time_t time = std::time(nullptr); - long int t = static_cast (std::time(nullptr)); - if (!(t == lasttaunt)) + if (lastTaunt.test_and_set(1000)) { - lasttaunt = t; g_IEngine->ClientCmd("taunt"); } } From 6f8292ce0a66e0b9e7cb5c6487181c3da616e4f0 Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sun, 24 Jun 2018 21:56:20 +0200 Subject: [PATCH 18/18] fix --- src/hacks/FollowBot.cpp | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/src/hacks/FollowBot.cpp b/src/hacks/FollowBot.cpp index df8e2c2a..fa130ac3 100644 --- a/src/hacks/FollowBot.cpp +++ b/src/hacks/FollowBot.cpp @@ -10,7 +10,6 @@ #include #include #include -#include namespace hacks::shared::followbot { @@ -233,20 +232,11 @@ void WorldTick() auto tar_orig = followtar->m_vecOrigin(); auto loc_orig = LOCAL_E->m_vecOrigin(); auto dist_to_target = loc_orig.DistTo(tar_orig); - if (roambot) + + if ((dist_to_target < (float) follow_distance) && + VisCheckEntFromEnt(LOCAL_E, followtar)) { - if ((dist_to_target < (float)follow_distance) && VisCheckEntFromEnt(LOCAL_E, followtar)) - { - idle_time.update(); - } - } - else - { - if (dist_to_target < 30) - { - breadcrumbs.clear(); - idle_time.update(); - } + idle_time.update(); } // New crumbs, we add one if its empty so we have something to follow @@ -257,12 +247,6 @@ void WorldTick() // Prune old and close crumbs that we wont need anymore, update idle timer // too - while (breadcrumbs.size() > 1 && loc_orig.DistTo(breadcrumbs.at(0)) < 60.f) - { - idle_time.update(); - breadcrumbs.erase(breadcrumbs.begin()); - } - for (int i = 0; i < breadcrumbs.size(); i++) { if (loc_orig.DistTo(breadcrumbs.at(i)) < 60.f) @@ -274,11 +258,8 @@ void WorldTick() } //moved because its worthless otherwise - if (sync_taunt && HasCondition(followtar)) { - if (lastTaunt.test_and_set(1000)) - { + if (sync_taunt && HasCondition(followtar) && lastTaunt.test_and_set(1000)) { g_IEngine->ClientCmd("taunt"); - } } // Follow the crumbs when too far away, or just starting to follow