413 lines
18 KiB
C++
413 lines
18 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 <chrono>
|
||
#include <Windows.h>
|
||
#include "../../menu/hud.h"
|
||
#include "../../menu/menu.h"
|
||
#include <array>
|
||
#include <cmath>
|
||
|
||
// Индексы костей (актуально для 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;
|
||
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);
|
||
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);
|
||
|
||
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) {
|
||
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->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;
|
||
}
|
||
}
|
||
if (bestTarget) {
|
||
Vector_t target_pos = GetAimbotTargetPos(bestTarget, lep, *viewangles);
|
||
//Vector_t target_pos = GetEntityEyePos(bestTarget);
|
||
QAngle_t angle = CalcAngles(target_pos, lep);
|
||
angle.x *= -1.f;
|
||
angle.y += 180.f;
|
||
QAngle_t ang_punch_angle = *(QAngle_t*)((uintptr_t)lp + SchemaFinder::Get(hash_32_fnv1a_const("C_CSPlayerPawn->m_aimPunchAngle")));
|
||
if (isShooting) {
|
||
last_punch_angle = ang_punch_angle;
|
||
} else {
|
||
last_punch_angle = {0,0,0};
|
||
}
|
||
// --- RCS ---
|
||
bool rcsActive = (Config::rcs || Config::shooterAfterAim) && (shotCount > 1);
|
||
if (rcsActive)
|
||
angle -= last_punch_angle * 2.f;
|
||
angle.z = 0.f;
|
||
angle = angle.Normalize();
|
||
// --- RCS ---
|
||
QAngle_t delta = (angle - *viewangles).Normalize();
|
||
if (rcsActive) {
|
||
float smooth_rcs = 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_rcs = Config::aimbot_smooth + (Config::aimbot_smooth * factor * Config::aimbot_dynamic_smooth_factor);
|
||
}
|
||
smooth_rcs = std::fmax(smooth_rcs / 10.f, 1.0f);
|
||
angle -= last_punch_angle * 2.f * smooth_rcs;
|
||
}
|
||
// --- 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;
|
||
}
|
||
}
|
||
// В этом режиме не используем 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->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 (!lockedTarget->handle().valid() || lockedTarget->getHealth() <= 0) {
|
||
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 ang_punch_angle = *(QAngle_t*)((uintptr_t)lp + SchemaFinder::Get(hash_32_fnv1a_const("C_CSPlayerPawn->m_aimPunchAngle")));
|
||
if (isShooting) {
|
||
last_punch_angle = ang_punch_angle;
|
||
} else {
|
||
last_punch_angle = {0,0,0};
|
||
}
|
||
// --- RCS ---
|
||
bool rcsActive = (Config::rcs || Config::shooterAfterAim) && (shotCount > 1);
|
||
if (rcsActive)
|
||
angle -= last_punch_angle * 2.f;
|
||
angle.z = 0.f;
|
||
angle = angle.Normalize();
|
||
// --- RCS ---
|
||
QAngle_t delta = (angle - *viewangles).Normalize();
|
||
if (rcsActive) {
|
||
float smooth_rcs = 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_rcs = Config::aimbot_smooth + (Config::aimbot_smooth * factor * Config::aimbot_dynamic_smooth_factor);
|
||
}
|
||
smooth_rcs = std::fmax(smooth_rcs / 10.f, 1.0f);
|
||
angle -= last_punch_angle * 2.f * smooth_rcs;
|
||
}
|
||
// --- 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->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;
|
||
|
||
//if (Config::shooterAfterAim) {
|
||
// if (g_ShowMenu) return;
|
||
// C_CSPlayerPawn* lp = H::oGetLocalPlayer(0);
|
||
// bool onEnemy = false;
|
||
// if (lp) {
|
||
// int crosshairIdx = *(int*)((uintptr_t)lp + 0x1458); // m_iIDEntIndex
|
||
// if (crosshairIdx > 0) {
|
||
// auto target = I::GameEntity->Instance->Get<C_CSPlayerPawn>(crosshairIdx);
|
||
// if (target && target->getHealth() > 0 && (!Config::team_check || target->getTeam() != lp->getTeam()))
|
||
// onEnemy = true;
|
||
// }
|
||
// }
|
||
// // Если врага нет под прицелом — всегда блокируем ЛКМ
|
||
// if (!onEnemy && (GetAsyncKeyState(VK_LBUTTON) & 0x8000)) {
|
||
// INPUT input = { 0 };
|
||
// input.type = INPUT_MOUSE;
|
||
// input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
|
||
// SendInput(1, &input, sizeof(INPUT));
|
||
// }
|
||
// // return; // Не делаем return, чтобы аимбот работал всегда
|
||
//}
|
||
}
|