diff --git a/Client/game_sa/CModelInfoSA.cpp b/Client/game_sa/CModelInfoSA.cpp index 0b5ff312b3..9982bcf5bd 100644 --- a/Client/game_sa/CModelInfoSA.cpp +++ b/Client/game_sa/CModelInfoSA.cpp @@ -1761,6 +1761,24 @@ void CModelInfoSA::MakeObjectModel(ushort usBaseID) CopyStreamingInfoFromModel(usBaseID); } +void CModelInfoSA::MakeObjectDamageableModel(std::uint16_t baseModel) +{ + CDamageableModelInfoSAInterface* m_pInterface = new CDamageableModelInfoSAInterface(); + + CDamageableModelInfoSAInterface* pBaseObjectInfo = static_cast(ppModelInfo[baseModel]); + MemCpyFast(m_pInterface, pBaseObjectInfo, sizeof(CDamageableModelInfoSAInterface)); + m_pInterface->usNumberOfRefs = 0; + m_pInterface->pRwObject = nullptr; + m_pInterface->usUnknown = 65535; + m_pInterface->usDynamicIndex = 65535; + m_pInterface->m_damagedAtomic = nullptr; + + ppModelInfo[m_dwModelID] = m_pInterface; + + m_dwParentID = baseModel; + CopyStreamingInfoFromModel(baseModel); +} + void CModelInfoSA::MakeTimedObjectModel(ushort usBaseID) { CTimeModelInfoSAInterface* m_pInterface = new CTimeModelInfoSAInterface(); @@ -1826,7 +1844,14 @@ void CModelInfoSA::DeallocateModel(void) delete reinterpret_cast(ppModelInfo[m_dwModelID]); break; case eModelInfoType::ATOMIC: - delete reinterpret_cast(ppModelInfo[m_dwModelID]); + if (IsDamageableAtomic()) + { + delete reinterpret_cast(ppModelInfo[m_dwModelID]); + } + else + { + delete reinterpret_cast(ppModelInfo[m_dwModelID]); + } break; case eModelInfoType::CLUMP: delete reinterpret_cast(ppModelInfo[m_dwModelID]); @@ -2081,6 +2106,12 @@ bool CModelInfoSA::IsTowableBy(CModelInfo* towingModel) return isTowable; } +bool CModelInfoSA::IsDamageableAtomic() +{ + void* asDamagable = ((void* (*)())m_pInterface->VFTBL->AsDamageAtomicModelInfoPtr)(); + return asDamagable != nullptr; +} + ////////////////////////////////////////////////////////////////////////////////////////// // // CModelInfoSA::ForceUnload diff --git a/Client/game_sa/CModelInfoSA.h b/Client/game_sa/CModelInfoSA.h index 6fc7b04811..ac55d61f48 100644 --- a/Client/game_sa/CModelInfoSA.h +++ b/Client/game_sa/CModelInfoSA.h @@ -259,6 +259,12 @@ class CTimeModelInfoSAInterface : public CBaseModelInfoSAInterface CTimeInfoSAInterface timeInfo; }; +class CDamageableModelInfoSAInterface : public CBaseModelInfoSAInterface +{ +public: + void* m_damagedAtomic; +}; + class CVehicleModelVisualInfoSAInterface // Not sure about this name. If somebody knows more, please change { public: @@ -447,6 +453,7 @@ class CModelInfoSA : public CModelInfo // CModelInfoSA methods void MakePedModel(char* szTexture); void MakeObjectModel(ushort usBaseModelID); + void MakeObjectDamageableModel(std::uint16_t usBaseModelID) override; void MakeVehicleAutomobile(ushort usBaseModelID); void MakeTimedObjectModel(ushort usBaseModelID); void MakeClumpModel(ushort usBaseModelID); @@ -467,6 +474,7 @@ class CModelInfoSA : public CModelInfo bool IsTowableBy(CModelInfo* towingModel) override; bool IsDynamic() { return m_pInterface ? m_pInterface->usDynamicIndex != MODEL_PROPERTIES_GROUP_STATIC : false; }; + bool IsDamageableAtomic() override; static bool IsVehicleModel(std::uint32_t model) noexcept; diff --git a/Client/mods/deathmatch/logic/CClientModel.cpp b/Client/mods/deathmatch/logic/CClientModel.cpp index fd1e6e4ab5..906f77324c 100644 --- a/Client/mods/deathmatch/logic/CClientModel.cpp +++ b/Client/mods/deathmatch/logic/CClientModel.cpp @@ -51,6 +51,17 @@ bool CClientModel::Allocate(ushort usParentID) return true; } break; + case eClientModelType::OBJECT_DAMAGEABLE: + { + bool isValidModel = g_pClientGame->GetObjectManager()->IsValidModel(usParentID); + bool isDamagable = pParentModelInfo->IsDamageableAtomic(); + if (isValidModel && isDamagable) + { + pModelInfo->MakeObjectDamageableModel(usParentID); + return true; + } + break; + } case eClientModelType::CLUMP: if (g_pClientGame->GetObjectManager()->IsValidModel(usParentID)) { @@ -109,6 +120,7 @@ void CClientModel::RestoreEntitiesUsingThisModel() { case eClientModelType::PED: case eClientModelType::OBJECT: + case eClientModelType::OBJECT_DAMAGEABLE: case eClientModelType::CLUMP: case eClientModelType::TIMED_OBJECT: case eClientModelType::VEHICLE: @@ -174,6 +186,7 @@ void CClientModel::RestoreDFF(CModelInfo* pModelInfo) } case eClientModelType::CLUMP: case eClientModelType::OBJECT: + case eClientModelType::OBJECT_DAMAGEABLE: case eClientModelType::TIMED_OBJECT: { const auto& objects = &g_pClientGame->GetManager()->GetObjectManager()->GetObjects(); diff --git a/Client/mods/deathmatch/logic/CClientModel.h b/Client/mods/deathmatch/logic/CClientModel.h index 903148192d..759890e0e5 100644 --- a/Client/mods/deathmatch/logic/CClientModel.h +++ b/Client/mods/deathmatch/logic/CClientModel.h @@ -18,6 +18,7 @@ enum class eClientModelType { PED, OBJECT, + OBJECT_DAMAGEABLE, VEHICLE, TIMED_OBJECT, CLUMP, diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index 43f57a637d..4274befdc8 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -707,6 +707,7 @@ IMPLEMENT_ENUM_END("surface-adhesion-group") IMPLEMENT_ENUM_CLASS_BEGIN(eClientModelType) ADD_ENUM(eClientModelType::PED, "ped") ADD_ENUM(eClientModelType::OBJECT, "object") +ADD_ENUM(eClientModelType::OBJECT_DAMAGEABLE, "object-damageable") ADD_ENUM(eClientModelType::VEHICLE, "vehicle") ADD_ENUM(eClientModelType::TIMED_OBJECT, "timed-object") ADD_ENUM(eClientModelType::CLUMP, "clump") diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp index 7ca02230d5..a6a688c366 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp @@ -892,6 +892,9 @@ int CLuaEngineDefs::EngineRequestModel(lua_State* luaVM) case eClientModelType::OBJECT: usParentID = 1337; // BinNt07_LA (trash can) break; + case eClientModelType::OBJECT_DAMAGEABLE: + usParentID = 994; // lhouse_barrier2 + break; case eClientModelType::VEHICLE: usParentID = VT_LANDSTAL; break; diff --git a/Client/sdk/game/CModelInfo.h b/Client/sdk/game/CModelInfo.h index c578be1990..8b27fc0304 100644 --- a/Client/sdk/game/CModelInfo.h +++ b/Client/sdk/game/CModelInfo.h @@ -236,6 +236,7 @@ class CModelInfo virtual RwObject* GetRwObject() = 0; virtual void MakePedModel(char* szTexture) = 0; virtual void MakeObjectModel(unsigned short usBaseID) = 0; + virtual void MakeObjectDamageableModel(std::uint16_t baseID) = 0; virtual void MakeVehicleAutomobile(unsigned short usBaseID) = 0; virtual void MakeTimedObjectModel(unsigned short usBaseID) = 0; virtual void MakeClumpModel(unsigned short usBaseID) = 0; @@ -252,4 +253,5 @@ class CModelInfo virtual unsigned int GetParentID() = 0; virtual bool IsDynamic() = 0; + virtual bool IsDamageableAtomic() = 0; };