-
Автор темы
- #1
Код:
// tickbase.hpp
#pragma once
struct local_data_t {
float m_spawn_time{}, m_abs_yaw{};
int m_tick_base{}, m_adjusted_tick_base{}, m_shift_amount{};
bool m_override_tick_base{}, m_restore_tick_base{};
vec3_t m_move{};
CUserCmd m_user_cmd{};
};
class c_exploits {
private:
int get_type( );
//struct cfg_t {
// int m_dt_key{ };
//};
//sdk::cfg_var_t< cfg_t > m_cfg{ 0x05562b95u, { } };
public:
enum exploits_type_t : int {
type_none = 0,
type_doubletap = 3,
type_ready = 4,
type_defensive = 5
};
void handle_context( CUserCmd* user_cmd );
__forceinline bool is_charged( );
bool try_to_recharge( bool* send_packet, CUserCmd* user_cmd );
bool is_peeking( ang_t& angle, float ticks, bool auto_stop ); // qang
int clock_correction( ) const;
int adjust_tick_base(
const int old_new_cmds,
const int total_new_cmds, const int delta
) const;
void handle_break_lc( const std::uintptr_t ecx, const std::uintptr_t edx, const int slot, bf_write* buffer, int& from, int& to, int* m_new_cmds, int* m_backup_cmds );
void process_real_cmds( const std::uintptr_t ecx, const std::uintptr_t edx, const int slot, bf_write* buffer, int& from, int& to, int* m_new_cmds, int* m_backup_cmds );
void skip_lag_interpolation( bool status );
bool m_allow_choke{ };
//__forceinline cfg_t& cfg( ) { return m_cfg.value( ); };
bool m_charged{ }, m_shift_cycle{ }, m_had_target{ };
int m_ticks_allowed{ },
m_next_shift_amount{ }, m_recharge_cmd{ }, m_type{ }, m_simulation_diff{ }, m_prediction_tick{ };
int m_process_ticks{ 0 };
int m_cur_shift_amount{ 0 };
int m_max_process_ticks;
int m_last_processed{ };
int m_last_defensive_tick{ }, m_last_shift_tick{ };
bool is_in_defensive{ false };
bool m_will_target{ false };
bool m_peeking_someone{ };
bool m_in_charge{ };
std::array< local_data_t, 150u > m_local_data{};
__forceinline bool& in_charge( ) { return m_in_charge; }
};
inline const auto g_exploits = std::make_unique< c_exploits >( );
// tickbase.cpp
#include "includes.h"
#pragma optimize( "", off )
void write_useer_cmd( bf_write* buf, CUserCmd* in, CUserCmd* out ) {
static auto WriteUsercmdF = pattern::find( g_csgo.m_client_dll, XOR( "55 8B EC 83 E4 F8 51 53 56 8B D9 8B 0D" ) );
__asm
{
mov ecx, buf
mov edx, in
push out
call WriteUsercmdF
add esp, 4
}
}
int c_exploits::get_type( ) {
if ( !g_cl.m_local )
return 0;
if ( GetKeyState( VK_XBUTTON2 ) )
return 3;
return 0;
}
void c_exploits::handle_context( CUserCmd* user_cmd ) {
static ConVar* sv_maxusrcmdprocessticks = g_csgo.m_cvar->FindVar( HASH( "sv_maxusrcmdprocessticks" ) );
m_max_process_ticks = sv_maxusrcmdprocessticks->GetInt( ) - 2;
Weapon* weapon = g_cl.m_weapon;
int shift_amount{ };
if ( ( m_type = get_type( ) ) ) {
if ( weapon ) {
const auto item_index = weapon->m_iItemDefinitionIndex( );
if ( item_index != ZEUS
&& item_index != C4
&& !( item_index >= FLASHBANG && item_index <= MOLOTOV ) ) {
if ( m_ticks_allowed ) {
if ( m_type == 1 )
shift_amount = 8;
else if ( m_type == 2 || m_type == 3 ) {
//if ( hacks::g_aim_bot->can_shoot( false, 0, false ) ) // i dont think i need this, i will seee
shift_amount = m_ticks_allowed;
}
if ( g_csgo.m_globals->m_curtime >= g_cl.m_local->m_flNextAttack( ) ) {
m_next_shift_amount = shift_amount;
}
goto prepare_cheat;
}
}
}
};
m_cur_shift_amount = m_next_shift_amount = 0;
if ( !m_type && m_ticks_allowed > 0 ) {
m_type = type_ready;
m_cur_shift_amount = m_next_shift_amount = m_ticks_allowed;
m_charged = true;
}
prepare_cheat:
const auto wpn_data = weapon != nullptr ? weapon->GetWpnData( ) : nullptr;
if ( wpn_data == nullptr || !wpn_data )
return;
if ( ( m_charged )
&& ( user_cmd->m_buttons & IN_ATTACK )
&& wpn_data != nullptr
&& wpn_data->m_weapon_type != WEAPONTYPE_GRENADE )
user_cmd->m_buttons &= ~IN_ATTACK;
if ( m_charged )
m_allow_choke = false;
else {
if ( m_type
&& m_ticks_allowed ) {
if ( g_csgo.m_cl->m_net_channel->m_choked_packets >= 1 ) // should work
m_allow_choke = false;
else
m_allow_choke = true;
} else {
if ( g_csgo.m_cl->m_net_channel->m_choked_packets >= 14 )
m_allow_choke = false;
else
m_allow_choke = true;
}
}
if ( ( m_charged )
&& ( user_cmd->m_buttons & IN_ATTACK )
&& wpn_data->m_weapon_type != WEAPONTYPE_GRENADE )
user_cmd->m_buttons &= ~IN_ATTACK;
if ( GetAsyncKeyState( VK_END ) ) {
g_notify.add( "m_ticks_allowed : " + std::to_string( m_ticks_allowed ) + " \n" );
g_notify.add( "m_charged : " + std::to_string( m_charged ) + " \n" );
g_notify.add( "m_next_shift_amo : " + std::to_string( m_next_shift_amount ) + " \n" );
g_notify.add( "m_cur_shift_amou : " + std::to_string( m_cur_shift_amount ) + " \n" );
}
}
bool c_exploits::try_to_recharge( bool* send_packet, CUserCmd* user_cmd ) {
if ( ( g_csgo.m_globals->m_curtime - g_cl.m_local->m_flSpawnTime( ) ) < 1.f )
return false;
//if ( g_aim_bot->stop_type( )
// || g_ctx->anim_data( ).m_local_data.m_old_shot )
// return false;
if ( m_recharge_cmd != g_csgo.m_cl->m_last_outgoing_command
&& ( g_csgo.m_cl->m_choked_commands || m_ticks_allowed >= 14 ) )
return false;
if ( !get_type( )
/* || std::abs( g_ctx->anim_data( ).m_local_data.m_last_shot_time - g_csgo.m_globals->m_curtime ) < 0.40f*/ )
return false;
if ( m_ticks_allowed >= 14 ) {
m_charged = true;
if ( ( m_ticks_allowed + 1 ) <= 16 ) {
if ( m_ticks_allowed < 0 )
m_ticks_allowed = 0;
} else
m_ticks_allowed = 15;
return false;
}
m_recharge_cmd = g_csgo.m_cl->m_last_outgoing_command;
if ( ++m_ticks_allowed > 16 )
m_ticks_allowed = 16;
return true;
}
int c_exploits::clock_correction( ) const {
static auto sv_clockcorrection_msecs = g_csgo.m_cvar->FindVar( HASH( "sv_clockcorrection_msecs" ) );
return g_csgo.m_globals->m_max_clients <= 1
? -1 : game::TIME_TO_TICKS( std::clamp( sv_clockcorrection_msecs->GetFloat( ) / 1000.f, 0.f, 1.f ) );
}
int c_exploits::adjust_tick_base(
const int old_new_cmds,
const int total_new_cmds, const int delta
) const {
auto final_tick_base = -1;
const auto correction_ticks = clock_correction( );
if ( correction_ticks != -1 ) {
const auto& prev_local_data = m_local_data[ g_csgo.m_cl->m_last_command_ack % 150 ];
if ( prev_local_data.m_spawn_time == g_cl.m_local->m_flSpawnTime( ) ) {
final_tick_base = prev_local_data.m_tick_base + 1;
const auto tick_count = final_tick_base + old_new_cmds - m_simulation_diff;
const auto ideal_final_tick = tick_count + correction_ticks;
const auto too_fast_limit = ideal_final_tick + correction_ticks;
const auto too_slow_limit = ideal_final_tick - correction_ticks;
const auto estimated_final_tick = final_tick_base + total_new_cmds;
if ( estimated_final_tick > too_fast_limit
|| estimated_final_tick < too_slow_limit ) {
final_tick_base = ideal_final_tick - total_new_cmds;
}
}
}
if ( final_tick_base != -1 )
return final_tick_base;
const auto& local_data = m_local_data[ ( g_csgo.m_cl->m_last_outgoing_command + 1 ) % 150 ];
return ( local_data.m_spawn_time == g_cl.m_local->m_flSpawnTime( )
? local_data.m_tick_base : g_cl.m_local->m_nTickBase( ) ) - delta;
}
void c_exploits::handle_break_lc( const std::uintptr_t ecx, const std::uintptr_t edx, const int slot, bf_write* buffer, int& from, int& to, int* m_new_cmds, int* m_backup_cmds ) {
// add + 2 to max process ticks cus we wanna allow full shifting on defensive then clamp our shift to that
int shift_amount = std::clamp( m_cur_shift_amount, 0, m_max_process_ticks + 2 );//;
m_cur_shift_amount = 0;
m_last_processed = g_csgo.m_globals->m_tick_count;
const int actual_cmds = std::min( *m_new_cmds + m_ticks_allowed, 16 );
int ticks_allowed{ };
const auto who_tf = actual_cmds - *m_new_cmds;
if ( who_tf >= 0 )
ticks_allowed = who_tf;
m_ticks_allowed = ticks_allowed;
const auto old_new_cmds = *m_new_cmds;
*m_new_cmds = std::clamp( *m_new_cmds + shift_amount, 1, 62 );
*m_backup_cmds = 0;
const auto next_cmd_number = g_csgo.m_cl->m_last_outgoing_command +
g_csgo.m_cl->m_choked_commands + 1;
for ( to = next_cmd_number - old_new_cmds + 1; to <= next_cmd_number; ++to ) {
if ( !ho::orig_write_user_cmd_delta_to_buffer( ecx, edx, slot, buffer, from, to, true ) )
return;
from = to;
}
const auto user_cmd = g_csgo.m_input->get_user_cmd( slot, from );
if ( !user_cmd )
return;
auto from_user_cmd = *user_cmd, to_user_cmd = *user_cmd;
if ( shift_amount ) {
to_user_cmd.m_tick += 200;
++to_user_cmd.m_command_number;
while ( --shift_amount > 0 ) {
write_useer_cmd( buffer, &to_user_cmd, &from_user_cmd );
from_user_cmd = to_user_cmd;
++to_user_cmd.m_tick;
++to_user_cmd.m_command_number;
};
}
}
void c_exploits::process_real_cmds( const std::uintptr_t ecx, const std::uintptr_t edx, const int slot, bf_write* buffer, int& from, int& to, int* m_new_cmds, int* m_backup_cmds ) {
m_last_shift_tick = g_csgo.m_globals->m_tick_count;
// just safety clamp incase it tries shifting more
int shift_amount = std::clamp( m_cur_shift_amount, 0, m_max_process_ticks );
m_cur_shift_amount = 0;
const auto actual_cmds = std::min( *m_new_cmds + m_ticks_allowed, 16 );
int new_ticks_allowed{ };
auto wtf = actual_cmds - *m_new_cmds;
wtf -= shift_amount;
if ( wtf >= 0 )
new_ticks_allowed = wtf;
m_ticks_allowed = new_ticks_allowed;
const auto old_new_cmds = *m_new_cmds;
*m_new_cmds = std::clamp( *m_new_cmds + shift_amount, 1, 62 );
*m_backup_cmds = 0;
auto first_tick_base = adjust_tick_base( old_new_cmds, *m_new_cmds, shift_amount );
const auto next_cmd_number = g_csgo.m_cl->m_last_outgoing_command +
g_csgo.m_cl->m_choked_commands + 1;
for ( to = next_cmd_number - old_new_cmds + 1; to <= next_cmd_number; ++to ) {
if ( !ho::orig_write_user_cmd_delta_to_buffer( ecx, edx, slot, buffer, from, to, true ) )
return;
from = to;
}
/* we dont need this yet
for ( auto i = valve::g_client_state.get( )->m_last_cmd_out + 1; i <= next_cmd_number; ++i ) {
auto& local_data = hacks::g_eng_pred->local_data( ).at( i % 150 );
local_data.m_fake_amount = 0;
local_data.m_override_tick_base = true;
local_data.m_restore_tick_base = local_data.m_restore_tick_base;
local_data.m_adjusted_tick_base = first_tick_base++;
}*/
const auto user_cmd = g_csgo.m_input->get_user_cmd( slot, from );
if ( !user_cmd )
return;
auto from_user_cmd = *user_cmd, to_user_cmd = *user_cmd;
++to_user_cmd.m_command_number;
// stuff
g_csgo.m_prediction->m_previous_startframe = -1;
g_csgo.m_prediction->m_commands_predicted = 0;
vec2_t target_move{ };
m_shift_cycle = true;
++g_csgo.m_cl->m_choked_commands;
++g_csgo.m_cl->m_net_channel->m_choked_packets;
++g_csgo.m_cl->m_net_channel->m_out_seq;
const auto& local_data = m_local_data[ next_cmd_number % 150 ];
target_move = { local_data.m_move.x, local_data.m_move.y };
int shifted_cmds{ };
do {
g_csgo.m_prediction->Update(
g_csgo.m_cl->m_delta_tick,
g_csgo.m_cl->m_delta_tick > 0,
g_csgo.m_cl->m_last_command_ack,
g_csgo.m_cl->m_last_outgoing_command + g_csgo.m_cl->m_choked_commands
);
// if we are mid-shifting
if ( shifted_cmds < shift_amount )
to_user_cmd.m_buttons &= ~( IN_ATTACK | IN_ATTACK2 ); // remove attack and scope
to_user_cmd.m_buttons &= ~0xFFBEFFF9;
to_user_cmd.m_forward_move = to_user_cmd.m_side_move = {};
auto player = g_cl.m_local;//C_CSPlayer::GetLocalPlayer( );
if ( player && player->alive( ) ) { // !alive()
if ( m_type == type_doubletap ) {
} else {
to_user_cmd.m_forward_move = target_move.x;
to_user_cmd.m_side_move = target_move.y;
}
auto& local_data = m_local_data[ to_user_cmd.m_command_number % 150 ];
local_data.m_tick_base = local_data.m_adjusted_tick_base = player->m_nTickBase( );
local_data.m_spawn_time = player->m_flSpawnTime( );
}
// verified commands
g_csgo.m_input->m_commands[ to_user_cmd.m_command_number % 150 ] = to_user_cmd;
g_csgo.m_input->m_verified[ to_user_cmd.m_command_number % 150 ] = { to_user_cmd, to_user_cmd.GetChecksum( ) };
write_useer_cmd( buffer, &to_user_cmd, &from_user_cmd );
++shifted_cmds;
if ( shifted_cmds >= shift_amount ) {
if ( to_user_cmd.m_tick != std::numeric_limits < float >::max( ) ) {
m_shift_cycle = false;
//auto& out = g_ctx->get_out_cmds( ).emplace_back( );
//out.m_is_outgoing = true;
//out.m_is_used = false;
//out.m_command_nr = g_csgo.m_cl->m_last_outgoing_command +
// g_csgo.m_cl->m_choked_commands + 1;
//out.m_prev_command_nr = crypt_int( 0 );
}
} else {
++g_csgo.m_cl->m_choked_commands;
++g_csgo.m_cl->m_net_channel->m_choked_packets;
++g_csgo.m_cl->m_net_channel->m_out_seq;
}
from_user_cmd = to_user_cmd;
++to_user_cmd.m_command_number;
} while ( shifted_cmds < shift_amount );
m_shift_cycle = false;
}
#pragma optimize( "", on )
// hooks
#include "tickbase_simulation.hpp"
namespace ho {
bool __fastcall write_user_cmd_delta_to_buffer(
const std::uintptr_t ecx, const std::uintptr_t edx,
const int slot, bf_write* const buffer,
int from, int to, const bool is_new_cmd
) {
if ( !g_cl.m_local )
return orig_write_user_cmd_delta_to_buffer( ecx, edx, slot, buffer, from, to, is_new_cmd );
if ( g_exploits->m_cur_shift_amount
|| g_csgo.m_cl->m_last_outgoing_command == g_exploits->m_recharge_cmd
|| g_exploits->m_type == c_exploits::exploits_type_t::type_ready ) {
uintptr_t frame_ptr = 0;
__asm mov frame_ptr, ebp;
auto backup_commands = reinterpret_cast < int* > ( frame_ptr + 0xFD8 );
auto new_commands = reinterpret_cast < int* > ( frame_ptr + 0xFDC );
if ( from == -1 ) {
if ( g_csgo.m_cl->m_last_outgoing_command == g_exploits->m_recharge_cmd ) {
*new_commands = 1;
*backup_commands = 0;
const auto next_cmd_number = g_csgo.m_cl->m_last_outgoing_command +
g_csgo.m_cl->m_choked_commands + 1;
for ( to = next_cmd_number - *new_commands + 1; to <= next_cmd_number; ++to ) {
if ( !orig_write_user_cmd_delta_to_buffer( ecx, edx, slot, buffer, from, to, true ) )
break;
from = to;
}
g_notify.add( "check 1" );
}
else if ( g_exploits->m_type == c_exploits::exploits_type_t::type_defensive ) {
g_exploits->handle_break_lc( ecx, edx, slot, buffer, from, to, new_commands, backup_commands );
g_notify.add( "exploits::handle_break_lc" );
} else {
g_notify.add( "exploits::process_real_cmds" );
g_exploits->process_real_cmds( ecx, edx, slot, buffer, from, to, new_commands, backup_commands );
}
}
return true;
}
if ( from == -1 ) {
uintptr_t frame_ptr = 0;
__asm mov frame_ptr, ebp;
auto m_new_cmds = reinterpret_cast < int* > ( frame_ptr + 0xFDC );
const auto m_max_allowed = std::min( *m_new_cmds + g_exploits->m_ticks_allowed, 16 );
int m_ticks_allowed{ };
const auto m_new_allowed = m_max_allowed - *m_new_cmds;
if ( m_new_allowed >= 0 )
m_ticks_allowed = m_new_allowed;
g_exploits->m_ticks_allowed = m_ticks_allowed;
}
return orig_write_user_cmd_delta_to_buffer( ecx, edx, slot, buffer, from, to, is_new_cmd );
}
void __cdecl cl_move( float samples, bool final_tick ) {
if ( !g_csgo.m_engine->IsInGame( )
|| !g_cl.m_local
|| !g_cl.m_local->alive( ) ) {
orig_cl_move( samples, final_tick );
return;
}
if ( g_exploits->m_cur_shift_amount )
final_tick = true;
orig_cl_move( samples, final_tick );
}
}
// client
bool break_lc = false;
if ( !g_exploits->try_to_recharge( m_packet, m_cmd ) ) {
break_lc = false;
g_exploits->handle_context( m_cmd );
if ( g_exploits->m_ticks_allowed > 0
&& !( m_cmd->m_buttons & IN_ATTACK )
&& GetKeyState( VK_XBUTTON2)
&& !g_exploits->m_will_target ) {
if ( ( g_csgo.m_cl->m_last_outgoing_command != g_exploits->m_recharge_cmd )
&& std::abs( g_csgo.m_globals->m_tick_count - g_exploits->m_last_defensive_tick ) >= 14 ) { // dont unshift twice if interval is too small
g_notify.add( "works 1" );
g_exploits->m_last_defensive_tick = g_csgo.m_globals->m_tick_count;
g_exploits->m_cur_shift_amount = 0;
}
else {
break_lc = true;
}
}
if (m_weapon_fire) {
g_exploits->m_cur_shift_amount = g_exploits->m_next_shift_amount;
}
} else {
m_packet = false;
g_exploits->handle_context( m_cmd );
}
// reset on spawn
{
static float prev_spawn_time = g_cl.m_local->m_flSpawnTime( );
if ( prev_spawn_time != g_cl.m_local->m_flSpawnTime() ) {
g_exploits->m_ticks_allowed = 0; // test if this works
//store spawntime
prev_spawn_time = g_cl.m_local->m_flSpawnTime( );
}
}
g_exploits->is_in_defensive = false;
bool can_send{ true };
if ( !m_packet
&& can_send ) {
} else {
if ( g_csgo.m_cl->m_last_outgoing_command == g_exploits->m_recharge_cmd ) {
auto& local_data = g_exploits->m_local_data[ ( g_csgo.m_cl->m_last_outgoing_command + 1 ) % 150 ];
local_data.m_override_tick_base = true;
local_data.m_adjusted_tick_base = g_exploits->adjust_tick_base(
g_csgo.m_cl->m_choked_commands + 1, 1, -g_csgo.m_cl->m_choked_commands
);
} else if ( break_lc ) {
g_exploits->m_type = c_exploits::type_defensive;
g_exploits->m_cur_shift_amount = g_exploits->m_max_process_ticks + 2;//hacks::g_exploits->m_ticks_allowed;
g_exploits->is_in_defensive = true;
}
}
g_exploits->m_charged = false;