-
Автор темы
- #1
C++:
void c_anim_sync::on_fsn( c_client_fsn stage ) {
if ( stage != e_fsn::frame_update_end )
return;
if ( !cfg::get< bool >( "ragebot::enable" ) )
return;
for ( int i = 1; i <= 64; i++ ) {
auto player = static_cast< c_cs_player* >( interfaces::ent_list->get_client_ent( i ) );
if ( !player || !player->is_alive( ) || player->is_dormant( ) || player->is_immunie( ) ) {
player_records[ i ].clear( );
continue;
}
// thanks for this part skeet.
// and nemesis too using this part and buy source from: vk.com/lnk1181
// i not platina i fucking retard.
auto update = ( player_records[ i ].empty( ) || ( player->get_sim_time( ) > player->get_old_sim_time( ) ) );
if ( update && !player_records[ i ].empty( ) ) {
auto layer = &player->get_anim_layers( )[ 11 ];
auto previous_layer = &player_records[ i ].front( );
if ( layer->m_cycle == previous_layer->m_anim_layers[ 11 ].m_cycle ) {
player->get_sim_time( ) = player->get_old_sim_time( );
update = false;
continue;
}
}
if ( update ) {
// setup record.
player_records[ i ].emplace_back( c_lag_record( player ) );
// update player animations.
update_player_animation( player );
}
// size of validations bones.
while ( player_records[ i ].size( ) > 32 )
player_records[ i ].pop_back( );
}
}
void c_anim_sync::update_player_animation( c_cs_player* player ) {
auto state = player->get_anim_state( );
if ( !state )
return;
// setup record.
auto records &player_records[ player->index( ) ];
// records empty?
if ( records->empty( ) )
return;
// previous record?
c_lag_record* previous_record = nullptr;
// setup previous record.
if ( records->size( ) >= 2 )
previous_record = &records->at( 1 );
// setup record.
auto record = &records->front( );
// copy anim layers from player lag record.
std::memcpy( record->m_anim_layers, &player->get_anim_layers( ), 13 * sizeof( c_animation_layer ) );
// backup player stuff.
const auto backup_lby = player->get_lby( );
const auto backup_duck = player->get_duck_amount( );
const auto backup_flags = player->get_flags( );
const auto backup_eflags = player->get_ie_flags( );
// backup global_vars stuff.
const auto backup_cur_time = interfaces::global_vars->m_cur_time;
const auto backup_frame_time = interfaces::global_vars->m_frame_time;
const auto backup_real_time = interfaces::global_vars->m_real_time;
const auto backup_frame_count = interfaces::global_vars->frame_count;
const auto backup_tick_count = interfaces::global_vars->m_tick_count;
const auto backup_interp_amount = interfaces::global_vars->interp_amount;
// allow game update anims on per tick.
interfaces::global_vars->m_cur_time = player->get_sim_time( );
interfaces::global_vars->m_frame_time = interfaces::global_vars->m_interval_per_tick;
// calc velocity by anim overlays, etc..
if ( previous_record ) {
// simulation_time delta.
auto time_diff = game::time_to_ticks( player->get_sim_time( ) - previous_record->m_sim_time );
// origin delta.
auto origin_diff = player->get_origin( ) - previous_record->m_origin;
// anim speed for valid player velocity.
auto anim_speed = 0.f;
// calc velocity.
// based on new formula.
// ref: https://github.com/perilouswithadollarsign/cstrike15_src/blob/f82112a2388b841d72cb62ca48ab1846dfcc11c8/game/client/c_baseplayer.cpp#L1139
player->get_velocity( ) = origin_diff / game::ticks_to_time( time_diff );
// calculate animation speed yielded by anim overlays.
// thanks for this part skeet.
if ( player->get_flags( ) & e_flags::fl_onground && previous_record->m_flags & e_flags::fl_onground
&& record->m_anim_layers[ 11 ].m_weight > 0.f
&& record->m_anim_layers[ 11 ].m_weight < 1.f
&& record->m_anim_layers[ 11 ].m_play_back_rate == previous_record->m_anim_layers[ 11 ].m_play_back_rate ) {
auto anim_modifier = 0.35f * ( 1.f - record->m_anim_layers[ 11 ].m_weight );
if ( anim_modifier > 0.f && anim_modifier < 1.f )
anim_speed = max_speed * ( anim_modifier + 0.55f );
}
// this velocity is valid ONLY in anim update tick!!
// so dont store it to record as get_velocity.
if ( anim_speed > 0.f ) {
player->get_velocity( ).x *= anim_speed;
player->get_velocity( ).y *= anim_speed;
}
// fix z velocity if player in air.
if ( !( player->get_flags( ) & e_flags::fl_onground ) )
player->get_velocity( ).z -= globals->m_cvars::sv_gravity->get_float( ) * TICKS_TO_TIME( time_diff ) * 0.5f;
else // reset value if on ground.
player->get_velocity( ).z = 0.f;
}
// skip call to C_BaseEntity::CalcAbsoluteVelocity.
player->get_ie_flags( ) &= ~0x1000u;
// set abs velocity to player velocity.
player->set_abs_velocity( player->get_velocity( ) );
// fix some issues with velocity.
// thanks skeet for this part.
if ( player->get_flags( ) & e_flags::fl_onground && player->get_velocity( ).length( ) <= 0.f && record->m_anim_layers[ 6 ].m_play_back_rate <= 0.f && record->m_anim_layers[ 6 ].m_weight <= 0.f )
player->get_velocity( ).clear( );
else {
auto v30 = max_speed;
if ( player->get_flags( ) & e_flags::in_duck )
v30 *= 0.34f;
else if ( player->is_walking( ) )
v30 *= 0.52f;
auto v35 = record->m_anim_layers[ 6 ].m_weight * v30;
player->get_velocity( ) *= v35 / player->get_velocity( ).length( );
}
// thanks onetap for this part.
if ( previous_record ) {
// copy previous layers from previous lag_record data.
std::memcpy( previous_record->m_anim_layers, &player->get_anim_layers( ), 13 * sizeof( c_animation_layer ) );
// fix with simulation ticks.
auto play_back_rate = record->m_anim_layers[ 11 ].m_play_back_rate;
if ( play_back_rate != 0.f ) {
auto ticks = 0;
auto layer_cycle = record->m_anim_layers[ 11 ].m_cycle;
auto previous_play_back_rate = previous_record->m_anim_layers[ 11 ].m_play_back_rate;
if ( previous_play_back_rate != 0.f ) {
auto previous_cycle = previous_record->m_anim_layers[ 11 ].m_cycle;
ticks = 0;
if ( previous_cycle > layer_cycle )
layer_cycle += 1.f;
while ( layer_cycle > previous_cycle ) {
const auto ticks_backup = ticks;
const auto playback_mult_ipt = interfaces::global_vars->m_interval_per_tick * previous_play_back_rate;
previous_cycle += interfaces::global_vars->m_interval_per_tick * previous_play_back_rate;
if ( previous_cycle >= 1.0f )
previous_play_back_rate = play_back_rate;
++ticks;
if ( previous_cycle > layer_cycle && ( previous_cycle - layer_cycle ) > ( playback_mult_ipt * 0.5f ) )
ticks = ticks_backup;
}
}
// max choking value for sv_maxusrcmdprocessticks its 15, 16 is prediction error.
// refs:
// https://github.com/perilouswithadollarsign/cstrike15_src/blob/f82112a2388b841d72cb62ca48ab1846dfcc11c8/game/server/player.cpp#L129
// https://github.com/perilouswithadollarsign/cstrike15_src/blob/master/game/server/player_command.cpp#L318
// https://github.com/perilouswithadollarsign/cstrike15_src/blob/f82112a2388b841d72cb62ca48ab1846dfcc11c8/game/server/player.cpp#L3579-L3590
record->m_lag = std::clamp( ticks, 0, 15 );
}
// fix various issues with the game.
// these issues can only occur when a player is choking data.
if ( record->m_lag > 1 ) {
// delta in duckamt and delta in time.
auto duck_amount_per_tick = ( player->get_duck_amount( ) - previous_record->m_duck ) / record->m_lag;
for ( int i = 1; i <= record->m_lag; i++ ) {
// get simulated time.
auto simulated_time = previous_record->m_sim_time + game::ticks_to_time( i );
// fix crouching players.
// the duck amount we receive when people choke is of the last simulation.
// if a player chokes packets the issue here is that we will always receive the last duckamount.
// but we need the one that was animated.
if ( duck_amount_per_tick )
player->get_duck_amount( ) = previous_record->m_duck + duck_amount_per_tick * ( float )i;
// fix landing anims.
// thanks for this part skeet.
auto v490 = player->get_seq_act( record->m_anim_layers[ 4 ].m_sequence );
if ( !( player->get_flags( ) & e_flags::fl_onground ) && !( previous_record->m_flags & e_flags::fl_onground )
&& record->m_anim_layers[ 4 ].m_weight > 0.f && previous_record->m_anim_layers[ 4 ].m_weight <= 0.f
|| !( v490 == e_activity::act_csgo_land_light || v490 == e_activity::act_csgo_land_heavy ) )
player->get_flags( ) &= ~e_flags::fl_onground;
else
player->get_flags( ) |= e_flags::fl_onground;
// get simulated ticks.
auto simulated_ticks = game::time_to_ticks( simulated_time );
// fixes for networking players.
interfaces::global_vars->m_real_time = simulated_time;
interfaces::global_vars->m_cur_time = simulated_time;
interfaces::global_vars->frame_count = simulated_ticks;
interfaces::global_vars->m_tick_count = simulated_ticks;
interfaces::global_vars->interp_amount = 0.f;
// 'm_animating' returns true if being called from SetupVelocity, passes raw velocity to animstate.
globals::m_animating = true;
player->update_clientside_animation();
globals::m_animating = false;
// restore backup global_vars data.
interfaces::global_vars->m_real_time = backup_realtime;
interfaces::global_vars->m_cur_time = backup_cur_time;
interfaces::global_vars->frame_count = backup_frame_count;
interfaces::global_vars->m_tick_count = backup_tick_count;
interfaces::global_vars->interp_amount = backup_interp_amount;
}
}
}
// 'm_animating' returns true if being called from SetupVelocity, passes raw velocity to animstate.
globals::m_animating = true;
player->update_clientside_animation();
globals::m_animating = false;
// build main matrix and copy bone cache for main matrix.
bone_manager->setup_bones_rebuilt( record->m_player_matrix, e_flags_bones::bone_used_by_anything );
std::memcpy( player->m_cached_bones( ).base( ), record->m_player_matrix player->m_cached_bones( ).count( ) * sizeof( matrix3x4_t ) );
// restore backup globals_vars data.
interfaces::global_vars->m_cur_time = backup_cur_time;
interfaces::global_vars->m_frame_time = backup_frame_time;
// restore backup player data.
player->get_lby( ) = backup_lby;
player->get_duck_amount( ) = backup_duck;
player->get_flags( ) = backup_flags;
player->get_ie_flags( ) = backup_eflags;
// store data on records.
record->store_data( player, false );
// if shift tickbase or broke origin than set record->m_broke_lc to true.
// refs:
// https://github.com/perilouswithadollarsign/cstrike15_src/blob/f82112a2388b841d72cb62ca48ab1846dfcc11c8/game/server/player_lagcompensation.cpp#L385
// https://github.com/perilouswithadollarsign/cstrike15_src/blob/f82112a2388b841d72cb62ca48ab1846dfcc11c8/game/server/player_lagcompensation.cpp#L392
if ( ( record->m_origin - previous_record->m_origin ).length_sqr( ) > 4096.f
&& player->get_sim_time( ) <= player->get_old_sim_time( ) )
record->m_broke_lc = true;
}