#include "hooks.hpp" #include "context.hpp" #include "base_cheat.hpp" void __fastcall hooks::update_clientside_animation( void* ecx_, void* edx_ ) { static bool first_update = true; auto old_func = g_csgo.m_local->get_old_function< decltype( &hooks::update_clientside_animation ) >( 218 ); auto ent = ( c_base_player* )( ecx_ ); static ent_animdata_t prev_anims; static float last_choke; static float last_update; static float last_spawntime = 0.f; static float last_yaw; // Arbitrary number much. if( !g_settings.rage.anti_aim || !g_ctx.m_local->is_valid( ) || std::abs( last_update - g_csgo.m_globals->m_curtime ) > TICKS_TO_TIME( 20 ) || last_spawntime != ent->m_flSpawnTime( ) ) { last_update = g_csgo.m_globals->m_curtime; first_update = true; if( last_spawntime != ent->m_flSpawnTime( ) ) last_spawntime = ent->m_flSpawnTime( ); return old_func( ecx_, edx_ ); } *( byte* )( uintptr_t( ent ) + 0x270 ) = 1; if( !g_cheat.m_lagmgr.get_choked( ) || g_cheat.m_lagmgr.get_sent( ) > 1 || first_update ) { vec3_t backup; g_csgo.m_prediction( )->GetLocalViewAngles( backup ); float backup_curtime = g_csgo.m_globals->m_curtime; float backup_frametime = g_csgo.m_globals->m_frametime; g_csgo.m_globals->m_curtime = g_ctx.pred_time( ); g_csgo.m_globals->m_frametime = TICK_INTERVAL( ); if( g_csgo.m_globals->m_curtime != ent->get_animstate( )->m_flLastClientSideAnimationUpdateTime ) { last_update = backup_curtime; last_choke = std::max( g_csgo.m_globals->m_curtime - ent->get_animstate( )->m_flLastClientSideAnimationUpdateTime, TICK_INTERVAL( ) ); vec3_t real_angle = g_ctx.m_thirdperson_angle; float pitch; if( g_ctx.m_local->get_animstate( )->m_bInHitGroundAnimation && ( g_ctx.m_local->m_fFlags( ) & FL_ONGROUND ) ) { bool dist = g_settings.rage.enabled( ) && g_settings.rage.selection_type( ) == 1; int target = util::get_closest_player( dist ); if( target != -1 ) { auto t = g_csgo.m_entlist( )->GetClientEntity( target ); pitch = math::vector_angles( ent->m_vecOrigin( ), t->m_vecOrigin( ) ).x; } else pitch = -10.f; real_angle.x = pitch; } last_yaw = ent->get_animstate( )->m_flGoalFeetYaw; if( last_yaw < 0.f ) last_yaw += 360.f; g_csgo.m_prediction( )->SetViewAngles( real_angle ); ent->get_animstate( )->update( real_angle.y, real_angle.x ); old_func( ecx_, edx_ ); memcpy( &prev_anims, &ent->get_animdata( ), sizeof( prev_anims ) ); prev_anims.m_last_simtime = last_yaw; ent->cache_anim_data( ); } g_csgo.m_prediction( )->SetLocalViewAngles( backup ); g_csgo.m_globals->m_curtime = backup_curtime; g_csgo.m_globals->m_frametime = backup_frametime; } ent->restore_anim_data( true ); float lerp = std::min( last_choke, TICK_INTERVAL( ) * 2.f ); float update_delta = last_choke; float update_lerp = std::clamp( update_delta - lerp, 0.f, 1.f ); if( update_delta > 0.f ) lerp = std::clamp( lerp, 0.f, update_delta ); float lerp_progress = ( last_update + lerp - g_csgo.m_globals->m_curtime ) / lerp; float lerp_yaw = 0.f; if( !first_update && ( ent->get_animstate( )->m_velocity > 0.1f || std::abs( last_yaw - ent->get_animstate( )->m_flGoalFeetYaw ) < 35.f ) && update_delta <= TICK_INTERVAL( ) * 2.f ) { float yaw = ent->get_animstate( )->m_flGoalFeetYaw; if( yaw < 0.f ) yaw += 360.f; if( std::abs( yaw - last_yaw ) >= 180.f ) lerp_yaw = yaw; else { lerp_yaw = math::lerp( yaw, last_yaw, std::clamp( lerp_progress, 0.f, 1.f ) ); } } else { lerp_yaw = ent->get_animstate( )->m_flGoalFeetYaw; } //interpolate EVERYTHING if( !first_update && !( ent->get_animstate( )->m_bInHitGroundAnimation && ent->get_animstate( )->m_bOnGround ) ) { for( size_t i{ }; i < 18; ++i ) { float old_param = prev_anims.m_poseparams.at( i ); float param = ent->get_animdata( ).m_poseparams.at( i ); if( i == BODY_YAW ) continue; if( !isfinite( old_param ) || !isfinite( param ) ) continue; float final_param = math::lerp( param, old_param, std::clamp( lerp_progress, 0.f, 1.f ) ); ent->m_flPoseParameter( )[ i ] = final_param; } for( size_t i{ }; i < 13; ++i ) { auto old_cycle = prev_anims.m_animlayers.at( i ).m_flCycle; auto cycle = ent->get_animdata( ).m_animlayers.at( i ).m_flCycle; if( old_cycle > 0.9f && cycle < 0.1f ) { cycle += 1.f; } float final_cycle = math::lerp( cycle, old_cycle, std::clamp( lerp_progress, 0.f, 1.f ) ); if( final_cycle > 1.f ) final_cycle -= 1.f; ent->m_AnimOverlay( ).GetElements( )[ i ].m_flCycle = final_cycle; } } if( !first_update ) { //*( byte* )( uintptr_t( ent ) + 0x270 ) = 0; ent->set_abs_angles( vec3_t( 0, lerp_yaw, 0 ) ); bool backup = ent->get_animstate( )->m_bOnGround; ent->get_animstate( )->m_bOnGround = false; ent->invalidate_bone_cache( ); ent->ce( )->SetupBones( nullptr, 128, BONE_USED_BY_ANYTHING, 0.f ); ent->get_animstate( )->m_bOnGround = backup; } first_update = false; }