Вопрос Есть дефолтный легит бот легендвара, но он криво работает на игроков в движении

Начинающий
Статус
Оффлайн
Регистрация
9 Авг 2019
Сообщения
164
Реакции[?]
10
Поинты[?]
1K
В общем, если цель находится в движении, то он промажет (в 90% случаев, особенно с autofire'ом), такое чувство, будто бы в бектрек стреляет

Как можно это исправить?

legitbot.cpp

C++:
#include "legitbot.h"
#include "..\lagcompensation\animation_system.h"
#include "..\autowall\autowall.h"

bool IsNotTarget(player_t* e)
{
    if (!e)
        return true;

    if (e == g_ctx.local())
        return true;

    if (e->m_iHealth() <= 0)
        return true;

    if (e->m_bGunGameImmunity())
        return true;

    if (e->m_fFlags() & FL_FROZEN)
        return true;

    return false;
}

void legit_bot::do_smooth(const Vector& currentAngle, const Vector& aimAngle, Vector& angle)
{
    auto smooth_value = smooth_t;
    if (smooth_value <= 1) {
        return;
    }

    static auto recoil_scale = m_cvar()->FindVar("weapon_recoil_scale")->GetFloat();
    aim_punch = g_ctx.local()->m_aimPunchAngle() * recoil_scale;
    aim_punch *= (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].rcs / 100.f);

    Vector delta = aimAngle - (currentAngle + aim_punch);
    math::normalize_angles(delta);

    if (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].smooth_type == 1) {
        float randomize = math::random_float(-0.2f, 0.2f);
        smooth_value = (m_globals()->m_intervalpertick * 64.0f) * (smooth_value + (randomize * smooth_value));
        smooth_value = math::clamp(smooth_value, m_globals()->m_intervalpertick * 64.0f * smooth_t, 13.f);
    }
    else {
        smooth_value = (m_globals()->m_intervalpertick * 64.0f) * smooth_value;
    }

    delta /= smooth_value;
    angle = currentAngle + delta;
    math::normalize_angles(angle);
}


float dynamic_fov_to(float distance, const Vector& angle, const Vector& viewangles) {
    Vector aimingAt;
    math::angle_vectors(viewangles, aimingAt);
    aimingAt *= distance;
    Vector aimAt;
    math::angle_vectors(angle, aimAt);
    aimAt *= distance;
    return aimingAt.DistTo(aimAt) / 5;
}

float static_fov_to(const Vector& viewAngle, const Vector& aimAngle) {
    Vector delta = aimAngle - viewAngle;
    math::normalize_angles(delta);
    return sqrtf(powf(delta.x, 2.0f) + powf(delta.y, 2.0f));
}

bool in_smoke(const Vector& in, const Vector& out)
{
    static auto LineGoesThroughSmokeFn = (bool(*)(Vector vStartPos, Vector vEndPos))util::FindSignature(crypt_str("client.dll"), crypt_str("55 8B EC 83 EC 08 8B 15 ? ? ? ? 0F 57 C0"));
    return LineGoesThroughSmokeFn(in, out);
}

void legit_bot::createmove(CUserCmd* cmd)
{
    if (!g_cfg.legitbot.enabled)
        return;

    // rata-ta-ta-ta range
    calc_fov();

    bool should_do_rcs = false;
    static bool started_scope = false;
    static bool started_unscope = false;
    static int scope_delay = 0;
    static int autofire_delay = 0;

    if (g_ctx.globals.weapon->is_non_aim() || g_ctx.globals.weapon->m_iClip1() <= 0)
    {
        target = nullptr;
        point = Vector(0, 0, 0);
        started_scope = false;
        started_unscope = false;
        scope_delay = 0;
        autofire_delay = 0;
        return;
    }

    if (!g_ctx.globals.weapon->is_sniper())
    {
        started_scope = false;
        started_unscope = false;
        scope_delay = 0;
    }

    if (g_ctx.globals.weapon->is_sniper() && started_unscope && g_ctx.globals.weapon->can_fire(false) && g_ctx.local()->m_bIsScoped())
    {
        scope_delay = 0;
        cmd->m_buttons |= IN_ATTACK2;

        if (g_ctx.globals.weapon->m_zoomLevel() == 3)
            started_unscope = false;

        return;
    }

    // rata-ta-ta-ta speed
    calc_smooth();

    // my pistols do pew-pew
    if (g_cfg.legitbot.autopistol)
        auto_pistol(cmd);

    if (target_switch_delay > m_globals()->m_realtime)
    {
        point = Vector(0, 0, 0);
        target = nullptr;
        autofire_delay = 0;

        if ((key_binds::get().get_key_bind_state(1) || key_binds::get().get_key_bind_state(0)) && !g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].rcs_type)
            do_rcs(cmd);

        return;
    }

    // find the closest enemy to our crosshair
    target_index = -1;
    target = nullptr;
    find_target();

    if (!target->valid(false, true))
        target = nullptr;

    // rata-ta-ta-ta control
    if ((key_binds::get().get_key_bind_state(1) || key_binds::get().get_key_bind_state(0)) && !g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].rcs_type)
        should_do_rcs = true;

    if (!target)
    {
        point = Vector(0, 0, 0);
        autofire_delay = 0;

        if (should_do_rcs)
            do_rcs(cmd);

        return;
    }

    // legitbot key check
    if (!key_binds::get().get_key_bind_state(1) && !key_binds::get().get_key_bind_state(0))
    {
        autofire_delay = 0;

        if (should_do_rcs)
            do_rcs(cmd);

        return;
    }

    // point to rata-ta-ta-ta
    auto is_silent = !g_ctx.local()->m_iShotsFired() && g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].silent_fov;
    point = Vector(0, 0, 0);
    find_best_point(cmd, fov_t);

    if (point == Vector(0, 0, 0))
    {
        autofire_delay = 0;

        if (should_do_rcs)
            do_rcs(cmd);

        if (is_silent)
        {
            find_best_point(cmd, g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].silent_fov);
            if (point == Vector(0, 0, 0))
                return;
        }
        else
            return;
    }

    // is enemy in smoke?
    if (!g_cfg.legitbot.do_if_enemy_in_smoke && in_smoke(g_ctx.globals.eye_pos, target->hitbox_position(0)))
    {
        autofire_delay = 0;

        if (should_do_rcs)
            do_rcs(cmd);

        return;
    }

    // are we flashed?
    if (!g_cfg.legitbot.do_if_local_flashed && g_ctx.local()->m_flFlashDuration() >= 0.1f)
    {
        autofire_delay = 0;

        if (should_do_rcs)
            do_rcs(cmd);

        return;
    }

    // is local in air?
    if (!g_cfg.legitbot.do_if_local_in_air && !(g_ctx.local()->m_fFlags() & FL_ONGROUND))
    {
        if (should_do_rcs)
            do_rcs(cmd);

        return;
    }

    if (!g_ctx.local()->m_iShotsFired() && key_binds::get().get_key_bind_state(0) && autofire_delay < g_cfg.legitbot.autofire_delay)
    {
        autofire_delay += 1;
        return;
    }
    else if (!g_ctx.local()->m_iShotsFired())
        autofire_delay = 0;

    auto weapon = g_ctx.globals.weapon;

    if (g_cfg.legitbot.autoscope && (!g_ctx.local()->m_bIsScoped() || (started_scope && scope_delay > 9)) && weapon->is_sniper())
    {
        cmd->m_buttons |= IN_ATTACK2;
        cmd->m_buttons &= ~IN_ATTACK;

        started_scope = true;
        scope_delay += 1;

        return;
    }

    scope_delay = 0;
    started_scope = false;

    // are we not in scope or not ready to shoot after scope and we dont use autoscope?
    if (weapon->is_sniper() &&
        g_cfg.legitbot.sniper_in_zoom_only && !g_cfg.legitbot.autoscope && !g_ctx.local()->m_bIsScoped())
    {
        if (should_do_rcs)
            do_rcs(cmd);

        return;
    }

    auto is_silent_s = !g_ctx.local()->m_iShotsFired() && g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].silent_fov && target_fov <= g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].silent_fov;

    if (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].auto_stop)
        cmd->m_forwardmove = cmd->m_sidemove = 0;

    aim_angle = math::calculate_angle(g_ctx.globals.eye_pos, point).Clamp();

    if (!is_silent_s)
        do_smooth(cmd->m_viewangles, aim_angle, aim_angle);

    math::normalize_angles(aim_angle);

    cmd->m_viewangles = aim_angle;
    cmd->m_tickcount = TIME_TO_TICKS(target->m_flSimulationTime() + util::get_interpolation());

    if (!is_silent_s)
        m_engine()->SetViewAngles(cmd->m_viewangles);

    if (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].rcs_type || should_do_rcs)
        do_rcs(cmd);

    auto hitchanced = hitchance(target, aim_angle, point, targets[target->EntIndex()].hitbox) >= g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].autofire_hitchance;

    if (key_binds::get().get_key_bind_state(0) && g_ctx.globals.weapon->can_fire(true) && hitchanced)
        cmd->m_buttons |= IN_ATTACK;

    if (cmd->m_buttons & IN_ATTACK && !started_unscope)
        if (g_ctx.globals.weapon->is_sniper() && g_cfg.legitbot.unscope)
            started_unscope = true;
}

void legit_bot::calc_fov()
{
    if (g_ctx.local()->m_iShotsFired() < 2)
        fov_t = g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].fov;

    else if (g_ctx.local()->m_iShotsFired() >= 2 && g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].custom_rcs_fov > 0.f)
        fov_t = g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].custom_rcs_fov;

    else
        fov_t = g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].fov;
}

void legit_bot::calc_smooth()
{
    if (g_ctx.local()->m_iShotsFired() < 2)
        smooth_t = g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].smooth;

    else if (g_ctx.local()->m_iShotsFired() >= 2 && g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].custom_rcs_smooth >= 1.f)
        smooth_t = g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].custom_rcs_smooth;

    else
        smooth_t = g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].smooth;
}

void legit_bot::do_rcs(CUserCmd* cmd)
{
    auto weapon = g_ctx.globals.weapon;
    static Vector prev_punch = { 0.0f, 0.0f, 0.0f };

    if (weapon->m_iItemDefinitionIndex() == WEAPON_REVOLVER
        || g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].rcs <= 0
        || weapon->is_non_aim()
        || g_ctx.local()->m_iShotsFired() < 2)
    {
        prev_punch = Vector(0, 0, 0);
        return;
    }


    static auto recoil_scale = m_cvar()->FindVar("weapon_recoil_scale")->GetFloat();
    aim_punch = g_ctx.local()->m_aimPunchAngle() * recoil_scale;

    // rcs in %
    aim_punch *= (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].rcs / 100.f);

    auto rcs = cmd->m_viewangles += (prev_punch - aim_punch);
    math::normalize_angles(rcs);
    m_engine()->SetViewAngles(rcs);

    prev_punch = aim_punch;
}

void legit_bot::auto_pistol(CUserCmd* cmd)
{
    auto weapon = g_ctx.globals.weapon;

    if (!weapon->is_pistol()
        || weapon->m_iItemDefinitionIndex() == WEAPON_REVOLVER
        || weapon->m_iClip1() <= 0)
        return;

    static bool is_firing = false;

    if (cmd->m_buttons & IN_ATTACK) {
        if (is_firing) {
            cmd->m_buttons &= ~IN_ATTACK;
        }
    }

    is_firing = cmd->m_buttons & IN_ATTACK;
}

void legit_bot::find_best_point(CUserCmd* cmd, float fov_v)
{
    static auto recoil_scale = m_cvar()->FindVar("weapon_recoil_scale")->GetFloat();
    aim_punch = g_ctx.local()->m_aimPunchAngle() * recoil_scale;
    aim_punch *= (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].rcs / 100.f);

    auto best_fov = fov_v;

    // if nearest aimbot method
    if (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].priority == 0)
    {
        for (auto bone : { HITBOX_HEAD, HITBOX_PELVIS, HITBOX_CHEST, HITBOX_UPPER_CHEST, HITBOX_STOMACH })
        {
            float distance = 0.f;
            float fov = FLT_MAX;
            Vector ang = Vector(0, 0, 0);

            auto bone_pos = target->hitbox_position(bone);
            math::vector_angles(bone_pos - g_ctx.globals.eye_pos, ang);
            math::normalize_angles(ang);
            distance = g_ctx.globals.eye_pos.DistTo(bone_pos);

            if (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].fov_type == 1)
                fov = dynamic_fov_to(distance, ang, cmd->m_viewangles + aim_punch);
            else
                fov = static_fov_to(cmd->m_viewangles + aim_punch, ang);

            if (fov > best_fov)
                continue;
           
            auto fire_data = autowall::get().wall_penetration(g_ctx.globals.eye_pos, bone_pos, target);

            if (!fire_data.visible && !g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].awall_dmg)
                continue;

            if (!fire_data.visible && g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].awall_dmg > 0 && fire_data.damage < g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].awall_dmg)
                continue;
               
            best_fov = fov;
            point = bone_pos;
            target_fov = fov;
            targets[target->EntIndex()].hitbox = bone;
        }
    }
    else if (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].priority == 1) // head only
    {
        float distance = 0.f;
        float fov = FLT_MAX;
        Vector ang = Vector(0, 0, 0);

        auto bone_pos = target->hitbox_position(0);
        math::vector_angles(bone_pos - g_ctx.globals.eye_pos, ang);
        math::normalize_angles(ang);
        distance = g_ctx.globals.eye_pos.DistTo(bone_pos);

        if (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].fov_type == 1)
            fov = dynamic_fov_to(distance, ang, cmd->m_viewangles + aim_punch);
        else
            fov = static_fov_to(cmd->m_viewangles + aim_punch, ang);

        if (fov > best_fov)
            return;

        auto fire_data = autowall::get().wall_penetration(g_ctx.globals.eye_pos, bone_pos, target);

        if (!fire_data.visible && !g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].awall_dmg)
            return;

        if (!fire_data.visible && g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].awall_dmg > 0 && fire_data.damage < g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].awall_dmg)
            return;

        best_fov = fov;
        point = bone_pos;
        target_fov = fov;
        targets[target->EntIndex()].hitbox = 0;
    }
    else if (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].priority == 2) // nearest body
    {
        for (auto bone : { HITBOX_PELVIS, HITBOX_CHEST, HITBOX_UPPER_CHEST, HITBOX_STOMACH }) {
            float distance = 0.f;
            float fov = FLT_MAX;
            Vector ang = Vector(0, 0, 0);

            auto bone_pos = target->hitbox_position(bone);
            math::vector_angles(bone_pos - g_ctx.globals.eye_pos, ang);
            math::normalize_angles(ang);
            distance = g_ctx.globals.eye_pos.DistTo(bone_pos);

            if (g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].fov_type == 1)
                fov = dynamic_fov_to(distance, ang, cmd->m_viewangles + aim_punch);
            else
                fov = static_fov_to(cmd->m_viewangles + aim_punch, ang);

            if (fov > best_fov)
                continue;

            auto fire_data = autowall::get().wall_penetration(g_ctx.globals.eye_pos, bone_pos, target);

            if (!fire_data.visible && !g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].awall_dmg)
                continue;

            if (!fire_data.visible && g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].awall_dmg > 0 && fire_data.damage < g_cfg.legitbot.weapon[g_ctx.globals.current_weapon].awall_dmg)
                continue;

            best_fov = fov;
            point = bone_pos;
            target_fov = fov;
            targets[target->EntIndex()].hitbox = bone;
        }
    }
}

void legit_bot::find_target()
{
    for (auto i = 0; i < 65; ++i)
    {
        targets[i].fov = 0.0f;
        targets[i].hitbox = -1;
    }

    auto best_fov = FLT_MAX;

    for (auto i = 1; i <= m_globals()->m_maxclients; ++i)
    {
        auto e = static_cast<player_t*>(m_entitylist()->GetClientEntity(i));

        if (IsNotTarget(e))
            continue;

        if (!g_cfg.legitbot.friendly_fire && e->m_iTeamNum() == g_ctx.local()->m_iTeamNum())
            continue;

        Vector engine_angles;
        m_engine()->GetViewAngles(engine_angles);
        targets[i].fov = math::get_fov(engine_angles, math::calculate_angle(g_ctx.globals.eye_pos, e->hitbox_position(HITBOX_CHEST)));

        if (targets[i].fov < best_fov)
        {
            best_fov = targets[i].fov;
            target = e;
            target_index = i;
        }
    }
}

int legit_bot::hitchance(player_t* target, const Vector& aim_angle, const Vector& point, int hitbox) //-V688
{
    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 - 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[256][6];

        if (setup_spread_values)
        {
            setup_spread_values = false;

            for (auto i = 0; i < 256; ++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 < 256; ++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(target, target->m_CachedBoneData().Base(), hitbox, g_ctx.globals.eye_pos, end))
                ++hits;
        }

        final_hitchance = (int)((float)hits / 2.56f);
    }

    return final_hitchance;
}

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 legit_bot::hitbox_intersection(player_t* e, matrix3x4_t* matrix, int hitbox, const Vector& start, const Vector& end)
{
    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);

    return clip_ray_to_hitbox(ray, studio_hitbox, matrix[studio_hitbox->bone], trace) >= 0;
}
legitbot.h


C++:
#pragma once

#include "..\..\includes.hpp"
#include "..\..\sdk\structs.hpp"

struct target_info
{
    float fov;
    int hitbox;
};

class legit_bot : public singleton <legit_bot>
{
public:
    void createmove(CUserCmd* cmd);

    void find_target();
    void find_best_point(CUserCmd* cmd, float fov);

    void auto_pistol(CUserCmd* cmd);
    void do_rcs(CUserCmd* cmd);
    void calc_fov();
    void calc_smooth();
    void do_smooth(const Vector& currentAngle, const Vector& aimAngle, Vector& angle);
    int hitchance(player_t* target, const Vector& aim_angle, const Vector& point, int hitbox);
    bool hitbox_intersection(player_t* e, matrix3x4_t* matrix, int hitbox, const Vector& start, const Vector& end);
    player_t* target;
    int tickcount = -1;
    int target_index = -1;
    float target_switch_delay;
private:
    target_info targets[65];
    float target_fov;
    float fov_t;
    float smooth_t;
    float reaction_t;
    Vector point = Vector(0, 0, 0);
    Vector aim_punch = Vector(0, 0, 0);
    Vector aim_angle = Vector(0, 0, 0);
};
 
Сверху Снизу