mirror of
https://github.com/CookiePLMonster/SilentPatch.git
synced 2024-12-29 15:23:02 +05:00
III/VC: Upgrade the variable resets fix to how it is in SA
Also call CTimer::Initialise from CGame::Initialise Fixes #20
This commit is contained in:
parent
836fbafd41
commit
a535081e8a
2 changed files with 126 additions and 103 deletions
|
@ -361,16 +361,6 @@ int NewFrameRender(int nEvent, void* pParam)
|
||||||
return RsEventHandler(nEvent, pParam);
|
return RsEventHandler(nEvent, pParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
static signed int& LastTimeFireTruckCreated = **(int**)Memory::DynBaseAddress(0x41D2E5);
|
|
||||||
static signed int& LastTimeAmbulanceCreated = **(int**)Memory::DynBaseAddress(0x41D2F9);
|
|
||||||
static void (*orgCarCtrlReInit)();
|
|
||||||
void CarCtrlReInit_SilentPatch()
|
|
||||||
{
|
|
||||||
orgCarCtrlReInit();
|
|
||||||
LastTimeFireTruckCreated = 0;
|
|
||||||
LastTimeAmbulanceCreated = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void (*orgPickNextNodeToChaseCar)(void*, float, float, void*);
|
static void (*orgPickNextNodeToChaseCar)(void*, float, float, void*);
|
||||||
static float PickNextNodeToChaseCarZ = 0.0f;
|
static float PickNextNodeToChaseCarZ = 0.0f;
|
||||||
static void PickNextNodeToChaseCarXYZ( void* vehicle, const CVector& vec, void* chaseTarget )
|
static void PickNextNodeToChaseCarXYZ( void* vehicle, const CVector& vec, void* chaseTarget )
|
||||||
|
@ -695,6 +685,49 @@ namespace DodoKeyboardControls
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============= Resetting stats and variables on New Game =============
|
||||||
|
namespace VariableResets
|
||||||
|
{
|
||||||
|
static auto TimerInitialise = reinterpret_cast<void(*)()>(hook::get_pattern("83 E4 F8 68 ? ? ? ? E8", -6));
|
||||||
|
|
||||||
|
using VarVariant = std::variant< bool*, int* >;
|
||||||
|
std::vector<VarVariant> GameVariablesToReset;
|
||||||
|
|
||||||
|
static void ReInitOurVariables()
|
||||||
|
{
|
||||||
|
for ( const auto& var : GameVariablesToReset )
|
||||||
|
{
|
||||||
|
std::visit( []( auto&& v ) {
|
||||||
|
*v = {};
|
||||||
|
}, var );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions that should have been called by the game but aren't...
|
||||||
|
TimerInitialise();
|
||||||
|
PurpleNinesGlitchFix();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t Index>
|
||||||
|
static void (*orgReInitGameObjectVariables)();
|
||||||
|
|
||||||
|
template<std::size_t Index>
|
||||||
|
void ReInitGameObjectVariables()
|
||||||
|
{
|
||||||
|
// First reinit "our" variables in case stock ones rely on those during resetting
|
||||||
|
ReInitOurVariables();
|
||||||
|
orgReInitGameObjectVariables<Index>();
|
||||||
|
}
|
||||||
|
HOOK_EACH_FUNC(ReInitGameObjectVariables, orgReInitGameObjectVariables, ReInitGameObjectVariables);
|
||||||
|
|
||||||
|
static void (*orgGameInitialise)(const char*);
|
||||||
|
void GameInitialise(const char* path)
|
||||||
|
{
|
||||||
|
ReInitOurVariables();
|
||||||
|
orgGameInitialise(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
|
void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
|
||||||
{
|
{
|
||||||
using namespace Memory;
|
using namespace Memory;
|
||||||
|
@ -973,21 +1006,6 @@ void Patch_III_10(uint32_t width, uint32_t height)
|
||||||
InjectHook(0x582EFD, NewFrameRender);
|
InjectHook(0x582EFD, NewFrameRender);
|
||||||
InjectHook(0x582EA4, GetTimeSinceLastFrame);
|
InjectHook(0x582EA4, GetTimeSinceLastFrame);
|
||||||
|
|
||||||
// Reinit CCarCtrl fields (firetruck and ambulance generation)
|
|
||||||
ReadCall( 0x48C4FB, orgCarCtrlReInit );
|
|
||||||
InjectHook(0x48C4FB, CarCtrlReInit_SilentPatch);
|
|
||||||
|
|
||||||
|
|
||||||
// Reinit free resprays flag
|
|
||||||
// add esp, 38h
|
|
||||||
// mov CGarages::RespraysAreFree, 0
|
|
||||||
// retn
|
|
||||||
bool* pFreeResprays = *(bool**)DynBaseAddress(0x4224A4);
|
|
||||||
Patch<BYTE>(0x421E06, 0x38);
|
|
||||||
Patch<WORD>(0x421E07, 0x05C6);
|
|
||||||
Patch<const void*>(0x421E09, pFreeResprays);
|
|
||||||
Patch<BYTE>(0x421E0E, 0xC3);
|
|
||||||
|
|
||||||
|
|
||||||
// Radar blips bounds check
|
// Radar blips bounds check
|
||||||
InjectHook(0x4A55B2, RadarBoundsCheckCoordBlip, HookType::Jump);
|
InjectHook(0x4A55B2, RadarBoundsCheckCoordBlip, HookType::Jump);
|
||||||
|
@ -1106,22 +1124,6 @@ void Patch_III_11(uint32_t width, uint32_t height)
|
||||||
InjectHook(0x5831E4, GetTimeSinceLastFrame);
|
InjectHook(0x5831E4, GetTimeSinceLastFrame);
|
||||||
|
|
||||||
|
|
||||||
// Reinit CCarCtrl fields (firetruck and ambulance generation)
|
|
||||||
ReadCall( 0x48C5FB, orgCarCtrlReInit );
|
|
||||||
InjectHook(0x48C5FB, CarCtrlReInit_SilentPatch);
|
|
||||||
|
|
||||||
|
|
||||||
// Reinit free resprays flag
|
|
||||||
// add esp, 38h
|
|
||||||
// mov CGarages::RespraysAreFree, 0
|
|
||||||
// retn
|
|
||||||
bool* pFreeResprays = *(bool**)DynBaseAddress(0x4224A4);
|
|
||||||
Patch<BYTE>(0x421E06, 0x38);
|
|
||||||
Patch<WORD>(0x421E07, 0x05C6);
|
|
||||||
Patch<const void*>(0x421E09, pFreeResprays);
|
|
||||||
Patch<BYTE>(0x421E0E, 0xC3);
|
|
||||||
|
|
||||||
|
|
||||||
// Radar blips bounds check
|
// Radar blips bounds check
|
||||||
InjectHook(0x4A56A2, RadarBoundsCheckCoordBlip, HookType::Jump);
|
InjectHook(0x4A56A2, RadarBoundsCheckCoordBlip, HookType::Jump);
|
||||||
InjectHook(0x4A5748, RadarBoundsCheckEntityBlip, HookType::Jump);
|
InjectHook(0x4A5748, RadarBoundsCheckEntityBlip, HookType::Jump);
|
||||||
|
@ -1224,21 +1226,6 @@ void Patch_III_Steam(uint32_t width, uint32_t height)
|
||||||
InjectHook(0x58312D, NewFrameRender);
|
InjectHook(0x58312D, NewFrameRender);
|
||||||
InjectHook(0x5830D4, GetTimeSinceLastFrame);
|
InjectHook(0x5830D4, GetTimeSinceLastFrame);
|
||||||
|
|
||||||
// Reinit CCarCtrl fields (firetruck and ambulance generation)
|
|
||||||
ReadCall( 0x48C58B, orgCarCtrlReInit );
|
|
||||||
InjectHook(0x48C58B, CarCtrlReInit_SilentPatch);
|
|
||||||
|
|
||||||
|
|
||||||
// Reinit free resprays flag
|
|
||||||
// add esp, 38h
|
|
||||||
// mov CGarages::RespraysAreFree, 0
|
|
||||||
// retn
|
|
||||||
bool* pFreeResprays = *(bool**)DynBaseAddress(0x4224A4);
|
|
||||||
Patch<BYTE>(0x421E06, 0x38);
|
|
||||||
Patch<WORD>(0x421E07, 0x05C6);
|
|
||||||
Patch<const void*>(0x421E09, pFreeResprays);
|
|
||||||
Patch<BYTE>(0x421E0E, 0xC3);
|
|
||||||
|
|
||||||
|
|
||||||
// Radar blips bounds check
|
// Radar blips bounds check
|
||||||
InjectHook(0x4A5632, RadarBoundsCheckCoordBlip, HookType::Jump);
|
InjectHook(0x4A5632, RadarBoundsCheckCoordBlip, HookType::Jump);
|
||||||
|
@ -1255,11 +1242,6 @@ void Patch_III_Common()
|
||||||
using namespace Memory;
|
using namespace Memory;
|
||||||
using namespace hook;
|
using namespace hook;
|
||||||
|
|
||||||
// Purple Nines Glitch fix
|
|
||||||
{
|
|
||||||
auto addr = get_pattern( "0F BF 4C 24 04 8B 44 24 08 C1 E1 04 89 81", -0xC );
|
|
||||||
InjectHook( addr, PurpleNinesGlitchFix, HookType::Jump );
|
|
||||||
}
|
|
||||||
|
|
||||||
// New timers fix
|
// New timers fix
|
||||||
{
|
{
|
||||||
|
@ -1588,6 +1570,26 @@ void Patch_III_Common()
|
||||||
bAllDodosCheat = allDodosCheat;
|
bAllDodosCheat = allDodosCheat;
|
||||||
InterceptCall(findPlayerVehicle, orgFindPlayerVehicle, FindPlayerVehicle_DodoCheck);
|
InterceptCall(findPlayerVehicle, orgFindPlayerVehicle, FindPlayerVehicle_DodoCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reset variables on New Game
|
||||||
|
{
|
||||||
|
using namespace VariableResets;
|
||||||
|
|
||||||
|
auto game_initialise = get_pattern("6A 00 E8 ? ? ? ? 83 C4 0C 68 ? ? ? ? E8 ? ? ? ? 59 C3", 15);
|
||||||
|
std::array<void*, 2> reinit_game_object_variables = {
|
||||||
|
get_pattern("E8 ? ? ? ? 80 3D ? ? ? ? ? 75 6B"),
|
||||||
|
get_pattern("C6 05 ? ? ? ? ? E8 ? ? ? ? C7 05", 7)
|
||||||
|
};
|
||||||
|
|
||||||
|
InterceptCall(game_initialise, orgGameInitialise, GameInitialise);
|
||||||
|
HookEach_ReInitGameObjectVariables(reinit_game_object_variables, InterceptCall);
|
||||||
|
|
||||||
|
// Variables to reset
|
||||||
|
GameVariablesToReset.emplace_back(*get_pattern<bool*>("80 3D ? ? ? ? ? 74 2A", 2)); // Free resprays
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
|
|
|
@ -235,22 +235,6 @@ int NewFrameRender(int nEvent, void* pParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static signed int& LastTimeFireTruckCreated = **AddressByVersion<int**>(0x429435, 0x429435, 0x429405);
|
|
||||||
static signed int& LastTimeAmbulanceCreated = **AddressByVersion<int**>(0x429449, 0x429449, 0x429419);
|
|
||||||
static void (*orgCarCtrlReInit)();
|
|
||||||
void CarCtrlReInit_SilentPatch()
|
|
||||||
{
|
|
||||||
orgCarCtrlReInit();
|
|
||||||
LastTimeFireTruckCreated = 0;
|
|
||||||
LastTimeAmbulanceCreated = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool& RespraysAreFree = **AddressByVersion<bool**>(0x430D17, 0x430D17, 0x430CE7);
|
|
||||||
void GaragesInit_SilentPatch()
|
|
||||||
{
|
|
||||||
RespraysAreFree = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void (*orgPickNextNodeToChaseCar)(void*, float, float, void*);
|
static void (*orgPickNextNodeToChaseCar)(void*, float, float, void*);
|
||||||
static float PickNextNodeToChaseCarZ = 0.0f;
|
static float PickNextNodeToChaseCarZ = 0.0f;
|
||||||
static void PickNextNodeToChaseCarXYZ( void* vehicle, const CVector& vec, void* chaseTarget )
|
static void PickNextNodeToChaseCarXYZ( void* vehicle, const CVector& vec, void* chaseTarget )
|
||||||
|
@ -686,6 +670,49 @@ namespace IsPlayerTargettingCharFix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============= Resetting stats and variables on New Game =============
|
||||||
|
namespace VariableResets
|
||||||
|
{
|
||||||
|
static auto TimerInitialise = reinterpret_cast<void(*)()>(hook::get_pattern("83 E4 F8 68 ? ? ? ? E8", -6));
|
||||||
|
|
||||||
|
using VarVariant = std::variant< bool*, int* >;
|
||||||
|
std::vector<VarVariant> GameVariablesToReset;
|
||||||
|
|
||||||
|
static void ReInitOurVariables()
|
||||||
|
{
|
||||||
|
for ( const auto& var : GameVariablesToReset )
|
||||||
|
{
|
||||||
|
std::visit( []( auto&& v ) {
|
||||||
|
*v = {};
|
||||||
|
}, var );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions that should have been called by the game but aren't...
|
||||||
|
TimerInitialise();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t Index>
|
||||||
|
static void (*orgReInitGameObjectVariables)();
|
||||||
|
|
||||||
|
template<std::size_t Index>
|
||||||
|
void ReInitGameObjectVariables()
|
||||||
|
{
|
||||||
|
// First reinit "our" variables in case stock ones rely on those during resetting
|
||||||
|
ReInitOurVariables();
|
||||||
|
orgReInitGameObjectVariables<Index>();
|
||||||
|
}
|
||||||
|
HOOK_EACH_FUNC(ReInitGameObjectVariables, orgReInitGameObjectVariables, ReInitGameObjectVariables);
|
||||||
|
|
||||||
|
static void (*orgGameInitialise)(const char*);
|
||||||
|
void GameInitialise(const char* path)
|
||||||
|
{
|
||||||
|
ReInitOurVariables();
|
||||||
|
orgGameInitialise(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
|
void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
|
||||||
{
|
{
|
||||||
using namespace Memory;
|
using namespace Memory;
|
||||||
|
@ -951,14 +978,6 @@ void Patch_VC_10(uint32_t width, uint32_t height)
|
||||||
Patch<DWORD>(0x5FDDDB, 0xC5);
|
Patch<DWORD>(0x5FDDDB, 0xC5);
|
||||||
|
|
||||||
|
|
||||||
// Reinit CCarCtrl fields (firetruck and ambulance generation)
|
|
||||||
ReadCall( 0x4A489B, orgCarCtrlReInit );
|
|
||||||
InjectHook(0x4A489B, CarCtrlReInit_SilentPatch);
|
|
||||||
|
|
||||||
|
|
||||||
// Reinit free resprays flag
|
|
||||||
InjectHook(0x4349BB, GaragesInit_SilentPatch, HookType::Jump);
|
|
||||||
|
|
||||||
// Fixed ammo for melee weapons in cheats
|
// Fixed ammo for melee weapons in cheats
|
||||||
Patch<BYTE>(0x4AED14+1, 1); // katana
|
Patch<BYTE>(0x4AED14+1, 1); // katana
|
||||||
Patch<BYTE>(0x4AEB74+1, 1); // chainsaw
|
Patch<BYTE>(0x4AEB74+1, 1); // chainsaw
|
||||||
|
@ -1056,15 +1075,6 @@ void Patch_VC_11(uint32_t width, uint32_t height)
|
||||||
Patch<DWORD>(0x5FDDFB, 0xC5);
|
Patch<DWORD>(0x5FDDFB, 0xC5);
|
||||||
|
|
||||||
|
|
||||||
// Reinit CCarCtrl fields (firetruck and ambulance generation)
|
|
||||||
ReadCall( 0x4A48BB, orgCarCtrlReInit );
|
|
||||||
InjectHook(0x4A48BB, CarCtrlReInit_SilentPatch);
|
|
||||||
|
|
||||||
|
|
||||||
// Reinit free resprays flag
|
|
||||||
InjectHook(0x4349BB, GaragesInit_SilentPatch, HookType::Jump);
|
|
||||||
|
|
||||||
|
|
||||||
// Fixed ammo for melee weapons in cheats
|
// Fixed ammo for melee weapons in cheats
|
||||||
Patch<BYTE>(0x4AED34+1, 1); // katana
|
Patch<BYTE>(0x4AED34+1, 1); // katana
|
||||||
Patch<BYTE>(0x4AEB94+1, 1); // chainsaw
|
Patch<BYTE>(0x4AEB94+1, 1); // chainsaw
|
||||||
|
@ -1151,15 +1161,6 @@ void Patch_VC_Steam(uint32_t width, uint32_t height)
|
||||||
Patch<DWORD>(0x5FDA3B, 0xC5);
|
Patch<DWORD>(0x5FDA3B, 0xC5);
|
||||||
|
|
||||||
|
|
||||||
// Reinit CCarCtrl fields (firetruck and ambulance generation)
|
|
||||||
ReadCall( 0x4A475B, orgCarCtrlReInit );
|
|
||||||
InjectHook(0x4A475B, CarCtrlReInit_SilentPatch);
|
|
||||||
|
|
||||||
|
|
||||||
// Reinit free resprays flag
|
|
||||||
InjectHook(0x43497B, GaragesInit_SilentPatch, HookType::Jump);
|
|
||||||
|
|
||||||
|
|
||||||
// Fixed ammo for melee weapons in cheats
|
// Fixed ammo for melee weapons in cheats
|
||||||
Patch<BYTE>(0x4AEA44+1, 1); // katana
|
Patch<BYTE>(0x4AEA44+1, 1); // katana
|
||||||
Patch<BYTE>(0x4AEBE4+1, 1); // chainsaw
|
Patch<BYTE>(0x4AEBE4+1, 1); // chainsaw
|
||||||
|
@ -1539,6 +1540,26 @@ void Patch_VC_Common()
|
||||||
auto busted_audio_rand = get_pattern("80 BB 48 01 00 00 00 0F 85 ? ? ? ? E8 ? ? ? ? 25 FF FF 00 00", 13);
|
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);
|
InjectHook(busted_audio_rand, rand15_ps2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reset variables on New Game
|
||||||
|
{
|
||||||
|
using namespace VariableResets;
|
||||||
|
|
||||||
|
auto game_initialise = get_pattern("6A 00 E8 ? ? ? ? 83 C4 0C 68 ? ? ? ? E8 ? ? ? ? 59 C3", 15);
|
||||||
|
std::array<void*, 2> reinit_game_object_variables = {
|
||||||
|
get_pattern("74 05 E8 ? ? ? ? E8 ? ? ? ? 80 3D", 7),
|
||||||
|
get_pattern("C6 05 ? ? ? ? ? E8 ? ? ? ? C7 05", 7)
|
||||||
|
};
|
||||||
|
|
||||||
|
InterceptCall(game_initialise, orgGameInitialise, GameInitialise);
|
||||||
|
HookEach_ReInitGameObjectVariables(reinit_game_object_variables, InterceptCall);
|
||||||
|
|
||||||
|
// Variables to reset
|
||||||
|
GameVariablesToReset.emplace_back(*get_pattern<bool*>("7D 09 80 3D ? ? ? ? ? 74 32", 2 + 2)); // Free resprays
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
|
|
Loading…
Reference in a new issue