From 6245a68f3d97fc222d78fbc66b67f422a13710bf Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Wed, 3 Apr 2024 18:44:36 +0300 Subject: [PATCH] Fix crashes caused by createBuilding with engineRequestModel (#3330) Bugs fixed: 1) Crash occurs when a resource that uses createBuilding with engineRequestModel is stopped 2) Destroyed building leaves grass --- Client/game_sa/CPoolsSA.cpp | 9 ++++++ Client/game_sa/CPtrNodeSingleListSA.h | 45 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 Client/game_sa/CPtrNodeSingleListSA.h diff --git a/Client/game_sa/CPoolsSA.cpp b/Client/game_sa/CPoolsSA.cpp index 6680e82194..e3810ec443 100644 --- a/Client/game_sa/CPoolsSA.cpp +++ b/Client/game_sa/CPoolsSA.cpp @@ -26,6 +26,7 @@ #include "CWorldSA.h" #include "CKeyGenSA.h" #include "CFileLoaderSA.h" +#include "CPtrNodeSingleListSA.h" extern CGameSA* pGame; @@ -410,6 +411,14 @@ void CPoolsSA::RemoveBuilding(CBuilding* pBuilding) // Remove building from world pGame->GetWorld()->Remove(pInterface, CBuildingPool_Destructor); + // Remove building from cover list + CPtrNodeSingleListSAInterface* coverList = reinterpret_cast*>(0xC1A2B8); + coverList->RemoveItem(pInterface); + + // Remove plant + using CPlantColEntry_Remove = CEntitySAInterface* (*)(CEntitySAInterface*); + ((CPlantColEntry_Remove)0x5DBEF0)(pInterface); + // Remove col reference auto modelInfo = pGame->GetModelInfo(pBuilding->GetModelIndex()); modelInfo->RemoveColRef(); diff --git a/Client/game_sa/CPtrNodeSingleListSA.h b/Client/game_sa/CPtrNodeSingleListSA.h new file mode 100644 index 0000000000..06df6a2575 --- /dev/null +++ b/Client/game_sa/CPtrNodeSingleListSA.h @@ -0,0 +1,45 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CPtrNodeSingleListSA.cpp + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +template +struct CPtrNodeSingleLink +{ + T* pItem; + CPtrNodeSingleLink* pNext; +}; + +template +class CPtrNodeSingleListSAInterface +{ +public: + void RemoveItem(T* item); + void RemoveAllItems(); + +private: + CPtrNodeSingleLink* m_pList; +}; + +template +void CPtrNodeSingleListSAInterface::RemoveItem(T* item) +{ + using CPtrNodeSingleList_RemoveItem_t = void(__thiscall*)(CPtrNodeSingleListSAInterface * pLinkList, void* item); + ((CPtrNodeSingleList_RemoveItem_t)0x533610)(this, item); +} + +template +void CPtrNodeSingleListSAInterface::RemoveAllItems() +{ + while (m_pList) + { + RemoveItem(m_pList->pItem); + } +}