summaryrefslogtreecommitdiff
path: root/internal_rewrite/util.cpp
diff options
context:
space:
mode:
authorJustSomePwner <crotchyalt@gmail.com>2018-08-30 14:01:54 +0200
committerJustSomePwner <crotchyalt@gmail.com>2018-08-30 14:01:54 +0200
commit7ccb819f867493f8ec202ea3b39c94c198c64584 (patch)
tree94622e61af0ff359e3d6689cf274d74f60b2492a /internal_rewrite/util.cpp
parent564d979b79e8a5aaa5014eba0ecd36c61575934f (diff)
first
Diffstat (limited to 'internal_rewrite/util.cpp')
-rw-r--r--internal_rewrite/util.cpp558
1 files changed, 558 insertions, 0 deletions
diff --git a/internal_rewrite/util.cpp b/internal_rewrite/util.cpp
new file mode 100644
index 0000000..7e07d2f
--- /dev/null
+++ b/internal_rewrite/util.cpp
@@ -0,0 +1,558 @@
+#include "util.hpp"
+
+#include "interface.hpp"
+#include "c_base_player.hpp"
+#include "pattern.hpp"
+#include "context.hpp"
+#include "settings.hpp"
+#include "math.hpp"
+#include "base_cheat.hpp"
+
+float TICK_INTERVAL( ) {
+ return g_csgo.m_globals->m_interval_per_tick;
+}
+
+int TIME_TO_TICKS( float dt ) {
+ return static_cast< int >( 0.5f + dt / TICK_INTERVAL( ) );
+}
+
+float TICKS_TO_TIME( int tick ) {
+ return tick * TICK_INTERVAL( );
+}
+
+bool util::is_low_fps( ) {
+ return g_csgo.m_globals->m_frametime > g_csgo.m_globals->m_interval_per_tick;
+}
+
+int util::get_closest_player( ) {
+ float cur_fov{ 360.f };
+ int ret{ -1 };
+ vec3_t viewangles{ };
+ vec3_t local_pos{ };
+
+ bool friendlies = g_settings.rage.active ?
+ g_settings.rage.friendlies : g_settings.legit.friendlies;
+
+ local_pos = g_ctx.m_local->get_eye_pos( );
+ g_csgo.m_engine( )->GetViewAngles( viewangles );
+
+ for( int i{ 1 }; i < g_csgo.m_globals->m_maxclients; ++i ) {
+ auto ent = g_csgo.m_entlist( )->GetClientEntity< >( i );
+
+ if( !ent ) continue;
+ if( ent == g_ctx.m_local ) continue;
+ if( !ent->is_valid( ) ) continue;
+ int team = ent->m_iTeamNum( );
+ if( team == g_ctx.m_local->m_iTeamNum( ) && !friendlies ) {
+ continue;
+ }
+
+ auto ang = math::vector_angles( local_pos, ent->get_hitbox_pos( 0 ) );
+ ang.clamp( );
+
+ float fov = ( viewangles - ang ).clamp( ).length2d( );
+ if( fov < cur_fov ) {
+ ret = i;
+ cur_fov = fov;
+ }
+ }
+
+ return ret;
+}
+
+void util::clip_trace_to_player( IClientEntity* player, const vec3_t& src, const vec3_t& end,
+ unsigned mask, CTraceFilter* filter, CGameTrace* tr ) {
+ CGameTrace player_trace;
+ Ray_t ray;
+ float smallest_fraction = tr->fraction;
+
+ ray.Init( src, end );
+
+ if ( !filter->ShouldHitEntity( player, mask ) ) {
+ return;
+ }
+
+ g_csgo.m_trace( )->ClipRayToEntity( ray, mask | CONTENTS_HITBOX, player, &player_trace );
+
+ if ( player_trace.fraction < smallest_fraction ) {
+ *tr = player_trace;
+ smallest_fraction = player_trace.fraction;
+ }
+}
+
+std::string util::hitgroup_to_string( int hitgroup ) {
+ switch( hitgroup ) {
+ case HITGROUP_CHEST:
+ return xors( "chest" );
+ case HITGROUP_HEAD:
+ return xors( "head" );
+ case HITGROUP_LEFTARM:
+ return xors( "left arm" );
+ case HITGROUP_LEFTLEG:
+ return xors( "left leg" );
+ case HITGROUP_RIGHTARM:
+ return xors( "right arm" );
+ case HITGROUP_RIGHTLEG:
+ return xors( "right leg" );
+ case HITGROUP_STOMACH:
+ return xors( "stomach" );
+ default:
+ return xors( "generic" );
+ }
+}
+
+bool util::trace_ray( const vec3_t& start, const vec3_t& end, IClientEntity* a, IClientEntity* b ) {
+ CGameTrace tr;
+ Ray_t ray;
+ CTraceFilter filter;
+
+ filter.pSkip = a;
+
+ ray.Init( start, end );
+
+ g_csgo.m_trace( )->TraceRay( ray, 0x46004003 | CONTENTS_HITBOX, &filter, &tr );
+ clip_trace_to_player( b, start, end, ( unsigned )0x46004003, &filter, &tr );
+
+ return tr.m_pEnt == b || tr.fraction > 0.98f;
+}
+
+void util::set_random_seed( int seed ) {
+ using fn = int( __cdecl* )( int );
+ fn fn_ptr = ( fn )( GetProcAddress(
+ GetModuleHandleA( xors( "vstdlib.dll" ) ),
+ xors( "RandomSeed" ) ) );
+
+ fn_ptr( seed );
+}
+
+float util::get_random_float( float min, float max ) {
+ using fn = float( *)( float, float );
+ fn fn_ptr = ( fn )( GetProcAddress(
+ GetModuleHandleA( xors( "vstdlib.dll" ) ),
+ xors( "RandomFloat" ) ) );
+
+ return fn_ptr( min, max );
+}
+
+std::array< util::hitchance_data_t, 256 > hitchance_data;
+void util::calculate_spread_runtime( ) {
+ constexpr float pi_2 = 2.0f * ( float ) M_PI;
+
+ for ( size_t n { }; n < 256; ++n ) {
+ set_random_seed( n );
+
+ const float rand_a = get_random_float( 0.0f, 1.0f );
+ const float rand_pi_a = get_random_float( 0.0f, pi_2 );
+ const float rand_b = get_random_float( 0.0f, 1.0f );
+ const float rand_pi_b = get_random_float( 0.0f, pi_2 );
+
+ hitchance_data [ n ] = {
+ { rand_a, rand_b },
+ { std::cos( rand_pi_a ), std::sin( rand_pi_a ) },
+ { std::cos( rand_pi_b ), std::sin( rand_pi_b ) }
+ };
+ }
+}
+
+// This is gay, I didn't want to fuck up the project.
+vec3_t util::get_spread_dir( void *weapon, float inaccuracy, float spread, vec3_t angles, int seed ) {
+ const int rnsd = ( seed & 0xFF );
+ const auto *data = &hitchance_data [ rnsd ];
+ auto *wpn = ( c_base_weapon * ) weapon;
+
+ if ( !wpn )
+ return vec3_t{ };
+
+ float rand_a = data->m_random[ 0 ];
+ float rand_b = data->m_random[ 1 ];
+
+ const uint16_t item_def = wpn->m_iItemDefinitionIndex( );
+
+ // Because fuck you.
+ if ( item_def == WEAPON_R8REVOLVER ) {
+ rand_a = 1.0f - rand_a * rand_a;
+ rand_b = 1.0f - rand_b * rand_b;
+ }
+ else if ( item_def == WEAPON_NEGEV ) {
+ const int recoil_seed = wpn->get_wpn_info( )->recoil_seed;
+
+ if ( recoil_seed < 3 ) {
+ // Shoutouts to toast for the epic simplified math :^)
+ rand_a = 1.0f - std::powf( rand_a, ( 3 - recoil_seed ) + 1 );
+ rand_b = 1.0f - std::powf( rand_b, ( 3 - recoil_seed ) + 1 );
+ }
+ }
+
+ // Calculate spread.
+ const float rand_inacc = rand_a * wpn->get_inaccuracy( );
+ const float rand_spread = rand_b * wpn->get_spread( );
+
+ const float spread_x = data->m_inaccuracy [ 0 ] * rand_inacc + data->m_spread [ 0 ] * rand_spread;
+ const float spread_y = data->m_inaccuracy [ 1 ] * rand_inacc + data->m_spread [ 1 ] * rand_spread;
+
+ // Transform angle to direction.
+ vec3_t forward, right, up;
+ math::angle_vectors( angles, &forward, &right, &up );
+
+ return forward + right * spread_x + up * spread_y;
+}
+
+bool __vectorcall util::intersects_hitbox( vec3_t eye_pos, vec3_t end_pos, vec3_t min, vec3_t max, float radius ) {
+ auto dist = math::dist_segment_to_segment( eye_pos, end_pos, min, max );
+
+ return ( dist < radius );
+}
+
+// Note: abuse this as much as you can to achieve the full potential it offers.
+bool util::hitchance( int target, const vec3_t& angles, int percentage ) {
+ if( g_settings.rage.compensate_spread )
+ return true;
+
+ auto ent = g_csgo.m_entlist( )->GetClientEntity< >( target );
+
+ if ( !ent ) return false;
+ if ( percentage <= 1 ) return true;
+
+ int hits_needed = percentage * 256 / 100;
+ int hits = 0;
+
+ auto wep = g_ctx.m_local->get_weapon( );
+ if ( !wep ) return false;
+
+ vec3_t eye_pos = g_ctx.m_local->get_eye_pos( );
+ auto wpn_info = wep->get_wpn_info( );
+ if( !wpn_info ) return false;
+
+ float length = wpn_info->range;
+
+ wep->update_accuracy_penalty( );
+
+ float inaccuracy = wep->get_inaccuracy( );
+ float spread = wep->get_spread( );
+
+ if( g_settings.rage.active->m_spread_limit( ) ) {
+ bool crouched = g_ctx.m_local->m_vecViewOffset( ).z < 50.f;
+ bool alt_inaccuracy = wep->is_sniper( ) || wep->m_iItemDefinitionIndex( ) == WEAPON_R8REVOLVER;
+ float min_accuracy = crouched ? ( alt_inaccuracy ? wpn_info->inaccuracy_crouch_alt : wpn_info->inaccuracy_crouch )
+ : ( alt_inaccuracy ? wpn_info->inaccuracy_stand_alt : wpn_info->inaccuracy_stand );
+
+ float max_accuracy = alt_inaccuracy ? wpn_info->inaccuracy_move_alt : wpn_info->inaccuracy_move;
+ min_accuracy += 0.0005f;
+
+ float spread_accuracy_fraction = -( g_settings.rage.active->m_spread_limit_min( ) * 0.01f - 1.0f );
+ float spread_accuracy_tolerance = max_accuracy * spread_accuracy_fraction;
+ min_accuracy += spread_accuracy_tolerance;
+
+ if( wep->m_iItemDefinitionIndex( ) == WEAPON_SSG08 && !( g_ctx.m_local->m_fFlags( ) & FL_ONGROUND ) ) {
+ min_accuracy = 0.008750f;
+ }
+
+ if( min_accuracy >= inaccuracy )
+ return true;
+ }
+
+ struct hitbox_data_t {
+ hitbox_data_t( const vec3_t& min, const vec3_t& max, float radius ) {
+ m_min = min;
+ m_max = max;
+ m_radius = radius;
+ }
+
+ vec3_t m_min{ };
+ vec3_t m_max{ };
+ float m_radius{ };
+ };
+
+ std::vector< hitbox_data_t > m_hitbox_data;
+
+ auto model = ent->ce( )->GetModel( );
+ if( !model ) return false;
+
+ auto hdr = g_csgo.m_model_info( )->GetStudiomodel( model );
+ if( !hdr ) return false;
+
+ matrix3x4 bone_matrix[ 128 ];
+ if( !ent->ce()->SetupBones( bone_matrix, 128, 0x100, g_csgo.m_globals->m_curtime ) ) {
+ return false;
+ }
+
+ auto set = hdr->pHitboxSet( ent->m_nHitboxSet( ) );
+ if( !set ) return false;
+
+ for( int hitbox{ }; hitbox < set->numhitboxes; ++hitbox ) {
+ auto box = set->pHitbox( hitbox );
+ if( !box ) continue;
+
+ auto min = math::vector_transform( box->bbmin, bone_matrix[ box->bone ] );
+ auto max = math::vector_transform( box->bbmax, bone_matrix[ box->bone ] );
+ auto radius = box->m_flRadius;
+
+ if( radius == -1.f ) {
+ radius = min.dist_to( max );
+ }
+
+ m_hitbox_data.push_back( hitbox_data_t( min, max, radius ) );
+ }
+
+ if( m_hitbox_data.empty( ) )
+ return false;
+
+ for ( int i{ }; i < 256; i ++ ) {
+ vec3_t spread_dir = get_spread_dir( wep, inaccuracy, spread, angles, i );
+
+ //Ray_t ray;
+ //vec3_t end_pos = eye_pos + spread_dir * length;
+ //ray.Init( eye_pos, end_pos );
+ //
+ //
+ //CGameTrace tr;
+ //g_csgo.m_trace( )->ClipRayToEntity( ray, 0x46004003, ent->ce( ), &tr );
+
+ vec3_t end_pos = eye_pos + ( spread_dir * length );
+
+ for( const auto& hitbox : m_hitbox_data ) {
+ if( intersects_hitbox( eye_pos, end_pos, hitbox.m_min, hitbox.m_max, hitbox.m_radius ) ) {
+ hits++;
+ break; // cannot hit more than one hitbox
+ }
+ }
+
+ if ( hits >= hits_needed )
+ return true;
+ }
+
+ return false;
+}
+
+
+float util::get_total_latency( ) {
+ auto nci = g_csgo.m_engine( )->GetNetChannelInfo( );
+
+ if ( nci ) {
+ float latency = nci->GetLatency( 0 ) + nci->GetLatency( 1 );
+ return latency;
+ }
+
+ return 0.f;
+}
+
+float util::get_lerptime( ) {
+ static cvar_t* cl_interpolate = g_csgo.m_cvar( )->FindVar( xors( "cl_interpolate" ) );
+ static cvar_t* cl_interp = g_csgo.m_cvar( )->FindVar( xors( "cl_interp" ) );
+ static cvar_t* cl_updaterate = g_csgo.m_cvar( )->FindVar( xors( "cl_updaterate" ) );
+ static cvar_t* cl_interp_ratio = g_csgo.m_cvar( )->FindVar( xors( "cl_interp_ratio" ) );
+
+ if( cl_interp && cl_interpolate && cl_updaterate && cl_interp_ratio ) {
+ bool interpolate = cl_interpolate->get_int( );
+ if( interpolate ) {
+ float interp = cl_interp->get_float( );
+ float interp_ratio = cl_interp_ratio->get_float( );
+ float updaterate = cl_updaterate->get_float( );
+
+ return std::max< float >( interp, interp_ratio / updaterate );
+ }
+ }
+
+ return 0.f;
+}
+
+bool util::is_tick_valid( int tickcount ) {
+ float latency = get_total_latency( );
+ float correct = std::clamp( latency + get_lerptime( ), 0.f, 1.f );
+ float delta = correct - ( g_ctx.pred_time( ) - TICKS_TO_TIME( tickcount ) );
+
+ if( g_settings.rage.enabled ) {
+ return std::abs( delta ) < ( 0.2f - TICK_INTERVAL( ) * 2.f );
+ }
+
+ return std::abs( delta ) < 0.2f;
+}
+
+void util::disable_pvs( ) {
+ for( int i{ 1 }; i < 65; ++i ) {
+ auto ent = g_csgo.m_entlist( )->GetClientEntity< >( i );
+
+ if( !ent || !ent->is_valid( ) )
+ continue;
+
+ if( ent == g_ctx.m_local )
+ continue;
+
+ *( int* )( uintptr_t( ent ) + 0xa30 ) = g_csgo.m_globals->m_framecount;
+ *( int* )( uintptr_t( ent ) + 0xa28 ) = 0;
+ }
+}
+
+vec2_t util::screen_transform( vec3_t world ) {
+ vec2_t screen;
+ auto w2s = [ &world, &screen ]( ) -> bool {
+ static uintptr_t view_matrix = 0;
+ if( !view_matrix ) {
+ view_matrix = pattern::first_code_match( g_csgo.m_chl.dll( ),
+ xors( "0F 10 05 ? ? ? ? 8D 85 ? ? ? ? B9" ) );
+
+ view_matrix = *reinterpret_cast< uintptr_t* >( view_matrix + 0x3 ) + 176;
+ }
+
+ const matrix3x4& matrix = *( matrix3x4* )view_matrix;
+ screen.x = matrix[ 0 ][ 0 ] * world[ 0 ] + matrix[ 0 ][ 1 ] * world[ 1 ] + matrix[ 0 ][ 2 ] * world[ 2 ] + matrix[ 0 ][ 3 ];
+ screen.y = matrix[ 1 ][ 0 ] * world[ 0 ] + matrix[ 1 ][ 1 ] * world[ 1 ] + matrix[ 1 ][ 2 ] * world[ 2 ] + matrix[ 1 ][ 3 ];
+
+ float w = matrix[ 3 ][ 0 ] * world[ 0 ] + matrix[ 3 ][ 1 ] * world[ 1 ] + matrix[ 3 ][ 2 ] * world[ 2 ] + matrix[ 3 ][ 3 ];
+
+ if( w < 0.001f ) {
+ //screen.x *= 100000.f;
+ //screen.y *= 100000.f;
+ return true;
+ }
+
+ float invw = 1.0f / w;
+ screen.x *= invw;
+ screen.y *= invw;
+
+ return false;
+ };
+
+ w2s( );
+ //if ( !w2s( ) ) {
+ int w, h;
+ g_csgo.m_engine( )->GetScreenSize( w, h );
+
+ screen.x = ( w * .5f ) + ( screen.x * w ) * .5f;
+ screen.y = ( h * .5f ) - ( screen.y * h ) * .5f;
+
+ return screen;
+ //}
+
+ return vec2_t{ };
+}
+
+int util::hitbox_to_hitgroup( int hitbox ) {
+ switch( hitbox ) {
+ case HITBOX_HEAD:
+ case HITBOX_NECK:
+ return HITGROUP_HEAD;
+ case HITBOX_BODY:
+ case HITBOX_CHEST:
+ case HITBOX_THORAX:
+ case HITBOX_PELVIS:
+ return HITGROUP_STOMACH;
+ case HITBOX_LEFT_CALF:
+ case HITBOX_LEFT_THIGH:
+ case HITBOX_LEFT_FOOT:
+ return HITGROUP_RIGHTLEG;
+ case HITBOX_RIGHT_CALF:
+ case HITBOX_RIGHT_THIGH:
+ case HITBOX_RIGHT_FOOT:
+ return HITGROUP_LEFTLEG;
+ case HITBOX_LEFT_HAND:
+ case HITBOX_LEFT_FOREARM:
+ case HITBOX_LEFT_UPPER_ARM:
+ return HITGROUP_LEFTARM;
+ case HITBOX_RIGHT_HAND:
+ case HITBOX_RIGHT_FOREARM:
+ case HITBOX_RIGHT_UPPER_ARM:
+ return HITGROUP_RIGHTARM;
+ default:
+ return HITGROUP_GENERIC;
+ }
+}
+
+const char* util::definition_index_to_name( int index ) {
+ index = std::clamp( index, 0, 65 );
+
+ switch( index ) {
+ case 0:
+ return xors( "knife" );
+ case WEAPON_DEAGLE:
+ return xors( "deagle" );
+ case WEAPON_ELITE:
+ return xors( "elite" );
+ case WEAPON_FIVESEVEN:
+ return xors( "five seven" );
+ case WEAPON_GLOCK:
+ return xors( "glock" );
+ case WEAPON_AK47:
+ return xors( "ak47" );
+ case WEAPON_AUG:
+ return xors( "aug" );
+ case WEAPON_AWP:
+ return xors( "awp" );
+ case WEAPON_FAMAS:
+ return xors( "famas" );
+ case WEAPON_G3SG1:
+ return xors( "g3sg1" );
+ case WEAPON_GALILAR:
+ return xors( "galil" );
+ case WEAPON_M249:
+ return xors( "m249" );
+ case WEAPON_M4A1:
+ return xors( "m4a4" );
+ case WEAPON_MAC10:
+ return xors( "mac10" );
+ case WEAPON_P90:
+ return xors( "p90" );
+ case WEAPON_UMP45:
+ return xors( "ump45" );
+ case WEAPON_XM1014:
+ return xors( "xm1014" );
+ case WEAPON_BIZON:
+ return xors( "bizon" );
+ case WEAPON_MAG7:
+ return xors( "mag7" );
+ case WEAPON_NEGEV:
+ return xors( "negev" );
+ case WEAPON_SAWEDOFF:
+ return xors( "sawed-off" );
+ case WEAPON_TEC9:
+ return xors( "tec9" );
+ case WEAPON_TASER:
+ return xors( "zeus" );
+ case WEAPON_HKP2000:
+ return xors( "p2000" );
+ case WEAPON_MP7:
+ return xors( "mp7" );
+ case WEAPON_MP9:
+ return xors( "mp9" );
+ case WEAPON_NOVA:
+ return xors( "nova" );
+ case WEAPON_P250:
+ return xors( "p250" );
+ case WEAPON_SCAR20:
+ return xors( "scar20" );
+ case WEAPON_SG556:
+ return xors( "sg556" );
+ case WEAPON_SSG08:
+ return xors( "ssg08" );
+ case WEAPON_KNIFEGG:
+ return xors( "golden knife" ); // for the gun game hackers
+ case WEAPON_KNIFE:
+ return xors( "knife" );
+ case WEAPON_FLASHBANG:
+ return xors( "flash" );
+ case WEAPON_HEGRENADE:
+ return xors( "nade" );
+ case WEAPON_SMOKEGRENADE:
+ return xors( "smoke" );
+ case WEAPON_MOLOTOV:
+ return xors( "molotov" );
+ case WEAPON_DECOY:
+ return xors( "decoy" );
+ case WEAPON_INCGRENADE:
+ return xors( "incendiary" );
+ case WEAPON_C4:
+ return xors( "c4" );
+ case WEAPON_KNIFE_T:
+ return xors( "knife" );
+ case WEAPON_M4A1_SILENCER:
+ return xors( "M4A1" );
+ case WEAPON_USP_SILENCER:
+ return xors( "usp" );
+ case WEAPON_CZ75A:
+ return xors( "cz75" );
+ case WEAPON_R8REVOLVER:
+ return xors( "revolver" );
+ default:
+ return xors( "none" );
+ }
+}