summaryrefslogtreecommitdiff
path: root/cheat/internal_rewrite/visual_player.cpp
diff options
context:
space:
mode:
authorboris <wzn@moneybot.cc>2018-11-28 16:00:02 +1300
committerboris <wzn@moneybot.cc>2018-11-28 16:00:02 +1300
commit3d412a4b30a9f7c7f51ea6562e694315948bd3da (patch)
tree26d67dfd1f3e5fd12903ad13e85d0cb8bcf8f21c /cheat/internal_rewrite/visual_player.cpp
parente4729e4393d90271a3814c7a79950a660c48325a (diff)
cleaned up
in short, the cheat and loader are now separate solutions. unused stuff was moved into the legacy solution in case anyone wants to compile it or whatever. i can change this back if you want to. also, i configured the loader to compile in x64, and have separate build types for linux and win64
Diffstat (limited to 'cheat/internal_rewrite/visual_player.cpp')
-rw-r--r--cheat/internal_rewrite/visual_player.cpp1174
1 files changed, 1174 insertions, 0 deletions
diff --git a/cheat/internal_rewrite/visual_player.cpp b/cheat/internal_rewrite/visual_player.cpp
new file mode 100644
index 0000000..f14a0d7
--- /dev/null
+++ b/cheat/internal_rewrite/visual_player.cpp
@@ -0,0 +1,1174 @@
+#include <algorithm>
+
+#include "visual.hpp"
+#include "context.hpp"
+#include "base_cheat.hpp"
+#include "renderer.hpp"
+#include "input_system.hpp"
+#include "math.hpp"
+
+#undef PlaySound
+
+//2k lines of code here
+int screen_w, screen_h;
+con_var< bool > dbg_anims{ &data::holder_, fnv( "dbg_anims" ), false };
+
+namespace features
+{
+ void c_visuals::update_position( int index, const vec3_t& pos ) {
+ m_stored_pos[ index ] = pos;
+ if( m_anim_progress[ index ] > 0.f && m_anim_progress[ index ] <= 0.3f
+ && m_has_seen[ index ] && g_settings.visuals.dormant ) {
+ m_anim_progress[ index ] = 0.3f;
+ }
+ }
+
+ void c_visuals::reset_position( ) {
+ for( size_t i{ }; i < 65; ++i ) {
+ m_anim_progress[ i ] = 0.f;
+ m_has_seen[ i ] = false;
+ }
+ }
+
+ void c_visuals::store_hit( ) {
+ if( !g_settings.visuals.hitmarkers )
+ return;
+
+ g_csgo.m_surface( )->PlaySound( xors( "buttons\\arena_switch_press_02.wav" ) );
+ m_last_hit = g_csgo.m_globals->m_curtime;
+ }
+
+ void c_visuals::radar( ) {
+ if( !g_settings.visuals.radar( ) )
+ return;
+
+ for( int i = 0; i < 32; i++ ) {
+ auto ent = g_csgo.m_entlist( )->GetClientEntity( i );
+ if( !ent || !ent->is_valid( ) )
+ continue;
+
+ ent->m_bSpotted( ) = true;
+ }
+ }
+
+ void c_visuals::draw_hits( ) {
+ if( !g_settings.visuals.hitmarkers || !g_ctx.run_frame( ) )
+ return;
+
+ float delta = ( g_csgo.m_globals->m_curtime - m_last_hit ) * 1.5f;
+ if( std::abs( delta ) > 1.0f ) return;
+
+ clr_t col = g_settings.menu.menu_color;
+ if( delta > 0.75f ) {
+ col.a( ) = 255 * ( 1.0f - delta ) * 4.f;
+ }
+
+ auto get_rotated_point = [ ]( vec2_t point, float rotation, float distance ) {
+ float rad = DEG2RAD( rotation );
+
+ point.x += sin( rad ) * distance;
+ point.y += cos( rad ) * distance;
+
+ return point;
+ };
+
+
+ for( size_t i{ }; i < 2; ++i ) {
+ float rotation = 135.f + i * 90.f;
+
+ vec2_t center = { screen_w * 0.5f, screen_h * 0.5f };
+
+ for( size_t dist = 7; dist < 14; ++dist ) {
+ vec2_t start = get_rotated_point( center, rotation, dist );
+ vec2_t end = get_rotated_point( center, rotation, dist + 1 );
+
+ vec2_t rot_start = get_rotated_point( center, rotation - 180.f, dist );
+ vec2_t rot_end = get_rotated_point( center, rotation - 180.f, dist + 1 );
+
+ int point = dist - 6;
+ float percentage = point / 7;
+
+ percentage = 1.f - percentage;
+ percentage *= std::clamp( delta + 0.75f, 0.f, 1.f );
+
+ clr_t draw = col;
+ draw.a( ) *= percentage;
+
+ draw_line( start, end, draw );
+ draw_line( rot_start, rot_end, draw );
+ }
+ }
+ }
+
+ struct box_t {
+ int x, y, w, h;
+ };
+
+ box_t get_box( c_base_player* ent, vec3_t stored_origin ) {
+ const matrix3x4& matrix = ent->m_CoordinateFrame( );
+
+ vec2_t min_corner{ FLT_MAX, FLT_MAX };
+ vec2_t max_corner{ FLT_MIN, FLT_MIN };
+
+ vec3_t min_pos;
+ vec3_t max_pos;
+
+ matrix3x4 bone_matrix[ 128 ];
+ memcpy( bone_matrix, ent->m_CachedBoneData( ).GetElements( ), ent->m_CachedBoneData( ).GetSize( ) * sizeof( matrix3x4 ) );
+
+ auto hdr = g_csgo.m_model_info( )->GetStudiomodel( ent->ce( )->GetModel( ) );
+
+ for( size_t i{ }; i < hdr->numbones; ++i ) {
+ auto bone = hdr->GetBone( i );
+
+ if( bone && bone->parent != -1 && bone->flags & 0x100 ) {
+ auto& matrix = bone_matrix[ i ];
+ vec3_t hitbox = vec3_t( matrix[ 0 ][ 3 ], matrix[ 1 ][ 3 ], matrix[ 2 ][ 3 ] );
+ hitbox -= ent->ce( )->GetRenderOrigin( );
+ hitbox += stored_origin;
+
+
+ vec2_t pos = util::screen_transform( hitbox );
+
+ if( pos.x < min_corner.x )
+ min_corner.x = pos.x;
+
+ if( pos.x > max_corner.x )
+ max_corner.x = pos.x;
+
+ if( pos.y < min_corner.y )
+ min_corner.y = pos.y;
+
+ if( pos.y > max_corner.y )
+ max_corner.y = pos.y;
+ }
+ }
+
+ vec2_t origin = util::screen_transform( stored_origin );
+ if( max_corner.y > 1 && max_corner.x > 1 && min_corner.y < screen_h && min_corner.x < screen_w ) {
+ vec3_t origin_zoffset = stored_origin;
+ origin_zoffset.z += 10;
+
+ vec2_t delta = util::screen_transform( origin_zoffset ) - origin;
+
+ min_corner.x += delta.y;
+ max_corner.x -= delta.y;
+
+ min_corner.y += delta.y;
+ max_corner.y -= delta.y;
+ }
+ else {
+ return { -100, -100, 0, 0 };
+ }
+
+ int x = ( int )min_corner.x;
+ int w = ( int )( max_corner.x - min_corner.x );
+
+ int y = ( int )min_corner.y;
+ int h = ( int )( max_corner.y - min_corner.y );
+
+ return { x, y, w, h };
+ }
+
+ void c_visuals::out_of_fov( c_base_player* ent, const vec3_t& pos, clr_t col ) {
+ vec2_t screen;
+ vec2_t circle;
+
+ auto find_point = [ ]( vec2_t& point, float deg_x, float deg_y ) {
+ float x2 = screen_w / 2.f;
+ float y2 = screen_h / 2.f;
+
+ float d = sqrt( pow( point.x - x2, 2 ) + pow( point.y - y2, 2 ) );
+ float r_x = deg_x / d;
+ float r_y = deg_y / d;
+
+ point.x = r_x * point.x + ( 1.f - r_x ) * x2;
+ point.y = r_y * point.y + ( 1.f - r_y ) * y2;
+ };
+
+ auto get_screen_point = [ ]( vec2_t& screen, const vec3_t& delta ) {
+ decltype( auto ) w2s_matrix = g_csgo.m_engine( )->WorldToScreenMatrix( );
+ float x;
+ float w;
+ float y;
+
+ screen.x = w2s_matrix[ 0 ][ 0 ] * delta[ 0 ] + w2s_matrix[ 0 ][ 1 ] * delta[ 1 ] + w2s_matrix[ 0 ][ 2 ] * delta[ 2 ] + w2s_matrix[ 0 ][ 3 ];
+ screen.y = w2s_matrix[ 1 ][ 0 ] * delta[ 0 ] + w2s_matrix[ 1 ][ 1 ] * delta[ 1 ] + w2s_matrix[ 1 ][ 2 ] * delta[ 2 ] + w2s_matrix[ 1 ][ 3 ];
+ w = w2s_matrix[ 3 ][ 0 ] * delta[ 0 ] + w2s_matrix[ 3 ][ 1 ] * delta[ 1 ] + w2s_matrix[ 3 ][ 2 ] * delta[ 2 ] + w2s_matrix[ 3 ][ 3 ];
+
+ if( w < 0.001f ) {
+ float invw = -1.0f / w;
+ screen.x *= invw;
+ screen.y *= invw;
+ }
+ else {
+ float invw = 1.0f / w;
+ screen.x *= invw;
+ screen.y *= invw;
+ }
+
+ x = float( screen_w ) / 2.f;
+ y = float( screen_h ) / 2.f;
+ x += 0.5f * screen.x * screen_w + 0.5f;
+ y -= 0.5f * screen.y * screen_h + 0.5f;
+ screen.x = x;
+ screen.y = y;
+ };
+
+ screen = util::screen_transform( pos );//get_screen_point( screen, pos );
+ circle = util::screen_transform( pos );// get_screen_point( circle, pos );
+
+ float radius = g_settings.visuals.out_of_pov_radius * 0.49f;
+
+ float ratio = g_settings.visuals.out_of_pov_radius;
+
+ float w = screen_w * ratio + screen_h * ( 1.0f - ratio );
+
+ find_point( screen, w * radius,
+ float( screen_h ) * radius );
+
+ auto min = std::min< int >( screen_w, screen_h ) * radius;
+ find_point( circle, float( min ), float( min ) );
+
+ auto rot_around_center = [ ]( vec2_t start, float rot ) {
+ float rad = rot * ( M_PI / 180.f );
+
+ start.x += sin( rad ) * float( g_settings.visuals.out_of_pov_size );
+ start.y += cos( rad ) * float( g_settings.visuals.out_of_pov_size );
+
+ return start;
+ };
+
+ float delta_x = ( float( screen_w / 2 ) - circle.x );
+ float delta_y = ( float( screen_h / 2 ) - circle.y );
+
+ auto hyp = sqrt( delta_x * delta_x + delta_y * delta_y );
+
+ float cos_ = delta_x / hyp;
+
+ float deg = RAD2DEG( acos( cos_ ) );
+
+ if( screen.y < screen_h / 2 ) {
+ deg *= -1.f;
+ }
+
+ auto rotated_pos_1 = rot_around_center( screen, deg + 115 );
+ auto rotated_pos_2 = rot_around_center( screen, deg + 65 );
+
+ col.a( ) *= 0.8f;
+
+ vertex_t v[ ] = {
+ { screen },
+ { rotated_pos_1 },
+ { rotated_pos_2 }
+ };
+
+ if( !g_settings.misc.hide_from_obs )
+ g_renderer.draw_polygon( 3, v, col );
+ else {
+ draw_line( screen, rotated_pos_1, col );
+ draw_line( screen, rotated_pos_2, col );
+ draw_line( rotated_pos_1, rotated_pos_2, col );
+ }
+ }
+
+ void c_visuals::update_glow( ) {
+ if( !g_settings.visuals.active || g_settings.misc.hide_from_obs )
+ return;
+
+#ifdef HEADER_MODULE
+ static auto manager_ptr = g_header.patterns.glow_manager + 0x3;
+#else
+ static auto manager_ptr = pattern::first_code_match( g_csgo.m_chl.dll( ), xors( "0F 11 05 00 00 00 00 83 C8 01" ), 0x3 );
+#endif
+
+ auto glow_object_manager = *( GlowObjectManager_t** )( manager_ptr );
+ auto glow_count = glow_object_manager->Count;
+ auto glow_objects = glow_object_manager->DataPtr;
+
+ if( glow_count > 500 || glow_count <= 0 )
+ return;
+
+ for( int i{ }; i < glow_count; ++i ) {
+ auto& object = glow_objects[ i ];
+
+ auto ent = object.m_pEntity->as< c_base_player >( );
+ if( !ent ) continue;
+
+ if( ent->is_player( ) ) {
+ if( g_settings.visuals.glow &&
+ ent->is_valid( ) && ent->has_valid_anim( ) && ( ent->m_iTeamNum( ) != g_ctx.m_local->m_iTeamNum( ) ||
+ g_settings.visuals.friendlies || g_settings.visuals.chams.friendlies ) ) {
+
+ clr_t clr = ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) ?
+ g_settings.visuals.glow_friendly : g_settings.visuals.glow_enemy;
+
+ object.color = clr.to_fclr( );
+ object.m_bRenderWhenOccluded = true;
+ object.m_bRenderWhenUnoccluded = false;
+ object.m_flBloomAmount = 0.85f;
+ }
+ }
+ else {
+ auto ce = ent->ce( );
+ auto client_class = ce->GetClientClass( );
+ if( !client_class ) continue;
+ int class_id = client_class->m_class_id;
+ if( class_id != CBaseWeaponWorldModel && ( strstr( client_class->m_name, xors( "Weapon" ) )
+ || class_id == CDEagle || class_id == CAK47 ) ) {
+ bool glow = g_settings.visuals.weapon_esp == 2 || g_settings.visuals.weapon_esp == 3;
+ object.color = g_settings.visuals.weapon_esp_clr( ).to_fclr( );
+ object.m_bRenderWhenOccluded = true;
+ object.m_bRenderWhenUnoccluded = false;
+ object.m_flBloomAmount = glow ? 0.85f : 0.0f;
+ }
+ else {
+ auto model = ce->GetModel( );
+ if( !model ) continue;
+
+ bool glow = g_settings.visuals.grenade_esp( ) == 2 || g_settings.visuals.grenade_esp( ) == 3;
+ auto hdr = g_csgo.m_model_info( )->GetStudiomodel( model );
+ if( !strstr( hdr->name, xors( "thrown" ) ) && !strstr( hdr->name, xors( "dropped" ) ) )
+ continue;
+
+ object.color = g_settings.visuals.grenade_esp_clr( ).to_fclr( );
+ object.m_bRenderWhenOccluded = true;
+ object.m_bRenderWhenUnoccluded = false;
+ object.m_flBloomAmount = glow ? 0.85f : 0.0f;
+ }
+ }
+ }
+ }
+
+ inline clr_t blend_clr( clr_t in, float progress ) {
+ static const clr_t clr_gray = { 160, 160, 160, 255 };
+ int a = in.a( );
+
+ clr_t ret = clr_t::blend( clr_gray, in, 0.1f + progress * 0.9f );
+ ret.a( ) = a;
+ return ret;
+ }
+
+ void c_visuals::update_positions( ) {
+ CUtlVector< CSndInfo > sound_info{ };
+
+ g_csgo.m_engine_sound( )->GetActiveSounds( sound_info );
+
+ for( size_t i{ }; i < sound_info.GetSize( ); ++i ) {
+ auto& snd = sound_info.GetElements( )[ i ];
+
+ if( snd.origin ) {
+ int idx = snd.sound_source;
+ auto ent = g_csgo.m_entlist( )->GetClientEntity( idx );
+
+ if( ent && ent->is_player( ) && ent->ce( )->IsDormant( ) )
+ update_position( idx, snd.origin[ 0 ] );
+ }
+ }
+ }
+
+ void c_visuals::draw_players( ) {
+ static constexpr float anim_rate = 1.0f / 0.5f;
+ static float pov_progress[ 65 ]{ };
+
+ auto resource = c_base_player::get_player_resource( );
+
+ for( int i{ }; i < 65; ++i ) {
+ auto ent = g_csgo.m_entlist( )->GetClientEntity< >( i );
+
+ if( !ent || !ent->is_player( ) || !ent->is_alive( ) || ent == g_ctx.m_local ) {
+ m_has_seen[ i ] = false;
+ m_anim_progress[ i ] = 0.f;
+ continue;
+ }
+
+ if( !ent->has_valid_anim( ) )
+ continue;
+
+ if( i == ( g_ctx.m_local->m_hObserverTarget( ) & 0xfff ) )
+ continue;
+
+ if( ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) &&
+ !g_settings.visuals.friendlies( ) )
+ continue;
+
+ float rate = g_csgo.m_globals->m_frametime * anim_rate;
+ float& anim = m_anim_progress[ i ];
+ float alpha = anim;
+ bool dormant = ent->ce( )->IsDormant( );
+ int health = ent->m_iHealth( );
+ auto origin = ent->ce( )->GetRenderOrigin( );
+ int right_pos = 0;
+ int bottom_pos = 0;
+ bool too_distant = true;
+ if( g_ctx.m_local )
+ too_distant = ent->m_vecOrigin( ).dist_to( g_ctx.m_local->m_vecOrigin( ) ) > 2000.f;
+
+ if( !dormant ) {
+ update_position( i, origin );
+ if( anim > 0.f )
+ anim = std::clamp( anim + rate, 0.f, 1.f );
+ else
+ anim = 0.5f;
+
+ m_has_seen[ i ] = true;
+ }
+ else {
+ if( anim < 0.3f && g_settings.visuals.dormant && !too_distant ) {
+ rate *= 0.02f;
+ }
+ anim = std::clamp( anim -= rate, 0.f, 1.0f );
+ if( m_anim_progress[ i ] <= 0.f ) {
+ m_has_seen[ i ] = false;
+ continue;
+ }
+ }
+
+ auto box = get_box( ent, m_stored_pos[ i ] );
+
+ clr_t col = ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) ?
+ g_settings.visuals.box_friendly : g_settings.visuals.box_enemy;
+
+ if( dormant ) {
+ col = blend_clr( col, anim );
+ col.a( ) *= anim;
+ }
+
+ if( box.x > screen_w || box.x + box.w < 0 ||
+ box.y > screen_h || box.y + box.h < 0 ) {
+ if( g_settings.visuals.out_of_pov ) {
+ auto& anim = pov_progress[ i ];
+
+ if( dormant )
+ anim = std::clamp( anim -= g_csgo.m_globals->m_frametime * anim_rate, 0.f, 1.0f );
+ else
+ anim = std::clamp( anim += g_csgo.m_globals->m_frametime * anim_rate, 0.f, 1.0f );
+
+ col.a( ) *= anim;
+ out_of_fov( ent, ent->ce( )->GetRenderOrigin( ), col );
+ }
+ continue;
+ }
+
+ pov_progress[ i ] = 0.f;
+
+ if( g_settings.visuals.skeleton( ) && !dormant ) {
+ clr_t col = ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) ? g_settings.visuals.skeleton_friendly : g_settings.visuals.skeleton_enemy;
+ col.a( ) *= alpha;
+
+ auto hdr = g_csgo.m_model_info( )->GetStudiomodel( ent->ce( )->GetModel( ) );
+ if( hdr ) {
+ matrix3x4 matrix[ 128 ];
+ memcpy( matrix, ent->m_CachedBoneData( ).GetElements( ),
+ ent->m_CachedBoneData( ).GetSize( ) * sizeof( matrix3x4 ) );
+
+ for( size_t bone{ }; bone < hdr->numbones; ++bone ) {
+ auto b = hdr->GetBone( bone );
+ if( b && b->flags & 0x100 && b->parent != -1 ) {
+ vec3_t child = vec3_t{ matrix[ bone ][ 0 ][ 3 ], matrix[ bone ][ 1 ][ 3 ], matrix[ bone ][ 2 ][ 3 ] };
+ vec3_t parent = vec3_t{ matrix[ b->parent ][ 0 ][ 3 ], matrix[ b->parent ][ 1 ][ 3 ], matrix[ b->parent ][ 2 ][ 3 ] };
+
+ auto child_screen = util::screen_transform( child );
+ auto parent_screen = util::screen_transform( parent );
+
+ draw_line( child_screen, parent_screen, col );
+ }
+ }
+ }
+ }
+
+ if( g_settings.visuals.box( ) ) {
+ auto alpha_ = col.a( );
+ float percent = float( alpha_ ) / 255.f;
+ draw_rect( box.x + 1, box.y + 1, box.w - 2, box.h - 2, clr_t( 0, 0, 0, 180 * alpha * percent ) );
+ draw_rect( box.x, box.y, box.w, box.h, col );
+ }
+
+ if( g_settings.visuals.health( ) ) {
+ auto fill = box.h - 1;
+ fill *= std::clamp( health, 0, 100 ) * 0.01f;
+
+ auto hp_col = clr_t(
+ std::min< int >( 510 * ( 100 - health ) / 100, 255 ),
+ std::min< int >( 510 * health / 100, 255 ),
+ 0,
+ 255 * alpha );
+
+ draw_filled_rect( box.x - 4, box.y, 3, box.h + 1, clr_t( 0, 0, 0, 170 * alpha ) );
+ draw_filled_rect( box.x - 3, box.y + box.h - fill, 1, fill, hp_col );
+
+ if( health != 100 )
+ draw_string( box.x - 2, box.y + 1 + box.h - fill - 3, ALIGN_CENTER, false, clr_t( 255, 255, 255, 255 * alpha ), "%d", health );
+ }
+
+ if( g_settings.visuals.name( ) ) {
+ clr_t col = ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) ? g_settings.visuals.name_friendly( ) : g_settings.visuals.name_enemy( );
+ col.a( ) *= alpha;
+
+ char name[ 32 ];
+ ent->get_name_safe( name );
+
+ draw_string( box.x + box.w / 2, box.y - 12, ALIGN_CENTER, true,
+ blend_clr( col, anim ), name );
+ }
+
+ if( g_settings.visuals.money( ) ) {
+ int x_pos = box.x + box.w + 2;
+ int y_pos = box.y - 1 + right_pos;
+ draw_string( x_pos, y_pos, ALIGN_LEFT, false,
+ blend_clr( esp_green( 255 * alpha ), anim ),
+ xors( "%d$" ), ent->m_iAccount( ) );
+
+ right_pos += 9;
+ }
+
+ if( g_settings.visuals.resolver_indicator && g_settings.rage.resolver && g_cheat.m_player_mgr.is_cheater( i ) && !dormant && g_ctx.m_local->is_valid( ) ) {
+ bool can_backtrack_lby = g_cheat.m_ragebot.m_lagcomp->can_backtrack_entity( i ) == RECORD_LBY && !ent->is_breaking_lc( );
+ bool can_backtrack = !!g_cheat.m_ragebot.m_lagcomp->can_backtrack_entity( i ) && !ent->is_breaking_lc( );
+ int x_pos = box.x + box.w + 3;
+ int y_pos = box.y - 1 + right_pos;
+
+ bool is_fake = !can_backtrack_lby;
+ bool is_breaking_lc = g_cheat.m_prediction.is_breaking_lc( i );
+
+ if( is_breaking_lc ) {
+ draw_string( x_pos, y_pos, ALIGN_LEFT, false,
+ clr_t( 255, 255, 255, 255 * alpha ),
+ xors( "lc" ) );
+
+ right_pos += 9;
+ }
+ else if( is_fake && g_ctx.m_local->is_valid( ) ) {
+ if( ent->m_fFlags( ) & FL_ONGROUND && ent->get_anim_velocity( ).length2d( ) < 0.1f && !dormant && !g_settings.misc.hide_from_obs ) {
+ float update = g_cheat.m_ragebot.m_lagcomp->get_flick_time( i );
+ float delta = ( ent->m_flSimulationTime( ) - update ) * 0.9f;
+
+ if( delta >= 0.f && delta <= 1.f ) {
+
+ //don't allocate 20000000 bytes on the stack thx
+ static vertex_t v[ 48 ];
+
+ float radius = box.w / 5.f;
+
+ radius = std::clamp( radius, 4.f, 8.f );
+
+ right_pos += radius * 2;
+
+ v[ 0 ].init( x_pos + radius / 2 + 2, y_pos + radius / 2 + 2 );
+
+ int progress = ( 1.f - delta ) * 48;
+
+
+ const float step = ( M_PI * 2.f ) / 48.f;
+
+ for( int r = 1; r < progress; ++r ) {
+ float s = sin( step * r ) * radius;
+ float c = cos( step * r ) * radius;
+
+
+ v[ r ].init( x_pos + radius / 2 + c + 2, y_pos + s + radius / 2 + 2 );
+ }
+
+ g_renderer.draw_filled_circle( x_pos + radius / 2 + 2, y_pos + radius / 2 + 2, radius + 1, clr_t( 0, 0, 0, 170 * alpha ) );
+ g_renderer.draw_polygon( progress, v, g_settings.visuals.lby_bar_clr );
+ }
+ }
+ else {
+ draw_string( x_pos, y_pos, ALIGN_LEFT, false,
+ clr_t( 255, 255, 255, 255 * alpha ),
+ xors( "fake" ) );
+
+ right_pos += 9;
+ }
+ }
+
+ if( !!g_cheat.m_ragebot.m_resolver->get_state( i ) && !dormant && g_ctx.m_local->is_valid( ) && g_settings.misc.hide_from_obs( ) ) {
+ float update = g_cheat.m_ragebot.m_lagcomp->get_flick_time( i );
+ float delta = ( ent->m_flSimulationTime( ) - update ) * 0.9f;
+ if( delta >= 0.f && delta <= 1.f ) {
+ float max = box.w - 2.f;
+ float fill = max * std::clamp( delta, 0.f, 1.f );
+
+ draw_filled_rect( box.x, box.y + box.h + 3 + bottom_pos,
+ box.w, 3, clr_t( 0, 0, 0, 180 * alpha ) );
+
+ clr_t col = g_settings.visuals.lby_bar_clr;
+ col.a( ) *= alpha;
+
+ draw_filled_rect( box.x + 1, box.y + box.h + 4 + bottom_pos,
+ fill, 1, blend_clr( col, anim ) );
+
+ bottom_pos += 4;
+ }
+ }
+ }
+
+ if( g_settings.visuals.ping( ) ) {
+ auto ping = ent->get_ping( );
+
+ if( ping > 310 ) {
+ int x_pos = box.x + box.w + 3;
+ int y_pos = box.y - 1 + right_pos;
+
+ draw_string( x_pos, y_pos, ALIGN_LEFT, false,
+ blend_clr( esp_blue( 255 * alpha ), anim ),
+ xors( "ping" ) );
+
+ right_pos += 9;
+ }
+ }
+
+ if( g_settings.visuals.weapon( ) ) {
+ auto weapon = ent->get_weapon( );
+ if( weapon ) { //magic font
+ auto weapon_info = weapon->get_wpn_info( );
+ int max = weapon_info->max_clip_ammo;
+
+ if( g_settings.visuals.ammo && max > 1 ) {
+ auto progress = float( weapon->m_iClip1( ) ) / max;
+ float fill = box.w - 2.f;
+ float percent = fill * progress;
+
+ draw_filled_rect( box.x, box.y + box.h + 3 + bottom_pos,
+ box.w, 3, clr_t( 0, 0, 0, 180 * alpha ) );
+
+ clr_t col = g_settings.visuals.ammo_bar_clr;
+ col.a( ) *= alpha;
+
+ draw_filled_rect( box.x + 1, box.y + box.h + 4 + bottom_pos,
+ percent, 1, blend_clr( col, anim ) );
+
+ if( progress < 0.25f ) {
+ draw_string(
+ box.x + percent, box.y + box.h + bottom_pos, ALIGN_LEFT, false,
+ clr_t( 255, 255, 255, 180 * alpha ), "%d", weapon->m_iClip1( ) );
+ }
+
+ bottom_pos += 4;
+ }
+
+
+ char wep_str[ 64 ];
+ sprintf_s< 64 >( wep_str, "%s", util::definition_index_to_name( weapon->m_iItemDefinitionIndex( ) ) );
+
+ draw_string( box.x + box.w / 2, box.y + box.h + 3 + bottom_pos, ALIGN_CENTER, false,
+ clr_t( 255, 255, 255, alpha * 255 ), wep_str );
+ }
+ }
+
+ if( g_settings.visuals.flags( ) ) {
+ int x_pos = box.x + box.w + 3;
+ int y_pos = box.y - 1;
+
+ if( ent->m_bIsScoped( ) && right_pos < box.h ) {
+ draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, clr_t( 255, 255, 255, 255 * alpha ), xors( "scope" ) );
+ right_pos += 9;
+ }
+
+ if( ent->is_flashed( ) && right_pos < box.h ) {
+ const float step = M_PI * 2.f / 6;
+
+ float radius = std::clamp( box.w / 5.f, 4.f, 8.f );
+
+ for( int i = 0; i < 6; ++i ) {
+ float c = cos( step * i + DEG2RAD( 30.f ) );
+ float s = sin( step * i + DEG2RAD( 30.f ) );
+
+ float off = 0;
+
+ if( i == 5 || i == 0 )
+ off = 0.25f;
+
+ draw_line( x_pos + c * radius / 2 + radius / 2 + 2, y_pos + right_pos + s * radius / 2 + radius / 2 + 3,
+ x_pos + c * ( radius + off ) + radius / 2 + off + 2, y_pos + s * ( radius + off ) + right_pos + radius / 2 + 3,
+ blend_clr( esp_blue( 255 * alpha ), anim ) );
+ }
+
+ //draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, blend_clr( esp_blue( 255 * alpha ), anim ), xors( "flash" ) );
+ right_pos += radius * 2.3f;
+ }
+
+ if( !( util::is_low_fps( ) && g_settings.rage.preserve_fps( ) ) ) {
+ if( m_hit_flag[ i ] && g_ctx.m_local->is_valid( ) && i != g_cheat.m_ragebot.get_target( ) && g_settings.rage.enabled ) {
+ clr_t col = m_hit_flag[ i ] == HIT_1W ? clr_t( 255, 255, 255, 255 * alpha ) : esp_red( alpha * 255 );
+ draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, blend_clr( col, anim ), xors( "hit" ) );
+ right_pos += 9;
+ }
+ }
+
+ if( ent->is_reloading( ) && right_pos < box.h ) {
+ draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, clr_t( 255, 255, 255, 255 * alpha ), xors( "rel" ) );
+ right_pos += 9;
+ }
+ }
+
+
+
+ static con_var< bool > dbg_multipoint{ &data::holder_, fnv( "dbg_multipoint" ), false };
+ if( dbg_multipoint( ) ) {
+ auto should_multipoint = [ ]( int hitbox, bool moving ) -> bool {
+ auto& setting = g_settings.rage.multipoint;
+
+ switch( hitbox ) {
+ case HITBOX_HEAD:
+ return setting.head;
+ case HITBOX_PELVIS:
+ case HITBOX_BODY:
+ return setting.stomach;
+ //case HITBOX_CHEST:
+ case HITBOX_UPPER_CHEST:
+ case HITBOX_THORAX:
+ return setting.chest;
+ case HITBOX_RIGHT_THIGH:
+ case HITBOX_LEFT_THIGH:
+ if( moving && g_settings.rage.ignore_limbs_moving )
+ return false;
+
+ if( g_settings.rage.preserve_fps && util::is_low_fps( ) )
+ return false;
+
+ return setting.thighs;
+
+ case HITBOX_LEFT_CALF:
+ case HITBOX_RIGHT_CALF:
+ if( moving && g_settings.rage.ignore_limbs_moving )
+ return false;
+
+ if( g_settings.rage.preserve_fps && util::is_low_fps( ) )
+ return false;
+
+ return setting.calves;
+ default:
+ return false;
+ }
+ };
+
+ bool moving = ent->m_vecVelocity( ).length2d( ) > 0.1f && !ent->is_fakewalking( );
+
+ matrix3x4 bone_matrix[ 128 ];
+ ent->ce( )->SetupBones( bone_matrix, 128, BONE_USED_BY_HITBOX, 0.f );
+
+ for( int hitbox = 0; hitbox < HITBOX_MAX; ++hitbox ) {
+ if( should_multipoint( hitbox, moving ) ) {
+ const auto model = ent->ce( )->GetModel( );
+ if( !model ) continue;
+
+ auto hdr = g_csgo.m_model_info( )->GetStudiomodel( model );
+ if( !hdr ) continue;
+
+ auto set = hdr->pHitboxSet( ent->m_nHitboxSet( ) );
+ if( !set ) continue;
+
+ //literally 20000 iq, the best multipoint
+ //im an actual fucking retard jesus christ
+ auto box = set->pHitbox( hitbox );
+ if( !box ) continue;
+
+ vec3_t center = ( box->bbmax + box->bbmin ) * 0.5f;
+
+ float dist = box->m_flRadius;
+
+ if( box->m_flRadius == -1.f )
+ dist = center.dist_to( box->bbmin ) * 0.85f;
+ vec3_t min_dir = math::angle_vectors( math::vector_angles( center, box->bbmin ) );
+ vec3_t min = center + min_dir * dist * g_settings.rage.active->m_hitbox_scale * 1.1f;
+
+ if( box->m_flRadius == -1.f )
+ dist = center.dist_to( box->bbmax ) * 0.85f;
+ vec3_t max_dir = math::angle_vectors( math::vector_angles( center, box->bbmax ) );
+ vec3_t max = center + max_dir * dist * g_settings.rage.active->m_hitbox_scale * 1.1f;
+
+ std::vector< vec3_t > points;
+
+ points.push_back( center );
+
+ if( g_settings.rage.multipoint_enable( ) == 1 ||
+ hitbox == HITBOX_LEFT_CALF || hitbox == HITBOX_RIGHT_CALF ||
+ hitbox == HITBOX_LEFT_THIGH || hitbox == HITBOX_RIGHT_THIGH ) {
+ points.push_back( vec3_t{ min.x, min.y, center.z } );
+ points.push_back( vec3_t{ max.x, min.y, center.z } );
+ points.push_back( vec3_t{ min.x, max.y, center.z } );
+ points.push_back( vec3_t{ max.x, max.y, center.z } );
+ }
+ else if( g_settings.rage.multipoint_enable( ) == 2 ) {
+ points.push_back( vec3_t{ max.x, max.y, max.z } );
+ points.push_back( vec3_t{ min.x, max.y, max.z } );
+ points.push_back( vec3_t{ max.x, min.y, max.z } );
+ points.push_back( vec3_t{ min.x, min.y, max.z } );
+
+ points.push_back( vec3_t{ max.x, max.y, min.z } );
+ points.push_back( vec3_t{ min.x, max.y, min.z } );
+ points.push_back( vec3_t{ max.x, min.y, min.z } );
+ points.push_back( vec3_t{ min.x, min.y, min.z } );
+ }
+ else if( g_settings.rage.multipoint_enable( ) == 3 ) {
+ points.push_back( vec3_t{ min.x, min.y, center.z } );
+ points.push_back( vec3_t{ max.x, min.y, center.z } );
+ points.push_back( vec3_t{ min.x, max.y, center.z } );
+ points.push_back( vec3_t{ max.x, max.y, center.z } );
+
+ points.push_back( vec3_t{ max.x, max.y, max.z } );
+ points.push_back( vec3_t{ min.x, max.y, max.z } );
+ points.push_back( vec3_t{ max.x, min.y, max.z } );
+ points.push_back( vec3_t{ min.x, min.y, max.z } );
+
+ points.push_back( vec3_t{ max.x, max.y, min.z } );
+ points.push_back( vec3_t{ min.x, max.y, min.z } );
+ points.push_back( vec3_t{ max.x, min.y, min.z } );
+ points.push_back( vec3_t{ min.x, min.y, min.z } );
+ }
+
+ for( size_t i1 = 0; i1 < points.size( ); i1++ ) {
+ auto& it = points.at( i1 );
+
+ auto trans = math::vector_transform( it, bone_matrix[ box->bone ] );
+ auto w2s_box = util::screen_transform( trans );
+
+ draw_circle( ( int )w2s_box.x, ( int )w2s_box.y, 3, esp_blue( ), 16 );
+ }
+ }
+ }
+ }
+
+#ifdef _DEBUG
+ static con_var< bool > dbg_bt{ &data::holder_, fnv( "dbg_bt" ), false };
+ if( dbg_bt( ) && i == g_cheat.m_ragebot.get_shot_target( ) ) {
+ auto hdr = g_csgo.m_model_info( )->GetStudiomodel( ent->ce( )->GetModel( ) );
+ if( hdr ) {
+ auto matrix = g_cheat.m_ragebot.get_shot_matrix( );
+ for( size_t bone{ }; bone < hdr->numbones; ++bone ) {
+ auto b = hdr->GetBone( bone );
+ if( b && b->flags & 0x100 && b->parent != -1 ) {
+ vec3_t child = vec3_t{ matrix[ bone ][ 0 ][ 3 ], matrix[ bone ][ 1 ][ 3 ], matrix[ bone ][ 2 ][ 3 ] };
+ vec3_t parent = vec3_t{ matrix[ b->parent ][ 0 ][ 3 ], matrix[ b->parent ][ 1 ][ 3 ], matrix[ b->parent ][ 2 ][ 3 ] };
+
+ auto child_screen = util::screen_transform( child );
+ auto parent_screen = util::screen_transform( parent );
+
+ draw_line( child_screen, parent_screen, clr_t( 255, 255, 255, 200 ) );
+ }
+ }
+ }
+ }
+
+ static con_var< bool > dbg_pose{ &data::holder_, fnv( "dbg_pose" ) };
+ if( dbg_pose( ) ) {
+ for( size_t i{ }; i < 24; ++i ) {
+ int x = box.x + box.w + 15;
+ int y = box.y + 11 * i;
+
+ draw_string( x, y, ALIGN_LEFT, false, clr_t( 255, 255, 255 ), "%d %f", i, ent->m_flPoseParameter( )[ i ] );
+ }
+ }
+
+ static con_var< bool > dbg_anim{ &data::holder_, fnv( "dbg_anim" ) };
+ if( dbg_anim( ) ) {
+ draw_string( box.x - 14, box.y - 15, ALIGN_RIGHT, false, clr_t( 255, 255, 255 ), "%f", ent->get_animdata( ).m_last_velocity.length2d( ) );
+ draw_string( box.x - 14, box.y, ALIGN_RIGHT, false, clr_t( 255, 255, 255 ), "%f", ent->get_animdata( ).m_anim_velocity.length2d( ) );
+ for( size_t i{ }; i < 13; ++i ) {
+ int x = box.x - 15;
+ int y = box.y + 11 * ( i + 2 );
+
+ draw_string( x, y, ALIGN_RIGHT, false, clr_t( 255, 255, 255 ), "%d %f", i, ent->m_AnimOverlay( ).GetElements( )[ i ].m_flCycle );
+ }
+
+ auto ent_origin = ent->m_vecOrigin( );
+ auto ent_origin_vel = origin + ent->get_animdata( ).m_anim_velocity;
+ ent_origin_vel.z = ent_origin.z;
+
+ draw_line( util::screen_transform( ent_origin ), util::screen_transform( ent_origin_vel ), esp_blue( ) );
+ }
+#endif
+ }
+ }
+
+ void c_visuals::store_sound( int index, vec3_t origin ) {
+ if( !g_settings.visuals.sound )
+ return;
+
+ auto ent = g_csgo.m_entlist( )->GetClientEntity< >( index );
+ if( ent && ent->is_player( ) && ent->is_alive( ) && ent != g_ctx.m_local ) {
+ if( ent->m_iTeamNum( ) != g_ctx.m_local->m_iTeamNum( ) || ( ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) && g_settings.visuals.friendlies( ) ) ) {
+ sound_t new_sound;
+ new_sound.m_time = g_csgo.m_globals->m_curtime;
+ new_sound.m_ent = index;
+ new_sound.m_pos = origin;
+ new_sound.m_pos.z += 5.f;
+ m_sounds.emplace_back( new_sound );
+ }
+ }
+ }
+
+ void c_visuals::store_hit( context::shot_data_t* shot ) {
+ if( !g_settings.visuals.hits )
+ return;
+
+ hit_t new_hit;
+
+ auto ent = g_csgo.m_entlist( )->GetClientEntity( shot->m_enemy_index );
+
+ new_hit.m_ent = shot->m_enemy_index;
+ ent->get_name_safe( new_hit.m_name );
+
+ memcpy( new_hit.m_matrix,
+ shot->m_matrix,
+ sizeof( matrix3x4 ) * 128 );
+
+ new_hit.m_pos = shot->m_enemy_pos;
+ new_hit.m_time = g_csgo.m_globals->m_curtime;
+
+ m_hits.push_back( new_hit );
+ }
+
+ void c_visuals::draw_skeletons( ) {
+ if( !g_settings.visuals.hits )
+ return;
+
+ for( size_t i{ }; i < m_hits.size( ) && !m_hits.empty( ); ++i ) {
+ auto& hit = m_hits[ i ];
+
+ float delta = g_csgo.m_globals->m_curtime - hit.m_time;
+ if( std::abs( delta ) > g_settings.visuals.target_time )
+ m_hits.erase( m_hits.begin( ) + i );
+ }
+
+ for( auto& it : m_hits ) {
+ auto ent = g_csgo.m_entlist( )->GetClientEntity( it.m_ent );
+
+ if( !ent || !ent->is_player( ) )
+ continue;
+
+ if( !ent->is_alive( ) )
+ it.m_dead = true;
+
+ auto hdr = g_csgo.m_model_info( )->GetStudiomodel( ent->ce( )->GetModel( ) );
+
+ auto matrix = it.m_matrix;
+ vec3_t pos = it.m_pos;
+ float delta = g_csgo.m_globals->m_curtime - it.m_time;
+
+ float total = g_settings.visuals.target_time;
+ float threshold = total * 0.5f;
+
+ float fade = total - delta < threshold ? ( total - delta ) / ( total * 0.5f ) : 1.f;
+
+ float dist_fade = 1.f;
+ if( ent->is_valid( ) && !it.m_dead ) {
+ dist_fade = 300.f - std::clamp( ent->ce( )->GetRenderOrigin( ).dist_to( pos ), 1.f, 300.f ) / 300.f;
+ }
+
+ clr_t col = clr_t( 255, 255, 255, 100 * dist_fade * fade );
+
+ clr_t outer_col = ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) ?
+ g_settings.visuals.glow_friendly :
+ g_settings.visuals.glow_enemy;
+
+ outer_col.a( ) *= 0.65f;
+ outer_col.a( ) *= ( fade * dist_fade );
+
+ for( size_t bone{ }; bone < hdr->numbones; ++bone ) {
+ auto b = hdr->GetBone( bone );
+ if( b && b->flags & 0x100 && b->parent != -1 ) {
+ vec3_t child = vec3_t{ matrix[ bone ][ 0 ][ 3 ], matrix[ bone ][ 1 ][ 3 ], matrix[ bone ][ 2 ][ 3 ] };
+ vec3_t parent = vec3_t{ matrix[ b->parent ][ 0 ][ 3 ], matrix[ b->parent ][ 1 ][ 3 ], matrix[ b->parent ][ 2 ][ 3 ] };
+
+ auto child_screen = util::screen_transform( child );
+ auto parent_screen = util::screen_transform( parent );
+
+ draw_line( child_screen - vec2_t( 1, 1 ), parent_screen - vec2_t( 1, 1 ), outer_col );
+ draw_line( child_screen, parent_screen, col );
+
+ draw_line( child_screen + vec2_t( 1, 1 ), parent_screen + vec2_t( 1, 1 ), outer_col );
+ }
+ }
+ }
+ }
+
+ void c_visuals::update_hit_flags( ) {
+ if( !g_settings.visuals.flags || !g_settings.rage.enabled )
+ return;
+
+ if( util::is_low_fps( ) && g_settings.rage.preserve_fps )
+ return;
+
+ auto weapon = g_ctx.m_local->get_weapon( );
+
+ for( size_t i{ }; i < 65; ++i ) {
+ auto ent = g_csgo.m_entlist( )->GetClientEntity( i );
+
+ if( !ent || !ent->is_valid( ) || !ent->has_valid_anim( ) ||
+ ( ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) && !g_settings.rage.friendlies )
+ || ent->m_bGunGameImmunity( ) ) {
+ m_hit_flag[ i ] = HIT_NONE;
+ continue;
+ }
+
+ vec3_t local_pos = g_ctx.m_local->get_eye_pos( );
+ vec3_t enemy_pos = ent->get_hitbox_pos( 0 );
+
+ auto local_wep = g_ctx.m_local->get_weapon( );
+ auto enemy_wep = ent->get_weapon( );
+
+ if( !local_wep || !enemy_wep || local_wep->is_knife( ) || enemy_wep->is_knife( ) || local_wep->is_grenade( ) || enemy_wep->is_grenade( ) ) {
+ m_hit_flag[ i ] = HIT_NONE;
+ continue;
+ }
+
+ float local_dmg = g_cheat.m_autowall.run( g_ctx.m_local, ent, enemy_pos, false );
+ float enemy_dmg = g_cheat.m_autowall.run( ent, g_ctx.m_local, g_ctx.m_local->get_hitbox_pos( 0 ), false );
+
+ auto min_dmg = g_cheat.m_ragebot.get_min_dmg( ent );
+
+ if( enemy_dmg < 5.f && local_dmg > g_cheat.m_ragebot.get_min_dmg( ent ) )
+ m_hit_flag[ i ] = HIT_1W;
+ else if( enemy_dmg > 15.f && local_dmg < g_cheat.m_ragebot.get_min_dmg( ent ) )
+ m_hit_flag[ i ] = HIT_ALERT;
+ else
+ m_hit_flag[ i ] = HIT_NONE;
+ }
+ }
+
+ void c_visuals::store_ent_dmg( int attacker, int entindex, int dmg ) {
+ if( entindex == g_ctx.m_local->ce( )->GetIndex( ) )
+ return;
+
+ bool dead = false;
+ int hp = 100 - m_ent_dmg[ entindex ];
+
+ if( hp - dmg < 0 ) {
+ dmg = hp;
+ dead = true;
+ }
+
+ m_ent_dmg[ entindex ] += dmg;
+
+ auto ent = g_csgo.m_entlist( )->GetClientEntity( entindex );
+ if( attacker == g_csgo.m_engine( )->GetLocalPlayer( ) && ent && ent->is_player( ) && ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) && g_ctx.m_local->is_valid( ) ) {
+ m_teamdmg += ( g_csgo.m_globals->m_curtime - m_last_roundstart > 10.f ) || dead ? dmg : dmg * 2;
+ }
+ }
+
+ void c_visuals::on_round_start( ) {
+ reset_position( );
+
+ m_last_roundstart = g_csgo.m_globals->m_curtime;
+ for( size_t i{ }; i < 65; ++i ) {
+ m_ent_dmg[ i ] = 0.f;
+ }
+ }
+
+ void c_visuals::reset_local_dmg( ) {
+ m_teamdmg = 0;
+ }
+
+ void c_visuals::draw_sound( ) {
+ if( !g_settings.visuals.active ) return;
+ if( g_settings.misc.hide_from_obs ) return;
+
+ float time = g_csgo.m_globals->m_curtime;
+
+ if( m_sounds.empty( ) )
+ return;
+
+
+ for( size_t i{ }; i < m_sounds.size( ) && !m_sounds.empty( ); ++i ) {
+ auto& tr = m_sounds[ i ];
+
+ float delta = g_csgo.m_globals->m_curtime - tr.m_time;
+ if( delta > 0.001f || std::abs( delta ) > 0.001f ) m_sounds.erase( m_sounds.begin( ) + i );
+ }
+
+ if( !m_sounds.empty( ) ) {
+ for( auto& it : m_sounds ) {
+ auto ent = g_csgo.m_entlist( )->GetClientEntity( it.m_ent );
+ if( !ent || !ent->is_player( ) )
+ continue;
+
+ clr_t col = ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) ? g_settings.visuals.box_friendly : g_settings.visuals.box_enemy;
+ float delta = time - it.m_time;
+ if( !g_ctx.precache_model( xors( "materials/sprites/laserbeam.vmt" ) ) ) {
+ g_con->log( "nigga cant get" );
+ continue;
+ }
+
+ BeamInfo_t beam_info;
+
+ beam_info.m_nType = beam_ring_point;
+ beam_info.m_pszModelName = xors( "materials/sprites/laserbeam.vmt" );
+ beam_info.m_nModelIndex = g_csgo.m_model_info( )->GetModelIndex( xors( "materials/sprites/laserbeam.vmt" ) );
+ beam_info.m_flHaloScale = 0.0f;
+ beam_info.m_flLife = 0.75f; //0.09
+ beam_info.m_flWidth = 1.5f;
+ beam_info.m_flEndWidth = 1.5f;
+ beam_info.m_flFadeLength = 1.0f;
+ beam_info.m_flAmplitude = 0.f;
+ beam_info.m_flBrightness = col.a( );
+ beam_info.m_flSpeed = 2.f;
+ beam_info.m_nStartFrame = 0;
+ beam_info.m_flFrameRate = 60;
+ beam_info.m_flRed = col.r( );
+ beam_info.m_flGreen = col.g( );
+ beam_info.m_flBlue = col.b( );
+ beam_info.m_nSegments = 1;
+ beam_info.m_bRenderable = true;
+ beam_info.m_nFlags = 0;
+
+ beam_info.m_vecCenter = it.m_pos;
+ beam_info.m_flStartRadius = 0.f;
+ beam_info.m_flEndRadius = ( float )g_settings.visuals.sound_range( );
+
+ Beam_t* beam = g_csgo.m_beams( )->CreateBeamRingPoint( beam_info );
+
+ if( beam ) {
+ g_csgo.m_beams( )->DrawBeam( beam );
+ }
+ }
+ }
+ }
+
+ void c_visuals::operator()( ) {
+ g_csgo.m_engine( )->GetScreenSize( screen_w, screen_h );
+ if( g_ctx.run_frame( ) ) {
+ draw_local( );
+ }
+
+ if( !g_ctx.m_local )
+ return;
+
+ switch( g_settings.visuals.activation_type( ) ) {
+ case 0:
+ g_settings.visuals.active = false;
+ break;
+ case 1:
+ g_settings.visuals.active = true;
+ break;
+ case 2:
+ g_settings.visuals.active = g_input.is_key_pressed( g_settings.visuals.key );
+ break;
+ case 3: {
+ static bool held = false;
+ bool pressed = g_input.is_key_pressed( g_settings.visuals.key );
+ if( pressed ) {
+ if( !held )
+ g_settings.visuals.active ^= 1;
+ held = true;
+ }
+ else held = false;
+ }
+ break;
+ default:
+ g_settings.visuals.active = false;
+ break;
+ }
+
+ if( g_settings.visuals.active ) {
+ update_positions( );
+ draw_players( );
+ draw_skeletons( );
+ }
+
+ draw_world( );
+ draw_tracers( );
+ draw_hits( );
+ }
+} \ No newline at end of file