Skip to content

Commit 9617517

Browse files
saml1ercodenulls
andauthored
Workaround for custom map collision crashes (#1613)
* Potentional fix for custom maps crashes * properly set hooks * some improvements suggested in PR review * indentation fixes * Add useful comments to CRect * Fix purpose in copyright comment Co-authored-by: saml1er <[email protected]>
1 parent 1d84fae commit 9617517

File tree

12 files changed

+198
-33
lines changed

12 files changed

+198
-33
lines changed

Client/game_sa/CEntitySA.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,44 @@ extern CGameSA* pGame;
1616
unsigned long CEntitySA::FUNC_CClumpModelInfo__GetFrameFromId;
1717
unsigned long CEntitySA::FUNC_RwFrameGetLTM;
1818

19+
void CEntitySAInterface::TransformFromObjectSpace(CVector& outPosn, CVector const& offset)
20+
{
21+
((void(__thiscall*)(CEntitySAInterface*, CVector&, CVector const&))0x533560)(this, outPosn, offset);
22+
}
23+
24+
CVector* CEntitySAInterface::GetBoundCentre(CVector* pOutCentre)
25+
{
26+
return ((CVector * (__thiscall*)(CEntitySAInterface*, CVector*))0x534250)(this, pOutCentre);
27+
}
28+
29+
CRect* CEntitySAInterface::GetBoundRect_(CRect* pRect)
30+
{
31+
CColModelSAInterface* colModel = CModelInfoSAInterface::GetModelInfo(m_nModelIndex)->pColModel;
32+
CVector vecMin = colModel->boundingBox.vecMin;
33+
CVector vecMax = colModel->boundingBox.vecMax;
34+
CRect rect;
35+
CVector point;
36+
TransformFromObjectSpace(point, vecMin);
37+
rect.StretchToPoint(point.fX, point.fY);
38+
TransformFromObjectSpace(point, vecMax);
39+
rect.StretchToPoint(point.fX, point.fY);
40+
float maxX = vecMax.fX;
41+
vecMax.fX = vecMin.fX;
42+
vecMin.fX = maxX;
43+
TransformFromObjectSpace(point, vecMin);
44+
rect.StretchToPoint(point.fX, point.fY);
45+
TransformFromObjectSpace(point, vecMax);
46+
rect.StretchToPoint(point.fX, point.fY);
47+
*pRect = rect;
48+
pRect->FixIncorrectTopLeft(); // Fix #1613: custom map collision crashes in CPhysical class (infinite loop)
49+
return pRect;
50+
}
51+
52+
void CEntitySAInterface::StaticSetHooks()
53+
{
54+
HookInstall(0x534120, &CEntitySAInterface::GetBoundRect_);
55+
}
56+
1957
CEntitySA::CEntitySA()
2058
{
2159
// Set these variables to a constant state

Client/game_sa/CEntitySA.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
// not in CEntity really
3434
#define FUNC_RpAnimBlendClumpGetAssociation 0x4D6870
3535

36+
class CRect;
3637
class CEntitySAInterfaceVTBL
3738
{
3839
public:
@@ -193,6 +194,11 @@ class CEntitySAInterface
193194

194195
uint8 m_pad0; // 55
195196

197+
CRect* GetBoundRect_(CRect* pRect);
198+
void TransformFromObjectSpace(CVector& outPosn, CVector const& offset);
199+
CVector* GetBoundCentre(CVector* pOutCentre);
200+
static void StaticSetHooks();
201+
196202
//
197203
// Functions to hide member variable misuse
198204
//
@@ -227,13 +233,12 @@ class CEntitySA : public virtual CEntity
227233
friend class COffsets;
228234

229235
public:
230-
CEntitySA();
231-
232236
CEntitySAInterface* m_pInterface;
233237

234238
DWORD internalID;
235239
// VOID SetModelAlpha ( int iAlpha );
236240

241+
CEntitySA();
237242
CEntitySAInterface* GetInterface() { return m_pInterface; };
238243
VOID SetInterface(CEntitySAInterface* intInterface) { m_pInterface = intInterface; };
239244

Client/game_sa/CGameSA.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ CGameSA::CGameSA()
200200
// Increase matrix array size
201201
MemPut<int>(0x054F3A1, MAX_OBJECTS * 3); // Default is 900
202202

203+
CEntitySAInterface::StaticSetHooks();
204+
CPhysicalSAInterface::StaticSetHooks();
203205
CModelInfoSA::StaticSetHooks();
204206
CPlayerPedSA::StaticSetHooks();
205207
CRenderWareSA::StaticSetHooks();

Client/game_sa/CModelInfoSA.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
extern CGameSA* pGame;
1616

17+
CBaseModelInfoSAInterface** CModelInfoSAInterface::ms_modelInfoPtrs = (CBaseModelInfoSAInterface**)0xA9B0C8;
1718
CBaseModelInfoSAInterface** ppModelInfo = (CBaseModelInfoSAInterface**)ARRAY_ModelInfo;
1819

1920
std::map<unsigned short, int> CModelInfoSA::ms_RestreamTxdIDMap;

Client/game_sa/CModelInfoSA.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,18 @@ class CPedModelInfoSAInterface;
6565
#define FUNC_SetColModel 0x4C4BC0
6666
#define FUNC_AddPedModel 0x4c67a0
6767
#define VAR_CTempColModels_ModelPed1 0x968DF0
68-
/**
68+
69+
70+
class CBaseModelInfoSAInterface;
71+
class CModelInfoSAInterface
72+
{
73+
public:
74+
// Use GetModelInfo(int index) to get model info by id
75+
static CBaseModelInfoSAInterface** ms_modelInfoPtrs;
76+
static CBaseModelInfoSAInterface* GetModelInfo(int index) { return ms_modelInfoPtrs[index]; }
77+
};
78+
79+
/**
6980
* \todo Fill this class with info from R*
7081
*/
7182
class CBaseModelInfo_SA_VTBL

Client/game_sa/CPhysicalSA.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,21 @@
1111

1212
#include "StdInc.h"
1313

14+
CRect* CPhysicalSAInterface::GetBoundRect_(CRect* pRect)
15+
{
16+
CVector boundCentre;
17+
CEntitySAInterface::GetBoundCentre(&boundCentre);
18+
float fRadius = CModelInfoSAInterface::GetModelInfo(m_nModelIndex)->pColModel->boundingBox.fRadius;
19+
*pRect = CRect(boundCentre.fX - fRadius, boundCentre.fY - fRadius, boundCentre.fX + fRadius, boundCentre.fY + fRadius);
20+
pRect->FixIncorrectTopLeft(); // Fix #1613: custom map collision crashes in CPhysical class (infinite loop)
21+
return pRect;
22+
}
23+
24+
void CPhysicalSAInterface::StaticSetHooks()
25+
{
26+
HookInstall(0x5449B0, &CPhysicalSAInterface::GetBoundRect_);
27+
}
28+
1429
void CPhysicalSA::RestoreLastGoodPhysicsState()
1530
{
1631
CEntitySA::RestoreLastGoodPhysicsState();

Client/game_sa/CPhysicalSA.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ class CPhysicalSAInterface : public CEntitySAInterface
106106
float m_fLighting; // 300
107107
float m_fLighting2; // 304
108108
class CShadowDataSA* m_pShadowData; // 308
109+
110+
CRect* GetBoundRect_(CRect* pRect);
111+
static void StaticSetHooks();
109112
};
110113
static_assert(sizeof(CPhysicalSAInterface) == 0x138, "Invalid size for CPhysicalSAInterface");
111114

Client/game_sa/CRadarSA.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -175,20 +175,11 @@ VOID CRadarSA::ClearMarkerForEntity(CPed* ped)
175175
}
176176
}
177177

178-
struct CRect
179-
{
180-
float fX1, fY1, fX2, fY2;
181-
};
182-
183178
VOID CRadarSA::DrawAreaOnRadar(float fX1, float fY1, float fX2, float fY2, const SColor color)
184179
{
185180
// Convert color to required abgr at the last moment
186181
unsigned long abgr = color.A << 24 | color.B << 16 | color.G << 8 | color.R;
187-
CRect myRect;
188-
myRect.fX1 = fX1;
189-
myRect.fY1 = fY1;
190-
myRect.fX2 = fX2;
191-
myRect.fY2 = fY2;
182+
CRect myRect(fX1, fY1, fX2, fY2);
192183
DWORD dwFunc = FUNC_DrawAreaOnRadar;
193184
_asm
194185
{

Client/game_sa/HookSystem.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,6 @@
1111

1212
#include "StdInc.h"
1313

14-
//
15-
////////////////////////////////////////////////////////////////////
16-
17-
BOOL HookInstall(DWORD dwInstallAddress, DWORD dwHookHandler, int iJmpCodeSize)
18-
{
19-
BYTE JumpBytes[MAX_JUMPCODE_SIZE];
20-
MemSetFast(JumpBytes, 0x90, MAX_JUMPCODE_SIZE);
21-
if (CreateJump(dwInstallAddress, dwHookHandler, JumpBytes))
22-
{
23-
MemCpy((PVOID)dwInstallAddress, JumpBytes, iJmpCodeSize);
24-
return TRUE;
25-
}
26-
else
27-
{
28-
return FALSE;
29-
}
30-
}
31-
32-
////////////////////////////////////////////////////////////////////
3314

3415
BYTE* CreateJump(DWORD dwFrom, DWORD dwTo, BYTE* ByteArray)
3516
{

Client/game_sa/HookSystem.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,33 @@
1616

1717
#define MAX_JUMPCODE_SIZE 20
1818

19-
BOOL HookInstall(DWORD dwInstallAddress, DWORD dwHookHandler, int iJmpCodeSize);
19+
template <typename T>
20+
void* FunctionPointerToVoidP(T func)
21+
{
22+
union
23+
{
24+
T a;
25+
void* b;
26+
} c = {func};
27+
return c.b;
28+
}
29+
30+
template <typename T>
31+
BOOL HookInstall(DWORD dwInstallAddress, T dwHookHandler, int iJmpCodeSize = 5)
32+
{
33+
BYTE JumpBytes[MAX_JUMPCODE_SIZE];
34+
MemSetFast(JumpBytes, 0x90, MAX_JUMPCODE_SIZE);
35+
if (CreateJump(dwInstallAddress, (DWORD)FunctionPointerToVoidP(dwHookHandler), JumpBytes))
36+
{
37+
MemCpy((PVOID)dwInstallAddress, JumpBytes, iJmpCodeSize);
38+
return TRUE;
39+
}
40+
else
41+
{
42+
return FALSE;
43+
}
44+
}
45+
2046
BYTE* CreateJump(DWORD dwFrom, DWORD dwTo, BYTE* ByteArray);
2147

2248
// Auto detect requirement of US/EU hook installation

0 commit comments

Comments
 (0)