From 678a20134b644d8d1d076053ff5e7492bfdb66d9 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Tue, 11 Jun 2024 22:06:34 +0300 Subject: [PATCH] extract world removal class --- Client/game_sa/CBuildingRemovalSA.cpp | 698 ++++++++++++++++++ Client/game_sa/CBuildingRemovalSA.h | 44 ++ Client/game_sa/CGameSA.cpp | 3 + Client/game_sa/CGameSA.h | 2 + Client/game_sa/CWorldSA.cpp | 676 ----------------- Client/game_sa/CWorldSA.h | 21 +- Client/mods/deathmatch/logic/CClientGame.cpp | 3 +- .../mods/deathmatch/logic/CPacketHandler.cpp | 3 +- .../logic/CStaticFunctionDefinitions.cpp | 7 +- .../mods/deathmatch/logic/rpc/CWorldRPCs.cpp | 7 +- Client/multiplayer_sa/CMultiplayerSA.cpp | 23 +- Client/sdk/game/CBuildingRemoval.h | 124 ++++ Client/sdk/game/CGame.h | 2 + Client/sdk/game/CWorld.h | 100 +-- 14 files changed, 901 insertions(+), 812 deletions(-) create mode 100644 Client/game_sa/CBuildingRemovalSA.cpp create mode 100644 Client/game_sa/CBuildingRemovalSA.h create mode 100644 Client/sdk/game/CBuildingRemoval.h diff --git a/Client/game_sa/CBuildingRemovalSA.cpp b/Client/game_sa/CBuildingRemovalSA.cpp new file mode 100644 index 0000000000..c86cf5732b --- /dev/null +++ b/Client/game_sa/CBuildingRemovalSA.cpp @@ -0,0 +1,698 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CBuildingRemovalSA.cpp + * PURPOSE: Building removal logic + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include "CBuildingRemovalSA.h" + +#include "CWorldSA.h" +#include "CGameSA.h" +#include "CPoolsSA.h" + +extern CGameSA* pGame; + +CBuildingRemovalSA::CBuildingRemovalSA() +{ + m_pBuildingRemovals = new std::multimap; + m_pDataBuildings = new std::multimap; + m_pBinaryBuildings = new std::multimap; +} + +void CBuildingRemovalSA::RemoveBuilding(unsigned short usModelToRemove, float fRange, float fX, float fY, float fZ, char cInterior, uint* pOutAmount) +{ + // New building Removal + SBuildingRemoval* pRemoval = new SBuildingRemoval(); + pRemoval->m_usModel = usModelToRemove; + pRemoval->m_vecPos.fX = fX; + pRemoval->m_vecPos.fY = fY; + pRemoval->m_vecPos.fZ = fZ; + pRemoval->m_fRadius = fRange; + pRemoval->m_cInterior = cInterior; + // Push it to the back of the removal list + m_pBuildingRemovals->insert(std::pair(usModelToRemove, pRemoval)); + + bool bFound = false; + uint uiAmount = 0; + // Init loop variables + std::pair::iterator, std::multimap::iterator> + iterators = m_pDataBuildings->equal_range(usModelToRemove); + std::multimap::const_iterator iter = iterators.first; + for (; iter != iterators.second; ++iter) + { + sDataBuildingRemovalItem* pFind = (*iter).second; + if (pFind) + { + // if the count is <= 0 and the interface is valid check the distance in case we found a removal (count is used to store if we have already removed + // this once) + if (pFind->m_iCount <= 0 && pFind->m_pInterface) + { + // Grab distances across each axis + float fDistanceX = fX - pFind->m_pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = fY - pFind->m_pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = fZ - pFind->m_pInterface->Placeable.m_transform.m_translate.fZ; + + if (pFind->m_pInterface->Placeable.matrix != NULL) + { + fDistanceX = fX - pFind->m_pInterface->Placeable.matrix->vPos.fX; + fDistanceY = fY - pFind->m_pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = fZ - pFind->m_pInterface->Placeable.matrix->vPos.fZ; + } + + // Square root 'em + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + + // Is it in range + if (fDistance <= fRange && (pFind->m_pInterface->m_areaCode == cInterior || cInterior == -1)) + { + CEntitySAInterface* pInterface = pFind->m_pInterface; + // while ( pInterface && pInterface != NULL ) + // if the interface is valid + if (pInterface && pInterface != NULL) + { + // if the building type is dummy or building and it's not already being removed + if ((pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY || pInterface->nType == ENTITY_TYPE_OBJECT) && + pInterface->bRemoveFromWorld != 1) + { + if ((DWORD)(pInterface->vtbl) != VTBL_CPlaceable) + { + // Add the Data Building to the list + pRemoval->AddDataBuilding(pInterface); + // Remove the model from the world + pGame->GetWorld()->Remove(pInterface, BuildingRemoval2); + m_pRemovedEntities[(DWORD)pInterface] = true; + bFound = true; + } + } + // Get next LOD ( LOD's can have LOD's so we keep checking pInterface ) + // pInterface = pInterface->m_pLod; + } + // Set the count. + pFind->m_iCount = 1; + } + } + } + } + + std::pair::iterator, std::multimap::iterator> iteratorsBinary = + m_pBinaryBuildings->equal_range(usModelToRemove); + std::multimap::const_iterator iterBinary = iteratorsBinary.first; + for (; iterBinary != iteratorsBinary.second; ++iterBinary) + { + sBuildingRemovalItem* pFindBinary = (*iterBinary).second; + if (pFindBinary) + { + // if the count is <= 0 and the interface is valid check the distance in case we found a removal (count is used to store if we have already removed + // this once) + if (pFindBinary->m_iCount <= 0 && pFindBinary->m_pInterface) + { + // Grab distances across each axis + float fDistanceX = fX - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = fY - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = fZ - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fZ; + + if (pFindBinary->m_pInterface->Placeable.matrix != NULL) + { + fDistanceX = fX - pFindBinary->m_pInterface->Placeable.matrix->vPos.fX; + fDistanceY = fY - pFindBinary->m_pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = fZ - pFindBinary->m_pInterface->Placeable.matrix->vPos.fZ; + } + + // Square root 'em + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + + // Is it in range + if (fDistance <= fRange && (pFindBinary->m_pInterface->m_areaCode == cInterior || cInterior == -1)) + { + CEntitySAInterface* pInterface = pFindBinary->m_pInterface; + // while ( pInterface && pInterface != NULL ) + // if the interface is valid + if (pInterface && pInterface != NULL) + { + // if the building type is dummy or building and it's not already being removed + if ((pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY || pInterface->nType == ENTITY_TYPE_OBJECT) && + pInterface->bRemoveFromWorld != 1) + { + if ((DWORD)(pInterface->vtbl) != VTBL_CPlaceable) + { + // Add the Data Building to the list + pRemoval->AddBinaryBuilding(pInterface); + // Remove the model from the world + pGame->GetWorld()->Remove(pInterface, BuildingRemoval2); + m_pRemovedEntities[(DWORD)pInterface] = true; + bFound = true; + ++uiAmount; + } + } + // Get next LOD ( LOD's can have LOD's so we keep checking pInterface ) + // pInterface = pInterface->m_pLod; + } + // Set the count. + pFindBinary->m_iCount = 1; + } + } + } + } + if (bFound) + pGame->GetModelInfo(usModelToRemove)->RestreamIPL(); + + if (pOutAmount) + *pOutAmount = uiAmount; +} + +bool CBuildingRemovalSA::RestoreBuilding(unsigned short usModelToRestore, float fRange, float fX, float fY, float fZ, char cInterior, uint* pOutAmount) +{ + bool bSuccess = false; + uint uiAmount = 0; + + // Init some variables + std::pair::iterator, std::multimap::iterator> iterators = + m_pBuildingRemovals->equal_range(usModelToRestore); + std::multimap::const_iterator iter = iterators.first; + // Loop through the buildings list + for (; iter != iterators.second;) + { + SBuildingRemoval* pFind = (*iter).second; + // if pFind is valid and the model is the same + if (pFind) + { + // Grab distances across each axis + float fDistanceX = fX - pFind->m_vecPos.fX; + float fDistanceY = fY - pFind->m_vecPos.fY; + float fDistanceZ = fZ - pFind->m_vecPos.fZ; + + // Square root 'em + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + if (fDistance <= pFind->m_fRadius && (cInterior == -1 || pFind->m_cInterior == cInterior)) + { + // Init some variables + CEntitySAInterface* pEntity = NULL; + std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); + if (pFind->m_pBinaryRemoveList->empty() == false) + { + // Loop through the Binary object list + for (; entityIter != pFind->m_pBinaryRemoveList->end();) + { + // Grab the pEntity + pEntity = (*entityIter); + // if it's valid re-add it to the world. + if (pEntity != NULL) + { + // Remove it from the binary list + pFind->m_pBinaryRemoveList->erase(entityIter++); + // if the building type is dummy or building and it's not already being removed + if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && + pEntity->bRemoveFromWorld != 1) + { + // Don't call this on entities being removed. + if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + { + pGame->GetWorld()->Add(pEntity, Building_Restore); + m_pRemovedEntities[(DWORD)pEntity] = false; + // If the building isn't streamed in, we won't find the building in the list (because the hook wasn't called) -> + // removeWorldModel doesn't work next time + AddBinaryBuilding(pEntity); + ++uiAmount; + } + } + } + else + ++entityIter; + } + } + // Start the iterator with the data remove list first item + entityIter = pFind->m_pDataRemoveList->begin(); + if (pFind->m_pDataRemoveList->empty() == false) + { + // Loop through the Data list + for (; entityIter != pFind->m_pDataRemoveList->end();) + { + // Grab the pEntity + pEntity = (*entityIter); + // if it's valid re-add it to the world. + if (pEntity != NULL) + { + pFind->m_pDataRemoveList->erase(entityIter++); + // if the building type is dummy or building and it's not already being removed + if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && + pEntity->bRemoveFromWorld != 1) + { + if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + { + pGame->GetWorld()->Add(pEntity, Building_Restore2); + m_pRemovedEntities[(DWORD)pEntity] = false; + } + } + } + else + { + ++entityIter; + } + } + } + // Remove the building from the list + m_pBuildingRemovals->erase(iter++); + delete pFind; + // Success! don't return incase there are any others to delete + bSuccess = true; + } + else + iter++; + } + else + iter++; + } + std::pair::iterator, std::multimap::iterator> + dataBuildingIterators = m_pDataBuildings->equal_range(usModelToRestore); + std::multimap::const_iterator iterator = dataBuildingIterators.first; + for (; iterator != dataBuildingIterators.second; ++iterator) + { + sDataBuildingRemovalItem* pFound = (*iterator).second; + if (pFound) + { + // Grab distances across each axis + float fDistanceX = fX - pFound->m_pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = fY - pFound->m_pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = fZ - pFound->m_pInterface->Placeable.m_transform.m_translate.fZ; + + if (pFound->m_pInterface->Placeable.matrix != NULL) + { + fDistanceX = fX - pFound->m_pInterface->Placeable.matrix->vPos.fX; + fDistanceY = fY - pFound->m_pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = fZ - pFound->m_pInterface->Placeable.matrix->vPos.fZ; + } + + // Square root 'em + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + if (fDistance <= fRange && (cInterior == -1 || pFound->m_pInterface->m_areaCode == cInterior)) + { + // Fix the removed count. + pFound->m_iCount--; + if (pFound->m_iCount < 0) + pFound->m_iCount = 0; + } + } + } + + std::pair::iterator, std::multimap::iterator> + binaryBuildingIterators = m_pBinaryBuildings->equal_range(usModelToRestore); + std::multimap::const_iterator iteratorBinary = binaryBuildingIterators.first; + for (; iteratorBinary != binaryBuildingIterators.second; ++iteratorBinary) + { + sBuildingRemovalItem* pFoundBinary = (*iteratorBinary).second; + if (pFoundBinary) + { + // Grab distances across each axis + float fDistanceX = fX - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = fY - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = fZ - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fZ; + + if (pFoundBinary->m_pInterface->Placeable.matrix != NULL) + { + fDistanceX = fX - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fX; + fDistanceY = fY - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = fZ - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fZ; + } + + // Square root 'em + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + if (fDistance <= fRange && (cInterior == -1 || pFoundBinary->m_pInterface->m_areaCode == cInterior)) + { + // Fix the removed count. + pFoundBinary->m_iCount--; + if (pFoundBinary->m_iCount < 0) + pFoundBinary->m_iCount = 0; + } + } + } + + if (pOutAmount) + *pOutAmount = uiAmount; + + return bSuccess; +} + +// Check Distance to see if the model being requested is in the radius +bool CBuildingRemovalSA::IsRemovedModelInRadius(SIPLInst* pInst) +{ + // Init some variables + std::pair::iterator, std::multimap::iterator> iterators = + m_pBuildingRemovals->equal_range(pInst->m_nModelIndex); + std::multimap::const_iterator iter = iterators.first; + // Loop through the buildings list + for (; iter != iterators.second; ++iter) + { + SBuildingRemoval* pFind = (*iter).second; + // if pFind is valid and the model is the same + if (pFind) + { + // Grab the distance + float fDistanceX = pFind->m_vecPos.fX - pInst->m_pPosition.fX; + float fDistanceY = pFind->m_vecPos.fY - pInst->m_pPosition.fY; + float fDistanceZ = pFind->m_vecPos.fZ - pInst->m_pPosition.fZ; + + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + // is it in the removal spheres radius if so return else keep looking + if (fDistance <= pFind->m_fRadius && (pFind->m_cInterior == -1 || pFind->m_cInterior == pInst->m_nAreaCode)) + { + return true; + } + } + } + return false; +} + +// Check Distance to see if the model being requested is in the radius +bool CBuildingRemovalSA::IsObjectRemoved(CEntitySAInterface* pInterface) +{ + // Init some variables + std::pair::iterator, std::multimap::iterator> iterators = + m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); + std::multimap::const_iterator iter = iterators.first; + // Loop through the buildings list + for (; iter != iterators.second; ++iter) + { + SBuildingRemoval* pFind = (*iter).second; + // if pFind is valid and the model is the same + if (pFind) + { + // Are we using the interior param?? if so check for a match + if (pFind->m_cInterior == -1 || pFind->m_cInterior == pInterface->m_areaCode) + { + // Grab the distance + float fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.m_transform.m_translate.fZ; + + if (pInterface->Placeable.matrix != NULL) + { + fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.matrix->vPos.fX; + fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.matrix->vPos.fZ; + } + + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + // is it in the removal spheres radius if so return else keep looking + if (fDistance <= pFind->m_fRadius) + { + return true; + } + } + } + } + return false; +} + +// Check if a given model is replaced +bool CBuildingRemovalSA::IsModelRemoved(unsigned short usModelID) +{ + return m_pBuildingRemovals->count(usModelID) > 0; +} + +// Check if a given model is replaced +bool CBuildingRemovalSA::IsDataModelRemoved(unsigned short usModelID) +{ + return m_pBuildingRemovals->count(usModelID) > 0; +} + +// Check if a given model is replaced +bool CBuildingRemovalSA::IsEntityRemoved(CEntitySAInterface* pInterface) +{ + return m_pRemovedEntities.find((DWORD)pInterface) != m_pRemovedEntities.end() && m_pRemovedEntities[(DWORD)pInterface] == true; +} + +// Resets deleted list +void CBuildingRemovalSA::ClearRemovedBuildingLists(uint* pOutAmount) +{ + // Ensure no memory leaks by deleting items. + uint uiAmount = 0; + std::multimap::const_iterator iter = m_pBuildingRemovals->begin(); + + for (; iter != m_pBuildingRemovals->end();) + { + SBuildingRemoval* pFind = (*iter).second; + if (pFind) + { + // Init some variables + CEntitySAInterface* pEntity = NULL; + std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); + if (pFind->m_pBinaryRemoveList->empty() == false) + { + // Loop through the Binary remove list + for (; entityIter != pFind->m_pBinaryRemoveList->end(); ++entityIter) + { + // Grab the pEntity + pEntity = (*entityIter); + // if it's valid re-add it to the world. + if (pEntity && pEntity != NULL) + { + // if the building type is dummy or building and it's not already being removed + if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && + pEntity->bRemoveFromWorld != 1) + { + // Don't call this on entities being removed. + if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + { + pGame->GetWorld()->Add(pEntity, BuildingRemovalReset); + m_pRemovedEntities[(DWORD)pEntity] = false; + ++uiAmount; + } + } + } + } + } + entityIter = pFind->m_pDataRemoveList->begin(); + if (pFind->m_pDataRemoveList->empty() == false) + { + // Loop through the Data list + for (; entityIter != pFind->m_pDataRemoveList->end(); ++entityIter) + { + // Grab the pEntity + pEntity = (*entityIter); + // if it's valid re-add it to the world. + if (pEntity && pEntity != NULL) + { + // if the building type is dummy or building and it's not already being removed + if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && + pEntity->bRemoveFromWorld != 1) + { + // Don't call this on entities being removed. + if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + { + pGame->GetWorld()->Add(pEntity, BuildingRemovalReset2); + m_pRemovedEntities[(DWORD)pEntity] = false; + } + } + } + } + } + m_pBuildingRemovals->erase(iter++); + } + else + iter++; + } + // Init some variables + std::multimap::const_iterator iterator = m_pDataBuildings->begin(); + // Loop through the data building list + for (; iterator != m_pDataBuildings->end(); ++iterator) + { + sDataBuildingRemovalItem* pFound = (*iterator).second; + if (pFound) + { + // Set the count to 0 so we can remove it again + pFound->m_iCount = 0; + } + } + // Init some variables + std::multimap::const_iterator iteratorBinary = m_pBinaryBuildings->begin(); + // Loop through the data building list + for (; iteratorBinary != m_pBinaryBuildings->end(); ++iteratorBinary) + { + sBuildingRemovalItem* pFoundBinary = (*iteratorBinary).second; + if (pFoundBinary) + { + // Set the count to 0 so we can remove it again + pFoundBinary->m_iCount = 0; + } + } + // Delete old building lists + delete m_pBuildingRemovals; + // Create new + m_pBuildingRemovals = new std::multimap; + m_pRemovedEntities.clear(); + + if (pOutAmount) + *pOutAmount = uiAmount; +} + +// Resets deleted list +SBuildingRemoval* CBuildingRemovalSA::GetBuildingRemoval(CEntitySAInterface* pInterface) +{ + // Init some variables + std::pair::iterator, std::multimap::iterator> iterators = + m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); + std::multimap::const_iterator iter = iterators.first; + // Loop through the buildings list + for (; iter != iterators.second; ++iter) + { + SBuildingRemoval* pFind = (*iter).second; + // if pFind is valid and the model is the same + if (pFind) + { + // Grab the distance + float fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.m_transform.m_translate.fX; + float fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.m_transform.m_translate.fY; + float fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.m_transform.m_translate.fZ; + + if (pInterface->Placeable.matrix != NULL) + { + fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.matrix->vPos.fX; + fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.matrix->vPos.fY; + fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.matrix->vPos.fZ; + } + + float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); + // is it in the removal spheres radius if so return else keep looking + if (fDistance <= pFind->m_fRadius && (pFind->m_cInterior == -1 || pFind->m_cInterior == pInterface->m_areaCode)) + { + return pFind; + } + } + } + return NULL; +} + +void CBuildingRemovalSA::AddDataBuilding(CEntitySAInterface* pInterface) +{ + if (m_pAddedEntities.find((DWORD)pInterface) == m_pAddedEntities.end() || m_pAddedEntities[(DWORD)pInterface] == false) + { + // Create a new building removal + sDataBuildingRemovalItem* pBuildingRemoval = new sDataBuildingRemovalItem(pInterface, true); + // Insert it with the model index so we can fast lookup + m_pDataBuildings->insert(std::pair((unsigned short)pInterface->m_nModelIndex, pBuildingRemoval)); + m_pAddedEntities[(DWORD)pInterface] = true; + m_pRemovedEntities[(DWORD)pInterface] = false; + } +} + +void CBuildingRemovalSA::AddBinaryBuilding(CEntitySAInterface* pInterface) +{ + if (m_pAddedEntities.find((DWORD)pInterface) == m_pAddedEntities.end() || m_pAddedEntities[(DWORD)pInterface] == false) + { + // Create a new building removal + sBuildingRemovalItem* pBuildingRemoval = new sBuildingRemovalItem(pInterface, false); + // Insert it with the model index so we can fast lookup + m_pBinaryBuildings->insert(std::pair((unsigned short)pInterface->m_nModelIndex, pBuildingRemoval)); + m_pAddedEntities[(DWORD)pInterface] = true; + m_pRemovedEntities[(DWORD)pInterface] = false; + } +} + +void CBuildingRemovalSA::RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface) +{ + std::pair::iterator, std::multimap::iterator> iterators = + m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); + std::multimap::const_iterator iter = iterators.first; + + // Loop through the buildings list + for (; iter != iterators.second; ++iter) + { + SBuildingRemoval* pFind = (*iter).second; + // if pFind is valid and the model is the same + if (pFind) + { + CEntitySAInterface* pEntity = NULL; + // if the binary remove list is empty don't continue + if (pFind->m_pBinaryRemoveList->empty() == false) + { + // grab the beginning + std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); + // Loop through the binary remove list + for (; entityIter != pFind->m_pBinaryRemoveList->end();) + { + pEntity = (*entityIter); + // is the pointer the same as the one being deleted + if ((DWORD)pEntity == (DWORD)pInterface) + { + // remove it from the binary removed list for this removal + pFind->m_pBinaryRemoveList->erase(entityIter++); + } + else + entityIter++; + } + } + if (pFind->m_pDataRemoveList->empty() == false) + { + std::list::const_iterator entityIter = pFind->m_pDataRemoveList->begin(); + // Loop through the Data list + for (; entityIter != pFind->m_pDataRemoveList->end();) + { + // Grab the pEntity + pEntity = (*entityIter); + // is the pointer the same as the one being deleted + if ((DWORD)pEntity == (DWORD)pInterface) + { + // remove it from the data removed list for this removal + pFind->m_pDataRemoveList->erase(entityIter++); + } + else + entityIter++; + } + } + } + } + { + // Init some variables + std::pair::iterator, std::multimap::iterator> + dataIterators = m_pDataBuildings->equal_range(pInterface->m_nModelIndex); + std::multimap::const_iterator iterator = dataIterators.first; + for (; iterator != dataIterators.second;) + { + sDataBuildingRemovalItem* pFound = (*iterator).second; + if (pFound) + { + // is the pointer the same as the one being deleted + if ((DWORD)pFound->m_pInterface == (DWORD)pInterface) + { + // remove it from the data buildings list so we don't try and remove or add it again. + m_pDataBuildings->erase(iterator++); + } + else + iterator++; + } + else + iterator++; + } + } + { + // Init some variables + std::pair::iterator, std::multimap::iterator> + binaryIterators = m_pBinaryBuildings->equal_range(pInterface->m_nModelIndex); + std::multimap::const_iterator iteratorBinary = binaryIterators.first; + for (; iteratorBinary != binaryIterators.second;) + { + sBuildingRemovalItem* pFound = (*iteratorBinary).second; + if (pFound) + { + // is the pointer the same as the one being deleted + if ((DWORD)pFound->m_pInterface == (DWORD)pInterface) + { + // remove it from the data buildings list so we don't try and remove or add it again. + m_pBinaryBuildings->erase(iteratorBinary++); + } + else + iteratorBinary++; + } + else + iteratorBinary++; + } + } + m_pRemovedEntities[(DWORD)pInterface] = false; + m_pAddedEntities[(DWORD)pInterface] = false; +} diff --git a/Client/game_sa/CBuildingRemovalSA.h b/Client/game_sa/CBuildingRemovalSA.h new file mode 100644 index 0000000000..33c2d189da --- /dev/null +++ b/Client/game_sa/CBuildingRemovalSA.h @@ -0,0 +1,44 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: game_sa/CBuildingRemovalSA.h + * PURPOSE: Header file for building removal class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include +#include + +#include + +class CBuildingRemovalSA : public CBuildingRemoval +{ +public: + CBuildingRemovalSA(); + + void RemoveBuilding(unsigned short usModelToRemove, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL); + bool IsRemovedModelInRadius(SIPLInst* pInst); + bool IsModelRemoved(unsigned short modelID); + void ClearRemovedBuildingLists(uint* pOutAmount = NULL); + bool RestoreBuilding(unsigned short usModelToRestore, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL); + SBuildingRemoval* GetBuildingRemoval(CEntitySAInterface* pInterface); + void AddDataBuilding(CEntitySAInterface* pInterface); + void RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface); + void AddBinaryBuilding(CEntitySAInterface* pInterface); + bool IsObjectRemoved(CEntitySAInterface* pInterface); + bool IsDataModelRemoved(unsigned short usModelID); + bool IsEntityRemoved(CEntitySAInterface* pInterface); + +private: + std::multimap* m_pBuildingRemovals; + std::multimap* m_pDataBuildings; + std::multimap* m_pBinaryBuildings; + std::map* m_pRemovedObjects; + std::map m_pRemovedEntities; + std::map m_pAddedEntities; +}; diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index 073ad0a637..0fd27a053c 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -57,6 +57,7 @@ #include "CWorldSA.h" #include "D3DResourceSystemSA.h" #include "CIplStoreSA.h" +#include "CBuildingRemovalSA.h" extern CGameSA* pGame; @@ -141,6 +142,7 @@ CGameSA::CGameSA() m_pIplStore = new CIplStoreSA(); m_pCoverManager = new CCoverManagerSA(); m_pPlantManager = new CPlantManagerSA(); + m_pBuildingRemoval = new CBuildingRemovalSA(); // Normal weapon types (WEAPONSKILL_STD) for (int i = 0; i < NUM_WeaponInfosStdSkill; i++) @@ -278,6 +280,7 @@ CGameSA::~CGameSA() delete reinterpret_cast(m_pPointLights); delete static_cast(m_collisionStore); delete static_cast(m_pIplStore); + delete static_cast(m_pBuildingRemoval); delete m_pCoverManager; delete m_pPlantManager; diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index 0c3fcb97ea..29d9a9ef73 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -171,6 +171,7 @@ class CGameSA : public CGame CIplStore* GetIplStore() { return m_pIplStore; }; CCoverManagerSA* GetCoverManager() const noexcept { return m_pCoverManager; }; CPlantManagerSA* GetPlantManager() const noexcept { return m_pPlantManager; }; + CBuildingRemoval* GetBuildingRemoval() { return m_pBuildingRemoval; } CWeaponInfo* GetWeaponInfo(eWeaponType weapon, eWeaponSkill skill = WEAPONSKILL_STD); CModelInfo* GetModelInfo(DWORD dwModelID, bool bCanBeInvalid = false); @@ -339,6 +340,7 @@ class CGameSA : public CGame CObjectGroupPhysicalProperties* m_pObjectGroupPhysicalProperties; CCoverManagerSA* m_pCoverManager; CPlantManagerSA* m_pPlantManager; + CBuildingRemoval* m_pBuildingRemoval; CPad* m_pPad; CAERadioTrackManager* m_pCAERadioTrackManager; diff --git a/Client/game_sa/CWorldSA.cpp b/Client/game_sa/CWorldSA.cpp index c2c7376e6e..a60e360464 100644 --- a/Client/game_sa/CWorldSA.cpp +++ b/Client/game_sa/CWorldSA.cpp @@ -31,10 +31,6 @@ namespace CWorldSA::CWorldSA() { - m_pBuildingRemovals = new std::multimap; - m_pDataBuildings = new std::multimap; - m_pBinaryBuildings = new std::multimap; - m_pSurfaceInfo = reinterpret_cast(ARRAY_SurfaceInfos); InstallHooks(); @@ -735,678 +731,6 @@ int CWorldSA::FindClosestRailTrackNode(const CVector& vecPosition, uchar& ucOutT return iNodeId; } -void CWorldSA::RemoveBuilding(unsigned short usModelToRemove, float fRange, float fX, float fY, float fZ, char cInterior, uint* pOutAmount) -{ - // New building Removal - SBuildingRemoval* pRemoval = new SBuildingRemoval(); - pRemoval->m_usModel = usModelToRemove; - pRemoval->m_vecPos.fX = fX; - pRemoval->m_vecPos.fY = fY; - pRemoval->m_vecPos.fZ = fZ; - pRemoval->m_fRadius = fRange; - pRemoval->m_cInterior = cInterior; - // Push it to the back of the removal list - m_pBuildingRemovals->insert(std::pair(usModelToRemove, pRemoval)); - - bool bFound = false; - uint uiAmount = 0; - // Init loop variables - std::pair::iterator, std::multimap::iterator> - iterators = m_pDataBuildings->equal_range(usModelToRemove); - std::multimap::const_iterator iter = iterators.first; - for (; iter != iterators.second; ++iter) - { - sDataBuildingRemovalItem* pFind = (*iter).second; - if (pFind) - { - // if the count is <= 0 and the interface is valid check the distance in case we found a removal (count is used to store if we have already removed - // this once) - if (pFind->m_iCount <= 0 && pFind->m_pInterface) - { - // Grab distances across each axis - float fDistanceX = fX - pFind->m_pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = fY - pFind->m_pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = fZ - pFind->m_pInterface->Placeable.m_transform.m_translate.fZ; - - if (pFind->m_pInterface->Placeable.matrix != NULL) - { - fDistanceX = fX - pFind->m_pInterface->Placeable.matrix->vPos.fX; - fDistanceY = fY - pFind->m_pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = fZ - pFind->m_pInterface->Placeable.matrix->vPos.fZ; - } - - // Square root 'em - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - - // Is it in range - if (fDistance <= fRange && (pFind->m_pInterface->m_areaCode == cInterior || cInterior == -1)) - { - CEntitySAInterface* pInterface = pFind->m_pInterface; - // while ( pInterface && pInterface != NULL ) - // if the interface is valid - if (pInterface && pInterface != NULL) - { - // if the building type is dummy or building and it's not already being removed - if ((pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY || pInterface->nType == ENTITY_TYPE_OBJECT) && - pInterface->bRemoveFromWorld != 1) - { - if ((DWORD)(pInterface->vtbl) != VTBL_CPlaceable) - { - // Add the Data Building to the list - pRemoval->AddDataBuilding(pInterface); - // Remove the model from the world - Remove(pInterface, BuildingRemoval2); - m_pRemovedEntities[(DWORD)pInterface] = true; - bFound = true; - } - } - // Get next LOD ( LOD's can have LOD's so we keep checking pInterface ) - // pInterface = pInterface->m_pLod; - } - // Set the count. - pFind->m_iCount = 1; - } - } - } - } - - std::pair::iterator, std::multimap::iterator> iteratorsBinary = - m_pBinaryBuildings->equal_range(usModelToRemove); - std::multimap::const_iterator iterBinary = iteratorsBinary.first; - for (; iterBinary != iteratorsBinary.second; ++iterBinary) - { - sBuildingRemovalItem* pFindBinary = (*iterBinary).second; - if (pFindBinary) - { - // if the count is <= 0 and the interface is valid check the distance in case we found a removal (count is used to store if we have already removed - // this once) - if (pFindBinary->m_iCount <= 0 && pFindBinary->m_pInterface) - { - // Grab distances across each axis - float fDistanceX = fX - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = fY - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = fZ - pFindBinary->m_pInterface->Placeable.m_transform.m_translate.fZ; - - if (pFindBinary->m_pInterface->Placeable.matrix != NULL) - { - fDistanceX = fX - pFindBinary->m_pInterface->Placeable.matrix->vPos.fX; - fDistanceY = fY - pFindBinary->m_pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = fZ - pFindBinary->m_pInterface->Placeable.matrix->vPos.fZ; - } - - // Square root 'em - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - - // Is it in range - if (fDistance <= fRange && (pFindBinary->m_pInterface->m_areaCode == cInterior || cInterior == -1)) - { - CEntitySAInterface* pInterface = pFindBinary->m_pInterface; - // while ( pInterface && pInterface != NULL ) - // if the interface is valid - if (pInterface && pInterface != NULL) - { - // if the building type is dummy or building and it's not already being removed - if ((pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY || pInterface->nType == ENTITY_TYPE_OBJECT) && - pInterface->bRemoveFromWorld != 1) - { - if ((DWORD)(pInterface->vtbl) != VTBL_CPlaceable) - { - // Add the Data Building to the list - pRemoval->AddBinaryBuilding(pInterface); - // Remove the model from the world - Remove(pInterface, BuildingRemoval2); - m_pRemovedEntities[(DWORD)pInterface] = true; - bFound = true; - ++uiAmount; - } - } - // Get next LOD ( LOD's can have LOD's so we keep checking pInterface ) - // pInterface = pInterface->m_pLod; - } - // Set the count. - pFindBinary->m_iCount = 1; - } - } - } - } - if (bFound) - pGame->GetModelInfo(usModelToRemove)->RestreamIPL(); - - if (pOutAmount) - *pOutAmount = uiAmount; -} - -bool CWorldSA::RestoreBuilding(unsigned short usModelToRestore, float fRange, float fX, float fY, float fZ, char cInterior, uint* pOutAmount) -{ - bool bSuccess = false; - uint uiAmount = 0; - - // Init some variables - std::pair::iterator, std::multimap::iterator> iterators = - m_pBuildingRemovals->equal_range(usModelToRestore); - std::multimap::const_iterator iter = iterators.first; - // Loop through the buildings list - for (; iter != iterators.second;) - { - SBuildingRemoval* pFind = (*iter).second; - // if pFind is valid and the model is the same - if (pFind) - { - // Grab distances across each axis - float fDistanceX = fX - pFind->m_vecPos.fX; - float fDistanceY = fY - pFind->m_vecPos.fY; - float fDistanceZ = fZ - pFind->m_vecPos.fZ; - - // Square root 'em - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - if (fDistance <= pFind->m_fRadius && (cInterior == -1 || pFind->m_cInterior == cInterior)) - { - // Init some variables - CEntitySAInterface* pEntity = NULL; - std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); - if (pFind->m_pBinaryRemoveList->empty() == false) - { - // Loop through the Binary object list - for (; entityIter != pFind->m_pBinaryRemoveList->end();) - { - // Grab the pEntity - pEntity = (*entityIter); - // if it's valid re-add it to the world. - if (pEntity != NULL) - { - // Remove it from the binary list - pFind->m_pBinaryRemoveList->erase(entityIter++); - // if the building type is dummy or building and it's not already being removed - if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && - pEntity->bRemoveFromWorld != 1) - { - // Don't call this on entities being removed. - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) - { - Add(pEntity, Building_Restore); - m_pRemovedEntities[(DWORD)pEntity] = false; - // If the building isn't streamed in, we won't find the building in the list (because the hook wasn't called) -> - // removeWorldModel doesn't work next time - AddBinaryBuilding(pEntity); - ++uiAmount; - } - } - } - else - ++entityIter; - } - } - // Start the iterator with the data remove list first item - entityIter = pFind->m_pDataRemoveList->begin(); - if (pFind->m_pDataRemoveList->empty() == false) - { - // Loop through the Data list - for (; entityIter != pFind->m_pDataRemoveList->end();) - { - // Grab the pEntity - pEntity = (*entityIter); - // if it's valid re-add it to the world. - if (pEntity != NULL) - { - pFind->m_pDataRemoveList->erase(entityIter++); - // if the building type is dummy or building and it's not already being removed - if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && - pEntity->bRemoveFromWorld != 1) - { - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) - { - Add(pEntity, Building_Restore2); - m_pRemovedEntities[(DWORD)pEntity] = false; - } - } - } - else - { - ++entityIter; - } - } - } - // Remove the building from the list - m_pBuildingRemovals->erase(iter++); - delete pFind; - // Success! don't return incase there are any others to delete - bSuccess = true; - } - else - iter++; - } - else - iter++; - } - std::pair::iterator, std::multimap::iterator> - dataBuildingIterators = m_pDataBuildings->equal_range(usModelToRestore); - std::multimap::const_iterator iterator = dataBuildingIterators.first; - for (; iterator != dataBuildingIterators.second; ++iterator) - { - sDataBuildingRemovalItem* pFound = (*iterator).second; - if (pFound) - { - // Grab distances across each axis - float fDistanceX = fX - pFound->m_pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = fY - pFound->m_pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = fZ - pFound->m_pInterface->Placeable.m_transform.m_translate.fZ; - - if (pFound->m_pInterface->Placeable.matrix != NULL) - { - fDistanceX = fX - pFound->m_pInterface->Placeable.matrix->vPos.fX; - fDistanceY = fY - pFound->m_pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = fZ - pFound->m_pInterface->Placeable.matrix->vPos.fZ; - } - - // Square root 'em - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - if (fDistance <= fRange && (cInterior == -1 || pFound->m_pInterface->m_areaCode == cInterior)) - { - // Fix the removed count. - pFound->m_iCount--; - if (pFound->m_iCount < 0) - pFound->m_iCount = 0; - } - } - } - - std::pair::iterator, std::multimap::iterator> - binaryBuildingIterators = m_pBinaryBuildings->equal_range(usModelToRestore); - std::multimap::const_iterator iteratorBinary = binaryBuildingIterators.first; - for (; iteratorBinary != binaryBuildingIterators.second; ++iteratorBinary) - { - sBuildingRemovalItem* pFoundBinary = (*iteratorBinary).second; - if (pFoundBinary) - { - // Grab distances across each axis - float fDistanceX = fX - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = fY - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = fZ - pFoundBinary->m_pInterface->Placeable.m_transform.m_translate.fZ; - - if (pFoundBinary->m_pInterface->Placeable.matrix != NULL) - { - fDistanceX = fX - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fX; - fDistanceY = fY - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = fZ - pFoundBinary->m_pInterface->Placeable.matrix->vPos.fZ; - } - - // Square root 'em - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - if (fDistance <= fRange && (cInterior == -1 || pFoundBinary->m_pInterface->m_areaCode == cInterior)) - { - // Fix the removed count. - pFoundBinary->m_iCount--; - if (pFoundBinary->m_iCount < 0) - pFoundBinary->m_iCount = 0; - } - } - } - - if (pOutAmount) - *pOutAmount = uiAmount; - - return bSuccess; -} - -// Check Distance to see if the model being requested is in the radius -bool CWorldSA::IsRemovedModelInRadius(SIPLInst* pInst) -{ - // Init some variables - std::pair::iterator, std::multimap::iterator> iterators = - m_pBuildingRemovals->equal_range(pInst->m_nModelIndex); - std::multimap::const_iterator iter = iterators.first; - // Loop through the buildings list - for (; iter != iterators.second; ++iter) - { - SBuildingRemoval* pFind = (*iter).second; - // if pFind is valid and the model is the same - if (pFind) - { - // Grab the distance - float fDistanceX = pFind->m_vecPos.fX - pInst->m_pPosition.fX; - float fDistanceY = pFind->m_vecPos.fY - pInst->m_pPosition.fY; - float fDistanceZ = pFind->m_vecPos.fZ - pInst->m_pPosition.fZ; - - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - // is it in the removal spheres radius if so return else keep looking - if (fDistance <= pFind->m_fRadius && (pFind->m_cInterior == -1 || pFind->m_cInterior == pInst->m_nAreaCode)) - { - return true; - } - } - } - return false; -} - -// Check Distance to see if the model being requested is in the radius -bool CWorldSA::IsObjectRemoved(CEntitySAInterface* pInterface) -{ - // Init some variables - std::pair::iterator, std::multimap::iterator> iterators = - m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); - std::multimap::const_iterator iter = iterators.first; - // Loop through the buildings list - for (; iter != iterators.second; ++iter) - { - SBuildingRemoval* pFind = (*iter).second; - // if pFind is valid and the model is the same - if (pFind) - { - // Are we using the interior param?? if so check for a match - if (pFind->m_cInterior == -1 || pFind->m_cInterior == pInterface->m_areaCode) - { - // Grab the distance - float fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.m_transform.m_translate.fZ; - - if (pInterface->Placeable.matrix != NULL) - { - fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.matrix->vPos.fX; - fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.matrix->vPos.fZ; - } - - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - // is it in the removal spheres radius if so return else keep looking - if (fDistance <= pFind->m_fRadius) - { - return true; - } - } - } - } - return false; -} - -// Check if a given model is replaced -bool CWorldSA::IsModelRemoved(unsigned short usModelID) -{ - return m_pBuildingRemovals->count(usModelID) > 0; -} - -// Check if a given model is replaced -bool CWorldSA::IsDataModelRemoved(unsigned short usModelID) -{ - return m_pBuildingRemovals->count(usModelID) > 0; -} - -// Check if a given model is replaced -bool CWorldSA::IsEntityRemoved(CEntitySAInterface* pInterface) -{ - return m_pRemovedEntities.find((DWORD)pInterface) != m_pRemovedEntities.end() && m_pRemovedEntities[(DWORD)pInterface] == true; -} - -// Resets deleted list -void CWorldSA::ClearRemovedBuildingLists(uint* pOutAmount) -{ - // Ensure no memory leaks by deleting items. - uint uiAmount = 0; - std::multimap::const_iterator iter = m_pBuildingRemovals->begin(); - - for (; iter != m_pBuildingRemovals->end();) - { - SBuildingRemoval* pFind = (*iter).second; - if (pFind) - { - // Init some variables - CEntitySAInterface* pEntity = NULL; - std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); - if (pFind->m_pBinaryRemoveList->empty() == false) - { - // Loop through the Binary remove list - for (; entityIter != pFind->m_pBinaryRemoveList->end(); ++entityIter) - { - // Grab the pEntity - pEntity = (*entityIter); - // if it's valid re-add it to the world. - if (pEntity && pEntity != NULL) - { - // if the building type is dummy or building and it's not already being removed - if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && - pEntity->bRemoveFromWorld != 1) - { - // Don't call this on entities being removed. - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) - { - Add(pEntity, BuildingRemovalReset); - m_pRemovedEntities[(DWORD)pEntity] = false; - ++uiAmount; - } - } - } - } - } - entityIter = pFind->m_pDataRemoveList->begin(); - if (pFind->m_pDataRemoveList->empty() == false) - { - // Loop through the Data list - for (; entityIter != pFind->m_pDataRemoveList->end(); ++entityIter) - { - // Grab the pEntity - pEntity = (*entityIter); - // if it's valid re-add it to the world. - if (pEntity && pEntity != NULL) - { - // if the building type is dummy or building and it's not already being removed - if ((pEntity->nType == ENTITY_TYPE_BUILDING || pEntity->nType == ENTITY_TYPE_DUMMY || pEntity->nType == ENTITY_TYPE_OBJECT) && - pEntity->bRemoveFromWorld != 1) - { - // Don't call this on entities being removed. - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) - { - Add(pEntity, BuildingRemovalReset2); - m_pRemovedEntities[(DWORD)pEntity] = false; - } - } - } - } - } - m_pBuildingRemovals->erase(iter++); - } - else - iter++; - } - // Init some variables - std::multimap::const_iterator iterator = m_pDataBuildings->begin(); - // Loop through the data building list - for (; iterator != m_pDataBuildings->end(); ++iterator) - { - sDataBuildingRemovalItem* pFound = (*iterator).second; - if (pFound) - { - // Set the count to 0 so we can remove it again - pFound->m_iCount = 0; - } - } - // Init some variables - std::multimap::const_iterator iteratorBinary = m_pBinaryBuildings->begin(); - // Loop through the data building list - for (; iteratorBinary != m_pBinaryBuildings->end(); ++iteratorBinary) - { - sBuildingRemovalItem* pFoundBinary = (*iteratorBinary).second; - if (pFoundBinary) - { - // Set the count to 0 so we can remove it again - pFoundBinary->m_iCount = 0; - } - } - // Delete old building lists - delete m_pBuildingRemovals; - // Create new - m_pBuildingRemovals = new std::multimap; - m_pRemovedEntities.clear(); - - if (pOutAmount) - *pOutAmount = uiAmount; -} - -// Resets deleted list -SBuildingRemoval* CWorldSA::GetBuildingRemoval(CEntitySAInterface* pInterface) -{ - // Init some variables - std::pair::iterator, std::multimap::iterator> iterators = - m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); - std::multimap::const_iterator iter = iterators.first; - // Loop through the buildings list - for (; iter != iterators.second; ++iter) - { - SBuildingRemoval* pFind = (*iter).second; - // if pFind is valid and the model is the same - if (pFind) - { - // Grab the distance - float fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.m_transform.m_translate.fX; - float fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.m_transform.m_translate.fY; - float fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.m_transform.m_translate.fZ; - - if (pInterface->Placeable.matrix != NULL) - { - fDistanceX = pFind->m_vecPos.fX - pInterface->Placeable.matrix->vPos.fX; - fDistanceY = pFind->m_vecPos.fY - pInterface->Placeable.matrix->vPos.fY; - fDistanceZ = pFind->m_vecPos.fZ - pInterface->Placeable.matrix->vPos.fZ; - } - - float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); - // is it in the removal spheres radius if so return else keep looking - if (fDistance <= pFind->m_fRadius && (pFind->m_cInterior == -1 || pFind->m_cInterior == pInterface->m_areaCode)) - { - return pFind; - } - } - } - return NULL; -} - -void CWorldSA::AddDataBuilding(CEntitySAInterface* pInterface) -{ - if (m_pAddedEntities.find((DWORD)pInterface) == m_pAddedEntities.end() || m_pAddedEntities[(DWORD)pInterface] == false) - { - // Create a new building removal - sDataBuildingRemovalItem* pBuildingRemoval = new sDataBuildingRemovalItem(pInterface, true); - // Insert it with the model index so we can fast lookup - m_pDataBuildings->insert(std::pair((unsigned short)pInterface->m_nModelIndex, pBuildingRemoval)); - m_pAddedEntities[(DWORD)pInterface] = true; - m_pRemovedEntities[(DWORD)pInterface] = false; - } -} - -void CWorldSA::AddBinaryBuilding(CEntitySAInterface* pInterface) -{ - if (m_pAddedEntities.find((DWORD)pInterface) == m_pAddedEntities.end() || m_pAddedEntities[(DWORD)pInterface] == false) - { - // Create a new building removal - sBuildingRemovalItem* pBuildingRemoval = new sBuildingRemovalItem(pInterface, false); - // Insert it with the model index so we can fast lookup - m_pBinaryBuildings->insert(std::pair((unsigned short)pInterface->m_nModelIndex, pBuildingRemoval)); - m_pAddedEntities[(DWORD)pInterface] = true; - m_pRemovedEntities[(DWORD)pInterface] = false; - } -} - -void CWorldSA::RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface) -{ - std::pair::iterator, std::multimap::iterator> iterators = - m_pBuildingRemovals->equal_range(pInterface->m_nModelIndex); - std::multimap::const_iterator iter = iterators.first; - - // Loop through the buildings list - for (; iter != iterators.second; ++iter) - { - SBuildingRemoval* pFind = (*iter).second; - // if pFind is valid and the model is the same - if (pFind) - { - CEntitySAInterface* pEntity = NULL; - // if the binary remove list is empty don't continue - if (pFind->m_pBinaryRemoveList->empty() == false) - { - // grab the beginning - std::list::const_iterator entityIter = pFind->m_pBinaryRemoveList->begin(); - // Loop through the binary remove list - for (; entityIter != pFind->m_pBinaryRemoveList->end();) - { - pEntity = (*entityIter); - // is the pointer the same as the one being deleted - if ((DWORD)pEntity == (DWORD)pInterface) - { - // remove it from the binary removed list for this removal - pFind->m_pBinaryRemoveList->erase(entityIter++); - } - else - entityIter++; - } - } - if (pFind->m_pDataRemoveList->empty() == false) - { - std::list::const_iterator entityIter = pFind->m_pDataRemoveList->begin(); - // Loop through the Data list - for (; entityIter != pFind->m_pDataRemoveList->end();) - { - // Grab the pEntity - pEntity = (*entityIter); - // is the pointer the same as the one being deleted - if ((DWORD)pEntity == (DWORD)pInterface) - { - // remove it from the data removed list for this removal - pFind->m_pDataRemoveList->erase(entityIter++); - } - else - entityIter++; - } - } - } - } - { - // Init some variables - std::pair::iterator, std::multimap::iterator> - dataIterators = m_pDataBuildings->equal_range(pInterface->m_nModelIndex); - std::multimap::const_iterator iterator = dataIterators.first; - for (; iterator != dataIterators.second;) - { - sDataBuildingRemovalItem* pFound = (*iterator).second; - if (pFound) - { - // is the pointer the same as the one being deleted - if ((DWORD)pFound->m_pInterface == (DWORD)pInterface) - { - // remove it from the data buildings list so we don't try and remove or add it again. - m_pDataBuildings->erase(iterator++); - } - else - iterator++; - } - else - iterator++; - } - } - { - // Init some variables - std::pair::iterator, std::multimap::iterator> - binaryIterators = m_pBinaryBuildings->equal_range(pInterface->m_nModelIndex); - std::multimap::const_iterator iteratorBinary = binaryIterators.first; - for (; iteratorBinary != binaryIterators.second;) - { - sBuildingRemovalItem* pFound = (*iteratorBinary).second; - if (pFound) - { - // is the pointer the same as the one being deleted - if ((DWORD)pFound->m_pInterface == (DWORD)pInterface) - { - // remove it from the data buildings list so we don't try and remove or add it again. - m_pBinaryBuildings->erase(iteratorBinary++); - } - else - iteratorBinary++; - } - else - iteratorBinary++; - } - } - m_pRemovedEntities[(DWORD)pInterface] = false; - m_pAddedEntities[(DWORD)pInterface] = false; -} - bool CWorldSA::CalculateImpactPosition(const CVector& vecInputStart, CVector& vecInputEnd) { // get our position diff --git a/Client/game_sa/CWorldSA.h b/Client/game_sa/CWorldSA.h index 5b18c9b35d..340db3ef5d 100644 --- a/Client/game_sa/CWorldSA.h +++ b/Client/game_sa/CWorldSA.h @@ -68,32 +68,13 @@ class CWorldSA : public CWorld bool GetOcclusionsEnabled(); void FindWorldPositionForRailTrackPosition(float fRailTrackPosition, int iTrackId, CVector* pOutVecPosition); int FindClosestRailTrackNode(const CVector& vecPosition, uchar& ucOutTrackId, float& fOutRailDistance); - - void RemoveBuilding(unsigned short usModelToRemove, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL); - bool IsRemovedModelInRadius(SIPLInst* pInst); - bool IsModelRemoved(unsigned short modelID); - void ClearRemovedBuildingLists(uint* pOutAmount = NULL); - bool RestoreBuilding(unsigned short usModelToRestore, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL); - SBuildingRemoval* GetBuildingRemoval(CEntitySAInterface* pInterface); - void AddDataBuilding(CEntitySAInterface* pInterface); - void RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface); - void AddBinaryBuilding(CEntitySAInterface* pInterface); - bool IsObjectRemoved(CEntitySAInterface* pInterface); - bool IsDataModelRemoved(unsigned short usModelID); - bool IsEntityRemoved(CEntitySAInterface* pInterface); - bool CalculateImpactPosition(const CVector& vecInputStart, CVector& vecInputEnd); + bool CalculateImpactPosition(const CVector& vecInputStart, CVector& vecInputEnd); CSurfaceType* GetSurfaceInfo() override; void ResetAllSurfaceInfo() override; bool ResetSurfaceInfo(short sSurfaceID) override; private: - std::multimap* m_pBuildingRemovals; - std::multimap* m_pDataBuildings; - std::multimap* m_pBinaryBuildings; - std::map* m_pRemovedObjects; - std::map m_pRemovedEntities; - std::map m_pAddedEntities; float m_fAircraftMaxHeight; CSurfaceType* m_pSurfaceInfo; }; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index f5ef243b4a..aef97392a5 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "CServerInfo.h" @@ -3425,7 +3426,7 @@ void CClientGame::Event_OnIngame() g_pMultiplayer->DeleteAndDisableGangTags(); - g_pGame->GetWorld()->ClearRemovedBuildingLists(); + g_pGame->GetBuildingRemoval()->ClearRemovedBuildingLists(); g_pGame->GetWorld()->SetOcclusionsEnabled(true); g_pGame->ResetModelLodDistances(); diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index d41c01ccb8..c8a12566da 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "net/SyncStructures.h" #include "CServerInfo.h" @@ -2641,7 +2642,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) { bitStream.Read(cInterior); } - g_pGame->GetWorld()->RemoveBuilding(usModel, fRadius, fX, fY, fZ, cInterior); + g_pGame->GetBuildingRemoval()->RemoveBuilding(usModel, fRadius, fX, fY, fZ, cInterior); } bool bOcclusionsEnabled = true; diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index cb0466e894..c42156883b 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include using std::list; @@ -6711,20 +6712,20 @@ bool CStaticFunctionDefinitions::AreTrafficLightsLocked(bool& bLocked) bool CStaticFunctionDefinitions::RemoveWorldBuilding(unsigned short usModelToRemove, float fRadius, float fX, float fY, float fZ, char cInterior, uint& uiOutAmount) { - g_pGame->GetWorld()->RemoveBuilding(usModelToRemove, fRadius, fX, fY, fZ, cInterior, &uiOutAmount); + g_pGame->GetBuildingRemoval()->RemoveBuilding(usModelToRemove, fRadius, fX, fY, fZ, cInterior, &uiOutAmount); return true; } bool CStaticFunctionDefinitions::RestoreWorldBuildings(uint& uiOutAmount) { - g_pGame->GetWorld()->ClearRemovedBuildingLists(&uiOutAmount); + g_pGame->GetBuildingRemoval()->ClearRemovedBuildingLists(&uiOutAmount); return true; } bool CStaticFunctionDefinitions::RestoreWorldBuilding(unsigned short usModelToRestore, float fRadius, float fX, float fY, float fZ, char cInterior, uint& uiOutAmount) { - return g_pGame->GetWorld()->RestoreBuilding(usModelToRestore, fRadius, fX, fY, fZ, cInterior, &uiOutAmount); + return g_pGame->GetBuildingRemoval()->RestoreBuilding(usModelToRestore, fRadius, fX, fY, fZ, cInterior, &uiOutAmount); } bool CStaticFunctionDefinitions::GetSkyGradient(unsigned char& ucTopRed, unsigned char& ucTopGreen, unsigned char& ucTopBlue, unsigned char& ucBottomRed, diff --git a/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp index 7b37f094df..e4c2d93e4b 100644 --- a/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CWorldRPCs.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "CWorldRPCs.h" void CWorldRPCs::LoadFunctions() @@ -582,7 +583,7 @@ void CWorldRPCs::RemoveWorldModel(NetBitStreamInterface& bitStream) { bitStream.Read(cInterior); } - g_pGame->GetWorld()->RemoveBuilding(usModel, fRadius, fX, fY, fZ, cInterior); + g_pGame->GetBuildingRemoval()->RemoveBuilding(usModel, fRadius, fX, fY, fZ, cInterior); } } @@ -597,13 +598,13 @@ void CWorldRPCs::RestoreWorldModel(NetBitStreamInterface& bitStream) { bitStream.Read(cInterior); } - g_pGame->GetWorld()->RestoreBuilding(usModel, fRadius, fX, fY, fZ, cInterior); + g_pGame->GetBuildingRemoval()->RestoreBuilding(usModel, fRadius, fX, fY, fZ, cInterior); } } void CWorldRPCs::RestoreAllWorldModels(NetBitStreamInterface& bitStream) { - g_pGame->GetWorld()->ClearRemovedBuildingLists(); + g_pGame->GetBuildingRemoval()->ClearRemovedBuildingLists(); } void CWorldRPCs::SetSyncIntervals(NetBitStreamInterface& bitStream) diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index f3f2c63f41..ad8f6eb576 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -11,6 +11,7 @@ #include "StdInc.h" #include +#include #include #include #include @@ -5853,15 +5854,15 @@ bool CheckRemovedModelNoSet() bNextHookSetModel = false; bCodePathCheck = bNextHookSetModel; pLODInterface = NULL; - CWorld* pWorld = pGameInterface->GetWorld(); + CBuildingRemoval* pBuildingRemoval = pGameInterface->GetBuildingRemoval(); // You never know. - if (pWorld) + if (pBuildingRemoval) { // Is the model in question even removed? - if (pWorld->IsModelRemoved(pEntityWorldAdd->m_nModelIndex)) + if (pBuildingRemoval->IsModelRemoved(pEntityWorldAdd->m_nModelIndex)) { // is the replaced model in the spherical radius of any building removal - if (pGameInterface->GetWorld()->IsRemovedModelInRadius(pEntityWorldAdd)) + if (pGameInterface->GetBuildingRemoval()->IsRemovedModelInRadius(pEntityWorldAdd)) { // if it is next hook remove it from the world return true; @@ -5912,7 +5913,7 @@ void HideEntitySomehow() // Init pInterface with the Initial model CEntitySAInterface* pInterface = pLODInterface; // Grab the removal for the interface - SBuildingRemoval* pBuildingRemoval = pGameInterface->GetWorld()->GetBuildingRemoval(pInterface); + SBuildingRemoval* pBuildingRemoval = pGameInterface->GetBuildingRemoval()->GetBuildingRemoval(pInterface); // Remove down the LOD tree if (pBuildingRemoval && pInterface && pInterface != NULL && pInterface->bIsProcObject == 0 && (pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY)) @@ -5932,7 +5933,7 @@ void HideEntitySomehow() if (pInterface && pInterface != NULL && pInterface->bIsProcObject == 0 && (pInterface->nType == ENTITY_TYPE_BUILDING || pInterface->nType == ENTITY_TYPE_DUMMY)) { - pGameInterface->GetWorld()->AddBinaryBuilding(pInterface); + pGameInterface->GetBuildingRemoval()->AddBinaryBuilding(pInterface); } } // Reset our next hook variable @@ -5962,7 +5963,7 @@ void StorePointerToBuilding() { if (pBuildingAdd != NULL) { - pGameInterface->GetWorld()->AddDataBuilding(pBuildingAdd); + pGameInterface->GetBuildingRemoval()->AddDataBuilding(pBuildingAdd); } } @@ -5991,7 +5992,7 @@ bool CheckForRemoval() // Init pInterface with the Initial model CEntitySAInterface* pInterface = pLODInterface; // Remove down the LOD tree - if (pGameInterface->GetWorld()->IsObjectRemoved(pInterface)) + if (pGameInterface->GetBuildingRemoval()->IsObjectRemoved(pInterface)) { return true; } @@ -6020,7 +6021,7 @@ void _declspec(naked) Hook_CWorld_ADD_CPopulation_ConvertToRealObject() void RemoveObjectIfNeeded() { TIMING_CHECKPOINT("+RemoveObjectIfNeeded"); - SBuildingRemoval* pBuildingRemoval = pGameInterface->GetWorld()->GetBuildingRemoval(pLODInterface); + SBuildingRemoval* pBuildingRemoval = pGameInterface->GetBuildingRemoval()->GetBuildingRemoval(pLODInterface); if (pBuildingRemoval != NULL) { if ((DWORD)(pBuildingAdd->vtbl) != VTBL_CPlaceable) @@ -6069,7 +6070,7 @@ void RemovePointerToBuilding() { if (pBuildingRemove->nType == ENTITY_TYPE_BUILDING || pBuildingRemove->nType == ENTITY_TYPE_DUMMY || pBuildingRemove->nType == ENTITY_TYPE_OBJECT) { - pGameInterface->GetWorld()->RemoveWorldBuildingFromLists(pBuildingRemove); + pGameInterface->GetBuildingRemoval()->RemoveWorldBuildingFromLists(pBuildingRemove); } } @@ -6099,7 +6100,7 @@ void _declspec(naked) HOOK_CWorld_Remove_CPopulation_ConvertToDummyObject() // if it's replaced get rid of it void RemoveDummyIfReplaced() { - SBuildingRemoval* pBuildingRemoval = pGameInterface->GetWorld()->GetBuildingRemoval(pLODInterface); + SBuildingRemoval* pBuildingRemoval = pGameInterface->GetBuildingRemoval()->GetBuildingRemoval(pLODInterface); if (pBuildingRemoval != NULL) { if ((DWORD)(pBuildingAdd->vtbl) != VTBL_CPlaceable) diff --git a/Client/sdk/game/CBuildingRemoval.h b/Client/sdk/game/CBuildingRemoval.h new file mode 100644 index 0000000000..d266b0f3de --- /dev/null +++ b/Client/sdk/game/CBuildingRemoval.h @@ -0,0 +1,124 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: sdk/game/CBuildingRemoval.h + * PURPOSE: Game world interface + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + + *****************************************************************************/ + +#pragma once + +#include + +class CEntitySAInterface; +class CVector; +class CVector4D; + +struct SBuildingRemoval +{ + SBuildingRemoval() + { + m_pBinaryRemoveList = new std::list; + m_pDataRemoveList = new std::list; + m_usModel = 0; + m_vecPos = CVector(0, 0, 0); + m_fRadius = 0.0f; + m_cInterior = -1; + } + + ~SBuildingRemoval() + { + delete m_pBinaryRemoveList; + delete m_pDataRemoveList; + } + + void AddBinaryBuilding(CEntitySAInterface* pInterface) + { + // Add to list of binary buildings for this removal + m_pBinaryRemoveList->push_back(pInterface); + } + void AddDataBuilding(CEntitySAInterface* pInterface) + { + // Add to list of data buildings for this removal + m_pDataRemoveList->push_back(pInterface); + } + + unsigned short m_usModel; + CVector m_vecPos; + float m_fRadius; + char m_cInterior; + std::list* m_pBinaryRemoveList; + std::list* m_pDataRemoveList; +}; + +struct sDataBuildingRemovalItem +{ + sDataBuildingRemovalItem(CEntitySAInterface* pInterface, bool bData) + { + m_pInterface = pInterface; + m_iCount = 0; + } + void AddCount() { m_iCount++; } + void RemoveCount() { m_iCount--; } + CEntitySAInterface* m_pInterface; + int m_iCount; +}; + +struct sBuildingRemovalItem +{ + sBuildingRemovalItem(CEntitySAInterface* pInterface, bool bData) + { + m_pInterface = pInterface; + m_iCount = 0; + } + void AddCount() { m_iCount++; } + void RemoveCount() { m_iCount--; } + CEntitySAInterface* m_pInterface; + int m_iCount; +}; + +struct SIPLInst +{ + CVector m_pPosition; + CVector4D m_pRotation; + int32_t m_nModelIndex; + union + { + struct + { + uint32_t m_nAreaCode : 8; + uint32_t m_bRedundantStream : 1; + uint32_t m_bDontStream : 1; + uint32_t m_bUnderwater : 1; + uint32_t m_bTunnel : 1; + uint32_t m_bTunnelTransition : 1; + uint32_t m_nReserved : 19; + }; + uint32_t m_nInstanceType; + }; + int32_t m_nLodInstanceIndex; +}; +static_assert(sizeof(SIPLInst) == 0x28, "Invalid sizeof(SIPLInst)"); + +class CBuildingRemoval +{ +public: + + virtual void RemoveBuilding(unsigned short usModelToRemove, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL) = 0; + virtual bool IsRemovedModelInRadius(SIPLInst* pInst) = 0; + virtual bool IsModelRemoved(unsigned short usModelID) = 0; + virtual void ClearRemovedBuildingLists(uint* pOutAmount = NULL) = 0; + virtual bool RestoreBuilding(unsigned short usModelToRestore, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL) = 0; + virtual SBuildingRemoval* GetBuildingRemoval(CEntitySAInterface* pInterface) = 0; + virtual void AddDataBuilding(CEntitySAInterface* pInterface) = 0; + virtual void AddBinaryBuilding(CEntitySAInterface* pInterface) = 0; + virtual void RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface) = 0; + virtual bool IsObjectRemoved(CEntitySAInterface* pInterface) = 0; + virtual bool IsDataModelRemoved(unsigned short usModelID) = 0; + virtual bool IsEntityRemoved(CEntitySAInterface* pInterface) = 0; + +}; diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index 77c2be24d9..c529609ee5 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -67,6 +67,7 @@ class CWeaponStatManager; class CWeather; class CWorld; class CIplStore; +class CBuildingRemoval; enum eEntityType; enum ePedPieceTypes; @@ -147,6 +148,7 @@ class __declspec(novtable) CGame virtual CWeaponStatManager* GetWeaponStatManager() = 0; virtual CPointLights* GetPointLights() = 0; virtual CColStore* GetCollisionStore() = 0; + virtual CBuildingRemoval* GetBuildingRemoval() = 0; virtual CWeaponInfo* GetWeaponInfo(eWeaponType weapon, eWeaponSkill skill = WEAPONSKILL_STD) = 0; virtual CModelInfo* GetModelInfo(DWORD dwModelID, bool bCanBeInvalid = false) = 0; diff --git a/Client/sdk/game/CWorld.h b/Client/sdk/game/CWorld.h index fb6be0baf8..3684172f01 100644 --- a/Client/sdk/game/CWorld.h +++ b/Client/sdk/game/CWorld.h @@ -13,7 +13,9 @@ class CEntitySAInterface; class CVector; +class CVector2D; class CColPoint; +class CEntity; struct SLineOfSightFlags { @@ -59,89 +61,6 @@ struct SProcessLineOfSightMaterialInfoResult { bool valid{}; //< Data found in this struct is only valid if this is `true`! }; -struct SBuildingRemoval -{ - SBuildingRemoval() - { - m_pBinaryRemoveList = new std::list; - m_pDataRemoveList = new std::list; - m_usModel = 0; - m_vecPos = CVector(0, 0, 0); - m_fRadius = 0.0f; - m_cInterior = -1; - } - - ~SBuildingRemoval() - { - delete m_pBinaryRemoveList; - delete m_pDataRemoveList; - } - - void AddBinaryBuilding(CEntitySAInterface* pInterface) - { - // Add to list of binary buildings for this removal - m_pBinaryRemoveList->push_back(pInterface); - } - void AddDataBuilding(CEntitySAInterface* pInterface) - { - // Add to list of data buildings for this removal - m_pDataRemoveList->push_back(pInterface); - } - - unsigned short m_usModel; - CVector m_vecPos; - float m_fRadius; - char m_cInterior; - std::list* m_pBinaryRemoveList; - std::list* m_pDataRemoveList; -}; - -struct SIPLInst -{ - CVector m_pPosition; - CVector4D m_pRotation; - int32_t m_nModelIndex; - union { - struct { - uint32_t m_nAreaCode : 8; - uint32_t m_bRedundantStream : 1; - uint32_t m_bDontStream : 1; - uint32_t m_bUnderwater : 1; - uint32_t m_bTunnel : 1; - uint32_t m_bTunnelTransition : 1; - uint32_t m_nReserved : 19; - }; - uint32_t m_nInstanceType; - }; - int32_t m_nLodInstanceIndex; -}; -static_assert(sizeof(SIPLInst) == 0x28, "Invalid sizeof(SIPLInst)"); - -struct sDataBuildingRemovalItem -{ - sDataBuildingRemovalItem(CEntitySAInterface* pInterface, bool bData) - { - m_pInterface = pInterface; - m_iCount = 0; - } - void AddCount() { m_iCount++; } - void RemoveCount() { m_iCount--; } - CEntitySAInterface* m_pInterface; - int m_iCount; -}; -struct sBuildingRemovalItem -{ - sBuildingRemovalItem(CEntitySAInterface* pInterface, bool bData) - { - m_pInterface = pInterface; - m_iCount = 0; - } - void AddCount() { m_iCount++; } - void RemoveCount() { m_iCount--; } - CEntitySAInterface* m_pInterface; - int m_iCount; -}; - enum eDebugCaller { CEntity_SetMatrix, @@ -350,20 +269,7 @@ class CWorld virtual bool GetOcclusionsEnabled() = 0; virtual void FindWorldPositionForRailTrackPosition(float fRailTrackPosition, int iTrackId, CVector* pOutVecPosition) = 0; virtual int FindClosestRailTrackNode(const CVector& vecPosition, uchar& ucOutTrackId, float& fOutRailDistance) = 0; - - virtual void RemoveBuilding(unsigned short usModelToRemove, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL) = 0; - virtual bool IsRemovedModelInRadius(SIPLInst* pInst) = 0; - virtual bool IsModelRemoved(unsigned short usModelID) = 0; - virtual void ClearRemovedBuildingLists(uint* pOutAmount = NULL) = 0; - virtual bool RestoreBuilding(unsigned short usModelToRestore, float fDistance, float fX, float fY, float fZ, char cInterior, uint* pOutAmount = NULL) = 0; - virtual SBuildingRemoval* GetBuildingRemoval(CEntitySAInterface* pInterface) = 0; - virtual void AddDataBuilding(CEntitySAInterface* pInterface) = 0; - virtual void AddBinaryBuilding(CEntitySAInterface* pInterface) = 0; - virtual void RemoveWorldBuildingFromLists(CEntitySAInterface* pInterface) = 0; - virtual bool IsObjectRemoved(CEntitySAInterface* pInterface) = 0; - virtual bool IsDataModelRemoved(unsigned short usModelID) = 0; - virtual bool IsEntityRemoved(CEntitySAInterface* pInterface) = 0; - virtual bool CalculateImpactPosition(const CVector& vecInputStart, CVector& vecInputEnd) = 0; + virtual bool CalculateImpactPosition(const CVector& vecInputStart, CVector& vecInputEnd) = 0; virtual CSurfaceType* GetSurfaceInfo() = 0; virtual void ResetAllSurfaceInfo() = 0;