commit
9d3925c48f
@ -100,6 +100,7 @@
|
||||
#include "tfmm.hpp"
|
||||
#include "hooks/hookedmethods.hpp"
|
||||
#include "classinfo/classinfo.hpp"
|
||||
#include "votelogger.hpp"
|
||||
#include "crits.hpp"
|
||||
#include "textmode.hpp"
|
||||
#include "backpacktf.hpp"
|
||||
|
22
include/hacks/CatBot.hpp
Normal file
22
include/hacks/CatBot.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* CatBot.hpp
|
||||
*
|
||||
* Created on: Dec 30, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace hacks { namespace shared { namespace catbot {
|
||||
|
||||
bool is_a_catbot(unsigned steamID);
|
||||
bool should_ignore_player(CachedEntity *player);
|
||||
void update_ipc_data(ipc::user_data_s& data);
|
||||
void update();
|
||||
void init();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -42,5 +42,6 @@
|
||||
#include "FollowBot.hpp"
|
||||
#include "Announcer.hpp"
|
||||
#include "Killstreak.hpp"
|
||||
#include "CatBot.hpp"
|
||||
|
||||
#endif /* HACKS_HACKLIST_HPP_ */
|
||||
|
@ -48,34 +48,63 @@ struct server_data_s
|
||||
struct user_data_s
|
||||
{
|
||||
char name[32];
|
||||
char server[22];
|
||||
unsigned friendid;
|
||||
|
||||
bool connected;
|
||||
bool good;
|
||||
int health;
|
||||
int health_max;
|
||||
char life_state;
|
||||
int team;
|
||||
int clazz;
|
||||
int score;
|
||||
int last_score;
|
||||
int total_score;
|
||||
|
||||
time_t heartbeat;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
time_t ts_injected;
|
||||
time_t ts_connected;
|
||||
time_t ts_disconnected;
|
||||
int shots;
|
||||
int hits;
|
||||
int headshots;
|
||||
|
||||
struct accumulated_t
|
||||
{
|
||||
int kills; // TODO
|
||||
int deaths; // TODO
|
||||
int score;
|
||||
|
||||
int shots;
|
||||
int hits;
|
||||
int headshots;
|
||||
} accumulated;
|
||||
|
||||
struct
|
||||
{
|
||||
bool good;
|
||||
|
||||
int kills; // TODO
|
||||
int deaths; // TODO
|
||||
int score;
|
||||
|
||||
int shots; // TODO
|
||||
int hits; // TODO
|
||||
int headshots; // TODO
|
||||
|
||||
int team;
|
||||
int role; // class
|
||||
char life_state;
|
||||
int health;
|
||||
int health_max;
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
int player_count;
|
||||
int bot_count;
|
||||
|
||||
char server[24];
|
||||
char mapname[32];
|
||||
} ingame;
|
||||
};
|
||||
|
||||
using peer_t = cat_ipc::Peer<server_data_s, user_data_s>;
|
||||
|
||||
extern peer_t *peer;
|
||||
|
||||
void update_mapname();
|
||||
|
||||
void Heartbeat();
|
||||
void UpdateTemporaryData();
|
||||
void UpdateServerAddress(bool shutdown = false);
|
||||
|
19
include/votelogger.hpp
Normal file
19
include/votelogger.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* votelogger.hpp
|
||||
*
|
||||
* Created on: Dec 31, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class bf_read;
|
||||
|
||||
namespace votelogger
|
||||
{
|
||||
|
||||
void user_message(bf_read& buffer, int type);
|
||||
|
||||
}
|
||||
|
||||
|
@ -343,6 +343,7 @@ g_pGUI->Setup();
|
||||
hacks::shared::killsay::Init();
|
||||
hacks::shared::announcer::init();
|
||||
hacks::tf2::killstreak::init();
|
||||
hacks::shared::catbot::init();
|
||||
logging::Info("Hooked!");
|
||||
velocity::Init();
|
||||
playerlist::Load();
|
||||
|
@ -548,6 +548,8 @@ bool IsTargetStateGood(CachedEntity *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];
|
||||
|
240
src/hacks/CatBot.cpp
Normal file
240
src/hacks/CatBot.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* CatBot.cpp
|
||||
*
|
||||
* Created on: Dec 30, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#include "common.hpp"
|
||||
#include "hack.hpp"
|
||||
|
||||
namespace hacks { namespace shared { namespace catbot {
|
||||
|
||||
static CatVar enabled(CV_SWITCH, "cbu", "0", "CatBot Utils");
|
||||
static CatVar abandon_if_bots_gte(CV_INT, "cbu_abandon_if_bots_gte", "0", "Abandon if bots >=");
|
||||
static CatVar abandon_if_ipc_bots_gte(CV_INT, "cbu_abandon_if_ipc_bots_gte", "0", "Abandon if IPC bots >=");
|
||||
static CatVar abandon_if_humans_lte(CV_INT, "cbu_abandon_if_humans_lte", "0", "Abandon if humans <=");
|
||||
static CatVar abandon_if_players_lte(CV_INT, "cbu_abandon_if_players_lte", "0", "Abandon if players <=");
|
||||
static CatVar mark_human_threshold(CV_INT, "cbu_mark_human_threshold", "2", "Mark human after N kills");
|
||||
static CatVar random_votekicks(CV_SWITCH, "cbu_random_votekicks", "0", "Randomly initiate votekicks");
|
||||
|
||||
struct catbot_user_state
|
||||
{
|
||||
int treacherous_kills{ 0 };
|
||||
};
|
||||
|
||||
std::unordered_map<unsigned, catbot_user_state> human_detecting_map{};
|
||||
|
||||
bool is_a_catbot(unsigned steamID)
|
||||
{
|
||||
auto it = human_detecting_map.find(steamID);
|
||||
if (it == human_detecting_map.end())
|
||||
return false;
|
||||
|
||||
//if (!(*it).second.has_bot_name)
|
||||
// return false;
|
||||
|
||||
if ((*it).second.treacherous_kills <= int(mark_human_threshold))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void on_killed_by(int userid)
|
||||
{
|
||||
CachedEntity *player = ENTITY(g_IEngine->GetPlayerForUserID(userid));
|
||||
|
||||
if (CE_BAD(player))
|
||||
return;
|
||||
|
||||
unsigned steamID = player->player_info.friendsID;
|
||||
|
||||
if (human_detecting_map.find(steamID) == human_detecting_map.end())
|
||||
return;
|
||||
|
||||
//if (human_detecting_map[steamID].has_bot_name)
|
||||
human_detecting_map[steamID].treacherous_kills++;
|
||||
logging::Info("Treacherous kill #%d: %s [U:1:%u]", human_detecting_map[steamID].treacherous_kills, player->player_info.name, player->player_info.friendsID);
|
||||
}
|
||||
|
||||
void do_random_votekick()
|
||||
{
|
||||
std::vector<int> targets;
|
||||
for (int i = 1; i <= g_GlobalVars->maxClients; ++i)
|
||||
{
|
||||
player_info_s info;
|
||||
if (!g_IEngine->GetPlayerInfo(i, &info))
|
||||
continue;
|
||||
|
||||
if (g_pPlayerResource->GetTeam(i) != g_pLocalPlayer->team)
|
||||
continue;
|
||||
|
||||
if (is_a_catbot(info.friendsID))
|
||||
continue;
|
||||
|
||||
targets.push_back(info.userID);
|
||||
}
|
||||
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
int target = targets[rand() % targets.size()];
|
||||
player_info_s info;
|
||||
if (!g_IEngine->GetPlayerInfo(g_IEngine->GetPlayerForUserID(target), &info))
|
||||
return;
|
||||
hack::ExecuteCommand("callvote kick " + std::to_string(target) + " cheating");
|
||||
}
|
||||
|
||||
void update_catbot_list()
|
||||
{
|
||||
for (int i = 1; i < g_GlobalVars->maxClients; ++i)
|
||||
{
|
||||
player_info_s info;
|
||||
if (!g_IEngine->GetPlayerInfo(i, &info))
|
||||
continue;
|
||||
|
||||
info.name[31] = 0;
|
||||
if (strcasestr(info.name, "cat-bot") ||
|
||||
strcasestr(info.name, "just disable vac tf"))
|
||||
{
|
||||
if (human_detecting_map.find(info.friendsID) == human_detecting_map.end())
|
||||
{
|
||||
logging::Info("Found bot %s [U:1:%u]", info.name, info.friendsID);
|
||||
human_detecting_map.insert(std::make_pair(info.friendsID, catbot_user_state{ 0 }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CatBotEventListener : public IGameEventListener2
|
||||
{
|
||||
virtual void FireGameEvent(IGameEvent *event)
|
||||
{
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
int killer_id = g_IEngine->GetPlayerForUserID(event->GetInt("attacker"));
|
||||
int victim_id = g_IEngine->GetPlayerForUserID(event->GetInt("userid"));
|
||||
|
||||
if (victim_id == g_IEngine->GetLocalPlayer())
|
||||
{
|
||||
on_killed_by(killer_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CatBotEventListener &listener()
|
||||
{
|
||||
static CatBotEventListener object{};
|
||||
return object;
|
||||
}
|
||||
|
||||
Timer timer_votekicks{};
|
||||
Timer timer_catbot_list{};
|
||||
Timer timer_abandon{};
|
||||
|
||||
int count_bots{ 0 };
|
||||
|
||||
bool should_ignore_player(CachedEntity *player)
|
||||
{
|
||||
if (CE_BAD(player))
|
||||
return false;
|
||||
|
||||
return is_a_catbot(player->player_info.friendsID);
|
||||
}
|
||||
|
||||
void update_ipc_data(ipc::user_data_s& data)
|
||||
{
|
||||
data.ingame.bot_count = count_bots;
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
if (g_Settings.bInvalid)
|
||||
return;
|
||||
|
||||
if (CE_BAD(LOCAL_E))
|
||||
return;
|
||||
|
||||
if (random_votekicks && timer_votekicks.test_and_set(5000))
|
||||
do_random_votekick();
|
||||
if (timer_catbot_list.test_and_set(3000))
|
||||
update_catbot_list();
|
||||
if (timer_abandon.test_and_set(2000))
|
||||
{
|
||||
count_bots = 0;
|
||||
int count_ipc = 0;
|
||||
int count_total = 0;
|
||||
|
||||
for (int i = 1; i <= g_GlobalVars->maxClients; ++i)
|
||||
{
|
||||
if (g_IEntityList->GetClientEntity(i))
|
||||
++count_total;
|
||||
else
|
||||
continue;
|
||||
|
||||
player_info_s info;
|
||||
if (!g_IEngine->GetPlayerInfo(i, &info))
|
||||
continue;
|
||||
|
||||
if (is_a_catbot(info.friendsID))
|
||||
++count_bots;
|
||||
|
||||
if (playerlist::AccessData(info.friendsID).state == playerlist::k_EState::IPC)
|
||||
++count_ipc;
|
||||
}
|
||||
|
||||
if (abandon_if_bots_gte)
|
||||
{
|
||||
if (count_bots >= int(abandon_if_bots_gte))
|
||||
{
|
||||
logging::Info("Abandoning because there are %d bots in game, and abandon_if_bots_gte is %d.", count_bots, int(abandon_if_bots_gte));
|
||||
tfmm::abandon();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (abandon_if_ipc_bots_gte)
|
||||
{
|
||||
if (count_ipc >= int(abandon_if_ipc_bots_gte))
|
||||
{
|
||||
logging::Info("Abandoning because there are %d local players in game, and abandon_if_ipc_bots_gte is %d.", count_ipc, int(abandon_if_ipc_bots_gte));
|
||||
tfmm::abandon();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (abandon_if_humans_lte)
|
||||
{
|
||||
if (count_total - count_bots <= int(abandon_if_humans_lte))
|
||||
{
|
||||
logging::Info("Abandoning because there are %d non-bots in game, and abandon_if_humans_lte is %d.", count_total - count_bots, int(abandon_if_ipc_bots_gte));
|
||||
tfmm::abandon();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (abandon_if_players_lte)
|
||||
{
|
||||
if (count_total <= int(abandon_if_humans_lte))
|
||||
{
|
||||
logging::Info("Abandoning because there are %d total players in game, and abandon_if_humans_lte is %d.", count_total, int(abandon_if_humans_lte));
|
||||
tfmm::abandon();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
g_IEventManager2->AddListener(&listener(), "player_death", false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1148,78 +1148,6 @@ void OnLevelInit()
|
||||
}
|
||||
}
|
||||
|
||||
static CatVar wb_abandon_too_many_bots(CV_INT, "wb_population_control", "0",
|
||||
"Abandon if bots >");
|
||||
|
||||
Timer abandon_timer{};
|
||||
|
||||
CatVar wb_abandon_players_leq(CV_SWITCH, "wb_abandon_players_leq", "0", "Leave if non-bot player count <=");
|
||||
|
||||
void check_player_count()
|
||||
{
|
||||
#if ENABLE_IPC
|
||||
if (ipc::peer && wb_abandon_players_leq)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CheckLivingSpace()
|
||||
{
|
||||
#if ENABLE_IPC
|
||||
if (ipc::peer && wb_abandon_too_many_bots)
|
||||
{
|
||||
std::vector<unsigned> players{};
|
||||
for (int j = 1; j < 32; j++)
|
||||
{
|
||||
player_info_s info;
|
||||
if (g_IEngine->GetPlayerInfo(j, &info))
|
||||
{
|
||||
if (info.friendsID)
|
||||
players.push_back(info.friendsID);
|
||||
}
|
||||
}
|
||||
int count = 0;
|
||||
unsigned highest = 0;
|
||||
std::vector<unsigned> botlist{};
|
||||
for (unsigned i = 0; i < cat_ipc::max_peers; i++)
|
||||
{
|
||||
if (!ipc::peer->memory->peer_data[i].free)
|
||||
{
|
||||
for (auto &k : players)
|
||||
{
|
||||
if (ipc::peer->memory->peer_user_data[i].friendid &&
|
||||
k == ipc::peer->memory->peer_user_data[i].friendid)
|
||||
{
|
||||
botlist.push_back(i);
|
||||
count++;
|
||||
highest = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ipc::peer->client_id == highest &&
|
||||
count > int(wb_abandon_too_many_bots))
|
||||
{
|
||||
if (abandon_timer.test_and_set(1000 * 5))
|
||||
{
|
||||
logging::Info("Found %d other bots in-game, abandoning (%u)",
|
||||
count, ipc::peer->client_id);
|
||||
for (auto i : botlist)
|
||||
{
|
||||
logging::Info(
|
||||
"-> Bot %d with ID %u", i,
|
||||
ipc::peer->memory->peer_user_data[i].friendid);
|
||||
}
|
||||
tfmm::abandon();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Timer quit_timer{};
|
||||
|
||||
void Move()
|
||||
@ -1254,14 +1182,10 @@ void Move()
|
||||
{
|
||||
logging::Info("No map file, abandon");
|
||||
tfmm::abandon();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
static Timer livingspace_timer{};
|
||||
if (livingspace_timer.test_and_set(1000 * 2))
|
||||
{
|
||||
CheckLivingSpace();
|
||||
}
|
||||
if (nodes.size() == 0)
|
||||
return;
|
||||
if (force_slot)
|
||||
|
@ -384,7 +384,7 @@ void Shutdown_hook(void *_this, const char *reason)
|
||||
const Shutdown_t original =
|
||||
(Shutdown_t) hooks::netchannel.GetMethod(offsets::Shutdown());
|
||||
logging::Info("Disconnect: %s", reason);
|
||||
if (strstr(reason, "VAC banned"))
|
||||
if (strstr(reason, "banned"))
|
||||
{
|
||||
if (die_if_vac)
|
||||
{
|
||||
@ -393,10 +393,6 @@ void Shutdown_hook(void *_this, const char *reason)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (strstr(reason, "VAC"))
|
||||
{
|
||||
logging::Info("VAC error?");
|
||||
}
|
||||
#if ENABLE_IPC
|
||||
ipc::UpdateServerAddress(true);
|
||||
#endif
|
||||
@ -608,6 +604,7 @@ void FrameStageNotify_hook(void *_this, int stage)
|
||||
#endif
|
||||
if (stage == FRAME_NET_UPDATE_POSTDATAUPDATE_START && !g_Settings.bInvalid)
|
||||
{
|
||||
hacks::shared::catbot::update();
|
||||
angles::Update();
|
||||
hacks::shared::anticheat::CreateMove();
|
||||
if (hitrate_check)
|
||||
@ -670,8 +667,8 @@ void FrameStageNotify_hook(void *_this, int stage)
|
||||
std::lock_guard<std::mutex> guard(hack::command_stack_mutex);
|
||||
while (!hack::command_stack().empty())
|
||||
{
|
||||
logging::Info("executing %s",
|
||||
hack::command_stack().top().c_str());
|
||||
//logging::Info("executing %s",
|
||||
// hack::command_stack().top().c_str());
|
||||
g_IEngine->ClientCmd_Unrestricted(
|
||||
hack::command_stack().top().c_str());
|
||||
hack::command_stack().pop();
|
||||
@ -785,7 +782,16 @@ bool DispatchUserMessage_hook(void *_this, int type, bf_read &buf)
|
||||
if (dispatch_log)
|
||||
{
|
||||
logging::Info("D> %i", type);
|
||||
std::ostringstream str{};
|
||||
while (buf.GetNumBytesLeft())
|
||||
{
|
||||
unsigned char byte = buf.ReadByte();
|
||||
str << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte) << ' ';
|
||||
}
|
||||
logging::Info("MESSAGE %d, DATA = [ %s ]", type, str.str().c_str());
|
||||
buf.Seek(0);
|
||||
}
|
||||
votelogger::user_message(buf, type);
|
||||
return original(_this, type, buf);
|
||||
}
|
||||
|
||||
|
103
src/ipc.cpp
103
src/ipc.cpp
@ -51,10 +51,13 @@ CatCommand connect("ipc_connect", "Connect to IPC server", []() {
|
||||
});
|
||||
hacks::shared::followbot::AddMessageHandlers(peer);
|
||||
user_data_s &data = peer->memory->peer_user_data[peer->client_id];
|
||||
// Preserve total score
|
||||
int o_total_score = data.total_score;
|
||||
|
||||
// Preserve accumulated data
|
||||
ipc::user_data_s::accumulated_t accumulated;
|
||||
memcpy(&accumulated, &data.accumulated, sizeof(accumulated));
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.total_score = o_total_score;
|
||||
memcpy(&data.accumulated, &accumulated, sizeof(accumulated));
|
||||
|
||||
StoreClientData();
|
||||
Heartbeat();
|
||||
}
|
||||
@ -66,21 +69,6 @@ CatCommand connect("ipc_connect", "Connect to IPC server", []() {
|
||||
}
|
||||
|
||||
});
|
||||
CatCommand lobby("ipc_lobby", "Join a lobby", [](const CCommand &args) {
|
||||
std::string input(args.ArgS());
|
||||
std::size_t lobby_id_start = input.find("[L:1:");
|
||||
if (lobby_id_start == std::string::npos)
|
||||
{
|
||||
logging::Info("couldn't find lobby ID!");
|
||||
return;
|
||||
}
|
||||
input = input.substr(lobby_id_start + 5);
|
||||
unsigned long lobby32 = strtoul(input.c_str(), nullptr, 10);
|
||||
unsigned long long lobby64 = ((25559040ull << 32) | lobby32);
|
||||
logging::Info("lobby64 ID: %llu", lobby64);
|
||||
peer->SendMessage(format("connect_lobby ", lobby64).c_str(), 0,
|
||||
ipc::commands::execute_client_cmd, 0, 0);
|
||||
});
|
||||
CatCommand disconnect("ipc_disconnect", "Disconnect from IPC server", []() {
|
||||
if (peer)
|
||||
delete peer;
|
||||
@ -194,50 +182,75 @@ void UpdateServerAddress(bool shutdown)
|
||||
|
||||
user_data_s &data = peer->memory->peer_user_data[peer->client_id];
|
||||
data.friendid = g_ISteamUser->GetSteamID().GetAccountID();
|
||||
strncpy(data.server, s_addr, sizeof(data.server));
|
||||
strncpy(data.ingame.server, s_addr, sizeof(data.ingame.server));
|
||||
}
|
||||
|
||||
void update_mapname()
|
||||
{
|
||||
if (not peer)
|
||||
return;
|
||||
|
||||
user_data_s &data = peer->memory->peer_user_data[peer->client_id];
|
||||
strncpy(data.ingame.mapname, GetLevelName().c_str(), sizeof(data.ingame.mapname));
|
||||
}
|
||||
|
||||
void UpdateTemporaryData()
|
||||
{
|
||||
user_data_s &data = peer->memory->peer_user_data[peer->client_id];
|
||||
|
||||
data.connected = g_IEngine->IsInGame();
|
||||
data.shots = hitrate::count_shots;
|
||||
data.hits = hitrate::count_hits;
|
||||
data.headshots = hitrate::count_hits_head;
|
||||
// TODO kills, deaths
|
||||
data.accumulated.shots = hitrate::count_shots;
|
||||
data.accumulated.hits = hitrate::count_hits;
|
||||
data.accumulated.headshots = hitrate::count_hits_head;
|
||||
|
||||
if (data.connected)
|
||||
{
|
||||
IClientEntity *player =
|
||||
g_IEntityList->GetClientEntity(g_IEngine->GetLocalPlayer());
|
||||
if (player)
|
||||
{
|
||||
data.good = true;
|
||||
data.health = NET_INT(player, netvar.iHealth);
|
||||
data.health_max = g_pPlayerResource->GetMaxHealth(LOCAL_E);
|
||||
data.clazz = g_pPlayerResource->GetClass(LOCAL_E);
|
||||
data.life_state = NET_BYTE(player, netvar.iLifeState);
|
||||
data.score =
|
||||
data.ingame.good = true;
|
||||
// TODO kills, deaths, shots, hits, headshots
|
||||
|
||||
int score_saved = data.ingame.score;
|
||||
|
||||
data.ingame.score =
|
||||
g_pPlayerResource->GetScore(g_IEngine->GetLocalPlayer());
|
||||
if (data.last_score != data.score)
|
||||
{
|
||||
if (data.last_score > data.score)
|
||||
{
|
||||
data.total_score += data.score;
|
||||
}
|
||||
else
|
||||
{
|
||||
data.total_score += (data.score - data.last_score);
|
||||
}
|
||||
data.last_score = data.score;
|
||||
}
|
||||
data.team = g_pPlayerResource->GetTeam(g_IEngine->GetLocalPlayer());
|
||||
data.x = g_pLocalPlayer->v_Origin.x;
|
||||
data.y = g_pLocalPlayer->v_Origin.y;
|
||||
data.z = g_pLocalPlayer->v_Origin.z;
|
||||
data.ingame.team = g_pPlayerResource->GetTeam(g_IEngine->GetLocalPlayer());
|
||||
data.ingame.role = g_pPlayerResource->GetClass(LOCAL_E);
|
||||
data.ingame.life_state = NET_BYTE(player, netvar.iLifeState);
|
||||
data.ingame.health = NET_INT(player, netvar.iHealth);
|
||||
data.ingame.health_max = g_pPlayerResource->GetMaxHealth(LOCAL_E);
|
||||
|
||||
if (score_saved > data.ingame.score)
|
||||
score_saved = 0;
|
||||
|
||||
data.accumulated.score += data.ingame.score - score_saved;
|
||||
|
||||
data.ingame.x = g_pLocalPlayer->v_Origin.x;
|
||||
data.ingame.y = g_pLocalPlayer->v_Origin.y;
|
||||
data.ingame.z = g_pLocalPlayer->v_Origin.z;
|
||||
|
||||
int players = 0;
|
||||
|
||||
for (int i = 1; i <= g_GlobalVars->maxClients; ++i)
|
||||
{
|
||||
if (g_IEntityList->GetClientEntity(i))
|
||||
++players;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
data.ingame.player_count = players;
|
||||
hacks::shared::catbot::update_ipc_data(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.good = false;
|
||||
data.ingame.good = false;
|
||||
}
|
||||
if (g_IEngine->GetLevelName())
|
||||
update_mapname();
|
||||
}
|
||||
}
|
||||
|
||||
|
59
src/votelogger.cpp
Normal file
59
src/votelogger.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* votelogger.cpp
|
||||
*
|
||||
* Created on: Dec 31, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace votelogger
|
||||
{
|
||||
|
||||
static CatVar enabled(CV_SWITCH, "votelog", "0", "Log votes");
|
||||
|
||||
void user_message(bf_read& buffer, int type)
|
||||
{
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 45:
|
||||
// Call Vote Failed
|
||||
break;
|
||||
case 46: {
|
||||
unsigned char caller = buffer.ReadByte();
|
||||
// unknown
|
||||
buffer.ReadByte();
|
||||
char reason[64];
|
||||
char name[64];
|
||||
buffer.ReadString(reason, 64, false, nullptr);
|
||||
buffer.ReadString(name, 64, false, nullptr);
|
||||
unsigned char eid = buffer.ReadByte();
|
||||
buffer.Seek(0);
|
||||
eid >>= 1;
|
||||
|
||||
unsigned steamID = 0;
|
||||
player_info_s info;
|
||||
if (g_IEngine->GetPlayerInfo(eid, &info))
|
||||
{
|
||||
steamID = info.friendsID;
|
||||
}
|
||||
|
||||
logging::Info("Vote called to kick %s [U:1:%u] for %s", name, steamID, reason);
|
||||
break;
|
||||
}
|
||||
case 47:
|
||||
logging::Info("Vote passed");
|
||||
break;
|
||||
case 48:
|
||||
logging::Info("Vote failed");
|
||||
break;
|
||||
case 49:
|
||||
logging::Info("VoteSetup?");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user