608 lines
23 KiB
C++
608 lines
23 KiB
C++
#include "../../../cs2/entity/C_CSPlayerPawn/C_CSPlayerPawn.h"
|
||
#include "../../../templeware/interfaces/CGameEntitySystem/CGameEntitySystem.h"
|
||
#include "../../../templeware/interfaces/interfaces.h"
|
||
#include "../../../templeware/hooks/hooks.h"
|
||
#include "../../../templeware/config/config.h"
|
||
#include "../../utils/memory/patternscan/patternscan.h"
|
||
#include "../visuals/visuals.h"
|
||
#include "CUserCmd.h"
|
||
#include "../../../templeware/utils/schema/schema.h"
|
||
|
||
#include <chrono>
|
||
#include <Windows.h>
|
||
#include <array>
|
||
#include <cmath>
|
||
#include <Psapi.h>
|
||
#include "../../menu/hud.h"
|
||
#include "../../menu/menu.h"
|
||
#include <iostream>
|
||
|
||
// Адреса из дампа (актуально для 2024-07-18)
|
||
#define DW_SENSITIVITY 0x1A6A9D8
|
||
#define DW_SENSITIVITY_SENS 0x40
|
||
|
||
float GetGameSensitivity() {
|
||
static float fallback = 2.0f;
|
||
HMODULE hClient = GetModuleHandleA("client.dll");
|
||
if (!hClient) return fallback;
|
||
uintptr_t sensBase = reinterpret_cast<uintptr_t>(hClient) + DW_SENSITIVITY;
|
||
uintptr_t sensPtr = *reinterpret_cast<uintptr_t*>(sensBase);
|
||
if (!sensPtr) return fallback;
|
||
float sens = *reinterpret_cast<float*>(sensPtr + DW_SENSITIVITY_SENS);
|
||
if (sens < 0.01f || sens > 20.0f) return fallback;
|
||
return sens;
|
||
}
|
||
|
||
// Индексы костей (актуально для CS2)
|
||
constexpr int BONE_INDEX_HEAD = 6; // Head
|
||
constexpr int BONE_INDEX_NECK = 5; // Neck
|
||
constexpr int BONE_INDEX_BODY = 4;//0; // Pelvis/Root
|
||
|
||
// --- lastBoneIdx теперь глобальный static ---
|
||
static int lastBoneIdx = -1;
|
||
|
||
inline QAngle_t CalcAngles(Vector_t viewPos, Vector_t aimPos)
|
||
{
|
||
QAngle_t angle = { 0, 0, 0 };
|
||
|
||
Vector_t delta = aimPos - viewPos;
|
||
|
||
angle.x = -asin(delta.z / delta.Length()) * (180.0f / 3.141592654f);
|
||
angle.y = atan2(delta.y, delta.x) * (180.0f / 3.141592654f);
|
||
|
||
return angle;
|
||
}
|
||
|
||
inline float GetFov(const QAngle_t& viewAngle, const QAngle_t& aimAngle)
|
||
{
|
||
QAngle_t delta = (aimAngle - viewAngle).Normalize();
|
||
|
||
return sqrtf(powf(delta.x, 2.0f) + powf(delta.y, 2.0f));
|
||
}
|
||
|
||
// // Сигнатура функции GetBonePosition (актуально для client.dll):
|
||
// // 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC ? 4D 8B F1
|
||
// using GetBonePositionFn = int64_t(__fastcall*)(void*, uint32_t, Vector_t*, Vector_t*);
|
||
// static GetBonePositionFn oGetBonePosition = nullptr;
|
||
|
||
// static void InitGetBonePositionSig() {
|
||
// if (!oGetBonePosition) {
|
||
// uintptr_t addr = M::patternScan("client.dll", "48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC ? 4D 8B F1");
|
||
// oGetBonePosition = reinterpret_cast<GetBonePositionFn>(addr);
|
||
// }
|
||
// }
|
||
|
||
Vector_t GetBonePosition(const C_CSPlayerPawn* Entity, int boneIdx) {
|
||
if (!Entity) return {};
|
||
// Внешний способ: читаем Vector3 по адресу boneMatrix + boneIdx * 0x20
|
||
uintptr_t pGameSceneNode = *reinterpret_cast<uintptr_t*>((uintptr_t)Entity + 0x328);
|
||
if (!pGameSceneNode) return {};
|
||
uintptr_t pBoneMatrix = *reinterpret_cast<uintptr_t*>(pGameSceneNode + 0x1F0);
|
||
if (!pBoneMatrix) return {};
|
||
return *reinterpret_cast<Vector_t*>(pBoneMatrix + boneIdx * 0x20);
|
||
}
|
||
|
||
// Получить позицию для аимбота в зависимости от выбора пользователя
|
||
Vector_t GetAimbotTargetPos(const C_CSPlayerPawn* Entity, const Vector_t& from, const QAngle_t& viewAngles) {
|
||
switch (Config::aimbot_bone) {
|
||
case Config::BONE_HEAD:
|
||
return GetBonePosition(Entity, BONE_INDEX_HEAD);
|
||
case Config::BONE_NECK:
|
||
return GetBonePosition(Entity, BONE_INDEX_NECK);
|
||
case Config::BONE_BODY:
|
||
return GetBonePosition(Entity, BONE_INDEX_BODY);
|
||
case Config::BONE_NEAREST:
|
||
default: {
|
||
// Каждый раз ищем ближайшую кость по FOV
|
||
std::array<int, 2> bones = { BONE_INDEX_HEAD, BONE_INDEX_BODY };
|
||
float bestFov = FLT_MAX;
|
||
int bestIdx = BONE_INDEX_HEAD;
|
||
for (int idx : bones) {
|
||
Vector_t pos = GetBonePosition(Entity, idx);
|
||
QAngle_t ang = CalcAngles(from, pos); // <-- Исправлено!
|
||
float fov = GetFov(viewAngles, ang);
|
||
if (fov < bestFov && std::isfinite(fov)) {
|
||
bestFov = fov;
|
||
bestIdx = idx;
|
||
}
|
||
}
|
||
return GetBonePosition(Entity, bestIdx);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
Vector_t GetEntityEyePos(const C_CSPlayerPawn* Entity) {
|
||
if (!Entity)
|
||
return {};
|
||
|
||
uintptr_t game_scene_node = *reinterpret_cast<uintptr_t*>((uintptr_t)Entity + SchemaFinder::Get(hash_32_fnv1a_const("C_BaseEntity->m_pGameSceneNode")));
|
||
|
||
auto Origin = *reinterpret_cast<Vector_t*>(game_scene_node + SchemaFinder::Get(hash_32_fnv1a_const("CGameSceneNode->m_vecAbsOrigin")));
|
||
auto ViewOffset = *reinterpret_cast<Vector_t*>((uintptr_t)Entity + SchemaFinder::Get(hash_32_fnv1a_const("C_BaseModelEntity->m_vecViewOffset")));
|
||
|
||
Vector_t Result = Origin + ViewOffset;
|
||
if (!std::isfinite(Result.x) || !std::isfinite(Result.y) || !std::isfinite(Result.z))
|
||
return {};
|
||
|
||
return Result;
|
||
}
|
||
|
||
// Удаляем все вспомогательные функции инкапсуляции
|
||
|
||
void Aimbot() {
|
||
static C_CSPlayerPawn* lockedTarget = nullptr;
|
||
static bool prevAimbotState = false;
|
||
static bool targetWasLost = false;
|
||
static QAngle_t last_punch_angle = { 0,0,0 };
|
||
static int shotCount = 0;
|
||
float sensitivity = GetGameSensitivity();
|
||
bool aimbotActive = Config::always_on_aimbot ? true : Config::aimbot;
|
||
// --- shooterAfterAim + triggerbot_key ---
|
||
if (Config::shooterAfterAim && (GetAsyncKeyState(Config::triggerbot_key) & 0x8000)) {
|
||
aimbotActive = true;
|
||
}
|
||
C_CSPlayerPawn* lp = H::oGetLocalPlayer(0);
|
||
if (cached_players.empty() || !lp || !lp->handle().valid() || lp->getHealth() <= 0)
|
||
return;
|
||
Vector_t lep = GetEntityEyePos(lp);
|
||
QAngle_t* viewangles = (QAngle_t*)(modules.getModule("client") + 0x1A78650);
|
||
bool isShooting = (GetAsyncKeyState(Config::triggerbot_key) & 0x8000) || (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
|
||
|
||
int shotsFired = lp ? lp->getShotsFired() : 0;
|
||
shotCount = shotsFired;
|
||
//g_DebugString = "debug: " + std::to_string(shotsFired) + "Sens: " + std::to_string(sensitivity);
|
||
|
||
if (Config::aimbot_on_lmb && !Config::always_on_aimbot) {
|
||
aimbotActive = isShooting;
|
||
}
|
||
|
||
// Получаем локального игрока и viewangles всегда, чтобы не дублировать код
|
||
// C_CSPlayerPawn* lp = H::oGetLocalPlayer(0);
|
||
// Vector_t lep = GetEntityEyePos(lp);
|
||
// QAngle_t* viewangles = (QAngle_t*)(modules.getModule("client") + 0x1A78650);
|
||
|
||
// Проверка: стреляет ли игрок (LMB)
|
||
// bool isShooting = (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
|
||
|
||
// --- Новый режим: always_on_aimbot ---
|
||
if (Config::always_on_aimbot) {
|
||
float bestFov = Config::aimbot_fov;
|
||
PlayerCache* bestTarget = nullptr;
|
||
QAngle_t bestAngle = { 0, 0, 0 };
|
||
for (auto& Player : cached_players) {
|
||
if (!Player.handle.valid() || Player.health <= 0 || Player.handle.index() == INVALID_EHANDLE_INDEX)
|
||
continue;
|
||
if (Config::teamCheck && (Player.team_num == cached_local.team))
|
||
continue;
|
||
Vector_t target_pos = Player.position + Player.viewOffset;
|
||
QAngle_t angle = CalcAngles(target_pos, lep);
|
||
angle.x *= -1.f;
|
||
angle.y += 180.f;
|
||
const float fov = GetFov(*viewangles, angle);
|
||
if (!std::isfinite(fov) || fov > bestFov)
|
||
continue;
|
||
bestFov = fov;
|
||
bestTarget = &Player;
|
||
bestAngle = angle;
|
||
}
|
||
if (bestTarget) {
|
||
Vector_t target_pos = bestTarget->position + bestTarget->viewOffset;
|
||
QAngle_t angle = CalcAngles(target_pos, lep);
|
||
angle.x *= -1.f;
|
||
angle.y += 180.f;
|
||
QAngle_t cur_punch_angle = *(QAngle_t*)((uintptr_t)lp + SchemaFinder::Get(hash_32_fnv1a_const("C_CSPlayerPawn->m_aimPunchAngle")));
|
||
// --- RCS ---
|
||
bool rcsActive = false;
|
||
if (Config::shooterAfterAim && (GetAsyncKeyState(Config::triggerbot_key) & 0x8000)) {
|
||
rcsActive = (Config::rcs || Config::shooterAfterAim) && (shotCount > Config::rcsActivationShots);
|
||
}
|
||
else {
|
||
rcsActive = (Config::rcs || Config::shooterAfterAim) && (shotCount > Config::rcsActivationShots);
|
||
}
|
||
if (rcsActive && shotsFired > 1) {
|
||
// Для прямого изменения viewangles: делить НЕ нужно
|
||
//QAngle_t punchDelta = cur_punch_angle - last_punch_angle;
|
||
//g_DebugString = "debug: " + std::to_string(punchDelta.x);
|
||
angle -= cur_punch_angle * 2.f;
|
||
last_punch_angle = cur_punch_angle;
|
||
}
|
||
else {
|
||
last_punch_angle = { 0,0,0 };
|
||
}
|
||
angle.z = 0.f;
|
||
angle = angle.Normalize();
|
||
|
||
// --- Smooth ---
|
||
QAngle_t delta = (angle - *viewangles).Normalize();
|
||
if (Config::aimbot_smooth > 0.f) {
|
||
QAngle_t cur = *viewangles;
|
||
float smooth = Config::aimbot_smooth;
|
||
if (Config::aimbot_dynamic_smooth) {
|
||
float fov = sqrtf(delta.x * delta.x + delta.y * delta.y);
|
||
float maxFov = Config::aimbot_fov;
|
||
float factor = (maxFov > 0.01f) ? (fov / maxFov) : 0.f;
|
||
smooth = smooth + (smooth * factor * Config::aimbot_dynamic_smooth_factor);
|
||
}
|
||
angle = cur + delta * (1.f / smooth);
|
||
angle = angle.Normalize();
|
||
*viewangles = angle;
|
||
}
|
||
else {
|
||
*viewangles = angle;
|
||
}
|
||
}
|
||
// В этом режиме не используем lockedTarget и не трогаем targetWasLost/prevAimbotState
|
||
return;
|
||
}
|
||
|
||
// Если кнопка только что нажата (переход с false на true) — ищем новую цель
|
||
if (aimbotActive && !prevAimbotState) {
|
||
lastBoneIdx = -1; // Сброс при новой активации
|
||
int nMaxHighestEntity = I::GameEntity->Instance->GetHighestEntityIndex();
|
||
float bestFov = Config::aimbot_fov;
|
||
C_CSPlayerPawn* bestTarget = nullptr;
|
||
QAngle_t bestAngle = { 0, 0, 0 };
|
||
|
||
for (int i = 1; i <= nMaxHighestEntity; i++) {
|
||
auto Entity = I::GameEntity->Instance->Get(i);
|
||
if (!Entity)
|
||
continue;
|
||
if (!Entity->handle().valid())
|
||
continue;
|
||
SchemaClassInfoData_t* _class = nullptr;
|
||
Entity->dump_class_info(&_class);
|
||
if (!_class)
|
||
continue;
|
||
const uint32_t hash = HASH(_class->szName);
|
||
if (hash == HASH("C_CSPlayerPawn")) {
|
||
C_CSPlayerPawn* pawn = (C_CSPlayerPawn*)Entity;
|
||
if (!pawn) continue;
|
||
if (pawn->get_entity_by_handle() == lp->get_entity_by_handle()) continue;
|
||
if (pawn->getHealth() <= 0) continue;
|
||
if (Config::team_check && pawn->getTeam() == lp->getTeam()) continue;
|
||
Vector_t target_pos = GetEntityEyePos(pawn);//GetAimbotTargetPos(pawn, lep);
|
||
QAngle_t angle = CalcAngles(target_pos, lep);
|
||
angle.x *= -1.f;
|
||
angle.y += 180.f;
|
||
const float fov = GetFov(*viewangles, angle);
|
||
if (!std::isfinite(fov) || fov > bestFov)
|
||
continue;
|
||
bestFov = fov;
|
||
bestTarget = pawn;
|
||
bestAngle = angle;
|
||
}
|
||
}
|
||
lockedTarget = bestTarget;
|
||
targetWasLost = false;
|
||
// Сброс punch_angle при смене цели
|
||
last_punch_angle = { 0,0,0 };
|
||
}
|
||
|
||
// Если кнопка отпущена — сбрасываем захват
|
||
if (!aimbotActive) {
|
||
lockedTarget = nullptr;
|
||
targetWasLost = false;
|
||
last_punch_angle = { 0,0,0 }; // сброс rcs
|
||
// Сброс lastBoneIdx при отпускании кнопки аимбота (например, в Aimbot()):
|
||
// if (!aimbotActive) lastBoneIdx = -1;
|
||
}
|
||
|
||
// Если есть захваченная цель и кнопка удерживается
|
||
if (aimbotActive && lockedTarget) {
|
||
// Проверяем, что цель всё ещё валидна
|
||
if (!lp || !lp->handle().valid() || lp->getHealth() <= 0) {
|
||
lockedTarget = nullptr;
|
||
targetWasLost = false;
|
||
last_punch_angle = { 0,0,0 };
|
||
return;
|
||
}
|
||
if (
|
||
lockedTarget->get_entity_by_handle() == lp->get_entity_by_handle() ||
|
||
lockedTarget->getHealth() <= 0 ||
|
||
!lockedTarget->handle().valid()
|
||
) {
|
||
lockedTarget = nullptr;
|
||
targetWasLost = true;
|
||
last_punch_angle = { 0,0,0 }; // сброс rcs
|
||
}
|
||
else {
|
||
Vector_t target_pos = GetAimbotTargetPos(lockedTarget, lep, *viewangles);
|
||
QAngle_t angle = CalcAngles(target_pos, lep);
|
||
angle.x *= -1.f;
|
||
angle.y += 180.f;
|
||
QAngle_t cur_punch_angle = *(QAngle_t*)((uintptr_t)lp + SchemaFinder::Get(hash_32_fnv1a_const("C_CSPlayerPawn->m_aimPunchAngle")));
|
||
// --- RCS ---
|
||
bool rcsActive = false;
|
||
if (Config::shooterAfterAim && (GetAsyncKeyState(Config::triggerbot_key) & 0x8000)) {
|
||
rcsActive = (Config::rcs || Config::shooterAfterAim) && (shotCount > Config::rcsActivationShots);
|
||
}
|
||
else {
|
||
rcsActive = (Config::rcs || Config::shooterAfterAim) && (shotCount > Config::rcsActivationShots);
|
||
}
|
||
if (rcsActive && shotCount > 1) {
|
||
// Для прямого изменения viewangles: делить НЕ нужно
|
||
//QAngle_t punchDelta = cur_punch_angle - last_punch_angle;
|
||
//g_DebugString = "debug: " + std::to_string(punchDelta.x);
|
||
angle -= cur_punch_angle * 2.f;
|
||
last_punch_angle = cur_punch_angle;
|
||
}
|
||
else {
|
||
last_punch_angle = { 0,0,0 };
|
||
}
|
||
angle.z = 0.f;
|
||
angle = angle.Normalize();
|
||
// --- Smooth ---
|
||
if (Config::aimbot_smooth > 0.f) {
|
||
QAngle_t cur = *viewangles;
|
||
QAngle_t delta = (angle - cur).Normalize();
|
||
float smooth = Config::aimbot_smooth;
|
||
if (Config::aimbot_dynamic_smooth) {
|
||
float fov = sqrtf(delta.x * delta.x + delta.y * delta.y);
|
||
float maxFov = Config::aimbot_fov;
|
||
float factor = (maxFov > 0.01f) ? (fov / maxFov) : 0.f;
|
||
smooth = smooth + (smooth * factor * Config::aimbot_dynamic_smooth_factor);
|
||
}
|
||
angle = cur + delta * (1.f / smooth);
|
||
angle = angle.Normalize();
|
||
*viewangles = angle;
|
||
}
|
||
else {
|
||
*viewangles = angle;
|
||
}
|
||
}
|
||
}
|
||
|
||
//Если кнопка зажата, цели нет, и мы не теряли цель (т.е. только в начале или если цели не было вообще)
|
||
if (aimbotActive && !lockedTarget && !targetWasLost) {
|
||
int nMaxHighestEntity = I::GameEntity->Instance->GetHighestEntityIndex();
|
||
float bestFov = Config::aimbot_fov;
|
||
C_CSPlayerPawn* bestTarget = nullptr;
|
||
QAngle_t bestAngle = { 0, 0, 0 };
|
||
|
||
for (int i = 1; i <= nMaxHighestEntity; i++) {
|
||
auto Entity = I::GameEntity->Instance->Get(i);
|
||
if (!Entity)
|
||
continue;
|
||
if (!Entity->handle().valid())
|
||
continue;
|
||
SchemaClassInfoData_t* _class = nullptr;
|
||
Entity->dump_class_info(&_class);
|
||
if (!_class)
|
||
continue;
|
||
const uint32_t hash = HASH(_class->szName);
|
||
if (hash == HASH("C_CSPlayerPawn")) {
|
||
C_CSPlayerPawn* pawn = (C_CSPlayerPawn*)Entity;
|
||
if (!pawn) continue;
|
||
if (pawn->get_entity_by_handle() == lp->get_entity_by_handle()) continue;
|
||
if (pawn->getHealth() <= 0) continue;
|
||
if (Config::team_check && pawn->getTeam() == lp->getTeam()) continue;
|
||
Vector_t target_pos = GetEntityEyePos(pawn);//GetAimbotTargetPos(pawn, lep);
|
||
QAngle_t angle = CalcAngles(target_pos, lep);
|
||
angle.x *= -1.f;
|
||
angle.y += 180.f;
|
||
const float fov = GetFov(*viewangles, angle);
|
||
if (!std::isfinite(fov) || fov > bestFov)
|
||
continue;
|
||
bestFov = fov;
|
||
bestTarget = pawn;
|
||
bestAngle = angle;
|
||
}
|
||
}
|
||
lockedTarget = bestTarget;
|
||
// Сброс punch_angle при смене цели
|
||
last_punch_angle = { 0,0,0 };
|
||
}
|
||
|
||
prevAimbotState = aimbotActive;
|
||
}
|
||
|
||
void Ver2Aimbot(CUserCmd* pCmd) {
|
||
//// --- Silent Aim: чистая и безопасная реализация ---
|
||
//if (!Config::silent_aim || !pCmd) return;
|
||
//static C_CSPlayerPawn* lockedTarget = nullptr;
|
||
//static bool prevSilentState = false;
|
||
//static QAngle_t last_punch_angle = { 0,0,0 };
|
||
//static int shotCount = 0;
|
||
//static bool targetWasLost = false;
|
||
//static bool targetWasLockedThisPress = false;
|
||
//C_CSPlayerPawn* lp = H::oGetLocalPlayer(0);
|
||
//if (!lp || !lp->handle().valid() || lp->getHealth() <= 0) return;
|
||
//Vector_t lep = GetEntityEyePos(lp);
|
||
//// Получаем viewangles только из CUserCmd!
|
||
//QAngle_t* cur = nullptr;
|
||
//if (pCmd->csgoUserCmd.pBaseCmd && pCmd->csgoUserCmd.pBaseCmd->pViewAngles) {
|
||
// cur = &pCmd->csgoUserCmd.pBaseCmd->pViewAngles->angValue;
|
||
//}
|
||
//if (!cur) return;
|
||
//// --- Кнопка активации ---
|
||
//bool silentActive = Config::always_on_silent_aim ? true : (GetAsyncKeyState(Config::silent_aim_key) & 0x8000);
|
||
//if (Config::silent_shooterAfterAim && (GetAsyncKeyState(Config::triggerbot_key) & 0x8000)) {
|
||
// silentActive = true;
|
||
//}
|
||
//int shotsFired = lp ? lp->getShotsFired() : 0;
|
||
//shotCount = shotsFired;
|
||
//// --- Сброс флагов при новом нажатии ---
|
||
//if (silentActive && !prevSilentState) {
|
||
// targetWasLost = false;
|
||
// targetWasLockedThisPress = false;
|
||
//}
|
||
//// --- Поиск цели ---
|
||
//if (silentActive && !lockedTarget) {
|
||
// if (Config::silent_rage || (!targetWasLost && !targetWasLockedThisPress)) {
|
||
// int nMaxHighestEntity = I::GameEntity->Instance->GetHighestEntityIndex();
|
||
// float bestFov = Config::silent_aim_fov;
|
||
// C_CSPlayerPawn* bestTarget = nullptr;
|
||
// QAngle_t bestAngle = { 0, 0, 0 };
|
||
// for (int i = 1; i <= nMaxHighestEntity; i++) {
|
||
// auto Entity = I::GameEntity->Instance->Get(i);
|
||
// if (!Entity) continue;
|
||
// if (!Entity->handle().valid()) continue;
|
||
// SchemaClassInfoData_t* _class = nullptr;
|
||
// Entity->dump_class_info(&_class);
|
||
// if (!_class) continue;
|
||
// const uint32_t hash = HASH(_class->szName);
|
||
// if (hash == HASH("C_CSPlayerPawn")) {
|
||
// C_CSPlayerPawn* pawn = (C_CSPlayerPawn*)Entity;
|
||
// if (!pawn) continue;
|
||
// if (pawn->get_entity_by_handle() == lp->get_entity_by_handle()) continue;
|
||
// if (pawn->getHealth() <= 0) continue;
|
||
// if (Config::team_check && pawn->getTeam() == lp->getTeam()) continue;
|
||
// // --- Выбор кости для silent aim ---
|
||
// Vector_t target_pos;
|
||
// switch (Config::silent_aim_bone) {
|
||
// case Config::BONE_HEAD:
|
||
// target_pos = GetBonePosition(pawn, BONE_INDEX_HEAD); break;
|
||
// case Config::BONE_NECK:
|
||
// target_pos = GetBonePosition(pawn, BONE_INDEX_NECK); break;
|
||
// case Config::BONE_BODY:
|
||
// target_pos = GetBonePosition(pawn, BONE_INDEX_BODY); break;
|
||
// case Config::BONE_NEAREST:
|
||
// default:
|
||
// target_pos = GetAimbotTargetPos(pawn, lep, *cur); break;
|
||
// }
|
||
// QAngle_t angle = CalcAngles(target_pos, lep);
|
||
// angle.x *= -1.f;
|
||
// angle.y += 180.f;
|
||
// float fov = GetFov(*cur, angle);
|
||
// if (!std::isfinite(fov) || fov > bestFov) continue;
|
||
// bestFov = fov;
|
||
// bestTarget = pawn;
|
||
// bestAngle = angle;
|
||
// }
|
||
// }
|
||
// lockedTarget = bestTarget;
|
||
// last_punch_angle = { 0,0,0 };
|
||
// if (!Config::silent_rage && lockedTarget) targetWasLockedThisPress = true;
|
||
// if (!Config::silent_rage && !lockedTarget) targetWasLost = true;
|
||
// }
|
||
//}
|
||
//// --- Сброс при отпускании кнопки ---
|
||
//if (!silentActive) {
|
||
// lockedTarget = nullptr;
|
||
// last_punch_angle = { 0,0,0 };
|
||
// targetWasLost = false;
|
||
// targetWasLockedThisPress = false;
|
||
//}
|
||
//// --- Наведение на цель ---
|
||
//if (silentActive && lockedTarget) {
|
||
// // Проверка валидности цели
|
||
// if (!lp || !lp->handle().valid() || lp->getHealth() <= 0 ||
|
||
// lockedTarget->get_entity_by_handle() == lp->get_entity_by_handle() ||
|
||
// lockedTarget->getHealth() <= 0 ||
|
||
// !lockedTarget->handle().valid() ||
|
||
// (Config::team_check && lockedTarget->getTeam() == lp->getTeam())) {
|
||
// lockedTarget = nullptr;
|
||
// last_punch_angle = { 0,0,0 };
|
||
// targetWasLost = true;
|
||
// prevSilentState = silentActive;
|
||
// return;
|
||
// }
|
||
// // --- Выбор кости для silent aim ---
|
||
// Vector_t target_pos;
|
||
// switch (Config::silent_aim_bone) {
|
||
// case Config::BONE_HEAD:
|
||
// target_pos = GetBonePosition(lockedTarget, BONE_INDEX_HEAD); break;
|
||
// case Config::BONE_NECK:
|
||
// target_pos = GetBonePosition(lockedTarget, BONE_INDEX_NECK); break;
|
||
// case Config::BONE_BODY:
|
||
// target_pos = GetBonePosition(lockedTarget, BONE_INDEX_BODY); break;
|
||
// case Config::BONE_NEAREST:
|
||
// default:
|
||
// target_pos = GetAimbotTargetPos(lockedTarget, lep, *cur); break;
|
||
// }
|
||
// QAngle_t angle = CalcAngles(target_pos, lep);
|
||
// angle.x *= -1.f;
|
||
// angle.y += 180.f;
|
||
// // --- Smooth ---
|
||
// if (Config::silent_aim_smooth > 0.f) {
|
||
// QAngle_t delta = (angle - *cur).Normalize();
|
||
// float smooth = Config::silent_aim_smooth;
|
||
// angle = *cur + delta * (1.f / smooth);
|
||
// angle = angle.Normalize();
|
||
// }
|
||
// *cur = angle;
|
||
//}
|
||
//prevSilentState = silentActive;
|
||
}
|
||
|
||
// --- Функция для вывода отладочной информации через ImGui ---
|
||
void ShowSilentAimDebugInfo(const CUserCmd* pCmd) {
|
||
char debugBuf[256];
|
||
_snprintf_s(debugBuf, sizeof(debugBuf),
|
||
"CUserCmd: size=%zu, m_csgoUserCmd@%zu, m_nButtons@%zu, nSubticks=%d, pRep=%p, pBaseCmd=%p",
|
||
sizeof(CUserCmd),
|
||
offsetof(CUserCmd, m_csgoUserCmd),
|
||
offsetof(CUserCmd, m_nButtons),
|
||
pCmd->m_csgoUserCmd.m_inputHistoryField.m_pRep ? pCmd->m_csgoUserCmd.m_inputHistoryField.m_pRep->m_nAllocatedSize : 0,
|
||
(void*)pCmd->m_csgoUserCmd.m_inputHistoryField.m_pRep,
|
||
(void*)pCmd->m_csgoUserCmd.m_pBaseCmd);
|
||
g_DebugString = debugBuf;
|
||
}
|
||
|
||
void SilentAimbot(CUserCmd* pCmd) {
|
||
if (!Config::silent_aim || !pCmd)
|
||
return;
|
||
|
||
C_CSPlayerPawn* lp = H::oGetLocalPlayer(0);
|
||
if (!lp || !lp->handle().valid() || lp->getHealth() <= 0)
|
||
return;
|
||
|
||
// Кнопка активации
|
||
bool silentActive = Config::always_on_silent_aim ? true : (GetAsyncKeyState(Config::silent_aim_key) & 0x8000);
|
||
if (Config::silent_shooterAfterAim && (GetAsyncKeyState(Config::triggerbot_key) & 0x8000)) {
|
||
silentActive = true;
|
||
}
|
||
if (!silentActive)
|
||
return;
|
||
|
||
Vector_t localEye = GetEntityEyePos(lp);
|
||
// --- Исправленный доступ к углам ---
|
||
QAngle_t* curAngles = nullptr;
|
||
if (pCmd && pCmd->csgoUserCmd.pBaseCmd && pCmd->csgoUserCmd.pBaseCmd->pViewAngles)
|
||
curAngles = &pCmd->csgoUserCmd.pBaseCmd->pViewAngles->angValue;
|
||
if (!curAngles)
|
||
return;
|
||
|
||
// Поиск цели
|
||
float bestFov = Config::silent_aim_fov;
|
||
C_CSPlayerPawn* bestTarget = nullptr;
|
||
Vector_t bestTargetPos{};
|
||
for (int i = 1; i <= I::GameEntity->Instance->GetHighestEntityIndex(); ++i) {
|
||
auto Entity = I::GameEntity->Instance->Get(i);
|
||
if (!Entity || !Entity->handle().valid())
|
||
continue;
|
||
SchemaClassInfoData_t* _class = nullptr;
|
||
Entity->dump_class_info(&_class);
|
||
if (!_class || HASH(_class->szName) != HASH("C_CSPlayerPawn"))
|
||
continue;
|
||
C_CSPlayerPawn* pawn = (C_CSPlayerPawn*)Entity;
|
||
if (!pawn || pawn->get_entity_by_handle() == lp->get_entity_by_handle() || pawn->getHealth() <= 0)
|
||
continue;
|
||
if (Config::team_check && pawn->getTeam() == lp->getTeam())
|
||
continue;
|
||
Vector_t targetPos = GetBonePosition(pawn, Config::silent_aim_bone == Config::BONE_HEAD ? BONE_INDEX_HEAD :
|
||
Config::silent_aim_bone == Config::BONE_NECK ? BONE_INDEX_NECK :
|
||
Config::silent_aim_bone == Config::BONE_BODY ? BONE_INDEX_BODY :
|
||
BONE_INDEX_HEAD);
|
||
QAngle_t angle = CalcAngles(targetPos, localEye);
|
||
angle.x *= -1.f;
|
||
angle.y += 180.f;
|
||
float fov = GetFov(*curAngles, angle);
|
||
if (!std::isfinite(fov) || fov > bestFov)
|
||
continue;
|
||
bestFov = fov;
|
||
bestTarget = pawn;
|
||
bestTargetPos = targetPos;
|
||
}
|
||
if (!bestTarget)
|
||
return;
|
||
|
||
QAngle_t aimAngle = CalcAngles(bestTargetPos, localEye);
|
||
aimAngle.x *= -1.f;
|
||
aimAngle.y += 180.f;
|
||
|
||
// Установить угол для всех сабтиков
|
||
pCmd->SetSubTickAngle(aimAngle);
|
||
}
|