-
Автор темы
- #1
Tickbase.hpp:
#pragma once
#include "../includes.h"
class c_tickbase {
private:
struct tickbase_data_t {
int tickbase{};
int command_number{};
int shift_amount{};
int cmd_diff{};
bool restore_tickbase{};
} data;
public:
int simulation_amt{};
/// <summary>
/// get data for tickbase restoring after exploit usage
/// </summary>
/// <param name="tickbase"> tickbase before shift </param>
/// <param name="cmd"> last command number when shift began </param>
/// <param name="shift"> how many commands were shifted </param>
/// <param name="restore"> should we restore tickbase back? </param>
/// <param name="cmd_diff"> how many commands created after disabling shift </param>
void store( int tickbase, int cmd, int shift, bool restore, int cmd_diff = 1 );
void fix( int new_command_number, int& tickbase );
};
class c_exploits {
private:
void force_shift( CUserCmd* cmd, int amount, bool buffer = false );
bool dt_toggled{};
bool dt_active{};
bool dt_off{};
bool teleport{};
bool hs_toggled{};
bool hs_active{};
bool hs_off{};
public:
bool charge_dt{};
bool recharge{};
bool recharge_finish{};
bool stop_movement{};
bool hs_works{};
bool lag_shift{};
bool toggle_lag{};
bool break_lc{};
bool teleportshift{};
// they should now be updated always on
// based on sv_maxusrcmdprocessticks cvar
struct {
int recharge{};
int dt_shift{};
int hs_shift{};
} amounts;
__forceinline void update_amounts() {
amounts.recharge = 16;
amounts.dt_shift = 16 - 2;
amounts.hs_shift = std::max<int>( 0, 16 - 5 );
}
struct cl_move_t {
bool shift = false;
bool shifting = false;
bool valid = false;
int amount = 0;
}cl_move;
int shift{};
int shift_timer{};
int charge_ticks{};
int shift_tick{};
int dt_bullet{};
void reset_shift( ) {
recharge = false;
toggle_lag = false;
lag_shift = false;
shift = 0;
shift_timer = 0;
charge_ticks = 0;
shift_tick = 0;
}
bool recharged( ) {
return charge_ticks >= amounts.recharge && recharge_finish;
}
bool enabled( ) {
return GetKeyState( VK_XBUTTON1 ) && this->recharged() ;
}
bool dt_enabled( ) {
return GetKeyState( VK_XBUTTON1 ) && this->recharged() ;
}
//bool hs_enabled( ) {
// return !g_cfg.binds[ dt_b ].toggled && g_cfg.binds[ hs_b ].toggled && this->recharged() ;
//}
int tickbase_offset( bool dt = false ) {
//if ( this->hs_enabled() && !dt )
// return amounts.hs_shift;
if ( dt && this->dt_enabled( ) )
return amounts.dt_shift;
return 0;
}
bool recharging(CUserCmd* cmd);
void double_tap( );
void hide_shots( );
bool should_shift_cmd( int* new_commands, int* backup_commands, void* ecx, int slot, void* buf, int from, int to );
void on_pre_predict( );
void on_predict_start( );
void on_cl_move( float sample, bool final_tick );
};
extern c_tickbase g_Tickbase;
extern c_exploits g_Exploits;
Tickbase.cpp:
#include "Tickbase.hpp"
c_tickbase g_Tickbase;
c_exploits g_Exploits;
void c_tickbase::store( int tickbase, int cmd, int shift, bool restore, int cmd_diff ) {
this->data.tickbase = tickbase;
this->data.command_number = cmd;
this->data.shift_amount = shift;
this->data.restore_tickbase = restore;
this->data.cmd_diff = cmd_diff;
}
void c_tickbase::fix( int new_command_number, int& tickbase ) {
auto d = this->data;
if ( d.command_number <= 0 )
return;
if ( d.command_number == new_command_number )
tickbase = d.tickbase - d.shift_amount + g_csgo.m_globals->m_frame_simulation_ticks;
if ( d.restore_tickbase && d.command_number + d.cmd_diff == new_command_number )
tickbase += d.shift_amount - g_csgo.m_globals->m_frame_simulation_ticks;
}
void write_user_cmd( void* 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
}
}
bool c_exploits::should_shift_cmd( int* new_commands, int* backup_commands, void* ecx, int slot, void* buf, int from, int to ) {
static auto original = nem_hooks::oWriteUsercmdDeltaToBuffer;// g_hooks.m_client.GetOldMethod< WriteUsercmdDeltaToBuffer_t >( 23 )( this, slot, buf, from, to, isnewcommand ); ;// vtables[ vtables_t::client ].original<write_usercmd_fn>( xor_int( 23 ) );
// oWriteUsercmdDeltaToBuffer( ecx, slot, buffer, from, to, is_new_cmd );
auto newcmds = *new_commands;
auto shift_amount = std::clamp( shift, 1, 14 );
shift = 0;
*backup_commands = 0;
auto choked_modifier = newcmds + shift_amount;
if (choked_modifier > 62)
choked_modifier = 62;
*new_commands = choked_modifier;
auto final_from = -1;
auto next_cmdnr = g_csgo.m_cl->m_choked_commands + g_csgo.m_cl->m_last_outgoing_command + 1;
auto final_to = next_cmdnr - newcmds + 1;
if ( final_to <= next_cmdnr ) {
while ( original( ecx, slot, buf, final_from, final_to, true ) ) {
final_from = final_to++;
if ( final_to > next_cmdnr )
goto next_cmd;
}
return false;
}
next_cmd:
auto user_cmd = g_csgo.m_input->GetUserCmd( slot, final_from ); //whateer
if (!user_cmd)
return true;
CUserCmd to_cmd;
CUserCmd from_cmd;
from_cmd = *user_cmd;
to_cmd = from_cmd;
to_cmd.m_command_number++;
to_cmd.m_tick += 200;
if (newcmds > choked_modifier)
return true;
for ( auto i = choked_modifier - newcmds + 1; i > 0; --i ) {
write_user_cmd( buf, &to_cmd, &from_cmd );
from_cmd = to_cmd;
to_cmd.m_command_number++;
to_cmd.m_tick++;
}
g_Tickbase.simulation_amt = choked_modifier - newcmds + 1;
return true;
}
void c_exploits::force_shift( CUserCmd* cmd, int amount, bool buffer ) {
if (charge_ticks < amount)
return;
if (!stop_movement)
stop_movement = true;
if ( !teleportshift )
teleportshift = true;
shift_tick = g_cl.m_cmd->m_command_number;
cl_move.shift = true;
cl_move.amount = amount;
}
bool c_exploits::recharging( CUserCmd* cmd ) {
if (cmd->m_weapon_select)
return false;
static int last_choke = 0;
if (recharge && !last_choke) {
if ( ++charge_ticks >= amounts.recharge ) {
recharge = false;
recharge_finish = true;
stop_movement = true;
}
shift = 0;
lag_shift = false;
toggle_lag = false;
teleportshift = false;
return true;
} else
last_choke = g_csgo.m_cl->m_choked_commands;
return false;
}
void c_exploits::on_pre_predict() {
this->update_amounts();
static bool toggle_hs = false;
static bool toggle_dt = false;
if ( GetKeyState( VK_XBUTTON1 ) ) {
if (!toggle_dt) {
dt_active = true;
toggle_dt = true;
}
} else
toggle_dt = false;
bool active = dt_toggled && dt_active /*|| hs_toggled && hs_active*/;
if (charge_ticks < amounts.recharge && active ) {
recharge = true;
recharge_finish = false;
}
}
bool is_firing( ) {
return g_cl.m_cmd->m_buttons & IN_ATTACK;
}
void c_exploits::double_tap() {
static bool toggle_charge = false;
if (toggle_charge) {
toggle_charge = false;
charge_dt = true;
this->reset_shift();
return;
}
static int last_dt_tick = 0;
if (charge_dt) {
float shot_diff = std::abs( g_cl.m_weapon->m_fLastShotTime() - g_csgo.m_globals->m_curtime );
bool shot_finish = shot_diff >= 0.3f && !cl_move.shift;
if ( shot_finish && !g_csgo.m_cl->m_choked_commands ) {
if ( !GetKeyState( VK_XBUTTON1 ) )
teleport = false;
else
teleport = true;
dt_bullet = 0;
charge_dt = false;
dt_active = true;
} else if ( g_cl.m_cmd->m_buttons & IN_ATTACK ) {
dt_bullet++;
last_dt_tick = g_csgo.m_globals->m_tick_count;
}
shift_tick = 0;
return;
}
if ( !GetKeyState( VK_XBUTTON1 ) ) {
dt_toggled = false;
if (!dt_off) {
stop_movement = true;
if (teleport) {
this->force_shift( g_cl.m_cmd, amounts.dt_shift - 1 );
teleport = false;
}
this->reset_shift();
dt_off = true;
}
return;
}
dt_toggled = true;
dt_off = false;
if (!recharge_finish)
return;
if (!teleport)
teleport = true;
if ( g_cl.m_weapon->is_misc_weapon() && g_cl.m_weapon_type != WEAPONTYPE_KNIFE && g_cl.m_weapon_type != WEAPONTYPE_TASER ) {
lag_shift = false;
toggle_lag = false;
break_lc = true;
shift = amounts.dt_shift;
shift_timer = 0;
return;
}
if ( !g_cl.m_cmd->m_weapon_select && is_firing() ) {
this->force_shift( g_cl.m_cmd, amounts.dt_shift - 1, true );
last_dt_tick = g_csgo.m_globals->m_tick_count;
dt_bullet++;
dt_toggled = false;
dt_active = false;
lag_shift = false;
toggle_lag = false;
toggle_charge = true;
return;
}
if (/* g_anti_aim->is_peeking() &&*/ g_cl.m_weapon->m_iItemDefinitionIndex() != REVOLVER && !g_cl.m_weapon->is_misc_weapon() ) {
if (!toggle_lag) {
if (!lag_shift) {
shift_timer = 0;
lag_shift = true;
}
toggle_lag = true;
}
} else {
lag_shift = false;
toggle_lag = false;
}
if (lag_shift) {
shift = shift_timer > 0 ? amounts.dt_shift : 0;
if ( ++shift_timer >= amounts.dt_shift ) {
shift_timer = 0;
lag_shift = false;
}
} else {
shift = amounts.dt_shift;
shift_timer = 0;
toggle_lag = false;
}
/*static vector3d origin{};
if (!shift)
interfaces::debug_overlay->add_text_overlay(g_ctx.local->origin(), 3.f,
"*");*/
}
void c_exploits::on_predict_start() {
if (cl_move.shift)
return;
this->double_tap();
}
// paste on_clmove
#include "hooker.hpp"
void c_exploits::on_cl_move( float sample, bool final_tick ) {
if (!cl_move.shift)
return;
if ( g_csgo.m_cl->m_choked_commands == 0 ) {
*g_cl.m_packet = false;
return;
}
static auto original = hooker.original( &nem_hooks::engine::cl_move );
while (cl_move.amount >= 0) {
if ( cl_move.amount >= amounts.dt_shift )
*g_cl.m_packet = false;
// update later
// g_engine_prediction->update();
cl_move.shifting = true;
original( 0.f, cl_move.amount <= 0 );
cl_move.amount--;
}
cl_move.shift = false;
cl_move.shifting = false;
}
hooker.hpp:
#pragma once
#include "../includes.h"
#include "../minhook/minhook.h"
namespace detour {
struct hook_t {
bool enabled = false;
void* target = nullptr;
void* original = nullptr;
void* custom = nullptr;
void enable( ) {
MH_EnableHook( target );
enabled = true;
}
void disable( ) {
MH_DisableHook( target );
enabled = false;
}
};
class c_hooks {
std::vector<hook_t> m_hooks;
public:
c_hooks() {
MH_Initialize( );
}
~c_hooks() {
MH_Uninitialize( );
}
template <typename fn = uintptr_t >
bool create_hook( fn custom_func, void* o_func ) {
hook_t hook = {};
hook.target = o_func;
hook.custom = custom_func;
if ( MH_CreateHook( o_func, custom_func, &hook.original ) == MH_OK ) {
m_hooks.emplace_back( hook );
return true;
}
return false;
}
void enable( ) {
for ( auto& h : m_hooks )
h.enable( );
}
void restore( ) {
for ( auto& h : m_hooks )
h.disable( );
}
template <typename fn = uintptr_t, class ret = fn >
ret original( fn custom_func ) {
auto found = std::find_if( m_hooks.begin() ), m_hooks.end() , [ & ]( hook_t hook ) {
return hook.custom == custom_func;
} );
if ( found != m_hooks.end( ) )
return ( ret )found->original;
return nullptr;
}
};
}
hooks.cpp:
#include "Tickbase/Tickbase.hpp"
detour::c_hooks hooker = {};
namespace nem_hooks {
bool __fastcall write_user_cmd_delta_to_buffer( void* ecx, void* edx, int slot, void* buffer, int from, int to, bool is_new_cmd ) {
static auto original = nem_hooks::oWriteUsercmdDeltaToBuffer;// g_hooks.m_client.GetOldMethod< WriteUsercmdDeltaToBuffer_t >( 23 )( this, slot, buf, from, to, isnewcommand ); ;// vtables[ vtables_t::client ].original<write_usercmd_fn>( xor_int( 23 ) );
//if ( !g_cl.m_local || !g_cl.m_local->alive( ) )
// return original( ecx, slot, buffer, from, to, is_new_cmd );
if ( g_cl.m_processing && g_csgo.m_engine->IsConnected( ) && g_csgo.m_engine->IsInGame( ) ) {
if ( g_Exploits.recharge || !g_Exploits.shift )
return original( ecx, slot, buffer, from, to, is_new_cmd );
if (from != -1)
return true;
uintptr_t frame_ptr{};
__asm mov frame_ptr, ebp;
CCLCMsg_Move_t* msg = reinterpret_cast< CCLCMsg_Move_t* >( frame_ptr + 0xFCC );
return g_Exploits.should_shift_cmd( &msg->new_commands, &msg->backup_commands, ecx, slot, buffer, from, to );
} else {
return nem_hooks::oWriteUsercmdDeltaToBuffer( ecx, slot, buffer, from, to, is_new_cmd );
}
}
//void __vectorcall CL_Move2( float accumulated_extra_samples, bool bFinalTick ) {
// static auto original = oCL_Move;// hooker.original( &cl_move );
// if ( g_cl.m_local->alive() && g_Exploits.recharging( g_cl.m_cmd ) ) {
// //g_engine_prediction->update();
// return;
// }
//
// original( accumulated_extra_samples, bFinalTick );
//
// g_Exploits.on_cl_move( accumulated_extra_samples, bFinalTick );
//}
namespace engine {
void __vectorcall cl_move( float accumulated_extra_samples, bool final_tick ) {
static auto original = hooker.original( &cl_move );
if ( ( g_cl.m_local && g_cl.m_local->alive( ) ) && g_Exploits.recharging( g_cl.m_cmd ) ) {
//g_engine_prediction->update();
return;
}
original( accumulated_extra_samples, final_tick );
g_Exploits.on_cl_move( accumulated_extra_samples, final_tick );
}
}
}
// hooks::init
if ( MH_CreateHook( ( *reinterpret_cast< LPVOID** >( g_csgo.m_client ) )[ 23u ], reinterpret_cast< LPVOID >( &nem_hooks::write_user_cmd_delta_to_buffer ), reinterpret_cast< LPVOID* >( &nem_hooks::oWriteUsercmdDeltaToBuffer ) ) ! = MH_OK ) {
return;
}
auto pattern = pattern::find( PE::GetModule( HASH( "engine.dll" ) ), XOR( "55 8B EC 81 EC ? ? ? 53 56 57 8B 3D ? ? 8A" ) );
hooker.create_hook( nem_hooks::engine::cl_move, pattern );
hooks.hpp:
namespace nem_hooks {
using WriteUsercmdDeltaToBufferFn = bool( __thiscall* )( void*, int, void*, int, int, bool );
inline WriteUsercmdDeltaToBufferFn oWriteUsercmdDeltaToBuffer;
bool __fastcall write_user_cmd_delta_to_buffer( void* ECX, void* EDX, int nSlot, void* buf, int from, int to, bool isnewcommand );
//void __vectorcall CL_Move2( float accumulated_extra_samples, bool bFinalTick );
//inline decltype( &CL_Move2 ) oCL_Move;
namespace engine {
extern void __vectorcall cl_move( float accumulated_extra_samples, bool final_tick );
}
}
extern detour::c_hooks hooker;
entity.hpp -> weapon class:
__forceinline bool is_misc_weapon( ) {
auto info = this->GetWpnData( );
if (!info)
return false;
short idx = this->m_iItemDefinitionIndex( );
int type = info->m_weapon_type;
return idx == ZEUS || type == WEAPONTYPE_KNIFE || type == WEAPONTYPE_C4;//&& type <= WEAPONTYPE_MELE;
}
Пожалуйста, авторизуйтесь для просмотра ссылки.
| idax86