#include "aim.h" #include "interfaces.h" #include "ctx.hpp" #include "settings.h" #include "math.h" #include "base_cheat.h" #include "input_system.hpp" #include "d3d.hpp" namespace features { bool c_legitbot::lag_record_t::is_valid( ) { return util::is_tick_valid( m_tickcount ); } void c_legitbot::c_lagcomp::store_player( int ent_index ) { auto ent = cl.m_entlist( )->get_client_entity< c_base_player >( ent_index ); vec3_t pos = ent->get_hitbox_position( 0 ); int tickcount = TIME_TO_TICKS( ent->m_flSimulationTime( ) ); lag_record_t new_record; if( ent->ce( )->setup_bones( new_record.m_matrix, 128, 0x100, 0.f ) ) { new_record.m_position = pos; new_record.m_tickcount = tickcount; m_data[ ent_index ].push_front( new_record ); } while( !m_data[ ent_index ].empty( ) && ( m_data[ ent_index ].size( ) > TIME_TO_TICKS( 1.0f ) ) ) { m_data[ ent_index ].pop_back( ); } } bool c_legitbot::c_lagcomp::can_backtrack_entity( int ent_index ) { if( m_data[ ent_index ].empty( ) ) { return false; } for( auto& it : m_data[ ent_index ] ) { if( it.is_valid( ) ) return true; } return false; } c_legitbot::lag_record_t* c_legitbot::c_lagcomp::find_best_record( int ent_index ) { c_legitbot::lag_record_t* best_record = nullptr; float best_fov{ g_settings.legit.backtracking_fov( ) }; vec3_t cur_angle; vec3_t aim_angle; vec3_t aim_pos; vec3_t cur_pos; int cur_tick; if( m_data[ ent_index ].empty( ) ) { return nullptr; } cl.m_engine( )->GetViewAngles( cur_angle ); cur_pos = g_ctx.m_local->get_eye_pos( ); cur_tick = cl.m_globals->tickcount; for( auto& it : m_data[ ent_index ] ) { int delta = std::abs( cur_tick - it.m_tickcount ); auto nci = cl.m_engine( )->GetNetChannelInfo( ); if( nci ) { float max_latency = g_settings.legit.backtracking_time + nci->GetLatency( 0 ); if( delta > TIME_TO_TICKS( max_latency ) ) continue; } if( !it.is_valid( ) ) continue; aim_pos = it.m_position; aim_angle = math::vector_angles( cur_pos, aim_pos ).clamp( ); float fov = ( cur_angle - aim_angle ).clamp( ).length2d( ); if( fov < best_fov ) { best_fov = fov; best_record = ⁢ } } return best_record; } vec3_t c_legitbot::c_lagcomp::get_backtracked_position( int ent_index ) { if( !m_data[ ent_index ].size( ) ) return vec3_t( ); auto lag_record = find_best_record( ent_index ); vec3_t last_position{ }; for( auto& it : util::reverse_iterator( m_data[ ent_index ] ) ) { if( it.is_valid( ) ) last_position = it.m_position; break; } return lag_record ? lag_record->m_position : last_position; } void c_legitbot::c_lagcomp::store( ) { for( int i = 1; i < 65; ++i ) { auto ent = cl.m_entlist( )->get_client_entity< c_base_player >( i ); if( ent && ent->is_valid( ) && ent != g_ctx.m_local ) { store_player( i ); } else { m_data[ i ].clear( ); } } } bool c_legitbot::c_lagcomp::backtrack_entity( int ent_index ) { if( !m_cmd ) return false; if( !can_backtrack_entity( ent_index ) ) return false; auto best_record = find_best_record( ent_index ); if( best_record ) { m_cmd->m_tick_count = best_record->m_tickcount; return true; } return false; } void c_legitbot::c_lagcomp::operator()( user_cmd_t* cmd ) { if( !g_settings.legit.enabled( ) || !g_settings.legit.backtracking( ) ) return; m_cmd = cmd; store( ); auto target = g_cheat.aim.get_aim_target( g_settings.legit.backtracking_fov( ) ); bool active = false; if( g_settings.legit.activation_type( ) == 0 ) active = true; if( g_input.is_key_pressed( ( VirtualKeys_t )g_settings.legit.key( ) ) ) active = true; if( active && target != -1 ) { backtrack_entity( target ); } } }