Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9617517

Browse files
saml1ercodenulls
saml1er
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 <danishroar@gmail.com>
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)

AltStyle によって変換されたページ (->オリジナル) /