2016-10-19 03:01:01 -04:00
# include "STDInclude.hpp"
namespace Components
{
2017-05-15 15:57:45 -04:00
int QuickPatch : : FrameTime = 0 ;
2016-10-19 03:01:01 -04:00
void QuickPatch : : UnlockStats ( )
{
2017-02-21 15:49:42 -05:00
if ( Dedicated : : IsEnabled ( ) ) return ;
2017-02-21 15:40:59 -05:00
2016-11-04 15:24:47 -04:00
if ( Game : : CL_IsCgameInitialized ( ) )
{
Toast : : Show ( " cardicon_locked " , " ^1Error " , " Not allowed while ingame. " , 3000 ) ;
return ;
}
2016-10-19 03:01:01 -04:00
Command : : Execute ( " setPlayerData prestige 10 " ) ;
Command : : Execute ( " setPlayerData experience 2516000 " ) ;
Command : : Execute ( " setPlayerData iconUnlocked cardicon_prestige10_02 1 " ) ;
// Unlock challenges
Game : : StringTable * challengeTable = Game : : DB_FindXAssetHeader ( Game : : XAssetType : : ASSET_TYPE_STRINGTABLE , " mp/allchallengestable.csv " ) . stringTable ;
if ( challengeTable )
{
for ( int i = 0 ; i < challengeTable - > rowCount ; + + i )
{
// Find challenge
const char * challenge = Game : : TableLookup ( challengeTable , i , 0 ) ;
int maxState = 0 ;
int maxProgress = 0 ;
// Find correct tier and progress
for ( int j = 0 ; j < 10 ; + + j )
{
int progress = atoi ( Game : : TableLookup ( challengeTable , i , 6 + j * 2 ) ) ;
if ( ! progress ) break ;
maxState = j + 2 ;
maxProgress = progress ;
}
2017-01-06 09:27:35 -05:00
Command : : Execute ( Utils : : String : : VA ( " setPlayerData challengeState %s %d " , challenge , maxState ) ) ;
Command : : Execute ( Utils : : String : : VA ( " setPlayerData challengeProgress %s %d " , challenge , maxProgress ) ) ;
2016-10-19 03:01:01 -04:00
}
}
}
int QuickPatch : : MsgReadBitsCompressCheckSV ( const char * from , char * to , int size )
{
static char buffer [ 0x8000 ] ;
if ( size > 0x800 ) return 0 ;
size = Game : : MSG_ReadBitsCompress ( from , buffer , size ) ;
if ( size > 0x800 ) return 0 ;
std : : memcpy ( to , buffer , size ) ;
return size ;
}
int QuickPatch : : MsgReadBitsCompressCheckCL ( const char * from , char * to , int size )
{
static char buffer [ 0x100000 ] ;
if ( size > 0x20000 ) return 0 ;
size = Game : : MSG_ReadBitsCompress ( from , buffer , size ) ;
if ( size > 0x20000 ) return 0 ;
std : : memcpy ( to , buffer , size ) ;
return size ;
}
2017-07-12 17:39:40 -04:00
int QuickPatch : : SVCanReplaceServerCommand ( Game : : client_t * /*client*/ , const char * /*cmd*/ )
{
// This is a fix copied from V2. As I don't have time to investigate, let's simply trust them
return - 1 ;
}
2018-10-13 16:59:32 -04:00
long QuickPatch : : AtolAdjustPlayerLimit ( const char * string )
{
return std : : min ( atol ( string ) , 18l ) ;
}
2016-10-19 03:01:01 -04:00
void QuickPatch : : SelectStringTableEntryInDvarStub ( )
{
2016-12-07 14:00:24 -05:00
Command : : ClientParams args ;
2016-10-19 03:01:01 -04:00
2016-11-20 08:09:07 -05:00
if ( args . length ( ) > = 4 )
2016-10-19 03:01:01 -04:00
{
std : : string cmd = args [ 0 ] ;
std : : string table = args [ 1 ] ;
std : : string col = args [ 2 ] ;
std : : string dvarName = args [ 3 ] ;
Game : : dvar_t * dvar = Game : : Dvar_FindVar ( dvarName . data ( ) ) ;
2017-01-12 16:15:57 -05:00
if ( Command : : Find ( dvarName ) | | ( dvar & & ( dvar - > flags & ( Game : : DVAR_FLAG_WRITEPROTECTED | Game : : DVAR_FLAG_CHEAT | Game : : DVAR_FLAG_READONLY ) ) ) )
2016-10-19 03:01:01 -04:00
{
return ;
}
}
Game : : CL_SelectStringTableEntryInDvar_f ( ) ;
}
2018-07-17 08:30:29 -04:00
__declspec ( naked ) void QuickPatch : : JavelinResetHookStub ( )
{
__asm
{
mov eax , 577 A10h ;
call eax ;
pop edi ;
mov dword ptr [ esi + 34 h ] , 0 ;
pop esi ;
pop ebx ;
retn ;
}
}
2020-11-13 02:09:29 -05:00
__declspec ( naked ) int QuickPatch : : G_GetClientScore ( )
2020-05-11 14:33:08 -04:00
{
2020-11-13 02:09:29 -05:00
__asm
2020-05-11 14:33:08 -04:00
{
2020-11-13 02:09:29 -05:00
mov eax , [ esp + 4 ] // index
mov ecx , ds : 1 A831A8h // level: &g_clients
2020-05-11 14:33:08 -04:00
2020-11-13 02:09:29 -05:00
test ecx , ecx ;
jz invalid_ptr ;
imul eax , 366 Ch
2020-05-11 14:33:08 -04:00
mov eax , [ eax + ecx + 3134 h ]
ret
2020-11-13 02:09:29 -05:00
invalid_ptr :
xor eax , eax
ret
2020-05-11 14:33:08 -04:00
}
}
2018-11-19 15:08:23 -05:00
bool QuickPatch : : InvalidNameCheck ( char * dest , char * source , int size )
2018-07-17 08:30:29 -04:00
{
strncpy ( dest , source , size - 1 ) ;
dest [ size - 1 ] = 0 ;
for ( int i = 0 ; i < size - 1 ; i + + )
{
2018-11-19 15:08:23 -05:00
if ( ! dest [ i ] ) break ;
2019-10-03 03:10:00 -04:00
if ( dest [ i ] > 125 | | dest [ i ] < 32 | | dest [ i ] = = ' % ' )
2018-07-17 08:30:29 -04:00
{
return false ;
}
}
return true ;
}
__declspec ( naked ) void QuickPatch : : InvalidNameStub ( )
{
2020-12-09 14:13:34 -05:00
static const char * kick_reason = " Invalid name detected. " ;
2018-07-17 08:30:29 -04:00
__asm
{
call InvalidNameCheck ;
2018-11-19 15:08:23 -05:00
test al , al
2018-07-17 08:30:29 -04:00
2018-11-19 15:08:23 -05:00
jnz returnSafe ;
2018-07-17 08:30:29 -04:00
pushad ;
push 1 ;
push kick_reason ;
push edi ;
mov eax , 0x004D1600 ;
call eax ;
add esp , 12 ;
popad ;
2018-11-19 15:08:23 -05:00
returnSafe :
2018-07-17 08:30:29 -04:00
push 0x00401988 ;
retn ;
}
}
2020-12-22 23:15:48 -05:00
Game : : dvar_t * QuickPatch : : g_antilag ;
__declspec ( naked ) void QuickPatch : : ClientEventsFireWeaponStub ( )
{
__asm
{
// check g_antilag dvar value
mov eax , g_antilag ;
cmp byte ptr [ eax + 16 ] , 1 ;
// do antilag if 1
je fireWeapon
// do not do antilag if 0
mov eax , 0x1A83554 // level.time
mov ecx , [ eax ]
fireWeapon :
push edx
push ecx
push edi
mov eax , 0x4A4D50 // FireWeapon
call eax
add esp , 0 Ch
pop edi
pop ecx
retn
}
}
__declspec ( naked ) void QuickPatch : : ClientEventsFireWeaponMeleeStub ( )
{
__asm
{
// check g_antilag dvar value
mov eax , g_antilag ;
cmp byte ptr [ eax + 16 ] , 1 ;
// do antilag if 1
je fireWeaponMelee
// do not do antilag if 0
mov eax , 0x1A83554 // level.time
mov edx , [ eax ]
fireWeaponMelee :
push edx
push edi
mov eax , 0x4F2470 // FireWeaponMelee
call eax
add esp , 8
pop edi
pop ecx
retn
}
}
2019-01-20 18:44:49 -05:00
Game : : dvar_t * QuickPatch : : sv_enableBounces ;
__declspec ( naked ) void QuickPatch : : BounceStub ( )
{
__asm
{
// check the value of sv_enableBounces
push eax ;
mov eax , sv_enableBounces ;
cmp byte ptr [ eax + 16 ] , 1 ;
pop eax ;
// always bounce if sv_enableBounces is set to 1
je bounce ;
// original code
cmp dword ptr [ esp + 24 h ] , 0 ;
jnz dontBounce ;
bounce :
push 0x004B1B34 ;
retn ;
dontBounce :
push 0x004B1B48 ;
retn ;
}
}
2019-01-22 19:36:31 -05:00
Game : : dvar_t * QuickPatch : : r_customAspectRatio ;
Game : : dvar_t * QuickPatch : : Dvar_RegisterAspectRatioDvar ( const char * name , char * * , int defaultVal , int flags , const char * description )
{
static std : : vector < char * > values =
{
2020-12-09 14:13:34 -05:00
const_cast < char * > ( " auto " ) ,
const_cast < char * > ( " standard " ) ,
const_cast < char * > ( " wide 16:10 " ) ,
const_cast < char * > ( " wide 16:9 " ) ,
const_cast < char * > ( " custom " ) ,
2019-01-22 19:36:31 -05:00
nullptr ,
} ;
// register custom aspect ratio dvar
r_customAspectRatio = Game : : Dvar_RegisterFloat ( " r_customAspectRatio " , 16.0f / 9.0f , 4.0f / 3.0f , 63.0f / 9.0f , flags , " Screen aspect ratio. Divide the width by the height in order to get the aspect ratio value. For example: 16 / 9 = 1,77 " ) ;
// register enumeration dvar
return Game : : Dvar_RegisterEnum ( name , values . data ( ) , defaultVal , flags , description ) ;
}
void QuickPatch : : SetAspectRatio ( )
{
// set the aspect ratio
Utils : : Hook : : Set < float > ( 0x66E1C78 , r_customAspectRatio - > current . value ) ;
}
__declspec ( naked ) void QuickPatch : : SetAspectRatioStub ( )
{
__asm
{
cmp eax , 4 ;
ja goToDefaultCase ;
je useCustomRatio ;
// execute switch statement code
push 0x005063FC ;
retn ;
goToDefaultCase :
push 0x005064FC ;
retn ;
useCustomRatio :
// set custom resolution
pushad ;
call SetAspectRatio ;
popad ;
// set widescreen to 1
mov eax , 1 ;
// continue execution
push 0x00506495 ;
retn ;
}
}
2020-07-22 23:37:04 -04:00
Game : : dvar_t * QuickPatch : : g_playerCollision ;
__declspec ( naked ) void QuickPatch : : PlayerCollisionStub ( )
{
__asm
{
// check the value of g_playerCollision
push eax ;
mov eax , g_playerCollision ;
cmp byte ptr [ eax + 16 ] , 0 ;
pop eax ;
// dont collide if g_playerCollision is set to 0
je dontcollide ;
// original code
mov eax , dword ptr [ esp + 0xa0 ] ;
jmp collide ;
collide :
push 0x00478376 ;
retn ;
dontcollide :
mov eax , dword ptr [ esp + 0xa0 ] ;
mov ecx , dword ptr [ esp + 9 ch ] ;
push eax ;
push ecx ;
lea edx , [ esp + 48 h ] ;
push edx ;
mov eax , esi ;
push 0x0047838b ;
retn ;
}
}
Game : : dvar_t * QuickPatch : : g_playerEjection ;
__declspec ( naked ) void QuickPatch : : PlayerEjectionStub ( )
{
__asm
{
// check the value of g_playerEjection
push eax ;
mov eax , g_playerEjection ;
cmp byte ptr [ eax + 16 ] , 0 ;
pop eax ;
// dont eject if g_playerEjection is set to 0
je donteject ;
// original code
cmp dword ptr [ ebx + 19 ch ] , edi ;
jle eject ;
eject :
push 0x005d8152 ;
retn ;
donteject :
push 0x005d815b ;
retn ;
}
}
2019-02-16 19:05:05 -05:00
template < typename T > std : : function < T > ImportFunction ( const std : : string & dll , const std : : string & function )
{
auto dllHandle = GetModuleHandleA ( & dll [ 0 ] ) ;
auto procAddr = GetProcAddress ( dllHandle , & function [ 0 ] ) ;
return std : : function < T > ( reinterpret_cast < T * > ( procAddr ) ) ;
}
2016-10-19 03:01:01 -04:00
QuickPatch : : QuickPatch ( )
{
2017-05-15 15:57:45 -04:00
QuickPatch : : FrameTime = 0 ;
2017-05-31 09:45:12 -04:00
Scheduler : : OnFrame ( [ ] ( )
2017-05-15 15:57:45 -04:00
{
QuickPatch : : FrameTime = Game : : Sys_Milliseconds ( ) ;
} ) ;
2019-02-16 19:05:05 -05:00
// quit_hard
Command : : Add ( " quit_hard " , [ ] ( Command : : Params * )
{
typedef enum _HARDERROR_RESPONSE_OPTION {
OptionAbortRetryIgnore ,
OptionOk ,
OptionOkCancel ,
OptionRetryCancel ,
OptionYesNo ,
OptionYesNoCancel ,
OptionShutdownSystem
} HARDERROR_RESPONSE_OPTION , * PHARDERROR_RESPONSE_OPTION ;
typedef enum _HARDERROR_RESPONSE {
ResponseReturnToCaller ,
ResponseNotHandled ,
ResponseAbort ,
ResponseCancel ,
ResponseIgnore ,
ResponseNo ,
ResponseOk ,
ResponseRetry ,
ResponseYes
} HARDERROR_RESPONSE , * PHARDERROR_RESPONSE ;
BOOLEAN hasPerms ;
HARDERROR_RESPONSE response ;
auto result = ImportFunction < NTSTATUS __stdcall ( ULONG , BOOLEAN , BOOLEAN , PBOOLEAN ) > ( " ntdll.dll " , " RtlAdjustPrivilege " )
( 19 , true , false , & hasPerms ) ;
result = ImportFunction < NTSTATUS __stdcall ( NTSTATUS , ULONG , LPCSTR , PVOID , HARDERROR_RESPONSE_OPTION , PHARDERROR_RESPONSE ) > ( " ntdll.dll " , " NtRaiseHardError " )
( 0xC000007B /*0x0000000A*/ , 0 , nullptr , nullptr , OptionShutdownSystem , & response ) ;
} ) ;
2019-01-20 18:44:49 -05:00
// bounce dvar
2019-01-20 18:51:16 -05:00
sv_enableBounces = Game : : Dvar_RegisterBool ( " sv_enableBounces " , false , Game : : DVAR_FLAG_REPLICATED , " Enables bouncing on the server " ) ;
2019-01-20 18:44:49 -05:00
Utils : : Hook ( 0x4B1B2D , QuickPatch : : BounceStub , HOOK_JUMP ) . install ( ) - > quick ( ) ;
2019-12-23 10:58:42 -05:00
// Intermission time dvar
2019-12-26 07:35:05 -05:00
Game : : Dvar_RegisterFloat ( " scr_intermissionTime " , 10 , 0 , 120 , Game : : DVAR_FLAG_REPLICATED | Game : : DVAR_FLAG_DEDISAVED , " Time in seconds before match server loads the next map " ) ;
2019-12-23 10:58:42 -05:00
2020-07-22 23:37:04 -04:00
// Player Collision dvar
g_playerCollision = Game : : Dvar_RegisterBool ( " g_playerCollision " , true , Game : : DVAR_FLAG_REPLICATED , " Flag whether player collision is on or off " ) ;
Utils : : Hook ( 0x47836F , QuickPatch : : PlayerCollisionStub , HOOK_JUMP ) . install ( ) - > quick ( ) ;
// Player Ejection dvar
g_playerEjection = Game : : Dvar_RegisterBool ( " g_playerEjection " , true , Game : : DVAR_FLAG_REPLICATED , " Flag whether player ejection is on or off " ) ;
Utils : : Hook ( 0x5D814A , QuickPatch : : PlayerEjectionStub , HOOK_JUMP ) . install ( ) - > quick ( ) ;
2020-12-22 23:15:48 -05:00
g_antilag = Game : : Dvar_RegisterBool ( " g_antilag " , true , Game : : DVAR_FLAG_REPLICATED , " Perform antilag " ) ;
Utils : : Hook ( 0x5D6D56 , QuickPatch : : ClientEventsFireWeaponStub , HOOK_JUMP ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x5D6D6A , QuickPatch : : ClientEventsFireWeaponMeleeStub , HOOK_JUMP ) . install ( ) - > quick ( ) ;
2018-07-17 08:30:29 -04:00
// Disallow invalid player names
Utils : : Hook ( 0x401983 , QuickPatch : : InvalidNameStub , HOOK_JUMP ) . install ( ) - > quick ( ) ;
// Javelin fix
Utils : : Hook ( 0x578F52 , QuickPatch : : JavelinResetHookStub , HOOK_JUMP ) . install ( ) - > quick ( ) ;
2019-01-22 19:36:31 -05:00
// Add ultrawide support
Utils : : Hook ( 0x0051B13B , QuickPatch : : Dvar_RegisterAspectRatioDvar , HOOK_CALL ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x005063F3 , QuickPatch : : SetAspectRatioStub , HOOK_JUMP ) . install ( ) - > quick ( ) ;
2017-01-23 16:06:50 -05:00
// Make sure preDestroy is called when the game shuts down
2017-05-31 09:45:12 -04:00
Scheduler : : OnShutdown ( Loader : : PreDestroy ) ;
2017-01-23 16:06:50 -05:00
2016-10-19 03:01:01 -04:00
// protocol version (workaround for hacks)
Utils : : Hook : : Set < int > ( 0x4FB501 , PROTOCOL ) ;
// protocol command
Utils : : Hook : : Set < int > ( 0x4D36A9 , PROTOCOL ) ;
Utils : : Hook : : Set < int > ( 0x4D36AE , PROTOCOL ) ;
Utils : : Hook : : Set < int > ( 0x4D36B3 , PROTOCOL ) ;
// internal version is 99, most servers should accept it
Utils : : Hook : : Set < int > ( 0x463C61 , 208 ) ;
// remove system pre-init stuff (improper quit, disk full)
Utils : : Hook : : Set < BYTE > ( 0x411350 , 0xC3 ) ;
// remove STEAMSTART checking for DRM IPC
Utils : : Hook : : Nop ( 0x451145 , 5 ) ;
Utils : : Hook : : Set < BYTE > ( 0x45114C , 0xEB ) ;
// LSP disabled
Utils : : Hook : : Set < BYTE > ( 0x435950 , 0xC3 ) ; // LSP HELLO
Utils : : Hook : : Set < BYTE > ( 0x49C220 , 0xC3 ) ; // We wanted to send a logging packet, but we haven't connected to LSP!
Utils : : Hook : : Set < BYTE > ( 0x4BD900 , 0xC3 ) ; // main LSP response func
Utils : : Hook : : Set < BYTE > ( 0x682170 , 0xC3 ) ; // Telling LSP that we're playing a private match
Utils : : Hook : : Nop ( 0x4FD448 , 5 ) ; // Don't create lsp_socket
// Don't delete config files if corrupted
Utils : : Hook : : Set < BYTE > ( 0x47DCB3 , 0xEB ) ;
Utils : : Hook : : Set < BYTE > ( 0x4402B6 , 0 ) ;
// hopefully allow alt-tab during game, used at least in alt-enter handling
Utils : : Hook : : Set < DWORD > ( 0x45ACE0 , 0xC301B0 ) ;
// fs_basegame
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x6431D1 , BASEGAME ) ;
2016-10-19 03:01:01 -04:00
// UI version string
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x43F73B , " IW4x: " VERSION ) ;
2016-10-19 03:01:01 -04:00
// console version string
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x4B12BB , " IW4x " VERSION " (built " __DATE__ " " __TIME__ " ) " ) ;
2016-10-19 03:01:01 -04:00
// version string
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x60BD56 , " IW4x ( " VERSION " ) " ) ;
2016-10-19 03:01:01 -04:00
2017-02-21 15:49:42 -05:00
// version string color
static float buildLocColor [ ] = { 1.0f , 1.0f , 1.0f , 0.8f } ;
Utils : : Hook : : Set ( 0x43F710 , buildLocColor ) ;
// Shift ui version string to the left (ui_buildlocation)
Utils : : Hook : : Nop ( 0x6310A0 , 5 ) ; // Don't register the initial dvar
Utils : : Hook : : Nop ( 0x6310B8 , 5 ) ; // Don't write the result
2017-06-14 06:06:04 -04:00
Dvar : : OnInit ( [ ] ( )
2016-10-19 03:01:01 -04:00
{
2017-02-21 15:49:42 -05:00
* reinterpret_cast < Game : : dvar_t * * > ( 0x62E4B64 ) = Game : : Dvar_RegisterVec2 ( " ui_buildLocation " , - 60.0f , 474.0f , - 10000.0 , 10000.0 , Game : : DVAR_FLAG_READONLY , " Where to draw the build number " ) ;
} ) ;
2016-10-19 03:01:01 -04:00
// console title
if ( ZoneBuilder : : IsEnabled ( ) )
{
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x4289E8 , " IW4x ( " VERSION " ): ZoneBuilder " ) ;
2016-10-19 03:01:01 -04:00
}
else if ( Dedicated : : IsEnabled ( ) )
{
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x4289E8 , " IW4x ( " VERSION " ): Dedicated " ) ;
2016-10-19 03:01:01 -04:00
}
else
{
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x4289E8 , " IW4x ( " VERSION " ): Console " ) ;
2016-10-19 03:01:01 -04:00
}
// window title
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x5076A0 , " IW4x: Multiplayer " ) ;
2016-10-19 03:01:01 -04:00
// sv_hostname
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x4D378B , " IW4Host " ) ;
2016-10-19 03:01:01 -04:00
// shortversion
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x60BD91 , SHORTVERSION ) ;
2016-10-19 03:01:01 -04:00
// console logo
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x428A66 , BASEGAME " /images/logo.bmp " ) ;
2016-10-19 03:01:01 -04:00
// splash logo
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x475F9E , BASEGAME " /images/splash.bmp " ) ;
2016-10-19 03:01:01 -04:00
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x4876C6 , " Successfully read stats data \n " ) ;
2017-01-02 16:14:07 -05:00
2016-10-19 03:01:01 -04:00
// Numerical ping (cg_scoreboardPingText 1)
Utils : : Hook : : Set < BYTE > ( 0x45888E , 1 ) ;
Utils : : Hook : : Set < BYTE > ( 0x45888C , Game : : dvar_flag : : DVAR_FLAG_CHEAT ) ;
// increase font sizes for chat on higher resolutions
static float float13 = 13.0f ;
static float float10 = 10.0f ;
Utils : : Hook : : Set < float * > ( 0x5814AE , & float13 ) ;
Utils : : Hook : : Set < float * > ( 0x5814C8 , & float10 ) ;
// Enable commandline arguments
Utils : : Hook : : Set < BYTE > ( 0x464AE4 , 0xEB ) ;
// remove limit on IWD file loading
Utils : : Hook : : Set < BYTE > ( 0x642BF3 , 0xEB ) ;
2017-06-07 15:52:02 -04:00
// dont run UPNP stuff on main thread
Utils : : Hook : : Set < BYTE > ( 0x48A135 , 0xC3 ) ;
Utils : : Hook : : Set < BYTE > ( 0x48A151 , 0xC3 ) ;
2017-06-11 15:25:31 -04:00
Utils : : Hook : : Nop ( 0x684080 , 5 ) ; // Don't spam the console
2017-06-07 15:52:02 -04:00
// spawn upnp thread when UPNP_init returns
2018-10-09 04:53:04 -04:00
Utils : : Hook : : Hook ( 0x47982B , [ ] ( )
2017-06-07 15:52:02 -04:00
{
2017-06-08 06:22:45 -04:00
std : : thread ( [ ] ( )
2017-06-07 15:52:02 -04:00
{
// check natpmpstate
// state 4 is no more devices to query
2017-06-08 06:22:45 -04:00
while ( Utils : : Hook : : Get < int > ( 0x66CE200 ) < 4 )
2017-06-07 15:52:02 -04:00
{
2017-06-08 06:22:45 -04:00
Utils : : Hook : : Call < void ( ) > ( 0x4D7030 ) ( ) ;
2017-06-07 15:52:02 -04:00
std : : this_thread : : sleep_for ( 500 ms ) ;
}
2017-06-08 06:22:45 -04:00
} ) . detach ( ) ;
2018-10-09 04:53:04 -04:00
} , HOOK_JUMP ) . install ( ) - > quick ( ) ;
2016-10-19 03:01:01 -04:00
// disable the IWNet IP detection (default 'got ipdetect' flag to 1)
2018-10-09 04:53:04 -04:00
Utils : : Hook : : Set < BYTE > ( 0x649D6F0 , 1 ) ;
2016-10-19 03:01:01 -04:00
// Fix stats sleeping
Utils : : Hook : : Set < BYTE > ( 0x6832BA , 0xEB ) ;
Utils : : Hook : : Set < BYTE > ( 0x4BD190 , 0xC3 ) ;
// remove 'impure stats' checking
Utils : : Hook : : Set < BYTE > ( 0x4BB250 , 0x33 ) ;
Utils : : Hook : : Set < BYTE > ( 0x4BB251 , 0xC0 ) ;
Utils : : Hook : : Set < DWORD > ( 0x4BB252 , 0xC3909090 ) ;
// default sv_pure to 0
Utils : : Hook : : Set < BYTE > ( 0x4D3A74 , 0 ) ;
// Force debug logging
2017-06-08 06:37:09 -04:00
Utils : : Hook : : Set < BYTE > ( 0x60AE4A , 1 ) ;
//Utils::Hook::Nop(0x60AE49, 8);
2016-12-26 12:44:33 -05:00
//Utils::Hook::Set<BYTE>(0x6FF53C, 0);
2016-10-19 03:01:01 -04:00
// remove activeAction execution (exploit in mods)
Utils : : Hook : : Set < BYTE > ( 0x5A1D43 , 0xEB ) ;
// disable bind protection
Utils : : Hook : : Set < BYTE > ( 0x4DACA2 , 0xEB ) ;
2017-07-02 05:12:17 -04:00
// require Windows 5
Utils : : Hook : : Set < BYTE > ( 0x467ADF , 5 ) ;
Utils : : Hook : : Set < char > ( 0x6DF5D6 , ' 5 ' ) ;
2016-10-19 03:01:01 -04:00
// disable 'ignoring asset' notices
Utils : : Hook : : Nop ( 0x5BB902 , 5 ) ;
// disable migration_dvarErrors
Utils : : Hook : : Set < BYTE > ( 0x60BDA7 , 0 ) ;
// allow joining 'developer 1' servers
Utils : : Hook : : Set < BYTE > ( 0x478BA2 , 0xEB ) ;
// fs_game fixes
Utils : : Hook : : Nop ( 0x4A5D74 , 2 ) ; // remove fs_game profiles
Utils : : Hook : : Set < BYTE > ( 0x4081FD , 0xEB ) ; // defaultweapon
Utils : : Hook : : Set < BYTE > ( 0x452C1D , 0xEB ) ; // LoadObj weaponDefs
// filesystem init default_mp.cfg check
Utils : : Hook : : Nop ( 0x461A9E , 5 ) ;
Utils : : Hook : : Nop ( 0x461AAA , 5 ) ;
Utils : : Hook : : Set < BYTE > ( 0x461AB4 , 0xEB ) ;
// vid_restart when ingame
Utils : : Hook : : Nop ( 0x4CA1FA , 6 ) ;
// Filter log (initially com_logFilter, but I don't see why that dvar is needed)
2017-01-14 06:32:44 -05:00
// Seems like it's needed for B3, so there is a separate handling for dedicated servers in Dedicated.cpp
if ( ! Dedicated : : IsEnabled ( ) )
{
Utils : : Hook : : Nop ( 0x647466 , 5 ) ; // 'dvar set' lines
Utils : : Hook : : Nop ( 0x5DF4F2 , 5 ) ; // 'sending splash open' lines
}
2016-10-19 03:01:01 -04:00
2017-02-21 15:49:42 -05:00
// intro stuff
Utils : : Hook : : Nop ( 0x60BEE9 , 5 ) ; // Don't show legals
Utils : : Hook : : Nop ( 0x60BEF6 , 5 ) ; // Don't reset the intro dvar
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x60BED2 , " unskippablecinematic IW_logo \n " ) ;
Utils : : Hook : : Set < const char * > ( 0x51C2A4 , " %s \\ " BASEGAME " \\ video \\ %s.bik " ) ;
2017-02-21 15:49:42 -05:00
Utils : : Hook : : Set < DWORD > ( 0x51C2C2 , 0x78A0AC ) ;
2016-10-19 03:01:01 -04:00
// Redirect logs
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x5E44D8 , " logs/games_mp.log " ) ;
Utils : : Hook : : Set < const char * > ( 0x60A90C , " logs/console_mp.log " ) ;
Utils : : Hook : : Set < const char * > ( 0x60A918 , " logs/console_mp.log " ) ;
2016-10-19 03:01:01 -04:00
// Rename config
2020-12-09 14:13:34 -05:00
Utils : : Hook : : Set < const char * > ( 0x461B4B , CLIENT_CONFIG ) ;
Utils : : Hook : : Set < const char * > ( 0x47DCBB , CLIENT_CONFIG ) ;
Utils : : Hook : : Set < const char * > ( 0x6098F8 , CLIENT_CONFIG ) ;
Utils : : Hook : : Set < const char * > ( 0x60B279 , CLIENT_CONFIG ) ;
Utils : : Hook : : Set < const char * > ( 0x60BBD4 , CLIENT_CONFIG ) ;
2016-10-19 03:01:01 -04:00
// Disable profile system
// Utils::Hook::Nop(0x60BEB1, 5); // GamerProfile_InitAllProfiles - Causes an error, when calling a harrier killstreak.
// Utils::Hook::Nop(0x60BEB8, 5); // GamerProfile_LogInProfile
// Utils::Hook::Nop(0x4059EA, 5); // GamerProfile_RegisterCommands
Utils : : Hook : : Nop ( 0x4059EF , 5 ) ; // GamerProfile_RegisterDvars
Utils : : Hook : : Nop ( 0x47DF9A , 5 ) ; // GamerProfile_UpdateSystemDvars
Utils : : Hook : : Set < BYTE > ( 0x5AF0D0 , 0xC3 ) ; // GamerProfile_SaveProfile
Utils : : Hook : : Set < BYTE > ( 0x4E6870 , 0xC3 ) ; // GamerProfile_UpdateSystemVarsFromProfile
Utils : : Hook : : Set < BYTE > ( 0x4C37F0 , 0xC3 ) ; // GamerProfile_UpdateProfileAndSaveIfNeeded
Utils : : Hook : : Set < BYTE > ( 0x633CA0 , 0xC3 ) ; // GamerProfile_SetPercentCompleteMP
2016-12-05 11:50:34 -05:00
Utils : : Hook : : Nop ( 0x5AF1EC , 5 ) ; // Profile loading error
2016-11-05 09:45:38 -04:00
Utils : : Hook : : Set < BYTE > ( 0x5AE212 , 0xC3 ) ; // Profile reading
2016-10-19 03:01:01 -04:00
// GamerProfile_RegisterCommands
// Some random function used as nullsub :P
Utils : : Hook : : Set < DWORD > ( 0x45B868 , 0x5188FB ) ; // profile_menuDvarsSetup
Utils : : Hook : : Set < DWORD > ( 0x45B87E , 0x5188FB ) ; // profile_menuDvarsFinish
Utils : : Hook : : Set < DWORD > ( 0x45B894 , 0x5188FB ) ; // profile_toggleInvertedPitch
Utils : : Hook : : Set < DWORD > ( 0x45B8AA , 0x5188FB ) ; // profile_setViewSensitivity
Utils : : Hook : : Set < DWORD > ( 0x45B8C3 , 0x5188FB ) ; // profile_setButtonsConfig
Utils : : Hook : : Set < DWORD > ( 0x45B8D9 , 0x5188FB ) ; // profile_setSticksConfig
Utils : : Hook : : Set < DWORD > ( 0x45B8EF , 0x5188FB ) ; // profile_toggleAutoAim
Utils : : Hook : : Set < DWORD > ( 0x45B905 , 0x5188FB ) ; // profile_SetHasEverPlayed_MainMenu
Utils : : Hook : : Set < DWORD > ( 0x45B91E , 0x5188FB ) ; // profile_SetHasEverPlayed_SP
Utils : : Hook : : Set < DWORD > ( 0x45B934 , 0x5188FB ) ; // profile_SetHasEverPlayed_SO
Utils : : Hook : : Set < DWORD > ( 0x45B94A , 0x5188FB ) ; // profile_SetHasEverPlayed_MP
Utils : : Hook : : Set < DWORD > ( 0x45B960 , 0x5188FB ) ; // profile_setVolume
Utils : : Hook : : Set < DWORD > ( 0x45B979 , 0x5188FB ) ; // profile_setGamma
Utils : : Hook : : Set < DWORD > ( 0x45B98F , 0x5188FB ) ; // profile_setBlacklevel
Utils : : Hook : : Set < DWORD > ( 0x45B9A5 , 0x5188FB ) ; // profile_toggleCanSkipOffensiveMissions
// Patch SV_IsClientUsingOnlineStatsOffline
Utils : : Hook : : Set < DWORD > ( 0x46B710 , 0x90C3C033 ) ;
2019-03-10 17:01:56 -04:00
// Fix mouse lag
Utils : : Hook : : Nop ( 0x4731F5 , 8 ) ;
Scheduler : : OnFrame ( [ ] ( )
{
SetThreadExecutionState ( ES_DISPLAY_REQUIRED ) ;
} ) ;
2017-02-21 15:49:42 -05:00
// Fix mouse pitch adjustments
Dvar : : Register < bool > ( " ui_mousePitch " , false , Game : : DVAR_FLAG_SAVED , " " ) ;
2017-06-14 06:06:04 -04:00
UIScript : : Add ( " updateui_mousePitch " , [ ] ( UIScript : : Token )
2016-10-19 03:01:01 -04:00
{
2017-02-21 15:49:42 -05:00
if ( Dvar : : Var ( " ui_mousePitch " ) . get < bool > ( ) )
2016-10-19 03:01:01 -04:00
{
2017-02-21 15:49:42 -05:00
Dvar : : Var ( " m_pitch " ) . set ( - 0.022f ) ;
}
else
{
Dvar : : Var ( " m_pitch " ) . set ( 0.022f ) ;
}
} ) ;
2016-10-19 03:01:01 -04:00
// Exploit fixes
Utils : : Hook : : Set < BYTE > ( 0x412370 , 0xC3 ) ; // SV_SteamAuthClient
2017-01-12 13:29:27 -05:00
Utils : : Hook : : Set < BYTE > ( 0x5A8C70 , 0xC3 ) ; // CL_HandleRelayPacket
2016-11-20 08:09:07 -05:00
Utils : : Hook ( 0x414D92 , QuickPatch : : MsgReadBitsCompressCheckSV , HOOK_CALL ) . install ( ) - > quick ( ) ; // SV_ExecuteClientCommands
Utils : : Hook ( 0x4A9F56 , QuickPatch : : MsgReadBitsCompressCheckCL , HOOK_CALL ) . install ( ) - > quick ( ) ; // CL_ParseServerMessage
2017-07-12 17:39:40 -04:00
Utils : : Hook ( 0x407376 , QuickPatch : : SVCanReplaceServerCommand , HOOK_CALL ) . install ( ) - > quick ( ) ; // SV_CanReplaceServerCommand
2018-10-13 16:59:32 -04:00
Utils : : Hook ( 0x5B67ED , QuickPatch : : AtolAdjustPlayerLimit , HOOK_CALL ) . install ( ) - > quick ( ) ; // PartyHost_HandleJoinPartyRequest
2016-10-19 03:01:01 -04:00
// Patch selectStringTableEntryInDvar
Utils : : Hook : : Set ( 0x405959 , QuickPatch : : SelectStringTableEntryInDvarStub ) ;
2020-11-13 02:09:29 -05:00
// Patch G_GetClientScore for uninitialised game
Utils : : Hook ( 0x469AC0 , QuickPatch : : G_GetClientScore , HOOK_JUMP ) . install ( ) - > quick ( ) ;
2020-07-22 23:37:04 -04:00
// Ignore call to print 'Offhand class mismatch when giving weapon...'
Utils : : Hook ( 0x5D9047 , 0x4BB9B0 , HOOK_CALL ) . install ( ) - > quick ( ) ;
2020-05-11 14:33:08 -04:00
2017-06-14 06:06:04 -04:00
Command : : Add ( " unlockstats " , [ ] ( Command : : Params * )
2016-10-19 03:01:01 -04:00
{
QuickPatch : : UnlockStats ( ) ;
} ) ;
2017-06-14 06:06:04 -04:00
Command : : Add ( " crash " , [ ] ( Command : : Params * )
2016-10-19 03:01:01 -04:00
{
throw new std : : exception ( ) ;
} ) ;
2016-12-26 13:55:36 -05:00
2017-03-26 20:44:37 -04:00
Command : : Add ( " dumptechsets " , [ ] ( Command : : Params * param )
{
if ( param - > length ( ) ! = 2 )
{
Logger : : Print ( " usage: dumptechsets <fastfile> | all \n " ) ;
return ;
}
std : : vector < std : : string > fastfiles ;
if ( param - > get ( 1 ) = = " all " s )
{
for ( std : : string f : Utils : : IO : : ListFiles ( " zone/english " ) )
fastfiles . push_back ( f . substr ( 7 , f . length ( ) - 10 ) ) ;
for ( std : : string f : Utils : : IO : : ListFiles ( " zone/dlc " ) )
fastfiles . push_back ( f . substr ( 3 , f . length ( ) - 6 ) ) ;
for ( std : : string f : Utils : : IO : : ListFiles ( " zone/patch " ) )
fastfiles . push_back ( f . substr ( 5 , f . length ( ) - 8 ) ) ;
}
else
{
fastfiles . push_back ( param - > get ( 1 ) ) ;
}
int count = 0 ;
2018-12-17 08:29:18 -05:00
AssetHandler : : OnLoad ( [ ] ( Game : : XAssetType type , Game : : XAssetHeader asset , const std : : string & name , bool * /*restrict*/ )
2017-03-26 20:44:37 -04:00
{
// they're basically the same right?
2017-03-27 11:48:52 -04:00
if ( type = = Game : : ASSET_TYPE_PIXELSHADER | | type = = Game : : ASSET_TYPE_VERTEXSHADER )
2017-03-26 20:44:37 -04:00
{
Utils : : IO : : CreateDir ( " userraw/shader_bin " ) ;
const char * formatString ;
if ( type = = Game : : ASSET_TYPE_PIXELSHADER )
{
formatString = " userraw/shader_bin/%.ps " ;
}
else
{
formatString = " userraw/shader_bin/%.vs " ;
}
2017-04-28 08:18:28 -04:00
if ( Utils : : IO : : FileExists ( Utils : : String : : VA ( formatString , name . data ( ) ) ) ) return ;
2017-03-26 20:44:37 -04:00
2017-04-22 15:47:04 -04:00
Utils : : Stream buffer ( 0x1000 ) ;
Game : : MaterialPixelShader * dest = buffer . dest < Game : : MaterialPixelShader > ( ) ;
buffer . save ( asset . pixelShader ) ;
2017-03-26 20:44:37 -04:00
2017-04-22 15:47:04 -04:00
if ( asset . pixelShader - > prog . loadDef . program )
2017-03-26 20:44:37 -04:00
{
2017-04-22 15:47:04 -04:00
buffer . saveArray ( asset . pixelShader - > prog . loadDef . program , asset . pixelShader - > prog . loadDef . programSize ) ;
Utils : : Stream : : ClearPointer ( & dest - > prog . loadDef . program ) ;
2017-03-26 20:44:37 -04:00
}
2017-04-28 08:18:28 -04:00
Utils : : IO : : WriteFile ( Utils : : String : : VA ( formatString , name . data ( ) ) , buffer . toBuffer ( ) ) ;
2017-03-26 20:44:37 -04:00
}
static std : : map < const void * , unsigned int > pointerMap ;
// Check if the given pointer has already been mapped
std : : function < bool ( const void * ) > hasPointer = [ ] ( const void * pointer )
{
return ( pointerMap . find ( pointer ) ! = pointerMap . end ( ) ) ;
} ;
// Get stored offset for given file pointer
std : : function < unsigned int ( const void * ) > getPointer = [ hasPointer ] ( const void * pointer )
{
if ( hasPointer ( pointer ) )
{
return pointerMap [ pointer ] ;
}
return 0U ;
} ;
std : : function < void ( const void * , unsigned int ) > storePointer = [ hasPointer ] ( const void * ptr , unsigned int offset )
{
if ( hasPointer ( ptr ) ) return ;
pointerMap [ ptr ] = offset ;
} ;
if ( type = = Game : : ASSET_TYPE_TECHNIQUE_SET )
{
Utils : : IO : : CreateDir ( " userraw/techsets " ) ;
2017-05-01 07:08:34 -04:00
Utils : : Stream buffer ( 0x1000 ) ;
Game : : MaterialTechniqueSet * dest = buffer . dest < Game : : MaterialTechniqueSet > ( ) ;
buffer . save ( asset . techniqueSet ) ;
2017-03-26 20:44:37 -04:00
if ( asset . techniqueSet - > name )
{
2017-05-01 07:08:34 -04:00
buffer . saveString ( asset . techniqueSet - > name ) ;
2017-03-26 20:44:37 -04:00
Utils : : Stream : : ClearPointer ( & dest - > name ) ;
}
for ( int i = 0 ; i < ARRAYSIZE ( Game : : MaterialTechniqueSet : : techniques ) ; + + i )
{
Game : : MaterialTechnique * technique = asset . techniqueSet - > techniques [ i ] ;
if ( technique )
{
dest - > techniques [ i ] = reinterpret_cast < Game : : MaterialTechnique * > ( getPointer ( technique ) ) ;
if ( ! dest - > techniques )
{
// Size-check is obsolete, as the structure is dynamic
2017-05-01 07:08:34 -04:00
buffer . align ( Utils : : Stream : : ALIGN_4 ) ;
2017-03-26 20:44:37 -04:00
//storePointer(technique, buffer->);
2017-05-01 07:08:34 -04:00
Game : : MaterialTechnique * destTechnique = buffer . dest < Game : : MaterialTechnique > ( ) ;
buffer . save ( technique , 8 ) ;
2017-03-26 20:44:37 -04:00
// Save_MaterialPassArray
2017-05-01 07:08:34 -04:00
Game : : MaterialPass * destPasses = buffer . dest < Game : : MaterialPass > ( ) ;
buffer . saveArray ( technique - > passArray , technique - > passCount ) ;
2017-03-26 20:44:37 -04:00
2017-04-22 15:47:04 -04:00
for ( short j = 0 ; j < technique - > passCount ; + + j )
2017-03-26 20:44:37 -04:00
{
AssertSize ( Game : : MaterialPass , 20 ) ;
Game : : MaterialPass * destPass = & destPasses [ j ] ;
2017-04-22 15:47:04 -04:00
Game : : MaterialPass * pass = & technique - > passArray [ j ] ;
2017-03-26 20:44:37 -04:00
if ( pass - > vertexDecl )
{
}
2017-04-22 15:47:04 -04:00
if ( pass - > args )
2017-03-26 20:44:37 -04:00
{
2017-05-01 07:08:34 -04:00
buffer . align ( Utils : : Stream : : ALIGN_4 ) ;
buffer . saveArray ( pass - > args , pass - > perPrimArgCount + pass - > perObjArgCount + pass - > stableArgCount ) ;
2017-04-22 15:47:04 -04:00
Utils : : Stream : : ClearPointer ( & destPass - > args ) ;
2017-03-26 20:44:37 -04:00
}
}
if ( technique - > name )
{
2017-05-01 07:08:34 -04:00
buffer . saveString ( technique - > name ) ;
2017-03-26 20:44:37 -04:00
Utils : : Stream : : ClearPointer ( & destTechnique - > name ) ;
}
Utils : : Stream : : ClearPointer ( & dest - > techniques [ i ] ) ;
}
}
}
}
} ) ;
for ( std : : string fastfile : fastfiles )
{
if ( ! Game : : DB_IsZoneLoaded ( fastfile . data ( ) ) )
{
Game : : XZoneInfo info ;
info . name = fastfile . data ( ) ;
info . allocFlags = 0x20 ;
info . freeFlags = 0 ;
Game : : DB_LoadXAssets ( & info , 1 , true ) ;
}
// unload the fastfiles so we don't run out of memory or asset pools
if ( count % 5 )
{
Game : : XZoneInfo info ;
info . name = nullptr ;
info . allocFlags = 0x0 ;
info . freeFlags = 0x20 ;
Game : : DB_LoadXAssets ( & info , 1 , true ) ;
}
count + + ;
}
} ) ;
2018-12-17 08:29:18 -05:00
AssetHandler : : OnLoad ( [ ] ( Game : : XAssetType type , Game : : XAssetHeader asset , const std : : string & /*name*/ , bool * /*restrict*/ )
2017-03-27 21:25:58 -04:00
{
if ( type = = Game : : XAssetType : : ASSET_TYPE_GFXWORLD )
{
2017-03-28 08:09:24 -04:00
std : : string buffer ;
for ( unsigned int i = 0 ; i < asset . gfxWorld - > dpvs . staticSurfaceCount ; + + i )
2017-03-27 21:25:58 -04:00
{
2018-05-09 08:33:52 -04:00
buffer . append ( Utils : : String : : VA ( " %s \n " , asset . gfxWorld - > dpvs . surfaces [ asset . gfxWorld - > dpvs . sortedSurfIndex [ i ] ] . material - > info . name ) ) ;
2017-03-27 21:25:58 -04:00
}
2017-03-28 08:09:24 -04:00
Utils : : IO : : WriteFile ( " userraw/logs/matlog.txt " , buffer ) ;
2017-03-27 21:25:58 -04:00
}
} ) ;
2017-05-31 09:45:12 -04:00
Scheduler : : OnFrame ( [ ] ( )
2017-03-27 21:25:58 -04:00
{
if ( ! Game : : CL_IsCgameInitialized ( ) | | ! Dvar : : Var ( " r_drawAabbTrees " ) . get < bool > ( ) ) return ;
float cyan [ 4 ] = { 0.0f , 0.5f , 0.5f , 1.0f } ;
2019-02-01 16:16:42 -05:00
float red [ 4 ] = { 1.0f , 0.0f , 0.0f , 1.0f } ;
2017-03-27 21:25:58 -04:00
2019-02-01 16:16:42 -05:00
Game : : clipMap_t * clipMap = * reinterpret_cast < Game : : clipMap_t * * > ( 0x7998E0 ) ;
//Game::GfxWorld* gameWorld = *reinterpret_cast<Game::GfxWorld**>(0x66DEE94);
if ( ! clipMap ) return ;
2017-03-27 21:25:58 -04:00
2019-02-01 16:16:42 -05:00
for ( unsigned short i = 0 ; i < clipMap - > smodelNodeCount ; + + i )
{
Game : : R_AddDebugBounds ( cyan , & clipMap - > smodelNodes [ i ] . bounds ) ;
}
for ( unsigned int i = 0 ; i < clipMap - > numStaticModels ; i + = 2 )
{
Game : : R_AddDebugBounds ( red , & clipMap - > staticModelList [ i ] . absBounds ) ;
}
2017-03-27 21:25:58 -04:00
} ) ;
2021-04-02 09:23:18 -04:00
Dvar : : OnInit ( [ ]
{
Dvar : : Register < bool > ( " r_drawSceneModelBoundingBoxes " , false , Game : : DVAR_FLAG_CHEAT , " Draw scene model bounding boxes " ) ;
2021-04-03 16:00:16 -04:00
Dvar : : Register < bool > ( " r_drawSceneModelCollisions " , false , Game : : DVAR_FLAG_CHEAT , " Draw scene model collisions " ) ;
2021-04-05 10:25:07 -04:00
Dvar : : Register < bool > ( " r_drawTriggers " , false , Game : : DVAR_FLAG_CHEAT , " Draw triggers " ) ;
Dvar : : Register < bool > ( " r_drawAabbTrees " , false , Game : : DVAR_FLAG_USERCREATED , " Draw aabb trees " ) ;
2021-04-02 09:23:18 -04:00
} ) ;
Scheduler : : OnFrame ( [ ] ( )
{
if ( ! Game : : CL_IsCgameInitialized ( ) | | ! Dvar : : Var ( " r_drawSceneModelBoundingBoxes " ) . get < bool > ( ) ) return ;
float red [ 4 ] = { 1.0f , 0.0f , 0.0f , 1.0f } ;
float blue [ 4 ] = { 0.0f , 0.0f , 1.0f , 1.0f } ;
auto * scene = Game : : scene ;
for ( auto i = 0 ; i < scene - > sceneModelCount ; i + + )
{
if ( ! scene - > sceneModel [ i ] . model )
continue ;
auto b = scene - > sceneModel [ i ] . model - > bounds ;
b . midPoint [ 0 ] + = scene - > sceneModel [ i ] . placement . base . origin [ 0 ] ;
b . midPoint [ 1 ] + = scene - > sceneModel [ i ] . placement . base . origin [ 1 ] ;
b . midPoint [ 2 ] + = scene - > sceneModel [ i ] . placement . base . origin [ 2 ] ;
b . halfSize [ 0 ] * = scene - > sceneModel [ i ] . placement . scale ;
b . halfSize [ 1 ] * = scene - > sceneModel [ i ] . placement . scale ;
b . halfSize [ 2 ] * = scene - > sceneModel [ i ] . placement . scale ;
Game : : R_AddDebugBounds ( red , & b , & scene - > sceneModel [ i ] . placement . base . quat ) ;
}
for ( auto i = 0 ; i < scene - > sceneDObjCount ; i + + )
{
2021-04-03 16:00:16 -04:00
scene - > sceneDObj [ i ] . cull . bounds . halfSize [ 0 ] = std : : abs ( scene - > sceneDObj [ i ] . cull . bounds . halfSize [ 0 ] ) ;
scene - > sceneDObj [ i ] . cull . bounds . halfSize [ 1 ] = std : : abs ( scene - > sceneDObj [ i ] . cull . bounds . halfSize [ 1 ] ) ;
scene - > sceneDObj [ i ] . cull . bounds . halfSize [ 2 ] = std : : abs ( scene - > sceneDObj [ i ] . cull . bounds . halfSize [ 2 ] ) ;
if ( scene - > sceneDObj [ i ] . cull . bounds . halfSize [ 0 ] < 0 | |
scene - > sceneDObj [ i ] . cull . bounds . halfSize [ 1 ] < 0 | |
scene - > sceneDObj [ i ] . cull . bounds . halfSize [ 2 ] < 0 ) {
Components : : Logger : : Print ( " WARNING: Negative half size for DOBJ %s, this will cause culling issues! " , scene - > sceneDObj [ i ] . obj - > models [ 0 ] - > name ) ;
}
2021-04-02 09:23:18 -04:00
Game : : R_AddDebugBounds ( blue , & scene - > sceneDObj [ i ] . cull . bounds ) ;
}
} ) ;
2021-04-03 16:00:16 -04:00
Scheduler : : OnFrame ( [ ] ( )
{
if ( ! Game : : CL_IsCgameInitialized ( ) ) return ;
if ( ! Dvar : : Var ( " r_drawSceneModelCollisions " ) . get < bool > ( ) ) return ;
float green [ 4 ] = { 0.0f , 1.0f , 0.0f , 1.0f } ;
auto * scene = Game : : scene ;
for ( auto i = 0 ; i < scene - > sceneModelCount ; i + + )
{
if ( ! scene - > sceneModel [ i ] . model )
continue ;
for ( auto j = 0 ; j < scene - > sceneModel [ i ] . model - > numCollSurfs ; j + + ) {
auto b = scene - > sceneModel [ i ] . model - > collSurfs [ j ] . bounds ;
b . midPoint [ 0 ] + = scene - > sceneModel [ i ] . placement . base . origin [ 0 ] ;
b . midPoint [ 1 ] + = scene - > sceneModel [ i ] . placement . base . origin [ 1 ] ;
b . midPoint [ 2 ] + = scene - > sceneModel [ i ] . placement . base . origin [ 2 ] ;
b . halfSize [ 0 ] * = scene - > sceneModel [ i ] . placement . scale ;
b . halfSize [ 1 ] * = scene - > sceneModel [ i ] . placement . scale ;
b . halfSize [ 2 ] * = scene - > sceneModel [ i ] . placement . scale ;
Game : : R_AddDebugBounds ( green , & b , & scene - > sceneModel [ i ] . placement . base . quat ) ;
}
}
} ) ;
2021-04-03 18:56:15 -04:00
Scheduler : : OnFrame ( [ ] ( )
{
if ( ! Game : : CL_IsCgameInitialized ( ) | | ! Dvar : : Var ( " r_drawTriggers " ) . get < bool > ( ) ) return ;
float hurt [ 4 ] = { 1.0f , 0.0f , 0.0f , 1.0f } ;
float hurtTouch [ 4 ] = { 0.75f , 0.0f , 0.0f , 1.0f } ;
float damage [ 4 ] = { 0.0f , 0.0f , 1.0f , 1.0f } ;
float once [ 4 ] = { 0.0f , 1.0f , 1.0f , 1.0f } ;
float multiple [ 4 ] = { 0.0f , 1.0f , 0.0f , 1.0f } ;
auto * entities = Game : : g_entities ;
for ( auto i = 0u ; i < 0x800 ; i + + )
{
auto * ent = & entities [ i ] ;
if ( ent - > r . isInUse )
{
2021-04-04 12:04:00 -04:00
Game : : Bounds b = ent - > r . box ;
2021-04-03 18:56:15 -04:00
b . midPoint [ 0 ] + = ent - > r . currentOrigin [ 0 ] ;
b . midPoint [ 1 ] + = ent - > r . currentOrigin [ 1 ] ;
b . midPoint [ 2 ] + = ent - > r . currentOrigin [ 2 ] ;
switch ( ent - > handler )
{
case Game : : ENT_HANDLER_TRIGGER_HURT :
Game : : R_AddDebugBounds ( hurt , & b ) ;
break ;
case Game : : ENT_HANDLER_TRIGGER_HURT_TOUCH :
Game : : R_AddDebugBounds ( hurtTouch , & b ) ;
break ;
case Game : : ENT_HANDLER_TRIGGER_DAMAGE :
Game : : R_AddDebugBounds ( damage , & b ) ;
break ;
case Game : : ENT_HANDLER_TRIGGER_MULTIPLE :
if ( ent - > spawnflags & 0x40 )
Game : : R_AddDebugBounds ( once , & b ) ;
else
Game : : R_AddDebugBounds ( multiple , & b ) ;
break ;
default :
2021-04-04 12:04:00 -04:00
float rv = std : : min ( ( float ) ent - > handler , ( float ) 5 ) / 5 ;
float gv = std : : clamp ( ( float ) ent - > handler - 5 , ( float ) 0 , ( float ) 5 ) / 5 ;
float bv = std : : clamp ( ( float ) ent - > handler - 10 , ( float ) 0 , ( float ) 5 ) / 5 ;
float color [ 4 ] = { rv , gv , bv , 1.0f } ;
Game : : R_AddDebugBounds ( color , & b ) ;
2021-04-03 18:56:15 -04:00
break ;
}
}
}
} ) ;
2017-03-27 21:25:58 -04:00
2016-10-19 03:01:01 -04:00
// Dvars
2017-01-20 16:41:03 -05:00
Dvar : : Register < bool > ( " ui_streamFriendly " , false , Game : : DVAR_FLAG_SAVED , " Stream friendly UI " ) ;
2016-10-19 03:01:01 -04:00
// Debug patches
# ifdef DEBUG
// ui_debugMode 1
//Utils::Hook::Set<bool>(0x6312E0, true);
// fs_debug 1
Utils : : Hook : : Set < bool > ( 0x643172 , true ) ;
// developer 2
Utils : : Hook : : Set < BYTE > ( 0x4FA425 , 2 ) ;
Utils : : Hook : : Set < BYTE > ( 0x51B087 , 2 ) ;
Utils : : Hook : : Set < BYTE > ( 0x60AE13 , 2 ) ;
// developer_Script 1
Utils : : Hook : : Set < bool > ( 0x60AE2B , true ) ;
// Disable cheat protection for dvars
Utils : : Hook : : Set < BYTE > ( 0x647682 , 0xEB ) ;
// Constantly draw the mini console
Utils : : Hook : : Set < BYTE > ( 0x412A45 , 0xEB ) ;
2017-05-31 20:13:53 -04:00
2017-06-01 04:25:13 -04:00
Scheduler : : OnFrame ( [ ] ( )
{
2018-05-09 08:33:52 -04:00
if ( * reinterpret_cast < Game : : Font_s * * > ( 0x62E4BAC ) )
2016-10-19 03:01:01 -04:00
{
2017-06-01 04:25:13 -04:00
Game : : Con_DrawMiniConsole ( 0 , 2 , 4 , ( Game : : CL_IsCgameInitialized ( ) ? 1.0f : 0.4f ) ) ;
}
} , true ) ;
2017-01-18 10:04:24 -05:00
# else
// Remove missing tag message
Utils : : Hook : : Nop ( 0x4EBF1A , 5 ) ;
2016-10-19 03:01:01 -04:00
# endif
2017-04-13 16:04:01 -04:00
2017-06-14 06:06:04 -04:00
if ( Flags : : HasFlag ( " nointro " ) )
2017-04-13 16:04:01 -04:00
{
Utils : : Hook : : Set < BYTE > ( 0x60BECF , 0xEB ) ;
}
2016-10-19 03:01:01 -04:00
}
QuickPatch : : ~ QuickPatch ( )
{
2017-05-31 09:45:12 -04:00
2016-10-19 03:01:01 -04:00
}
2016-11-20 08:09:07 -05:00
bool QuickPatch : : unitTest ( )
2016-10-19 03:01:01 -04:00
{
uint32_t randIntCount = 4'000'000 ;
printf ( " Generating %d random integers... " , randIntCount ) ;
auto startTime = std : : chrono : : high_resolution_clock : : now ( ) ;
for ( uint32_t i = 0 ; i < randIntCount ; + + i )
{
Utils : : Cryptography : : Rand : : GenerateInt ( ) ;
}
auto duration = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : high_resolution_clock : : now ( ) - startTime ) . count ( ) ;
Logger : : Print ( " took %llims \n " , duration ) ;
printf ( " Testing ZLib compression... " ) ;
2017-01-06 09:27:35 -05:00
std : : string test = Utils : : String : : VA ( " %c " , Utils : : Cryptography : : Rand : : GenerateInt ( ) ) ;
2016-10-19 03:01:01 -04:00
for ( int i = 0 ; i < 21 ; + + i )
{
2017-07-03 10:32:10 -04:00
std : : string compressed = Utils : : Compression : : ZLib : : Compress ( test ) ;
std : : string decompressed = Utils : : Compression : : ZLib : : Decompress ( compressed ) ;
2016-10-19 03:01:01 -04:00
if ( test ! = decompressed )
{
printf ( " Error \n " ) ;
printf ( " Compressing %d bytes and decompressing failed! \n " , test . size ( ) ) ;
return false ;
}
auto size = test . size ( ) ;
for ( unsigned int j = 0 ; j < size ; + + j )
{
2017-01-06 09:27:35 -05:00
test . append ( Utils : : String : : VA ( " %c " , Utils : : Cryptography : : Rand : : GenerateInt ( ) ) ) ;
2016-10-19 03:01:01 -04:00
}
}
2017-06-13 09:35:12 -04:00
printf ( " Success \n " ) ;
printf ( " Testing trimming... " ) ;
std : : string trim1 = " 1 " ;
std : : string trim2 = " 1 " ;
std : : string trim3 = " 1 " ;
Utils : : String : : Trim ( trim1 ) ;
Utils : : String : : LTrim ( trim2 ) ;
Utils : : String : : RTrim ( trim3 ) ;
if ( trim1 ! = " 1 " ) return false ;
if ( trim2 ! = " 1 " ) return false ;
if ( trim3 ! = " 1 " ) return false ;
2016-10-19 03:01:01 -04:00
printf ( " Success \n " ) ;
return true ;
}
}