Исходник Fatality lagcomp to supremacy

Участник
Статус
Оффлайн
Регистрация
6 Апр 2021
Сообщения
338
Реакции[?]
207
Поинты[?]
113K
C++:
/ cpp
#include "../includes.h"
#include "lagcompensation.hpp"
#include "bone_setup.hpp"
lag_record_t::lag_record_t( Player* player ) {
    m_recv_time = g_csgo.m_globals->m_curtime;
    m_index = player->index( );
    m_valid = true;
    m_origin = player->m_vecOrigin( );
    m_abs_origin = player->GetAbsOrigin( );

    m_layers = player->get_anim_layers( ); // check when come back
    m_poses = player->get_pose_params( ); // check when come back

    m_old_simtime = player->m_flOldSimulationTime( );
    m_simtime = player->m_flSimulationTime( );
    m_duckamt = player->m_flDuckAmount( );
    m_lby = player->m_flLowerBodyYawTarget( );
    m_eye_angles = player->m_angEyeAngles( );
    m_eye_angles.NormalizeNoClamp( );// check when come back
    m_abs_ang = player->GetAbsAngles( );
    do_not_set = false;
    m_strafing = player->m_strafing( );// check when come back
    m_dormant = player->dormant( );
    m_velocity_modifier = player->velocity_modifier( );// check when come back
    for ( auto& state : m_state ) {
        state.m_abs_ang = player->GetAbsAngles( );
        state.m_poses = m_poses;
    }

    m_flags = player->m_fFlags( );
    m_ground_entity = player->GetGroundEntity( );
    m_lagamt = game::TIME_TO_TICKS( m_simtime - m_old_simtime );
    m_velocity = ( player->m_vecOrigin( ) - player->m_vecOldOrigin( ) ) * ( 1.f / game::TIME_TO_TICKS( m_lagamt ) );
    if ( m_flags & FL_ONGROUND )
        m_velocity.z = 0.f;
    if ( !m_velocity.IsValid( ) ) // check
        m_velocity = vec3_t( 0.f, 0.f, 0.f );
    m_shot = false;
    //const auto collideable = player->GetCollideable( );
    m_obb_maxs = player->m_vecMaxs( );
    m_obb_mins = player->m_vecMins( );


    m_net_time_deviation = game::TICKS_TO_TIME( g_csgo.m_cl->m_server_tick ) - m_simtime;
    m_server_tick = g_csgo.m_cl->m_server_tick;
    if ( player->m_PlayerAnimState( ) ) {
        for ( auto& state : m_state ) {
            state.m_animstate = *player->m_PlayerAnimState( );
            state.m_abs_ang = { 0.f, state.m_animstate.m_flFootYaw, 0.f };
        }
        has_animstate = true;
    }
    m_tickbase_shift = false;

    // get parser
    // m_collision_viewheight = player->get_collision_viewheight( );
    // m_collision_change_time = player->get_collision_bounds_change_time( );
}

bool setup_bones( lag_record_t& record, resolver_direction dir, bool extrapolated ) {
    const auto ret = bone_setup::handle_bone_setup( record, dir, false, extrapolated );
    if ( !ret ) {
        memset( record.m_state[ dir ].m_matrix, 0, sizeof( record.m_state[ dir ].m_matrix ) );
        record.m_valid = false;
    }
    return ret;
}

void lag_record_t::setup_matrices( resolver_direction dir, bool extrapolated ) {
    if ( dir != resolver_direction::resolver_invalid ) {
        if ( extrapolated || this->m_state[ dir ].m_setup_tick != g_csgo.m_globals->m_tick_count )
            setup_bones( *this, dir, extrapolated );

        return;
    }

    const auto player = g_csgo.m_entlist->GetClientEntity( this->m_index );
    player_info_t info;
    if ( !g_csgo.m_engine->GetPlayerInfo( this->m_index, &info ) )
        return;

    for ( auto j = resolver_direction::resolver_networked; j < resolver_direction::resolver_max_extra; j++ ) {
        if ( info.m_fake_player && j != resolver_direction::resolver_networked )
            continue;

        if ( extrapolated || this->m_state[ j ].m_setup_tick != g_csgo.m_globals->m_tick_count )
            setup_bones( *this, j, extrapolated );
    }
}

bool lag_record_t::can_delay_shot( ) const {

    return false;
}

int lag_record_t::ticks_behind( int lag ) const {
    return std::clamp( g_csgo.m_cl->m_server_tick - this->m_server_tick, 0, 16 );
}

bool lag_record_t::delay_shot( ) const {
    return false;
}

bool lag_record_t::breaking_lc( ) const {
    return this->m_breaking_lc && !this->m_dormant || !g_csgo.cl_lagcompensation;
}

#include "player_log.hpp"
bool lagcomp::run_extrapolation( Player* player, const bool simple ) {
    auto& log = player_log::get_log( player->index( ) );
    const auto& first = log.record.back( );

    if ( g_csgo.cl_lagcompensation && ( first.m_simtime < log.m_highest_simtime || first.m_simtime == log.m_highest_simtime && first.m_ignore ) ) {
        for ( auto i = log.record.size( ) - 1; i >= 0; i-- ) {
            const auto record = &log.record[ i ];
            if ( record->m_simtime == log.m_highest_simtime ) {
                // record->setup_matrices();
                log.extrapolated_record = *record;
                log.extrapolated_record.m_breaking_lc = record->breaking_lc( );
                log.extrapolated_record.m_shot_info.breaking_lc = log.extrapolated_record.m_breaking_lc;
                log.extrapolated_record.m_extrapolated = false;
                log.extrapolated_record.m_to_server_position = true;
                log.extrapolated_record.m_valid = true;
                log.extrapolated_record.m_shot_info.has_info = true;
                log.extrapolated_record.m_shot_info.delay_shot = false;
                log.extrapolated_record.m_shot_info.extrapolated = false;
                log.extrapolated_record.m_shot_info.backtrack_ticks = 0;
                return true;
            }
        }

        return false;
    }

    const auto record = &log.record.back( );

    //const auto rtt = misc::get_latency();
    const auto rtt = g_cl.m_latency;

    const auto lag = std::max( 1, record->m_lagamt );

    log.extrapolated_record = *record;
    log.extrapolated_record.m_breaking_lc = record->breaking_lc( );
    log.extrapolated_record.m_shot_info.breaking_lc = log.extrapolated_record.m_breaking_lc;

    const auto possible_future_tick = g_csgo.m_cl->m_server_tick + 1 + game::TIME_TO_TICKS( rtt ) + 8;
    const auto max_future_ticks = possible_future_tick - game::TIME_TO_TICKS( log.extrapolated_record.m_simtime + get_lerp_time( ) );
    const auto ticks_behind = record->ticks_behind( lag );

    auto to_server_position = log.extrapolated_record.m_breaking_lc;

    if ( !to_server_position ) {
        for ( auto i = 1; i <= max_future_ticks; i++ ) {
            log.extrapolated_record.m_lagamt = std::clamp( ( i + ticks_behind ) / lag * lag, 0, 64 );
            if ( valid_simtime( record->m_simtime + game::TICKS_TO_TIME( log.extrapolated_record.m_lagamt ) ) )
                break;
        }

        if ( !valid_simtime( record->m_simtime + game::TICKS_TO_TIME( log.extrapolated_record.m_lagamt ) ) )
            to_server_position = true;
    }

    const auto server_position = std::clamp( ( game::TIME_TO_TICKS( rtt ) + ticks_behind ) / lag * lag, 0, 64 );
    if ( to_server_position || server_position < log.extrapolated_record.m_lagamt )
        log.extrapolated_record.m_lagamt = server_position;

    log.extrapolated_record.m_tickbase_shift = false;

    // resolver::extrapolate_record(log.extrapolated_record.m_lagamt, log.extrapolated_record, simple);

    log.extrapolated_record.m_extrapolate_amt = log.extrapolated_record.m_lagamt;

    if ( log.extrapolated_record.m_lagamt > max_future_ticks )
        log.extrapolated_record.m_simtime = game::TICKS_TO_TIME( possible_future_tick - 2 ) - get_lerp_time( );

    log.extrapolated_record.m_extrapolated = true;
    log.extrapolated_record.m_to_server_position = to_server_position;
    log.extrapolated_record.m_valid = true;
    log.extrapolated_record.m_lagamt = lag;
    log.extrapolated_record.m_shot_info.has_info = true;
    log.extrapolated_record.m_shot_info.delay_shot = false;
    log.extrapolated_record.m_shot_info.extrapolated = true;
    log.extrapolated_record.m_shot_info.backtrack_ticks = game::TIME_TO_TICKS( log.m_highest_simtime - log.extrapolated_record.m_simtime );

    return true;
}

int lagcomp::fix_tickcount( const float& simtime ) {
    return game::TIME_TO_TICKS( simtime + get_lerp_time( ) );
}

float lagcomp::get_lerp_time( ) {
    static auto ret = 0.f;
    static auto last_tick = 0;
    if ( g_csgo.m_globals->m_tick_count == last_tick )
        return ret;

    //var(cl_updaterate);
    //var(cl_interp);
    //var(cl_interp_ratio);

    const auto update_rate = g_csgo.cl_updaterate->GetInt( );
    const auto interp_ratio = g_csgo.cl_interp_ratio->GetFloat( );

    auto lerp = interp_ratio / update_rate;

    if ( lerp <= g_csgo.cl_interp->GetFloat( ) )
        lerp = g_csgo.cl_interp->GetFloat( );

    ret = roundf( lerp * 1000.0f ) / 1000.0f;

    last_tick = g_csgo.m_globals->m_tick_count;

    return ret;
}

void lagcomp::extrapolate( Player* player, vec3_t& origin, vec3_t& velocity, vec3_t base_velocity, int& flags, bool wasonground ) {
    //var(sv_gravity);
    // DOUBLECHECK
    //var(sv_jump_impulse);

    auto sv_gravity = g_csgo.sv_gravity;
    auto sv_jump_impulse = g_csgo.sv_jump_impulse;

    if ( !( flags & FL_ONGROUND ) ) {
        velocity.z -= g_csgo.m_globals->m_interval * sv_gravity->GetFloat( );
        velocity.z += g_csgo.m_globals->m_interval * base_velocity.z;
    } else if ( !wasonground )
        velocity.z = sv_jump_impulse->GetFloat( ) - g_csgo.m_globals->m_interval * sv_gravity->GetFloat( );

    const vec3_t mins = player->m_vecMins( );
    const vec3_t max = player->m_vecMaxs( );

    const vec3_t src = origin;
    vec3_t end = src + ( velocity * g_csgo.m_globals->m_interval );

    Ray ray( src, end, mins, max );
    //ray.(src, end, mins, max);

    CGameTrace trace;
    CTraceFilterSimple filter; // ig

    g_csgo.m_engine_trace->TraceRay( ray, MASK_PLAYERSOLID, &filter, &trace );

    if ( trace.m_fraction != 1.f ) {
        for ( int i = 0; i < 2; i++ ) {
            velocity -= trace.m_plane.m_normal * velocity.Dot( trace.m_plane.m_normal );

            const float dot = velocity.Dot( trace.m_plane.m_normal );
            if ( dot < 0.f ) {
                velocity.x -= dot * trace.m_plane.m_normal.x;
                velocity.y -= dot * trace.m_plane.m_normal.y;
                velocity.z -= dot * trace.m_plane.m_normal.z;
            }

            end = trace.m_endpos + ( velocity * ( g_csgo.m_globals->m_interval * ( 1.f - trace.m_fraction ) ) );

            Ray second_ray( trace.m_endpos, end, mins, max );

            g_csgo.m_engine_trace->TraceRay( second_ray, MASK_PLAYERSOLID, &filter, &trace );

            if ( trace.m_fraction == 1.f )
                break;
        }
    }

    origin = trace.m_endpos;
    end = trace.m_endpos;
    end.z -= 2.f;

    Ray final_r( origin, end, mins, max );

    g_csgo.m_engine_trace->TraceRay( final_r, MASK_PLAYERSOLID, &filter, &trace );

    flags &= ~FL_ONGROUND;

    if ( trace.hit( ) && trace.m_plane.m_normal.z > 0.7f )
        flags |= FL_ONGROUND;
}
#include "../menu/menu_include.h"
bool lagcomp::valid_simtime( const float& simtime, const float time ) {
    const auto nci = g_csgo.m_engine->GetNetChannelInfo( );
    if ( !nci )
        return false;

    if ( !g_csgo.cl_lagcompensation )
        return false;

    const auto last_server_tick = g_csgo.m_cl->m_server_tick;

    const auto rtt = g_cl.m_latency;
    const auto possible_future_tick = last_server_tick + game::TIME_TO_TICKS( rtt ) + 8;

    float correct = 0;
    correct += rtt;
    correct += get_lerp_time( );

    // var(sv_maxunlag);
    auto sv_maxunlag = g_csgo.sv_maxunlag;

    const auto deadtime = static_cast< int >( game::TICKS_TO_TIME( last_server_tick ) + rtt - sv_maxunlag->GetFloat( ) );
    if ( simtime <= static_cast< float >( deadtime ) || game::TIME_TO_TICKS( simtime + get_lerp_time( ) ) > possible_future_tick )
        return false;

    correct = std::clamp( correct, 0.f, sv_maxunlag->GetFloat( ) );
    const auto delta_time = correct - ( time - simtime );
    const auto delta_time1 = correct - ( time - g_csgo.m_globals->m_interval - simtime );
    const auto delta_time2 = correct - ( time + g_csgo.m_globals->m_interval - simtime );

    if ( vars::legit.enabled->get<bool>( ) && vars::legit.backtrack->get<float>( ) != 0.f ) {
        if ( g_csgo.m_globals->m_curtime - simtime > vars::legit.backtrack->get<float>( ) / 1000.f )
            return false;
    }

    //if ((tickbase::fast_fire || tickbase::hide_shot) && tickbase::compute_current_limit() > 2)
    //    return fabsf(delta_time1) < 0.2f && fabsf(delta_time2) < 0.2f;

    return fabsf( delta_time ) < 0.2f;
}

int lagcomp::get_real_lag( Player* player, const lag_record_t* current ) {
    auto& log = player_log::get_log( player->index( ) );
    if ( log.record.size( ) < 2 )
        return false;

    const auto& server_tick = current->m_server_tick;

    for ( auto i = log.record.size( ) - 2; i >= 0; i-- ) {
        const auto record = &log.record[ i ];
        if ( record->m_ignore )
            continue;

        return server_tick - record->m_server_tick;
    }

    return current->m_lagamt;
}

bool lagcomp::is_breaking_lagcomp( Player* player, const lag_record_t* current ) {
    static constexpr auto teleport_distance_sqr = 64 * 64;

    auto& log = player_log::get_log( player->index( ) );
    if ( log.record.size( ) < 2 )
        return false;

    const auto& previous = log.record[ log.record.size( ) - 2 ];
    const auto force_breaking_lc = previous.m_ignore && current->m_ignore && ( !( previous.m_flags & FL_ONGROUND ) || !( current->m_flags & FL_ONGROUND ) );

    const auto& origin = current->m_origin;

    for ( auto i = log.record.size( ) - 2; i >= 0; i-- ) {
        const auto record = &log.record[ i ];
        if ( record->m_ignore )
            continue;

        const auto delta = record->m_origin - origin;
        if ( delta.length_2d_sqr( ) > teleport_distance_sqr || force_breaking_lc && ( delta.length_2d_sqr( ) > 3000 || record->m_velocity.length_2d_sqr( ) > 250 * 250 || previous.m_velocity.length_2d_sqr( ) > 250 * 250 ) )
            return true;

        break;
    }

    return false;
}

bool lagcomp::is_breaking_lagcomp( Player* player ) {
    static constexpr auto teleport_distance_sqr = 64 * 64;

    auto& log = player_log::get_log( player->index( ) );
    if ( log.record.size( ) < 2 )
        return false;

    const auto& first = log.record.back( );
    const auto force_breaking_lc = first.m_simtime < log.m_highest_simtime || first.m_ignore && !( first.m_flags & FL_ONGROUND );

    vec3_t origin{};

    auto first_lagcomp = true;
    for ( auto i = log.record.size( ) - 1; i >= 0; i-- ) {
        const auto record = &log.record[ i ];
        if ( record->m_ignore )
            continue;

        if ( first_lagcomp ) {
            origin = record->m_origin;
            first_lagcomp = false;
            continue;
        }

        const auto delta = record->m_origin - origin;
        if ( delta.length_2d_sqr( ) > teleport_distance_sqr || force_breaking_lc && ( delta.length_2d_sqr( ) > 3000 || record->m_velocity.length_2d_sqr( ) > 250 * 250 || first.m_velocity.length_2d_sqr( ) > 250 * 250 ) )
            return true;

        break;
    }

    return false;
}


// hpp
#pragma once

template <class T, size_t N = 0>
struct circular_buffer {
    circular_buffer( ) {
        if ( ( max_size_ = N ) > 0 )
            elem_.resize( max_size_ );
    }

    circular_buffer( const size_t sz ) : max_size_( sz ) {
        elem_.resize( max_size_ );
    }

    circular_buffer( const circular_buffer& other ) {
        max_size_ = other.max_size_;
        current_ = other.current_;
        size_ = other.size_;
        elem_ = other.elem_;

    }

    circular_buffer& operator=( const circular_buffer& other ) {
        max_size_ = other.max_size_;
        current_ = other.current_;
        size_ = other.size_;
        elem_ = other.elem_;

        return *this;
    }

    circular_buffer( circular_buffer&& other ) noexcept {
        max_size_ = other.max_size_;
        current_ = other.current_;
        size_ = other.size_;
        elem_ = other.elem_;

        other.elem_.clear( );
        other.size_ = other.max_size_ = 0u;
    }

    ~circular_buffer( ) = default;

    [[nodiscard]] inline T& operator[] ( size_t idx ) { return elem_[ ( current_ + idx ) % max_size_ ]; }
    [[nodiscard]] inline const T& operator[] ( size_t idx ) const { return elem_[ ( current_ + idx ) % max_size_ ]; }
    [[nodiscard]] inline int size( ) const { return size_; }
    [[nodiscard]] inline bool empty( ) const { return size_ == 0; }

    inline void clear( ) { size_ = 0; current_ = 0; }
    inline void clear_all_but_last( ) { current_ += size_ - 1; size_ = 1; }
    inline void pop_back( ) { --size_; }
    inline void pop_front( ) { ++current_; --size_; }

    inline void reserve( size_t newsize ) {
        if ( newsize == max_size_ )
            return;

        elem_.resize( max_size_ = newsize );
        size_ = 0;
        current_ = 0;
    }

    inline void resize( size_t newsize ) {
        elem_.resize( max_size_ = newsize );
        size_ = max_size_;
    }

    template<class... Args>
    inline T* emplace_back( Args&&... args ) { assert( size_ < max_size_ ); elem_[ ( current_ + size_++ ) % max_size_ ] = T( std::forward<Args>( args )... ); return &elem_[ ( current_ + size_ - 1 ) % max_size_ ]; }
    inline T* push_back( T&& item ) { return emplace_back( std::move( item ) ); }
    [[nodiscard]] inline T* push_back( ) { return size_ >= max_size_ ? nullptr : &elem_[ ( current_ + size_++ ) % max_size_ ]; }

    template<class... Args>
    inline void emplace_front( Args&&... args ) { assert( size_ < max_size_ ); elem_[ --current_ % max_size_ ] = T( std::forward<Args>( args )... ); ++size_; }
    inline void push_front( T&& item ) { emplace_front( std::move( item ) ); }
    [[nodiscard]] inline T* push_front( ) { if ( size_ >= max_size_ ) return nullptr; ++size_; return &elem_[ --current_ % max_size_ ]; }

    [[nodiscard]] inline T& back( ) { return elem_[ ( current_ + size_ - 1 ) % max_size_ ]; }
    [[nodiscard]] inline T& front( ) { return elem_[ current_ % max_size_ ]; }

    inline void sort( std::function<bool( const T&, const T& )> pred ) {
        current_ = current_ % max_size_;
        assert( current_ % max_size_ + size_ <= max_size_ );
        std::sort( elem_.begin( ) + current_ % max_size_, elem_.begin( ) + current_ % max_size_ + size_, pred );
    }

    std::vector<T> elem_{};
    size_t current_ = 0;
    size_t size_ = 0;
    size_t max_size_ = 0;
};


struct addons_t {
    bool in_jump = false;
    bool in_idle = false;
    bool swing_left = false;
    std::vector<uint16_t> activity_modifiers{};
    float next_lby_update = 0.f;
    bool in_deploy_rate_limit = false;
    float previous_action_weight = 0.f;
    float previous_action_delta = 0.f;
    float adjust_weight = 0.f;
    int vm = 0;
};

struct record_shot_info_t {
    bool has_info = false;
    bool delay_shot = false;
    bool breaking_lc = false;
    bool extrapolated = false;
    int backtrack_ticks = 0;
    float hitchance = 0.f;
    float target_dmg = 0.f;
    int safety = 0;
    std::string extra_info{};
};

enum class resolver_side {
    resolver_invalid = -1,
    resolver_left = 0,
    resolver_right,
    resolver_side_max
};

enum class resolver_mode {
    resolver_invalid = -1,
    resolver_default = 0,
    resolver_flip,
    resolver_shot,
    resolver_mode_max
};

enum class resolver_direction {
    resolver_invalid = -1,
    resolver_networked = 0,
    resolver_max,
    resolver_zero,
    resolver_min,
    resolver_max_extra,
    resolver_max_max,
    resolver_min_min,
    resolver_min_extra,
    resolver_direction_max,
};

inline resolver_direction& operator++( resolver_direction& s, int ) {
#ifndef RELEASE
    if ( s == resolver_direction::resolver_direction_max )
        __debugbreak( );
#endif
    s = static_cast< resolver_direction >( static_cast< int >( s ) + 1 );

    return s;
}

inline resolver_mode& operator++( resolver_mode& s, int ) {
#ifndef RELEASE
    if ( s == resolver_mode::resolver_mode_max )
        __debugbreak( );
#endif
    s = static_cast< resolver_mode >( static_cast< int >( s ) + 1 );

    return s;
}
#define DECL_ALIGN(x)            __declspec( align( x ) )
#define ALIGN16 DECL_ALIGN(16)
struct state_info {
    CCSGOPlayerAnimState m_animstate = {};
    ALIGN16 matrix3x4_t m_pristine_matrix[ 128 ] = {};
    ALIGN16 matrix3x4_t m_matrix[ 128 ] = {};
    ALIGN16 matrix3x4_t m_extra_matrix[ 128 ] = {};
    ang_t m_abs_ang = {};
    std::array<float, 24> m_poses = {};
    float m_simulated_yaw = {};
    std::array<C_AnimationLayer, 13> m_own_layers = {};
    int m_setup_tick = -1;
    addons_t addon = {};
};


template<typename E, class T, E N>
class enum_array : public std::array<T, static_cast< std::size_t >( N )> {
public:
    T& operator[] ( E e ) {
        return std::array<T, static_cast< std::size_t >( N )>::operator[]( static_cast< std::size_t >( e ) );
    }

    const T& operator[] ( E e ) const {
        return std::array<T, static_cast< std::size_t >( N )>::operator[]( static_cast< std::size_t >( e ) );
    }

    E distance( T e ) const {
        return static_cast< E >( std::distance( std::array< T, static_cast< std::size_t >( N ) >::begin( ), e ) );
    }
};


struct lag_record_t {
    lag_record_t( ) { }
    lag_record_t( Player* player );

    void setup_matrices( resolver_direction direction = resolver_direction::resolver_invalid, bool extrapolated = false );

    matrix3x4_t* matrix( resolver_direction direction ) {
        return m_state[ direction ].m_matrix;
    }

    matrix3x4_t* extra_matrix( resolver_direction direction ) {
        if ( !m_last_ang_differs )
            return nullptr;

        return m_state[ direction ].m_extra_matrix;
    }

    static float get_resolver_roll( const resolver_direction state ) {
        switch ( state ) {
        case resolver_direction::resolver_min_min:
        case resolver_direction::resolver_max_extra:
            return 50.f;
        case resolver_direction::resolver_max_max:
        case resolver_direction::resolver_min_extra:
            return -50.f;
        default:
            return 0.f;
        }
    }

    bool can_delay_shot( ) const;
    int ticks_behind( int lag = -1 ) const;
    bool delay_shot( ) const;
    bool breaking_lc( ) const;

    matrix3x4_t m_visual_matrix[ 128 ] = {};

    int m_index = {};
    enum_array<resolver_direction, state_info, resolver_direction::resolver_direction_max> m_state = {};
    int m_mode = {};

    record_shot_info_t m_shot_info = {};

    bool m_last_ang_differs = false;
    bool m_pitch_jitter = false;
    bool has_animstate = false;
    bool do_not_set = false;
    bool m_valid = false;
    bool m_dormant = {};
    bool m_did_wall_detect = {};
    vec3_t m_velocity = {};
    vec3_t m_calculated_velocity = {};
    vec3_t m_origin = {};
    vec3_t m_abs_origin = {};
    vec3_t m_obb_mins = {};
    vec3_t m_obb_maxs = {};
    CBaseHandle m_ground_entity = {};

    float m_net_time_deviation = {};
    float m_old_simtime = {};
    float m_simtime = {};
    float m_duckamt = {};
    float m_lby = {};
    bool m_strafing = {};
    int m_server_tick = {};

    ang_t m_eye_angles = {};
    float m_yaw_modifier = {};


    int m_flags = {};
    float m_velocity_modifier = {};
    int m_lagamt = {};
    int m_real_lag = {};
    float m_recv_time = {};
    int m_extrapolate_amt = {};
    bool m_extrapolated = {};
    bool m_to_server_position = {};
    bool m_ignore = false;
    bool m_unknown = false;

    int m_pitch_cycle = 0;
    bool m_tickbase_shift = false;
    bool m_breaking_lc = false;

    // float m_collision_viewheight = {};
    // float m_collision_change_time = {};

    addons_t addon{};

    std::array<C_AnimationLayer, 13> m_layers = {};
    std::array<float, 24> m_poses = {};
    ang_t m_abs_ang = {};

    bool m_has_visual_matrix = false;

    bool m_shot = {};

    int m_cmdnum = {}; //lp only
};

namespace lagcomp {
    bool run_extrapolation( Player* player, const bool simple = false );
    int fix_tickcount( const float& simtime );
    bool valid_simtime( const float& simtime, const float time = game::TICKS_TO_TIME( g_cl.m_local->m_nTickBase( ) - 1 ) );
    bool is_breaking_lagcomp( Player* player );
    bool is_breaking_lagcomp( Player* player, const lag_record_t* current );
    int get_real_lag( Player* player, const lag_record_t* current );
    float get_lerp_time( );
    void extrapolate( Player* player, vec3_t& origin, vec3_t& velocity, vec3_t base_velocity, int& flags, bool wasonground );
};
 
Сверху Снизу