Fixed vehicles exploding twice if the driver leaves the car while it's exploding

Fixes #13
This commit is contained in:
Silent 2024-02-29 21:44:18 +01:00
parent 1d2f0014f1
commit f025dff42d
No known key found for this signature in database
GPG key ID: AE53149BB0C45AF1
4 changed files with 174 additions and 4 deletions

View file

@ -506,6 +506,30 @@ namespace SirenSwitchingFix
};
// ============= Fixed vehicles exploding twice if the driver leaves the car while it's exploding =============
namespace RemoveDriverStatusFix
{
__declspec(naked) void RemoveDriver_SetStatus()
{
// if (m_nStatus != STATUS_WRECKED)
// m_nStatus = STATUS_ABANDONED;
_asm
{
mov ah, [ecx+50h]
mov al, ah
and ah, 0F8h
cmp ah, 28h
je DontSetStatus
and al, 7
or al, 20h
DontSetStatus:
retn
}
}
}
void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
{
using namespace Memory;
@ -1254,6 +1278,29 @@ void Patch_III_Common()
Patch( initHelis.get<void>( 9 + 3 ), &colModelChopper );
}
}
// Fixed vehicles exploding twice if the driver leaves the car while it's exploding
{
using namespace RemoveDriverStatusFix;
auto removeDriver = pattern("8A 41 50 24 07 0C 20 88 41 50 C7 81").get_one();
auto processCommands1 = get_pattern("88 41 50 8B 87");
auto processCommands2 = get_pattern("88 41 50 8B 2B");
auto processCommands3 = get_pattern("0C 20 88 42 50", 2);
auto processCommands4 = get_pattern("88 41 50 8B BE");
auto pedSetOutCar = get_pattern("88 41 50 8B 85");
Nop(removeDriver.get<void>(), 2);
InjectHook(removeDriver.get<void>(2), RemoveDriver_SetStatus, HookType::Call);
// CVehicle::RemoveDriver already sets the status to STATUS_ABANDONED, these are redundant
Nop(processCommands1, 3);
Nop(processCommands2, 3);
Nop(processCommands3, 3);
Nop(processCommands4, 3);
Nop(pedSetOutCar, 3);
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)

View file

@ -6,6 +6,7 @@
class CEntryExit;
class CEvent;
class CPed;
class CVehicle;
// This structure is very incomplete, but it is good enough for now
class __declspec(novtable) CTask
@ -33,6 +34,9 @@ public:
class __declspec(novtable) CTaskComplex : public CTask
{
private:
CTask* m_pSubTask;
public:
virtual bool IsSimpleTask() const override { return false; }
virtual void SetSubTask(CTask*);
@ -54,12 +58,20 @@ public:
bool Contains(int taskID) const;
public:
std::byte __pad1[8];
std::byte __pad1[4];
CTask* m_taskSequence[8];
std::byte __pad2[16];
};
static_assert(sizeof(CTaskComplexSequence) == 0x40, "Wrong size: CTaskComplexSequence");
class __declspec(novtable) CTaskComplexCarSlowBeDraggedOut : public CTaskComplex
{
public:
CVehicle* m_pVehicle;
int m_status;
};
static_assert(sizeof(CTaskComplexCarSlowBeDraggedOut) == 0x14, "Wrong size: CTaskComplexCarSlowBeDraggedOut");
class CTaskManager
{
public:
@ -215,9 +227,6 @@ public:
unsigned int bUsedForReplay : 1; // This ped is controlled by replay and should be removed when replay is done.
};
class CVehicle;
class CPed;
class CPlayerPedData
{
public:

View file

@ -2455,6 +2455,39 @@ namespace RiotDontTargetPlayerGroupDuringMissions
}
// ============= Fixed vehicles exploding twice if the driver leaves the car while it's exploding =============
namespace RemoveDriverStatusFix
{
__declspec(naked) void RemoveDriver_SetStatus()
{
// if (m_nStatus != STATUS_WRECKED)
// m_nStatus = STATUS_ABANDONED;
_asm
{
mov bl, [edi+36h]
mov al, bl
and bl, 0F8h
cmp bl, 28h
je DontSetStatus
and al, 7
or al, 20h
DontSetStatus:
retn
}
}
static void (__thiscall *orgPrepareVehicleForPedExit)(CTaskComplexCarSlowBeDraggedOut* task, CPed* ped);
static void __fastcall PrepareVehicleForPedExit_WreckedCheck(CTaskComplexCarSlowBeDraggedOut* task, void*, CPed* ped)
{
if (task->m_pVehicle->GetStatus() != STATUS_WRECKED)
{
orgPrepareVehicleForPedExit(task, ped);
}
}
}
// ============= LS-RP Mode stuff =============
namespace LSRPMode
{
@ -5206,6 +5239,21 @@ void Patch_SA_10(HINSTANCE hInstance)
Patch<const void*>(0x6D5612 + 2, &LightStatusRandomnessThreshold);
}
// Fixed vehicles exploding twice if the driver leaves the car while it's exploding
{
using namespace RemoveDriverStatusFix;
Nop(0x6D1955, 2);
InjectHook(0x6D1955 + 2, RemoveDriver_SetStatus, HookType::Call);
InterceptCall(0x64C8CE, orgPrepareVehicleForPedExit, PrepareVehicleForPedExit_WreckedCheck);
// CVehicle::RemoveDriver already sets the status to STATUS_ABANDONED, these are redundant
Nop(0x48628D, 3);
Nop(0x647E21, 3);
}
#if FULL_PRECISION_D3D
// Test - full precision D3D device
Patch<uint8_t>( 0x7F672B+1, *(uint8_t*)(0x7F672B+1) | D3DCREATE_FPU_PRESERVE );
@ -6900,6 +6948,26 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
static const double LightStatusRandomnessThreshold = 25000.0;
Patch<const void*>(getVehicleLightsStatus, &LightStatusRandomnessThreshold);
}
// Fixed vehicles exploding twice if the driver leaves the car while it's exploding
{
using namespace RemoveDriverStatusFix;
auto removeDriver = pattern("8A 47 36 24 07 0C 20 80 7D 08 00").get_one();
auto removeThisPed = get_pattern("80 C9 20 88 48 36 8B 96", 3);
auto taskSimpleCarSetPedOut = get_pattern("80 C9 20 88 48 36 8B 86", 3);
auto prepareVehicleForPedExit = get_pattern("57 E8 ? ? ? ? 57 8B CE E8 ? ? ? ? 57", 1);
Nop(removeDriver.get<void>(), 2);
InjectHook(removeDriver.get<void>(2), RemoveDriver_SetStatus, HookType::Call);
InterceptCall(prepareVehicleForPedExit, orgPrepareVehicleForPedExit, PrepareVehicleForPedExit_WreckedCheck);
// CVehicle::RemoveDriver already sets the status to STATUS_ABANDONED, these are redundant
Nop(removeThisPed, 3);
Nop(taskSimpleCarSetPedOut, 3);
}
}

View file

@ -449,6 +449,31 @@ namespace FBISirenCoronaFix
}
}
// ============= Fixed vehicles exploding twice if the driver leaves the car while it's exploding =============
namespace RemoveDriverStatusFix
{
__declspec(naked) void RemoveDriver_SetStatus()
{
// if (m_nStatus != STATUS_WRECKED)
// m_nStatus = STATUS_ABANDONED;
_asm
{
mov cl, [ebx+50h]
mov al, cl
and cl, 0F8h
cmp cl, 28h
je DontSetStatus
and al, 7
or al, 20h
DontSetStatus:
retn
}
}
}
void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
{
using namespace Memory;
@ -1158,6 +1183,27 @@ void Patch_VC_Common()
Patch( getDriverOneShot.get<void>( -8 ), { 0x90, 0x89, 0xD9 } );
InjectHook( getDriverOneShot.get<void>( -5 ), &CVehicle::GetOneShotOwnerID_SilentPatch, HookType::Call );
}
// Fixed vehicles exploding twice if the driver leaves the car while it's exploding
{
using namespace RemoveDriverStatusFix;
auto removeDriver = pattern("8A 43 50 24 07 0C 20 88 43 50 E8").get_one();
auto processCommands1 = get_pattern("88 42 50 8B 33");
auto processCommands2 = get_pattern("88 42 50 8B AE");
auto removeThisPed = get_pattern("88 42 50 8B 85");
auto pedSetOutCar = get_pattern("0C 20 88 47 50 8B 85", 2);
Nop(removeDriver.get<void>(), 2);
InjectHook(removeDriver.get<void>(2), RemoveDriver_SetStatus, HookType::Call);
// CVehicle::RemoveDriver already sets the status to STATUS_ABANDONED, these are redundant
Nop(processCommands1, 3);
Nop(processCommands2, 3);
Nop(removeThisPed, 3);
Nop(pedSetOutCar, 3);
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)