Исходник Proper converted qo0 autowall to lw

Забаненный
Статус
Оффлайн
Регистрация
2 Июн 2020
Сообщения
461
Реакции[?]
80
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Код:
#include "autowall.h"

bool autowall::is_breakable_entity(IClientEntity* e)
{
    if (!e || !e->EntIndex())
        return false;

    static auto is_breakable = util::FindSignature(crypt_str("client.dll"), crypt_str("55 8B EC 51 56 8B F1 85 F6 74 68"));

    auto take_damage = *(uintptr_t*)((uintptr_t)is_breakable + 0x26);
    auto backup = *(uint8_t*)((uintptr_t)e + take_damage);

    auto client_class = e->GetClientClass();
    auto network_name = client_class->m_pNetworkName;

    if (!strcmp(network_name, "CBreakableSurface"))
        *(uint8_t*)((uintptr_t)e + take_damage) = DAMAGE_YES;
    else if (!strcmp(network_name, "CBaseDoor") || !strcmp(network_name, "CDynamicProp"))
        *(uint8_t*)((uintptr_t)e + take_damage) = DAMAGE_NO;

    using Fn = bool(__thiscall*)(IClientEntity*);
    auto result = ((Fn)is_breakable)(e);

    *(uint8_t*)((uintptr_t)e + take_damage) = backup;
    return result;
}

void autowall::scale_damage(const int hit_group, player_t* entity, const float weapon_armor_ratio, const float weapon_headshot_multiplier, float& damage) {
    const auto heavy_armor = entity->m_bHasHeavyArmor();

    static auto mp_damage_scale_ct_head = m_cvar()->FindVar(crypt_str("mp_damage_scale_ct_head"));
    static auto mp_damage_scale_t_head = m_cvar()->FindVar(crypt_str("mp_damage_scale_t_head"));

    static auto mp_damage_scale_ct_body = m_cvar()->FindVar(crypt_str("mp_damage_scale_ct_body"));
    static auto mp_damage_scale_t_body = m_cvar()->FindVar(crypt_str("mp_damage_scale_t_body"));

    auto head_damage_scale = entity->m_iTeamNum() == 3 ? mp_damage_scale_ct_head->GetFloat() : mp_damage_scale_t_head->GetFloat();
    auto body_damage_scale = entity->m_iTeamNum() == 3 ? mp_damage_scale_ct_body->GetFloat() : mp_damage_scale_t_body->GetFloat();

    if (heavy_armor)
        head_damage_scale *= 0.5f;

    switch (hit_group) {
    case HITGROUP_HEAD:
        damage *= weapon_headshot_multiplier * head_damage_scale;
        break;
    case HITGROUP_CHEST:
    case HITGROUP_LEFTARM:
    case HITGROUP_RIGHTARM:
        damage *= body_damage_scale;
        break;
    case HITGROUP_STOMACH:
        damage *= 1.25f * body_damage_scale;
        break;
    case HITGROUP_LEFTLEG:
    case HITGROUP_RIGHTLEG:
        damage *= 0.75f * body_damage_scale;
        break;
    default:
        break;
    }

    auto is_armored = [&hit_group]() -> bool {
        switch (hit_group) {
        case HITGROUP_HEAD:
        case HITGROUP_GENERIC:
        case HITGROUP_CHEST:
        case HITGROUP_STOMACH:
        case HITGROUP_LEFTARM:
        case HITGROUP_RIGHTARM:
        case HITGROUP_LEFTLEG:
        case HITGROUP_RIGHTLEG:
        case HITGROUP_GEAR:
            return true;
        default:
            return false;
        }
    };

    if (entity->m_ArmorValue() > 0 && is_armored()) {
        float heavy_armor_bonus = 1.f, armor_bonus = 0.5f, armor_ratio = weapon_armor_ratio * 0.5f;

        if (heavy_armor) {
            heavy_armor_bonus = 0.25f;
            armor_bonus = 0.33f;
            armor_ratio *= 0.20f;
        }

        float damage_to_health = damage * armor_ratio;
        if (const auto damage_to_armor = (damage - damage_to_health) * (heavy_armor_bonus * armor_bonus); damage_to_armor > static_cast<float>(entity->m_ArmorValue()))
            damage_to_health = damage - static_cast<float>(entity->m_ArmorValue()) / armor_bonus;
    }
}

void autowall::clip_trace_to_player(const Vector& start, const Vector& end, const unsigned int mask, CTraceFilter* filter, CGameTrace* trace, const float min_range) {
    // @credits: https://github.com/perilouswithadollarsign/cstrike15_src/blob/master/game/shared/util_shared.cpp#L757
    CGameTrace* game_trace = {};
    if (game_trace == nullptr)
        return;
    auto smallest_fraction = game_trace->fraction;

    const Ray_t ray(start, end);

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

        if (!entity || !entity->is_alive() || entity->IsDormant())
            continue;

        if (filter != nullptr && filter->ShouldHitEntity(entity, mask))
            continue;

        const auto collideable = entity->GetCollideable();

        if (!collideable)
            continue;

        // get bounding box.
        const auto mins = collideable->OBBMins();
        const auto maxs = collideable->OBBMaxs();

        // calculate world space center.
        const auto center = (maxs + mins) * 0.5f;
        const auto position = center + entity->m_vecOrigin();

        const auto to = position - start;
        auto direction = end - start;
        const auto length = direction.Normalize();

        const auto range_along = direction.Dot(to);
        auto range = 0.f;

        // calculate distance to ray.
        if (range_along < 0.0f)
            // off start point.
            range = -to.Length();
        else if (range_along > length)
            // off end point.
            range = -(position - end).Length();
        else
            // within ray bounds.
            range = (position - (direction * range_along + start)).Length();

        constexpr auto max_range = 60.f;
        if (range < min_range || range > max_range)
            continue;

        m_trace()->ClipRayToEntity(ray, mask | CONTENTS_HITBOX, entity, trace);

        if (trace->fraction < smallest_fraction) {
            // we shortened the ray - save off the trace.
            trace = game_trace;
            smallest_fraction = trace->fraction;
        }
    }
}

bool autowall::trace_to_exit(CGameTrace& enter_trace, CGameTrace& exit_trace, const Vector& position, const Vector& direction, player_t* clip_player) {
    auto distance = 0.f;
    auto start_contents = 0;

    while (distance <= 90.f) {
        // add extra distance to our ray.
        distance += 4.f;

        // multiply the direction vector to the distance so we go outwards, add our position to it.
        auto start = position + direction * distance;

        if (!start_contents)
            start_contents = m_trace()->GetPointContents(start, MASK_SHOT_HULL | CONTENTS_HITBOX, nullptr);

        const auto current_contets = m_trace()->GetPointContents(start, MASK_SHOT_HULL | CONTENTS_HITBOX, nullptr);

        if (!(current_contets & MASK_SHOT_HULL) || (current_contets & CONTENTS_HITBOX && current_contets != start_contents)) {
            // setup our end position by deducting the direction by the extra added distance.
            const auto end = start - (direction * 4.f);

            // trace ray to world.
            Ray_t ray_world(start, end);
            m_trace()->TraceRay(ray_world, MASK_SHOT_HULL | CONTENTS_HITBOX, nullptr, &exit_trace);

            if (static auto sv_clip_penetration_traces_to_players = m_cvar()->FindVar(crypt_str("sv_clip_penetration_traces_to_players")); sv_clip_penetration_traces_to_players != nullptr && sv_clip_penetration_traces_to_players->GetBool()) {
                CTraceFilter filter;
                filter.pSkip = clip_player;
                clip_trace_to_player(end, start, MASK_SHOT_HULL | CONTENTS_HITBOX, &filter, &exit_trace, -60.f);
            }

            // check if a hitbox is in-front of our enemy and if they are behind of a solid wall.
            if (exit_trace.startsolid && exit_trace.surface.flags & SURF_HITBOX) {
                // trace ray to entity.
                Ray_t ray(start, position);
                CTraceFilter filter;
                filter.pSkip = exit_trace.hit_entity;

                m_trace()->TraceRay(ray, MASK_SHOT_HULL, &filter, &exit_trace);

                if (exit_trace.DidHit() && !exit_trace.startsolid) {
                    start = exit_trace.endpos;
                    return true;
                }

                continue;
            }

            if (exit_trace.DidHit() && !exit_trace.startsolid) {
                if (is_breakable_entity(exit_trace.hit_entity) && is_breakable_entity(exit_trace.hit_entity))
                    return true;

                if (enter_trace.surface.flags & SURF_NODRAW || (!(exit_trace.surface.flags & SURF_NODRAW) && exit_trace.plane.normal.Dot(direction) <= 1.f)) {
                    const auto multiplier = exit_trace.fraction * 4.f;
                    start -= direction * multiplier;
                    return true;
                }

                continue;
            }

            if (!exit_trace.DidHit() || exit_trace.startsolid) {
                if (enter_trace.hit_entity != nullptr && enter_trace.hit_entity->EntIndex() != 0 && is_breakable_entity(exit_trace.hit_entity)) {
                    // did hit breakable non world entity.
                    exit_trace = enter_trace;
                    exit_trace.endpos = start + direction;
                    return true;
                }

                continue;
            }
        }
    }

    return false;
}

bool autowall::handle_bullet_penetration(player_t* entity, const weapon_info_t* weapon_data, const surfacedata_t* enter_surface_data, fire_bullet_t& data) {
    static auto ff_damage_reduction_bullets = m_cvar()->FindVar(crypt_str("ff_damage_reduction_bullets"));
    static auto ff_damage_bullet_penetration = m_cvar()->FindVar(crypt_str("ff_damage_bullet_penetration"));

    const auto reduction_damage = ff_damage_reduction_bullets->GetFloat();
    const auto penetratate_damage = ff_damage_bullet_penetration->GetFloat();

    const auto enter_material = enter_surface_data->game.material;

    if (data.penetrate_count == 0 && enter_material != CHAR_TEX_GRATE && enter_material != CHAR_TEX_GLASS && !(data.enter_trace.surface.flags & SURF_NODRAW))
        return false;

    if (weapon_data->flPenetration <= 0.f || data.penetrate_count <= 0)
        return false;

    CGameTrace exit_trace = {};
    if (!trace_to_exit(data.enter_trace, exit_trace, data.enter_trace.endpos, data.direction, entity) && !(m_trace()->GetPointContents(data.enter_trace.endpos, MASK_SHOT_HULL, nullptr) & MASK_SHOT_HULL))
        return false;

    const auto exit_surface_data = m_physsurface()->GetSurfaceData(exit_trace.surface.surfaceProps);
    const auto exit_material = exit_surface_data->game.material;

    const auto enter_penetration_modifier = enter_surface_data->game.flPenetrationModifier;
    const auto exit_penetration_modifier = exit_surface_data->game.flPenetrationModifier;

    auto damage_lost_modifier = 0.16f;
    auto penetration_modifier = 0.f;

    if (enter_material == CHAR_TEX_GRATE || enter_material == CHAR_TEX_GLASS) {
        damage_lost_modifier = 0.05f;
        penetration_modifier = 3.f;
    }
    else if (((data.enter_trace.contents >> 3) & CONTENTS_SOLID) || ((data.enter_trace.surface.flags >> 7) & SURF_LIGHT)) {
        damage_lost_modifier = 0.16f;
        penetration_modifier = 1.f;
    }
    else if (enter_material == CHAR_TEX_FLESH && reduction_damage == 0.f && data.enter_trace.hit_entity != nullptr && ((player_t*)data.enter_trace.hit_entity)->is_player() && (entity->m_iTeamNum() == ((player_t*)data.enter_trace.hit_entity)->m_iTeamNum())) {
        if (penetratate_damage == 0.f)
            return false;

        // shot through teammates.
        damage_lost_modifier = penetratate_damage;
        penetration_modifier = penetratate_damage;
    }
    else {
        damage_lost_modifier = 0.16f;
        penetration_modifier = (enter_penetration_modifier + exit_penetration_modifier) * 0.5f;
    }

    if (enter_material == exit_material) {
        if (exit_material == CHAR_TEX_CARDBOARD || exit_material == CHAR_TEX_WOOD)
            penetration_modifier = 3.f;
        else if (exit_material == CHAR_TEX_PLASTIC)
            penetration_modifier = 2.f;
    }

    const auto trace_distance = (exit_trace.endpos - data.enter_trace.endpos).LengthSqr();

    // penetration modifier.
    const auto modifier = (penetration_modifier > 0.f ? 1.f / penetration_modifier : 0.f);

    // this calculates how much damage we've lost depending on thickness of the wall, our penetration, damage, and the modifiers set earlier.
    const auto lost_damage = (data.current_damage * damage_lost_modifier + (weapon_data->flPenetration > 0.f ? 3.75f / weapon_data->flPenetration : 0.f) * (modifier * 3.f)) + ((modifier * trace_distance) / 24.f);

    // did we loose too much damage?
    if (lost_damage > data.current_damage)
        return false;

    // we can't use any of the damage that we've lost.
    if (lost_damage > 0.f)
        data.current_damage -= lost_damage;

    // do we still have enough damage to deal?
    if (data.current_damage < 1.f)
        return false;

    data.position = exit_trace.endpos;
    --data.penetrate_count;
    return true;
}

bool autowall::fire_bullet(weapon_t* pWeapon, Vector& direction, bool& visible, float& currentDamage, int& hitbox, player_t* e, float length, const Vector& pos)
{
    if (!pWeapon)
        return false;

    auto weaponData = pWeapon->get_csweapon_info();

    if (!weaponData)
        return false;

    CGameTrace enterTrace;
    CTraceFilter filter;

    fire_bullet_t data = { };

    filter.pSkip = g_ctx.local();
    currentDamage = weaponData->iDamage;

    auto eyePosition = pos;
    auto currentDistance = 0.0f;
    auto maxRange = weaponData->flRange;
    auto penetrationDistance = 3000.0f;
    auto penetrationPower = weaponData->flPenetration;
    auto possibleHitsRemaining = 4;

    while (currentDamage >= 1.0f)
    {
        maxRange -= currentDistance;
        auto end = eyePosition + direction * maxRange;

        CTraceFilter filter;
        filter.pSkip = g_ctx.local();

        util::trace_line(eyePosition, end, MASK_SHOT_HULL | CONTENTS_HITBOX, &filter, &enterTrace);
        // check for player hitboxes extending outside their collision bounds.
        clip_trace_to_player( eyePosition, end + direction * 40.0f, MASK_SHOT_HULL | CONTENTS_HITBOX, &filter, &enterTrace);

        auto enterSurfaceData = m_physsurface()->GetSurfaceData(enterTrace.surface.surfaceProps);
        auto enterSurfPenetrationModifier = enterSurfaceData->game.flPenetrationModifier;
        auto enterMaterial = enterSurfaceData->game.material;

        if (enterTrace.fraction == 1.0f)  //-V550
            break;

        currentDistance += enterTrace.fraction * maxRange;
        currentDamage *= pow(weaponData->flRangeModifier, currentDistance / 500.0f);

        if (currentDistance > penetrationDistance && weaponData->flPenetration || enterSurfPenetrationModifier < 0.1f)  //-V1051
            break;

        auto canDoDamage = enterTrace.hitgroup != HITGROUP_GEAR && enterTrace.hitgroup != HITGROUP_GENERIC;
        auto isPlayer = ((player_t*)enterTrace.hit_entity)->is_player();
        auto isEnemy = ((player_t*)enterTrace.hit_entity)->m_iTeamNum() != g_ctx.local()->m_iTeamNum();

        if (canDoDamage && isPlayer && isEnemy)
        {
            scale_damage(enterTrace.hitgroup, ((player_t*)enterTrace.hit_entity), weaponData->flArmorRatio, weaponData->headshotmultyplrier, currentDamage);
            hitbox = enterTrace.hitbox;
            return true;
        }

        if (!possibleHitsRemaining)
            break;

        static auto damageReductionBullets = m_cvar()->FindVar(crypt_str("ff_damage_reduction_bullets"));
        static auto damageBulletPenetration = m_cvar()->FindVar(crypt_str("ff_damage_bullet_penetration"));

        // calling handlebulletpenetration here reduces our penetration Counter, and if it returns true, we can't shot through it.
        if (!handle_bullet_penetration(e, weaponData, enterSurfaceData, data))
            break;

        visible = false;
    }

    return false;
}

autowall::returninfo_t autowall::wall_penetration(const Vector& eye_pos, Vector& point, player_t* e)
{
    g_ctx.globals.autowalling = true;
    auto tmp = point - eye_pos;

    auto angles = ZERO;
    math::vector_angles(tmp, angles);

    auto direction = ZERO;
    math::angle_vectors(angles, direction);

    direction.NormalizeInPlace();

    auto visible = true;
    auto damage = -1.0f;
    auto hitbox = -1;

    auto weapon = g_ctx.local()->m_hActiveWeapon().Get();

    if (fire_bullet(weapon, direction, visible, damage, hitbox, e, 0.0f, eye_pos))
    {
        g_ctx.globals.autowalling = false;
        return returninfo_t(visible, (int)damage, hitbox); //-V2003
    }
    else
    {
        g_ctx.globals.autowalling = false;
        return returninfo_t(false, -1, -1);
    }
}

Код:
#include "..\..\includes.hpp"

class weapon_info_t;
class weapon_t;

struct fire_bullet_data
{
    Vector src;
    trace_t enter_trace;
    Vector direction;
    CTraceFilter filter;
    float trace_length;
    float trace_length_remaining;
    float current_damage;
    int penetrate_count;
};

struct fire_bullet_t {
    Vector position = {};
    Vector direction = {};

    CGameTrace enter_trace = {};

    float current_damage = 0.f;

    int penetrate_count = 0;
};

class autowall : public singleton <autowall>
{
public:
    struct returninfo_t
    {
        bool valid = false;

        bool visible = false;
        int damage = -1;
        int hitbox = -1;

        returninfo_t()
        {
            valid = false;

            visible = false;
            damage = -1;
            hitbox = -1;
        }

        returninfo_t(bool visible, int damage, int hitbox)
        {
            valid = true;

            this->visible = visible;
            this->damage = damage;
            this->hitbox = hitbox;
        }
    };

    struct FireBulletData
    {
        Vector src;
        trace_t enter_trace;
        Vector direction;
        CTraceFilter filter;
        weapon_info_t* wpn_data;
        float trace_length;
        float trace_length_remaining;
        float length_to_end;
        float current_damage;
        int penetrate_count;
    };

    bool is_breakable_entity(IClientEntity* e);
    void scale_damage(const int hit_group, player_t* entity, const float weapon_armor_ratio, const float weapon_headshot_multiplier, float& damage);
    void clip_trace_to_player(const Vector& start, const Vector& end, const unsigned int mask, CTraceFilter* filter, CGameTrace* trace, const float min_range = 0.f);
    bool trace_to_exit(CGameTrace& enter_trace, CGameTrace& exit_trace, const Vector& position, const Vector& direction, player_t* clip_player);
    bool handle_bullet_penetration(player_t* entity, const weapon_info_t* weapon_data, const surfacedata_t* enter_surface_data, fire_bullet_t& data);
    returninfo_t wall_penetration(const Vector& eye_pos, Vector& point, player_t* e);
    bool fire_bullet(weapon_t* pWeapon, Vector& direction, bool& visible, float& currentDamage, int& hitbox, player_t* e = nullptr, float length = 0.f, const Vector& pos = { 0.f,0.f,0.f });
};
 
Начинающий
Статус
Оффлайн
Регистрация
26 Янв 2019
Сообщения
113
Реакции[?]
12
Поинты[?]
7K
Код:
#include "autowall.h"

bool autowall::is_breakable_entity(IClientEntity* e)
{
    if (!e || !e->EntIndex())
        return false;

    static auto is_breakable = util::FindSignature(crypt_str("client.dll"), crypt_str("55 8B EC 51 56 8B F1 85 F6 74 68"));

    auto take_damage = *(uintptr_t*)((uintptr_t)is_breakable + 0x26);
    auto backup = *(uint8_t*)((uintptr_t)e + take_damage);

    auto client_class = e->GetClientClass();
    auto network_name = client_class->m_pNetworkName;

    if (!strcmp(network_name, "CBreakableSurface"))
        *(uint8_t*)((uintptr_t)e + take_damage) = DAMAGE_YES;
    else if (!strcmp(network_name, "CBaseDoor") || !strcmp(network_name, "CDynamicProp"))
        *(uint8_t*)((uintptr_t)e + take_damage) = DAMAGE_NO;

    using Fn = bool(__thiscall*)(IClientEntity*);
    auto result = ((Fn)is_breakable)(e);

    *(uint8_t*)((uintptr_t)e + take_damage) = backup;
    return result;
}

void autowall::scale_damage(const int hit_group, player_t* entity, const float weapon_armor_ratio, const float weapon_headshot_multiplier, float& damage) {
    const auto heavy_armor = entity->m_bHasHeavyArmor();

    static auto mp_damage_scale_ct_head = m_cvar()->FindVar(crypt_str("mp_damage_scale_ct_head"));
    static auto mp_damage_scale_t_head = m_cvar()->FindVar(crypt_str("mp_damage_scale_t_head"));

    static auto mp_damage_scale_ct_body = m_cvar()->FindVar(crypt_str("mp_damage_scale_ct_body"));
    static auto mp_damage_scale_t_body = m_cvar()->FindVar(crypt_str("mp_damage_scale_t_body"));

    auto head_damage_scale = entity->m_iTeamNum() == 3 ? mp_damage_scale_ct_head->GetFloat() : mp_damage_scale_t_head->GetFloat();
    auto body_damage_scale = entity->m_iTeamNum() == 3 ? mp_damage_scale_ct_body->GetFloat() : mp_damage_scale_t_body->GetFloat();

    if (heavy_armor)
        head_damage_scale *= 0.5f;

    switch (hit_group) {
    case HITGROUP_HEAD:
        damage *= weapon_headshot_multiplier * head_damage_scale;
        break;
    case HITGROUP_CHEST:
    case HITGROUP_LEFTARM:
    case HITGROUP_RIGHTARM:
        damage *= body_damage_scale;
        break;
    case HITGROUP_STOMACH:
        damage *= 1.25f * body_damage_scale;
        break;
    case HITGROUP_LEFTLEG:
    case HITGROUP_RIGHTLEG:
        damage *= 0.75f * body_damage_scale;
        break;
    default:
        break;
    }

    auto is_armored = [&hit_group]() -> bool {
        switch (hit_group) {
        case HITGROUP_HEAD:
        case HITGROUP_GENERIC:
        case HITGROUP_CHEST:
        case HITGROUP_STOMACH:
        case HITGROUP_LEFTARM:
        case HITGROUP_RIGHTARM:
        case HITGROUP_LEFTLEG:
        case HITGROUP_RIGHTLEG:
        case HITGROUP_GEAR:
            return true;
        default:
            return false;
        }
    };

    if (entity->m_ArmorValue() > 0 && is_armored()) {
        float heavy_armor_bonus = 1.f, armor_bonus = 0.5f, armor_ratio = weapon_armor_ratio * 0.5f;

        if (heavy_armor) {
            heavy_armor_bonus = 0.25f;
            armor_bonus = 0.33f;
            armor_ratio *= 0.20f;
        }

        float damage_to_health = damage * armor_ratio;
        if (const auto damage_to_armor = (damage - damage_to_health) * (heavy_armor_bonus * armor_bonus); damage_to_armor > static_cast<float>(entity->m_ArmorValue()))
            damage_to_health = damage - static_cast<float>(entity->m_ArmorValue()) / armor_bonus;
    }
}

void autowall::clip_trace_to_player(const Vector& start, const Vector& end, const unsigned int mask, CTraceFilter* filter, CGameTrace* trace, const float min_range) {
    // @credits: https://github.com/perilouswithadollarsign/cstrike15_src/blob/master/game/shared/util_shared.cpp#L757
    CGameTrace* game_trace = {};
    if (game_trace == nullptr)
        return;
    auto smallest_fraction = game_trace->fraction;

    const Ray_t ray(start, end);

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

        if (!entity || !entity->is_alive() || entity->IsDormant())
            continue;

        if (filter != nullptr && filter->ShouldHitEntity(entity, mask))
            continue;

        const auto collideable = entity->GetCollideable();

        if (!collideable)
            continue;

        // get bounding box.
        const auto mins = collideable->OBBMins();
        const auto maxs = collideable->OBBMaxs();

        // calculate world space center.
        const auto center = (maxs + mins) * 0.5f;
        const auto position = center + entity->m_vecOrigin();

        const auto to = position - start;
        auto direction = end - start;
        const auto length = direction.Normalize();

        const auto range_along = direction.Dot(to);
        auto range = 0.f;

        // calculate distance to ray.
        if (range_along < 0.0f)
            // off start point.
            range = -to.Length();
        else if (range_along > length)
            // off end point.
            range = -(position - end).Length();
        else
            // within ray bounds.
            range = (position - (direction * range_along + start)).Length();

        constexpr auto max_range = 60.f;
        if (range < min_range || range > max_range)
            continue;

        m_trace()->ClipRayToEntity(ray, mask | CONTENTS_HITBOX, entity, trace);

        if (trace->fraction < smallest_fraction) {
            // we shortened the ray - save off the trace.
            trace = game_trace;
            smallest_fraction = trace->fraction;
        }
    }
}

bool autowall::trace_to_exit(CGameTrace& enter_trace, CGameTrace& exit_trace, const Vector& position, const Vector& direction, player_t* clip_player) {
    auto distance = 0.f;
    auto start_contents = 0;

    while (distance <= 90.f) {
        // add extra distance to our ray.
        distance += 4.f;

        // multiply the direction vector to the distance so we go outwards, add our position to it.
        auto start = position + direction * distance;

        if (!start_contents)
            start_contents = m_trace()->GetPointContents(start, MASK_SHOT_HULL | CONTENTS_HITBOX, nullptr);

        const auto current_contets = m_trace()->GetPointContents(start, MASK_SHOT_HULL | CONTENTS_HITBOX, nullptr);

        if (!(current_contets & MASK_SHOT_HULL) || (current_contets & CONTENTS_HITBOX && current_contets != start_contents)) {
            // setup our end position by deducting the direction by the extra added distance.
            const auto end = start - (direction * 4.f);

            // trace ray to world.
            Ray_t ray_world(start, end);
            m_trace()->TraceRay(ray_world, MASK_SHOT_HULL | CONTENTS_HITBOX, nullptr, &exit_trace);

            if (static auto sv_clip_penetration_traces_to_players = m_cvar()->FindVar(crypt_str("sv_clip_penetration_traces_to_players")); sv_clip_penetration_traces_to_players != nullptr && sv_clip_penetration_traces_to_players->GetBool()) {
                CTraceFilter filter;
                filter.pSkip = clip_player;
                clip_trace_to_player(end, start, MASK_SHOT_HULL | CONTENTS_HITBOX, &filter, &exit_trace, -60.f);
            }

            // check if a hitbox is in-front of our enemy and if they are behind of a solid wall.
            if (exit_trace.startsolid && exit_trace.surface.flags & SURF_HITBOX) {
                // trace ray to entity.
                Ray_t ray(start, position);
                CTraceFilter filter;
                filter.pSkip = exit_trace.hit_entity;

                m_trace()->TraceRay(ray, MASK_SHOT_HULL, &filter, &exit_trace);

                if (exit_trace.DidHit() && !exit_trace.startsolid) {
                    start = exit_trace.endpos;
                    return true;
                }

                continue;
            }

            if (exit_trace.DidHit() && !exit_trace.startsolid) {
                if (is_breakable_entity(exit_trace.hit_entity) && is_breakable_entity(exit_trace.hit_entity))
                    return true;

                if (enter_trace.surface.flags & SURF_NODRAW || (!(exit_trace.surface.flags & SURF_NODRAW) && exit_trace.plane.normal.Dot(direction) <= 1.f)) {
                    const auto multiplier = exit_trace.fraction * 4.f;
                    start -= direction * multiplier;
                    return true;
                }

                continue;
            }

            if (!exit_trace.DidHit() || exit_trace.startsolid) {
                if (enter_trace.hit_entity != nullptr && enter_trace.hit_entity->EntIndex() != 0 && is_breakable_entity(exit_trace.hit_entity)) {
                    // did hit breakable non world entity.
                    exit_trace = enter_trace;
                    exit_trace.endpos = start + direction;
                    return true;
                }

                continue;
            }
        }
    }

    return false;
}

bool autowall::handle_bullet_penetration(player_t* entity, const weapon_info_t* weapon_data, const surfacedata_t* enter_surface_data, fire_bullet_t& data) {
    static auto ff_damage_reduction_bullets = m_cvar()->FindVar(crypt_str("ff_damage_reduction_bullets"));
    static auto ff_damage_bullet_penetration = m_cvar()->FindVar(crypt_str("ff_damage_bullet_penetration"));

    const auto reduction_damage = ff_damage_reduction_bullets->GetFloat();
    const auto penetratate_damage = ff_damage_bullet_penetration->GetFloat();

    const auto enter_material = enter_surface_data->game.material;

    if (data.penetrate_count == 0 && enter_material != CHAR_TEX_GRATE && enter_material != CHAR_TEX_GLASS && !(data.enter_trace.surface.flags & SURF_NODRAW))
        return false;

    if (weapon_data->flPenetration <= 0.f || data.penetrate_count <= 0)
        return false;

    CGameTrace exit_trace = {};
    if (!trace_to_exit(data.enter_trace, exit_trace, data.enter_trace.endpos, data.direction, entity) && !(m_trace()->GetPointContents(data.enter_trace.endpos, MASK_SHOT_HULL, nullptr) & MASK_SHOT_HULL))
        return false;

    const auto exit_surface_data = m_physsurface()->GetSurfaceData(exit_trace.surface.surfaceProps);
    const auto exit_material = exit_surface_data->game.material;

    const auto enter_penetration_modifier = enter_surface_data->game.flPenetrationModifier;
    const auto exit_penetration_modifier = exit_surface_data->game.flPenetrationModifier;

    auto damage_lost_modifier = 0.16f;
    auto penetration_modifier = 0.f;

    if (enter_material == CHAR_TEX_GRATE || enter_material == CHAR_TEX_GLASS) {
        damage_lost_modifier = 0.05f;
        penetration_modifier = 3.f;
    }
    else if (((data.enter_trace.contents >> 3) & CONTENTS_SOLID) || ((data.enter_trace.surface.flags >> 7) & SURF_LIGHT)) {
        damage_lost_modifier = 0.16f;
        penetration_modifier = 1.f;
    }
    else if (enter_material == CHAR_TEX_FLESH && reduction_damage == 0.f && data.enter_trace.hit_entity != nullptr && ((player_t*)data.enter_trace.hit_entity)->is_player() && (entity->m_iTeamNum() == ((player_t*)data.enter_trace.hit_entity)->m_iTeamNum())) {
        if (penetratate_damage == 0.f)
            return false;

        // shot through teammates.
        damage_lost_modifier = penetratate_damage;
        penetration_modifier = penetratate_damage;
    }
    else {
        damage_lost_modifier = 0.16f;
        penetration_modifier = (enter_penetration_modifier + exit_penetration_modifier) * 0.5f;
    }

    if (enter_material == exit_material) {
        if (exit_material == CHAR_TEX_CARDBOARD || exit_material == CHAR_TEX_WOOD)
            penetration_modifier = 3.f;
        else if (exit_material == CHAR_TEX_PLASTIC)
            penetration_modifier = 2.f;
    }

    const auto trace_distance = (exit_trace.endpos - data.enter_trace.endpos).LengthSqr();

    // penetration modifier.
    const auto modifier = (penetration_modifier > 0.f ? 1.f / penetration_modifier : 0.f);

    // this calculates how much damage we've lost depending on thickness of the wall, our penetration, damage, and the modifiers set earlier.
    const auto lost_damage = (data.current_damage * damage_lost_modifier + (weapon_data->flPenetration > 0.f ? 3.75f / weapon_data->flPenetration : 0.f) * (modifier * 3.f)) + ((modifier * trace_distance) / 24.f);

    // did we loose too much damage?
    if (lost_damage > data.current_damage)
        return false;

    // we can't use any of the damage that we've lost.
    if (lost_damage > 0.f)
        data.current_damage -= lost_damage;

    // do we still have enough damage to deal?
    if (data.current_damage < 1.f)
        return false;

    data.position = exit_trace.endpos;
    --data.penetrate_count;
    return true;
}

bool autowall::fire_bullet(weapon_t* pWeapon, Vector& direction, bool& visible, float& currentDamage, int& hitbox, player_t* e, float length, const Vector& pos)
{
    if (!pWeapon)
        return false;

    auto weaponData = pWeapon->get_csweapon_info();

    if (!weaponData)
        return false;

    CGameTrace enterTrace;
    CTraceFilter filter;

    fire_bullet_t data = { };

    filter.pSkip = g_ctx.local();
    currentDamage = weaponData->iDamage;

    auto eyePosition = pos;
    auto currentDistance = 0.0f;
    auto maxRange = weaponData->flRange;
    auto penetrationDistance = 3000.0f;
    auto penetrationPower = weaponData->flPenetration;
    auto possibleHitsRemaining = 4;

    while (currentDamage >= 1.0f)
    {
        maxRange -= currentDistance;
        auto end = eyePosition + direction * maxRange;

        CTraceFilter filter;
        filter.pSkip = g_ctx.local();

        util::trace_line(eyePosition, end, MASK_SHOT_HULL | CONTENTS_HITBOX, &filter, &enterTrace);
        // check for player hitboxes extending outside their collision bounds.
        clip_trace_to_player( eyePosition, end + direction * 40.0f, MASK_SHOT_HULL | CONTENTS_HITBOX, &filter, &enterTrace);

        auto enterSurfaceData = m_physsurface()->GetSurfaceData(enterTrace.surface.surfaceProps);
        auto enterSurfPenetrationModifier = enterSurfaceData->game.flPenetrationModifier;
        auto enterMaterial = enterSurfaceData->game.material;

        if (enterTrace.fraction == 1.0f)  //-V550
            break;

        currentDistance += enterTrace.fraction * maxRange;
        currentDamage *= pow(weaponData->flRangeModifier, currentDistance / 500.0f);

        if (currentDistance > penetrationDistance && weaponData->flPenetration || enterSurfPenetrationModifier < 0.1f)  //-V1051
            break;

        auto canDoDamage = enterTrace.hitgroup != HITGROUP_GEAR && enterTrace.hitgroup != HITGROUP_GENERIC;
        auto isPlayer = ((player_t*)enterTrace.hit_entity)->is_player();
        auto isEnemy = ((player_t*)enterTrace.hit_entity)->m_iTeamNum() != g_ctx.local()->m_iTeamNum();

        if (canDoDamage && isPlayer && isEnemy)
        {
            scale_damage(enterTrace.hitgroup, ((player_t*)enterTrace.hit_entity), weaponData->flArmorRatio, weaponData->headshotmultyplrier, currentDamage);
            hitbox = enterTrace.hitbox;
            return true;
        }

        if (!possibleHitsRemaining)
            break;

        static auto damageReductionBullets = m_cvar()->FindVar(crypt_str("ff_damage_reduction_bullets"));
        static auto damageBulletPenetration = m_cvar()->FindVar(crypt_str("ff_damage_bullet_penetration"));

        // calling handlebulletpenetration here reduces our penetration Counter, and if it returns true, we can't shot through it.
        if (!handle_bullet_penetration(e, weaponData, enterSurfaceData, data))
            break;

        visible = false;
    }

    return false;
}

autowall::returninfo_t autowall::wall_penetration(const Vector& eye_pos, Vector& point, player_t* e)
{
    g_ctx.globals.autowalling = true;
    auto tmp = point - eye_pos;

    auto angles = ZERO;
    math::vector_angles(tmp, angles);

    auto direction = ZERO;
    math::angle_vectors(angles, direction);

    direction.NormalizeInPlace();

    auto visible = true;
    auto damage = -1.0f;
    auto hitbox = -1;

    auto weapon = g_ctx.local()->m_hActiveWeapon().Get();

    if (fire_bullet(weapon, direction, visible, damage, hitbox, e, 0.0f, eye_pos))
    {
        g_ctx.globals.autowalling = false;
        return returninfo_t(visible, (int)damage, hitbox); //-V2003
    }
    else
    {
        g_ctx.globals.autowalling = false;
        return returninfo_t(false, -1, -1);
    }
}

Код:
#include "..\..\includes.hpp"

class weapon_info_t;
class weapon_t;

struct fire_bullet_data
{
    Vector src;
    trace_t enter_trace;
    Vector direction;
    CTraceFilter filter;
    float trace_length;
    float trace_length_remaining;
    float current_damage;
    int penetrate_count;
};

struct fire_bullet_t {
    Vector position = {};
    Vector direction = {};

    CGameTrace enter_trace = {};

    float current_damage = 0.f;

    int penetrate_count = 0;
};

class autowall : public singleton <autowall>
{
public:
    struct returninfo_t
    {
        bool valid = false;

        bool visible = false;
        int damage = -1;
        int hitbox = -1;

        returninfo_t()
        {
            valid = false;

            visible = false;
            damage = -1;
            hitbox = -1;
        }

        returninfo_t(bool visible, int damage, int hitbox)
        {
            valid = true;

            this->visible = visible;
            this->damage = damage;
            this->hitbox = hitbox;
        }
    };

    struct FireBulletData
    {
        Vector src;
        trace_t enter_trace;
        Vector direction;
        CTraceFilter filter;
        weapon_info_t* wpn_data;
        float trace_length;
        float trace_length_remaining;
        float length_to_end;
        float current_damage;
        int penetrate_count;
    };

    bool is_breakable_entity(IClientEntity* e);
    void scale_damage(const int hit_group, player_t* entity, const float weapon_armor_ratio, const float weapon_headshot_multiplier, float& damage);
    void clip_trace_to_player(const Vector& start, const Vector& end, const unsigned int mask, CTraceFilter* filter, CGameTrace* trace, const float min_range = 0.f);
    bool trace_to_exit(CGameTrace& enter_trace, CGameTrace& exit_trace, const Vector& position, const Vector& direction, player_t* clip_player);
    bool handle_bullet_penetration(player_t* entity, const weapon_info_t* weapon_data, const surfacedata_t* enter_surface_data, fire_bullet_t& data);
    returninfo_t wall_penetration(const Vector& eye_pos, Vector& point, player_t* e);
    bool fire_bullet(weapon_t* pWeapon, Vector& direction, bool& visible, float& currentDamage, int& hitbox, player_t* e = nullptr, float length = 0.f, const Vector& pos = { 0.f,0.f,0.f });
};
Не понял полезность данного конверта, ибо даже функи от лв остались такими же некоторые, хотя бы их бы изменил ещё, а так не сильно разница от автоволла ЛВ поменяется
 
Начинающий
Статус
Оффлайн
Регистрация
9 Окт 2021
Сообщения
8
Реакции[?]
2
Поинты[?]
0
you forgot

#pragma once

at the beginning of the .hpp file

And btw where do you simulate the damage?
This autowall won't work
 
Последнее редактирование:
Сверху Снизу