1818#include " CPtrNodeSingleListSA.h"
1919#include " MemSA.h"
2020#include " CVehicleSA.h"
21+ #include " CBuildingRemovalSA.h"
2122
2223extern CGameSA* pGame;
2324
@@ -48,7 +49,17 @@ inline bool CBuildingsPoolSA::AddBuildingToPool(CClientBuilding* pClientBuilding
4849 return true ;
4950}
5051
51- CBuilding* CBuildingsPoolSA::AddBuilding (CClientBuilding* pClientBuilding, uint16_t modelId, CVector* vPos, CVector4D* vRot, uint8_t interior)
52+ CClientEntity* CBuildingsPoolSA::GetClientBuilding (CBuildingSAInterface* pGameInterface) const noexcept
53+ {
54+ std::uint32_t poolIndex = (*m_ppBuildingPoolInterface)->GetObjectIndexSafe (pGameInterface);
55+
56+ if (poolIndex == static_cast <std::uint32_t >(-1 ))
57+ return nullptr ;
58+
59+ return m_buildingPool.entities [poolIndex].pClientEntity ;
60+ }
61+
62+ CBuilding* CBuildingsPoolSA::AddBuilding (CClientBuilding* pClientBuilding, uint16_t modelId, CVector* vPos, CVector* vRot, uint8_t interior)
5263{
5364 if (!HasFreeBuildingSlot ())
5465 return nullptr ;
@@ -61,15 +72,12 @@ CBuilding* CBuildingsPoolSA::AddBuilding(CClientBuilding* pClientBuilding, uint1
6172 modelInfo->SetObjectPropertiesGroup (MODEL_PROPERTIES_GROUP_STATIC);
6273
6374 // Load building
64- SFileObjectInstance instance;
75+ SFileObjectInstance instance{} ;
6576 instance.modelID = modelId;
6677 instance.lod = -1 ;
6778 instance.interiorID = interior;
6879 instance.position = *vPos;
69- instance.rotation = *vRot;
70-
71- // Fix strange SA rotation
72- instance.rotation .fW = -instance.rotation .fW ;
80+ instance.rotation = {};
7381
7482 auto pBuilding = static_cast <CBuildingSAInterface*>(CFileLoaderSA::LoadObjectInstance (&instance));
7583
@@ -87,6 +95,22 @@ CBuilding* CBuildingsPoolSA::AddBuilding(CClientBuilding* pClientBuilding, uint1
8795
8896 // Add building in world
8997 auto pBuildingSA = new CBuildingSA (pBuilding);
98+
99+ if (pBuilding->HasMatrix ())
100+ {
101+ // Edge case for the traincross2 (1374) model
102+ // LoadObjectInstance allocates a matrix for the model
103+ // We need allocate our own matrix and put the old matrix in the original pool
104+ pBuildingSA->ReallocateMatrix ();
105+ }
106+ else if (vRot->fX != 0 || vRot->fY != 0 )
107+ {
108+ // Allocate matrix in our unlimited storage instead of using the shared pool.
109+ pBuildingSA->AllocateMatrix ();
110+ }
111+
112+ pBuilding->SetOrientation (vRot->fX , vRot->fY , vRot->fZ );
113+
90114 pGame->GetWorld ()->Add (pBuildingSA, CBuildingPool_Constructor);
91115
92116 // Add CBuildingSA object in pool
@@ -105,6 +129,10 @@ void CBuildingsPoolSA::RemoveBuilding(CBuilding* pBuilding)
105129 if (dwElementIndexInPool == UINT_MAX)
106130 return ;
107131
132+ // Remove references to allocated matrix
133+ auto * pBuildingSA = m_buildingPool.entities [dwElementIndexInPool].pEntity ;
134+ pBuildingSA->RemoveAllocatedMatrix ();
135+
108136 // Remove building from cover list
109137 pGame->GetCoverManager ()->RemoveCover (pInterface);
110138
@@ -117,23 +145,24 @@ void CBuildingsPoolSA::RemoveBuilding(CBuilding* pBuilding)
117145 // Remove building from world
118146 pGame->GetWorld ()->Remove (pInterface, CBuildingPool_Destructor);
119147
148+ std::uint16_t modelId = pInterface->m_nModelIndex ;
149+
120150 // Call virtual destructor
121151 ((void *(__thiscall*)(void *, char ))pInterface->vtbl ->SCALAR_DELETING_DESTRUCTOR )(pInterface, 0 );
122152
123153 // Remove col reference
124- auto modelInfo = pGame->GetModelInfo (pBuilding-> GetModelIndex () );
154+ auto modelInfo = pGame->GetModelInfo (modelId );
125155 modelInfo->RemoveColRef ();
126156
157+ // Remove building from SA pool
158+ (*m_ppBuildingPoolInterface)->Release (dwElementIndexInPool);
159+
127160 // Remove from BuildingSA pool
128- auto * pBuildingSA = m_buildingPool.entities [dwElementIndexInPool].pEntity ;
129161 m_buildingPool.entities [dwElementIndexInPool] = {nullptr , nullptr };
130162
131163 // Delete it from memory
132164 delete pBuildingSA;
133165
134- // Remove building from SA pool
135- (*m_ppBuildingPoolInterface)->Release (dwElementIndexInPool);
136-
137166 // Decrease the count of elements in the pool
138167 --m_buildingPool.count ;
139168}
@@ -174,6 +203,9 @@ void CBuildingsPoolSA::RestoreBackup()
174203 if (!m_pOriginalBuildingsBackup)
175204 return ;
176205
206+ auto * worldSA = pGame->GetWorld ();
207+ auto * buildingRemovealSA = static_cast <CBuildingRemovalSA*>(pGame->GetBuildingRemoval ());
208+
177209 auto & originalData = *m_pOriginalBuildingsBackup;
178210 auto pBuildsingsPool = (*m_ppBuildingPoolInterface);
179211 for (size_t i = 0 ; i < MAX_BUILDINGS; i++)
@@ -184,7 +216,8 @@ void CBuildingsPoolSA::RestoreBackup()
184216 auto pBuilding = pBuildsingsPool->GetObject (i);
185217 *pBuilding = originalData[i].second ;
186218
187- pGame->GetWorld ()->Add (pBuilding, CBuildingPool_Constructor);
219+ worldSA->Add (pBuilding, CBuildingPool_Constructor);
220+ buildingRemovealSA->AddDataBuilding (pBuilding);
188221 }
189222 }
190223
0 commit comments