summaryrefslogtreecommitdiff
path: root/cheat/tf2/visuals_players.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/tf2/visuals_players.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/tf2/visuals_players.cpp')
-rw-r--r--cheat/tf2/visuals_players.cpp551
1 files changed, 551 insertions, 0 deletions
diff --git a/cheat/tf2/visuals_players.cpp b/cheat/tf2/visuals_players.cpp
new file mode 100644
index 0000000..8b9aaf9
--- /dev/null
+++ b/cheat/tf2/visuals_players.cpp
@@ -0,0 +1,551 @@
+#include <algorithm>
+
+#include "visuals.hpp"
+#include "ctx.hpp"
+#include "base_cheat.h"
+#include "renderer.hpp"
+#include "input_system.hpp"
+#include "math.h"
+#include "settings.h"
+#include "interfaces.h"
+//2k lines of code here
+int screen_w, screen_h;
+
+namespace features
+{
+ void c_visuals::update_position( int index, const vec3_t& pos ) {
+ m_stored_pos[ index ] = pos;
+ if( m_anim_progress[ index ] <= 0.3f && g_settings.visuals.dormant ) {
+ m_anim_progress[ index ] = 0.3f;
+ }
+ }
+
+ void c_visuals::store_hit( ) {
+ if( !g_settings.visuals.hitmarkers )
+ return;
+
+ cl.m_surface( )->play_sound( xors( "buttons\\arena_switch_press_02.wav" ) );
+ m_last_hit = cl.m_globals->curtime;
+ }
+
+
+ void c_visuals::draw_hits( ) {
+ if( !g_settings.visuals.hitmarkers || !g_ctx.run_frame( ) )
+ return;
+
+ static const clr_t col_start = clr_t( 231, 75, 75, 255 );
+ static const clr_t col_end = clr_t( 0xf4, 0x7c, 0xa8, 255 );
+
+ float delta = ( cl.m_globals->curtime - m_last_hit ) * 1.5f;
+ if( std::abs( delta ) > 1.0f ) return;
+
+ clr_t blend = clr_t::blend( col_start, col_end, delta );
+ if( delta > 0.75f ) {
+ blend.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 };
+ vec2_t start = get_rotated_point( center, rotation, 8.f );
+ vec2_t end = get_rotated_point( center, rotation, 17.f );
+
+ vec2_t rot_start = get_rotated_point( center, rotation - 180.f, 8.f );
+ vec2_t rot_end = get_rotated_point( center, rotation - 180.f, 17.f );
+
+ draw_line( start, end, blend );
+ draw_line( rot_start, rot_end, blend );
+ }
+ }
+
+ struct box_t {
+ int x, y, w, h;
+ };
+
+ box_t get_box( c_base_player* ent ) {
+ const matrix3x4& matrix = ent->m_CollisionGroup( );
+
+ vec3_t min = ent->m_vecMins( );
+ vec3_t max = ent->m_vecMaxs( );
+
+ std::array< vec3_t, 8 > point_list = {
+ vec3_t{ min.x, min.y, min.z },
+ vec3_t{ min.x, max.y, min.z },
+ vec3_t{ max.x, max.y, min.z },
+ vec3_t{ max.x, min.y, min.z },
+ vec3_t{ max.x, max.y, max.z },
+ vec3_t{ min.x, max.y, max.z },
+ vec3_t{ min.x, min.y, max.z },
+ vec3_t{ max.x, min.y, max.z }
+ };
+
+ std::array< float, 8 > x_points;
+ std::array< float, 8 > y_points;
+
+ vec2_t origin = util::screen_transform( ent->m_vecOrigin( ) );
+
+ for( auto& it : point_list ) {
+ vec3_t backup = it;
+ for( int i{ }; i < 3; ++i ) {
+ it[ i ] = backup.dot( ( const vec3_t& )( matrix[ i ] ) ) + matrix[ i ][ 3 ];
+ }
+ }
+
+ for( size_t i{ }; i < 8; ++i ) {
+ vec2_t w2s = util::screen_transform( point_list[ i ] );
+ x_points[ i ] = w2s.x;
+ y_points[ i ] = w2s.y;
+ }
+
+ std::sort( x_points.begin( ), x_points.end( ) );
+ std::sort( y_points.begin( ), y_points.end( ) );
+
+ int x = ( int )x_points.front( );
+ int w = ( int )x_points.back( ) - x;
+
+ int y = ( int )y_points.front( );
+ int h = ( int )y_points.back( ) - y;
+
+ return { x - ( int )origin.x, y - ( int )origin.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 = cl.m_engine( )->GetWorldToScreenMatrix( );
+ 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;
+
+ static auto glow_object_manager = *pattern::first_code_match< GlowObjectManager_t** >( cl.m_chl.dll( ), xors ( "8B 0D ? ? ? ? A1 ? ? ? ? 56 8B 37" ) ) + 0x2;
+ if( !glow_object_manager ) return;
+
+ static bool invalidated;
+ if( !g_settings.visuals.glow ) {
+ if( !invalidated ) {
+ invalidate_glow( );
+ invalidated = true;
+ }
+ return;
+ }
+
+ invalidated = false;
+ for( int i{ }; i < 64; ++i ) {
+ auto ent = cl.m_entlist( )->get_client_entity< c_base_player >( i );
+ if( !ent ) continue;
+
+
+ if( !ent->is_valid( ) ) {
+ continue;
+ }
+
+ if( ent->is_enemy( ) || g_settings.visuals.friendlies ) {
+ ent->m_bGlowEnabled( ) = true;
+ ent->update_glow_effect( );
+ }
+ }
+
+ if( !glow_object_manager->data.Count( ) ) return; //data count crashed yea lazy cool cool? cool
+ for( int i{ }; i < glow_object_manager->data.Count( ); ++i ) {
+ auto ent = ( c_base_player* )cl.m_entlist( )->get_entity_from_handle( glow_object_manager->data[ i ].ent_ptr );
+ if( ent && ent->is_valid( ) && ( ent->is_enemy( ) || g_settings.visuals.friendlies( ) ) ) {
+ clr_t clr = ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) ? g_settings.visuals.glow_friendly : g_settings.visuals.glow_enemy;
+ clr.a( ) = 200;
+ glow_object_manager->data[ i ].glow_color = clr.to_fclr( );
+ }
+ }
+
+ }
+
+ void c_visuals::invalidate_glow( ) {
+ for( int i{ }; i < 64; i++ ) {
+ auto ent = cl.m_entlist( )->get_client_entity< c_base_player >( i );
+ if( !ent ) continue;
+ if( ent->get_client_class( )->m_class_id == CTFPlayer ) {
+ ent->m_bGlowEnabled( ) = false;
+ ent->destroy_glow_effect( );
+ }
+ }
+ }
+
+ 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::draw_players( ) {
+ static constexpr float anim_rate = 1.0f / 0.3f;
+ static float pov_progress[ 65 ]{ };
+
+ auto resource = c_base_player::get_player_resource( );
+
+ for( int i{ }; i < 65; ++i ) {
+ auto ent = cl.m_entlist( )->get_client_entity< c_base_player >( i );
+
+ if( !ent || !ent->is_player( ) || !ent->is_alive( ) || ent == g_ctx.m_local )
+ 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 = cl.m_globals->frametime * anim_rate;
+ float& anim = m_anim_progress[ i ];
+ float alpha = anim;
+ bool dormant = ent->ce( )->is_dormant( );
+ int health = ent->m_iHealth( );
+ auto origin = ent->m_vecOrigin( );
+ auto box = get_box( ent );
+ 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( ) ) > 2500.f;
+
+ if( !dormant ) {
+ update_position( i, origin );
+ anim = 1.0f;
+ }
+ else {
+ if( anim < 0.3f && g_settings.visuals.dormant && !too_distant ) {
+ rate *= 0.01f;
+ }
+ anim = std::clamp( anim -= rate, 0.f, 1.0f );
+ if( m_anim_progress[ i ] <= 0.f )
+ continue;
+ }
+
+ 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;
+ }
+
+ auto w2s_cur_origin = util::screen_transform( m_stored_pos[ i ] );
+
+ box.x += w2s_cur_origin.x;
+ box.y += w2s_cur_origin.y;
+
+ 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 ];
+ anim = std::clamp( anim += cl.m_globals->frametime * anim_rate, 0.f, 1.0f );
+ if( dormant )
+ anim = std::clamp( anim -= cl.m_globals->frametime * anim_rate, 0.f, 1.0f );
+ else
+ anim = std::clamp( anim += cl.m_globals->frametime * anim_rate, 0.f, 1.0f );
+
+ col.a( ) *= anim;
+ out_of_fov( ent, origin, 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 = cl.m_modelinfo( )->GetStudioModel( ent->ce( )->get_model( ) );
+ if( hdr ) {
+ matrix3x4 matrix[ 128 ];
+ ent->ce( )->setup_bones( matrix, 128, 0x100, 0.f );
+
+ 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( ) ) {
+ draw_string( box.x + box.w / 2, box.y - 12, ALIGN_CENTER, true,
+ blend_clr( clr_t( 255, 255, 255, alpha * 255 ), anim ), ent->get_info( ).name );
+ }
+
+ if( g_settings.visuals.player_class( ) ) {
+ 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 ), ent->get_class_name( ) );
+
+ right_pos += 9;
+ }
+
+ if( g_settings.visuals.weapon( ) ) {
+ auto weapon = ent->get_active_weapon( );
+ if( weapon ) { //magic font
+ int max = weapon->get_max_clip_1( );
+
+ if( g_settings.visuals.ammo && max > 1 && g_settings.visuals.weapon == 1 && !g_settings.misc.hide_from_obs ) {
+ 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 ) );
+
+ draw_filled_rect( box.x + 1, box.y + box.h + 4 + bottom_pos,
+ percent, 1, blend_clr( clr_t( 66, 143, 244, 255 * alpha ), anim ) );
+
+ if( progress < 0.25f ) {
+ draw_string(
+ box.x + percent, box.y + box.h + 2 + bottom_pos, ALIGN_LEFT, false,
+ clr_t( 255, 255, 255, 180 * alpha ), "%d", weapon->m_iClip1( ) );
+ }
+
+ bottom_pos += 4;
+ }
+
+ /*if( g_settings.visuals.weapon == 1 && !g_settings.misc.hide_from_obs ) {
+ g_renderer.draw_string< ALIGN_CENTER >( 0xa1, box.x + box.w / 2, box.y + box.h + bottom_pos + 3,
+ clr_t( 255, 255, 255, alpha * 255 ), "%c", weapon->get_hud_icon( ) );
+ }*/
+ else {
+ char wep_str[ 64 ];
+ if( g_settings.visuals.ammo( ) && weapon->m_iClip1( ) > -1 )
+ sprintf_s< 64 >( wep_str, "%s [%d]", weapon->get_print_name( ), weapon->m_iClip1( ) );
+ else
+ sprintf_s< 64 >( wep_str, "%s", weapon->get_print_name( ) );
+
+ 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.conditions( ) ) {
+ int x_pos = box.x + box.w + 3;
+ int y_pos = box.y - 1;
+
+ switch( ent->m_nPlayerCond( ) ) {
+ case TFCond_Slowed:
+ draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, clr_t( 255, 255, 255, 255 * alpha ), xors( "slow" ) );
+ right_pos += 9;
+ break;
+ case TFCond_Zoomed: //dont work too lazy
+ draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, clr_t( 255, 255, 255, 255 * alpha ), xors( "scoped" ) );
+ right_pos += 9;
+ break;
+ case TFCond_Bonked:
+ draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, clr_t( 255, 255, 255, 255 * alpha ), xors( "bonk" ) );
+ right_pos += 9;
+ break;
+ case TFCond_Disguised:
+ draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, clr_t( 255, 255, 255, 255 * alpha ), xors( "disg" ) );
+ right_pos += 9;
+ break;
+ case TFCond_Cloaked:
+ draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, clr_t( 255, 255, 255, 255 * alpha ), xors( "cloak" ) );
+ right_pos += 9;
+ break;
+ case TFCond_Ubercharged:
+ draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, clr_t( 255, 255, 255, 255 * alpha ), xors( "uber" ) );
+ right_pos += 9;
+ break;
+ case TFCond_UberchargeFading:
+ draw_string( x_pos, y_pos + right_pos, ALIGN_LEFT, false, clr_t( 255, 255, 255, 255 * alpha ), xors( "uber" ) );
+ right_pos += 9;
+ break;
+ }
+
+ }
+
+ }
+ }
+
+ void c_visuals::operator()( ) {
+ cl.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 ) {
+ draw_players( );
+ }
+
+ draw_world( );
+ draw_hits( );
+ }
+} \ No newline at end of file