2016-10-19 03:01:01 -04:00
# include "STDInclude.hpp"
namespace Components
{
2017-02-12 14:36:38 -05:00
bool QuickPatch : : ReadyPassed = false ;
Utils : : Signal < QuickPatch : : Callback > QuickPatch : : ReadySignal ;
2017-01-06 09:27:35 -05:00
Utils : : Signal < QuickPatch : : Callback > QuickPatch : : ShutdownSignal ;
2016-10-19 03:01:01 -04:00
int64_t * QuickPatch : : GetStatsID ( )
{
static int64_t id = 0x110000100001337 ;
return & id ;
}
2017-02-12 14:36:38 -05:00
void QuickPatch : : OnReady ( Utils : : Slot < QuickPatch : : Callback > callback )
{
if ( QuickPatch : : ReadyPassed ) QuickPatch : : Once ( callback ) ;
else QuickPatch : : ReadySignal . connect ( callback ) ;
}
void QuickPatch : : ReadyHandler ( )
{
if ( ! FastFiles : : Ready ( ) ) QuickPatch : : Once ( QuickPatch : : ReadyHandler ) ;
else
{
QuickPatch : : ReadyPassed = true ;
QuickPatch : : ReadySignal ( ) ;
QuickPatch : : ReadySignal . clear ( ) ;
}
}
2017-01-06 09:27:35 -05:00
void QuickPatch : : OnShutdown ( Utils : : Slot < QuickPatch : : Callback > callback )
2016-10-19 03:01:01 -04:00
{
QuickPatch : : ShutdownSignal . connect ( callback ) ;
}
2016-11-12 08:31:56 -05:00
void QuickPatch : : ShutdownStub ( int num )
2016-10-19 03:01:01 -04:00
{
QuickPatch : : ShutdownSignal ( ) ;
2016-11-12 08:31:56 -05:00
Utils : : Hook : : Call < void ( int ) > ( 0x46B370 ) ( num ) ;
2016-10-19 03:01:01 -04:00
}
2017-01-06 09:27:35 -05:00
void QuickPatch : : OnFrame ( Utils : : Slot < QuickPatch : : Callback > callback )
2016-10-19 03:01:01 -04:00
{
if ( Dedicated : : IsEnabled ( ) | | ZoneBuilder : : IsEnabled ( ) )
{
Dedicated : : OnFrame ( callback ) ;
}
else
{
Renderer : : OnFrame ( callback ) ;
}
}
2017-01-06 09:27:35 -05:00
void QuickPatch : : Once ( Utils : : Slot < QuickPatch : : Callback > callback )
2016-10-19 03:01:01 -04:00
{
if ( Dedicated : : IsEnabled ( ) | | ZoneBuilder : : IsEnabled ( ) )
{
Dedicated : : Once ( callback ) ;
}
else
{
Renderer : : Once ( callback ) ;
}
}
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 ;
}
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 ( ) ;
}
2016-12-26 13:55:36 -05:00
void QuickPatch : : CompareMaterialStateBits ( )
{
Game : : DB_EnumXAssets ( Game : : XAssetType : : ASSET_TYPE_MATERIAL , [ ] ( Game : : XAssetHeader header , void * /*unused*/ )
{
bool first = true ;
Game : : Material * material = header . material ;
Logger : : Print ( 6 , " Checking material %s... " , material - > name ) ;
# define COMPARE_TECHNIQUES(x) if(!(material->stateBitsEntry[(Game::MaterialTechniqueType:: ## x)] == material->stateBitsEntry[(Game::MaterialTechniqueType:: ## x ## _DFOG)])) \
{ \
if ( first ) { Logger : : Print ( " \n Mismatch in material %s: \n " , material - > name ) ; first = false ; } \
Logger : : Print ( 6 , # x " != " # x " _DFOG \n " ) ; \
Logger : : Print ( " 0x02%hhx %hhb \n " , material - > stateBitsEntry [ ( Game : : MaterialTechniqueType : : # # x ) ] , material - > stateBitsEntry [ ( Game : : MaterialTechniqueType : : # # x ) ] ) ; \
Logger : : Print ( " 0x02%hhx %hhb \n " , material - > stateBitsEntry [ ( Game : : MaterialTechniqueType : : # # x # # _DFOG ) ] , material - > stateBitsEntry [ ( Game : : MaterialTechniqueType : : # # x # # _DFOG ) ] ) ; \
}
COMPARE_TECHNIQUES ( TECHNIQUE_EMISSIVE )
COMPARE_TECHNIQUES ( TECHNIQUE_EMISSIVE_SHADOW )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_SUN )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_SUN_SHADOW )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_SPOT )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_SPOT_SHADOW )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_OMNI )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_OMNI_SHADOW )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_INSTANCED )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_INSTANCED_SUN )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_INSTANCED_SUN_SHADOW )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_INSTANCED_SPOT )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_INSTANCED_SPOT_SHADOW )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_INSTANCED_OMNI )
COMPARE_TECHNIQUES ( TECHNIQUE_LIT_INSTANCED_OMNI_SHADOW )
# undef COMPARE_TECHNIQUES
if ( first )
{
Logger : : Print ( 6 , " no mismatches found \n " ) ;
}
} , nullptr , false ) ;
}
2016-10-19 03:01:01 -04:00
QuickPatch : : QuickPatch ( )
{
2017-02-12 14:36:38 -05:00
QuickPatch : : ReadyPassed = false ;
QuickPatch : : Once ( QuickPatch : : ReadyHandler ) ;
2017-01-23 16:06:50 -05:00
// Make sure preDestroy is called when the game shuts down
QuickPatch : : OnShutdown ( Loader : : PreDestroy ) ;
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
Utils : : Hook : : Set < char * > ( 0x6431D1 , BASEGAME ) ;
// UI version string
Utils : : Hook : : Set < char * > ( 0x43F73B , " IW4x: " VERSION ) ;
// console version string
Utils : : Hook : : Set < char * > ( 0x4B12BB , " IW4x " VERSION " (built " __DATE__ " " __TIME__ " ) " ) ;
// version string
Utils : : Hook : : Set < char * > ( 0x60BD56 , " IW4x ( " VERSION " ) " ) ;
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
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 ( ) )
{
Utils : : Hook : : Set < char * > ( 0x4289E8 , " IW4x ( " VERSION " ): ZoneBuilder " ) ;
}
else if ( Dedicated : : IsEnabled ( ) )
{
Utils : : Hook : : Set < char * > ( 0x4289E8 , " IW4x (r " VERSION " ): Dedicated " ) ;
}
else
{
Utils : : Hook : : Set < char * > ( 0x4289E8 , " IW4x (r " VERSION " ): Console " ) ;
}
// window title
Utils : : Hook : : Set < char * > ( 0x5076A0 , " IW4x: Multiplayer " ) ;
// sv_hostname
Utils : : Hook : : Set < char * > ( 0x4D378B , " IW4Host " ) ;
// shortversion
Utils : : Hook : : Set < char * > ( 0x60BD91 , SHORTVERSION ) ;
// console logo
Utils : : Hook : : Set < char * > ( 0x428A66 , BASEGAME " /images/logo.bmp " ) ;
// splash logo
Utils : : Hook : : Set < char * > ( 0x475F9E , BASEGAME " /images/splash.bmp " ) ;
2017-01-02 16:14:07 -05:00
Utils : : Hook : : Set < char * > ( 0x4876C6 , " Successfully read stats data \n " ) ;
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 ) ;
// Disable UPNP
Utils : : Hook : : Nop ( 0x60BE24 , 5 ) ;
// disable the IWNet IP detection (default 'got ipdetect' flag to 1)
Utils : : Hook : : Set < BYTE > ( 0x649D6F0 , 1 ) ;
// 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
2016-12-26 12:44:33 -05:00
Utils : : Hook : : Nop ( 0x4AA89F , 8 ) ;
//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 ) ;
// require Windows 5
Utils : : Hook : : Set < BYTE > ( 0x467ADF , 5 ) ;
Utils : : Hook : : Set < char > ( 0x6DF5D6 , ' 5 ' ) ;
// 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
Utils : : Hook : : Set < char * > ( 0x60BED2 , " unskippablecinematic IW_logo \n " ) ;
Utils : : Hook : : Set < char * > ( 0x51C2A4 , " %s \\ " BASEGAME " \\ video \\ %s.bik " ) ;
Utils : : Hook : : Set < DWORD > ( 0x51C2C2 , 0x78A0AC ) ;
2016-10-19 03:01:01 -04:00
// Redirect logs
Utils : : Hook : : Set < char * > ( 0x5E44D8 , " logs/games_mp.log " ) ;
Utils : : Hook : : Set < char * > ( 0x60A90C , " logs/console_mp.log " ) ;
Utils : : Hook : : Set < char * > ( 0x60A918 , " logs/console_mp.log " ) ;
// Rename config
Utils : : Hook : : Set < char * > ( 0x461B4B , CLIENT_CONFIG ) ;
Utils : : Hook : : Set < char * > ( 0x47DCBB , CLIENT_CONFIG ) ;
Utils : : Hook : : Set < char * > ( 0x6098F8 , CLIENT_CONFIG ) ;
Utils : : Hook : : Set < char * > ( 0x60B279 , CLIENT_CONFIG ) ;
Utils : : Hook : : Set < char * > ( 0x60BBD4 , CLIENT_CONFIG ) ;
2016-11-20 08:09:07 -05:00
Utils : : Hook ( 0x4D697A , QuickPatch : : ShutdownStub , HOOK_CALL ) . install ( ) - > quick ( ) ;
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 ) ;
2017-02-21 15:49:42 -05:00
// Fix mouse pitch adjustments
Dvar : : Register < bool > ( " ui_mousePitch " , false , Game : : DVAR_FLAG_SAVED , " " ) ;
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
// Rename stat file
Utils : : Hook : : SetString ( 0x71C048 , " iw4x.stat " ) ;
// Patch stats steamid
Utils : : Hook : : Nop ( 0x682EBF , 20 ) ;
Utils : : Hook : : Nop ( 0x6830B1 , 20 ) ;
2016-11-20 08:09:07 -05:00
Utils : : Hook ( 0x682EBF , QuickPatch : : GetStatsID , HOOK_CALL ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x6830B1 , QuickPatch : : GetStatsID , HOOK_CALL ) . install ( ) - > quick ( ) ;
2016-10-19 03:01:01 -04:00
//Utils::Hook::Set<BYTE>(0x68323A, 0xEB);
// 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
2016-10-19 03:01:01 -04:00
// Patch selectStringTableEntryInDvar
Utils : : Hook : : Set ( 0x405959 , QuickPatch : : SelectStringTableEntryInDvarStub ) ;
2016-12-07 14:00:24 -05:00
Command : : Add ( " unlockstats " , [ ] ( Command : : Params * )
2016-10-19 03:01:01 -04:00
{
QuickPatch : : UnlockStats ( ) ;
} ) ;
2016-12-07 14:00:24 -05: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
Command : : Add ( " checkmaterials " , [ ] ( Command : : Params * )
{
QuickPatch : : CompareMaterialStateBits ( ) ;
} ) ;
2016-12-29 21:46:06 -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 ;
AssetHandler : : OnLoad ( [ ] ( Game : : XAssetType type , Game : : XAssetHeader asset , std : : string name , bool * /*restrict*/ )
{
// 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 " ;
}
if ( Utils : : IO : : FileExists ( Utils : : String : : VA ( formatString , name ) ) ) return ;
Utils : : Stream * buffer = new Utils : : Stream ( 0x1000 ) ;
Game : : MaterialPixelShader * dest = buffer - > dest < Game : : MaterialPixelShader > ( ) ;
buffer - > save ( asset . pixelShader ) ;
if ( asset . pixelShader - > loadDef . physicalPart )
{
buffer - > save ( asset . pixelShader - > loadDef . physicalPart , 4 , asset . pixelShader - > loadDef . cachedPartSize & 0xFFFF ) ;
Utils : : Stream : : ClearPointer ( & dest - > loadDef . physicalPart ) ;
}
Utils : : IO : : WriteFile ( Utils : : String : : VA ( formatString , name ) , buffer - > toBuffer ( ) ) ;
}
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 " ) ;
Utils : : Stream * buffer = new Utils : : Stream ( 0x1000 ) ;
Game : : MaterialTechniqueSet * dest = buffer - > dest < Game : : MaterialTechniqueSet > ( ) ;
buffer - > save ( asset . techniqueSet ) ;
if ( asset . techniqueSet - > name )
{
buffer - > saveString ( asset . techniqueSet - > name ) ;
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
buffer - > align ( Utils : : Stream : : ALIGN_4 ) ;
//storePointer(technique, buffer->);
Game : : MaterialTechnique * destTechnique = buffer - > dest < Game : : MaterialTechnique > ( ) ;
buffer - > save ( technique , 8 ) ;
// Save_MaterialPassArray
Game : : MaterialPass * destPasses = buffer - > dest < Game : : MaterialPass > ( ) ;
buffer - > saveArray ( technique - > passes , technique - > numPasses ) ;
for ( short j = 0 ; j < technique - > numPasses ; + + j )
{
AssertSize ( Game : : MaterialPass , 20 ) ;
Game : : MaterialPass * destPass = & destPasses [ j ] ;
Game : : MaterialPass * pass = & technique - > passes [ j ] ;
if ( pass - > vertexDecl )
{
}
if ( pass - > argumentDef )
{
buffer - > align ( Utils : : Stream : : ALIGN_4 ) ;
buffer - > saveArray ( pass - > argumentDef , pass - > argCount1 + pass - > argCount2 + pass - > argCount3 ) ;
Utils : : Stream : : ClearPointer ( & destPass - > argumentDef ) ;
}
}
if ( technique - > name )
{
buffer - > saveString ( technique - > name ) ;
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 + + ;
}
} ) ;
2017-03-27 21:25:58 -04:00
static Game : : GfxWorld * storedWorld = nullptr ;
AssetHandler : : OnLoad ( [ ] ( Game : : XAssetType type , Game : : XAssetHeader asset , std : : string name , bool * /*restrict*/ )
{
if ( type = = Game : : XAssetType : : ASSET_TYPE_GFXWORLD )
{
Game : : GfxWorld * world = asset . gfxWorld ;
2017-03-28 02:56:51 -04:00
Utils : : Stream buffer ( 0x1000 ) ;
2017-03-27 21:25:58 -04:00
for ( unsigned int i = 0 ; i < world - > dpvs . staticSurfaceCount ; + + i )
{
2017-03-28 02:56:51 -04:00
buffer . saveString ( Utils : : String : : VA ( " %s \n " , world - > dpvs . surfaces [ world - > dpvs . sortedSurfIndex [ i ] ] . material - > name ) ) ;
2017-03-27 21:25:58 -04:00
}
2017-03-28 02:56:51 -04:00
Utils : : IO : : WriteFile ( " userraw/logs/matlog.txt " , buffer . toBuffer ( ) ) ;
2017-03-27 21:25:58 -04:00
storedWorld = asset . gfxWorld ;
}
} ) ;
Dvar : : OnInit ( [ ] ( )
{
Dvar : : Register < bool > ( " r_drawAabbTrees " , false , Game : : DVAR_FLAG_USERCREATED , " draw aabb trees " ) ;
} ) ;
Renderer : : OnFrame ( [ ] ( )
{
if ( ! Game : : CL_IsCgameInitialized ( ) | | ! Dvar : : Var ( " r_drawAabbTrees " ) . get < bool > ( ) ) return ;
float cyan [ 4 ] = { 0.0f , 0.5f , 0.5f , 1.0f } ;
2017-03-28 03:01:56 -04:00
Game : : GfxWorld * & gameWorld = * reinterpret_cast < Game : : GfxWorld * * > ( 0x66DEE94 ) ;
if ( ! gameWorld ) return ;
2017-03-27 21:25:58 -04:00
2017-03-28 03:01:56 -04:00
for ( int i = 0 ; i < gameWorld - > dpvsPlanes . cellCount ; + + i )
2017-03-27 21:25:58 -04:00
{
2017-03-28 03:01:56 -04:00
for ( int j = 0 ; j < gameWorld - > aabbTreeCounts [ i ] . aabbTreeCount ; + + j )
2017-03-27 21:25:58 -04:00
{
Game : : vec3_t v1 , v2 , v3 , v4 , v5 , v6 , v7 , v8 ;
2017-03-28 03:01:56 -04:00
float * center = gameWorld - > aabbTrees [ i ] . aabbTree [ j ] . bounds . midPoint ;
float * halfSize = gameWorld - > aabbTrees [ i ] . aabbTree [ j ] . bounds . halfSize ;
2017-03-27 21:25:58 -04:00
v1 [ 0 ] = center [ 0 ] - halfSize [ 0 ] ;
v1 [ 1 ] = center [ 1 ] - halfSize [ 1 ] ;
v1 [ 2 ] = center [ 2 ] - halfSize [ 2 ] ;
v2 [ 0 ] = center [ 0 ] + halfSize [ 0 ] ;
v2 [ 1 ] = center [ 1 ] - halfSize [ 1 ] ;
v2 [ 2 ] = center [ 2 ] - halfSize [ 2 ] ;
v3 [ 0 ] = center [ 0 ] - halfSize [ 0 ] ;
v3 [ 1 ] = center [ 1 ] + halfSize [ 1 ] ;
v3 [ 2 ] = center [ 2 ] - halfSize [ 2 ] ;
v4 [ 0 ] = center [ 0 ] + halfSize [ 0 ] ;
v4 [ 1 ] = center [ 1 ] + halfSize [ 1 ] ;
v4 [ 2 ] = center [ 2 ] - halfSize [ 2 ] ;
v5 [ 0 ] = center [ 0 ] - halfSize [ 0 ] ;
v5 [ 1 ] = center [ 1 ] - halfSize [ 1 ] ;
v5 [ 2 ] = center [ 2 ] + halfSize [ 2 ] ;
v6 [ 0 ] = center [ 0 ] + halfSize [ 0 ] ;
v6 [ 1 ] = center [ 1 ] - halfSize [ 1 ] ;
v6 [ 2 ] = center [ 2 ] + halfSize [ 2 ] ;
v7 [ 0 ] = center [ 0 ] - halfSize [ 0 ] ;
v7 [ 1 ] = center [ 1 ] + halfSize [ 1 ] ;
v7 [ 2 ] = center [ 2 ] + halfSize [ 2 ] ;
v8 [ 0 ] = center [ 0 ] + halfSize [ 0 ] ;
v8 [ 1 ] = center [ 1 ] + halfSize [ 1 ] ;
v8 [ 2 ] = center [ 2 ] + halfSize [ 2 ] ;
// bottom
Game : : R_AddDebugLine ( cyan , v1 , v2 ) ;
Game : : R_AddDebugLine ( cyan , v2 , v4 ) ;
Game : : R_AddDebugLine ( cyan , v4 , v3 ) ;
Game : : R_AddDebugLine ( cyan , v3 , v1 ) ;
// top
Game : : R_AddDebugLine ( cyan , v5 , v6 ) ;
Game : : R_AddDebugLine ( cyan , v6 , v8 ) ;
Game : : R_AddDebugLine ( cyan , v8 , v7 ) ;
Game : : R_AddDebugLine ( cyan , v7 , v5 ) ;
// verticals
Game : : R_AddDebugLine ( cyan , v1 , v5 ) ;
Game : : R_AddDebugLine ( cyan , v2 , v6 ) ;
Game : : R_AddDebugLine ( cyan , v3 , v7 ) ;
Game : : R_AddDebugLine ( cyan , v4 , v8 ) ;
}
}
} ) ;
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 ) ;
Renderer : : OnFrame ( [ ] ( )
{
if ( * reinterpret_cast < Game : : Font * * > ( 0x62E4BAC ) )
{
Game : : Con_DrawMiniConsole ( 0 , 2 , 4 , ( Game : : CL_IsCgameInitialized ( ) ? 1.0f : 0.4f ) ) ;
}
} ) ;
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
}
QuickPatch : : ~ QuickPatch ( )
{
2017-02-12 14:36:38 -05:00
QuickPatch : : ReadySignal . clear ( ) ;
2016-10-19 03:01:01 -04:00
QuickPatch : : ShutdownSignal . clear ( ) ;
}
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 )
{
std : : string compressed = Utils : : Compression : : ZLib : : Compress ( test ) ;
std : : string decompressed = Utils : : Compression : : ZLib : : Decompress ( compressed ) ;
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
}
}
printf ( " Success \n " ) ;
return true ;
}
}