mirror of
https://github.com/CookiePLMonster/SilentPatch.git
synced 2024-12-28 06:43:01 +05:00
Migrate to transactional patterns
This commit is contained in:
parent
6ee676400b
commit
d4374df50a
9 changed files with 706 additions and 439 deletions
|
@ -75,7 +75,6 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
|
@ -107,7 +106,6 @@ copy /y "$(TargetPath)" "D:\Steam\steamapps\common\Grand Theft Auto Vice City\dd
|
|||
<AdditionalIncludeDirectories>..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
|
@ -141,7 +139,6 @@ copy /y "$(TargetPath)" "D:\Steam\steamapps\common\Grand Theft Auto Vice City\dd
|
|||
<AdditionalIncludeDirectories>..\SilentPatch;..\DDraw;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
|
|
|
@ -208,30 +208,38 @@ namespace Common {
|
|||
void III_VC_Common()
|
||||
{
|
||||
using namespace Memory;
|
||||
using namespace hook;
|
||||
using namespace hook::txn;
|
||||
|
||||
// Delayed patching
|
||||
try
|
||||
{
|
||||
using namespace DelayedPatches;
|
||||
|
||||
auto addr_mssHook = get_pattern( "6A 00 6A 02 6A 10 68 00 7D 00 00", -6 + 2 );
|
||||
auto addr_ualHook = get_pattern( "FF 15 ? ? ? ? 6A 00 6A 18", 0xA );
|
||||
|
||||
OldSetPreference = *static_cast<decltype(OldSetPreference)*>(addr_mssHook);
|
||||
Patch( addr_mssHook, &pInjectMSS );
|
||||
|
||||
auto addr_ualHook = get_pattern( "FF 15 ? ? ? ? 6A 00 6A 18", 0xA );
|
||||
ReadCall( addr_ualHook, RsEventHandler );
|
||||
InjectHook( addr_ualHook, Inject_UAL );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed bomb ownership/bombs saving for bikes
|
||||
try
|
||||
{
|
||||
auto addr = get_pattern( "83 3C 33 00 74 19 89 F9 E8", 8 );
|
||||
|
||||
ReadCall( addr, CStoredCar::orgRestoreCar );
|
||||
InjectHook( addr, &CStoredCar::RestoreCar_SilentPatch );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed handling.cfg name matching (names don't need unique prefixes anymore)
|
||||
try
|
||||
{
|
||||
using namespace HandlingNameLoadFix;
|
||||
|
||||
|
@ -240,9 +248,11 @@ namespace Common {
|
|||
InjectHook( findExactWord.get<void>( -5 ), strncpy_Fix );
|
||||
InjectHook( findExactWord.get<void>( 0xD ), strncmp_Fix );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed corona lines rendering on non-nvidia cards
|
||||
try
|
||||
{
|
||||
using namespace CoronaLinesFix;
|
||||
|
||||
|
@ -250,9 +260,11 @@ namespace Common {
|
|||
|
||||
InterceptCall(renderLine, orgRwIm2DRenderLine, RenderLine_SetRecipZ);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed static shadows not rendering under fire and pickups
|
||||
try
|
||||
{
|
||||
using namespace StaticShadowAlphaFix;
|
||||
|
||||
|
@ -281,9 +293,11 @@ namespace Common {
|
|||
HookEach_StoreAlphaTest(disableAlphaTestAndSetState, InterceptCall);
|
||||
HookEach_RestoreAlphaTest(setStateAndReenableAlphaTest, InterceptCall);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Reset requested extras if created vehicle has no extras
|
||||
try
|
||||
{
|
||||
using namespace CompsToUseFix;
|
||||
|
||||
|
@ -291,10 +305,12 @@ namespace Common {
|
|||
InjectHook( resetComps.get<void>( -14 ), ResetCompsForNoExtras, HookType::Call );
|
||||
Nop( resetComps.get<void>( -9 ), 9 );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Rescale light switching randomness in CAutomobile::PreRender/CBike::PreRender for PC the randomness range
|
||||
// The original randomness was 50000 out of 65535, which is impossible to hit with PC's 32767 range
|
||||
try
|
||||
{
|
||||
// GTA III expects 2 matches, VC expects 4 due to the addition of CBike::PreRender
|
||||
#if _GTA_III
|
||||
|
@ -310,9 +326,11 @@ namespace Common {
|
|||
Patch<const void*>(match.get<void>(2), &LightStatusRandomnessThreshold);
|
||||
});
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Make script randomness 16-bit, like on PS2
|
||||
try
|
||||
{
|
||||
using namespace Rand16bit;
|
||||
|
||||
|
@ -323,6 +341,7 @@ namespace Common {
|
|||
|
||||
HookEach_Rand(rands, InterceptCall);
|
||||
}
|
||||
TXN_CATCH();
|
||||
}
|
||||
|
||||
void III_VC_SetDelayedPatchesFunc( void(*func)() )
|
||||
|
@ -333,24 +352,21 @@ namespace Common {
|
|||
void III_VC_DelayedCommon( bool /*hasDebugMenu*/, const wchar_t* wcModulePath )
|
||||
{
|
||||
using namespace Memory;
|
||||
using namespace hook;
|
||||
using namespace hook::txn;
|
||||
|
||||
ExtraCompSpecularity::ReadExtraCompSpecularityExceptions(wcModulePath);
|
||||
|
||||
// Corrected taxi light placement for Taxi
|
||||
if ( GetPrivateProfileIntW(L"SilentPatch", L"EnableVehicleCoronaFixes", -1, wcModulePath) == 1 )
|
||||
if ( GetPrivateProfileIntW(L"SilentPatch", L"EnableVehicleCoronaFixes", -1, wcModulePath) == 1 ) try
|
||||
{
|
||||
using namespace TaxiCoronaFix;
|
||||
|
||||
auto getTaxiLightPos = pattern( "E8 ? ? ? ? D9 84 24 ? ? ? ? D8 84 24 ? ? ? ? 83 C4 0C FF 35" );
|
||||
auto getTaxiLightPos = pattern( "E8 ? ? ? ? D9 84 24 ? ? ? ? D8 84 24 ? ? ? ? 83 C4 0C FF 35" ).get_one();
|
||||
|
||||
if ( getTaxiLightPos.count_hint(1).size() == 1 )
|
||||
{
|
||||
auto match = getTaxiLightPos.get_one();
|
||||
Patch<uint8_t>( match.get<void>( -15 ), 0x55 ); // push eax -> push ebp
|
||||
InjectHook( match.get<void>(), GetTransformedCoronaPos );
|
||||
}
|
||||
Patch<uint8_t>( getTaxiLightPos.get<void>( -15 ), 0x55 ); // push eax -> push ebp
|
||||
InjectHook( getTaxiLightPos.get<void>(), GetTransformedCoronaPos );
|
||||
}
|
||||
TXN_CATCH();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,25 +39,37 @@ namespace Common {
|
|||
|
||||
namespace Patches {
|
||||
|
||||
bool FixRwcseg_Patterns()
|
||||
bool FixRwcseg_Patterns() try
|
||||
{
|
||||
using namespace hook;
|
||||
using namespace hook::txn;
|
||||
|
||||
auto begin = pattern( "55 8B EC 50 53 51 52 8B 5D 14 8B 4D 10 8B 45 0C 8B 55 08" );
|
||||
auto end = pattern( "9B D9 3D ? ? ? ? 81 25 ? ? ? ? FF FC FF FF 83 0D ? ? ? ? 3F" );
|
||||
// _rwcseg can be placed far after the code section, and the default pattern heuristics currently break with it
|
||||
// (it's only using SizeOfCode instead of scanning all code sections).
|
||||
// To fix this, explicitly scan the entire module
|
||||
const uintptr_t module = reinterpret_cast<uintptr_t>(GetModuleHandle(nullptr));
|
||||
PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(module);
|
||||
PIMAGE_NT_HEADERS ntHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(module + dosHeader->e_lfanew);
|
||||
|
||||
if ( begin.count_hint(1).size() == 1 && end.count_hint(1).size() == 1 )
|
||||
const uintptr_t sizeOfHeaders = ntHeader->OptionalHeader.SizeOfHeaders;
|
||||
const uintptr_t moduleBegin = module + sizeOfHeaders;
|
||||
const uintptr_t moduleEnd = module + (ntHeader->OptionalHeader.SizeOfImage - sizeOfHeaders);
|
||||
|
||||
auto begin = make_range_pattern(moduleBegin, moduleEnd, "55 8B EC 50 53 51 52 8B 5D 14 8B 4D 10 8B 45 0C 8B 55 08").get_first<void>();
|
||||
auto end = make_range_pattern(moduleBegin, moduleEnd, "9B D9 3D ? ? ? ? 81 25 ? ? ? ? FF FC FF FF 83 0D ? ? ? ? 3F").get_first<void>(31);
|
||||
|
||||
const ptrdiff_t size = reinterpret_cast<uintptr_t>(end) - reinterpret_cast<uintptr_t>(begin);
|
||||
if ( size > 0 )
|
||||
{
|
||||
const ptrdiff_t size = (intptr_t)end.get_first( 24 ) - (intptr_t)begin.get_first();
|
||||
if ( size > 0 )
|
||||
{
|
||||
DWORD dwProtect;
|
||||
VirtualProtect( begin.get_first(), size, PAGE_EXECUTE_READ, &dwProtect );
|
||||
return true;
|
||||
}
|
||||
DWORD dwProtect;
|
||||
VirtualProtect( begin, size, PAGE_EXECUTE_READ, &dwProtect );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (const hook::txn_exception&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// ================= III =================
|
||||
void DDraw_III_10( uint32_t width, uint32_t height, const char* desktopText )
|
||||
|
@ -207,38 +219,34 @@ namespace Common {
|
|||
void DDraw_Common()
|
||||
{
|
||||
using namespace Memory;
|
||||
using namespace hook;
|
||||
using namespace hook::txn;
|
||||
|
||||
// Remove FILE_FLAG_NO_BUFFERING from CdStreams
|
||||
try
|
||||
{
|
||||
auto mem = pattern( "81 7C 24 04 00 08 00 00" ).count_hint(1);
|
||||
if ( mem.size() == 1 )
|
||||
{
|
||||
Patch<uint8_t>( mem.get_first( 0x12 ), 0xEB );
|
||||
}
|
||||
auto mem = get_pattern("81 7C 24 04 00 08 00 00", 0x12);
|
||||
Patch<uint8_t>( mem, 0xEB );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// No censorships
|
||||
try
|
||||
{
|
||||
auto addr = pattern( "83 FB 07 74 0A 83 FD 07 74 05 83 FE 07 75 15" ).count_hint(1);
|
||||
if ( addr.size() == 1 )
|
||||
{
|
||||
Patch( addr.get_first(), { 0xEB, 0x5E } );
|
||||
}
|
||||
|
||||
auto addr = get_pattern( "83 FB 07 74 0A 83 FD 07 74 05 83 FE 07 75 15" );
|
||||
Patch( addr, { 0xEB, 0x5E } );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
// unnamed CdStream semaphore
|
||||
try
|
||||
{
|
||||
auto mem = pattern( "8D 04 85 00 00 00 00 50 6A 40 FF 15" ).count_hint(1);
|
||||
if ( mem.size() == 1 )
|
||||
{
|
||||
Patch( mem.get_first( 0x25 ), { 0x6A, 0x00 } ); // push 0 \ nop
|
||||
Nop( mem.get_first( 0x25 + 2 ), 3 );
|
||||
}
|
||||
|
||||
auto mem = pattern( "8D 04 85 00 00 00 00 50 6A 40 FF 15" ).get_one();
|
||||
|
||||
Patch( mem.get<void>( 0x25 ), { 0x6A, 0x00 } ); // push 0 \ nop
|
||||
Nop( mem.get<void>( 0x25 + 2 ), 3 );
|
||||
}
|
||||
TXN_CATCH();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -842,7 +842,7 @@ namespace SitInBoat
|
|||
void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
|
||||
{
|
||||
using namespace Memory;
|
||||
using namespace hook;
|
||||
using namespace hook::txn;
|
||||
|
||||
const ModuleList moduleList;
|
||||
|
||||
|
@ -876,135 +876,124 @@ void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModul
|
|||
}
|
||||
|
||||
// Make crane be unable to lift Coach instead of Blista
|
||||
try
|
||||
{
|
||||
// There is a possible incompatibility with limit adjusters, so patch it in a delayed hook point and gracefully handle failure
|
||||
auto canPickBlista = pattern( "83 FA 66 74" ).count_hint(1);
|
||||
if ( canPickBlista.size() == 1 )
|
||||
{
|
||||
Patch<int8_t>( canPickBlista.get_first<void>( 2 ), 127 ); // coach
|
||||
}
|
||||
auto canPickBlista = get_pattern("83 FA 66 74", 2);
|
||||
Patch<int8_t>( canPickBlista, 127 ); // coach
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Corrected siren corona placement for emergency vehicles
|
||||
if ( GetPrivateProfileIntW(L"SilentPatch", L"EnableVehicleCoronaFixes", -1, wcModulePath) == 1 )
|
||||
{
|
||||
// Other mods might be touching it, so only patch specific vehicles if their code has not been touched at all
|
||||
try
|
||||
{
|
||||
auto firetruckX1 = pattern( "C7 84 24 9C 05 00 00 CD CC 8C 3F" );
|
||||
auto firetruckY1 = pattern( "C7 84 24 A4 05 00 00 9A 99 D9 3F" );
|
||||
auto firetruckZ1 = pattern( "C7 84 24 A8 05 00 00 00 00 00 40" );
|
||||
auto firetruckX1 = get_pattern("C7 84 24 9C 05 00 00 CD CC 8C 3F", 7);
|
||||
auto firetruckY1 = get_pattern("C7 84 24 A4 05 00 00 9A 99 D9 3F", 7);
|
||||
auto firetruckZ1 = get_pattern("C7 84 24 A8 05 00 00 00 00 00 40", 7);
|
||||
|
||||
auto firetruckX2 = pattern( "C7 84 24 A8 05 00 00 CD CC 8C BF" );
|
||||
auto firetruckY2 = pattern( "C7 84 24 B0 05 00 00 9A 99 D9 3F" );
|
||||
auto firetruckZ2 = pattern( "C7 84 24 B4 05 00 00 00 00 00 40" );
|
||||
auto firetruckX2 = get_pattern("C7 84 24 A8 05 00 00 CD CC 8C BF", 7);
|
||||
auto firetruckY2 = get_pattern("C7 84 24 B0 05 00 00 9A 99 D9 3F", 7);
|
||||
auto firetruckZ2 = get_pattern("C7 84 24 B4 05 00 00 00 00 00 40", 7);
|
||||
|
||||
if ( firetruckX1.count_hint(1).size() == 1 && firetruckY1.count_hint(1).size() == 1 && firetruckZ1.count_hint(1).size() == 1 &&
|
||||
firetruckX2.count_hint(1).size() == 1 && firetruckY2.count_hint(1).size() == 1 && firetruckZ2.count_hint(1).size() == 1 )
|
||||
{
|
||||
constexpr CVector FIRETRUCK_SIREN_POS(0.95f, 3.2f, 1.4f);
|
||||
constexpr CVector FIRETRUCK_SIREN_POS(0.95f, 3.2f, 1.4f);
|
||||
|
||||
Patch<float>( firetruckX1.get_first( 7 ), FIRETRUCK_SIREN_POS.x );
|
||||
Patch<float>( firetruckY1.get_first( 7 ), FIRETRUCK_SIREN_POS.y );
|
||||
Patch<float>( firetruckZ1.get_first( 7 ), FIRETRUCK_SIREN_POS.z );
|
||||
Patch<float>( firetruckX1, FIRETRUCK_SIREN_POS.x );
|
||||
Patch<float>( firetruckY1, FIRETRUCK_SIREN_POS.y );
|
||||
Patch<float>( firetruckZ1, FIRETRUCK_SIREN_POS.z );
|
||||
|
||||
Patch<float>( firetruckX2.get_first( 7 ), -FIRETRUCK_SIREN_POS.x );
|
||||
Patch<float>( firetruckY2.get_first( 7 ), FIRETRUCK_SIREN_POS.y );
|
||||
Patch<float>( firetruckZ2.get_first( 7 ), FIRETRUCK_SIREN_POS.z );
|
||||
}
|
||||
Patch<float>( firetruckX2, -FIRETRUCK_SIREN_POS.x );
|
||||
Patch<float>( firetruckY2, FIRETRUCK_SIREN_POS.y );
|
||||
Patch<float>( firetruckZ2, FIRETRUCK_SIREN_POS.z );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
try
|
||||
{
|
||||
auto ambulanceX1 = pattern( "C7 84 24 84 05 00 00 CD CC 8C 3F" );
|
||||
auto ambulanceY1 = pattern( "C7 84 24 8C 05 00 00 66 66 66 3F" );
|
||||
auto ambulanceZ1 = pattern( "C7 84 24 90 05 00 00 CD CC CC 3F" );
|
||||
auto ambulanceX1 = get_pattern("C7 84 24 84 05 00 00 CD CC 8C 3F", 7);
|
||||
auto ambulanceY1 = get_pattern("C7 84 24 8C 05 00 00 66 66 66 3F", 7);
|
||||
auto ambulanceZ1 = get_pattern("C7 84 24 90 05 00 00 CD CC CC 3F", 7);
|
||||
|
||||
auto ambulanceX2 = pattern( "C7 84 24 90 05 00 00 CD CC 8C BF" );
|
||||
auto ambulanceY2 = pattern( "C7 84 24 98 05 00 00 66 66 66 3F" );
|
||||
auto ambulanceZ2 = pattern( "C7 84 24 9C 05 00 00 CD CC CC 3F" );
|
||||
auto ambulanceX2 = get_pattern("C7 84 24 90 05 00 00 CD CC 8C BF", 7);
|
||||
auto ambulanceY2 = get_pattern("C7 84 24 98 05 00 00 66 66 66 3F", 7);
|
||||
auto ambulanceZ2 = get_pattern("C7 84 24 9C 05 00 00 CD CC CC 3F", 7);
|
||||
|
||||
if ( ambulanceX1.count_hint(1).size() == 1 && ambulanceY1.count_hint(1).size() == 1 && ambulanceZ1.count_hint(1).size() == 1 &&
|
||||
ambulanceX2.count_hint(1).size() == 1 && ambulanceY2.count_hint(1).size() == 1 && ambulanceZ2.count_hint(1).size() == 1 )
|
||||
{
|
||||
constexpr CVector AMBULANCE_SIREN_POS(0.7f, 0.65f, 1.55f);
|
||||
constexpr CVector AMBULANCE_SIREN_POS(0.7f, 0.65f, 1.55f);
|
||||
|
||||
Patch<float>( ambulanceX1.get_first( 7 ), AMBULANCE_SIREN_POS.x );
|
||||
Patch<float>( ambulanceY1.get_first( 7 ), AMBULANCE_SIREN_POS.y );
|
||||
Patch<float>( ambulanceZ1.get_first( 7 ), AMBULANCE_SIREN_POS.z );
|
||||
Patch<float>( ambulanceX1, AMBULANCE_SIREN_POS.x );
|
||||
Patch<float>( ambulanceY1, AMBULANCE_SIREN_POS.y );
|
||||
Patch<float>( ambulanceZ1, AMBULANCE_SIREN_POS.z );
|
||||
|
||||
Patch<float>( ambulanceX2.get_first( 7 ), -AMBULANCE_SIREN_POS.x );
|
||||
Patch<float>( ambulanceY2.get_first( 7 ), AMBULANCE_SIREN_POS.y );
|
||||
Patch<float>( ambulanceZ2.get_first( 7 ), AMBULANCE_SIREN_POS.z );
|
||||
}
|
||||
Patch<float>( ambulanceX2, -AMBULANCE_SIREN_POS.x );
|
||||
Patch<float>( ambulanceY2, AMBULANCE_SIREN_POS.y );
|
||||
Patch<float>( ambulanceZ2, AMBULANCE_SIREN_POS.z );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
try
|
||||
{
|
||||
auto enforcerX1 = pattern( "C7 84 24 6C 05 00 00 CD CC 8C 3F" );
|
||||
auto enforcerY1 = pattern( "C7 84 24 74 05 00 00 CD CC 4C 3F" );
|
||||
auto enforcerZ1 = pattern( "C7 84 24 78 05 00 00 9A 99 99 3F" );
|
||||
auto enforcerX1 = get_pattern("C7 84 24 6C 05 00 00 CD CC 8C 3F", 7);
|
||||
auto enforcerY1 = get_pattern("C7 84 24 74 05 00 00 CD CC 4C 3F", 7);
|
||||
auto enforcerZ1 = get_pattern("C7 84 24 78 05 00 00 9A 99 99 3F", 7);
|
||||
|
||||
auto enforcerX2 = pattern( "C7 84 24 78 05 00 00 CD CC 8C BF" );
|
||||
auto enforcerY2 = pattern( "C7 84 24 80 05 00 00 CD CC 4C 3F" );
|
||||
auto enforcerZ2 = pattern( "C7 84 24 84 05 00 00 9A 99 99 3F" );
|
||||
auto enforcerX2 = get_pattern("C7 84 24 78 05 00 00 CD CC 8C BF", 7);
|
||||
auto enforcerY2 = get_pattern("C7 84 24 80 05 00 00 CD CC 4C 3F", 7);
|
||||
auto enforcerZ2 = get_pattern("C7 84 24 84 05 00 00 9A 99 99 3F", 7);
|
||||
|
||||
if ( enforcerX1.count_hint(1).size() == 1 && enforcerY1.count_hint(1).size() == 1 && enforcerZ1.count_hint(1).size() == 1 &&
|
||||
enforcerX2.count_hint(1).size() == 1 && enforcerY2.count_hint(1).size() == 1 && enforcerZ2.count_hint(1).size() == 1 )
|
||||
{
|
||||
constexpr CVector ENFORCER_SIREN_POS(0.6f, 1.05f, 1.4f);
|
||||
constexpr CVector ENFORCER_SIREN_POS(0.6f, 1.05f, 1.4f);
|
||||
|
||||
Patch<float>( enforcerX1.get_first( 7 ), ENFORCER_SIREN_POS.x );
|
||||
Patch<float>( enforcerY1.get_first( 7 ), ENFORCER_SIREN_POS.y );
|
||||
Patch<float>( enforcerZ1.get_first( 7 ), ENFORCER_SIREN_POS.z );
|
||||
Patch<float>( enforcerX1, ENFORCER_SIREN_POS.x );
|
||||
Patch<float>( enforcerY1, ENFORCER_SIREN_POS.y );
|
||||
Patch<float>( enforcerZ1, ENFORCER_SIREN_POS.z );
|
||||
|
||||
Patch<float>( enforcerX2.get_first( 7 ), -ENFORCER_SIREN_POS.x );
|
||||
Patch<float>( enforcerY2.get_first( 7 ), ENFORCER_SIREN_POS.y );
|
||||
Patch<float>( enforcerZ2.get_first( 7 ), ENFORCER_SIREN_POS.z );
|
||||
}
|
||||
Patch<float>( enforcerX2, -ENFORCER_SIREN_POS.x );
|
||||
Patch<float>( enforcerY2, ENFORCER_SIREN_POS.y );
|
||||
Patch<float>( enforcerZ2, ENFORCER_SIREN_POS.z );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
try
|
||||
{
|
||||
auto chopper1 = pattern( "C7 44 24 44 00 00 E0 40 50 C7 44 24 4C 00 00 00 00" ); // Front light
|
||||
auto chopper1 = pattern("C7 44 24 44 00 00 E0 40 50 C7 44 24 4C 00 00 00 00").get_one(); // Front light
|
||||
|
||||
if ( chopper1.count_hint(1).size() == 1 )
|
||||
{
|
||||
constexpr CVector CHOPPER_SEARCH_LIGHT_POS(0.0f, 3.0f, -1.25f);
|
||||
constexpr CVector CHOPPER_SEARCH_LIGHT_POS(0.0f, 3.0f, -1.25f);
|
||||
|
||||
auto match = chopper1.get_one();
|
||||
|
||||
Patch( match.get<float>( 4 ), CHOPPER_SEARCH_LIGHT_POS.y );
|
||||
Patch( match.get<float>( 9 + 4 ), CHOPPER_SEARCH_LIGHT_POS.z );
|
||||
}
|
||||
Patch( chopper1.get<float>( 4 ), CHOPPER_SEARCH_LIGHT_POS.y );
|
||||
Patch( chopper1.get<float>( 9 + 4 ), CHOPPER_SEARCH_LIGHT_POS.z );
|
||||
}
|
||||
TXN_CATCH();
|
||||
}
|
||||
|
||||
|
||||
// Corrected FBI Car secondary siren sound
|
||||
try
|
||||
{
|
||||
using namespace SirenSwitchingFix;
|
||||
|
||||
// Other mods might be touching it, so only patch specific vehicles if their code has not been touched at all
|
||||
auto usesSirenSwitching = pattern( "E8 ? ? ? ? 84 C0 74 12 83 C4 08" ).count_hint(1);
|
||||
if ( usesSirenSwitching.size() == 1 )
|
||||
{
|
||||
auto match = usesSirenSwitching.get_one();
|
||||
ReadCall( match.get<void>(), orgUsesSirenSwitching );
|
||||
InjectHook( match.get<void>(), UsesSirenSwitching_FbiCar );
|
||||
}
|
||||
auto usesSirenSwitching = pattern("E8 ? ? ? ? 84 C0 74 12 83 C4 08").get_one();
|
||||
|
||||
InterceptCall(usesSirenSwitching.get<void>(), orgUsesSirenSwitching, UsesSirenSwitching_FbiCar);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Corrected CSimpleModelInfo::SetupBigBuilding minimum draw distance for big buildings without a matching model
|
||||
// Fixes cranes in Portland and bright windows in the city
|
||||
// By aap
|
||||
try
|
||||
{
|
||||
auto setupMinDist = pattern( "C7 43 44 00 00 C8 42" ).count_hint(1);
|
||||
if ( setupMinDist.size() == 1 ) // In case of another mod or second instance of SP changing it
|
||||
{
|
||||
auto match = setupMinDist.get_one();
|
||||
auto setupMinDist = pattern("C7 43 44 00 00 C8 42").get_one();
|
||||
|
||||
// mov ecx, ebx
|
||||
// call CSimpleModelInfo::SetNearDistanceForLOD
|
||||
Patch( match.get<void>(), { 0x89, 0xD9 } );
|
||||
InjectHook( match.get<void>( 2 ), &CSimpleModelInfo::SetNearDistanceForLOD_SilentPatch, HookType::Call );
|
||||
}
|
||||
// mov ecx, ebx
|
||||
// call CSimpleModelInfo::SetNearDistanceForLOD
|
||||
Patch( setupMinDist.get<void>(), { 0x89, 0xD9 } );
|
||||
InjectHook( setupMinDist.get<void>( 2 ), &CSimpleModelInfo::SetNearDistanceForLOD_SilentPatch, HookType::Call );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
FLAUtils::Init(moduleList);
|
||||
}
|
||||
|
@ -1346,10 +1335,11 @@ void Patch_III_Steam(uint32_t width, uint32_t height)
|
|||
void Patch_III_Common()
|
||||
{
|
||||
using namespace Memory;
|
||||
using namespace hook;
|
||||
using namespace hook::txn;
|
||||
|
||||
|
||||
// New timers fix
|
||||
try
|
||||
{
|
||||
auto hookPoint = pattern( "83 E4 F8 89 44 24 08 C7 44 24 0C 00 00 00 00 DF 6C 24 08" ).get_one();
|
||||
auto jmpPoint = get_pattern( "DD D8 E9 37 FF FF FF DD D8" );
|
||||
|
@ -1357,8 +1347,11 @@ void Patch_III_Common()
|
|||
InjectHook( hookPoint.get<void>( 0x21 ), CTimer::Update_SilentPatch, HookType::Call );
|
||||
InjectHook( hookPoint.get<void>( 0x21 + 5 ), jmpPoint, HookType::Jump );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Alt+F4
|
||||
try
|
||||
{
|
||||
auto addr = pattern( "59 59 31 C0 83 C4 48 5D 5F 5E 5B C2 10 00" ).count(2);
|
||||
auto dest = get_pattern( "53 55 56 FF 74 24 68 FF 15" );
|
||||
|
@ -1367,8 +1360,11 @@ void Patch_III_Common()
|
|||
InjectHook( match.get<void>( 2 ), dest, HookType::Jump );
|
||||
});
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Proper panels damage
|
||||
try
|
||||
{
|
||||
auto addr = pattern( "C6 43 09 03 C6 43 0A 03 C6 43 0B 03" ).get_one();
|
||||
|
||||
|
@ -1376,8 +1372,11 @@ void Patch_III_Common()
|
|||
Patch<uint8_t>( addr.get<void>( 0x23 + 1 ), 6 );
|
||||
Nop( addr.get<void>( 0x3F ), 7 );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Proper metric-imperial conversion constants
|
||||
try
|
||||
{
|
||||
static const float METERS_TO_MILES = 0.0006213711922f;
|
||||
static const float METERS_TO_FEET = 3.280839895f;
|
||||
|
@ -1389,8 +1388,11 @@ void Patch_III_Common()
|
|||
Patch<const void*>( addr.get(2).get<void>( 2 ), &METERS_TO_FEET );
|
||||
Patch<const void*>( addr.get(3).get<void>( 2 ), &METERS_TO_FEET );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Improved pathfinding in PickNextNodeAccordingStrategy - PickNextNodeToChaseCar with XYZ coords
|
||||
try
|
||||
{
|
||||
auto addr = pattern( "E8 ? ? ? ? 50 8D 44 24 10 50 E8" ).get_one();
|
||||
ReadCall( addr.get<void>( 0x25 ), orgPickNextNodeToChaseCar );
|
||||
|
@ -1421,25 +1423,31 @@ void Patch_III_Common()
|
|||
// Uncomment this to get rid of "treadable hack" in CCarCtrl::PickNextNodeToChaseCar (to mirror VC behaviour)
|
||||
InjectHook( funcAddr + 0x2A, funcAddr + 0x182, HookType::Jump );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// No censorships
|
||||
try
|
||||
{
|
||||
auto addr = get_pattern( "8B 15 ? ? ? ? C6 05 ? ? ? ? 00 89 D0" );
|
||||
Patch( addr, { 0x83, 0xC4, 0x08, 0xC3 } ); // add esp, 8 \ retn
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// 014C cargen counter fix (by spaceeinstein)
|
||||
try
|
||||
{
|
||||
auto do_processing = pattern( "0F B7 45 28 83 F8 FF 7D 04 66 FF 4D 28" ).get_one();
|
||||
|
||||
Patch<uint8_t>( do_processing.get<uint8_t*>(1), 0xBF ); // movzx eax, word ptr [ebx+28h] -> movsx eax, word ptr [ebx+28h]
|
||||
Patch<uint8_t>( do_processing.get<uint8_t*>(7), 0x74 ); // jge -> jz
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed ammo from SCM
|
||||
try
|
||||
{
|
||||
using namespace ZeroAmmoFix;
|
||||
|
||||
|
@ -1449,9 +1457,11 @@ void Patch_III_Common()
|
|||
};
|
||||
HookEach_GiveWeapon(give_weapon, InterceptCall);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Credits =)
|
||||
try
|
||||
{
|
||||
auto renderCredits = pattern( "83 C4 14 8D 45 F4 50 FF 35 ? ? ? ? E8 ? ? ? ? 59 59 8D 45 F4 50 FF 35 ? ? ? ? E8 ? ? ? ? 59 59 E8" ).get_one();
|
||||
|
||||
|
@ -1459,9 +1469,11 @@ void Patch_III_Common()
|
|||
ReadCall( renderCredits.get<void>( -5 ), Credits::PrintCreditText_Hooked );
|
||||
InjectHook( renderCredits.get<void>( -5 ), Credits::PrintSPCredits );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Decreased keyboard input latency
|
||||
try
|
||||
{
|
||||
using namespace KeyboardInputFix;
|
||||
|
||||
|
@ -1477,20 +1489,20 @@ void Patch_III_Common()
|
|||
InjectHook( simButtonCheckers, ClearSimButtonPressCheckers );
|
||||
InjectHook( updatePads.get<void>( 10 ), jmpDest, HookType::Jump );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Locale based metric/imperial system
|
||||
try
|
||||
{
|
||||
using namespace Localization;
|
||||
|
||||
void* updateCompareFlag = get_pattern( "89 E9 6A 00 E8 ? ? ? ? 30 C0 83 C4 70 5D 5E 5B C2 04 00", 4 );
|
||||
auto constructStatLine = pattern( "FF 24 9D ? ? ? ? 39 D0" ).get_one();
|
||||
|
||||
ReadCall( updateCompareFlag, orgUpdateCompareFlag_IsMetric );
|
||||
InjectHook( updateCompareFlag, UpdateCompareFlag_IsMetric );
|
||||
|
||||
// Stats
|
||||
auto constructStatLine = pattern( "FF 24 9D ? ? ? ? 39 D0" ).get_one();
|
||||
|
||||
// push eax
|
||||
// push edx
|
||||
// call IsMetric_LocaleBased
|
||||
|
@ -1503,25 +1515,29 @@ void Patch_III_Common()
|
|||
Patch( constructStatLine.get<void>( -0xF + 7 ), { 0x0F, 0xB6, 0xD8, 0x5A, 0x58 } );
|
||||
Nop( constructStatLine.get<void>( -0xF + 12 ), 3 );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Add cDMAudio::IsAudioInitialised checks before constructing cAudioScriptObject, like in VC
|
||||
try
|
||||
{
|
||||
using namespace AudioInitializedFix;
|
||||
|
||||
auto processCommands300 = pattern( "E8 ? ? ? ? 85 C0 59 74 ? 89 C1 E8 ? ? ? ? D9 05" ).get_one();
|
||||
auto processCommands300_2 = pattern( "6A 14 E8 ? ? ? ? 89 C3 59 85 DB 74" ).get_one();
|
||||
auto bulletInfoUpdate_Switch = *get_pattern<uintptr_t*>( "FF 24 85 ? ? ? ? 6A 14", 3 );
|
||||
auto playlayOneShotScriptObject = pattern( "6A 14 E8 ? ? ? ? 85 C0 59 74 ? 89 C1 E8 ? ? ? ? D9 03 D9 58 04" ).get_one();
|
||||
auto loadAllAudioScriptObjects = get_pattern( "FF B5 78 FF FF FF E8 ? ? ? ? 59 59 8B 45 C8", 6 );
|
||||
|
||||
ReadCall( processCommands300.get<void>( 0 ), operatorNew );
|
||||
|
||||
InjectHook( processCommands300.get<void>( 0 ), operatorNew_InitializedCheck );
|
||||
Patch<int8_t>( processCommands300.get<void>( 8 + 1 ), 0x440B62 - 0x440B24 );
|
||||
|
||||
auto processCommands300_2 = pattern( "6A 14 E8 ? ? ? ? 89 C3 59 85 DB 74" ).get_one();
|
||||
InjectHook( processCommands300_2.get<void>( 2 ), operatorNew_InitializedCheck );
|
||||
Patch<int8_t>( processCommands300_2.get<void>( 0xC + 1 ), 0x440BD7 - 0x440B8B );
|
||||
|
||||
// We need to patch switch cases 0, 3, 4
|
||||
auto bulletInfoUpdate_Switch = *get_pattern<uintptr_t*>( "FF 24 85 ? ? ? ? 6A 14", 3 );
|
||||
|
||||
const uintptr_t bulletInfoUpdate_0 = bulletInfoUpdate_Switch[0];
|
||||
const uintptr_t bulletInfoUpdate_3 = bulletInfoUpdate_Switch[3];
|
||||
const uintptr_t bulletInfoUpdate_4 = bulletInfoUpdate_Switch[4];
|
||||
|
@ -1535,32 +1551,31 @@ void Patch_III_Common()
|
|||
InjectHook( bulletInfoUpdate_4 + 2, operatorNew_InitializedCheck );
|
||||
Patch<int8_t>( bulletInfoUpdate_4 + 0xA + 1, 0x558C19 - 0x558BE3 );
|
||||
|
||||
auto playlayOneShotScriptObject = pattern( "6A 14 E8 ? ? ? ? 85 C0 59 74 ? 89 C1 E8 ? ? ? ? D9 03 D9 58 04" ).get_one();
|
||||
InjectHook( playlayOneShotScriptObject.get<void>( 2 ), operatorNew_InitializedCheck );
|
||||
Patch<int8_t>( playlayOneShotScriptObject.get<void>( 0xA + 1 ), 0x57C633 - 0x57C601 );
|
||||
|
||||
auto loadAllAudioScriptObjects = get_pattern( "FF B5 78 FF FF FF E8 ? ? ? ? 59 59 8B 45 C8", 6 );
|
||||
ReadCall( loadAllAudioScriptObjects, orgLoadAllAudioScriptObjects );
|
||||
InjectHook( loadAllAudioScriptObjects, LoadAllAudioScriptObjects_InitializedCheck );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Give chopper/escape a properly sized collision bounding box instead of using ped's
|
||||
try
|
||||
{
|
||||
auto initHelisPattern = pattern( "C6 40 2C 00 A1" ).count_hint(1);
|
||||
if ( initHelisPattern.size() == 1 )
|
||||
{
|
||||
static constexpr CColModel colModelChopper( CColSphere( 8.5f, CVector(0.0f, -1.75f, 0.73f), 0, 0 ),
|
||||
CColBox( CVector(-2.18f, -8.52f, -0.67f), CVector(-2.18f, 4.58f, 2.125f), 0, 0 ) );
|
||||
auto initHelis = pattern( "C6 40 2C 00 A1" ).get_one();
|
||||
|
||||
auto initHelis = initHelisPattern.get_one();
|
||||
Patch( initHelis.get<void>( -7 + 3 ), &colModelChopper );
|
||||
Patch( initHelis.get<void>( 9 + 3 ), &colModelChopper );
|
||||
}
|
||||
static constexpr CColModel colModelChopper( CColSphere( 8.5f, CVector(0.0f, -1.75f, 0.73f), 0, 0 ),
|
||||
CColBox( CVector(-2.18f, -8.52f, -0.67f), CVector(-2.18f, 4.58f, 2.125f), 0, 0 ) );
|
||||
|
||||
Patch( initHelis.get<void>( -7 + 3 ), &colModelChopper );
|
||||
Patch( initHelis.get<void>( 9 + 3 ), &colModelChopper );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed vehicles exploding twice if the driver leaves the car while it's exploding
|
||||
try
|
||||
{
|
||||
using namespace RemoveDriverStatusFix;
|
||||
|
||||
|
@ -1581,35 +1596,43 @@ void Patch_III_Common()
|
|||
Nop(processCommands4, 3);
|
||||
Nop(pedSetOutCar, 3);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed an inverted condition in CCarCtrl::PickNextNodeRandomly
|
||||
// leading to cars being unable to turn right from one way roads
|
||||
// By Nick007J
|
||||
try
|
||||
{
|
||||
auto pickNodeRandomly = get_pattern("3B 44 24 24 74 09", 4);
|
||||
Patch<uint8_t>(pickNodeRandomly, 0x75);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Apply bilinear filtering on the player skin
|
||||
try
|
||||
{
|
||||
using namespace SkinTextureFilter;
|
||||
|
||||
auto getSkinTexture = get_pattern("E8 ? ? ? ? 89 C3 59 55");
|
||||
InterceptCall(getSkinTexture, orgRwTextureCreate, RwTextureCreate_SetLinearFilter);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Apply the environment mapping on extra components
|
||||
try
|
||||
{
|
||||
auto setEnvironmentMap = get_pattern("C7 83 D8 01 00 00 00 00 00 00 E8", 10);
|
||||
|
||||
InterceptCall(setEnvironmentMap, CVehicleModelInfo::orgSetEnvironmentMap, &CVehicleModelInfo::SetEnvironmentMap_ExtraComps);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fix the evasive dive miscalculating the angle, resulting in peds diving towards the vehicle
|
||||
try
|
||||
{
|
||||
using namespace EvasiveDiveFix;
|
||||
|
||||
|
@ -1618,9 +1641,11 @@ void Patch_III_Common()
|
|||
Nop(setEvasiveDive.get<void>(), 1);
|
||||
InjectHook(setEvasiveDive.get<void>(1), &CalculateAngle_Hook, HookType::Call);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fix probabilities in CVehicle::InflictDamage incorrectly assuming a random range from 0 to 100.000
|
||||
try
|
||||
{
|
||||
auto probability_do_nothing = get_pattern("66 81 7E 5A ? ? 73 50", 4);
|
||||
auto probability_flee = get_pattern("0F B7 46 5A 3D ? ? ? ? 0F 8E", 4 + 1);
|
||||
|
@ -1628,9 +1653,11 @@ void Patch_III_Common()
|
|||
Patch<uint16_t>(probability_do_nothing, 35000u * 32767u / 100000u);
|
||||
Patch<uint32_t>(probability_flee, 75000u * 32767u / 100000u);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Null terminate read lines in CPlane::LoadPath and CTrain::ReadAndInterpretTrackFile
|
||||
try
|
||||
{
|
||||
using namespace NullTerminatedLines;
|
||||
|
||||
|
@ -1648,25 +1675,26 @@ void Patch_III_Common()
|
|||
Nop(readTrackFile2.get<void>(), 2);
|
||||
InjectHook(readTrackFile2.get<void>(2), ReadTrackFile_Terminate, HookType::Call);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Backport 1.1 Stats menu font fix to 1.0
|
||||
try
|
||||
{
|
||||
using namespace StatsMenuFont;
|
||||
|
||||
// This pattern fails by design on 1.1/Steam
|
||||
auto constructStatLine = pattern("E8 ? ? ? ? D9 05 ? ? ? ? DC 0D ? ? ? ? 89 C7").count_hint(1);
|
||||
if (constructStatLine.size() == 1)
|
||||
{
|
||||
auto setFontStyle = get_pattern("6A 00 E8 ? ? ? ? 83 3D ? ? ? ? ? 59 0F 84", 2);
|
||||
auto constructStatLine = pattern("E8 ? ? ? ? D9 05 ? ? ? ? DC 0D ? ? ? ? 89 C7").get_one();
|
||||
auto setFontStyle = get_pattern("6A 00 E8 ? ? ? ? 83 3D ? ? ? ? ? 59 0F 84", 2);
|
||||
|
||||
ReadCall(setFontStyle, orgSetFontStyle);
|
||||
InterceptCall(constructStatLine.get_first<void>(), orgConstructStatLine, ConstructStatLine_SetFontStyle);
|
||||
}
|
||||
ReadCall(setFontStyle, orgSetFontStyle);
|
||||
InterceptCall(constructStatLine.get<void>(), orgConstructStatLine, ConstructStatLine_SetFontStyle);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Enable Dodo keyboard controls for all cars when the flying cars cheat is enabled
|
||||
try
|
||||
{
|
||||
using namespace DodoKeyboardControls;
|
||||
|
||||
|
@ -1676,9 +1704,11 @@ void Patch_III_Common()
|
|||
bAllDodosCheat = allDodosCheat;
|
||||
InterceptCall(findPlayerVehicle, orgFindPlayerVehicle, FindPlayerVehicle_DodoCheck);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Reset variables on New Game
|
||||
try
|
||||
{
|
||||
using namespace VariableResets;
|
||||
|
||||
|
@ -1696,9 +1726,11 @@ void Patch_III_Common()
|
|||
GameVariablesToReset.emplace_back(*get_pattern<int*>("7D 72 A1 ? ? ? ? 05", 2 + 1)); // LastTimeAmbulanceCreated
|
||||
GameVariablesToReset.emplace_back(*get_pattern<int*>("74 7F A1 ? ? ? ? 05", 2 + 1)); // LastTimeFireTruckCreated
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Clean up the pickup object when reusing a temporary slot
|
||||
try
|
||||
{
|
||||
using namespace GenerateNewPickup_ReuseObjectFix;
|
||||
|
||||
|
@ -1707,10 +1739,12 @@ void Patch_III_Common()
|
|||
pPickupObject = *give_us_a_pick_up_object.get<void*>(7 + 2);
|
||||
InterceptCall(give_us_a_pick_up_object.get<void>(2), orgGiveUsAPickUpObject, GiveUsAPickUpObject_CleanUpObject);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Sitting in boat (Speeder), implemented as a special vehicle feature
|
||||
// Based off SitInBoat from Fire_Head, with extra improvements
|
||||
try
|
||||
{
|
||||
using namespace SitInBoat;
|
||||
|
||||
|
@ -1730,36 +1764,40 @@ void Patch_III_Common()
|
|||
// This is intended - we don't actually need the original SetFinishCallback, only its parameters!
|
||||
InjectHook(finish_callback, FinishCallback_CallImmediately);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Copy the atomic render CB in CloneAtomicToFrameCB instead of overriding it
|
||||
// Fixes detached limbs rendering the normal and LOD atomics together
|
||||
try
|
||||
{
|
||||
auto set_render_cb = get_pattern("55 E8 ? ? ? ? 89 D8 59", 1);
|
||||
Nop(set_render_cb, 5);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fix dark car reflections in the Steam EXE
|
||||
// Based off Sergenaur's fix
|
||||
try
|
||||
{
|
||||
auto reflection = pattern("A1 ? ? ? ? 85 C0 74 34");
|
||||
if (reflection.count_hint(1).size() == 1) // This will only pass on the Steam EXE, and if Sergenaur's standalone fix isn't present
|
||||
{
|
||||
auto match = reflection.get_one();
|
||||
// This will only pass on the Steam EXE, and if Sergenaur's standalone fix isn't present
|
||||
auto reflection = pattern("A1 ? ? ? ? 85 C0 74 34").get_one();
|
||||
|
||||
// xor eax, eax \ nop
|
||||
Patch(match.get<void>(), { 0x31, 0xC0 });
|
||||
Nop(match.get<void>(2), 3);
|
||||
}
|
||||
// xor eax, eax \ nop
|
||||
Patch(reflection.get<void>(), { 0x31, 0xC0 });
|
||||
Nop(reflection.get<void>(2), 3);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Don't override the color of the FBI car
|
||||
try
|
||||
{
|
||||
auto spawn_one_car = get_pattern("83 7C 24 ? ? 75 0E C6 85", 5);
|
||||
Patch<uint8_t>(spawn_one_car, 0xEB);
|
||||
}
|
||||
TXN_CATCH();
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
|
|
|
@ -152,7 +152,6 @@
|
|||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -186,7 +185,6 @@
|
|||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
|
@ -222,7 +220,6 @@
|
|||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -97,7 +97,6 @@
|
|||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -137,7 +136,6 @@ copy /y "$(TargetPath)" "H:\Rockstar Games\Grand Theft Auto San Andreas\SilentPa
|
|||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
|
@ -179,7 +177,6 @@ copy /y "$(TargetPath)" "H:\Rockstar Games\Grand Theft Auto San Andreas\SilentPa
|
|||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
|
|
|
@ -717,7 +717,7 @@ namespace VariableResets
|
|||
void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
|
||||
{
|
||||
using namespace Memory;
|
||||
using namespace hook;
|
||||
using namespace hook::txn;
|
||||
|
||||
const ModuleList moduleList;
|
||||
|
||||
|
@ -749,139 +749,124 @@ void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModule
|
|||
if ( GetPrivateProfileIntW(L"SilentPatch", L"EnableVehicleCoronaFixes", -1, wcModulePath) == 1 )
|
||||
{
|
||||
// Other mods might be touching it, so only patch specific vehicles if their code has not been touched at all
|
||||
try
|
||||
{
|
||||
auto firetruck1 = pattern( "8D 8C 24 24 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" );
|
||||
auto firetruck2 = pattern( "8D 8C 24 30 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" );
|
||||
auto firetruck1 = pattern("8D 8C 24 24 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
|
||||
auto firetruck2 = pattern("8D 8C 24 30 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
|
||||
|
||||
if ( firetruck1.count_hint(1).size() == 1 && firetruck2.count_hint(1).size() == 1 )
|
||||
{
|
||||
static const CVector FIRETRUCK_SIREN_POS(0.95f, 3.2f, 1.4f);
|
||||
static const float FIRETRUCK_SIREN_MINUS_X = -FIRETRUCK_SIREN_POS.x;
|
||||
static const CVector FIRETRUCK_SIREN_POS(0.95f, 3.2f, 1.4f);
|
||||
static const float FIRETRUCK_SIREN_MINUS_X = -FIRETRUCK_SIREN_POS.x;
|
||||
|
||||
auto match1 = firetruck1.get_one();
|
||||
auto match2 = firetruck2.get_one();
|
||||
Patch( firetruck1.get<float*>( 7 + 2 ), &FIRETRUCK_SIREN_POS.z );
|
||||
Patch( firetruck1.get<float*>( 7 + 2 + (6*1) ), &FIRETRUCK_SIREN_POS.y );
|
||||
Patch( firetruck1.get<float*>( 7 + 2 + (6*2) ), &FIRETRUCK_SIREN_POS.x );
|
||||
|
||||
Patch( match1.get<float*>( 7 + 2 ), &FIRETRUCK_SIREN_POS.z );
|
||||
Patch( match1.get<float*>( 7 + 2 + (6*1) ), &FIRETRUCK_SIREN_POS.y );
|
||||
Patch( match1.get<float*>( 7 + 2 + (6*2) ), &FIRETRUCK_SIREN_POS.x );
|
||||
|
||||
Patch( match2.get<float*>( 7 + 2 ), &FIRETRUCK_SIREN_POS.z );
|
||||
Patch( match2.get<float*>( 7 + 2 + (6*1) ), &FIRETRUCK_SIREN_POS.y );
|
||||
Patch( match2.get<float*>( 7 + 2 + (6*2) ), &FIRETRUCK_SIREN_MINUS_X );
|
||||
}
|
||||
Patch( firetruck2.get<float*>( 7 + 2 ), &FIRETRUCK_SIREN_POS.z );
|
||||
Patch( firetruck2.get<float*>( 7 + 2 + (6*1) ), &FIRETRUCK_SIREN_POS.y );
|
||||
Patch( firetruck2.get<float*>( 7 + 2 + (6*2) ), &FIRETRUCK_SIREN_MINUS_X );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
try
|
||||
{
|
||||
auto ambulan1 = pattern( "8D 8C 24 0C 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" );
|
||||
auto ambulan2 = pattern( "8D 8C 24 18 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" );
|
||||
auto ambulan1 = pattern("8D 8C 24 0C 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
|
||||
auto ambulan2 = pattern("8D 8C 24 18 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
|
||||
|
||||
if ( ambulan1.count_hint(1).size() == 1 && ambulan2.count_hint(1).size() == 1 )
|
||||
{
|
||||
static const CVector AMBULANCE_SIREN_POS(0.7f, 0.65f, 1.55f);
|
||||
static const float AMBULANCE_SIREN_MINUS_X = -AMBULANCE_SIREN_POS.x;
|
||||
static const CVector AMBULANCE_SIREN_POS(0.7f, 0.65f, 1.55f);
|
||||
static const float AMBULANCE_SIREN_MINUS_X = -AMBULANCE_SIREN_POS.x;
|
||||
|
||||
auto match1 = ambulan1.get_one();
|
||||
auto match2 = ambulan2.get_one();
|
||||
Patch( ambulan1.get<float*>( 7 + 2 ), &AMBULANCE_SIREN_POS.z );
|
||||
Patch( ambulan1.get<float*>( 7 + 2 + (6*1) ), &AMBULANCE_SIREN_POS.y );
|
||||
Patch( ambulan1.get<float*>( 7 + 2 + (6*2) ), &AMBULANCE_SIREN_POS.x );
|
||||
|
||||
Patch( match1.get<float*>( 7 + 2 ), &AMBULANCE_SIREN_POS.z );
|
||||
Patch( match1.get<float*>( 7 + 2 + (6*1) ), &AMBULANCE_SIREN_POS.y );
|
||||
Patch( match1.get<float*>( 7 + 2 + (6*2) ), &AMBULANCE_SIREN_POS.x );
|
||||
|
||||
Patch( match2.get<float*>( 7 + 2 ), &AMBULANCE_SIREN_POS.z );
|
||||
Patch( match2.get<float*>( 7 + 2 + (6*1) ), &AMBULANCE_SIREN_POS.y );
|
||||
Patch( match2.get<float*>( 7 + 2 + (6*2) ), &AMBULANCE_SIREN_MINUS_X );
|
||||
}
|
||||
Patch( ambulan2.get<float*>( 7 + 2 ), &AMBULANCE_SIREN_POS.z );
|
||||
Patch( ambulan2.get<float*>( 7 + 2 + (6*1) ), &AMBULANCE_SIREN_POS.y );
|
||||
Patch( ambulan2.get<float*>( 7 + 2 + (6*2) ), &AMBULANCE_SIREN_MINUS_X );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
try
|
||||
{
|
||||
auto police1 = pattern( "8D 8C 24 DC 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" );
|
||||
auto police2 = pattern( "8D 8C 24 E8 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" );
|
||||
auto police1 = pattern("8D 8C 24 DC 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
|
||||
auto police2 = pattern("8D 8C 24 E8 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
|
||||
|
||||
if ( police1.count_hint(1).size() == 1 && police2.count_hint(1).size() == 1 )
|
||||
{
|
||||
static const CVector POLICE_SIREN_POS(0.55f, -0.4f, 0.95f);
|
||||
static const float POLICE_SIREN_MINUS_X = -POLICE_SIREN_POS.x;
|
||||
static const CVector POLICE_SIREN_POS(0.55f, -0.4f, 0.95f);
|
||||
static const float POLICE_SIREN_MINUS_X = -POLICE_SIREN_POS.x;
|
||||
|
||||
auto match1 = police1.get_one();
|
||||
auto match2 = police2.get_one();
|
||||
Patch( police1.get<float*>( 7 + 2 ), &POLICE_SIREN_POS.z );
|
||||
Patch( police1.get<float*>( 7 + 2 + (6*1) ), &POLICE_SIREN_POS.y );
|
||||
Patch( police1.get<float*>( 7 + 2 + (6*2) ), &POLICE_SIREN_POS.x );
|
||||
|
||||
Patch( match1.get<float*>( 7 + 2 ), &POLICE_SIREN_POS.z );
|
||||
Patch( match1.get<float*>( 7 + 2 + (6*1) ), &POLICE_SIREN_POS.y );
|
||||
Patch( match1.get<float*>( 7 + 2 + (6*2) ), &POLICE_SIREN_POS.x );
|
||||
|
||||
Patch( match2.get<float*>( 7 + 2 ), &POLICE_SIREN_POS.z );
|
||||
Patch( match2.get<float*>( 7 + 2 + (6*1) ), &POLICE_SIREN_POS.y );
|
||||
Patch( match2.get<float*>( 7 + 2 + (6*2) ), &POLICE_SIREN_MINUS_X );
|
||||
}
|
||||
Patch( police2.get<float*>( 7 + 2 ), &POLICE_SIREN_POS.z );
|
||||
Patch( police2.get<float*>( 7 + 2 + (6*1) ), &POLICE_SIREN_POS.y );
|
||||
Patch( police2.get<float*>( 7 + 2 + (6*2) ), &POLICE_SIREN_MINUS_X );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
try
|
||||
{
|
||||
auto enforcer1 = pattern( "8D 8C 24 F4 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" );
|
||||
auto enforcer2 = pattern( "8D 8C 24 00 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35" );
|
||||
auto enforcer1 = pattern("8D 8C 24 F4 08 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
|
||||
auto enforcer2 = pattern("8D 8C 24 00 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35").get_one();
|
||||
|
||||
if ( enforcer1.count_hint(1).size() == 1 && enforcer2.count_hint(1).size() == 1 )
|
||||
{
|
||||
static const CVector ENFORCER_SIREN_POS(0.6f, 1.05f, 1.4f);
|
||||
static const float ENFORCER_SIREN_MINUS_X = -ENFORCER_SIREN_POS.x;
|
||||
static const CVector ENFORCER_SIREN_POS(0.6f, 1.05f, 1.4f);
|
||||
static const float ENFORCER_SIREN_MINUS_X = -ENFORCER_SIREN_POS.x;
|
||||
|
||||
auto match1 = enforcer1.get_one();
|
||||
auto match2 = enforcer2.get_one();
|
||||
Patch( enforcer1.get<float*>( 7 + 2 ), &ENFORCER_SIREN_POS.z );
|
||||
Patch( enforcer1.get<float*>( 7 + 2 + (6*1) ), &ENFORCER_SIREN_POS.y );
|
||||
Patch( enforcer1.get<float*>( 7 + 2 + (6*2) ), &ENFORCER_SIREN_POS.x );
|
||||
|
||||
Patch( match1.get<float*>( 7 + 2 ), &ENFORCER_SIREN_POS.z );
|
||||
Patch( match1.get<float*>( 7 + 2 + (6*1) ), &ENFORCER_SIREN_POS.y );
|
||||
Patch( match1.get<float*>( 7 + 2 + (6*2) ), &ENFORCER_SIREN_POS.x );
|
||||
|
||||
Patch( match2.get<float*>( 7 + 2 ), &ENFORCER_SIREN_POS.z );
|
||||
Patch( match2.get<float*>( 7 + 2 + (6*1) ), &ENFORCER_SIREN_POS.y );
|
||||
Patch( match2.get<float*>( 7 + 2 + (6*2) ), &ENFORCER_SIREN_MINUS_X );
|
||||
}
|
||||
Patch( enforcer2.get<float*>( 7 + 2 ), &ENFORCER_SIREN_POS.z );
|
||||
Patch( enforcer2.get<float*>( 7 + 2 + (6*1) ), &ENFORCER_SIREN_POS.y );
|
||||
Patch( enforcer2.get<float*>( 7 + 2 + (6*2) ), &ENFORCER_SIREN_MINUS_X );
|
||||
}
|
||||
{
|
||||
auto chopper1 = pattern( "C7 44 24 44 00 00 E0 40 50 C7 44 24 4C 00 00 00 00" ); // Front light
|
||||
auto chopper2 = pattern( "C7 44 24 6C 00 00 10 C1 8D 44 24 5C C7 44 24 70 00 00 00 00" ); // Tail light
|
||||
TXN_CATCH();
|
||||
|
||||
if ( chopper1.count_hint(1).size() == 1 )
|
||||
{
|
||||
try
|
||||
{
|
||||
auto chopper1 = pattern("C7 44 24 44 00 00 E0 40 50 C7 44 24 4C 00 00 00 00").get_one(); // Front light
|
||||
|
||||
constexpr CVector CHOPPER_SEARCH_LIGHT_POS(0.0f, 3.0f, -1.0f); // Same as in III Aircraft (not implemented there yet!)
|
||||
|
||||
auto match = chopper1.get_one();
|
||||
|
||||
Patch( match.get<float>( 4 ), CHOPPER_SEARCH_LIGHT_POS.y );
|
||||
Patch( match.get<float>( 9 + 4 ), CHOPPER_SEARCH_LIGHT_POS.z );
|
||||
Patch( chopper1.get<float>( 4 ), CHOPPER_SEARCH_LIGHT_POS.y );
|
||||
Patch( chopper1.get<float>( 9 + 4 ), CHOPPER_SEARCH_LIGHT_POS.z );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
if ( chopper2.count_hint(1).size() == 1 )
|
||||
try
|
||||
{
|
||||
auto chopper2 = pattern("C7 44 24 6C 00 00 10 C1 8D 44 24 5C C7 44 24 70 00 00 00 00").get_one(); // Tail light
|
||||
|
||||
constexpr CVector CHOPPER_RED_LIGHT_POS(0.0f, -7.5f, 2.5f); // Same as in III Aircraft
|
||||
|
||||
auto match = chopper2.get_one();
|
||||
|
||||
Patch( match.get<float>( 4 ), CHOPPER_RED_LIGHT_POS.y );
|
||||
Patch( match.get<float>( 12 + 4 ), CHOPPER_RED_LIGHT_POS.z );
|
||||
Patch( chopper2.get<float>( 4 ), CHOPPER_RED_LIGHT_POS.y );
|
||||
Patch( chopper2.get<float>( 12 + 4 ), CHOPPER_RED_LIGHT_POS.z );
|
||||
}
|
||||
TXN_CATCH();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using namespace FBISirenCoronaFix;
|
||||
|
||||
auto hasFBISiren = pattern( "83 E9 04 0F 84 87 0A 00 00 83 E9 10" ); // Predicate for showing FBI/Vice Squad siren
|
||||
auto viceCheetah = pattern( "8D 8C 24 CC 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35 ? ? ? ? E8" ); // Siren pos
|
||||
auto viceCheetah = pattern("8D 8C 24 CC 09 00 00 FF 35 ? ? ? ? FF 35 ? ? ? ? FF 35 ? ? ? ? E8").get_one(); // Siren pos
|
||||
|
||||
if ( viceCheetah.count_hint(1).size() == 1 )
|
||||
try
|
||||
{
|
||||
auto match = viceCheetah.get_one();
|
||||
auto hasFBISiren = pattern("83 E9 04 0F 84 87 0A 00 00 83 E9 10").get_one(); // Predicate for showing FBI/Vice Squad siren
|
||||
|
||||
if ( hasFBISiren.count_hint(1).size() == 1 )
|
||||
{
|
||||
auto matchSiren = hasFBISiren.get_one();
|
||||
Patch<uint8_t>( hasFBISiren.get<void>(), 0x55 ); // push ebp
|
||||
InjectHook( hasFBISiren.get<void>( 1 ), SetUpFBISiren, HookType::Call );
|
||||
Patch( hasFBISiren.get<void>( 1 + 5 ), { 0x83, 0xC4, 0x04, 0x84, 0xC0, 0x90 } ); // add esp, 4 / test al, al / nop
|
||||
|
||||
Patch<uint8_t>( matchSiren.get<void>(), 0x55 ); // push ebp
|
||||
InjectHook( matchSiren.get<void>( 1 ), SetUpFBISiren, HookType::Call );
|
||||
Patch( matchSiren.get<void>( 1 + 5 ), { 0x83, 0xC4, 0x04, 0x84, 0xC0, 0x90 } ); // add esp, 4 / test al, al / nop
|
||||
|
||||
InjectHook( match.get<void>( 0x19 ), SetUpVector );
|
||||
}
|
||||
|
||||
static const float VICE_CHEETAH_SIREN_POS_Z = 0.25f;
|
||||
Patch( match.get<float*>( 7 + 2 ), &VICE_CHEETAH_SIREN_POS_Z );
|
||||
InjectHook( viceCheetah.get<void>( 0x19 ), SetUpVector );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
static const float VICE_CHEETAH_SIREN_POS_Z = 0.25f;
|
||||
Patch( viceCheetah.get<float*>( 7 + 2 ), &VICE_CHEETAH_SIREN_POS_Z );
|
||||
}
|
||||
TXN_CATCH();
|
||||
}
|
||||
|
||||
FLAUtils::Init(moduleList);
|
||||
|
@ -1180,9 +1165,10 @@ void Patch_VC_JP()
|
|||
void Patch_VC_Common()
|
||||
{
|
||||
using namespace Memory;
|
||||
using namespace hook;
|
||||
using namespace hook::txn;
|
||||
|
||||
// New timers fix
|
||||
try
|
||||
{
|
||||
auto hookPoint = pattern( "83 E4 F8 89 44 24 08 C7 44 24 0C 00 00 00 00 DF 6C 24 08" ).get_one();
|
||||
auto jmpPoint = get_pattern( "DD D8 E9 31 FF FF FF" );
|
||||
|
@ -1190,8 +1176,11 @@ void Patch_VC_Common()
|
|||
InjectHook( hookPoint.get<void>( 0x21 ), CTimer::Update_SilentPatch, HookType::Call );
|
||||
InjectHook( hookPoint.get<void>( 0x21 + 5 ), jmpPoint, HookType::Jump );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Alt+F4
|
||||
try
|
||||
{
|
||||
auto addr = pattern( "59 59 31 C0 83 C4 70 5D 5F 5E 5B C2 10 00" ).count(2);
|
||||
auto dest = get_pattern( "53 55 56 FF B4 24 90 00 00 00 FF 15" );
|
||||
|
@ -1200,8 +1189,11 @@ void Patch_VC_Common()
|
|||
InjectHook( match.get<void>( 2 ), dest, HookType::Jump );
|
||||
});
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Proper panels damage
|
||||
try
|
||||
{
|
||||
auto addr = pattern( "C6 41 09 03 C6 41 0A 03 C6 41 0B 03" ).get_one();
|
||||
|
||||
|
@ -1212,20 +1204,27 @@ void Patch_VC_Common()
|
|||
|
||||
Nop( addr.get<void>( 0x33 ), 7 );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Proper metric-imperial conversion constants
|
||||
try
|
||||
{
|
||||
static const float METERS_TO_MILES = 0.0006213711922f;
|
||||
auto addr = pattern( "75 ? D9 05 ? ? ? ? D8 0D ? ? ? ? 6A 00 6A 00 D9 9C 24" ).count(6);
|
||||
auto sum = get_pattern( "D9 9C 24 A8 00 00 00 8D 84 24 A8 00 00 00 50", -6 + 2 );
|
||||
|
||||
addr.for_each_result( [&]( pattern_match match ) {
|
||||
Patch<const void*>( match.get<void>( 0x8 + 2 ), &METERS_TO_MILES );
|
||||
});
|
||||
|
||||
auto sum = get_pattern( "D9 9C 24 A8 00 00 00 8D 84 24 A8 00 00 00 50", -6 + 2 );
|
||||
Patch<const void*>( sum, &METERS_TO_MILES );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Improved pathfinding in PickNextNodeAccordingStrategy - PickNextNodeToChaseCar with XYZ coords
|
||||
try
|
||||
{
|
||||
auto addr = pattern( "E8 ? ? ? ? 50 8D 44 24 10 50 E8" ).get_one();
|
||||
ReadCall( addr.get<void>( 0x25 ), orgPickNextNodeToChaseCar );
|
||||
|
@ -1258,25 +1257,31 @@ void Patch_VC_Common()
|
|||
InjectHook( addr.get<void>( 0x46 ), PickNextNodeToChaseCarXYZ );
|
||||
Patch<uint8_t>( addr.get<void>( 0x4B + 2 ), 0xC );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// No censorships
|
||||
try
|
||||
{
|
||||
auto addr = get_pattern( "8B 43 50 85 C0 8B 53 50 74 2B 83 E8 01" );
|
||||
Patch( addr, { 0x83, 0xC4, 0x08, 0x5B, 0xC3 } ); // add esp, 8 \ pop ebx \ retn
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// 014C cargen counter fix (by spaceeinstein)
|
||||
try
|
||||
{
|
||||
auto do_processing = pattern( "0F B7 43 28 83 F8 FF 7D 04 66 FF 4B 28" ).get_one();
|
||||
|
||||
Patch<uint8_t>( do_processing.get<uint8_t*>(1), 0xBF ); // movzx eax, word ptr [ebx+28h] -> movsx eax, word ptr [ebx+28h]
|
||||
Patch<uint8_t>( do_processing.get<uint8_t*>(7), 0x74 ); // jge -> jz
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed ammo from SCM
|
||||
try
|
||||
{
|
||||
using namespace ZeroAmmoFix;
|
||||
|
||||
|
@ -1286,16 +1291,20 @@ void Patch_VC_Common()
|
|||
};
|
||||
HookEach_GiveWeapon(give_weapon, InterceptCall);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Extras working correctly on bikes
|
||||
try
|
||||
{
|
||||
auto createInstance = get_pattern( "89 C1 8B 41 04" );
|
||||
InjectHook( createInstance, CreateInstance_BikeFix, HookType::Call );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Credits =)
|
||||
try
|
||||
{
|
||||
auto renderCredits = pattern( "8D 44 24 28 83 C4 14 50 FF 35 ? ? ? ? E8 ? ? ? ? 8D 44 24 1C 59 59 50 FF 35 ? ? ? ? E8 ? ? ? ? 59 59" ).get_one();
|
||||
|
||||
|
@ -1303,9 +1312,11 @@ void Patch_VC_Common()
|
|||
ReadCall( renderCredits.get<void>( -5 ), Credits::PrintCreditText_Hooked );
|
||||
InjectHook( renderCredits.get<void>( -5 ), Credits::PrintSPCredits );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Decreased keyboard input latency
|
||||
try
|
||||
{
|
||||
using namespace KeyboardInputFix;
|
||||
|
||||
|
@ -1321,42 +1332,44 @@ void Patch_VC_Common()
|
|||
InjectHook( simButtonCheckers, ClearSimButtonPressCheckers );
|
||||
InjectHook( updatePads.get<void>( 9 ), jmpDest, HookType::Jump );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Locale based metric/imperial system
|
||||
try
|
||||
{
|
||||
using namespace Localization;
|
||||
|
||||
void* updateCompareFlag = get_pattern( "89 D9 6A 00 E8 ? ? ? ? 30 C0 83 C4 70 5D 5F 5E 5B C2 04 00", 4 );
|
||||
auto constructStatLine = pattern( "85 C0 74 11 83 E8 01 83 F8 03" ).get_one();
|
||||
|
||||
ReadCall( updateCompareFlag, orgUpdateCompareFlag_IsMetric );
|
||||
InjectHook( updateCompareFlag, UpdateCompareFlag_IsMetric );
|
||||
|
||||
// Stats
|
||||
auto constructStatLine = pattern( "85 C0 74 11 83 E8 01 83 F8 03" ).get_one();
|
||||
|
||||
Nop( constructStatLine.get<void>( -11 ), 1 );
|
||||
InjectHook( constructStatLine.get<void>( -11 + 1 ), PrefsLanguage_IsMetric, HookType::Call );
|
||||
Nop( constructStatLine.get<void>( -2 ), 2 );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Corrected FBI Washington sirens sound
|
||||
// Primary siren lower pitched like in FBI Rancher and secondary siren higher pitched
|
||||
try
|
||||
{
|
||||
using namespace SirenSwitchingFix;
|
||||
|
||||
// Other mods might be touching it, so only patch specific vehicles if their code has not been touched at all
|
||||
auto sirenPitch = pattern( "83 F8 17 74 32" ).count_hint(1);
|
||||
if ( sirenPitch.size() == 1 )
|
||||
auto sirenPitch = pattern( "83 F8 17 74 32" ).get_one();
|
||||
|
||||
InjectHook( sirenPitch.get<void>( 5 ), IsFBIRanchOrFBICar, HookType::Call );
|
||||
Patch( sirenPitch.get<void>( 5 + 5 ), { 0x84, 0xC0 } ); // test al, al
|
||||
Nop( sirenPitch.get<void>( 5 + 5 + 2 ), 4 );
|
||||
|
||||
// Pitch shift FBI Washington primary siren
|
||||
try
|
||||
{
|
||||
auto match = sirenPitch.get_one();
|
||||
|
||||
InjectHook( match.get<void>( 5 ), IsFBIRanchOrFBICar, HookType::Call );
|
||||
Patch( match.get<void>( 5 + 5 ), { 0x84, 0xC0 } ); // test al, al
|
||||
Nop( match.get<void>( 5 + 5 + 2 ), 4 );
|
||||
|
||||
// Pitch shift FBI Washington primary siren
|
||||
struct tVehicleSampleData {
|
||||
int m_nAccelerationSampleIndex;
|
||||
char m_bEngineSoundType;
|
||||
|
@ -1375,20 +1388,25 @@ void Patch_VC_Common()
|
|||
dataTable[17].m_nSirenOrAlarmFrequency = dataTable[90].m_nSirenOrAlarmFrequency;
|
||||
}
|
||||
}
|
||||
TXN_CATCH();
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Allow extra6 to be picked with component rule 4 (any)
|
||||
try
|
||||
{
|
||||
void* extraMult6 = get_pattern( "D8 0D ? ? ? ? D9 7C 24 04 8B 44 24 04 80 4C 24 05 0C D9 6C 24 04 89 44 24 04 DB 5C 24 08 D9 6C 24 04 8B 44 24 08 83 C4 10 5D", 2 );
|
||||
|
||||
static const float MULT_6 = 6.0f;
|
||||
Patch( extraMult6, &MULT_6 );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Make drive-by one shot sounds owned by the driver instead of the car
|
||||
// Fixes incorrect weapon sound being used for drive-by
|
||||
try
|
||||
{
|
||||
auto getDriverOneShot = pattern( "FF 35 ? ? ? ? 6A 37 50 E8 ? ? ? ? 83 7E 08 00" ).get_one();
|
||||
|
||||
|
@ -1398,9 +1416,11 @@ void Patch_VC_Common()
|
|||
Patch( getDriverOneShot.get<void>( -8 ), { 0x90, 0x89, 0xD9 } );
|
||||
InjectHook( getDriverOneShot.get<void>( -5 ), &CVehicle::GetOneShotOwnerID_SilentPatch, HookType::Call );
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed vehicles exploding twice if the driver leaves the car while it's exploding
|
||||
try
|
||||
{
|
||||
using namespace RemoveDriverStatusFix;
|
||||
|
||||
|
@ -1419,9 +1439,11 @@ void Patch_VC_Common()
|
|||
Nop(removeThisPed, 3);
|
||||
Nop(pedSetOutCar, 3);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Apply the environment mapping on extra components
|
||||
try
|
||||
{
|
||||
using namespace EnvMapsOnExtras;
|
||||
|
||||
|
@ -1431,17 +1453,21 @@ void Patch_VC_Common()
|
|||
Patch<uint8_t>(forAllAtomics.get<void>(), 0x53);
|
||||
InterceptCall(forAllAtomics.get<void>(1), orgRpClumpForAllAtomics, RpClumpForAllAtomics_ExtraComps);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fix probabilities in CVehicle::InflictDamage incorrectly assuming a random range from 0 to 100.000
|
||||
try
|
||||
{
|
||||
auto probability = get_pattern("66 81 7B 5A ? ? 73 50", 4);
|
||||
|
||||
Patch<uint16_t>(probability, 35000u / 2u);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Null terminate read lines in CPlane::LoadPath
|
||||
try
|
||||
{
|
||||
using namespace NullTerminatedLines;
|
||||
|
||||
|
@ -1449,9 +1475,11 @@ void Patch_VC_Common()
|
|||
|
||||
InterceptCall(loadPath, orgSscanf_LoadPath, sscanf1_LoadPath_Terminate);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Don't reset mouse sensitivity on New Game
|
||||
try
|
||||
{
|
||||
using namespace MouseSensNewGame;
|
||||
|
||||
|
@ -1464,9 +1492,11 @@ void Patch_VC_Common()
|
|||
Nop(cameraInit.get<void>(20), 10);
|
||||
InterceptCall(setDirMyDocuments, orgSetDirMyDocuments, SetDirMyDocuments_ResetMouse);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed pickup effects
|
||||
try
|
||||
{
|
||||
using namespace PickupEffectsFixes;
|
||||
|
||||
|
@ -1479,22 +1509,24 @@ void Patch_VC_Common()
|
|||
|
||||
// Don't spawn the grenade together with the detonator in the pickup
|
||||
// FLA might be altering this due to the usage of 16-bit IDs? Just in case allow for graceful failure
|
||||
auto pickupExtraObject = pattern("75 04 66 8B 70 58").count_hint(1);
|
||||
if (pickupExtraObject.size() == 1)
|
||||
try
|
||||
{
|
||||
auto match = pickupExtraObject.get_one();
|
||||
auto pickupExtraObject = pattern("75 04 66 8B 70 58").get_one();
|
||||
|
||||
Nop(match.get<void>(), 1);
|
||||
InjectHook(match.get<void>(1), &PickUpEffects_GiveUsAnObject, HookType::Call);
|
||||
Nop(pickupExtraObject.get<void>(), 1);
|
||||
InjectHook(pickupExtraObject.get<void>(1), &PickUpEffects_GiveUsAnObject, HookType::Call);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
InjectHook(bigDollarColor, &PickUpEffects_BigDollarColor, HookType::Call);
|
||||
InjectHook(minigun2Glow, &PickUpEffects_Minigun2Glow, HookType::Call);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed the muzzle flash facing the wrong direction
|
||||
// By Wesser
|
||||
try
|
||||
{
|
||||
auto fireInstantHit = pattern("D9 44 24 50 D8 44 24 44").get_one();
|
||||
|
||||
|
@ -1503,11 +1535,13 @@ void Patch_VC_Common()
|
|||
Patch(fireInstantHit.get<void>(15), { 0xD9, 0xEE, 0x90, 0x90 });
|
||||
Patch(fireInstantHit.get<void>(30), { 0xD9, 0xEE, 0x90, 0x90 });
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Fixed IS_PLAYER_TARGETTING_CHAR incorrectly detecting targetting in Classic controls
|
||||
// when the player is not aiming
|
||||
// By Wesser
|
||||
try
|
||||
{
|
||||
using namespace IsPlayerTargettingCharFix;
|
||||
|
||||
|
@ -1525,17 +1559,21 @@ void Patch_VC_Common()
|
|||
memmove(isPlayerTargettingChar.get<void>(), isPlayerTargettingChar.get<void>(5), 5);
|
||||
InjectHook(isPlayerTargettingChar.get<void>(5), IsPlayerTargettingChar_ExtraChecks, HookType::Call);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Use PS2 randomness for Rosenberg audio to hopefully bring the odds closer to PS2
|
||||
// The functionality was never broken on PC - but the random distribution seemingly made it looks as if it was
|
||||
try
|
||||
{
|
||||
auto busted_audio_rand = get_pattern("80 BB 48 01 00 00 00 0F 85 ? ? ? ? E8 ? ? ? ? 25 FF FF 00 00", 13);
|
||||
InjectHook(busted_audio_rand, rand15_ps2);
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Reset variables on New Game
|
||||
try
|
||||
{
|
||||
using namespace VariableResets;
|
||||
|
||||
|
@ -1553,30 +1591,28 @@ void Patch_VC_Common()
|
|||
GameVariablesToReset.emplace_back(*get_pattern<int*>("7D 78 A1 ? ? ? ? 05", 2 + 1)); // LastTimeAmbulanceCreated
|
||||
GameVariablesToReset.emplace_back(*get_pattern<int*>("A1 ? ? ? ? 05 ? ? ? ? 39 05 ? ? ? ? 0F 86 ? ? ? ? 8B 15", 1)); // LastTimeFireTruckCreated
|
||||
}
|
||||
TXN_CATCH();
|
||||
|
||||
|
||||
// Ped speech fix
|
||||
// Based off Sergenaur's fix
|
||||
try
|
||||
{
|
||||
// Remove the artificial 6s delay between any ped speech samples
|
||||
auto delay_check = pattern("80 BE ? ? ? ? ? 0F 85 ? ? ? ? B9");
|
||||
auto comment_delay_id1 = pattern("0F B7 C2 DD D8 C1 E0 04");
|
||||
auto comment_delay_id2 = pattern("0F B7 95 DA 05 00 00 D9 6C 24 04");
|
||||
auto delay_check = get_pattern("80 BE ? ? ? ? ? 0F 85 ? ? ? ? B9", 7);
|
||||
auto comment_delay_id1 = get_pattern("0F B7 C2 DD D8 C1 E0 04");
|
||||
auto comment_delay_id2 = pattern("0F B7 95 DA 05 00 00 D9 6C 24 04").get_one();
|
||||
|
||||
// Make sure we don't conflict with Sergenaur's fix
|
||||
if (delay_check.count_hint(1).size() == 1 && comment_delay_id1.count_hint(1).size() == 1 && comment_delay_id2.count_hint(1).size() == 1)
|
||||
{
|
||||
Nop(delay_check.get_first<void>(7), 6);
|
||||
Nop(delay_check, 6);
|
||||
|
||||
// movzx eax, dx -> movzx eax, bx
|
||||
Patch(comment_delay_id1.get_first<void>(), { 0x0F, 0xB7, 0xC3 });
|
||||
// movzx eax, dx -> movzx eax, bx
|
||||
Patch(comment_delay_id1, { 0x0F, 0xB7, 0xC3 });
|
||||
|
||||
// movzx edx, word ptr [ebp+5DAh] -> movzx edx, bx \ nop
|
||||
auto delay_id2 = comment_delay_id2.get_one();
|
||||
Patch(delay_id2.get<void>(), { 0x0F, 0xB7, 0xD3 });
|
||||
Nop(delay_id2.get<void>(3), 4);
|
||||
}
|
||||
// movzx edx, word ptr [ebp+5DAh] -> movzx edx, bx \ nop
|
||||
Patch(comment_delay_id2.get<void>(), { 0x0F, 0xB7, 0xD3 });
|
||||
Nop(comment_delay_id2.get<void>(3), 4);
|
||||
}
|
||||
TXN_CATCH();
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
|
|
|
@ -82,7 +82,6 @@
|
|||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
<AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
|
@ -114,7 +113,6 @@
|
|||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
<AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
|
@ -148,7 +146,6 @@
|
|||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
<AdditionalOptions>/Zc:threadSafeInit- /Zc:strictStrings %(AdditionalOptions)</AdditionalOptions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
|
|
Loading…
Reference in a new issue