Skip to content

Commit 2df1c14

Browse files
committed
Addendum to a9be1ec - it's more complex than it seemed, .. (read below)
20a14e8 exposed previously hidden GTA bugs that are correlated to BLOCKING_LOAD states. As it turns out, the whole "Blocking load" workaround concept across the codebase is primarily to avoid freezes, and these "Susoension lines / vehicle handling" code sites are at the roots of it, and yet they were always still causing game freezes. I'm slowly addressing it, this and a9be1ec is part of it, im still to go deeper, but these 2 commits should at least allow for more blocking/non blocking load manipulation as they'd be the first underlying issues to hit, and should now be resolved.
1 parent b7362a0 commit 2df1c14

File tree

4 files changed

+58
-9
lines changed

4 files changed

+58
-9
lines changed

Client/game_sa/CModelInfoSA.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1280,11 +1280,15 @@ unsigned int CModelInfoSA::GetNumRemaps()
12801280

12811281
void* CModelInfoSA::GetVehicleSuspensionData()
12821282
{
1283+
if (!GetInterface()->pColModel || !GetInterface()->pColModel->m_data)
1284+
return nullptr;
12831285
return GetInterface()->pColModel->m_data->m_suspensionLines;
12841286
}
12851287

12861288
void* CModelInfoSA::SetVehicleSuspensionData(void* pSuspensionLines)
12871289
{
1290+
if (!GetInterface()->pColModel || !GetInterface()->pColModel->m_data)
1291+
return nullptr;
12881292
CColDataSA* pColData = GetInterface()->pColModel->m_data;
12891293
void* pOrigSuspensionLines = pColData->m_suspensionLines;
12901294
pColData->m_suspensionLines = reinterpret_cast<CColLineSA*>(pSuspensionLines);
@@ -1617,7 +1621,7 @@ void CModelInfoSA::RestoreColModel()
16171621

16181622
// Force the game to load the original collision model data, if we applied a custom collision model before
16191623
// there was any object/building, which would've provoked CColStore to request it.
1620-
if (!m_pInterface->pColModel->m_data && m_dwReferences > 1)
1624+
if (m_pInterface->pColModel && !m_pInterface->pColModel->m_data && m_dwReferences > 1)
16211625
{
16221626
pGame->GetStreaming()->RemoveModel(RESOURCE_ID_COL + m_pInterface->pColModel->m_sphere.m_collisionSlot);
16231627
}

Client/game_sa/CPhysicalSA.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@ CRect* CPhysicalSAInterface::GetBoundRect_(CRect* pRect)
2222
{
2323
CVector boundCentre;
2424
CEntitySAInterface::GetBoundCentre(&boundCentre);
25-
float fRadius = CModelInfoSAInterface::GetModelInfo(m_nModelIndex)->pColModel->m_sphere.m_radius;
25+
CBaseModelInfoSAInterface* pModelInfo = CModelInfoSAInterface::GetModelInfo(m_nModelIndex);
26+
27+
if (!pModelInfo || !pModelInfo->pColModel)
28+
return pRect;
29+
30+
float fRadius = pModelInfo->pColModel->m_sphere.m_radius;
2631
*pRect = CRect(boundCentre.fX - fRadius, boundCentre.fY - fRadius, boundCentre.fX + fRadius, boundCentre.fY + fRadius);
27-
pRect->FixIncorrectTopLeft(); // Fix #1613: custom map collision crashes in CPhysical class (infinite loop)
32+
pRect->FixIncorrectTopLeft(); // Fix #1613: custom map collision crashes in CPhysical class (infinite loop)
2833
return pRect;
2934
}
3035

Client/game_sa/CVehicleSA.cpp

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,10 +1350,21 @@ CFlyingHandlingEntry* CVehicleSA::GetFlyingHandlingData()
13501350

13511351
void CVehicleSA::SetHandlingData(CHandlingEntry* pHandling)
13521352
{
1353+
if (!pHandling)
1354+
return;
1355+
1356+
CVehicleSAInterface* pVehicleInterface = GetVehicleInterface();
1357+
if (!pVehicleInterface)
1358+
return;
1359+
13531360
// Store the handling and recalculate it
13541361
m_pHandlingData = static_cast<CHandlingEntrySA*>(pHandling);
1355-
GetVehicleInterface()->pHandlingData = m_pHandlingData->GetInterface();
1356-
RecalculateHandling();
1362+
pVehicleInterface->pHandlingData = m_pHandlingData->GetInterface();
1363+
1364+
// Only recalculate if collision model is loaded (needed for suspension lines)
1365+
CModelInfo* pModelInfo = pGame->GetModelInfo(GetModelIndex());
1366+
if (pModelInfo && pModelInfo->GetInterface()->pColModel && pModelInfo->GetInterface()->pColModel->m_data)
1367+
RecalculateHandling();
13571368
}
13581369

13591370
void CVehicleSA::SetFlyingHandlingData(CFlyingHandlingEntry* pFlyingHandling)
@@ -1369,13 +1380,24 @@ void CVehicleSA::RecalculateHandling()
13691380
if (!m_pHandlingData)
13701381
return;
13711382

1383+
// Validate vehicle interface
1384+
CVehicleSAInterface* pInt = GetVehicleInterface();
1385+
if (!pInt)
1386+
return;
1387+
1388+
// Ensure collision model is loaded before recalculating (needed for suspension lines)
1389+
CModelInfo* pModelInfo = pGame->GetModelInfo(GetModelIndex());
1390+
if (!pModelInfo || !pModelInfo->GetInterface()->pColModel || !pModelInfo->GetInterface()->pColModel->m_data)
1391+
return;
1392+
13721393
m_pHandlingData->Recalculate();
13731394

1374-
// Recalculate the suspension lines
1375-
RecalculateSuspensionLines();
1395+
// Recalculate the suspension lines (only for vehicles that have suspension)
1396+
// Already validated that pColModel and m_data exist above
1397+
if (pModelInfo->IsCar() || pModelInfo->IsMonsterTruck() || pModelInfo->IsTrailer() || pModelInfo->IsBike())
1398+
RecalculateSuspensionLines();
13761399

13771400
// Put it in our interface
1378-
CVehicleSAInterface* pInt = GetVehicleInterface();
13791401
unsigned int uiHandlingFlags = m_pHandlingData->GetInterface()->uiHandlingFlags;
13801402
bool hydralicsInstalled = false, nitroInstalled = false;
13811403

@@ -1758,6 +1780,11 @@ void* CVehicleSA::GetPrivateSuspensionLines()
17581780
if (m_pSuspensionLines == NULL)
17591781
{
17601782
CModelInfo* pModelInfo = pGame->GetModelInfo(GetModelIndex());
1783+
// pColModel can be NULL if collision data hasn't been streamed in yet.
1784+
// GTA SA loads visual models and collision models separately via CColStore.
1785+
// The model can be marked as "loaded" even if collision data is still pending.
1786+
if (!pModelInfo->GetInterface()->pColModel || !pModelInfo->GetInterface()->pColModel->m_data)
1787+
return NULL;
17611788
CColDataSA* pColData = pModelInfo->GetInterface()->pColModel->m_data;
17621789
if (pModelInfo->IsMonsterTruck())
17631790
{
@@ -1782,6 +1809,9 @@ void* CVehicleSA::GetPrivateSuspensionLines()
17821809
void CVehicleSA::CopyGlobalSuspensionLinesToPrivate()
17831810
{
17841811
CModelInfo* pModelInfo = pGame->GetModelInfo(GetModelIndex());
1812+
// Collision model may not be loaded yet (see GetPrivateSuspensionLines)
1813+
if (!pModelInfo->GetInterface()->pColModel || !pModelInfo->GetInterface()->pColModel->m_data)
1814+
return;
17851815
CColDataSA* pColData = pModelInfo->GetInterface()->pColModel->m_data;
17861816
if (pModelInfo->IsMonsterTruck())
17871817
{
@@ -1815,8 +1845,14 @@ void CVehicleSA::RecalculateSuspensionLines()
18151845
if (pModelInfo->IsTrain() || dwModel == 571 || dwModel == 570 || dwModel == 569 || dwModel == 590)
18161846
return;
18171847

1818-
GetVehicleInterface()->SetupSuspensionLines();
1848+
// Ensure collision model is loaded before setting up suspension
1849+
if (!pModelInfo->GetInterface()->pColModel || !pModelInfo->GetInterface()->pColModel->m_data)
1850+
return;
18191851

1852+
// Note: We skip calling SetupSuspensionLines() because it's GTA SA's native code that can
1853+
// access pColModel->m_data without validation. If collision model is unloaded during execution
1854+
// (race condition), it causes crashes. CopyGlobalSuspensionLinesToPrivate() is safer as it
1855+
// validates collision model before accessing.
18201856
CopyGlobalSuspensionLinesToPrivate();
18211857
}
18221858
}

Client/mods/deathmatch/logic/CClientVehicle.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4305,6 +4305,10 @@ void CClientVehicle::ApplyHandling()
43054305
if (!pModelInfo || !pModelInfo->IsLoaded())
43064306
return;
43074307

4308+
// Ensure collision model is loaded before recalculating (needed for suspension lines)
4309+
if (!pModelInfo->GetInterface()->pColModel || !pModelInfo->GetInterface()->pColModel->m_data)
4310+
return;
4311+
43084312
m_pVehicle->RecalculateHandling();
43094313

43104314
if (m_eVehicleType == CLIENTVEHICLE_BMX || m_eVehicleType == CLIENTVEHICLE_BIKE)

0 commit comments

Comments
 (0)