Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Client/game_sa/CModelInfoSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "CModelInfoSA.h"
#include "CPedModelInfoSA.h"
#include "CPedSA.h"
#include "CPoolsSA.h"
#include "CWorldSA.h"
#include "gamesa_renderware.h"

Expand Down Expand Up @@ -1962,6 +1963,9 @@ void CModelInfoSA::DeallocateModel(void)
switch (GetModelType())
{
case eModelInfoType::VEHICLE:
// Stop detached car parts referencing this model (they keep their source vehicle's
// model index for repainting, and would dereference the freed model info)
static_cast<CPoolsSA*>(pGame->GetPools())->ResetDetachedCarPartsRefModel(static_cast<std::uint16_t>(m_dwModelID));
delete reinterpret_cast<CVehicleModelInfoSAInterface*>(ppModelInfo[m_dwModelID]);
break;
case eModelInfoType::PED:
Expand Down
4 changes: 2 additions & 2 deletions Client/game_sa/CObjectSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class CObjectSAInterface : public CPhysicalSAInterface
uint32 b0x10 : 1;
uint32 b0x20 : 1;
uint32 bExploded : 1;
uint32 b0x80 : 1;
uint32 bChangesVehColor : 1; // Detached car part that gets repainted with its source vehicle's colours when rendered

uint32 b0x100 : 1; // 321
uint32 b0x200 : 1;
Expand Down Expand Up @@ -98,7 +98,7 @@ class CObjectSAInterface : public CPhysicalSAInterface
uint8 pad6; // 327
uint8 pad7; // 328
uint8 pad8; // 329
uint16 pad9; // 330
short sRefModelIndex; // 330 Model of the vehicle a detached car part came from (-1 = none)
uint8 pad10; // 332
uint8 pad11; // 333
uint8 pad12; // 334
Expand Down
24 changes: 24 additions & 0 deletions Client/game_sa/CPoolsSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,30 @@ void CPoolsSA::DeleteAllObjects()
}
}

//
// Detached car parts (e.g. doors spawned by CAutomobile::SpawnFlyingComponent) keep the model
// index of the vehicle they came from, so CObject::Render can repaint them with that vehicle's
// colours and CObject's destructor can release its model reference. Called when a vehicle model
// info is deallocated, so the parts can't dereference the freed model info anymore.
//
void CPoolsSA::ResetDetachedCarPartsRefModel(std::uint16_t usModelID) noexcept
{
CPoolSAInterface<CObjectSAInterface>* pObjectPool = *m_ppObjectPoolInterface;

for (int i = 0; i < pObjectPool->m_nSize; i++)
{
if (pObjectPool->IsEmpty(i))
continue;

CObjectSAInterface* pObject = pObjectPool->GetObject(i);
if (pObject->sRefModelIndex == static_cast<short>(usModelID))
{
pObject->sRefModelIndex = -1;
pObject->bChangesVehColor = false;
}
}
}

//////////////////////////////////////////////////////////////////////////////////////////
// PEDS POOL //
//////////////////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 2 additions & 0 deletions Client/game_sa/CPoolsSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ class CPoolsSA : public CPools
DWORD GetVehiclePoolIndex(std::uint8_t* pInterfacee);
DWORD GetObjectPoolIndex(std::uint8_t* pInterface);

void ResetDetachedCarPartsRefModel(std::uint16_t usModelID) noexcept;

int GetNumberOfUsedSpaces(ePools pools);
int GetPoolDefaultCapacity(ePools pool);
int GetPoolDefaultModdedCapacity(ePools pool);
Expand Down