diff --git a/src/hacks/Walkbot.cpp b/src/hacks/Walkbot.cpp index ca08b83b..f857f202 100644 --- a/src/hacks/Walkbot.cpp +++ b/src/hacks/Walkbot.cpp @@ -269,8 +269,8 @@ bool Load(std::string filename) { { DIR* walkbot_dir = opendir(DATA_PATH "/walkbot"); if (!walkbot_dir) { - logging::Info("Walkbot directory doesn't exist, creating one!"); - mkdir(DATA_PATH "/walkbot", S_IRWXU | S_IRWXG); + logging::Info("Walkbot directory doesn't exist!"); + return false; } else closedir(walkbot_dir); } std::string path = format(DATA_PATH "/walkbot/", GetLevelName()); diff --git a/src/hitrate.cpp b/src/hitrate.cpp new file mode 100644 index 00000000..a3d2db39 --- /dev/null +++ b/src/hitrate.cpp @@ -0,0 +1,91 @@ +/* + * hitrate.cpp + * + * Created on: Aug 16, 2017 + * Author: nullifiedcat + */ + +#include "common.h" +#include "init.hpp" + +namespace hitrate { + +int lastweapon { 0 }; +int lastammo { 0 }; + +int count_shots { 0 }; +int count_hits { 0 }; +int count_hits_head { 0 }; + +std::vector> shots {}; + +void OnShot() { + ++count_shots; +} + +void OnHit(bool crit) { + count_hits++; + if (crit) { + count_hits_head++; + } +} + +CatCommand debug_hitrate("debug_hitrate", "Debug hitrate", []() { + int p1 = 0; + int p2 = 0; + if (count_shots) { + p1 = float(count_hits) / float(count_shots) * 100.0f; + } + if (count_hits) { + p1 = float(count_hits_head) / float(count_hits) * 100.0f; + } + logging::Info("%d / %d (%d%%)", count_hits, count_shots, p1); + logging::Info("%d / %d (%d%%)", count_hits_head, count_hits, p2); +}); + +CatCommand debug_ammo("debug_ammo", "Debug ammo", []() { + for (int i = 0; i < 4; i++) { + logging::Info("%d %d", i, CE_INT(LOCAL_E, netvar.m_iAmmo + i * 4)); + } +}); + +void Update() { + CachedEntity* weapon = LOCAL_W; + if (CE_GOOD(weapon)) { + if (LOCAL_W->m_iClassID == CL_CLASS(CTFSniperRifle) || LOCAL_W->m_iClassID == CL_CLASS(CTFSniperRifleDecap)) { + // ONLY tracks primary ammo + int ammo = CE_INT(LOCAL_E, netvar.m_iAmmo + 4); + if (lastweapon) { + if (ammo < lastammo) { + OnShot(); + } + } + lastweapon = weapon->m_IDX; + lastammo = ammo; + } + } else { + lastweapon = 0; + } +} + +class HurtListener : public IGameEventListener { +public: + virtual void FireGameEvent(KeyValues* event) { + if (strcmp("player_hurt", event->GetName())) return; + if (g_IEngine->GetPlayerForUserID(event->GetInt("attacker")) == g_IEngine->GetLocalPlayer()) { + if (CE_GOOD(LOCAL_W) && (LOCAL_W->m_iClassID == CL_CLASS(CTFSniperRifle) || LOCAL_W->m_iClassID == CL_CLASS(CTFSniperRifleDecap))) + OnHit(event->GetBool("crit")); + } + } +}; + +HurtListener& listener() { + static HurtListener l {}; + return l; +} + +InitRoutine init([]() { + g_IGameEventManager->AddListener(&listener(), false); +}); + +} diff --git a/src/hitrate.hpp b/src/hitrate.hpp new file mode 100644 index 00000000..f7a095e5 --- /dev/null +++ b/src/hitrate.hpp @@ -0,0 +1,18 @@ +/* + * hitrate.hpp + * + * Created on: Aug 16, 2017 + * Author: nullifiedcat + */ + +#pragma once + +namespace hitrate { + +extern int count_shots; +extern int count_hits; +extern int count_hits_head; + +void Update(); + +} diff --git a/src/hooks/others.cpp b/src/hooks/others.cpp index 08230f27..397a5d09 100644 --- a/src/hooks/others.cpp +++ b/src/hooks/others.cpp @@ -10,6 +10,7 @@ #include "../chatlog.hpp" #include "../hack.h" #include "ucccccp.hpp" +#include "../hitrate.hpp" #include "hookedmethods.h" #if ENABLE_VISUALS == 1 @@ -377,6 +378,8 @@ void FireGameEvent_hook(void* _this, IGameEvent* event) { original(_this, event); } +static CatVar hitrate_check(CV_SWITCH, "hitrate", "0", "Monitor hitrate"); + void FrameStageNotify_hook(void* _this, int stage) { static IClientEntity *ent; @@ -394,6 +397,9 @@ void FrameStageNotify_hook(void* _this, int stage) { if (stage == FRAME_NET_UPDATE_POSTDATAUPDATE_START) { angles::Update(); hacks::shared::anticheat::CreateMove(); + if (hitrate_check) { + hitrate::Update(); + } } if (resolver && cathook && !g_Settings.bInvalid && stage == FRAME_NET_UPDATE_POSTDATAUPDATE_START) { PROF_SECTION(FSN_resolver); diff --git a/src/ipc.cpp b/src/ipc.cpp index a7e533b2..8a2bfcbb 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -10,6 +10,7 @@ #include "common.h" #include "hack.h" +#include "hitrate.hpp" #ifdef IPC_ENABLED @@ -171,6 +172,9 @@ void UpdateServerAddress(bool shutdown) { 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; if (data.connected) { IClientEntity* player = g_IEntityList->GetClientEntity(g_IEngine->GetLocalPlayer()); if (player) { diff --git a/src/ipc.h b/src/ipc.h index 1c9c8702..6a5dc326 100644 --- a/src/ipc.h +++ b/src/ipc.h @@ -67,6 +67,9 @@ struct user_data_s { time_t ts_injected; time_t ts_connected; time_t ts_disconnected; + int shots; + int hits; + int headshots; }; using peer_t = cat_ipc::Peer; diff --git a/src/netvars.cpp b/src/netvars.cpp index 8fdbe59f..43b09283 100644 --- a/src/netvars.cpp +++ b/src/netvars.cpp @@ -22,6 +22,7 @@ void NetVars::Init() { this->vVelocity = gNetvars.get_offset("DT_BasePlayer", "localdata", "m_vecVelocity[0]"); this->movetype = gNetvars.get_offset("DT_BaseEntity", "movetype"); this->m_iAmmo = gNetvars.get_offset("DT_BasePlayer", "localdata", "m_iAmmo"); + this->m_iClip1 = gNetvars.get_offset("DT_BaseCombatWeapon", "LocalWeaponData", "m_iClip1"); this->m_Collision = gNetvars.get_offset("DT_BaseEntity", "m_Collision"); m_flSimulationTime = gNetvars.get_offset("DT_BaseEntity", "m_flSimulationTime"); IF_GAME (IsTF2()) { diff --git a/src/netvars.h b/src/netvars.h index c6684afc..c294d177 100644 --- a/src/netvars.h +++ b/src/netvars.h @@ -75,6 +75,7 @@ public: offset_t iNextMeleeCrit; offset_t flNextPrimaryAttack; offset_t iNextThinkTick; + offset_t m_iClip1; //offset_t flReloadPriorNextFire; //offset_t flObservedCritChance; offset_t nTickBase;