View difference between Paste ID: 6y1HdXy5 and
SHOW: | | - or go back to the newest paste.
1-
1+
#include "CustomFiberThread.h"
2
#include "Scripting.h"
3
#include "../ScriptHook/Log.h"
4
5
#include <windows.h>
6
#include <stdio.h>
7
8
using namespace Scripting;
9
10
// ASSEMBLY FUNCTIONS, MAYBE CAN NOT BE A CLASS FUNCTION
11
12
__declspec( noinline ) u32 GTA4_GetHandleFromPed( CPool< void* >* pPool, void *Ped )
13
{
14
	_asm mov	ecx, pPool;
15
	_asm mov	eax, Ped;
16
	_asm sub	eax, [ecx];
17
	_asm cdq;
18
	_asm idiv	dword ptr [ecx+12];
19
	_asm mov	edx, eax;
20
	_asm mov	eax, [ecx+4];
21
	_asm movzx	eax, byte ptr [eax+edx];
22
	_asm shl	edx, 8;
23
	_asm add	eax, edx;
24
}
25
26
// ASSEMBLY FUNCTIONS, MAYBE CAN NOT BE A CLASS FUNCTION
27
28
RiotThread::RiotThread()
29
{
30
	SetName( "RiotIV_050" );
31
}
32
33
CPool< void* >* RiotThread::GetPedPoolNative()
34
{
35
//	HACKHACK: Static address for GTAIV 1.0.6.0; DEPRECIATED!!!
36
//	return reinterpret_cast< CPool< void* >* >( *reinterpret_cast< DWORD* >( Game::GetBase() + 0x18A72BC ) );
37
38
	return reinterpret_cast< CPool< void* >* >( *reinterpret_cast< DWORD* >( m_ulPedPoolBase ) );
39
}
40
41
u32 RiotThread::GetPedCount()
42
{
43
	if( GetPedPoolNative() == NULL ) return 0;
44
45
	return GetPedPoolNative()->Count();
46
}
47
48
b8 RiotThread::GetPedByIndex( int idx, Ped *Out )
49
{
50
	if( !Out )
51
		return false;
52
53
	Out->Set( 0 );
54
55
	if( GetPedCount() == 0 )
56
		return false;
57
58
	void *CurrentPedIdx = GetPedPoolNative()->at( idx );
59
60
	if( CurrentPedIdx == NULL )
61
		return false;
62
63
	Out->Set( GTA4_GetHandleFromPed( GetPedPoolNative(), CurrentPedIdx ) );
64
65
	return ( Out->IsValid() && DoesCharExist( *Out ) );
66
}
67
68
Scripting::Vector3 RiotThread::GetPedVector( Scripting::Ped *In )
69
{
70
	Vector3 Ret(0,0,0);
71
	Scripting::GetCharCoordinates( *In, &Ret.X, &Ret.Y, &Ret.Z );
72
	return Ret;
73
}
74
75
Player RiotThread::GetPlayer()
76
{
77
	Player playerIndex = ConvertIntToPlayerIndex(GetPlayerId());
78
	return playerIndex;
79
}
80
81
Scripting::Ped RiotThread::GetPlayerPed()
82
{
83
	Ped ped;
84
	GetPlayerChar( GetPlayer(), &ped );
85
	return ped;
86
}
87
88
Scripting::eWeapon RiotThread::GetRandomWeapon()
89
{
90
	srand( GetTickCount() );
91
92
	return static_cast< eWeapon >( m_UsableWeaponry[ rand() % m_UsableWeaponry.size() ] );
93
}
94
95
b8 RiotThread::IsPedPolice( Scripting::Ped ped )
96
{
97
	eModel CurrentModel;
98
99
	Scripting::GetCharModel( ped, &CurrentModel );
100
101
	return (
102
		( CurrentModel == MODEL_M_Y_COP )			||
103
		( CurrentModel == MODEL_M_Y_COP_TRAFFIC )	||
104
		( CurrentModel == MODEL_M_M_FATCOP_01 )		||
105
		( CurrentModel == MODEL_CS_MITCHCOP )		||
106
		( CurrentModel == MODEL_M_Y_SWAT )			||
107
		( CurrentModel == MODEL_M_M_FBI )			||
108
		( CurrentModel == MODEL_M_Y_STROOPER ) );
109
}
110
111
b8 RiotThread::ShouldRiot( Scripting::Ped ped )
112
{
113
	if( m_DontRiotHashes.empty() )
114
	{
115
		return true;
116
	}
117
118
	for( size_t i = 0; i < m_DontRiotHashes.size(); i++ )
119
	{
120
		if( IsCharModel( ped, static_cast< Scripting::eModel >( m_DontRiotHashes[ i ] ) ) )
121
		{
122
			return false;
123
		}
124
	}
125
126
	return true;
127
}
128
129
b8 RiotThread::IsPedAllowedToRiot( Scripting::Ped ped )
130
{
131
	if( m_RiotHashes.empty() )
132
		return true;
133
134
	for( size_t i = 0; i < m_RiotHashes.size(); i++ )
135
	{
136
		if( IsCharModel( ped, static_cast< Scripting::eModel >( m_RiotHashes[ i ] ) ) )
137
		{
138
			return true;
139
		}
140
	}
141
142
	return false;
143
}
144
145
b8 RiotThread::CausePedToRiot( Scripting::Ped LocalPed, Scripting::Ped RiotPed )
146
{
147
	// Check if ped exists
148
	if( DoesCharExist( RiotPed ) == false )
149
	{
150
		return false;
151
	}
152
153
	// Check the model for status
154
	if( ShouldRiot( RiotPed ) == false || IsPedAllowedToRiot( RiotPed ) == false )
155
	{
156
		if( IsPedAMissionPed( RiotPed ) )
157
		{
158
			MarkCharAsNoLongerNeeded( &RiotPed );
159
		}
160
161
		return false;
162
	}
163
164
	// If not "visible", delete them, not needed
165
	if( IsCharVisible( RiotPed ) == false )
166
	{
167
		if( IsPedAMissionPed( RiotPed ) )
168
		{
169
			MarkCharAsNoLongerNeeded( &RiotPed );
170
171
			DeleteChar( &RiotPed );
172
		}
173
174
		return false;
175
	}
176
177
	// If dead, fatally injured
178
	// if mission ped, unmark, stop
179
	if( IsCharDead( RiotPed ) || IsCharFatallyInjured( RiotPed ) )
180
	{
181
		if( IsPedAMissionPed( RiotPed ) )
182
		{
183
			MarkCharAsNoLongerNeeded( &RiotPed );
184
		}
185
186
		return false;
187
	}
188
189
	// If cops rioting is disabled and ped is police, stop
190
191
	if( m_bCopsGoCrazy == false && IsPedPolice( RiotPed ) )
192
	{
193
		if( IsPedAMissionPed( RiotPed ) )
194
		{
195
			MarkCharAsNoLongerNeeded( &RiotPed );
196
		}
197
198
		return false;
199
	}
200
201
	// If usable weaponry is available 
202
	if( m_UsableWeaponry.size() > 0 )
203
	{
204
		//if NOT police (already have weapons)
205
		if( IsPedPolice( RiotPed ) == false )
206
		{
207
			//if have a gun already, and not police, stop
208
			if( Scripting::IsCharArmed( RiotPed, WEAPON_SLOT_MELEE ) 
209
					|| Scripting::IsCharArmed( RiotPed, WEAPON_SLOT_HANDGUN )
210
					|| Scripting::IsCharArmed( RiotPed, WEAPON_SLOT_HEAVY )
211
					|| Scripting::IsCharArmed( RiotPed, WEAPON_SLOT_RIFLE )
212
					|| Scripting::IsCharArmed( RiotPed, WEAPON_SLOT_SHOTGUN ) 
213
					|| Scripting::IsCharArmed( RiotPed, WEAPON_SLOT_SMG )
214
					|| Scripting::IsCharArmed( RiotPed, WEAPON_SLOT_SNIPER )
215
					|| Scripting::IsCharArmed( RiotPed, WEAPON_SLOT_THROWN ) )
216
			{
217
				return false;
218
			}
219
		}
220
	}
221
222
	// Range checking to avoid crashes
223
	Scripting::Vector3 LocalVec = GetPedVector( &LocalPed );
224
	Scripting::Vector3 PedVec	= GetPedVector( &RiotPed );
225
226
	if( PedVec.Distance( &LocalVec ) > m_fMaximumRange )
227
	{
228
		// HACKHACK: If outside of maximum range mark as no longer needed...
229
230
		if( IsPedAMissionPed( RiotPed ) )
231
		{
232
			MarkCharAsNoLongerNeeded( &RiotPed );
233
		}
234
235
		return false;
236
	}
237
238
	if( IsPedAMissionPed( RiotPed ) == false )
239
	{
240
		// Setup violent tendencies
241
242
		SetCharAsMissionChar( RiotPed );
243
244
		SetCharAsEnemy( RiotPed, m_bTargetPlayer );
245
246
		SetPedDiesWhenInjured( RiotPed, true );
247
248
		AllowTargetWhenInjured( RiotPed, true );
249
250
		SetCharWillMoveWhenInjured( RiotPed, true );
251
252
		SetCharWillDoDrivebys( RiotPed, true );
253
254
		SetCharWillUseCarsInCombat( RiotPed, m_bPedsUseCars );
255
256
		SetPedWontAttackPlayerWithoutWantedLevel( RiotPed, 0 );
257
258
		SetSenseRange( RiotPed, m_fMaximumRange );
259
260
		SetCharAccuracy( RiotPed, 100 );
261
262
		if( IsPedPolice( RiotPed ) == false )
263
		{
264
			SetCharWantedByPolice( RiotPed, m_bPedsWanted );
265
266
			SetCharRelationshipGroup( RiotPed, 8 );
267
268
			// If weaponry available, give random weapon
269
270
			if( m_UsableWeaponry.size() > 0 )
271
			{
272
				eWeapon RandomWeapon = GetRandomWeapon();
273
274
				GiveWeaponToChar( RiotPed, RandomWeapon, ( RandomWeapon > 3 ) ? 9999 : 0, 0 );
275
276
				SetCurrentCharWeapon( RiotPed, RandomWeapon, true );
277
278
				BlockPedWeaponSwitching( RiotPed, true );
279
			}
280
			else
281
			{
282
				// Melee if no weapons are set
283
284
				RemoveAllCharWeapons( RiotPed );
285
			}
286
		}
287
288
		// Set attacking task
289
290
		TaskCombatHatedTargetsAroundChar( RiotPed, m_fMaximumRange );
291
292
		SetCharKeepTask( RiotPed, true );
293
	}
294
295
	return true;
296
}
297
298
void RiotThread::SpawnNewRioter( Ped LocalPed, Vector3 SpawnVector )
299
{
300
	Scripting::PrintStringWithLiteralStringNow( "STRING", "Spawning new riot ped", 3000, true );
301
302
	srand( GetTickCount() );
303
304
	eModel ModelSpawn = static_cast< eModel >( m_SpawnHashes[ rand() % m_SpawnHashes.size() ] );
305
306
	RequestModel( ModelSpawn );
307
308
	while( HasModelLoaded( ModelSpawn ) == false )
309
	{
310
		Wait(10);
311
	}
312
313
	Ped OutPed;
314
315
	CreateChar( 2, ModelSpawn, SpawnVector.X, SpawnVector.Y, SpawnVector.Z, &OutPed, true );
316
317
	if( OutPed.IsValid() )
318
	{
319
		while( DoesCharExist( OutPed ) == false )
320
		{
321
			Wait(10);
322
		}
323
324
		while( IsCharVisible( OutPed ) == false )
325
		{
326
			Wait(10);
327
		}
328
329
		SetCharHealth( OutPed, 200 );
330
331
		MarkCharAsNoLongerNeeded( &OutPed );
332
	}
333
}
334
335
void RiotThread::SetupRelationships()
336
{
337
	SetRelationship( 5, 8, 8 ); // Rioters hate themselves
338
	SetRelationship( 5, 8, 3 );	// Rioters hate police
339
340
	SetPlayerCanBeHassledByGangs( GetPlayer(), m_bTargetPlayer );
341
342
	if( m_bTargetPlayer )
343
	{
344
		SetRelationship( 5, 8, 0 ); // Rioters hate player (you)
345
		SetRelationship( 5, 0, 8 ); // Player hate rioters
346
347
		if( m_bCopsGoCrazy )
348
		{
349
			SetRelationship( 5, 0, 3 ); //Cops hate player (you)
350
		}
351
	}
352
	else
353
	{
354
		SetRelationship( 1, 8, 0 ); // Rioters ignore player (you)
355
		SetRelationship( 1, 0, 8 ); // Player ignore rioters
356
	}
357
358
	if( m_bCopsGoCrazy )
359
	{
360
		SetRelationship( 5, 3, 8 ); // Cops hate rioters
361
	}
362
}
363
364
std::vector< int > RiotThread::StringToIntList( const char *str )
365
{
366
	std::vector< int > ReturnVector;
367
368
	if( str == NULL )
369
	{
370
		ReturnVector.clear();
371
372
		return ReturnVector;
373
	}
374
375
	//
376
377
	char *pch = strtok( const_cast< char* >( str ), "," );
378
379
	if( pch == NULL )
380
	{
381
		ReturnVector.push_back( atoi( str ) );
382
	}
383
	else
384
	{
385
		while( pch )
386
		{
387
			ReturnVector.push_back( atoi( pch ) );
388
389
			pch = strtok( 0, "," );
390
		}
391
	}
392
393
	return ReturnVector;
394
}
395
396
void RiotThread::SetupSettingsFile()
397
{
398
	Log::Debug( "Loading Settings..." );
399
400
	m_pConfigService = ScriptHookManager::RequestService< IConfigService >( "Config" );
401
402
	if( m_pConfigService )
403
	{
404
		IConfig* Configuration = m_pConfigService->Create( IConfigService::ConfigTypeXml );
405
406
		if( Configuration == NULL )
407
			return;
408
409
		Configuration->Set( "RiotIV", "Enabled", "1" );
410
		Configuration->Set( "RiotIV", "TargetPlayer", "0" );
411
		Configuration->Set( "RiotIV", "CrazyCops", "1" );
412
		Configuration->Set( "RiotIV", "PedsUseCars", "1" );
413
		Configuration->Set( "RiotIV", "PedsWanted", "1" );
414
		Configuration->Set( "RiotIV", "MadDrivers", "1" );
415
		Configuration->Set( "RiotIV", "EmergencyServicesDisabled", "1" );
416
		Configuration->Set( "RiotIV", "PedMultiplierEnforce", "NONE" );
417
		Configuration->Set( "RiotIV", "UsableWeaponry", "4,5,7,9,10,11,12,13,14,15,16,17,18" );
418
		Configuration->Set( "RiotIV", "DontRiotHashes", "" );
419
		Configuration->Set( "RiotIV", "SpawnHashes", "1794146792" );
420
		Configuration->Set( "RiotIV", "RiotHashes", "ANY" );
421
		Configuration->Set( "RiotIV", "MaximumRange", "100.0" );
422
423
		char *pszModulePath = GetModulePath();
424
425
		if( pszModulePath == 0 || strlen( pszModulePath ) == 0 )
426
			return;
427
428
		Log::Debug( "Module Path [%s]", pszModulePath );
429
430
		char pszConfigPath[ MAX_PATH ] = { 0 };
431
432
		strcat_s( pszConfigPath, MAX_PATH, GetModulePath() );
433
		strcat_s( pszConfigPath, MAX_PATH, "Riot.xml" );
434
		
435
		Log::Debug( "Loading configuration from [%s]", pszConfigPath );
436
437
		WIN32_FIND_DATAA wfd;
438
439
		if ( FindFirstFileA( pszConfigPath, &wfd ) != INVALID_HANDLE_VALUE )
440
		{
441
			Configuration->Load( pszConfigPath );
442
443
			// HACKHACK: Save after we load to ensure any new values are inserted into the file for future loading
444
			Configuration->Save( pszConfigPath );
445
		}
446
		else
447
		{
448
			Configuration->Save( pszConfigPath );
449
		}
450
451
		m_bEnabled						= ( Configuration->GetInteger( "RiotIV", "Enabled", 1 ) == 1 );
452
		m_bTargetPlayer 				= ( Configuration->GetInteger( "RiotIV", "TargetPlayer", 0 ) == 1 );
453
		m_bCopsGoCrazy					= ( Configuration->GetInteger( "RiotIV", "CrazyCops", 0 ) == 1 );
454
		m_bPedsUseCars					= ( Configuration->GetInteger( "RiotIV", "PedsUseCars", 1 ) == 1 );
455
		m_bPedsWanted					= ( Configuration->GetInteger( "RiotIV", "PedsWanted", 0 ) == 1 );
456
		m_bMadDrivers					= ( Configuration->GetInteger( "RiotIV", "MadDrivers", 0 ) == 1 );
457
		m_bEmergencyServicesDisabled	= ( Configuration->GetInteger( "RiotIV", "EmergencyServicesDisabled", 0 ) == 1 );
458
		m_fMaximumRange					= Configuration->GetFloat( "RiotIV", "MaximumRange", 100.f );
459
		
460
		CONST CHAR* PedMultiEnforce		= Configuration->GetString( "RiotIV", "PedMultiplierEnforce" );
461
		CONST CHAR* UsableWeapons		= Configuration->GetString( "RiotIV", "UsableWeaponry" );
462
		CONST CHAR* DontRiotHashes		= Configuration->GetString( "RiotIV", "DontRiotHashes" );
463
		CONST CHAR* RiotHashes			= Configuration->GetString( "RiotIV", "RiotHashes" );
464
		CONST CHAR* SpawnHashes			= Configuration->GetString( "RiotIV", "SpawnHashes" );
465
		
466
		m_UsableWeaponry				= StringToIntList( UsableWeapons );
467
		m_DontRiotHashes				= StringToIntList( DontRiotHashes );
468
		m_SpawnHashes					= StringToIntList( SpawnHashes );
469
470
		if( _stricmp( PedMultiEnforce, "NONE" ) == 0 )
471
		{
472
			m_bForcePedMultiplier = false;
473
		}
474
		else
475
		{
476
			m_bForcePedMultiplier = true;
477
478
			m_fPedMultiplier = static_cast< f32 >( atof( PedMultiEnforce ) );
479
		}
480
481
		if( _stricmp( RiotHashes, "ANY" ) == 0 )
482
		{
483
			m_RiotHashes.clear();
484
		}
485
		else
486
		{
487
			m_RiotHashes = StringToIntList( RiotHashes );
488
		}
489
490
		Configuration->Release();
491
	}
492
	else
493
	{
494
		Log::Debug( "Unable to load configuration service.." );
495
	}
496
}
497
498
char* RiotThread::GetModulePath()
499
{
500
	static char pszPath[ MAX_PATH ] = { 0 };
501
502
	if( strlen( pszPath ) > 0 )
503
		return pszPath;
504
505
	GetModuleFileNameA( m_hModule, pszPath, sizeof( pszPath ) );
506
507
    u32 i = strlen( pszPath );
508
509
    while( i > 0 && pszPath[i] != '\\' )
510
	{
511
		i--;
512
	}
513
514
	pszPath[i] = 0;
515
516
	strcat_s( pszPath, MAX_PATH, "\\" );
517
518
	return pszPath;
519
}
520
521
void RiotThread::UpdateCode()
522
{
523
	HMODULE hMainModule = GetModuleHandleW( NULL );
524
525
	Log::Debug( "Finding signiture..[0x%X][0x%X]", hMainModule, Game::GetBase() );
526
527
	m_ulPedPoolBase = Code::FindAddress::DetectPattern( 
528
		reinterpret_cast< unsigned long >( hMainModule ), 0xFFFFFF, 
529
		( BYTE* )"\x55\x8B\xEC\x83\xE4\xF0\x8B\x15\x00\x00\x00\x00\x81\xEC\xEC\x00\x00\x00", 
530
		( CHAR* )"xxxxxxxx????xxxxxx" );
531
532
	if( m_ulPedPoolBase == NULL )
533
	{
534
		Log::Fatal( "PedPoolBase not found...critical error" );
535
536
		ExitProcess(0);
537
	}
538
	else
539
	{
540
		Log::Debug( "PedPoolBase 001 [0x%X]", m_ulPedPoolBase );
541
542
		m_ulPedPoolBase += 8;
543
544
		Log::Debug( "PedPoolBase 002 [0x%X]", m_ulPedPoolBase );
545
546
		m_ulPedPoolBase = *reinterpret_cast< unsigned long* >( m_ulPedPoolBase );
547
548
		Log::Debug( "PedPoolBase FIN [0x%X]", m_ulPedPoolBase );
549
550
		Log::Debug( "Address - Base = [0x%X]", m_ulPedPoolBase - reinterpret_cast< unsigned long >( hMainModule ) );
551
	}
552
}
553
554
void RiotThread::RunScript()
555
{
556
	SetupSettingsFile();
557
558
	CreateKeyboard();
559
560
	CreateMenu();
561
562
	while( IsThreadAlive() )
563
	{
564
		if( NetworkIsSessionStarted() == false )
565
		{
566
			Ped LocalPed = GetPlayerPed();
567
568
			if( LocalPed.IsValid() == false )
569
				continue;
570
571
			Vector3 LocalVector = GetPedVector( &LocalPed );
572
573
			if( m_bSpawnRandomPedNextFrame && m_SpawnHashes.size() )
574
			{
575
				SpawnNewRioter( LocalPed, Vector3( LocalVector.X + 2.f, LocalVector.Y, LocalVector.Z ) );
576
577
				m_bSpawnRandomPedNextFrame = false;
578
			}
579
580
			if( m_bForcePedMultiplier )
581
			{
582
				SetPedDensityMultiplier( m_fPedMultiplier );
583
			}
584
585
			SwitchMadDrivers( m_bMadDrivers );
586
587
			AllowEmergencyServices( !m_bEmergencyServicesDisabled );
588
589
			SetPoliceIgnorePlayer( GetPlayer(), m_bEmergencyServicesDisabled );
590
591
			if( m_bEmergencyServicesDisabled )
592
			{
593
				SetCharWantedByPolice( LocalPed, false );
594
595
				ClearWantedLevel( GetPlayer() );
596
597
				ClearAreaOfCops( LocalVector.X, LocalVector.Y, LocalVector.Z, m_fMaximumRange );
598
			}
599
600
			if( m_bEnabled )
601
			{
602
				AllowGangRelationshipsToBeChangedByNextCommand( true );
603
604
				SetupRelationships();
605
606
				for( u32 i = 0; i < GetPedCount(); i++ )
607
				{
608
					Ped Index;
609
610
					Index.Set( 0 );
611
612
					if( GetPedByIndex( i, &Index ) )
613
					{
614
						if( Index.IsNull() )
615
							continue;
616
617
						if( Index.Get() == LocalPed.Get() )
618
							continue;
619
620
						if( CausePedToRiot( LocalPed, Index ) == false )
621
							continue;
622
					}
623
				}
624
			}
625
		}
626
627
		Wait( 10 );
628
	}
629
}
630
631
void RiotThread::OnStart()
632
{
633
	m_pMenu = NULL;
634
}
635
636
void RiotThread::OnKill()
637
{
638
	IKeyboardHookService *kbhService = ScriptHookManager::RequestService<IKeyboardHookService>( "KeyboardHook" );
639
	
640
	kbhService->RemoveHandler( this );
641
642
	if( m_pMenu )
643
	{
644
		m_pMenu->Release();
645
		m_pMenu = NULL;
646
	}
647
648
	ScriptThread::OnKill();
649
}
650
651
void RiotThread::CreateKeyboard()
652
{
653
	IKeyboardHookService *kbhService = ScriptHookManager::RequestService<IKeyboardHookService>( "KeyboardHook" );
654
655
	kbhService->AddHandler( this );
656
}
657
658
void RiotThread::CreateMenu()
659
{
660
	IMenuService *menuService = ScriptHookManager::RequestService< IMenuService >( "Menu" );
661
662
	m_pMenu = menuService->CreateMenu();
663
664
	m_pMenu->SetTitle( "Riot mode" );
665
666
	AddMenuItemCustom( 0, m_bEnabled ? "Disable Riot Mode" : "Enable Riot Mode" );
667
	AddMenuItemCustom( 1, m_bTargetPlayer ? "Disable peds targetting player" : "Enable peds targetting player" );
668
	AddMenuItemCustom( 2, m_bCopsGoCrazy ? "Disable cops rioting" : "Enable cops rioting" );
669
	AddMenuItemCustom( 3, m_bPedsUseCars ? "Disable peds use cars in combat" : "Enable peds use cars in combat" );
670
	AddMenuItemCustom( 4, m_bPedsWanted ? "Disable peds wanted" : "Enable peds wanted" );
671
	AddMenuItemCustom( 5, m_bMadDrivers ? "Disable mad drivers" : "Enable mad drives" );
672
	AddMenuItemCustom( 6, m_bEmergencyServicesDisabled ? "Enable emergancy services" : "Disable emergancy services" );
673
674
	m_pMenu->SetEventHandler( this );
675
}
676
677
void RiotThread::AddMenuItemCustom( int idx, char *pszFormat, ... )
678
{
679
	char FormattedBuffer[ 1024 ] = { 0 };
680
681
	va_list va_alist;
682
683
	va_start( va_alist, pszFormat );
684
685
	_vsnprintf( 
686
		FormattedBuffer + strlen( FormattedBuffer ),
687
		sizeof( FormattedBuffer ) - strlen( FormattedBuffer ),
688
		pszFormat, va_alist );
689
690
	va_end( va_alist );
691
692
	m_pMenu->AddItem( idx, FormattedBuffer );
693
}
694
695
void RiotThread::SetMenuItemCustom( int idx, char *pszFormat, ... )
696
{
697
	char FormattedBuffer[ 1024 ] = { 0 };
698
699
	va_list va_alist;
700
701
	va_start( va_alist, pszFormat );
702
703
	_vsnprintf( 
704
		FormattedBuffer + strlen( FormattedBuffer ),
705
		sizeof( FormattedBuffer ) - strlen( FormattedBuffer ),
706
		pszFormat, va_alist );
707
708
	va_end( va_alist );
709
710
	m_pMenu->SetItem( idx, FormattedBuffer );
711
}
712
713
void RiotThread::OnMenuSelectionChanged( IMenu *menu, u32 id )
714
{
715
	// None?
716
}
717
718
void RiotThread::OnMenuSelected( IMenu *menu, u32 id )
719
{
720
	switch( id )
721
	{
722
	case 0:
723
		{
724
			m_bEnabled = !m_bEnabled;
725
726
			SetMenuItemCustom( 0, m_bEnabled ? "Disable Riot Mode" : "Enable Riot Mode" );
727
728
			break;
729
		}
730
	case 1:
731
		{
732
			m_bTargetPlayer = !m_bTargetPlayer;
733
734
			SetMenuItemCustom( 1, m_bTargetPlayer ? "Disable peds targetting player" : "Enable peds targetting player" );
735
736
			break;
737
		}
738
	case 2:
739
		{
740
			m_bCopsGoCrazy = !m_bCopsGoCrazy;
741
742
			SetMenuItemCustom( 2, m_bCopsGoCrazy ? "Disable cops rioting" : "Enable cops rioting" );
743
744
			break;
745
		}
746
	case 3:
747
		{
748
			m_bPedsUseCars = !m_bPedsUseCars;
749
750
			SetMenuItemCustom( 3, m_bPedsUseCars ? "Disable peds use cars in combat" : "Enable peds use cars in combat" );
751
752
			break;
753
		}
754
	case 4:
755
		{
756
			m_bPedsWanted = !m_bPedsWanted;
757
758
			SetMenuItemCustom( 4, m_bPedsWanted ? "Disable peds wanted" : "Enable peds wanted" );
759
760
			break;
761
		}
762
	case 5:
763
		{
764
			m_bMadDrivers = !m_bMadDrivers;
765
766
			SetMenuItemCustom( 5, m_bMadDrivers ? "Disable mad drivers" : "Enable mad drives" );
767
768
			break;
769
		}
770
	case 6:
771
		{
772
			m_bEmergencyServicesDisabled = !m_bEmergencyServicesDisabled;
773
774
			SetMenuItemCustom( 6, m_bEmergencyServicesDisabled ? "Enable emergancy services" : "Disable emergancy services" );
775
776
			break;
777
		}
778
	}
779
}
780
781
void RiotThread::OnKeyboardHookEvent( const IKeyboardHookHandler::KeyEventArgs &args )
782
{
783
	if( args.VirtualKey == VK_INSERT && !args.WasKeyDownBefore )
784
	{
785
		if( m_pMenu )
786
		{
787
			m_pMenu->Show();
788
		}
789
	}
790
791
	if( args.VirtualKey == VK_F3 && !args.WasKeyDownBefore )
792
	{
793
		m_bSpawnRandomPedNextFrame = true;
794
	}
795
}