diff --git a/CMakeLists.txt b/CMakeLists.txt index f6eefc03..d32852c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ endif() find_package(Git REQUIRED) find_package(Boost REQUIRED) +find_package(SDL2 REQUIRED) # cat packages diff --git a/attach b/attach index 35e0bcfb..2881a4b0 100755 --- a/attach +++ b/attach @@ -1,7 +1,6 @@ #!/usr/bin/env bash sudo ./scripts/auto-updater -sudo ./scripts/attach-partybypass $1 line=$(pidof hl2_linux) arr=($line) inst=$1 diff --git a/attach-gdb b/attach-gdb index a98fd7e0..2ecca801 100755 --- a/attach-gdb +++ b/attach-gdb @@ -1,7 +1,6 @@ #!/usr/bin/env bash sudo ./scripts/auto-updater -sudo ./scripts/attach-partybypass $1 line=$(pidof hl2_linux) arr=($line) inst=$1 diff --git a/attach-libnamed.sh b/attach-libnamed.sh index 2b01035a..09f5aeec 100755 --- a/attach-libnamed.sh +++ b/attach-libnamed.sh @@ -4,7 +4,6 @@ # https://github.com/LWSS/Fuzion/commit/a53b6c634cde0ed47b08dd587ba40a3806adf3fe sudo ./scripts/auto-updater -sudo ./scripts/attach-partybypass $1 line=$(pidof hl2_linux) arr=($line) inst=$1 diff --git a/external/libglez b/external/libglez index ac817c1c..d73465e8 160000 --- a/external/libglez +++ b/external/libglez @@ -1 +1 @@ -Subproject commit ac817c1c55b61387df289773fb3761fee8f462c0 +Subproject commit d73465e8ac369db0cbbfcd0b9f7d4047cc66b3ed diff --git a/include/MiscTemporary.hpp b/include/MiscTemporary.hpp index 7a3918d9..c47d9b91 100755 --- a/include/MiscTemporary.hpp +++ b/include/MiscTemporary.hpp @@ -28,6 +28,9 @@ extern settings::Bool crypt_chat; extern settings::Bool nolerp; extern settings::Bool no_zoom; extern settings::Bool disable_visuals; +extern settings::Int print_r; +extern settings::Int print_g; +extern settings::Int print_b; void SetCanshootStatus(); extern bool CanShootException; diff --git a/include/core/profiler.hpp b/include/core/profiler.hpp index fd12c271..849b428c 100644 --- a/include/core/profiler.hpp +++ b/include/core/profiler.hpp @@ -43,7 +43,7 @@ public: #if ENABLE_PROFILER #define PROF_SECTION(id) \ static ProfilerSection __PROFILER__##id(#id); \ - ProfilerNode __PROFILER_NODE__##id(__PROFILER__##id); + volatile ProfilerNode __PROFILER_NODE__##id(__PROFILER__##id); #else #define PROF_SECTION(id) #endif diff --git a/include/reclasses/C_TFWeaponBaseMelee.hpp b/include/reclasses/C_TFWeaponBaseMelee.hpp index 61eced95..34bec8f0 100644 --- a/include/reclasses/C_TFWeaponBaseMelee.hpp +++ b/include/reclasses/C_TFWeaponBaseMelee.hpp @@ -23,7 +23,7 @@ public: inline static int GetSwingRange(IClientEntity *self) { if (g_pLocalPlayer->holding_sapper) - return 48; + return 115; typedef int (*fn_t)(IClientEntity *); return vfunc(self, offsets::PlatformOffset(521, offsets::undefined, 521), 0)(self); } diff --git a/install-all b/install-all index 48ff7122..12ad6347 100755 --- a/install-all +++ b/install-all @@ -9,7 +9,7 @@ fi # Install base Dependencies # if [ -x "$(command -v pacman)" ]; then - sudo pacman -S --needed --noconfirm boost cmake make gcc gdb lib32-sdl2 lib32-glew freetype2 rsync lib32-libglvnd + sudo pacman -S --needed --noconfirm boost cmake make gcc gdb lib32-sdl2 lib32-glew lib32-freetype2 rsync lib32-libglvnd else sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y sudo apt update diff --git a/lib/libpartybypass-linux.so b/lib/libpartybypass-linux.so deleted file mode 100644 index aeff700d..00000000 Binary files a/lib/libpartybypass-linux.so and /dev/null differ diff --git a/scripts/attach-partybypass b/scripts/attach-partybypass deleted file mode 100755 index abb87c34..00000000 --- a/scripts/attach-partybypass +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash -if [ ! -f ./scripts/partybypass-preferences ]; then - while true; do - echo 'https://github.com/nullworks/cathook/wiki/What-is-Partybypass-and-how-do-I-use-it%3F' - read -p "Do you want to enable the precompiled partybypass library? y/n " yn - case $yn in - [Yy]* ) echo true > ./scripts/partybypass-preferences; break;; - [Nn]* ) echo false > ./scripts/partybypass-preferences; exit;; - * ) echo "Please answer y or n.";; - esac - done -fi -if [ `cat ./scripts/partybypass-preferences` == "true" ]; then - line=$(pidof hl2_linux) - arr=($line) - inst=$1 - if [ $# == 0 ]; then - inst=0 - fi - - if [ ${#arr[@]} == 0 ]; then - echo TF2 isn\'t running! - exit - fi - - if [ $inst -gt ${#arr[@]} ] || [ $inst == ${#arr[@]} ]; then - echo wrong index! - exit - fi - - proc=${arr[$inst]} - - # pBypass for crash dumps being sent - # You may also want to consider using -nobreakpad in your launch options. - sudo rm -rf /tmp/dumps # Remove if it exists - sudo mkdir /tmp/dumps # Make it as root - sudo chmod 000 /tmp/dumps # No permissions - - FILENAME="/tmp/.gl$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1)" - - cp "./lib/libpartybypass-linux.so" "$FILENAME" - - gdb -n -q -batch \ - -ex "attach $proc" \ - -ex "set \$dlopen = (void*(*)(char*, int)) dlopen" \ - -ex "call \$dlopen(\"$FILENAME\", 1)" \ - -ex "detach" \ - -ex "quit" > /dev/null 2>&1 - - rm $FILENAME - echo -e "\n\033[1;34mPartybypass injected.\033[0m" && exit 0 -fi diff --git a/scripts/run-updater b/scripts/run-updater index a5377d2a..716d02c4 100755 --- a/scripts/run-updater +++ b/scripts/run-updater @@ -2,7 +2,7 @@ LOCKFILE=/tmp/chupdater.lock if [ -e ${LOCKFILE} ] && ps -p `cat ${LOCKFILE}` >/dev/null; then - echo -e "\033[1;31m \n \nAuto Updater: Auto Updater already running in the background\n\033[0m" + echo -e "\033[1;33m \n \nAuto Updater: Auto Updater already running in the background\n\033[0m" exit 1 fi @@ -13,9 +13,9 @@ echo $$ > ${LOCKFILE} echo -e "\033[1;34m \n \nAuto Updater: Updating cathook in the background\n\033[0m" if [ "$(git rev-parse --is-shallow-repository)" == "true" ]; then - sudo -u $LOGNAME bash -c 'git fetch --depth 1 origin >/dev/null && git reset --hard @{upstream} >/dev/null && git submodule update --depth 1 --init --recursive >/dev/null' || { echo -e "\033[1;31m \n \nAuto Updater: Failed to pull from github!\n\033[0m"; exit 1; } + sudo -u $LOGNAME bash -c 'git fetch --force --depth 1 origin refs/tags/latest:refs/tags/latest && git reset --hard latest && git submodule update --depth 1 --init --recursive || { echo -e "\033[1;33m\nFailed to pull from github! Trying alternative pull (legacy)\n\033[0m"; git fetch --depth 1 && git reset --hard @{upstream} && git submodule update --depth 1 --init --recursive; }' || { echo -e "\033[1;31m\nFailed to pull from github! A reinstall is recommended. https://github.com/nullworks/cathook\n\033[0m"; exit 1; } else - sudo -u $LOGNAME bash -c 'git pull origin >/dev/null && git submodule update --init --recursive >/dev/null' || { echo -e "\033[1;31m \n \nAuto Updater: Failed to pull from github!\n\033[0m"; exit 1; } + sudo -u $LOGNAME bash -c 'echo -e "\033[1;33m\nWarning! Running in developer mode! Expect issues!\n\033[0m" && git pull origin >/dev/null && git submodule update --init --recursive >/dev/null' || { echo -e "\033[1;31m \n \nAuto Updater: Failed to pull from github!\n\033[0m"; exit 1; } fi pushd build >/dev/null || exit 1 diff --git a/src/MiscTemporary.cpp b/src/MiscTemporary.cpp index d6cf5e25..5d53699a 100644 --- a/src/MiscTemporary.cpp +++ b/src/MiscTemporary.cpp @@ -38,5 +38,6 @@ settings::Bool clean_screenshots{ "visual.clean-screenshots", "false" }; settings::Bool nolerp{ "misc.no-lerp", "false" }; settings::Bool no_zoom{ "remove.scope", "false" }; settings::Bool disable_visuals{ "visual.disable", "false" }; - -static CatCommand identify("print_steamid", "Prints your SteamID", []() { g_ICvar->ConsolePrintf("%u\n", g_ISteamUser->GetSteamID().GetAccountID()); }); +settings::Int print_r{ "print.rgb.r", "183" }; +settings::Int print_g{ "print.rgb.b", "27" }; +settings::Int print_b{ "print.rgb.g", "139" }; diff --git a/src/core/logging.cpp b/src/core/logging.cpp index 32870fe5..82083028 100644 --- a/src/core/logging.cpp +++ b/src/core/logging.cpp @@ -13,6 +13,7 @@ #include "common.hpp" #include "hack.hpp" +#include "MiscTemporary.hpp" settings::Bool log_to_console{ "hack.log-console", "false" }; @@ -51,7 +52,7 @@ void logging::Info(const char *fmt, ...) if (!hack::shutdown) { if (*log_to_console) - g_ICvar->ConsolePrintf("CAT: %s \n", result.get()); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "CAT: %s \n", result.get()); } #endif } diff --git a/src/entityhitboxcache.cpp b/src/entityhitboxcache.cpp index c382d496..d442af8c 100644 --- a/src/entityhitboxcache.cpp +++ b/src/entityhitboxcache.cpp @@ -44,9 +44,6 @@ void EntityHitboxCache::InvalidateCache() void EntityHitboxCache::Update() { InvalidateCache(); - if (CE_BAD(parent_ref)) - if (GetHitbox(0)) - return; } void EntityHitboxCache::Init() @@ -103,7 +100,7 @@ bool EntityHitboxCache::VisibilityCheck(int id) return m_VisCheck[id]; } -static settings::Int setupbones_time{ "source.setupbones-time", "0" }; +static settings::Int setupbones_time{ "source.setupbones-time", "1" }; static std::mutex setupbones_mutex; @@ -131,8 +128,16 @@ matrix3x4_t *EntityHitboxCache::GetBones() // std::lock_guard lock(setupbones_mutex); if (g_Settings.is_create_move) { - RAW_ENT(parent_ref)->GetModel(); - bones_setup = RAW_ENT(parent_ref)->SetupBones(bones, MAXSTUDIOBONES, 0x7FF00, bones_setup_time); + PROF_SECTION(bone_test); + auto to_copy = CE_VAR(parent_ref, 0x838, matrix3x4_t *); + if (to_copy) + { + bones->Invalidate(); + memcpy((matrix3x4_t *) bones, to_copy, 48 * (CE_INT(parent_ref, 0x844))); + bones_setup = true; + } + else + bones_setup = RAW_ENT(parent_ref)->SetupBones(bones, MAXSTUDIOBONES, 0x7FF00, bones_setup_time); } } return bones; @@ -155,34 +160,32 @@ void EntityHitboxCache::Reset() CachedHitbox *EntityHitboxCache::GetHitbox(int id) { + if (m_CacheValidationFlags[id]) + return &m_CacheInternal[id]; mstudiobbox_t *box; if (!m_bInit) Init(); if (id < 0 || id >= m_nNumHitboxes) - return 0; + return nullptr; if (!m_bSuccess) - return 0; + return nullptr; if (CE_BAD(parent_ref)) - return 0; - typedef int (*InvalidateBoneCache_t)(IClientEntity *); - static uintptr_t addr = gSignatures.GetClientSignature("55 8B 0D ? ? ? ? 89 E5 8B 45 ? 8D 51"); - static InvalidateBoneCache_t InvalidateBoneCache = InvalidateBoneCache_t(addr); - InvalidateBoneCache(RAW_ENT(parent_ref)); - auto model = (model_t *) RAW_ENT(parent_ref)->GetModel(); + return nullptr; + auto model = (const model_t *) RAW_ENT(parent_ref)->GetModel(); if (!model) - return 0; + return nullptr; auto shdr = g_IModelInfo->GetStudiomodel(model); if (!shdr) - return 0; + return nullptr; auto set = shdr->pHitboxSet(CE_INT(parent_ref, netvar.iHitboxSet)); if (!dynamic_cast(set)) - return 0; + return nullptr; box = set->pHitbox(id); if (!box) - return 0; + return nullptr; if (box->bone < 0 || box->bone >= MAXSTUDIOBONES) - return 0; + return nullptr; VectorTransform(box->bbmin, GetBones()[box->bone], m_CacheInternal[id].min); VectorTransform(box->bbmax, GetBones()[box->bone], m_CacheInternal[id].max); m_CacheInternal[id].bbox = box; diff --git a/src/hacks/AutoHeal.cpp b/src/hacks/AutoHeal.cpp index 99f67402..babd80c0 100644 --- a/src/hacks/AutoHeal.cpp +++ b/src/hacks/AutoHeal.cpp @@ -297,6 +297,7 @@ void DoResistSwitching() } int force_healing_target{ 0 }; +unsigned steamid = 0; static CatCommand heal_steamid("autoheal_heal_steamid", "Heals a player with SteamID", [](const CCommand &args) { if (args.ArgC() < 2) { @@ -382,7 +383,7 @@ void UpdateData() if (reset_cd[i].test_and_set(10000)) data[i] = {}; CachedEntity *ent = ENTITY(i); - if (CE_GOOD(ent)) + if (CE_GOOD(ent) && ent->m_bAlivePlayer()) { int health = ent->m_iHealth(); if (data[i].last_damage > g_GlobalVars->curtime) @@ -395,7 +396,7 @@ void UpdateData() data[i].accum_damage_start = 0.0f; } const int last_health = data[i].last_health; - if (health != last_health) + if (health != last_health && health <= g_pPlayerResource->GetMaxHealth(ent)) { reset_cd[i].update(); data[i].last_health = health; @@ -523,7 +524,7 @@ void CreateMove() current_user_cmd->buttons |= IN_ATTACK2; } } - if (!force_healing_target && !enable) + if (!force_healing_target && !steamid && !enable) return; if (GetWeaponMode() != weapon_medigun) return; @@ -532,10 +533,27 @@ void CreateMove() CachedEntity *target = ENTITY(force_healing_target); if (CE_GOOD(target)) { - Vector out; - GetHitbox(target, 7, out); - AimAt(g_pLocalPlayer->v_Eye, out, current_user_cmd); - current_user_cmd->buttons |= IN_ATTACK; + if (target->player_info.friendsID != steamid) + force_healing_target = 0; + else + { + Vector out; + GetHitbox(target, 7, out); + AimAt(g_pLocalPlayer->v_Eye, out, current_user_cmd); + current_user_cmd->buttons |= IN_ATTACK; + } + } + } + else if (steamid) + { + for (auto i = 0; i < g_IEngine->GetMaxClients(); i++) + { + CachedEntity *ent = ENTITY(i); + if (ent->player_info.friendsID == steamid) + { + force_healing_target = steamid; + break; + } } } if (!enable) @@ -587,8 +605,13 @@ void CreateMove() void rvarCallback(settings::VariableBase &var, int after) { - if (after < 0) + if (!after) + { + force_healing_target = 0; + steamid = 0; return; + } + steamid = after; for (int i = 1; i <= 32 && i < HIGHEST_ENTITY; i++) { CachedEntity *ent = ENTITY(i); @@ -603,8 +626,13 @@ void rvarCallback(settings::VariableBase &var, int after) } } } +void LevelInit() +{ + force_healing_target = 0; +} static InitRoutine Init([]() { steam_var.installChangeCallback(rvarCallback); EC::Register(EC::CreateMove, CreateMove, "autoheal", EC::average); + EC::Register(EC::LevelInit, LevelInit, "autoheal_lvlinit", EC::average); }); } // namespace hacks::tf::autoheal diff --git a/src/hacks/AutoJoin.cpp b/src/hacks/AutoJoin.cpp index 08b481c3..1d8f8d99 100644 --- a/src/hacks/AutoJoin.cpp +++ b/src/hacks/AutoJoin.cpp @@ -11,11 +11,13 @@ #include "common.hpp" #include "hack.hpp" +#include "MiscTemporary.hpp" static settings::Bool autojoin_team{ "autojoin.team", "false" }; static settings::Int autojoin_class{ "autojoin.class", "0" }; static settings::Bool auto_queue{ "autojoin.auto-queue", "false" }; static settings::Bool auto_requeue{ "autojoin.auto-requeue", "false" }; +static settings::Bool partybypass{ "hack.party-bypass", "true" }; namespace hacks::shared::autojoin { @@ -130,5 +132,18 @@ void onShutdown() tfmm::startQueue(); } -static InitRoutine init([]() { EC::Register(EC::CreateMove, update, "cm_autojoin", EC::average); }); +static CatCommand get_steamid("print_steamid", "Prints your SteamID", []() { g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "%u\n", g_ISteamUser->GetSteamID().GetAccountID()); }); + +static InitRoutine init([]() { + EC::Register(EC::CreateMove, update, "cm_autojoin", EC::average); + static BytePatch p = { gSignatures.GetClientSignature, "55 89 E5 53 83 EC 14 8B 45 08 8B 40 30", 0x00, { 0x31, 0xC0, 0x40, 0xC3 } }; + if (*partybypass) + p.Patch(); + partybypass.installChangeCallback([](settings::VariableBase &, bool new_val) { + if (new_val) + p.Patch(); + else + p.Shutdown(); + }); +}); } // namespace hacks::shared::autojoin diff --git a/src/hacks/Backtrack.cpp b/src/hacks/Backtrack.cpp index 2d8fe649..8ddc19fd 100644 --- a/src/hacks/Backtrack.cpp +++ b/src/hacks/Backtrack.cpp @@ -75,7 +75,7 @@ void Init() { for (int i = 0; i < 32; i++) for (int j = 0; j < 66; j++) - EmptyBacktrackData(headPositions[i][j]); + headPositions[i][j] = {}; } int BestTick = -1; @@ -89,6 +89,7 @@ static void Run() isBacktrackEnabled = false; return; } + UpdateIncomingSequences(); isBacktrackEnabled = true; if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer() || CE_BAD(LOCAL_W)) @@ -106,50 +107,49 @@ static void Run() CUserCmd *cmd = current_user_cmd; float bestFov = 99999; - float prev_distance = 9999; - - auto bestEntBestTick = getBestEntBestTick(); - BestTick = bestEntBestTick.second; - iBestTarget = bestEntBestTick.first; - - for (int i = 1; i < g_IEngine->GetMaxClients(); i++) + float prev_distance = 9999; + std::pair bestEntBestTick = getBestEntBestTick(); + BestTick = bestEntBestTick.second; + iBestTarget = bestEntBestTick.first; + // Fill backtrack data (stored in headPositions) { - CachedEntity *pEntity = ENTITY(i); + PROF_SECTION(cm_bt_ent_loop) + for (int i = 1; i < g_IEngine->GetMaxClients(); i++) + { + CachedEntity *pEntity = ENTITY(i); + if (CE_BAD(pEntity) || !pEntity->m_bAlivePlayer()) + { + for (BacktrackData &btd : headPositions[i]) + btd.simtime = FLT_MAX; + continue; + } + if (!pEntity->m_bEnemy()) + continue; + if (pEntity->m_Type() != ENTITY_PLAYER) + continue; + if (!pEntity->hitboxes.GetHitbox(0)) + continue; + if (HasCondition(pEntity)) + continue; + auto &hbd = headPositions[i][cmd->command_number % getTicks()]; + float _viewangles = CE_VECTOR(pEntity, netvar.m_angEyeAngles).y; + hbd.viewangles = (_viewangles > 180) ? _viewangles - 360 : _viewangles; + hbd.simtime = CE_FLOAT(pEntity, netvar.m_flSimulationTime); + hbd.entorigin = pEntity->InternalEntity()->GetAbsOrigin(); + hbd.tickcount = cmd->tick_count; - if (CE_BAD(pEntity) || !pEntity->m_bAlivePlayer()) - { - for (BacktrackData &btd : headPositions[i]) - EmptyBacktrackData(btd); - continue; + for (size_t i = 0; i < 18; i++) + { + hbd.hitboxes[i].center = pEntity->hitboxes.GetHitbox(i)->center; + hbd.hitboxes[i].min = pEntity->hitboxes.GetHitbox(i)->min; + hbd.hitboxes[i].max = pEntity->hitboxes.GetHitbox(i)->max; + } + hbd.collidable.min = RAW_ENT(pEntity)->GetCollideable()->OBBMins() + hbd.entorigin; + hbd.collidable.max = RAW_ENT(pEntity)->GetCollideable()->OBBMaxs() + hbd.entorigin; + hbd.collidable.center = (hbd.collidable.min + hbd.collidable.max) / 2; } - if (pEntity->m_iTeam() == LOCAL_E->m_iTeam()) - continue; - if (pEntity->m_Type() != ENTITY_PLAYER) - continue; - if (!pEntity->hitboxes.GetHitbox(0)) - continue; - if (HasCondition(pEntity)) - continue; - float _viewangles = CE_VECTOR(pEntity, netvar.m_angEyeAngles).y; - float viewangles = (_viewangles > 180) ? _viewangles - 360 : _viewangles; - float simtime = CE_FLOAT(pEntity, netvar.m_flSimulationTime); - Vector ent_orig = pEntity->InternalEntity()->GetAbsOrigin(); - std::array hbdArray; - for (size_t i = 0; i < hbdArray.max_size(); i++) - { - hbdArray.at(i).center = pEntity->hitboxes.GetHitbox(i)->center; - hbdArray.at(i).min = pEntity->hitboxes.GetHitbox(i)->min; - hbdArray.at(i).max = pEntity->hitboxes.GetHitbox(i)->max; - } - hitboxData collidable{}; - { - collidable.min = RAW_ENT(pEntity)->GetCollideable()->OBBMins() + ent_orig; - collidable.max = RAW_ENT(pEntity)->GetCollideable()->OBBMaxs() + ent_orig; - collidable.center = (collidable.min + collidable.max) / 2; - } - auto hdr = g_IModelInfo->GetStudiomodel(RAW_ENT(pEntity)->GetModel()); - headPositions[i][cmd->command_number % getTicks()] = BacktrackData{ cmd->tick_count, hbdArray, collidable, viewangles, simtime, ent_orig, cmd->command_number % getTicks() }; } + if (iBestTarget != -1 && CanShoot()) { CachedEntity *tar = ENTITY(iBestTarget); diff --git a/src/hacks/CatBot.cpp b/src/hacks/CatBot.cpp index 6cd9cb9f..4acda81e 100644 --- a/src/hacks/CatBot.cpp +++ b/src/hacks/CatBot.cpp @@ -191,8 +191,6 @@ void reportall() patch.Patch(); patched_report = true; } - player_info_s local; - g_IEngine->GetPlayerInfo(g_pLocalPlayer->entity_idx, &local); for (int i = 1; i < g_IEngine->GetMaxClients(); i++) { CachedEntity *ent = ENTITY(i); diff --git a/src/hacks/Misc.cpp b/src/hacks/Misc.cpp index c7b65da0..278a81b0 100644 --- a/src/hacks/Misc.cpp +++ b/src/hacks/Misc.cpp @@ -544,8 +544,23 @@ static CatCommand dump_vars("debug_dump_netvars", "Dump netvars of entity", [](c DumpRecvTable(ent, clz->m_pRecvTable, 0, ft, 0); }); +void Shutdown() +{ + if (CE_BAD(LOCAL_E)) + return; + // unpatching local player + void **vtable = *(void ***) (g_pLocalPlayer->entity->InternalEntity()); + if (vtable[offsets::ShouldDraw()] == C_TFPlayer__ShouldDraw_hook) + { + void *page = (void *) ((uintptr_t) vtable & ~0xFFF); + mprotect(page, 0xFFF, PROT_READ | PROT_WRITE | PROT_EXEC); + vtable[offsets::ShouldDraw()] = (void *) C_TFPlayer__ShouldDraw_original; + mprotect(page, 0xFFF, PROT_READ | PROT_EXEC); + } +} InitRoutine init([]() { teammatesPushaway = g_ICvar->FindVar("tf_avoidteammates_pushaway"); + EC::Register(EC::Shutdown, Shutdown, "draw_local_player", EC::average); EC::Register(EC::CreateMove, CreateMove, "cm_misc_hacks", EC::average); #if ENABLE_VISUALS EC::Register(EC::Draw, DrawText, "draw_misc_hacks", EC::average); diff --git a/src/hacks/MiscAimbot.cpp b/src/hacks/MiscAimbot.cpp index 8740193a..ad8b6c14 100644 --- a/src/hacks/MiscAimbot.cpp +++ b/src/hacks/MiscAimbot.cpp @@ -9,6 +9,8 @@ #include "PlayerTools.hpp" #include "hacks/Trigger.hpp" +namespace hacks::tf2::misc_aimbot +{ static settings::Bool sandwichaim_enabled{ "sandwichaim.enable", "false" }; static settings::Button sandwichaim_aimkey{ "sandwichaim.aimkey", "" }; static settings::Int sandwichaim_aimkey_mode{ "sandwichaim.aimkey-mode", "0" }; @@ -247,8 +249,8 @@ static void SapperAimbot() return; CachedEntity *target = nullptr; - float fov = FLT_MAX; - float range = re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)); + float distance = FLT_MAX; + for (int i = 0; i < entity_cache::max; i++) { CachedEntity *ent = ENTITY(i); @@ -260,21 +262,29 @@ static void SapperAimbot() continue; if (CE_BYTE(ent, netvar.m_bHasSapper)) continue; - if (GetBuildingPosition(ent).DistTo(g_pLocalPlayer->v_Eye) > range) - continue; - float new_fov = GetFov(g_pLocalPlayer->v_OrigViewangles, g_pLocalPlayer->v_Eye, GetBuildingPosition(ent)); - if (fov <= new_fov) + float new_distance = g_pLocalPlayer->v_Eye.DistTo(GetBuildingPosition(ent)); + if (distance <= new_distance) continue; - fov = new_fov; - target = ent; + distance = new_distance; + target = ent; } if (target) { - AimAt(g_pLocalPlayer->v_Eye, GetBuildingPosition(target), current_user_cmd); - if (autosapper_silent) - g_pLocalPlayer->bUseSilentAngles = true; - current_user_cmd->buttons |= IN_ATTACK; + float range = re::C_TFWeaponBaseMelee::GetSwingRange(RAW_ENT(LOCAL_W)); + Vector angle = GetAimAtAngles(g_pLocalPlayer->v_Eye, GetBuildingPosition(target)); + Vector forward = GetForwardVector(g_pLocalPlayer->v_Eye, angle, range); + trace_t trace; + if (IsEntityVectorVisible(target, forward, MASK_SHOT, &trace)) + { + if (trace.DidHit() && (IClientEntity *) trace.m_pEnt == RAW_ENT(target)) + { + current_user_cmd->viewangles = angle; + if (autosapper_silent) + g_pLocalPlayer->bUseSilentAngles = true; + current_user_cmd->buttons |= IN_ATTACK; + } + } } } @@ -287,3 +297,4 @@ static void CreateMove() } static InitRoutine init([]() { EC::Register(EC::CreateMove, CreateMove, "cm_miscaimbot", EC::late); }); +} // namespace hacks::tf2::misc_aimbot diff --git a/src/helpers.cpp b/src/helpers.cpp index e8aeadcb..0763d68f 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -614,6 +614,8 @@ bool HasWeapon(CachedEntity *ent, int wantedId) int *hWeapons; // Grab the handle and store it into the var hWeapons = (int *) ((unsigned) (RAW_ENT(ent) + netvar.hMyWeapons)); + if (!hWeapons || !RAW_ENT(ent) || ent->m_Type() != ENTITY_PLAYER) + return false; // Go through the handle array and search for the item for (int i = 0; hWeapons[i]; i++) { @@ -893,6 +895,8 @@ bool VisCheckEntFromEntVector(Vector startVector, CachedEntity *startEnt, Cached Vector GetBuildingPosition(CachedEntity *ent) { + if (ent->hitboxes.GetHitbox(1)) + return ent->hitboxes.GetHitbox(1)->center; if (ent->hitboxes.GetHitbox(0)) return ent->hitboxes.GetHitbox(0)->center; Vector res; diff --git a/src/hooks/CreateMove.cpp b/src/hooks/CreateMove.cpp index 7cb21879..e59bceca 100644 --- a/src/hooks/CreateMove.cpp +++ b/src/hooks/CreateMove.cpp @@ -117,8 +117,6 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, CUs } ret = original::CreateMove(this_, input_sample_time, cmd); - PROF_SECTION(CreateMove); - if (!cmd) { g_Settings.is_create_move = false; @@ -146,7 +144,7 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, CUs return true; } - // PROF_BEGIN(); + PROF_SECTION(CreateMove); if (current_user_cmd && current_user_cmd->command_number) last_cmd_number = current_user_cmd->command_number; @@ -339,7 +337,6 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, CUs } } #endif - hacks::shared::backtrack::UpdateIncomingSequences(); if (CE_GOOD(g_pLocalPlayer->entity)) { speedapplied = false; diff --git a/src/hooks/DispatchUserMessage.cpp b/src/hooks/DispatchUserMessage.cpp index 292125dc..5a2d67ae 100644 --- a/src/hooks/DispatchUserMessage.cpp +++ b/src/hooks/DispatchUserMessage.cpp @@ -120,7 +120,7 @@ DEFINE_HOOKED_METHOD(DispatchUserMessage, bool, void *this_, int type, bf_read & anti_balance_attempts = 0; } if (anti_balance_attempts < 2) - g_IEngine->ClientCmd_Unrestricted("cat_disconnect read if gay;wait 100;cat_mm_join"); + g_IEngine->ClientCmd_Unrestricted("killserver;wait 100;cat_mm_join"); else { std::string autobalance_msg = "tf_party_chat \"autobalanced in 3 seconds"; @@ -132,7 +132,6 @@ DEFINE_HOOKED_METHOD(DispatchUserMessage, bool, void *this_, int type, bf_read & } anti_balance_attempts++; } - buf.Seek(0); } break; case 4: @@ -156,13 +155,14 @@ DEFINE_HOOKED_METHOD(DispatchUserMessage, bool, void *this_, int type, bf_read & std::string event(p), name((p += event.size() + 1)), message(p + name.size() + 1); if (chat_filter_enable && data[0] == LOCAL_E->m_IDX && event == "#TF_Name_Change") { - chat_stack::Say("." + clear, false); + chat_stack::Say("\e" + clear, false); } else if (chat_filter_enable && data[0] != LOCAL_E->m_IDX && event.find("TF_Chat") == 0) { player_info_s info{}; g_IEngine->GetPlayerInfo(LOCAL_E->m_IDX, &info); - std::string name1 = info.name, claz; + const char *claz = nullptr; + std::string name1 = info.name; switch (g_pLocalPlayer->clazz) { @@ -197,7 +197,10 @@ DEFINE_HOOKED_METHOD(DispatchUserMessage, bool, void *this_, int type, bf_read & break; } - std::vector res = { "skid", "script", "cheat", "hak", "hac", "f1", "hax", "vac", "ban", "bot", "report", "kick", claz }; + std::vector res = { "skid", "script", "cheat", "hak", "hac", "f1", "hax", "vac", "ban", "bot", "report", "kick" }; + if (claz) + res.emplace_back(claz); + SplitName(res, name1, 2); SplitName(res, name1, 3); @@ -213,7 +216,7 @@ DEFINE_HOOKED_METHOD(DispatchUserMessage, bool, void *this_, int type, bf_read & for (auto filter : res) if (boost::contains(message2, filter)) { - chat_stack::Say("." + clear, true); + chat_stack::Say("\e" + clear, true); retrun = true; lastfilter = message; lastname = format(name); diff --git a/src/hooks/FireEvent.cpp b/src/hooks/FireEvent.cpp index c90b153f..4d6fbfb3 100644 --- a/src/hooks/FireEvent.cpp +++ b/src/hooks/FireEvent.cpp @@ -5,11 +5,16 @@ #include "HookedMethods.hpp" +namespace hacks::tf2::killstreak +{ +extern void fire_event(IGameEvent *event); +} namespace hooked_methods { DEFINE_HOOKED_METHOD(FireEvent, bool, IGameEventManager2 *this_, IGameEvent *event, bool no_broadcast) { + hacks::tf2::killstreak::fire_event(event); return original::FireEvent(this_, event, no_broadcast); } -} // namespace hooked_methods \ No newline at end of file +} // namespace hooked_methods diff --git a/src/hooks/FireEventClientSide.cpp b/src/hooks/FireEventClientSide.cpp index e1a08014..f9297a42 100644 --- a/src/hooks/FireEventClientSide.cpp +++ b/src/hooks/FireEventClientSide.cpp @@ -5,11 +5,16 @@ #include "HookedMethods.hpp" +namespace hacks::tf2::killstreak +{ +extern void fire_event(IGameEvent *event); +} namespace hooked_methods { DEFINE_HOOKED_METHOD(FireEventClientSide, bool, IGameEventManager2 *this_, IGameEvent *event) { + hacks::tf2::killstreak::fire_event(event); return original::FireEventClientSide(this_, event); } -} // namespace hooked_methods \ No newline at end of file +} // namespace hooked_methods diff --git a/src/hooks/HookTools.cpp b/src/hooks/HookTools.cpp index 7fea402b..e1085442 100644 --- a/src/hooks/HookTools.cpp +++ b/src/hooks/HookTools.cpp @@ -6,24 +6,23 @@ namespace EC struct EventCallbackData { - explicit EventCallbackData(const EventFunction &function, std::string name, enum ec_priority priority) : function{ function }, priority{ int(priority) }, event_name{ name }, section{ name } + explicit EventCallbackData(const EventFunction &function, std::string name, enum ec_priority priority) : function{ function }, priority{ int(priority) }, section{ name }, event_name{ name } { + section.m_name = name; } EventFunction function; int priority; - mutable ProfilerSection section; + ProfilerSection section; std::string event_name; - bool operator<(const EventCallbackData &other) const - { - return priority < other.priority; - } }; -// Ordered set to always keep priorities correct -static std::multiset events[ec_types::EcTypesSize]; + +static std::vector events[ec_types::EcTypesSize]; void Register(enum ec_types type, const EventFunction &function, const std::string &name, enum ec_priority priority) { - events[type].insert(EventCallbackData(function, name, priority)); + events[type].emplace_back(function, name, priority); + // Order vector to always keep priorities correct + std::sort(events[type].begin(), events[type].end(), [](EventCallbackData &a, EventCallbackData &b) { return a.priority < b.priority; }); } void Unregister(enum ec_types type, const std::string &name) @@ -39,11 +38,11 @@ void Unregister(enum ec_types type, const std::string &name) void run(ec_types type) { - const auto &set = events[type]; - for (auto &i : set) + auto &vector = events[type]; + for (auto &i : vector) { #if ENABLE_PROFILER - ProfilerNode node(i.section); + volatile ProfilerNode node(i.section); #endif i.function(); } diff --git a/src/playerlist.cpp b/src/playerlist.cpp index 46c6a675..09b9c9f9 100644 --- a/src/playerlist.cpp +++ b/src/playerlist.cpp @@ -113,18 +113,19 @@ void Load() #if ENABLE_VISUALS rgba_t Color(unsigned steamid) { - if (AccessData(steamid).state == k_EState::DEVELOPER) + const auto &pl = AccessData(steamid); + if (pl.state == k_EState::DEVELOPER) return colors::RainbowCurrent(); - if (AccessData(steamid).state == k_EState::CAT) + else if (pl.state == k_EState::CAT) return colors::RainbowCurrent(); - if (AccessData(steamid).color.a) - { - return AccessData(steamid).color; - } - else - { - return k_Colors[static_cast(AccessData(steamid).state)]; - } + else if (pl.color.a) + return pl.color; + + int state = static_cast(pl.state); + if (state < sizeof(k_Colors) / sizeof(*k_Colors)) + return k_Colors[state]; + + return colors::empty; } rgba_t Color(CachedEntity *player) diff --git a/src/settings/SettingCommands.cpp b/src/settings/SettingCommands.cpp index 5036b916..9c97a7db 100644 --- a/src/settings/SettingCommands.cpp +++ b/src/settings/SettingCommands.cpp @@ -7,7 +7,7 @@ #include #include #include - +#include /* Created on 29.07.18. */ @@ -17,14 +17,14 @@ static void getAndSortAllConfigs(); static CatCommand cat("cat", "", [](const CCommand &args) { if (args.ArgC() < 3) { - g_ICvar->ConsolePrintf("Usage: cat [value]\n"); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "Usage: cat [value]\n"); return; } auto variable = settings::Manager::instance().lookup(args.Arg(2)); if (variable == nullptr) { - g_ICvar->ConsolePrintf("Variable not found: %s\n", args.Arg(2)); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "Variable not found: %s\n", args.Arg(2)); return; } @@ -32,21 +32,21 @@ static CatCommand cat("cat", "", [](const CCommand &args) { { if (args.ArgC() < 4) { - g_ICvar->ConsolePrintf("Usage: cat \n"); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "Usage: cat \n"); return; } variable->fromString(args.Arg(3)); - g_ICvar->ConsolePrintf("%s = \"%s\"\n", args.Arg(2), variable->toString().c_str()); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "%s = \"%s\"\n", args.Arg(2), variable->toString().c_str()); return; } else if (!strcmp(args.Arg(1), "get")) { - g_ICvar->ConsolePrintf("%s = \"%s\"\n", args.Arg(2), variable->toString().c_str()); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "%s = \"%s\"\n", args.Arg(2), variable->toString().c_str()); return; } else { - g_ICvar->ConsolePrintf("Usage: cat \n"); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "Usage: cat \n"); return; } }); diff --git a/src/settings/SettingsIO.cpp b/src/settings/SettingsIO.cpp index db1f7202..b78c4bc4 100644 --- a/src/settings/SettingsIO.cpp +++ b/src/settings/SettingsIO.cpp @@ -8,6 +8,7 @@ #include "core/logging.hpp" #include "interfaces.hpp" #include "icvar.h" +#include "MiscTemporary.hpp" settings::SettingsWriter::SettingsWriter(settings::Manager &manager) : manager(manager) { @@ -23,7 +24,7 @@ bool settings::SettingsWriter::saveTo(std::string path, bool only_changed) if (!stream || stream.bad() || !stream.is_open() || stream.fail()) { logging::Info("cat_save: FATAL! FAILED to create stream!"); - g_ICvar->ConsolePrintf("CAT: cat_save: Can't create config file!\n"); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "CAT: cat_save: Can't create config file!\n"); return false; } @@ -46,11 +47,11 @@ bool settings::SettingsWriter::saveTo(std::string path, bool only_changed) } if (!stream || stream.bad() || stream.fail()) { - g_ICvar->ConsolePrintf("CAT: cat_save: Failed to save config!\n"); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "CAT: cat_save: Failed to save config!\n"); logging::Info("cat_save: FATAL! Stream bad!"); } else - g_ICvar->ConsolePrintf("CAT: cat_save: Successfully saved config!\n"); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "CAT: cat_save: Successfully saved config!\n"); stream.close(); if (stream.fail()) logging::Info("cat_save: FATAL! Stream bad (2)!"); @@ -99,7 +100,7 @@ bool settings::SettingsReader::loadFrom(std::string path) if (stream.fail()) { logging::Info("cat_load: Can't access file!"); - g_ICvar->ConsolePrintf("CAT: cat_load: File doesn't exist / can't open file!\n"); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "CAT: cat_load: File doesn't exist / can't open file!\n"); return false; } @@ -114,12 +115,12 @@ bool settings::SettingsReader::loadFrom(std::string path) if (stream.fail() && !stream.eof()) { logging::Info("cat_load: FATAL: Read failed!"); - g_ICvar->ConsolePrintf("CAT: cat_load: Failed to read config!\n"); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "CAT: cat_load: Failed to read config!\n"); return false; } logging::Info("cat_load: Read Success!"); - g_ICvar->ConsolePrintf("CAT: cat_load: Successfully loaded config!\n"); + g_ICvar->ConsoleColorPrintf(Color(*print_r, *print_g, *print_b, 255), "CAT: cat_load: Successfully loaded config!\n"); finishString(true); return true; diff --git a/src/votelogger.cpp b/src/votelogger.cpp index 0e21a078..b53c6c57 100644 --- a/src/votelogger.cpp +++ b/src/votelogger.cpp @@ -48,21 +48,30 @@ void dispatchUserMessage(bf_read &buffer, int type) steamID = info.friendsID; if (eid == LOCAL_E->m_IDX) was_local_player = true; - if (*vote_kickn) - if (playerlist::AccessData(info.friendsID).state != playerlist::k_EState::RAGE && playerlist::AccessData(info.friendsID).state != playerlist::k_EState::DEFAULT) - g_IEngine->ClientCmd_Unrestricted("vote option2"); - if (*vote_kicky) - if (playerlist::AccessData(info.friendsID).state == playerlist::k_EState::RAGE || playerlist::AccessData(info.friendsID).state == playerlist::k_EState::DEFAULT) - g_IEngine->ClientCmd_Unrestricted("vote option1"); - if (*party_say) + if (*vote_kickn || *vote_kicky) { - if (g_IEngine->GetPlayerInfo(caller, &info2)) - { - // because tf2 is stupid and doesn't have escape characters, - // use the greek question marks instead. big brain. - // Clang-format why, TODO: Don't use format func - g_IEngine->ExecuteClientCmd(format("say_party [CAT] votekick called: ", boost::replace_all_copy((std::string) info2.name, ";", ";"), " => ", boost::replace_all_copy((std::string) info.name, ";", ";"), " (", reason, ")").c_str()); - } + auto &pl = playerlist::AccessData(info.friendsID); + if (*vote_kickn && pl.state != playerlist::k_EState::RAGE && pl.state != playerlist::k_EState::DEFAULT) + g_IEngine->ClientCmd_Unrestricted("vote option2"); + else if (*vote_kicky && (pl.state == playerlist::k_EState::RAGE || pl.state == playerlist::k_EState::DEFAULT)) + g_IEngine->ClientCmd_Unrestricted("vote option1"); + } + if (*party_say && g_IEngine->GetPlayerInfo(caller, &info2)) + { + char formated_string[512]; + // because tf2 is stupid and doesn't have escape characters, + // use the greek question marks instead. big brain. + std::string kicked_name(info.name), caller_name(info2.name); + /* ';' (0x3B) regular replaced with unicode analog ';' (0xCD 0xBE) + * to prevent exploits (by crafting name such that it executes command) + * and output message properly + * TO DO: Saner way to accomplish same */ + ReplaceString(kicked_name, ";", ";"); + ReplaceString(caller_name, ";", ";"); + std::snprintf(formated_string, sizeof(formated_string), + "say_party [CAT] votekick called: %s => %s (%s)", + caller_name.c_str(), kicked_name.c_str(), reason); + g_IEngine->ExecuteClientCmd(formated_string); } logging::Info("Vote called to kick %s [U:1:%u] for %s", name, steamID, reason); break; diff --git a/update b/update index 37c4c414..5a6db5ce 100755 --- a/update +++ b/update @@ -1,12 +1,16 @@ #!/usr/bin/env bash +if [ $EUID == 0 ]; then + echo "\033[1;31m\nThis script must not be run as root\n\033[0m" + exit 1 +fi #Get updated source code if [ "$(git rev-parse --is-shallow-repository)" == "true" ]; then - git fetch --depth 1 origin && git reset --hard @{upstream} && git submodule update --depth 1 --init --recursive || { echo -e "\033[1;31m \n \nFailed to pull from github!"; exit 1; } + git fetch --force --depth 1 origin refs/tags/latest:refs/tags/latest && git reset --hard latest && git submodule update --depth 1 --init --recursive || { echo -e "\033[1;33m\nFailed to pull from github! Trying alternative pull (legacy)\n\033[0m"; git fetch --depth 1 && git reset --hard @{upstream} && git submodule update --depth 1 --init --recursive || { echo -e "\033[1;31m\nFailed to pull from github! A reinstall is recommended. https://github.com/nullworks/cathook\n\033[0m"; exit 1; } } else - git pull origin && git submodule update --init --recursive || { echo -e "\033[1;31m \n \nFailed to pull from github!"; exit 1; } + echo -e "\033[1;33m\nWarning! Running in developer mode! Expect issues!\n\033[0m" && git pull origin && git submodule update --init --recursive || { echo -e "\033[1;31m\n\nFailed to pull from github!\n\033[0m"; exit 1; } fi #Update cathook -cd build && cmake .. && cmake --build . --target cathook -- -j$(grep -c '^processor' /proc/cpuinfo) || { echo -e "\033[1;31m \n \nFailed to compile cathook"; exit 1; } +cd build && cmake .. && cmake --build . --target cathook -- -j$(grep -c '^processor' /proc/cpuinfo) || { echo -e "\033[1;31m \n \nFailed to compile cathook\n\033[0m"; exit 1; } #Update data -sudo cmake --build . --target data || { echo -e "\033[1;31m \n \nFailed to update /opt/cathook/data directory"; exit 1; } -echo -e "\n\n\033[1;34mCathook updated successfully" +sudo cmake --build . --target data || { echo -e "\033[1;31m\nFailed to update /opt/cathook/data directory\n\033[0m"; exit 1; } +echo -e "\n\033[1;34mCathook updated successfully\n\033[0m"