bool c_ragebot::hitchance( vec3_t &angle, c_csplayer *ent ) {
int traces_hit = 0;
auto local = c_csplayer::get_local( );
if( !local )
return false;
vec3_t forward, right, up;
const vec3_t eye_position = local->eye_pos( );
math::angle_to_vectors( angle + local->punch_angle( ) * 2.f, &forward, &right, &up ); // maybe add an option to not account for punch.
c_base_combat_weapon *weapon = local->get_active_weapon( );
if( !weapon )
return false;
weapon->update_accuracy( );
float weapon_spread = weapon->spread( );
float weapon_cone = weapon->inaccuracy( );
const auto get_bullet_location = [ & ]( int seed ) {
static auto random_seed = pe::get_export< void( *)( int ) >( pe::get_module( "vstdlib.dll" ), "RandomSeed" );
random_seed( seed );
float a = math::random_float( 0.f, 1.f );
float b = math::random_float( 0.f, 2.f * math::pi );
float c = math::random_float( 0.f, 1.f );
float d = math::random_float( 0.f, 2.f * math::pi );
const float generated_spread = a * weapon_spread;
const float generated_cone = c * weapon_cone;
const vec3_t spread = vec3_t(
std::cos( b ) * generated_spread + std::cos( d ) * generated_cone,
std::sin( b ) * generated_spread + std::sin( d ) * generated_cone,
0.f
);
return vec3_t( forward + right * -spread.x + up * -spread.y ).normalized( );
};
for( int i = 1; i <= 256; i++ ) {
vec3_t spread_angle;
vec3_t bullet_end;
math::vector_angle( get_bullet_location( i ), spread_angle );
math::angle_to_vector( angle - ( spread_angle - angle ), bullet_end );
trace_t trace;
ray_t ray;
ray.init( eye_position, eye_position + bullet_end * weapon->get_weapon_info( )->range );
g_csgo.m_engine_trace->clip_ray_to_entity( ray, MASK_SHOT, ent, &trace );
if( trace.m_hit_entity == ent )
++traces_hit;
if( traces_hit >= static_cast< int >( g_vars.rage.hitchance * 2.56f ) )
return true;
}
return false;
}