-
Автор темы
- #1
Код:
// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com
#include "aim.h"
#include "..\misc\misc.h"
#include "..\misc\logs.h"
#include "..\autowall\autowall.h"
#include "..\..\utils\draw_manager.h"
#include "..\misc\prediction_system.h"
#include "..\fakewalk\slowwalk.h"
#include "..\lagcompensation\local_animations.h"
void aim::run(CUserCmd* cmd)
{
backup.clear();
targets.clear();
scanned_targets.clear();
final_target.reset();
should_stop = false;
if (!g_cfg.ragebot.enable)
return;
automatic_revolver(cmd);
prepare_targets();
if (g_ctx.globals.weapon->is_non_aim())
return;
if (g_ctx.globals.current_weapon == -1)
return;
scan_targets();
if (!should_stop && g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].autostop_modifiers[AUTOSTOP_PREDICTIVE])
{
for (auto& target : targets)
{
if (!target.last_record->valid())
continue;
scan_data last_data;
target.last_record->adjust_player();
scan(target.last_record, last_data, g_ctx.globals.eye_pos);
if (!last_data.valid())
continue;
should_stop = true;
break;
}
}
if (!automatic_stop(cmd))
return;
if (scanned_targets.empty())
return;
find_best_target();
if (!final_target.data.valid())
return;
fire(cmd);
}
void aim::automatic_revolver(CUserCmd* cmd)
{
if (!m_engine()->IsActiveApp())
return;
if (g_ctx.globals.weapon->m_iItemDefinitionIndex() != WEAPON_REVOLVER)
return;
if (cmd->m_buttons & IN_ATTACK)
return;
cmd->m_buttons &= ~IN_ATTACK2;
static auto r8cock_time = 0.0f;
auto server_time = TICKS_TO_TIME(g_ctx.globals.backup_tickbase);
if (g_ctx.globals.weapon->can_fire(false))
{
if (r8cock_time <= server_time)
{
if (g_ctx.globals.weapon->m_flNextSecondaryAttack() <= server_time)
r8cock_time = server_time + 0.234375f;
else
cmd->m_buttons |= IN_ATTACK2;
}
else
cmd->m_buttons |= IN_ATTACK;
}
else
{
r8cock_time = server_time + 0.234375f;
cmd->m_buttons &= ~IN_ATTACK;
}
g_ctx.globals.revolver_working = true;
}
void aim::prepare_targets()
{
for (auto i = 1; i < m_globals()->m_maxclients; i++)
{
if (g_cfg.player_list.white_list[i])
continue;
auto e = (player_t*)m_entitylist()->GetClientEntity(i);
if (!e->valid(true, false))
continue;
auto records = &player_records[i]; //-V826
if (records->empty())
continue;
targets.emplace_back(target(e, get_record(records, true), get_record(records, true)));
}
if (targets.size() >= 4)
{
auto first = rand() % targets.size();
auto second = rand() % targets.size();
auto third = rand() % targets.size();
for (auto i = 0; i < targets.size(); ++i)
{
if (i == first || i == second || i == third)
continue;
targets.erase(targets.begin() + i);
if (i > 0)
--i;
}
}
for (auto& target : targets)
backup.emplace_back(adjust_data(target.e));
}
static bool compare_records(const optimized_adjust_data& first, const optimized_adjust_data& second)
{
if (first.shot != second.shot)
return first.shot;
else if (first.speed != second.speed)
return first.speed > second.speed;
return first.simulation_time < second.simulation_time;
}
adjust_data* aim::get_record(std::deque <adjust_data>* records, bool history)
{
if (history)
{
std::deque <optimized_adjust_data> optimized_records;
for (auto i = 0; i < records->size(); ++i)
{
auto record = &records->at(i);
optimized_adjust_data optimized_record;
optimized_record.i = i;
optimized_record.player = record->player;
optimized_record.simulation_time = record->simulation_time;
optimized_record.speed = record->velocity.Length();
optimized_record.shot = record->shot;
optimized_records.emplace_back(optimized_record);
}
if (optimized_records.size() < 2)
return nullptr;
std::sort(optimized_records.begin(), optimized_records.end(), compare_records);
for (auto& optimized_record : optimized_records)
{
auto record = &records->at(optimized_record.i);
if (!record->valid())
continue;
return record;
}
}
else
{
for (auto i = 0; i < records->size(); ++i)
{
auto record = &records->at(i);
if (!record->valid())
continue;
return record;
}
}
return nullptr;
}
int aim::get_minimum_damage(bool visible, int health)
{
auto minimum_damage = 1;
if (visible)
{
if (minimum_damage > health)
minimum_damage = health + 5.f;
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].minimum_visible_damage > 100)
minimum_damage = health + g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].minimum_visible_damage - 100;
else
minimum_damage = math::clamp(g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].minimum_visible_damage, 1, health);
}
else
{
if (minimum_damage > health)
minimum_damage = health + 5.f;
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].minimum_damage > 100)
minimum_damage = health + g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].minimum_damage - 100;
else
minimum_damage = math::clamp(g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].minimum_damage, 1, health);
}
if (key_binds::get().get_key_bind_state(4 + g_ctx.globals.current_weapon))
{
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].minimum_override_damage > 100)
minimum_damage = health + g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].minimum_override_damage - 100;
else
minimum_damage = math::clamp(g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].minimum_override_damage, 1, health);
}
return minimum_damage;
}
void aim::scan_targets()
{
if (targets.empty())
return;
for (auto& target : targets)
{
if (target.history_record->valid())
{
scan_data last_data;
if (target.last_record->valid())
{
target.last_record->adjust_player();
scan(target.last_record, last_data);
}
scan_data history_data;
target.history_record->adjust_player();
scan(target.history_record, history_data);
if (last_data.valid() && last_data.damage > history_data.damage)
scanned_targets.emplace_back(scanned_target(target.last_record, last_data));
else if (history_data.valid())
scanned_targets.emplace_back(scanned_target(target.history_record, history_data));
}
else
{
if (!target.last_record->valid())
continue;
scan_data last_data;
target.last_record->adjust_player();
scan(target.last_record, last_data);
if (!last_data.valid())
continue;
scanned_targets.emplace_back(scanned_target(target.last_record, last_data));
}
}
}
bool aim::automatic_stop(CUserCmd* cmd)
{
if (!should_stop)
return true;
if (g_ctx.globals.slowwalking)
return true;
if (!(g_ctx.local()->m_fFlags() & FL_ONGROUND && engineprediction::get().backup_data.flags & FL_ONGROUND))
return true;
if (g_ctx.globals.weapon->is_empty())
return true;
if (!g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].autostop_modifiers[AUTOSTOP_BETWEEN_SHOTS] && !g_ctx.globals.weapon->can_fire(false))
return true;
if (!g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].autostop)
return true;
auto animlayer = g_ctx.local()->get_animlayers()[1];
if (animlayer.m_nSequence)
{
auto activity = g_ctx.local()->sequence_activity(animlayer.m_nSequence);
if (activity == ACT_CSGO_RELOAD && animlayer.m_flWeight > 0.0f)
return true;
}
auto weapon_info = g_ctx.globals.weapon->get_csweapon_info();
if (!weapon_info)
return true;
auto max_speed = 0.33f * (g_ctx.globals.scoped ? weapon_info->flMaxPlayerSpeedAlt : weapon_info->flMaxPlayerSpeed);
if (engineprediction::get().backup_data.velocity.Length2D() < max_speed)
slowwalk::get().create_move(cmd);
else
{
Vector direction;
Vector real_view;
math::vector_angles(engineprediction::get().backup_data.velocity, direction);
m_engine()->GetViewAngles(real_view);
direction.y = real_view.y - direction.y;
Vector forward;
math::angle_vectors(direction, forward);
static auto cl_forwardspeed = m_cvar()->FindVar(crypt_str("cl_forwardspeed"));
static auto cl_sidespeed = m_cvar()->FindVar(crypt_str("cl_sidespeed"));
auto negative_forward_speed = -cl_forwardspeed->GetFloat();
auto negative_side_speed = -cl_sidespeed->GetFloat();
auto negative_forward_direction = forward * negative_forward_speed;
auto negative_side_direction = forward * negative_side_speed;
cmd->m_forwardmove = negative_forward_direction.x;
cmd->m_sidemove = negative_side_direction.y;
cmd->m_forwardmove *= -1;
cmd->m_sidemove *= -1;
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].autostop_modifiers[AUTOSTOP_FORCE_ACCURACY])
return false;
}
return true;
}
static bool compare_points(const scan_point& first, const scan_point& second)
{
return !first.center && first.hitbox == second.hitbox;
}
auto get_hitgroup = [](const int& hitbox)
{
if (hitbox == HITBOX_HEAD)
return 0;
else if (hitbox == HITBOX_PELVIS)
return 1;
else if (hitbox == HITBOX_STOMACH)
return 2;
else if (hitbox >= HITBOX_LOWER_CHEST && hitbox <= HITBOX_UPPER_CHEST)
return 3;
else if (hitbox >= HITBOX_RIGHT_THIGH && hitbox <= HITBOX_LEFT_FOOT)
return 4;
else if (hitbox >= HITBOX_RIGHT_HAND && hitbox <= HITBOX_LEFT_FOREARM)
return 5;
return -2;
};
void aim::scan(adjust_data* record, scan_data& data, const Vector& shoot_position)
{
// setup some variables
auto should_force_baim = false;
auto weapon = g_ctx.local()->m_hActiveWeapon().Get();
if (!weapon)
return;
auto weapon_info = weapon->get_csweapon_info();
if (!weapon_info)
return;
auto hitboxes = get_hitboxes(record);
if (hitboxes.empty())
return;
auto force_safe_points = key_binds::get().get_key_bind_state(3) || g_cfg.player_list.force_safe_points[record->i];
auto best_damage = 0;
auto minimum_damage = get_minimum_damage(false, record->player->m_iHealth());
auto minimum_visible_damage = get_minimum_damage(true, record->player->m_iHealth());
std::vector <scan_point> points;
for (auto& hitbox : hitboxes)
{
points.emplace_back(scan_point(record->player->hitbox_position_matrix(hitbox, record->matrixes_data.main), hitbox, false));
auto current_points = get_points(record, hitbox);
for (auto& point : current_points)
{
if ((g_ctx.globals.eye_pos - final_target.data.point.point).Length() <= weapon_info->flRange)
{
point.safe = g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].prefer_safe_points ? hitbox_intersection(record->player, record->matrixes_data.first, hitbox, shoot_position, point.point) && hitbox_intersection(record->player, record->matrixes_data.second, hitbox, shoot_position, point.point) : hitbox_intersection(record->player, record->matrixes_data.first, hitbox, shoot_position, point.point) && hitbox_intersection(record->player, record->matrixes_data.zero, hitbox, shoot_position, point.point) && hitbox_intersection(record->player, record->matrixes_data.second, hitbox, shoot_position, point.point);
if (!(key_binds::get().get_key_bind_state(3) || g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].prefer_safe_points || g_cfg.player_list.force_safe_points[record->i]) || point.safe)
{
points.emplace_back(point);
}
}
}
}
if (points.empty())
return;
for (auto& point : points)
{
if ((g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].prefer_safe_points || force_safe_points) && data.point.safe && data.point.safe < point.safe)
continue;
auto fire_data = autowall::get().wall_penetration(shoot_position, point.point, record->player);
if (!fire_data.valid)
continue;
if (fire_data.damage < 1)
continue;
if (!fire_data.visible && !g_cfg.ragebot.autowall)
continue;
auto current_minimum_damage = fire_data.visible ? minimum_visible_damage : minimum_damage;
if (fire_data.damage >= current_minimum_damage && fire_data.damage >= best_damage)
{
if (!should_stop)
should_stop = true;
if (force_safe_points && !point.safe)
continue;
best_damage = fire_data.damage;
data.point = point;
data.visible = fire_data.visible;
data.damage = fire_data.damage;
data.hitbox = fire_data.hitbox;
}
}
}
std::vector <int> aim::get_hitboxes(adjust_data* record)
{
std::vector <int> hitboxes; //-V827
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].hitboxes[2]) {
hitboxes.emplace_back(HITBOX_STOMACH);
hitboxes.emplace_back(HITBOX_LOWER_CHEST);
}
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].hitboxes[0])
{
hitboxes.emplace_back(HITBOX_HEAD);
}
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].hitboxes[1]) {
hitboxes.emplace_back(HITBOX_UPPER_CHEST);
hitboxes.emplace_back(HITBOX_CHEST);
}
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].hitboxes[3])
{
hitboxes.emplace_back(HITBOX_RIGHT_UPPER_ARM);
hitboxes.emplace_back(HITBOX_LEFT_UPPER_ARM);
}
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].hitboxes[4])
{
hitboxes.emplace_back(HITBOX_RIGHT_THIGH);
hitboxes.emplace_back(HITBOX_LEFT_THIGH);
hitboxes.emplace_back(HITBOX_RIGHT_CALF);
hitboxes.emplace_back(HITBOX_LEFT_CALF);
}
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].hitboxes[5])
{
hitboxes.emplace_back(HITBOX_RIGHT_FOOT);
hitboxes.emplace_back(HITBOX_LEFT_FOOT);
}
return hitboxes;
}
std::vector <scan_point> aim::get_points(adjust_data* record, int hitbox, bool from_aim)
{
std::vector <scan_point> points;
auto model = record->player->GetModel();
if (!model)
return points;
auto hdr = m_modelinfo()->GetStudioModel(model);
if (!hdr)
return points;
auto set = hdr->pHitboxSet(record->player->m_nHitboxSet());
if (!set)
return points;
auto bbox = set->pHitbox(hitbox);
if (!bbox)
return points;
const auto mod = bbox->radius != -1.0f ? bbox->radius : 0.0f;
Vector max;
Vector min;
math::vector_transform(bbox->bbmax + mod, record->matrixes_data.main[bbox->bone], max);
math::vector_transform(bbox->bbmin - mod, record->matrixes_data.main[bbox->bone], min);
const auto center = (min + max) * 0.5f;
points.emplace_back(scan_point(center, hitbox, true));
if (!bbox->radius)
return points;
if (hitbox == HITBOX_NECK || hitbox == HITBOX_RIGHT_THIGH || hitbox == HITBOX_LEFT_THIGH || hitbox == HITBOX_RIGHT_CALF || hitbox == HITBOX_LEFT_CALF || hitbox == HITBOX_RIGHT_FOOT || hitbox == HITBOX_LEFT_FOOT || hitbox == HITBOX_RIGHT_HAND || hitbox == HITBOX_LEFT_HAND || hitbox == HITBOX_RIGHT_UPPER_ARM || hitbox == HITBOX_LEFT_UPPER_ARM || hitbox == HITBOX_RIGHT_FOREARM || hitbox == HITBOX_LEFT_FOREARM)
return points;
const auto cur_angles = math::calculate_angle(center, g_ctx.globals.eye_pos);
Vector forward;
math::angle_vectors(cur_angles, forward);
auto rs = 0.0f;
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].static_point_scale && g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].static_point_scale > 0) // run static pointscale
{
rs = bbox->radius * g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].static_point_scale;
}
else if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].static_point_scale && g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].static_point_scale < 1) //run dynamic pointscale
{
auto transformed_center = center;
math::vector_transform(transformed_center, record->matrixes_data.main[bbox->bone], transformed_center);
auto spread = g_ctx.globals.spread + g_ctx.globals.inaccuracy;
auto distance = transformed_center.DistTo(g_ctx.globals.eye_pos);
distance /= math::fast_sin(DEG2RAD(90.0f - RAD2DEG(spread)));
spread = math::fast_sin(spread);
auto radius = max(bbox->radius - distance * spread, 0.0f);
rs = bbox->radius * math::clamp(radius / bbox->radius, 0.0f, 1.0f);
}
if (rs < 0.2f)
return points;
const auto top = Vector(0, 0, 1) * rs;
const auto right = forward.Cross(Vector(0, 0, 1)) * rs;
const auto left = Vector(-right.x, -right.y, right.z);
if (hitbox == HITBOX_HEAD)
points.emplace_back(scan_point(center + top, hitbox, false));
points.emplace_back(scan_point(center + right, hitbox, false));
points.emplace_back(scan_point(center + left, hitbox, false));
return points;
}
static bool compare_targets(const scanned_target& first, const scanned_target& second)
{
return first.distance < second.distance;
}
void aim::find_best_target()
{
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].selection_type)
std::sort(scanned_targets.begin(), scanned_targets.end(), compare_targets);
for (auto& target : scanned_targets)
{
if (target.fov > (float)g_cfg.ragebot.field_of_view)
continue;
final_target = target;
final_target.record->adjust_player();
break;
}
}
bool rbot_SilentAim(Vector aim_angle)
{
if (!g_cfg.ragebot.silent_aim) {
m_engine()->SetViewAngles(aim_angle);
return true;
}
return false;
}
float rbot_Hitchance_correction()
{
if (g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].double_tap_hitchance)
{
return g_ctx.globals.double_tap_aim ? 0 : g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].hitchance_amount;
}
else if (!g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].double_tap_hitchance)
{
return g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].hitchance_amount;
}
}
static auto get_hitbox_name = [](int hitbox, bool shot_info = false) -> std::string
{
switch (hitbox)
{
case HITBOX_HEAD:
return shot_info ? crypt_str("Head") : crypt_str("head");
case HITBOX_LOWER_CHEST:
return shot_info ? crypt_str("Lower chest") : crypt_str("lower chest");
case HITBOX_CHEST:
return shot_info ? crypt_str("Chest") : crypt_str("chest");
case HITBOX_UPPER_CHEST:
return shot_info ? crypt_str("Upper chest") : crypt_str("upper chest");
case HITBOX_STOMACH:
return shot_info ? crypt_str("Stomach") : crypt_str("stomach");
case HITBOX_PELVIS:
return shot_info ? crypt_str("Pelvis") : crypt_str("pelvis");
case HITBOX_RIGHT_UPPER_ARM:
case HITBOX_RIGHT_FOREARM:
case HITBOX_RIGHT_HAND:
return shot_info ? crypt_str("Left arm") : crypt_str("left arm");
case HITBOX_LEFT_UPPER_ARM:
case HITBOX_LEFT_FOREARM:
case HITBOX_LEFT_HAND:
return shot_info ? crypt_str("Right arm") : crypt_str("right arm");
case HITBOX_RIGHT_THIGH:
case HITBOX_RIGHT_CALF:
return shot_info ? crypt_str("Left leg") : crypt_str("left leg");
case HITBOX_LEFT_THIGH:
case HITBOX_LEFT_CALF:
return shot_info ? crypt_str("Right leg") : crypt_str("right leg");
case HITBOX_RIGHT_FOOT:
return shot_info ? crypt_str("Left foot") : crypt_str("left foot");
case HITBOX_LEFT_FOOT:
return shot_info ? crypt_str("Right foot") : crypt_str("right foot");
}
};
bool aim::hit_chance(Vector angle, player_t* ent, float chance, int hitbox)
{
auto weap = (weapon_t*)(m_entitylist()->GetClientEntityFromHandle(g_ctx.local()->m_hActiveWeapon()));
if (!weap)
return false;
if (chance < 2.f)
return true;
auto weap_data = weap->get_csweapon_info();
if (!weap_data)
return false;
Vector forward, right, up = ZERO;
auto eye_position = g_ctx.local()->get_shoot_position();
math::angle_vectors(angle, &forward, &right, &up);
int TraceHits = 0;
int cNeededHits = static_cast<int>(128.f * (chance / 100.f));
weap->update_accuracy_penality();
float weap_sir = weap->get_spread();
float weap_inac = weap->get_inaccuracy();
auto recoil_index = weap->m_flRecoilSeed();
if (weap_sir <= 0.f)
return true;
for (int i = 0; i < 128; i++)
{
float a = math::random_float(0.f, 1.f);
float b = math::random_float(0.f, 6.2831855f);
float c = math::random_float(0.f, 1.f);
float d = math::random_float(0.f, 6.2831855f);
float inac = a * weap_inac;
float sir = c * weap_sir;
if (weap->m_iItemDefinitionIndex() == 64)
{
a = 1.f - a * a;
a = 1.f - c * c;
}
else if (weap->m_iItemDefinitionIndex() == 28 && recoil_index < 3.0f)
{
for (int i = 3; i > recoil_index; i--)
{
a *= a;
c *= c;
}
a = 1.0f - a;
c = 1.0f - c;
}
else if (!(g_ctx.local()->m_fFlags() & FL_ONGROUND) && weap->m_iItemDefinitionIndex() == 40) {
if (weap->get_inaccuracy() < 0.009f) {
return true;
}
}
Vector sirVec((cos(b) * inac) + (cos(d) * sir), (sin(b) * inac) + (sin(d) * sir), 0), direction;
direction.x = forward.x + (sirVec.x * right.x) + (sirVec.y * up.x);
direction.y = forward.y + (sirVec.x * right.y) + (sirVec.y * up.y);
direction.z = forward.z + (sirVec.x * right.z) + (sirVec.y * up.z);
direction.Normalize();
Vector viewAnglesSpread;
math::vector_angles(direction, up, viewAnglesSpread);
viewAnglesSpread.Normalize();
Vector viewForward;
math::angle_vectors(viewAnglesSpread, viewForward);
viewForward.NormalizeInPlace();
viewForward = g_ctx.local()->get_shoot_position() + (viewForward * weap_data->flRange);
trace_t tr;
Ray_t ray;
ray.Init(g_ctx.local()->get_shoot_position(), viewForward);
// glass fix xD
m_trace()->ClipRayToEntity(ray, MASK_SHOT | CONTENTS_GRATE | CONTENTS_WINDOW, ent, &tr);
if (tr.hit_entity == ent)
if (false) {
if (tr.hitgroup == get_hitgroup(hitbox))
++TraceHits;
}
else ++TraceHits;
int aimbot_accuracy_boost = 0;
// adding manual accuracy boost calculation here
if (static_cast<int>((static_cast<float>(TraceHits) / 128.f) * 100.f) >= chance) {
if (((static_cast<float>(TraceHits) / static_cast<float>(128.f)) >= (aimbot_accuracy_boost / 100.f)) || aimbot_accuracy_boost <= 1.f)
return true;
}
if ((128 - i + TraceHits) < cNeededHits)
return false;
}
return false;
}
void aim::fire(CUserCmd* cmd)
{
if (!g_cfg.ragebot.autoshoot && !(cmd->m_buttons & IN_ATTACK) || !g_ctx.globals.weapon->can_fire(true)) //dont run if we cannot fire / menu var missing
return;
//setup some variables
auto aim_angle = math::calculate_angle(g_ctx.globals.eye_pos, final_target.data.point.point).Clamp(); //Set aim angle to our target_aim_points
auto backtrack_ticks = 0;
auto net_channel_info = m_engine()->GetNetChannelInfo();
static bool rbot_shotfired = false;
rbot_SilentAim(aim_angle); //run silent aim
if (net_channel_info)
{
auto original_tickbase = g_ctx.globals.backup_tickbase;
if (misc::get().double_tap_enabled && misc::get().double_tap_key)
original_tickbase = g_ctx.globals.backup_tickbase + g_ctx.globals.weapon->get_max_tickbase_shift();
static auto sv_maxunlag = m_cvar()->FindVar(crypt_str("sv_maxunlag"));
auto correct = math::clamp(net_channel_info->GetLatency(FLOW_OUTGOING) + net_channel_info->GetLatency(FLOW_INCOMING) + util::get_interpolation(), 0.0f, sv_maxunlag->GetFloat());
auto delta_time = correct - (TICKS_TO_TIME(original_tickbase) - final_target.record->simulation_time);
backtrack_ticks = TIME_TO_TICKS(fabs(delta_time));
}
bool final_hc = hit_chance(aim_angle, final_target.record->player, rbot_Hitchance_correction(), final_target.data.hitbox);
//properly done autoscope
if (final_hc && g_cfg.ragebot.autoscope && g_cfg.ragebot.autoscope == 0)
{
auto is_zoomable_weapon = g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_SCAR20 || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_G3SG1 || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_SSG08 || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_AWP || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_AUG || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_SG553;
if (is_zoomable_weapon)
{
cmd->m_buttons |= IN_ATTACK2;
}
}
else if (g_cfg.ragebot.autoscope && g_cfg.ragebot.autoscope > 0)
{
auto is_zoomable_weapon = g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_SCAR20 || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_G3SG1 || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_SSG08 || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_AWP || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_AUG || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_SG553;
if (is_zoomable_weapon)
{
cmd->m_buttons |= IN_ATTACK2;
}
}
if (final_hc && g_ctx.globals.weapon->can_fire(true)) //if we reached our hitchance ammount then aim and shoot
{
cmd->m_viewangles = aim_angle;
cmd->m_buttons |= IN_ATTACK;
cmd->m_tickcount = TIME_TO_TICKS(final_target.record->simulation_time + util::get_interpolation());
//store some info
player_info_t player_info;
m_engine()->GetPlayerInfo(final_target.record->i, &player_info);
last_target_index = final_target.record->i;
last_shoot_position = g_ctx.globals.eye_pos;
last_target[last_target_index] = Last_target{ *final_target.record, final_target.data, final_target.distance };
std::stringstream rbot_log;
static bool exp_state = false;
auto shot = &g_ctx.shots.emplace_back();
shot->last_target = last_target_index;
shot->side = final_target.record->side;
shot->fire_tick = m_globals()->m_tickcount;
shot->shot_info.target_name = player_info.szName;
shot->shot_info.client_hitbox = get_hitbox_name(final_target.data.hitbox, true);
shot->shot_info.client_damage = final_target.data.damage;
shot->shot_info.hitchance = final_hc;
shot->shot_info.backtrack_ticks = backtrack_ticks;
shot->shot_info.aim_point = final_target.data.point.point;
g_ctx.globals.aimbot_working = true;
g_ctx.globals.revolver_working = false;
g_ctx.globals.last_aimbot_shot = m_globals()->m_tickcount;
}
}
int aim::hitchance(const Vector& aim_angle)
{
auto final_hitchance = 0;
auto weapon_info = g_ctx.globals.weapon->get_csweapon_info();
if (!weapon_info)
return final_hitchance;
if ((g_ctx.globals.eye_pos - final_target.data.point.point).Length() > weapon_info->flRange)
return final_hitchance;
auto forward = ZERO;
auto right = ZERO;
auto up = ZERO;
math::angle_vectors(aim_angle, &forward, &right, &up);
math::fast_vec_normalize(forward);
math::fast_vec_normalize(right);
math::fast_vec_normalize(up);
auto is_special_weapon = g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_AWP || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_G3SG1 || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_SCAR20 || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_SSG08;
auto inaccuracy = weapon_info->flInaccuracyStand;
if (g_ctx.local()->m_fFlags() & FL_DUCKING)
{
if (is_special_weapon)
inaccuracy = weapon_info->flInaccuracyCrouchAlt;
else
inaccuracy = weapon_info->flInaccuracyCrouch;
}
else if (is_special_weapon)
inaccuracy = weapon_info->flInaccuracyStandAlt;
if (g_ctx.globals.inaccuracy - 0.000001f < inaccuracy)
final_hitchance = 101;
else
{
static auto setup_spread_values = true;
static float spread_values[340][6];
if (setup_spread_values)
{
setup_spread_values = false;
for (auto i = 0; i < 340; ++i)
{
math::random_seed(i + 1);
auto a = math::random_float(0.0f, 1.0f);
auto b = math::random_float(0.0f, DirectX::XM_2PI);
auto c = math::random_float(0.0f, 1.0f);
auto d = math::random_float(0.0f, DirectX::XM_2PI);
spread_values[i][0] = a;
spread_values[i][1] = c;
auto sin_b = 0.0f, cos_b = 0.0f;
DirectX::XMScalarSinCos(&sin_b, &cos_b, b);
auto sin_d = 0.0f, cos_d = 0.0f;
DirectX::XMScalarSinCos(&sin_d, &cos_d, d);
spread_values[i][2] = sin_b;
spread_values[i][3] = cos_b;
spread_values[i][4] = sin_d;
spread_values[i][5] = cos_d;
}
}
auto hits = 0;
for (auto i = 0; i < 340; ++i)
{
auto inaccuracy = spread_values[i][0] * g_ctx.globals.inaccuracy;
auto spread = spread_values[i][1] * g_ctx.globals.spread;
auto spread_x = spread_values[i][3] * inaccuracy + spread_values[i][5] * spread;
auto spread_y = spread_values[i][2] * inaccuracy + spread_values[i][4] * spread;
auto direction = ZERO;
direction.x = forward.x + right.x * spread_x + up.x * spread_y;
direction.y = forward.y + right.y * spread_x + up.y * spread_y;
direction.z = forward.z + right.z * spread_x + up.z * spread_y; //-V778
auto end = g_ctx.globals.eye_pos + direction * weapon_info->flRange;
if (hitbox_intersection(final_target.record->player, final_target.record->matrixes_data.main, final_target.data.hitbox, g_ctx.globals.eye_pos, end))
++hits;
}
final_hitchance = (int)((float)hits / 3.4f);
}
if (g_ctx.globals.double_tap_aim)
return final_hitchance;
auto damage = 0;
auto high_accuracy_weapon = g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_AWP || g_ctx.globals.weapon->m_iItemDefinitionIndex() == WEAPON_SSG08;
auto spread = g_ctx.globals.spread + g_ctx.globals.inaccuracy;
for (auto i = 1; i <= 6; ++i)
{
for (auto j = 0; j < 8; ++j)
{
auto current_spread = spread * ((float)i / 6.0f);
auto direction_cos = 0.0f;
auto direction_sin = 0.0f;
DirectX::XMScalarSinCos(&direction_cos, &direction_sin, (float)j / 8.0f * DirectX::XM_2PI);
auto spread_x = direction_cos * current_spread;
auto spread_y = direction_sin * current_spread;
auto direction = ZERO;
direction.x = forward.x + spread_x * right.x + spread_y * up.x;
direction.y = forward.y + spread_x * right.y + spread_y * up.y;
direction.z = forward.z + spread_x * right.z + spread_y * up.z;
auto end = g_ctx.globals.eye_pos + direction * weapon_info->flRange;
if (hitbox_intersection(final_target.record->player, final_target.record->matrixes_data.main, final_target.data.hitbox, g_ctx.globals.eye_pos, end))
{
auto fire_data = autowall::get().wall_penetration(g_ctx.globals.eye_pos, end, final_target.record->player);
auto valid_hitbox = true;
if (final_target.data.hitbox == HITBOX_HEAD && fire_data.hitbox != HITBOX_HEAD)
valid_hitbox = false;
if (fire_data.valid && fire_data.damage >= 1 && valid_hitbox)
damage += high_accuracy_weapon ? fire_data.damage : 1;
}
}
}
return (float)damage / 48.0f >= (float)g_cfg.ragebot.weapon[g_ctx.globals.current_weapon].hitchance_amount * 0.01f ? final_hitchance : 0;
}
static int clip_ray_to_hitbox(const Ray_t& ray, mstudiobbox_t* hitbox, matrix3x4_t& matrix, trace_t& trace)
{
static auto fn = util::FindSignature(crypt_str("client.dll"), crypt_str("55 8B EC 83 E4 F8 F3 0F 10 42"));
trace.fraction = 1.0f;
trace.startsolid = false;
return reinterpret_cast <int(__fastcall*)(const Ray_t&, mstudiobbox_t*, matrix3x4_t&, trace_t&)> (fn)(ray, hitbox, matrix, trace);
}
bool aim::hitbox_intersection(player_t* e, matrix3x4_t* matrix, int hitbox, const Vector& start, const Vector& end, float* safe)
{
auto model = e->GetModel();
if (!model)
return false;
auto studio_model = m_modelinfo()->GetStudioModel(model);
if (!studio_model)
return false;
auto studio_set = studio_model->pHitboxSet(e->m_nHitboxSet());
if (!studio_set)
return false;
auto studio_hitbox = studio_set->pHitbox(hitbox);
if (!studio_hitbox)
return false;
trace_t trace;
Ray_t ray;
ray.Init(start, end);
auto intersected = clip_ray_to_hitbox(ray, studio_hitbox, matrix[studio_hitbox->bone], trace) >= 0;
if (!safe)
return intersected;
Vector min, max;
math::vector_transform(studio_hitbox->bbmin, matrix[studio_hitbox->bone], min);
math::vector_transform(studio_hitbox->bbmax, matrix[studio_hitbox->bone], max);
auto center = (min + max) * 0.5f;
auto distance = center.DistTo(end);
if (distance > *safe)
*safe = distance;
return intersected;
}
Код:
#pragma once
#include "..\..\includes.hpp"
#include "..\lagcompensation\animation_system.h"
class target
{
public:
player_t* e;
adjust_data* last_record;
adjust_data* history_record;
target()
{
e = nullptr;
last_record = nullptr;
history_record = nullptr;
}
target(player_t* e, adjust_data* last_record, adjust_data* history_record) //-V818
{
this->e = e;
this->last_record = last_record;
this->history_record = history_record;
}
};
class scan_point
{
public:
Vector point;
int hitbox;
bool center;
float safe;
scan_point()
{
point.Zero();
hitbox = -1;
center = false;
safe = 0.0f;
}
scan_point(const Vector& point, const int& hitbox, const bool& center) //-V818 //-V730
{
this->point = point;
this->hitbox = hitbox;
this->center = center;
}
void reset()
{
point.Zero();
hitbox = -1;
center = false;
safe = 0.0f;
}
};
class scan_data
{
public:
scan_point point;
bool visible;
int damage;
int hitbox;
scan_data()
{
reset();
}
void reset()
{
point.reset();
visible = false;
damage = -1;
hitbox = -1;
}
bool valid()
{
return damage >= 1 && hitbox != -1;
}
};
struct Last_target
{
adjust_data record;
scan_data data;
float distance;
};
class scanned_target
{
public:
adjust_data* record;
scan_data data;
float fov;
float distance;
int health;
scanned_target()
{
reset();
}
scanned_target(const scanned_target& data) //-V688
{
this->record = data.record;
this->data = data.data;
this->fov = data.fov;
this->distance = data.distance;
this->health = data.health;
}
scanned_target& operator=(const scanned_target& data) //-V688
{
this->record = data.record;
this->data = data.data;
this->fov = data.fov;
this->distance = data.distance;
this->health = data.health;
return *this;
}
scanned_target(adjust_data* record, const scan_data& data) //-V688 //-V818
{
this->record = record;
this->data = data;
Vector viewangles;
m_engine()->GetViewAngles(viewangles);
auto aim_angle = math::calculate_angle(g_ctx.globals.eye_pos, data.point.point); //-V688
auto fov = math::get_fov(viewangles, aim_angle); //-V688
this->fov = fov;
this->distance = g_ctx.globals.eye_pos.DistTo(data.point.point);
this->health = record->player->m_iHealth();
}
void reset()
{
record = nullptr;
data.reset();
fov = 0.0f;
distance = 0.0f;
health = 0;
}
};
class aim : public singleton <aim>
{
void automatic_revolver(CUserCmd* cmd);
void prepare_targets();
adjust_data* get_record(std::deque <adjust_data>* records, bool history);
int get_minimum_damage(bool visible, int health);
void scan_targets();
bool automatic_stop(CUserCmd* cmd);
void find_best_target();
bool hit_chance(Vector angle, player_t* ent, float chance, int hitbox);
void fire(CUserCmd* cmd);
int hitchance(const Vector& aim_angle);
std::vector <scanned_target> scanned_targets;
scanned_target final_target;
public:
void run(CUserCmd* cmd);
void scan(adjust_data* record, scan_data& data, const Vector& shoot_position = g_ctx.globals.eye_pos);
std::vector<int> get_hitboxes(adjust_data* record);
std::vector <scan_point> get_points(adjust_data* record, int hitbox, bool from_aim = true);
bool hitbox_intersection(player_t* e, matrix3x4_t* matrix, int hitbox, const Vector& start, const Vector& end, float* safe = nullptr);
std::vector <target> targets;
std::vector <adjust_data> backup;
int last_target_index = -1;
Last_target last_target[65];
Vector last_shoot_position;
bool should_stop;
};