summaryrefslogtreecommitdiff
path: root/cheat/gmod/prediction.cpp
blob: ebfea5bf33eb68fc286ac10580b81bc97a95e976 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "prediction.hpp"
#include "hooks.hpp"
#include "context.hpp"

NAMESPACE_REGION( features )

void c_prediction::predict_player( c_base_player* player ) {
	static uintptr_t run_command_address = g_gmod.m_prediction->get_old_function< uintptr_t >( 17 );
	static uintptr_t set_prediction_random_seed_address = ( run_command_address + 0x21 + 4 + *( uintptr_t* )( run_command_address + 0x21 ) );


	CMoveData move_data{ };
	auto ce = player->ce( );

	float old_curtime = g_gmod.m_globals->m_curtime;
	float old_frametime = g_gmod.m_globals->m_frametime;

	int backup_tickbase = player->m_nTickBase( );
	int backup_simtime = player->m_flSimulationTime( );


	//random seed is already being calculated and set in createmove
	**( uintptr_t** )( set_prediction_random_seed_address + 0xC ) = g_ctx.get_last_cmd( )->m_random_seed; //prediction seed
	**( uintptr_t** )( run_command_address + 0x2F ) = uintptr_t( g_ctx.m_local ); //prediction player

	//start prediction
	g_gmod.m_game_movement( )->StartTrackPredictionErrors( ce );

	//run prediction
	g_gmod.m_prediction( )->SetupMove( ce, *player->get< user_cmd_t** >( 0x24B0 ), g_gmod.m_move_helper( ), &move_data );
	g_gmod.m_game_movement( )->ProcessMovement( ce, &move_data );
	g_gmod.m_prediction( )->FinishMove( ce, *player->get< user_cmd_t** >( 0x24B0 ), &move_data );

	//finish prediction
	g_gmod.m_game_movement( )->FinishTrackPredictionErrors( ce );

	**( uintptr_t** )( set_prediction_random_seed_address + 0xC ) = 0xffffffff;
	**( uintptr_t*** )( run_command_address + 0x2F ) = nullptr;

	player->m_nTickBase( ) = backup_tickbase;
	player->m_flSimulationTime( ) = backup_simtime;

	g_gmod.m_globals->m_curtime = old_curtime;
	g_gmod.m_globals->m_frametime = old_frametime;
}

void c_prediction::run( user_cmd_t* ucmd ) {	
	if ( !ucmd || !g_ctx.m_local || !g_ctx.m_local->is_alive( ) )
		return;

	static uintptr_t run_command_address = g_gmod.m_prediction->get_old_function< uintptr_t >( 17 );
	static uintptr_t relative_call_addr = run_command_address + 0x21;
	static uintptr_t set_prediction_random_seed_address = ( relative_call_addr + 4 + *( uintptr_t* )( relative_call_addr ) );

	static auto sv_footsteps = g_gmod.m_cvar( )->FindVar( "sv_footsteps" );

	CMoveData move_data{ };
	IClientEntity* local_ent   = g_ctx.m_local->ce( );

	//backup data
	int old_buttons            = ucmd->m_buttons;
	float old_curtime          = g_gmod.m_globals->m_curtime;
	float old_frame_time       = g_gmod.m_globals->m_frametime;
	int old_tickbase           = g_ctx.m_local->m_nTickBase( );
	int old_flags              = g_ctx.m_local->m_fFlags( );
	MoveType_t old_move_type   = g_ctx.m_local->m_nMoveType( );
	vec3_t old_velocity        = g_ctx.m_local->m_vecVelocity( );
	int old_sv_flags		   = sv_footsteps->m_flags;

	sv_footsteps->m_flags = 0;
	sv_footsteps->m_nvalue = 0;

	//set globals
	g_gmod.m_globals->m_curtime = g_gmod.m_globals->m_interval_per_tick * old_tickbase;
	g_gmod.m_globals->m_frametime = g_gmod.m_globals->m_interval_per_tick;

	//random seed is already being calculated and set in createmove
	**( uintptr_t** )( set_prediction_random_seed_address + 0xC ) = ucmd->m_random_seed; //prediction seed
	**( uintptr_t** )( run_command_address + 0x2F ) = uintptr_t( g_ctx.m_local ); //prediction player
		
	//start prediction
	g_gmod.m_game_movement( )->StartTrackPredictionErrors( local_ent );
	
	//run prediction
	g_gmod.m_prediction( )->SetupMove( local_ent, ucmd, nullptr, &move_data );
	g_gmod.m_game_movement( )->ProcessMovement( local_ent, &move_data );
	g_gmod.m_prediction( )->FinishMove( local_ent, ucmd, &move_data );

	//finish prediction
	g_gmod.m_game_movement( )->FinishTrackPredictionErrors( local_ent );

	**( uintptr_t** )( set_prediction_random_seed_address + 0xC ) = 0xffffffff;
	**( uintptr_t*** )( run_command_address + 0x2F ) = nullptr;

	//good to have, can be used for edge jump and such
	m_predicted_flags = g_ctx.m_local->m_fFlags( ); 

	//restore
	ucmd->m_buttons					= old_buttons;
	g_gmod.m_globals->m_curtime     = old_curtime;
	g_gmod.m_globals->m_frametime   = old_frame_time;
	g_ctx.m_local->m_nTickBase( )   = old_tickbase;
	g_ctx.m_local->m_fFlags( )      = old_flags;
	g_ctx.m_local->m_nMoveType( )   = old_move_type;
	g_ctx.m_local->m_vecVelocity( ) = old_velocity;

	sv_footsteps->m_nvalue = 1;
	sv_footsteps->m_flags = old_sv_flags;
}

END_REGION