diff --git a/Client/game_sa/CBuildingRemovalSA.cpp b/Client/game_sa/CBuildingRemovalSA.cpp index 122a1bba45e..95de2a21e9a 100644 --- a/Client/game_sa/CBuildingRemovalSA.cpp +++ b/Client/game_sa/CBuildingRemovalSA.cpp @@ -54,15 +54,15 @@ void CBuildingRemovalSA::RemoveBuilding(uint16_t usModelToRemove, float fRange, 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; + float fDistanceX = fX - pFind->m_pInterface->m_transform.m_translate.fX; + float fDistanceY = fY - pFind->m_pInterface->m_transform.m_translate.fY; + float fDistanceZ = fZ - pFind->m_pInterface->m_transform.m_translate.fZ; - if (pFind->m_pInterface->Placeable.matrix != NULL) + if (pFind->m_pInterface->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; + fDistanceX = fX - pFind->m_pInterface->matrix->vPos.fX; + fDistanceY = fY - pFind->m_pInterface->matrix->vPos.fY; + fDistanceZ = fZ - pFind->m_pInterface->matrix->vPos.fZ; } // Square root 'em @@ -80,7 +80,7 @@ void CBuildingRemovalSA::RemoveBuilding(uint16_t usModelToRemove, float fRange, 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) + if (!pInterface->IsPlaceableVTBL()) { // Add the Data Building to the list pRemoval->AddDataBuilding(pInterface); @@ -113,15 +113,15 @@ void CBuildingRemovalSA::RemoveBuilding(uint16_t usModelToRemove, float fRange, 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; + float fDistanceX = fX - pFindBinary->m_pInterface->m_transform.m_translate.fX; + float fDistanceY = fY - pFindBinary->m_pInterface->m_transform.m_translate.fY; + float fDistanceZ = fZ - pFindBinary->m_pInterface->m_transform.m_translate.fZ; - if (pFindBinary->m_pInterface->Placeable.matrix != NULL) + if (pFindBinary->m_pInterface->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; + fDistanceX = fX - pFindBinary->m_pInterface->matrix->vPos.fX; + fDistanceY = fY - pFindBinary->m_pInterface->matrix->vPos.fY; + fDistanceZ = fZ - pFindBinary->m_pInterface->matrix->vPos.fZ; } // Square root 'em @@ -139,7 +139,7 @@ void CBuildingRemovalSA::RemoveBuilding(uint16_t usModelToRemove, float fRange, 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) + if (!pInterface->IsPlaceableVTBL()) { // Add the Data Building to the list pRemoval->AddBinaryBuilding(pInterface); @@ -211,7 +211,7 @@ bool CBuildingRemovalSA::RestoreBuilding(uint16_t usModelToRestore, float fRange pEntity->bRemoveFromWorld != 1) { // Don't call this on entities being removed. - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + if (!pEntity->IsPlaceableVTBL()) { pGame->GetWorld()->Add(pEntity, Building_Restore); m_pRemovedEntities[(DWORD)pEntity] = false; @@ -243,7 +243,7 @@ bool CBuildingRemovalSA::RestoreBuilding(uint16_t usModelToRestore, float fRange 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) + if (!pEntity->IsPlaceableVTBL()) { pGame->GetWorld()->Add(pEntity, Building_Restore2); m_pRemovedEntities[(DWORD)pEntity] = false; @@ -277,15 +277,15 @@ bool CBuildingRemovalSA::RestoreBuilding(uint16_t usModelToRestore, float fRange 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; + float fDistanceX = fX - pFound->m_pInterface->m_transform.m_translate.fX; + float fDistanceY = fY - pFound->m_pInterface->m_transform.m_translate.fY; + float fDistanceZ = fZ - pFound->m_pInterface->m_transform.m_translate.fZ; - if (pFound->m_pInterface->Placeable.matrix != NULL) + if (pFound->m_pInterface->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; + fDistanceX = fX - pFound->m_pInterface->matrix->vPos.fX; + fDistanceY = fY - pFound->m_pInterface->matrix->vPos.fY; + fDistanceZ = fZ - pFound->m_pInterface->matrix->vPos.fZ; } // Square root 'em @@ -309,15 +309,15 @@ bool CBuildingRemovalSA::RestoreBuilding(uint16_t usModelToRestore, float fRange 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; + float fDistanceX = fX - pFoundBinary->m_pInterface->m_transform.m_translate.fX; + float fDistanceY = fY - pFoundBinary->m_pInterface->m_transform.m_translate.fY; + float fDistanceZ = fZ - pFoundBinary->m_pInterface->m_transform.m_translate.fZ; - if (pFoundBinary->m_pInterface->Placeable.matrix != NULL) + if (pFoundBinary->m_pInterface->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; + fDistanceX = fX - pFoundBinary->m_pInterface->matrix->vPos.fX; + fDistanceY = fY - pFoundBinary->m_pInterface->matrix->vPos.fY; + fDistanceZ = fZ - pFoundBinary->m_pInterface->matrix->vPos.fZ; } // Square root 'em @@ -386,15 +386,15 @@ bool CBuildingRemovalSA::IsObjectRemoved(CEntitySAInterface* pInterface) 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; + float fDistanceX = pFind->m_vecPos.fX - pInterface->m_transform.m_translate.fX; + float fDistanceY = pFind->m_vecPos.fY - pInterface->m_transform.m_translate.fY; + float fDistanceZ = pFind->m_vecPos.fZ - pInterface->m_transform.m_translate.fZ; - if (pInterface->Placeable.matrix != NULL) + if (pInterface->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; + fDistanceX = pFind->m_vecPos.fX - pInterface->matrix->vPos.fX; + fDistanceY = pFind->m_vecPos.fY - pInterface->matrix->vPos.fY; + fDistanceZ = pFind->m_vecPos.fZ - pInterface->matrix->vPos.fZ; } float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); @@ -457,7 +457,7 @@ void CBuildingRemovalSA::ClearRemovedBuildingLists(uint* pOutAmount) pEntity->bRemoveFromWorld != 1) { // Don't call this on entities being removed. - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + if (!pEntity->IsPlaceableVTBL()) { pGame->GetWorld()->Add(pEntity, BuildingRemovalReset); m_pRemovedEntities[(DWORD)pEntity] = false; @@ -483,7 +483,7 @@ void CBuildingRemovalSA::ClearRemovedBuildingLists(uint* pOutAmount) pEntity->bRemoveFromWorld != 1) { // Don't call this on entities being removed. - if ((DWORD)(pEntity->vtbl) != VTBL_CPlaceable) + if (!pEntity->IsPlaceableVTBL()) { pGame->GetWorld()->Add(pEntity, BuildingRemovalReset2); m_pRemovedEntities[(DWORD)pEntity] = false; @@ -546,15 +546,15 @@ SBuildingRemoval* CBuildingRemovalSA::GetBuildingRemoval(CEntitySAInterface* pIn 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; + float fDistanceX = pFind->m_vecPos.fX - pInterface->m_transform.m_translate.fX; + float fDistanceY = pFind->m_vecPos.fY - pInterface->m_transform.m_translate.fY; + float fDistanceZ = pFind->m_vecPos.fZ - pInterface->m_transform.m_translate.fZ; - if (pInterface->Placeable.matrix != NULL) + if (pInterface->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; + fDistanceX = pFind->m_vecPos.fX - pInterface->matrix->vPos.fX; + fDistanceY = pFind->m_vecPos.fY - pInterface->matrix->vPos.fY; + fDistanceZ = pFind->m_vecPos.fZ - pInterface->matrix->vPos.fZ; } float fDistance = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY + fDistanceZ * fDistanceZ); diff --git a/Client/game_sa/CBuildingSA.cpp b/Client/game_sa/CBuildingSA.cpp index 09b8e96e7f7..b636fddd4b7 100644 --- a/Client/game_sa/CBuildingSA.cpp +++ b/Client/game_sa/CBuildingSA.cpp @@ -74,9 +74,9 @@ void CBuildingSA::AllocateMatrix() { auto* newMatrix = g_matrixPool.AllocateItem(); std::memset(newMatrix, 0, sizeof(CMatrixLinkSAInterface)); - newMatrix->SetTranslateOnly(m_pInterface->Placeable.m_transform.m_translate); + newMatrix->SetTranslateOnly(m_pInterface->m_transform.m_translate); - m_pInterface->Placeable.matrix = reinterpret_cast(newMatrix); + m_pInterface->matrix = reinterpret_cast(newMatrix); } void CBuildingSA::ReallocateMatrix() @@ -85,13 +85,13 @@ void CBuildingSA::ReallocateMatrix() return; auto* newMatrix = g_matrixPool.AllocateItem(); - std::memcpy(newMatrix, m_pInterface->Placeable.matrix, sizeof(CMatrixLinkSAInterface)); + std::memcpy(newMatrix, m_pInterface->matrix, sizeof(CMatrixLinkSAInterface)); newMatrix->m_pOwner = nullptr; newMatrix->m_pPrev = nullptr; newMatrix->m_pNext = nullptr; m_pInterface->RemoveMatrix(); - m_pInterface->Placeable.matrix = reinterpret_cast(newMatrix); + m_pInterface->matrix = reinterpret_cast(newMatrix); } void CBuildingSA::RemoveAllocatedMatrix() @@ -99,12 +99,12 @@ void CBuildingSA::RemoveAllocatedMatrix() if (!m_pInterface->HasMatrix()) return; - CMatrixLinkSAInterface* pMatrix = reinterpret_cast(m_pInterface->Placeable.matrix); + CMatrixLinkSAInterface* pMatrix = reinterpret_cast(m_pInterface->matrix); if (pMatrix->m_pOwner || (pMatrix->m_pNext && pMatrix->m_pPrev)) return; - g_matrixPool.RemoveItem(reinterpret_cast(m_pInterface->Placeable.matrix)); + g_matrixPool.RemoveItem(reinterpret_cast(m_pInterface->matrix)); g_matrixPool.SetCapacity(0); - m_pInterface->Placeable.matrix = nullptr; + m_pInterface->matrix = nullptr; } diff --git a/Client/game_sa/CBuildingsPoolSA.cpp b/Client/game_sa/CBuildingsPoolSA.cpp index 04da84e9255..ae51fa06734 100644 --- a/Client/game_sa/CBuildingsPoolSA.cpp +++ b/Client/game_sa/CBuildingsPoolSA.cpp @@ -148,7 +148,7 @@ void CBuildingsPoolSA::RemoveBuilding(CBuilding* pBuilding) std::uint16_t modelId = pInterface->m_nModelIndex; // Call virtual destructor - ((void*(__thiscall*)(void*, char))pInterface->vtbl->SCALAR_DELETING_DESTRUCTOR)(pInterface, 0); + pInterface->Destructor(false); // Remove col reference auto modelInfo = pGame->GetModelInfo(modelId); @@ -172,7 +172,7 @@ void CBuildingsPoolSA::RemoveAllWithBackup() if (m_pOriginalBuildingsBackup) return; - m_pOriginalBuildingsBackup = std::make_unique, MAX_BUILDINGS>>(); + m_pOriginalBuildingsBackup = std::make_unique(); auto pBuildsingsPool = (*m_ppBuildingPoolInterface); for (size_t i = 0; i < MAX_BUILDINGS; i++) @@ -189,7 +189,7 @@ void CBuildingsPoolSA::RemoveAllWithBackup() pBuildsingsPool->Release(i); (*m_pOriginalBuildingsBackup)[i].first = true; - (*m_pOriginalBuildingsBackup)[i].second = *building; + std::memcpy(&(*m_pOriginalBuildingsBackup)[i].second, building, sizeof(CBuildingSAInterface)); } else { @@ -212,9 +212,8 @@ void CBuildingsPoolSA::RestoreBackup() { if (originalData[i].first) { - pBuildsingsPool->AllocateAt(i); - auto pBuilding = pBuildsingsPool->GetObject(i); - *pBuilding = originalData[i].second; + auto* pBuilding = pBuildsingsPool->AllocateAtNoInit(i); + std::memcpy(pBuilding, &originalData[i].second, sizeof(CBuildingSAInterface)); worldSA->Add(pBuilding, CBuildingPool_Constructor); buildingRemovealSA->AddDataBuilding(pBuilding); @@ -322,13 +321,13 @@ void CBuildingsPoolSA::UpdateIplEntrysPointers(uint32_t offset) void CBuildingsPoolSA::UpdateBackupLodPointers(uint32_t offset) { - std::array, MAX_BUILDINGS> *arr = m_pOriginalBuildingsBackup.get(); + backup_array_t* arr = m_pOriginalBuildingsBackup.get(); for (auto i = 0; i < MAX_BUILDINGS; i++) { - std::pair* data = &(*arr)[i]; + std::pair* data = &(*arr)[i]; if (data->first) { - CBuildingSAInterface* building = &data->second; + CBuildingSAInterface* building = reinterpret_cast(&data->second); if (building->m_pLod != nullptr) { building->m_pLod = (CBuildingSAInterface*)((uint32_t)building->m_pLod + offset); diff --git a/Client/game_sa/CBuildingsPoolSA.h b/Client/game_sa/CBuildingsPoolSA.h index ba68918d41e..4e5007ba05a 100644 --- a/Client/game_sa/CBuildingsPoolSA.h +++ b/Client/game_sa/CBuildingsPoolSA.h @@ -44,5 +44,8 @@ class CBuildingsPoolSA : public CBuildingsPool SVectorPoolData m_buildingPool{MAX_BUILDINGS}; CPoolSAInterface** m_ppBuildingPoolInterface; - std::unique_ptr, MAX_BUILDINGS>> m_pOriginalBuildingsBackup; + using building_buffer_t = std::uint8_t[sizeof(CBuildingSAInterface)]; + using backup_array_t = std::array, MAX_BUILDINGS>; + + std::unique_ptr m_pOriginalBuildingsBackup; }; diff --git a/Client/game_sa/CCameraSA.cpp b/Client/game_sa/CCameraSA.cpp index 2e8f6b6eb81..a485934561e 100644 --- a/Client/game_sa/CCameraSA.cpp +++ b/Client/game_sa/CCameraSA.cpp @@ -187,7 +187,7 @@ void CCameraSA::RestoreLastGoodState() CMatrix* CCameraSA::GetMatrix(CMatrix* matrix) { - CMatrix_Padded* pCamMatrix = &GetInterface()->m_cameraMatrix; // ->Placeable.matrix; + CMatrix_Padded* pCamMatrix = &GetInterface()->m_cameraMatrix; // ->matrix; if (pCamMatrix) { matrix->vFront = pCamMatrix->vFront; @@ -210,7 +210,7 @@ CMatrix* CCameraSA::GetMatrix(CMatrix* matrix) void CCameraSA::SetMatrix(CMatrix* matrix) { - CMatrix_Padded* pCamMatrix = GetInterface()->Placeable.matrix; + CMatrix_Padded* pCamMatrix = GetInterface()->matrix; if (pCamMatrix) { pCamMatrix->vFront = matrix->vFront; diff --git a/Client/game_sa/CCameraSA.h b/Client/game_sa/CCameraSA.h index 6ccf5fe4719..4ffd6d270ab 100644 --- a/Client/game_sa/CCameraSA.h +++ b/Client/game_sa/CCameraSA.h @@ -77,14 +77,9 @@ class CTrainCamNode /*** END PURE R* CLASSES ***/ -class CCameraSAInterface +class CCameraSAInterface : public CPlaceableSAInterface { public: - // CPlaceable - CPlaceableSAInterface Placeable; - std::uint8_t specialPadding[4]; // Temporary padding due to incorrect CPlaceableSAInterface class - // End CPlaceable - // move these out the class, have decided to set up a mirrored enumerated type thingy at the top bool m_bAboveGroundTrainNodesLoaded; bool m_bBelowGroundTrainNodesLoaded; diff --git a/Client/game_sa/CDummyPoolSA.cpp b/Client/game_sa/CDummyPoolSA.cpp index 6a67cdb9000..cc29446e450 100644 --- a/Client/game_sa/CDummyPoolSA.cpp +++ b/Client/game_sa/CDummyPoolSA.cpp @@ -43,7 +43,7 @@ void CDummyPoolSA::RemoveAllWithBackup() pDummyPool->Release(i); (*m_pOriginalElementsBackup)[i].first = true; - (*m_pOriginalElementsBackup)[i].second = *building; + std::memcpy((*m_pOriginalElementsBackup)[i].second, building, sizeof(CEntitySAInterface)); } else { @@ -63,9 +63,9 @@ void CDummyPoolSA::RestoreBackup() { if (originalData[i].first) { - pDummyPool->AllocateAt(i); + pDummyPool->AllocateAtNoInit(i); auto pDummy = pDummyPool->GetObject(i); - *pDummy = originalData[i].second; + std::memcpy(pDummy, &originalData[i].second, sizeof(CEntitySAInterface)); pGame->GetWorld()->Add(pDummy, CDummyPool_Constructor); } @@ -88,7 +88,7 @@ void CDummyPoolSA::UpdateBackupLodOffset(const std::uint32_t offset) { if (it.first) { - CEntitySAInterface* object = &it.second; + CEntitySAInterface* object = reinterpret_cast(&it.second); CEntitySAInterface* lod = object->GetLod(); if (lod) object->SetLod((CEntitySAInterface*)((std::uint32_t)lod + offset)); diff --git a/Client/game_sa/CDummyPoolSA.h b/Client/game_sa/CDummyPoolSA.h index 8f42d98c7c1..d23a0550961 100644 --- a/Client/game_sa/CDummyPoolSA.h +++ b/Client/game_sa/CDummyPoolSA.h @@ -35,6 +35,7 @@ class CDummyPoolSA final : public CDummyPool private: CPoolSAInterface** m_ppDummyPoolInterface; - using pool_backup_t = std::array, MAX_DUMMIES_DEFAULT>; + using building_buffer_t = std::uint8_t[sizeof(CEntitySAInterface)]; + using pool_backup_t = std::array, MAX_DUMMIES_DEFAULT>; std::unique_ptr m_pOriginalElementsBackup; }; diff --git a/Client/game_sa/CEntitySA.cpp b/Client/game_sa/CEntitySA.cpp index 4c1d6be7dc4..10ceffcd4d4 100644 --- a/Client/game_sa/CEntitySA.cpp +++ b/Client/game_sa/CEntitySA.cpp @@ -101,14 +101,14 @@ void CEntitySA::SetPosition(float fX, float fY, float fZ) { // Remove & add to world? CVector* vecPos; - if (m_pInterface->Placeable.matrix) + if (m_pInterface->matrix) { OnChangingPosition(CVector(fX, fY, fZ)); - vecPos = &m_pInterface->Placeable.matrix->vPos; + vecPos = &m_pInterface->matrix->vPos; } else { - vecPos = &m_pInterface->Placeable.m_transform.m_translate; + vecPos = &m_pInterface->m_transform.m_translate; } if (vecPos) @@ -139,21 +139,10 @@ void CEntitySA::SetPosition(float fX, float fY, float fZ) void CEntitySA::Teleport(float fX, float fY, float fZ) { - if (m_pInterface->Placeable.matrix) + if (m_pInterface->matrix) { SetPosition(fX, fY, fZ); - - DWORD dwFunc = m_pInterface->vtbl->Teleport; - DWORD dwThis = (DWORD)m_pInterface; - _asm - { - mov ecx, dwThis - push 1 - push fZ - push fY - push fX - call dwFunc - } + m_pInterface->Teleport(CVector(fX, fY, fZ), true); } else { @@ -163,34 +152,18 @@ void CEntitySA::Teleport(float fX, float fY, float fZ) void CEntitySA::ProcessControl() { - DWORD dwFunc = m_pInterface->vtbl->ProcessControl; - DWORD dwThis = (DWORD)m_pInterface; - if (dwFunc) - { - _asm - { - mov ecx, dwThis - call dwFunc - } - } + m_pInterface->ProcessControl(); } void CEntitySA::SetupLighting() { - DWORD dwFunc = m_pInterface->vtbl->SetupLighting; - DWORD dwThis = (DWORD)m_pInterface; - if (dwFunc) - { - _asm - { - mov ecx, dwThis - call dwFunc - } - } + m_pInterface->SetupLighting(); } +// Remove this function? void CEntitySA::Render() { + // This function may use m_pInterface->Render() DWORD dwFunc = 0x59F180; // m_pInterface->vtbl->Render; DWORD dwThis = (DWORD)m_pInterface; _asm @@ -198,16 +171,6 @@ void CEntitySA::Render() mov ecx, dwThis call dwFunc } - - /* DWORD dwFunc = 0x553260; - DWORD dwThis = (DWORD) m_pInterface; - - _asm - { - push dwThis - call dwFunc - add esp, 4 - }*/ } void CEntitySA::SetOrientation(float fX, float fY, float fZ) @@ -295,10 +258,10 @@ CVector* CEntitySA::GetPosition() CVector* CEntitySA::GetPositionInternal() { - if (m_pInterface->Placeable.matrix) - return &m_pInterface->Placeable.matrix->vPos; + if (m_pInterface->matrix) + return &m_pInterface->matrix->vPos; else - return &m_pInterface->Placeable.m_transform.m_translate; + return &m_pInterface->m_transform.m_translate; } // @@ -321,12 +284,12 @@ CMatrix* CEntitySA::GetMatrix(CMatrix* matrix) CMatrix* CEntitySA::GetMatrixInternal(CMatrix* matrix) { - if (m_pInterface->Placeable.matrix && matrix) + if (m_pInterface->matrix && matrix) { - MemCpyFast(&matrix->vFront, &m_pInterface->Placeable.matrix->vFront, sizeof(CVector)); - MemCpyFast(&matrix->vPos, &m_pInterface->Placeable.matrix->vPos, sizeof(CVector)); - MemCpyFast(&matrix->vUp, &m_pInterface->Placeable.matrix->vUp, sizeof(CVector)); - MemCpyFast(&matrix->vRight, &m_pInterface->Placeable.matrix->vRight, sizeof(CVector)); + MemCpyFast(&matrix->vFront, &m_pInterface->matrix->vFront, sizeof(CVector)); + MemCpyFast(&matrix->vPos, &m_pInterface->matrix->vPos, sizeof(CVector)); + MemCpyFast(&matrix->vUp, &m_pInterface->matrix->vUp, sizeof(CVector)); + MemCpyFast(&matrix->vRight, &m_pInterface->matrix->vRight, sizeof(CVector)); return matrix; } else @@ -337,16 +300,16 @@ CMatrix* CEntitySA::GetMatrixInternal(CMatrix* matrix) void CEntitySA::SetMatrix(CMatrix* matrix) { - if (m_pInterface->Placeable.matrix && matrix) + if (m_pInterface->matrix && matrix) { OnChangingPosition(matrix->vPos); - MemCpyFast(&m_pInterface->Placeable.matrix->vFront, &matrix->vFront, sizeof(CVector)); - MemCpyFast(&m_pInterface->Placeable.matrix->vPos, &matrix->vPos, sizeof(CVector)); - MemCpyFast(&m_pInterface->Placeable.matrix->vUp, &matrix->vUp, sizeof(CVector)); - MemCpyFast(&m_pInterface->Placeable.matrix->vRight, &matrix->vRight, sizeof(CVector)); + MemCpyFast(&m_pInterface->matrix->vFront, &matrix->vFront, sizeof(CVector)); + MemCpyFast(&m_pInterface->matrix->vPos, &matrix->vPos, sizeof(CVector)); + MemCpyFast(&m_pInterface->matrix->vUp, &matrix->vUp, sizeof(CVector)); + MemCpyFast(&m_pInterface->matrix->vRight, &matrix->vRight, sizeof(CVector)); - m_pInterface->Placeable.m_transform.m_translate = matrix->vPos; + m_pInterface->m_transform.m_translate = matrix->vPos; m_LastGoodPosition = matrix->vPos; /* @@ -490,7 +453,7 @@ void CEntitySA::SetVisible(bool bVisible) void CEntitySA::MatrixConvertFromEulerAngles(float fX, float fY, float fZ, int iUnknown) { - CMatrix_Padded* matrixPadded = m_pInterface->Placeable.matrix; + CMatrix_Padded* matrixPadded = m_pInterface->matrix; if (matrixPadded) { DWORD dwFunc = FUNC_CMatrix__ConvertFromEulerAngles; @@ -508,7 +471,7 @@ void CEntitySA::MatrixConvertFromEulerAngles(float fX, float fY, float fZ, int i void CEntitySA::MatrixConvertToEulerAngles(float* fX, float* fY, float* fZ, int iUnknown) { - CMatrix_Padded* matrixPadded = m_pInterface->Placeable.matrix; + CMatrix_Padded* matrixPadded = m_pInterface->matrix; if (matrixPadded) { DWORD dwFunc = FUNC_CMatrix__ConvertToEulerAngles; diff --git a/Client/game_sa/CEntitySA.h b/Client/game_sa/CEntitySA.h index 36b3faa098d..bdcbcfce849 100644 --- a/Client/game_sa/CEntitySA.h +++ b/Client/game_sa/CEntitySA.h @@ -12,10 +12,9 @@ #pragma once #include +#include "CPlaceableSA.h" #include -#include #include -#include #define FUNC_GetDistanceFromCentreOfMassToBaseOfModel 0x536BE0 @@ -29,33 +28,8 @@ // not in CEntity really #define FUNC_RpAnimBlendClumpGetAssociation 0x4D6870 +class CPhysicalSAInterface; class CRect; -class CEntitySAInterfaceVTBL -{ -public: - DWORD SCALAR_DELETING_DESTRUCTOR; // +0h - DWORD Add_CRect; // +4h - DWORD Add; // +8h - DWORD Remove; // +Ch - DWORD SetIsStatic; // +10h - DWORD SetModelIndex; // +14h - DWORD SetModelIndexNoCreate; // +18h - DWORD CreateRwObject; // +1Ch - DWORD DeleteRwObject; // +20h - DWORD GetBoundRect; // +24h - DWORD ProcessControl; // +28h - DWORD ProcessCollision; // +2Ch - DWORD ProcessShift; // +30h - DWORD TestCollision; // +34h - DWORD Teleport; // +38h - DWORD SpecialEntityPreCollisionStuff; // +3Ch - DWORD SpecialEntityCalcCollisionSteps; // +40h - DWORD PreRender; // +44h - DWORD Render; // +48h - DWORD SetupLighting; // +4Ch - DWORD RemoveLighting; // +50h - DWORD FlagToDestroyWhenNextProcessed; // +54h -}; /** * \todo Move CReferences (and others below?) into it's own file @@ -105,27 +79,33 @@ class XYZStore }; static_assert(sizeof(XYZStore) == 0x1FC, "Invalid size for XYZStore"); -class CSimpleTransformSAInterface // 16 bytes -{ -public: - CVector m_translate; - float m_heading; -}; - -class CPlaceableSAInterface // 20 bytes +class CEntitySAInterface : public CPlaceableSAInterface { public: - CSimpleTransformSAInterface m_transform; - CMatrix_Padded* matrix; // This is actually XYZ*, change later -}; + virtual void Add() = 0; + virtual void Add(const CRect& rect) = 0; + virtual void Remove() = 0; + virtual void SetIsStatic(bool isStatic) = 0; + virtual void SetModelIndex(std::uint32_t model) = 0; + virtual void SetModelIndexNoCreate(std::uint32_t model) = 0; + virtual void CreateRwObject() = 0; + virtual void DeleteRwObject() = 0; + virtual CRect GetBoundRect() = 0; + virtual void ProcessControl() = 0; + virtual void ProcessCollision() = 0; + virtual void ProcessShift() = 0; + virtual bool TestCollision(bool bApplySpeed) = 0; + virtual void Teleport(CVector destination, bool resetRotation) = 0; + virtual void SpecialEntityPreCollisionStuff(CPhysicalSAInterface* colPhysical, bool bIgnoreStuckCheck, bool& bCollisionDisabled, + bool& bCollidedEntityCollisionIgnored, bool& bCollidedEntityUnableToMove, bool& bThisOrCollidedEntityStuck) = 0; + virtual std::uint8_t SpecialEntityCalcCollisionSteps(bool& bProcessCollisionBeforeSettingTimeStep, bool& unk2) = 0; + virtual void PreRender() = 0; + virtual void Render() = 0; + virtual bool SetupLighting() = 0; + virtual void* RemoveLighting(bool bRemove) = 0; + virtual void FlagToDestroyWhenNextProcessed() = 0; -class CEntitySAInterface -{ public: - CEntitySAInterfaceVTBL* vtbl; // the virtual table it should be in the CPlaceableSAInterface - - CPlaceableSAInterface Placeable; // 4 - RpClump* m_pRwObject; // 24 /********** BEGIN CFLAGS **************/ unsigned long bUsesCollision : 1; // does entity use collision @@ -239,28 +219,13 @@ class CEntitySAInterface ((CStencilShadow_dtorByOwner)0x711730)(this); }; - void DeleteRwObject() - { - using vtbl_DeleteRwObject = void(__thiscall*)(CEntitySAInterface * pEntity); - ((vtbl_DeleteRwObject)this->vtbl->DeleteRwObject)(this); - }; - - void SetOrientation(float x, float y, float z) { - using CPlacetable_SetOrientation = void(__thiscall*)(CEntitySAInterface * pEntity, float, float, float); - ((CPlacetable_SetOrientation)0x439A80)(this, x, y, z); - } - void RemoveRWObjectWithReferencesCleanup() { DeleteRwObject(); ResolveReferences(); RemoveShadows(); } - - bool HasMatrix() const noexcept { return Placeable.matrix != nullptr; } - - void RemoveMatrix() { ((void(__thiscall*)(void*))0x54F3B0)(this); } - }; + static_assert(sizeof(CEntitySAInterface) == 0x38, "Invalid size for CEntitySAInterface"); class CEntitySA : public virtual CEntity diff --git a/Client/game_sa/CModelInfoSA.cpp b/Client/game_sa/CModelInfoSA.cpp index 16eecbc9978..715515f488c 100644 --- a/Client/game_sa/CModelInfoSA.cpp +++ b/Client/game_sa/CModelInfoSA.cpp @@ -1000,14 +1000,15 @@ void CModelInfoSA::StaticFlushPendingRestreamIPL() CEntitySAInterface* pEntity = (CEntitySAInterface*)pSectorEntry[0]; // Possible bug - pEntity seems to be invalid here occasionally - if (pEntity->vtbl->DeleteRwObject != 0x00534030) + constexpr auto CEntity_DeleteRwObject_VTBL_OFFSET = 8; + if (static_cast(pEntity->GetVTBL())[CEntity_DeleteRwObject_VTBL_OFFSET] != 0x00534030) { // Log info OutputDebugString(SString("Entity 0x%08x (with model %d) at ARRAY_StreamSectors[%d,%d] is invalid\n", pEntity, pEntity->m_nModelIndex, i / 2 % NUM_StreamSectorRows, i / 2 / NUM_StreamSectorCols)); // Assert in debug #if MTA_DEBUG - assert(pEntity->vtbl->DeleteRwObject == 0x00534030); + assert(static_cast(pEntity->GetVTBL())[CEntity_DeleteRwObject_VTBL_OFFSET] != 0x00534030); #endif pSectorEntry = (DWORD*)pSectorEntry[1]; continue; diff --git a/Client/game_sa/CObjectSA.cpp b/Client/game_sa/CObjectSA.cpp index 83d2feef23e..bfcad0ea44c 100644 --- a/Client/game_sa/CObjectSA.cpp +++ b/Client/game_sa/CObjectSA.cpp @@ -146,18 +146,12 @@ CObjectSA::~CObjectSA() { pGame->GetRopes()->RemoveEntityRope(pInterface); - if ((DWORD)pInterface->vtbl != VTBL_CPlaceable) + if (!pInterface->IsPlaceableVTBL()) { CWorldSA* world = (CWorldSA*)pGame->GetWorld(); world->Remove(pInterface, CObject_Destructor); - DWORD dwFunc = pInterface->vtbl->SCALAR_DELETING_DESTRUCTOR; // we use the vtbl so we can be type independent - _asm - { - mov ecx, pInterface - push 1 // delete too - call dwFunc - } + pInterface->Destructor(true); } } @@ -233,22 +227,10 @@ float CObjectSA::GetHealth() void CObjectSA::SetModelIndex(unsigned long ulModel) { // Delete any existing RwObject first - DWORD dwFunc = GetInterface()->vtbl->DeleteRwObject; - DWORD dwThis = (DWORD)GetInterface(); - _asm - { - mov ecx, dwThis - call dwFunc - } + GetInterface()->DeleteRwObject(); - // Jax: I'm not sure if using the vtbl is right (as ped and vehicle dont), but it works - dwFunc = GetInterface()->vtbl->SetModelIndex; - _asm - { - mov ecx, dwThis - push ulModel - call dwFunc - } + // Jax: I'm not sure if using the virtual method is right (as ped and vehicle dont), but it works + GetInterface()->SetModelIndex(ulModel); CheckForGangTag(); } diff --git a/Client/game_sa/CPhysicalSA.h b/Client/game_sa/CPhysicalSA.h index a1236f371b7..c9aa1fb6c26 100644 --- a/Client/game_sa/CPhysicalSA.h +++ b/Client/game_sa/CPhysicalSA.h @@ -16,6 +16,8 @@ #include #include "CPtrNodeDoubleListSA.h" +class CColPointSAInterface; + #define FUNC_GetMoveSpeed 0x404460 #define FUNC_GetTurnSpeed 0x470030 #define FUNC_ProcessCollision 0x54DFB0 @@ -29,6 +31,8 @@ class CPhysicalSAInterface : public CEntitySAInterface { + virtual std::int32_t ProcessEntityCollision(CEntitySAInterface* entity, CColPointSAInterface* colPoint) = 0; + public: float pad1; // 56 uint32 pad2; // 60 diff --git a/Client/game_sa/CPlaceableSA.h b/Client/game_sa/CPlaceableSA.h new file mode 100644 index 00000000000..5869680b81c --- /dev/null +++ b/Client/game_sa/CPlaceableSA.h @@ -0,0 +1,38 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include +#include + +class CSimpleTransformSAInterface // 16 bytes +{ +public: + CVector m_translate; + float m_heading; +}; + +class CPlaceableSAInterface +{ +public: + virtual void* Destructor(bool free) = 0; + + void* GetVTBL() const { return *reinterpret_cast(this); } + bool HasVTBL() const { return GetVTBL() != nullptr; } + bool IsPlaceableVTBL() const { return GetVTBL() == (void*)0x863C40; } + + bool HasMatrix() const noexcept { return matrix != nullptr; } + void RemoveMatrix() { ((void(__thiscall*)(void*))0x54F3B0)(this); } + + void SetOrientation(float x, float y, float z) { ((void(__thiscall*)(CPlaceableSAInterface * pEntity, float, float, float))0x439A80)(this, x, y, z); } + +public: + CSimpleTransformSAInterface m_transform; + CMatrix_Padded* matrix; // This is actually XYZ*, change later +}; +static_assert(sizeof(CPlaceableSAInterface) == 0x18, "Invalid size for CPlaceableSAInterface"); diff --git a/Client/game_sa/CPlayerPedSA.cpp b/Client/game_sa/CPlayerPedSA.cpp index cf8a03faea4..17c10e9d640 100644 --- a/Client/game_sa/CPlayerPedSA.cpp +++ b/Client/game_sa/CPlayerPedSA.cpp @@ -133,22 +133,13 @@ CPlayerPedSA::~CPlayerPedSA() { if (!BeingDeleted && DoNotRemoveFromGame == false) { - DWORD dwInterface = (DWORD)m_pInterface; - - if ((DWORD)GetInterface()->vtbl != VTBL_CPlaceable) + if (!m_pInterface->IsPlaceableVTBL()) { CWorldSA* world = (CWorldSA*)pGame->GetWorld(); pGame->GetProjectileInfo()->RemoveEntityReferences(this); world->Remove(m_pInterface, CPlayerPed_Destructor); - DWORD dwThis = (DWORD)m_pInterface; - DWORD dwFunc = m_pInterface->vtbl->SCALAR_DELETING_DESTRUCTOR; // we use the vtbl so we can be type independent - _asm - { - mov ecx, dwThis - push 1 // delete too - call dwFunc - } + m_pInterface->Destructor(true); } BeingDeleted = true; ((CPoolsSA*)pGame->GetPools())->RemovePed((CPed*)(CPedSA*)this, false); diff --git a/Client/game_sa/CPoolSAInterface.h b/Client/game_sa/CPoolSAInterface.h index 0416b90a34f..b27f66c2add 100644 --- a/Client/game_sa/CPoolSAInterface.h +++ b/Client/game_sa/CPoolSAInterface.h @@ -104,6 +104,14 @@ class CPoolSAInterface return &m_pObjects[uiSlot]; } + B* AllocateAtNoInit(std::uint32_t uiSlot) + { + m_byteMap[uiSlot].bEmpty = false; + m_byteMap[uiSlot].nId ^= uiSlot ^ (uiSlot + 1); + + return &m_pObjects[uiSlot]; + } + void Release(uint index) { m_byteMap[index].bEmpty = true; diff --git a/Client/game_sa/CProjectileInfoSA.cpp b/Client/game_sa/CProjectileInfoSA.cpp index 843f029462b..c753aa40bcb 100644 --- a/Client/game_sa/CProjectileInfoSA.cpp +++ b/Client/game_sa/CProjectileInfoSA.cpp @@ -36,12 +36,12 @@ void CProjectileInfoSA::RemoveProjectile(CProjectileInfo* pProjectileInfo, CProj if (!pProjectileSA) return; - CEntitySAInterface* projectileInterface = pProjectileSA->GetInterface(); + CProjectileSAInterface* projectileInterface = pProjectileSA->GetProjectileInterface(); // Check that this infact is a CProjectile // This is perhaps the fix for a crash where it jumps to 0x42480000 // The proper cause should be figured out instead though as this is a rather unsafe fix. - if ((DWORD)projectileInterface->vtbl == VTBL_CProjectile) + if (projectileInterface->IsProjectableVTBL()) { // Has it not already been removed by GTA? if (pProjectileInfo->IsActive()) diff --git a/Client/game_sa/CProjectileInfoSA.h b/Client/game_sa/CProjectileInfoSA.h index 73b69f74e2a..ab5f1fe4df4 100644 --- a/Client/game_sa/CProjectileInfoSA.h +++ b/Client/game_sa/CProjectileInfoSA.h @@ -25,8 +25,6 @@ #define ARRAY_CProjectile 0xC89110 //##SA## #define ARRAY_CProjectileInfo 0xC891A8 //##SA## -#define VTBL_CProjectile 0x867030 - // #pragma pack(push,1) class CProjectileInfoSAInterface { diff --git a/Client/game_sa/CProjectileSA.cpp b/Client/game_sa/CProjectileSA.cpp index 1eb7082596a..2ae4b8719b0 100644 --- a/Client/game_sa/CProjectileSA.cpp +++ b/Client/game_sa/CProjectileSA.cpp @@ -107,15 +107,15 @@ bool CProjectileSA::CorrectPhysics() // create a matrix variable CMatrix attachedToMatrix; - if (pCollidedWithInterface->Placeable.matrix != NULL) + if (pCollidedWithInterface->matrix != NULL) { // get our matrix - pCollidedWithInterface->Placeable.matrix->ConvertToMatrix(attachedToMatrix); + pCollidedWithInterface->matrix->ConvertToMatrix(attachedToMatrix); } else { // get our matrix - attachedToMatrix = CMatrix(pCollidedWithInterface->Placeable.m_transform.m_translate); + attachedToMatrix = CMatrix(pCollidedWithInterface->m_transform.m_translate); } // transform our matrix into local (attached) space diff --git a/Client/game_sa/CProjectileSA.h b/Client/game_sa/CProjectileSA.h index bb3791d6ac9..669a566a0f6 100644 --- a/Client/game_sa/CProjectileSA.h +++ b/Client/game_sa/CProjectileSA.h @@ -16,6 +16,8 @@ class CProjectileSAInterface : public CObjectSAInterface // entirely inherited from CObject { +public: + bool IsProjectableVTBL() const { return GetVTBL() == (void*)0x867030; }; }; class CProjectileSA : public virtual CProjectile, public virtual CObjectSA @@ -29,6 +31,8 @@ class CProjectileSA : public virtual CProjectile, public virtual CObjectSA CProjectileSA(class CProjectileSAInterface* projectileInterface); ~CProjectileSA(); void Destroy(bool bBlow = true); + CProjectileSAInterface* GetProjectileInterface() const { return static_cast(m_pInterface); }; + bool CalculateImpactPosition(CEntitySAInterface* pCollidedWith, CVector vecInputStart, CVector& vecInputEnd); void SetProjectileInfo(CProjectileInfo* pProjectileInfo) { projectileInfo = pProjectileInfo; } diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index e397be884a0..7d235fa77f4 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -224,22 +224,37 @@ void CVehicleSA::Init() m_RGBColors[3] = CVehicleColor::GetRGBFromPaletteIndex(GetVehicleInterface()->m_colour4); SetColor(m_RGBColors[0], m_RGBColors[1], m_RGBColors[2], m_RGBColors[3], 0); - // Initialize doors depending on the vtable. - DWORD dwOffset; - DWORD dwFunc = ((CVehicleSAInterfaceVTBL*)GetVehicleInterface()->vtbl)->GetDoorAngleOpenRatio_; - if (dwFunc == FUNC_CAutomobile__GetDoorAngleOpenRatio) - dwOffset = 1464; - else if (dwFunc == FUNC_CTrain__GetDoorAngleOpenRatio) - dwOffset = 1496; - else - dwOffset = 0; // Other vehicles don't have door information. + // Initialize doors depending on the vehicle type. + std::uint32_t doorArrayOffset; - if (dwOffset != 0) + switch (static_cast(GetVehicleInterface()->m_vehicleClass)) { - for (unsigned int i = 0; i < sizeof(m_doors) / sizeof(m_doors[0]); ++i) + case VehicleClass::AUTOMOBILE: + case VehicleClass::MONSTER_TRUCK: + case VehicleClass::QUAD: + case VehicleClass::HELI: + case VehicleClass::PLANE: + case VehicleClass::TRAILER: { - DWORD dwInterface = (DWORD)GetInterface(); - DWORD dwDoorAddress = dwInterface + 1464 + i * 24; + doorArrayOffset = 1464; + break; + } + case VehicleClass::TRAIN: + { + doorArrayOffset = 1496; + break; + } + default: + doorArrayOffset = 0; + break; + } + + if (doorArrayOffset != 0) + { + for (std::uint32_t i = 0; i < sizeof(m_doors) / sizeof(m_doors[0]); ++i) + { + std::uint32_t dwInterface = (std::uint32_t)GetInterface(); + std::uint32_t dwDoorAddress = dwInterface + doorArrayOffset + i * 24; m_doors[i].SetInterface((CDoorSAInterface*)dwDoorAddress); } } @@ -251,7 +266,7 @@ CVehicleSA::~CVehicleSA() { if (!BeingDeleted) { - if ((DWORD)m_pInterface->vtbl != VTBL_CPlaceable) + if (!m_pInterface->IsPlaceableVTBL()) { GetVehicleInterface()->m_pVehicle = nullptr; @@ -286,13 +301,7 @@ CVehicleSA::~CVehicleSA() pWorld->Remove(m_pInterface, CVehicle_Destructor); pWorld->RemoveReferencesToDeletedObject(m_pInterface); - dwFunc = m_pInterface->vtbl->SCALAR_DELETING_DESTRUCTOR; // we use the vtbl so we can be vehicle type independent - _asm - { - mov ecx, dwThis - push 1 //delete too - call dwFunc - } + m_pInterface->Destructor(true); } BeingDeleted = true; ((CPoolsSA*)pGame->GetPools())->RemoveVehicle((CVehicle*)this); @@ -681,25 +690,8 @@ CDoorSA* CVehicleSA::GetDoor(unsigned char ucDoor) void CVehicleSA::OpenDoor(unsigned char ucDoor, float fRatio, bool bMakeNoise) { - DWORD dwThis = (DWORD)m_pInterface; - DWORD dwFunc = ((CVehicleSAInterfaceVTBL*)GetVehicleInterface()->vtbl)->OpenDoor; - - // Grab the car node index for the given door id - static int s_iCarNodeIndexes[6] = {0x10, 0x11, 0x0A, 0x08, 0x0B, 0x09}; - DWORD dwIdx = s_iCarNodeIndexes[ucDoor]; - DWORD dwDoor = ucDoor; - DWORD dwMakeNoise = bMakeNoise; - - _asm - { - mov ecx, dwThis - push dwMakeNoise - push fRatio - push dwDoor - push dwIdx - push 0 - call dwFunc - } + static const int s_iCarNodeIndexes[6] = {0x10, 0x11, 0x0A, 0x08, 0x0B, 0x09}; + return GetVehicleInterface()->OpenDoor(nullptr, s_iCarNodeIndexes[ucDoor], ucDoor, fRatio, bMakeNoise); } void CVehicleSA::SetSwingingDoorsAllowed(bool bAllowed) @@ -831,47 +823,12 @@ float CVehicleSA::GetGasPedal() bool CVehicleSA::GetTowBarPos(CVector* pVector, CVehicle* pTrailer) { - CVehicleSAInterfaceVTBL* vehicleVTBL = (CVehicleSAInterfaceVTBL*)(m_pInterface->vtbl); - DWORD dwThis = (DWORD)m_pInterface; - DWORD dwFunc = vehicleVTBL->GetTowbarPos; - bool bReturn = false; - - DWORD dwTrailerInt = 0; - CVehicleSA* pTrailerSA = dynamic_cast(pTrailer); - if (pTrailerSA) - dwTrailerInt = (DWORD)pTrailerSA->GetInterface(); - - _asm - { - mov ecx, dwThis - push dwTrailerInt - push 1 - push pVector - call dwFunc - mov bReturn, al - } - - return bReturn; + return GetVehicleInterface()->GetTowbarPos(pVector, true, pTrailer ? pTrailer->GetVehicleInterface() : nullptr); } bool CVehicleSA::GetTowHitchPos(CVector* pVector) { - CVehicleSAInterfaceVTBL* vehicleVTBL = (CVehicleSAInterfaceVTBL*)(m_pInterface->vtbl); - DWORD dwThis = (DWORD)m_pInterface; - DWORD dwFunc = vehicleVTBL->GetTowHitchPos; - bool bReturn = false; - - _asm - { - mov ecx, dwThis - push 0 - push 1 - push pVector - call dwFunc - mov bReturn, al - } - - return bReturn; + return GetVehicleInterface()->GetTowHitchPos(pVector, true, nullptr); } bool CVehicleSA::IsUpsideDown() @@ -1166,19 +1123,7 @@ CDamageManager* CVehicleSA::GetDamageManager() void CVehicleSA::BlowUp(CEntity* pCreator, unsigned long ulUnknown) { - CVehicleSAInterfaceVTBL* vehicleVTBL = (CVehicleSAInterfaceVTBL*)(GetInterface()->vtbl); - DWORD dwThis = (DWORD)m_pInterface; - DWORD dwFunc = vehicleVTBL->BlowUpCar; - - DWORD dwCreator = (DWORD)pCreator; - - _asm - { - push ulUnknown - push dwCreator - mov ecx, dwThis - call dwFunc - } + GetVehicleInterface()->BlowUpCar(pCreator->GetInterface(), ulUnknown); } void CVehicleSA::FadeOut(bool bFadeOut) @@ -1214,20 +1159,7 @@ void CVehicleSA::SetTowLink(CVehicle* pVehicle) bool CVehicleSA::BreakTowLink() { - DWORD dwThis = (DWORD)GetInterface(); - - CVehicleSAInterfaceVTBL* vehicleVTBL = (CVehicleSAInterfaceVTBL*)(GetInterface()->vtbl); - DWORD dwFunc = vehicleVTBL->BreakTowLink; - bool bReturn = false; - - _asm - { - mov ecx, dwThis - call dwFunc - mov bReturn, al - } - - return bReturn; + return GetVehicleInterface()->BreakTowLink(); } CVehicle* CVehicleSA::GetTowedVehicle() @@ -1468,16 +1400,7 @@ void CVehicleSA::RecalculateHandling() void CVehicleSA::BurstTyre(BYTE bTyre) { - CVehicleSAInterfaceVTBL* vehicleVTBL = (CVehicleSAInterfaceVTBL*)(m_pInterface->vtbl); - DWORD dwThis = (DWORD)m_pInterface; - DWORD dwFunc = vehicleVTBL->BurstTyre; - _asm - { - mov ecx, dwThis - push 1 // not used - push bTyre - call dwFunc - } + GetVehicleInterface()->BurstTyre(bTyre, true); } BYTE CVehicleSA::GetBikeWheelStatus(BYTE bWheel) @@ -1578,7 +1501,7 @@ void CVehicleSA::SetGravity(const CVector* pvecGravity) GetMatrixForGravity(m_vecGravity, matOld); GetMatrixForGravity(*pvecGravity, matNew); - CVector* pvecPosition = &m_pInterface->Placeable.matrix->vPos; + CVector* pvecPosition = &m_pInterface->matrix->vPos; matOld.Invert(); pCam->GetTargetHistoryPos()[0] = matOld * (pCam->GetTargetHistoryPos()[0] - *pvecPosition); @@ -1859,19 +1782,11 @@ void CVehicleSA::RecalculateSuspensionLines() CModelInfo* pModelInfo = pGame->GetModelInfo(dwModel); if (pModelInfo && pModelInfo->IsMonsterTruck() || pModelInfo->IsCar()) { - CVehicleSAInterface* pInt = GetVehicleInterface(); // Trains (Their trailers do as well!) if (pModelInfo->IsTrain() || dwModel == 571 || dwModel == 570 || dwModel == 569 || dwModel == 590) return; - CVehicleSAInterfaceVTBL* pVtbl = reinterpret_cast(pInt->vtbl); - DWORD dwSetupSuspensionLines = pVtbl->SetupSuspensionLines; - DWORD dwThis = (DWORD)pInt; - _asm - { - mov ecx, dwThis - call dwSetupSuspensionLines - } + GetVehicleInterface()->SetupSuspensionLines(); CopyGlobalSuspensionLinesToPrivate(); } @@ -1907,7 +1822,7 @@ void CVehicleSA::OnChangingPosition(const CVector& vecNewPosition) // Only apply to CAutomobile and down if (GetBaseVehicleType() == 0) { - CVector vecDelta = vecNewPosition - m_pInterface->Placeable.matrix->vPos; + CVector vecDelta = vecNewPosition - m_pInterface->matrix->vPos; if (vecDelta.LengthSquared() > 10 * 10) { // Reposition colpoints for big moves to avoid random spinning diff --git a/Client/game_sa/CVehicleSA.h b/Client/game_sa/CVehicleSA.h index 5c4b332b7c1..1f1d905d53f 100644 --- a/Client/game_sa/CVehicleSA.h +++ b/Client/game_sa/CVehicleSA.h @@ -24,6 +24,7 @@ class CFxSystemSAInterface; class CTrainSAInterface; +class CColModelSAInterface; struct RwTexture; #define SIZEOF_CHELI 2584 @@ -70,9 +71,6 @@ struct RwTexture; #define VARS_CarCounts 0x969094 // 5 values for each vehicle type -// Used when deleting vehicles -#define VTBL_CPlaceable 0x863C40 - #define MAX_PASSENGERS 8 #define NUM_RAILTRACKS 4 @@ -118,55 +116,6 @@ struct SRailNodeSA WORD padding; }; -class CVehicleSAInterfaceVTBL : public CEntitySAInterfaceVTBL -{ -public: - DWORD ProcessEntityCollision; // +58h - DWORD ProcessControlCollisionCheck; // +5Ch - DWORD ProcessControlInputs; // +60h - DWORD GetComponentWorldPosition; // +64h - DWORD IsComponentPresent; // +68h - DWORD OpenDoor; // +6Ch - DWORD ProcessOpenDoor; // +70h - DWORD GetDoorAngleOpenRatio; // +74h - DWORD GetDoorAngleOpenRatio_; // +78h - DWORD IsDoorReady; // +7Ch - DWORD IsDoorReady_; // +80h - DWORD IsDoorFullyOpen; // +84h - DWORD IsDoorFullyOpen_; // +88h - DWORD IsDoorClosed; // +8Ch - DWORD IsDoorClosed_; // +90h - DWORD IsDoorMissing; // +94h - DWORD IsDoorMissing_; // +98h - DWORD IsOpenTopCar; // +9Ch - DWORD RemoveRefsToVehicle; // +A0h - DWORD BlowUpCar; // +A4h - DWORD BlowUpCarCutSceneNoExtras; // +A8h - DWORD SetUpWheelColModel; // +ACh - DWORD BurstTyre; // +B0h - DWORD IsRoomForPedToLeaveCar; // +B4h - DWORD ProcessDrivingAnims; // +B8h - DWORD GetRideAnimData; // +BCh - DWORD SetupSuspensionLines; // +C0h - DWORD AddMovingCollisionSpeed; // +C4h - DWORD Fix; // +C8h - DWORD SetupDamageAfterLoad; // +CCh - DWORD DoBurstAndSoftGroundRatios; // +D0h - DWORD GetHeightAboveRoad; // +D4h - DWORD PlayCarHorn; // +D8h - DWORD GetNumContactWheels; // +DCh - DWORD VehicleDamage; // +E0h - DWORD CanPedStepOutCar; // +E4h - DWORD CanPedJumpOutCar; // +E8h - DWORD GetTowHitchPos; // +ECh - DWORD GetTowbarPos; // +F0h - DWORD SetTowLink; // +F4h - DWORD BreakTowLink; // +F8h - DWORD FindWheelWidth; // +FCh - DWORD Save; // +100h - DWORD Load; // +104h -}; - struct CVehicleFlags { unsigned char bIsLawEnforcer : 1; // Is this guy chasing the player at the moment @@ -274,6 +223,60 @@ class CAutoPilot class CVehicleSAInterface : public CPhysicalSAInterface { public: + virtual void ProcessControlCollisionCheck(bool applySpeed) = 0; + virtual void ProcessControlInputs(std::uint8_t playerNum) = 0; + virtual void GetComponentWorldPosition(std::int32_t componentId, CVector& outPos) = 0; + virtual bool IsComponentPresent(std::int32_t componentId) = 0; + virtual void OpenDoor(CPedSAInterface* entity, std::uint32_t doorFrameId, std::uint32_t doorId, float ratio, bool makeNoise) = 0; + virtual void ProcessOpenDoor(CPedSAInterface* ped, std::uint32_t doorComponentId, std::uint32_t animGroup, std::uint32_t animId, float fTime) = 0; + + virtual float GetDoorAngleOpenRatio(std::uint32_t door) = 0; + virtual float GetDoorAngleOpenRatio_(std::uint8_t door) = 0; + + virtual bool IsDoorReady(std::uint32_t door) = 0; + virtual bool IsDoorReady_(std::uint8_t door) = 0; + virtual bool IsDoorFullyOpen(std::uint32_t door) = 0; + virtual bool IsDoorFullyOpen_(std::uint8_t door) = 0; + virtual bool IsDoorClosed(std::uint32_t door) = 0; + virtual bool IsDoorClosed_(std::uint8_t door) = 0; + virtual bool IsDoorMissing(std::uint32_t door) = 0; + virtual bool IsDoorMissing_(std::uint8_t door) = 0; + + virtual bool IsOpenTopCar() = 0; + + virtual void RemoveRefsToVehicle(CEntitySAInterface* entity) = 0; + virtual void BlowUpCar(CEntitySAInterface* creator, bool bHideExplosion) = 0; + virtual void BlowUpCarCutSceneNoExtras(bool bNoCamShake, bool bNoSpawnFlyingComps, bool bDetachWheels, bool bExplosionSound) = 0; + virtual bool SetUpWheelColModel(CColModelSAInterface* wheelCol) = 0; + virtual bool BurstTyre(std::uint8_t tireId, bool bPhysicalEffect) = 0; + virtual bool IsRoomForPedToLeaveCar(std::uint32_t doorId, CVector* arg) = 0; + virtual void ProcessDrivingAnims(CPedSAInterface* driver, bool bBlend) = 0; + + virtual void* GetRideAnimData() = 0; + + virtual void SetupSuspensionLines() = 0; + virtual CVector AddMovingCollisionSpeed(CVector& point) = 0; + virtual void Fix() = 0; + virtual void SetupDamageAfterLoad() = 0; + virtual void DoBurstAndSoftGroundRatios() = 0; + + virtual float GetHeightAboveRoad() = 0; + + virtual void PlayCarHorn() = 0; + virtual std::int32_t GetNumContactWheels() = 0; + + virtual void VehicleDamage(float damageIntensity, std::uint16_t collisionComponent, CEntitySAInterface* damager, CVector* vecCollisionCoors, + CVector* vecCollisionDirection, eWeaponType weapon) = 0; + virtual bool CanPedStepOutCar(bool bIgnoreSpeedUpright = false) = 0; + virtual bool CanPedJumpOutCar(CPedSAInterface* ped) = 0; + virtual bool GetTowHitchPos(CVector* pVector, bool bCheckModelInfo, CVehicleSAInterface* anotherVehicle) = 0; + virtual bool GetTowbarPos(CVector* pVector, bool ignoreModelType, CVehicleSAInterface* pTrailer) = 0; + virtual void SetTowLink() = 0; + virtual bool BreakTowLink() = 0; + virtual float FindWheelWidth() = 0; + virtual bool Save() = 0; + virtual bool Load() = 0; + void SetComponentVisibility(RwFrame* component, std::uint32_t state) { ((void(__thiscall*)(CVehicleSAInterface*, RwFrame*, std::uint32_t))0x6D2700)(this, component, state); @@ -395,7 +398,7 @@ class CVehicleSAInterface : public CPhysicalSAInterface float m_steeringLeftRight; // 1424 - uint8_t m_vehicleClass; + VehicleClass m_vehicleClass; uint32_t m_vehicleSubClass; int16_t m_peviousRemapTxd; diff --git a/Client/game_sa/CWorldSA.cpp b/Client/game_sa/CWorldSA.cpp index 72befc316e7..038d7697694 100644 --- a/Client/game_sa/CWorldSA.cpp +++ b/Client/game_sa/CWorldSA.cpp @@ -138,7 +138,7 @@ void CWorldSA::Add(CEntity* pEntity, eDebugCaller CallerId) if (pEntitySA) { CEntitySAInterface* pInterface = pEntitySA->GetInterface(); - if ((DWORD)pInterface->vtbl == VTBL_CPlaceable) + if (pInterface->IsPlaceableVTBL()) { SString strMessage("Caller: %i ", CallerId); LogEvent(506, "CWorld::Add ( CEntity * ) Crash", "", strMessage); @@ -157,7 +157,7 @@ void CWorldSA::Add(CEntity* pEntity, eDebugCaller CallerId) void CWorldSA::Add(CEntitySAInterface* entityInterface, eDebugCaller CallerId) { DWORD dwFunction = FUNC_Add; - if ((DWORD)entityInterface->vtbl == VTBL_CPlaceable) + if (entityInterface->IsPlaceableVTBL()) { SString strMessage("Caller: %i ", CallerId); LogEvent(506, "CWorld::Add ( CEntitySAInterface * ) Crash", "", strMessage); @@ -177,7 +177,7 @@ void CWorldSA::Remove(CEntity* pEntity, eDebugCaller CallerId) if (pEntitySA) { CEntitySAInterface* pInterface = pEntitySA->GetInterface(); - if ((DWORD)pInterface->vtbl == VTBL_CPlaceable) + if (pInterface->IsPlaceableVTBL()) { SString strMessage("Caller: %i ", CallerId); LogEvent(507, "CWorld::Remove ( CEntity * ) Crash", "", strMessage); @@ -195,7 +195,7 @@ void CWorldSA::Remove(CEntity* pEntity, eDebugCaller CallerId) void CWorldSA::Remove(CEntitySAInterface* entityInterface, eDebugCaller CallerId) { - if ((DWORD)entityInterface->vtbl == VTBL_CPlaceable) + if (entityInterface->IsPlaceableVTBL()) { SString strMessage("Caller: %i ", CallerId); LogEvent(507, "CWorld::Remove ( CEntitySAInterface * ) Crash", "", strMessage); @@ -277,7 +277,7 @@ auto CWorldSA::ProcessLineAgainstMesh(CEntitySAInterface* targetEntity, CVector } // Get matrix, and it's inverse - c.entity->Placeable.matrix->ConvertToMatrix(c.entMat); + c.entity->matrix->ConvertToMatrix(c.entMat); c.entInvMat = c.entMat.Inverse(); // ...to transform the line origin and end into object space @@ -465,11 +465,11 @@ bool CWorldSA::ProcessLineOfSight(const CVector* vecStart, const CVector* vecEnd pBuildingResult->usLODModelID = 0; pBuildingResult->pInterface = targetEntity; - pBuildingResult->vecPosition = targetEntity->Placeable.m_transform.m_translate; - if (targetEntity->Placeable.matrix) + pBuildingResult->vecPosition = targetEntity->m_transform.m_translate; + if (targetEntity->matrix) { CVector& vecRotation = pBuildingResult->vecRotation; - ConvertMatrixToEulerAngles(*targetEntity->Placeable.matrix, vecRotation.fX, vecRotation.fY, vecRotation.fZ); + ConvertMatrixToEulerAngles(*targetEntity->matrix, vecRotation.fX, vecRotation.fY, vecRotation.fZ); vecRotation = -vecRotation; } } @@ -483,15 +483,15 @@ bool CWorldSA::ProcessLineOfSight(const CVector* vecStart, const CVector* vecEnd pBuildingResult->usLODModelID = 0; pBuildingResult->pInterface = targetEntity; - if (targetEntity->Placeable.matrix) + if (targetEntity->matrix) { - pBuildingResult->vecPosition = targetEntity->Placeable.matrix->vPos; + pBuildingResult->vecPosition = targetEntity->matrix->vPos; CVector& vecRotation = pBuildingResult->vecRotation; - ConvertMatrixToEulerAngles(*targetEntity->Placeable.matrix, vecRotation.fX, vecRotation.fY, vecRotation.fZ); + ConvertMatrixToEulerAngles(*targetEntity->matrix, vecRotation.fX, vecRotation.fY, vecRotation.fZ); vecRotation = -vecRotation; } else - pBuildingResult->vecPosition = targetEntity->Placeable.m_transform.m_translate; + pBuildingResult->vecPosition = targetEntity->m_transform.m_translate; } } } @@ -536,8 +536,8 @@ CEntity* CWorldSA::TestSphereAgainstWorld(const CVector& sphereCenter, float rad result.collisionDetected = true; result.modelID = entity->m_nModelIndex; - result.entityPosition = entity->Placeable.matrix->vPos; - ConvertMatrixToEulerAngles(*entity->Placeable.matrix, result.entityRotation.fX, result.entityRotation.fY, result.entityRotation.fZ); + result.entityPosition = entity->matrix->vPos; + ConvertMatrixToEulerAngles(*entity->matrix, result.entityRotation.fX, result.entityRotation.fY, result.entityRotation.fZ); result.entityRotation = -result.entityRotation; result.lodID = entity->m_pLod ? entity->m_pLod->m_nModelIndex : 0; result.type = static_cast(entity->nType); diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index f0cd5661336..500d9eafeb7 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -2763,14 +2763,14 @@ void CMultiplayerSA::SetCenterOfWorld(CEntity* entity, CVector* vecPosition, FLO { activeEntityForStreaming = new CPedSAInterface(); MemSet (activeEntityForStreaming, 0, sizeof(CPedSAInterface)); - activeEntityForStreaming->Placeable.matrix = new CMatrix_Padded(); + activeEntityForStreaming->matrix = new CMatrix_Padded(); } bActiveEntityForStreamingIsFakePed = true; - activeEntityForStreaming->Placeable.matrix->vPos.fX = vecPosition->fX; - activeEntityForStreaming->Placeable.matrix->vPos.fY = vecPosition->fY; - activeEntityForStreaming->Placeable.matrix->vPos.fZ = vecPosition->fZ; + activeEntityForStreaming->matrix->vPos.fX = vecPosition->fX; + activeEntityForStreaming->matrix->vPos.fY = vecPosition->fY; + activeEntityForStreaming->matrix->vPos.fZ = vecPosition->fZ; }*/ // DWORD dwCurrentValue = *(DWORD *)FUNC_CPlayerInfoBase; @@ -2781,7 +2781,7 @@ void CMultiplayerSA::SetCenterOfWorld(CEntity* entity, CVector* vecPosition, FLO { /*if ( bActiveEntityForStreamingIsFakePed ) { - delete activeEntityForStreaming->Placeable.matrix; + delete activeEntityForStreaming->matrix; delete activeEntityForStreaming; } @@ -3218,10 +3218,10 @@ bool processGrab() { // CObjectSA * object = (CObjectSA*)entity; // CModelInfo * info = pGameInterface->GetModelInfo(entity->m_nModelIndex); - if (entity->Placeable.matrix) - edgeHeight = *entityEdgeHeight + entity->Placeable.matrix->vPos.fZ; + if (entity->matrix) + edgeHeight = *entityEdgeHeight + entity->matrix->vPos.fZ; else - edgeHeight = *entityEdgeHeight + entity->Placeable.m_transform.m_translate.fZ; + edgeHeight = *entityEdgeHeight + entity->m_transform.m_translate.fZ; } else edgeHeight = *entityEdgeHeight; @@ -6372,13 +6372,13 @@ void RemoveObjectIfNeeded() SBuildingRemoval* pBuildingRemoval = pGameInterface->GetBuildingRemoval()->GetBuildingRemoval(pLODInterface); if (pBuildingRemoval != NULL) { - if ((DWORD)(pBuildingAdd->vtbl) != VTBL_CPlaceable) + if (!pBuildingAdd->IsPlaceableVTBL()) { pBuildingRemoval->AddDataBuilding(pBuildingAdd); pGameInterface->GetWorld()->Remove(pBuildingAdd, BuildingRemoval3); } - if ((DWORD)(pLODInterface->vtbl) != VTBL_CPlaceable) + if (!pLODInterface->IsPlaceableVTBL()) { pBuildingRemoval->AddDataBuilding(pLODInterface); pGameInterface->GetWorld()->Remove(pLODInterface, BuildingRemoval4); @@ -6451,7 +6451,7 @@ void RemoveDummyIfReplaced() SBuildingRemoval* pBuildingRemoval = pGameInterface->GetBuildingRemoval()->GetBuildingRemoval(pLODInterface); if (pBuildingRemoval != NULL) { - if ((DWORD)(pBuildingAdd->vtbl) != VTBL_CPlaceable) + if (!pBuildingAdd->IsPlaceableVTBL()) { pBuildingRemoval->AddDataBuilding(pBuildingAdd); pGameInterface->GetWorld()->Remove(pBuildingAdd, BuildingRemoval5); diff --git a/Client/multiplayer_sa/CMultiplayerSA_1.3.cpp b/Client/multiplayer_sa/CMultiplayerSA_1.3.cpp index fd47e12ba8c..486b6a43361 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_1.3.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_1.3.cpp @@ -876,7 +876,7 @@ void _declspec(naked) HOOK_CVehicle_ProcessStuff_TestCameraPosition() } bool DisableVehicleSiren() { - if (pVehicleWithTheSiren && pVehicleWithTheSiren->vtbl != NULL) + if (pVehicleWithTheSiren && pVehicleWithTheSiren->HasVTBL()) { SClientEntity* pVehicleClientEntity = pGameInterface->GetPools()->GetVehicle((DWORD*)pVehicleWithTheSiren); CVehicle* pVehicle = pVehicleClientEntity ? pVehicleClientEntity->pEntity : nullptr; @@ -1635,20 +1635,20 @@ void UpdateExplosionLocation() if (pExplosionEntity) { // project backwards 20% of our velocity just to catch us going too far - CVector vecStart = pExplosionEntity->Placeable.matrix->vPos + (pExplosionEntity->m_vecLinearVelocity * 0.20f); + CVector vecStart = pExplosionEntity->matrix->vPos + (pExplosionEntity->m_vecLinearVelocity * 0.20f); // project forwards 120% to look for collisions forwards CVector vecEnd = vecStart - (pExplosionEntity->m_vecLinearVelocity * 1.20f); // calculate our actual impact position if (pGameInterface->GetWorld()->CalculateImpactPosition(vecStart, vecEnd)) { // Apply it - if (pExplosionEntity->Placeable.matrix) + if (pExplosionEntity->matrix) { - pExplosionEntity->Placeable.matrix->vPos = vecEnd; + pExplosionEntity->matrix->vPos = vecEnd; } else { - pExplosionEntity->Placeable.m_transform.m_translate = vecEnd; + pExplosionEntity->m_transform.m_translate = vecEnd; } } } diff --git a/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp b/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp index b346f258740..0654572dda6 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_Rendering.cpp @@ -77,7 +77,7 @@ void _declspec(naked) HOOK_CallIdle() ////////////////////////////////////////////////////////////////////////////////////////// bool IsEntityRenderable(CEntitySAInterface* pEntity) { - bool bIsPlaceable = ((DWORD)(pEntity->vtbl) == VTBL_CPlaceable); + bool bIsPlaceable = pEntity->IsPlaceableVTBL(); bool bHasRwObject = (pEntity->m_pRwObject != nullptr); if (bIsPlaceable || !bHasRwObject) { diff --git a/Client/multiplayer_sa/CMultiplayerSA_VehicleCollision.cpp b/Client/multiplayer_sa/CMultiplayerSA_VehicleCollision.cpp index c17b2aa2972..30de5308fe4 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_VehicleCollision.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_VehicleCollision.cpp @@ -40,8 +40,10 @@ void TriggerVehicleCollisionEvent() } else { + const bool isProjectile = static_cast(pEntity)->IsProjectableVTBL(); pVehicleCollisionHandler(pCollisionVehicle, pEntity, pEntity->m_nModelIndex, pCollisionVehicle->m_fDamageImpulseMagnitude, 0.0f, - pCollisionVehicle->m_usPieceType, pCollisionVehicle->m_vecCollisionPosition, pCollisionVehicle->m_vecCollisionImpactVelocity, pEntity->nType == ENTITY_TYPE_OBJECT && pEntity->vtbl == (CEntitySAInterfaceVTBL*)0x867030); + pCollisionVehicle->m_usPieceType, pCollisionVehicle->m_vecCollisionPosition, pCollisionVehicle->m_vecCollisionImpactVelocity, + pEntity->nType == ENTITY_TYPE_OBJECT && isProjectile); } TIMING_CHECKPOINT("-TriggerVehColEvent"); } diff --git a/Client/multiplayer_sa/StdInc.h b/Client/multiplayer_sa/StdInc.h index 79526c0a04f..9396212e417 100644 --- a/Client/multiplayer_sa/StdInc.h +++ b/Client/multiplayer_sa/StdInc.h @@ -22,5 +22,6 @@ #include "..\game_sa\CCameraSA.h" #include "..\game_sa\CEntitySA.h" #include "..\game_sa\CPedSA.h" +#include "..\game_sa\CProjectileSA.h" extern CMultiplayerSA* pMultiplayer;