@@ -35,6 +35,7 @@ std::map<CTimeInfoSAInterface*, CTimeInfoSAInterface*> CModelInfo
3535std::unordered_map<DWORD, unsigned short > CModelInfoSA::ms_OriginalObjectPropertiesGroups;
3636std::unordered_map<DWORD, std::pair<float , float >> CModelInfoSA::ms_VehicleModelDefaultWheelSizes;
3737std::map<unsigned short , int > CModelInfoSA::ms_DefaultTxdIDMap;
38+ std::unordered_map<std::uint32_t , CBaseModelInfoSAInterface*> CModelInfoSA::m_convertedModelInterfaces;
3839
3940union tIdeFlags
4041{
@@ -1512,6 +1513,7 @@ bool CModelInfoSA::SetCustomModel(RpClump* pClump)
15121513 case eModelInfoType::ATOMIC:
15131514 case eModelInfoType::LOD_ATOMIC:
15141515 case eModelInfoType::TIME:
1516+ case eModelInfoType::CLUMP:
15151517 success = pGame->GetRenderWare ()->ReplaceAllAtomicsInModel (pClump, static_cast <unsigned short >(m_dwModelID));
15161518 break ;
15171519 default :
@@ -1530,6 +1532,16 @@ void CModelInfoSA::RestoreOriginalModel()
15301532 pGame->GetStreaming ()->RemoveModel (m_dwModelID);
15311533 }
15321534
1535+ // Restore original interface if model was converted
1536+ if (MapContains (m_convertedModelInterfaces, m_dwModelID))
1537+ {
1538+ CBaseModelInfoSAInterface* currentInterface = ppModelInfo[m_dwModelID];
1539+ ppModelInfo[m_dwModelID] = MapGet (m_convertedModelInterfaces, m_dwModelID);
1540+
1541+ delete currentInterface;
1542+ MapRemove (m_convertedModelInterfaces, m_dwModelID);
1543+ }
1544+
15331545 // Reset the stored custom vehicle clump
15341546 m_pCustomClump = NULL ;
15351547}
@@ -1799,6 +1811,73 @@ void CModelInfoSA::MakeClumpModel(ushort usBaseID)
17991811 CopyStreamingInfoFromModel (usBaseID);
18001812}
18011813
1814+ bool CModelInfoSA::ConvertToClump ()
1815+ {
1816+ if (GetModelType () != eModelInfoType::ATOMIC)
1817+ return false ;
1818+
1819+ // Get current interface
1820+ CAtomicModelInfoSAInterface* currentAtomicInterface = static_cast <CAtomicModelInfoSAInterface*>(ppModelInfo[m_dwModelID]);
1821+ if (!currentAtomicInterface)
1822+ return false ;
1823+
1824+ // Create new clump interface
1825+ CClumpModelInfoSAInterface* newClumpInterface = new CClumpModelInfoSAInterface ();
1826+ MemCpyFast (newClumpInterface, currentAtomicInterface, sizeof (CClumpModelInfoSAInterface));
1827+ newClumpInterface->m_nAnimFileIndex = -1 ;
1828+
1829+ // (FileEX): We do not destroy or set pRwObject to nullptr here
1830+ // because our IsLoaded code expects the RwObject to exist.
1831+ // We destroy the old RwObject in CRenderWareSA::ReplaceAllAtomicsInModel after passing the IsLoaded condition in the SetCustomModel.
1832+
1833+ // Set CClumpModelInfo vtbl after copying data
1834+ newClumpInterface->VFTBL = reinterpret_cast <CBaseModelInfo_SA_VTBL*>(VTBL_CClumpModelInfo);
1835+
1836+ // Set new interface for ModelInfo
1837+ ppModelInfo[m_dwModelID] = newClumpInterface;
1838+
1839+ // Store original interface
1840+ MapSet (m_convertedModelInterfaces, m_dwModelID, static_cast <CBaseModelInfoSAInterface*>(currentAtomicInterface));
1841+ return true ;
1842+ }
1843+
1844+ bool CModelInfoSA::ConvertToAtomic ()
1845+ {
1846+ if (GetModelType () != eModelInfoType::CLUMP)
1847+ return false ;
1848+
1849+ // Get current interface
1850+ CClumpModelInfoSAInterface* currentClumpInterface = static_cast <CClumpModelInfoSAInterface*>(ppModelInfo[m_dwModelID]);
1851+ if (!currentClumpInterface)
1852+ return false ;
1853+
1854+ // Create new atomic interface
1855+ CAtomicModelInfoSAInterface* newAtomicInterface = new CAtomicModelInfoSAInterface ();
1856+ MemCpyFast (newAtomicInterface, currentClumpInterface, sizeof (CAtomicModelInfoSAInterface));
1857+
1858+ // (FileEX): We do not destroy or set pRwObject to nullptr here
1859+ // because our IsLoaded code expects the RwObject to exist.
1860+ // We destroy the old RwObject in CFileLoader_SetRelatedModelInfoCB after passing the IsLoaded condition in the SetCustomModel.
1861+
1862+ // Set CAtomicModelInfo vtbl after copying data
1863+ newAtomicInterface->VFTBL = reinterpret_cast <CBaseModelInfo_SA_VTBL*>(VTBL_CAtomicModelInfo);
1864+
1865+ // Set new interface for ModelInfo
1866+ ppModelInfo[m_dwModelID] = newAtomicInterface;
1867+
1868+ // Store original interface
1869+ MapSet (m_convertedModelInterfaces, m_dwModelID, currentClumpInterface);
1870+ return true ;
1871+ }
1872+
1873+ CBaseModelInfoSAInterface* CModelInfoSA::GetOriginalInterface () const
1874+ {
1875+ if (!MapContains (m_convertedModelInterfaces, m_dwModelID))
1876+ return nullptr ;
1877+
1878+ return MapGet (m_convertedModelInterfaces, m_dwModelID);
1879+ }
1880+
18021881void CModelInfoSA::MakeVehicleAutomobile (ushort usBaseID)
18031882{
18041883 CVehicleModelInfoSAInterface* m_pInterface = new CVehicleModelInfoSAInterface ();
0 commit comments