#include "TriggerBot.hpp"
#include "../../Entities/Entities.hpp"
#include "../../Interface/Interface.hpp"
#include "../Math/Math.hpp"
#include "../../Globals.hpp"
#include <chrono>
#include <thread>
#include <Windows.h>
namespace TriggerBot {
bool Running = false;
std::thread Thread;
bool IsKeyDown(int key) {
return (GetAsyncKeyState(key) & 0x8000) != 0;
}
struct aim_point_t {
Vector3 m_point;
int m_hitbox;
bool m_center = false;
aim_point_t(Vector3 point, int hitbox, bool center = false) : m_point(point), m_hitbox(hitbox), m_center(center) {}
};
struct aim_target_t {
uintptr_t m_pawn = 0;
std::unique_ptr<aim_point_t> m_best_point = nullptr;
aim_target_t() = default;
aim_target_t(uintptr_t pawn) : m_pawn(pawn) {}
};
std::unordered_map<int, aim_target_t> m_aim_targets;
aim_target_t* m_best_target = nullptr;
std::vector<int> m_hitboxes;
bool can_shoot(uintptr_t local_pawn, uintptr_t weapon) {
if (!local_pawn || !weapon) return false;
const int clip = *reinterpret_cast<int*>(weapon + Offsets::m_iClip1);
const float next_attack = *reinterpret_cast<float*>(weapon + Offsets::m_flNextPrimaryAttack);
const float current_time = *reinterpret_cast<float*>(CEntities::Client + Offsets::m_flGlobalVarsCurtime);
return (clip > 0) && (next_attack <= current_time);
}
bool is_visible(uintptr_t local_pawn, uintptr_t target) {
if (!CEntities::Client || !local_pawn || !target) return false;
int crosshairId = *reinterpret_cast<int*>(CEntities::Client + Offsets::m_iIDEntIndex);
if (crosshairId <= 0 || crosshairId > 64) return false;
uintptr_t targetPawn = Entities->GetPawnFromIndex(crosshairId);
return targetPawn == target;
}
aim_point_t select_best_point(uintptr_t target, float& best_damage) {
aim_point_t best_point(Vector3(0.f, 0.f, 0.f), -1);
best_damage = 0.f;
if (!target || !CEntities::Client) return best_point;
uintptr_t local_pawn = *reinterpret_cast<uintptr_t*>(CEntities::Client + Offsets::LocalPlayer);
if (!local_pawn) return best_point;
for (const auto& hitbox : m_hitboxes) {
Vector3 point;
switch (hitbox) {
case HITBOX_HEAD: point = *reinterpret_cast<Vector3*>(target + Offsets::m_vecOrigin) + Vector3(0.f, 0.f, 70.f); break;
case HITBOX_CHEST: point = *reinterpret_cast<Vector3*>(target + Offsets::m_vecOrigin) + Vector3(0.f, 0.f, 50.f); break;
case HITBOX_LOWER_CHEST: point = *reinterpret_cast<Vector3*>(target + Offsets::m_vecOrigin) + Vector3(0.f, 0.f, 40.f); break;
case HITBOX_UPPER_CHEST: point = *reinterpret_cast<Vector3*>(target + Offsets::m_vecOrigin) + Vector3(0.f, 0.f, 60.f); break;
case HITBOX_PELVIS: point = *reinterpret_cast<Vector3*>(target + Offsets::m_vecOrigin) + Vector3(0.f, 0.f, 30.f); break;
case HITBOX_STOMACH: point = *reinterpret_cast<Vector3*>(target + Offsets::m_vecOrigin) + Vector3(0.f, 0.f, 35.f); break;
default: continue;
}
if (!is_visible(local_pawn, target)) continue;
float damage = (hitbox == HITBOX_HEAD) ? 100.0f : 50.0f; // Упрощенный расчет урона
if (damage > best_damage) {
best_damage = damage;
best_point = aim_point_t(point, hitbox, true);
}
}
return best_point;
}
void store_hitboxes() {
m_hitboxes.clear();
if (Globals::TriggerBot.Hitboxes[0]) m_hitboxes.emplace_back(HITBOX_HEAD);
if (Globals::TriggerBot.Hitboxes[1]) {
m_hitboxes.emplace_back(HITBOX_CHEST);
m_hitboxes.emplace_back(HITBOX_LOWER_CHEST);
m_hitboxes.emplace_back(HITBOX_UPPER_CHEST);
}
if (Globals::TriggerBot.Hitboxes[2]) {
m_hitboxes.emplace_back(HITBOX_PELVIS);
m_hitboxes.emplace_back(HITBOX_STOMACH);
}
}
void find_targets() {
m_aim_targets.clear();
if (!CEntities::Client) return;
uintptr_t local_pawn = *reinterpret_cast<uintptr_t*>(CEntities::Client + Offsets::LocalPlayer);
if (!local_pawn) return;
int local_team = *reinterpret_cast<int*>(local_pawn + Offsets::Team);
auto entities = Entities->GetEntities();
for (const auto& entity : entities) {
if (!entity.IsValid() || !entity.Base) continue;
if (*reinterpret_cast<int*>(entity.Base + Offsets::Team) == local_team) continue;
if (*reinterpret_cast<int*>(entity.Base + Offsets::Health) <= 0) continue;
int handle = entity.Index;
m_aim_targets.emplace(handle, aim_target_t(entity.Base));
}
}
aim_target_t* select_target() {
aim_target_t* best_target = nullptr;
float best_damage = 0.f;
for (auto& [handle, target] : m_aim_targets) {
if (!target.m_pawn) continue;
float damage = 0.f;
aim_point_t point = select_best_point(target.m_pawn, damage);
if (point.m_hitbox == -1 || damage < Globals::TriggerBot.MinimumDamage) continue;
target.m_best_point = std::make_unique<aim_point_t>(point);
if (damage > best_damage) {
best_damage = damage;
best_target = ⌖
}
}
return best_target;
}
void Loop() {
static auto lastShotTime = std::chrono::steady_clock::now();
while (Running) {
try {
if (!Globals::TriggerBot.Enabled || !CEntities::Client) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
continue;
}
if (Globals::TriggerBot.OnKey && !IsKeyDown(Globals::TriggerBot.Key)) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
uintptr_t local_pawn = *reinterpret_cast<uintptr_t*>(CEntities::Client + Offsets::LocalPlayer);
if (!local_pawn) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
uintptr_t weapon = *reinterpret_cast<uintptr_t*>(local_pawn + Offsets::m_hActiveWeapon);
if (!weapon || !can_shoot(local_pawn, weapon)) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
store_hitboxes();
if (m_hitboxes.empty()) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
find_targets();
m_best_target = select_target();
if (!m_best_target || !m_best_target->m_best_point) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
auto now = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - lastShotTime).count();
if (duration < Globals::TriggerBot.DelayBetweenShots) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
INPUT input = {0};
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
SendInput(1, &input, sizeof(INPUT));
std::this_thread::sleep_for(std::chrono::milliseconds(Globals::TriggerBot.ShotDelay));
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, &input, sizeof(INPUT));
lastShotTime = now;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
catch (const std::exception&) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
}
void Start() {
if (Running) return;
Running = true;
Thread = std::thread(Loop);
}
void Stop() {
Running = false;
if (Thread.joinable()) {
Thread.join();
}
}
}