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:
Silent 2024-05-07 22:30:32 +02:00
parent 836fbafd41
commit a535081e8a
No known key found for this signature in database
GPG key ID: AE53149BB0C45AF1
2 changed files with 126 additions and 103 deletions

View file

@ -361,16 +361,6 @@ int NewFrameRender(int nEvent, void* 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 float PickNextNodeToChaseCarZ = 0.0f;
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 )
{
using namespace Memory;
@ -973,21 +1006,6 @@ void Patch_III_10(uint32_t width, uint32_t height)
InjectHook(0x582EFD, NewFrameRender);
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
InjectHook(0x4A55B2, RadarBoundsCheckCoordBlip, HookType::Jump);
@ -1106,22 +1124,6 @@ void Patch_III_11(uint32_t width, uint32_t height)
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
InjectHook(0x4A56A2, RadarBoundsCheckCoordBlip, 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(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
InjectHook(0x4A5632, RadarBoundsCheckCoordBlip, HookType::Jump);
@ -1255,11 +1242,6 @@ void Patch_III_Common()
using namespace Memory;
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
{
@ -1588,6 +1570,26 @@ void Patch_III_Common()
bAllDodosCheat = allDodosCheat;
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)

View file

@ -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 float PickNextNodeToChaseCarZ = 0.0f;
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 )
{
using namespace Memory;
@ -951,14 +978,6 @@ void Patch_VC_10(uint32_t width, uint32_t height)
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
Patch<BYTE>(0x4AED14+1, 1); // katana
Patch<BYTE>(0x4AEB74+1, 1); // chainsaw
@ -1056,15 +1075,6 @@ void Patch_VC_11(uint32_t width, uint32_t height)
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
Patch<BYTE>(0x4AED34+1, 1); // katana
Patch<BYTE>(0x4AEB94+1, 1); // chainsaw
@ -1151,15 +1161,6 @@ void Patch_VC_Steam(uint32_t width, uint32_t height)
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
Patch<BYTE>(0x4AEA44+1, 1); // katana
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);
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)