commit
0f578a6298
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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 = https://github.com/nullworks/co-library.git
|
||||
|
@ -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)")
|
||||
@ -31,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)
|
||||
@ -62,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)
|
||||
|
1
external/co-library
vendored
Submodule
1
external/co-library
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 393948a6bf7ee4a62f5a3bd82d94c05d4bc405aa
|
@ -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}")
|
||||
|
||||
@ -50,6 +51,7 @@ add_subdirectory(hacks)
|
||||
add_subdirectory(hooks)
|
||||
add_subdirectory(reclasses)
|
||||
add_subdirectory(sdk)
|
||||
add_subdirectory(online)
|
||||
|
||||
if(EnableVisuals)
|
||||
add_subdirectory(visual)
|
||||
|
44
include/PlayerTools.hpp
Normal file
44
include/PlayerTools.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Created on 23.06.18.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
#include <optional>
|
||||
|
||||
#if ENABLE_VISUALS
|
||||
#include <colors.hpp>
|
||||
#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<colors::rgba_t> forceEspColorSteamId(unsigned id);
|
||||
std::optional<colors::rgba_t> forceEspColor(CachedEntity *entity);
|
||||
#endif
|
||||
|
||||
void onKilledBy(CachedEntity *entity);
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -7,5 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
class CachedEntity;
|
||||
|
||||
void UpdateHoovyList();
|
||||
bool IsHoovy(CachedEntity *entity);
|
||||
|
2
include/online/CMakeLists.txt
Normal file
2
include/online/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
target_sources(cathook PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Online.hpp")
|
40
include/online/Online.hpp
Normal file
40
include/online/Online.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Created on 23.06.18.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <colors.hpp>
|
||||
#include <config.h>
|
||||
#include <vector>
|
||||
|
||||
namespace online
|
||||
{
|
||||
|
||||
struct user_data
|
||||
{
|
||||
bool is_anonymous{ false };
|
||||
bool is_using_friendly_software{ false };
|
||||
bool is_steamid_verified{ false };
|
||||
std::string username{};
|
||||
std::vector<std::string> shown_groups{};
|
||||
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{};
|
||||
bool rainbow{ false };
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Identify unidentified users, send online status, etc
|
||||
*/
|
||||
void update();
|
||||
|
||||
user_data *getUserData(unsigned steamId);
|
||||
|
||||
}
|
@ -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<const glez::rgba *>(this);
|
||||
@ -76,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 };
|
||||
|
@ -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)
|
||||
@ -41,6 +42,7 @@ add_subdirectory(hacks)
|
||||
add_subdirectory(hooks)
|
||||
add_subdirectory(reclasses)
|
||||
add_subdirectory(sdk)
|
||||
add_subdirectory(online)
|
||||
|
||||
if(EnableVisuals)
|
||||
add_subdirectory(visual)
|
||||
|
161
src/PlayerTools.cpp
Normal file
161
src/PlayerTools.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
Created on 23.06.18.
|
||||
*/
|
||||
|
||||
#include <core/cvwrapper.hpp>
|
||||
#include <unordered_map>
|
||||
#include <hoovy.hpp>
|
||||
#include <playerlist.hpp>
|
||||
#include <online/Online.hpp>
|
||||
#include "PlayerTools.hpp"
|
||||
#include "entitycache.hpp"
|
||||
|
||||
static std::unordered_map<unsigned, unsigned> 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<TFCond_Taunting>(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<colors::rgba_t> forceEspColorSteamId(unsigned id)
|
||||
{
|
||||
if (id == 0)
|
||||
return std::nullopt;
|
||||
|
||||
auto pl = playerlist::Color(id);
|
||||
if (pl != colors::empty)
|
||||
return std::optional<colors::rgba_t>{ pl };
|
||||
|
||||
auto *co = online::getUserData(id);
|
||||
if (co)
|
||||
{
|
||||
if (co->has_color)
|
||||
return std::optional<colors::rgba_t>{ co->color };
|
||||
if (co->rainbow)
|
||||
return std::optional<colors::rgba_t>{ colors::RainbowCurrent() };
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
std::optional<colors::rgba_t> 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -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",
|
||||
|
13
src/hack.cpp
13
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;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <hacks/AntiAim.hpp>
|
||||
#include <hacks/ESP.hpp>
|
||||
#include <glez/draw.hpp>
|
||||
#include <PlayerTools.hpp>
|
||||
#include "common.hpp"
|
||||
|
||||
namespace hacks::shared::aimbot
|
||||
@ -60,8 +61,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",
|
||||
@ -574,8 +573,10 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
}
|
||||
}
|
||||
|
||||
// Taunting
|
||||
if (ignore_taunting && HasCondition<TFCond_Taunting>(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))
|
||||
@ -605,19 +606,7 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
HasCondition<TFCond_UberBulletResist>(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];
|
||||
|
@ -5,6 +5,7 @@
|
||||
* Author: nullifiedcat & Lighty
|
||||
*/
|
||||
|
||||
#include <PlayerTools.hpp>
|
||||
#include "common.hpp"
|
||||
|
||||
namespace hacks::tf::autodetonator
|
||||
@ -53,19 +54,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<TFCond_Taunting>(ent))
|
||||
return false;
|
||||
|
||||
// If settings allow, dont target cloaked players
|
||||
if (legit && IsPlayerInvisible(ent))
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "common.hpp"
|
||||
#include <hacks/AutoSticky.hpp>
|
||||
#include <PlayerTools.hpp>
|
||||
|
||||
namespace hacks::tf::autosticky
|
||||
{
|
||||
@ -58,8 +59,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())
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include <hacks/ESP.hpp>
|
||||
#include <glez/draw.hpp>
|
||||
#include <online/Online.hpp>
|
||||
#include <PlayerTools.hpp>
|
||||
#include "common.hpp"
|
||||
|
||||
namespace hacks::shared::esp
|
||||
@ -146,6 +148,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_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");
|
||||
|
||||
// Unknown
|
||||
@ -1153,10 +1160,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
|
||||
@ -1168,6 +1177,23 @@ 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_groups)
|
||||
for (auto& s: data->shown_groups)
|
||||
AddEntityString(ent, s, colors::orange);
|
||||
if (online_software && data->has_software)
|
||||
{
|
||||
if (data->is_using_friendly_software)
|
||||
AddEntityString(ent, "Software: " + data->software_name);
|
||||
else
|
||||
AddEntityString(ent, "Software: " + data->software_name, colors::red);
|
||||
}
|
||||
}
|
||||
|
||||
// Powerup handling
|
||||
if (powerup_esp)
|
||||
{
|
||||
@ -1177,8 +1203,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
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <hacks/Trigger.hpp>
|
||||
#include "common.hpp"
|
||||
#include <hacks/Backtrack.hpp>
|
||||
#include <PlayerTools.hpp>
|
||||
|
||||
namespace hacks::shared::triggerbot
|
||||
{
|
||||
@ -272,6 +273,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
|
||||
@ -291,9 +296,6 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// If settings allow, ignore taunting players
|
||||
if (ignore_taunting && HasCondition<TFCond_Taunting>(entity))
|
||||
return false;
|
||||
// Dont target invulnerable players, ex: uber, bonk
|
||||
if (IsPlayerInvulnerable(entity))
|
||||
return false;
|
||||
@ -307,17 +309,6 @@ bool IsTargetStateGood(CachedEntity *entity)
|
||||
HasCondition<TFCond_UberBulletResist>(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))
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <hacks/hacklist.hpp>
|
||||
#include <online/Online.hpp>
|
||||
#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))
|
||||
|
2
src/online/CMakeLists.txt
Normal file
2
src/online/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
target_sources(cathook PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Online.cpp")
|
289
src/online/Online.cpp
Normal file
289
src/online/Online.cpp
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
Created on 23.06.18.
|
||||
*/
|
||||
|
||||
#include <online/Online.hpp>
|
||||
#include <core/cvwrapper.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <optional>
|
||||
#include <timer.hpp>
|
||||
#include <sstream>
|
||||
|
||||
#undef null
|
||||
|
||||
#include <co/OnlineService.hpp>
|
||||
#include <fstream>
|
||||
#include <init.hpp>
|
||||
#include <thread>
|
||||
|
||||
namespace online
|
||||
{
|
||||
|
||||
void saveApiKeyAndHost(std::string host);
|
||||
void claimSteamId();
|
||||
|
||||
static co::OnlineService cathookOnlineService{};
|
||||
static std::unordered_map<unsigned, std::optional<user_data>> data{};
|
||||
static std::unordered_map<unsigned, bool> 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() != 3)
|
||||
{
|
||||
logging::Info("\nUsage: online_login <API_KEY> \"<IP:PORT>\"\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, host](co::ApiCallResult result, std::optional<co::logged_in_user> me) {
|
||||
if (result == co::ApiCallResult::OK)
|
||||
{
|
||||
logging::Info("[CO] Successfully logged in. Welcome, %s", me->username.c_str());
|
||||
api_key = key;
|
||||
saveApiKeyAndHost(host);
|
||||
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;
|
||||
});
|
||||
|
||||
// INTERNAL METHODS
|
||||
|
||||
void claimSteamId()
|
||||
{
|
||||
auto id = g_ISteamUser->GetSteamID();
|
||||
logging::Info("[CO] Claiming SteamID %u", id.GetAccountID());
|
||||
try {
|
||||
cathookOnlineService.gameStartup(id.GetAccountID());
|
||||
} catch (std::exception& ex) {
|
||||
logging::Info("[CO] Exception: %s", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool tryLoadApiKeyAndHost()
|
||||
{
|
||||
std::ifstream keyfile(DATA_PATH "/api_key", std::ios::in);
|
||||
if (keyfile)
|
||||
{
|
||||
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 saveApiKeyAndHost(std::string host)
|
||||
{
|
||||
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' << host << '\n';
|
||||
}
|
||||
|
||||
void queueUserForIdentification(unsigned steamId)
|
||||
{
|
||||
|
||||
identify_queue[steamId] = false;
|
||||
identify_timer.update();
|
||||
identify_stale = true;
|
||||
}
|
||||
|
||||
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.groups)
|
||||
{
|
||||
if (i.display_name.has_value())
|
||||
udata.shown_groups.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
|
||||
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<unsigned> 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)
|
||||
{
|
||||
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()
|
||||
{
|
||||
std::vector<unsigned> 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);
|
||||
}
|
||||
}
|
||||
logging::Info("[CO] Sending identify request for %u players", steamIds.size());
|
||||
try {
|
||||
cathookOnlineService.userIdentify(steamIds, (std::function<void(co::ApiCallResult, std::optional<co::identified_user_group>)>)[steamIds](co::ApiCallResult result, std::optional<co::identified_user_group> 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;
|
||||
}
|
||||
});
|
||||
} catch (std::exception& ex) {
|
||||
logging::Info("[CO] Exception: %s", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
InitRoutine init([]() {
|
||||
cathookOnlineService.setErrorHandler((std::function<void(std::string)>)[](std::string error) {
|
||||
logging::Info("[CO] Error: %s", error.c_str());
|
||||
});
|
||||
if (tryLoadApiKeyAndHost())
|
||||
{
|
||||
logging::Info("[CO] API key loaded successfully");
|
||||
try {
|
||||
cathookOnlineService.login(api_key, [](co::ApiCallResult result, std::optional<co::logged_in_user> 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());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// EXTERNAL METHODS
|
||||
|
||||
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) && !identify_queue.empty())
|
||||
{
|
||||
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())
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
@ -5,6 +5,8 @@
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#include <online/Online.hpp>
|
||||
#include <PlayerTools.hpp>
|
||||
#include "common.hpp"
|
||||
|
||||
static CatVar user_red_blue(CV_INT, "esp_color_red_b", "0", "Red Team: Blue",
|
||||
@ -130,9 +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;
|
||||
|
||||
auto o = player_tools::forceEspColor(ent);
|
||||
if (o.has_value())
|
||||
return *o;
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,3 +147,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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user