From 1ba1bc08effec006fcccb3ee3627edd4258425a4 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Mon, 30 Sep 2024 01:30:47 +0300 Subject: [PATCH 1/7] First draw --- Client/game_sa/CBuildingRemovalSA.cpp | 96 +++++------ Client/game_sa/CBuildingsPoolSA.cpp | 17 +- Client/game_sa/CBuildingsPoolSA.h | 5 +- Client/game_sa/CCameraSA.cpp | 4 +- Client/game_sa/CCameraSA.h | 6 +- Client/game_sa/CEntitySA.cpp | 87 +++------- Client/game_sa/CEntitySA.h | 55 +----- Client/game_sa/CModelInfoSA.cpp | 4 +- Client/game_sa/CObjectSA.cpp | 28 +--- Client/game_sa/CPlaceableSA.h | 55 ++++++ Client/game_sa/CPlayerPedSA.cpp | 13 +- Client/game_sa/CPoolSAInterface.h | 8 + Client/game_sa/CProjectileInfoSA.cpp | 4 +- Client/game_sa/CProjectileInfoSA.h | 2 - Client/game_sa/CProjectileSA.cpp | 6 +- Client/game_sa/CProjectileSA.h | 4 + Client/game_sa/CVehicleSA.cpp | 157 ++++-------------- Client/game_sa/CVehicleSA.h | 101 ++++++----- Client/game_sa/CWorldSA.cpp | 24 +-- Client/multiplayer_sa/CMultiplayerSA.cpp | 22 +-- Client/multiplayer_sa/CMultiplayerSA_1.3.cpp | 10 +- .../CMultiplayerSA_Rendering.cpp | 2 +- .../CMultiplayerSA_VehicleCollision.cpp | 4 +- Client/multiplayer_sa/StdInc.h | 1 + 24 files changed, 288 insertions(+), 427 deletions(-) create mode 100644 Client/game_sa/CPlaceableSA.h diff --git a/Client/game_sa/CBuildingRemovalSA.cpp b/Client/game_sa/CBuildingRemovalSA.cpp index 122a1bba45..95de2a21e9 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/CBuildingsPoolSA.cpp b/Client/game_sa/CBuildingsPoolSA.cpp index caa392c132..39a39645fe 100644 --- a/Client/game_sa/CBuildingsPoolSA.cpp +++ b/Client/game_sa/CBuildingsPoolSA.cpp @@ -108,7 +108,7 @@ void CBuildingsPoolSA::RemoveBuilding(CBuilding* pBuilding) pGame->GetWorld()->Remove(pInterface, CBuildingPool_Destructor); // Call virtual destructor - ((void*(__thiscall*)(void*, char))pInterface->vtbl->SCALAR_DELETING_DESTRUCTOR)(pInterface, 0); + pInterface->Destructor(false); // Remove col reference auto modelInfo = pGame->GetModelInfo(pBuilding->GetModelIndex()); @@ -140,7 +140,7 @@ void CBuildingsPoolSA::RemoveAllBuildings() using CStencilShadowObjects_dtorAll = void* (*)(); ((CStencilShadowObjects_dtorAll)0x711390)(); - 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++) @@ -154,7 +154,7 @@ void CBuildingsPoolSA::RemoveAllBuildings() pBuildsingsPool->Release(i); (*m_pOriginalBuildingsBackup)[i].first = true; - (*m_pOriginalBuildingsBackup)[i].second = *building; + std::memcpy(&(*m_pOriginalBuildingsBackup)[i].second, building, sizeof(CBuildingSAInterface)); } else { @@ -174,9 +174,8 @@ void CBuildingsPoolSA::RestoreAllBuildings() { 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)); pGame->GetWorld()->Add(pBuilding, CBuildingPool_Constructor); } @@ -286,13 +285,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 5ce719bd73..863e916e5f 100644 --- a/Client/game_sa/CBuildingsPoolSA.h +++ b/Client/game_sa/CBuildingsPoolSA.h @@ -43,5 +43,8 @@ class CBuildingsPoolSA : public CBuildingsPool SVectorPoolData m_buildingPool{MAX_BUILDINGS}; CPoolSAInterface** m_ppBuildingPoolInterface; - std::unique_ptr, MAX_BUILDINGS>> m_pOriginalBuildingsBackup; + typedef std::uint8_t building_buffer_t[sizeof(CBuildingSAInterface)]; + typedef std::array, MAX_BUILDINGS> backup_array_t; + + std::unique_ptr m_pOriginalBuildingsBackup; }; diff --git a/Client/game_sa/CCameraSA.cpp b/Client/game_sa/CCameraSA.cpp index 960ec7cfa7..d3ef5c87bd 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 246f3362d8..2d95f3b3b3 100644 --- a/Client/game_sa/CCameraSA.h +++ b/Client/game_sa/CCameraSA.h @@ -77,13 +77,9 @@ class CTrainCamNode /*** END PURE R* CLASSES ***/ -class CCameraSAInterface +class CCameraSAInterface : public CPlaceableSAInterface { public: - // CPlaceable - CPlaceableSAInterface Placeable; - // 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/CEntitySA.cpp b/Client/game_sa/CEntitySA.cpp index 02a9f00380..63f7c51302 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(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) @@ -305,10 +268,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; } // @@ -331,12 +294,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 @@ -347,16 +310,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; /* @@ -500,7 +463,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; @@ -518,7 +481,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 548cb657f6..177291b32f 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 @@ -31,32 +30,6 @@ #define FUNC_RpAnimBlendClumpGetAssociation 0x4D6870 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 @@ -106,27 +79,9 @@ 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 -}; - -class CEntitySAInterface -{ -public: - CEntitySAInterfaceVTBL* vtbl; // the virtual table - - CPlaceableSAInterface Placeable; // 4 - RpClump* m_pRwObject; // 24 /********** BEGIN CFLAGS **************/ unsigned long bUsesCollision : 1; // does entity use collision @@ -237,11 +192,7 @@ class CEntitySAInterface ((CStencilShadow_dtorByOwner)0x711730)(this); }; - void DeleteRwObject() - { - using vtbl_DeleteRwObject = void(__thiscall*)(CEntitySAInterface * pEntity); - ((vtbl_DeleteRwObject)this->vtbl->DeleteRwObject)(this); - }; + bool IsUsesEntityDeleteRwObject() { return *(*reinterpret_cast(this) + 0x20) == 0x00534030; }; }; static_assert(sizeof(CEntitySAInterface) == 0x38, "Invalid size for CEntitySAInterface"); diff --git a/Client/game_sa/CModelInfoSA.cpp b/Client/game_sa/CModelInfoSA.cpp index 2db97a5245..0552f03f95 100644 --- a/Client/game_sa/CModelInfoSA.cpp +++ b/Client/game_sa/CModelInfoSA.cpp @@ -985,14 +985,14 @@ void CModelInfoSA::StaticFlushPendingRestreamIPL() CEntitySAInterface* pEntity = (CEntitySAInterface*)pSectorEntry[0]; // Possible bug - pEntity seems to be invalid here occasionally - if (pEntity->vtbl->DeleteRwObject != 0x00534030) + if (!pEntity->IsUsesEntityDeleteRwObject()) { // 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(!pEntity->IsUsesEntityDeleteRwObject()); #endif pSectorEntry = (DWORD*)pSectorEntry[1]; continue; diff --git a/Client/game_sa/CObjectSA.cpp b/Client/game_sa/CObjectSA.cpp index ef31e9b37a..3c48bad2f2 100644 --- a/Client/game_sa/CObjectSA.cpp +++ b/Client/game_sa/CObjectSA.cpp @@ -145,18 +145,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); } } @@ -232,22 +226,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/CPlaceableSA.h b/Client/game_sa/CPlaceableSA.h new file mode 100644 index 0000000000..318701a335 --- /dev/null +++ b/Client/game_sa/CPlaceableSA.h @@ -0,0 +1,55 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include +#include + +#define VTBL_CPlaceable 0x863C40 + +class CSimpleTransformSAInterface // 16 bytes +{ +public: + CVector m_translate; + float m_heading; +}; + +class CPlaceableSAInterface +{ +public: + virtual void* Destructor(bool deletedFromPool) = 0; // + virtual void Add_CRect() = 0; + virtual void Add() = 0; // + virtual void Remove() = 0; + virtual void SetIsStatic() = 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 void GetBoundRect() = 0; + virtual void ProcessControl() = 0; // + virtual void ProcessCollision() = 0; + virtual void ProcessShift() = 0; + virtual void TestCollision() = 0; + virtual void Teleport(float x, float y, float z, bool resetRotation) = 0; // + virtual void SpecialEntityPreCollisionStuff() = 0; + virtual void SpecialEntityCalcCollisionSteps() = 0; + virtual void PreRender() = 0; // + virtual void Render() = 0; // + virtual void SetupLighting() = 0; // + virtual void* RemoveLighting(bool) = 0; // + virtual void FlagToDestroyWhenNextProcessed() = 0; // + + bool IsPlaceableVTBL() const { return *reinterpret_cast(this) == VTBL_CPlaceable; }; + bool HasVTBL() const { return *reinterpret_cast(this) != 0; }; + +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 ad555041d0..545aa48ede 100644 --- a/Client/game_sa/CPlayerPedSA.cpp +++ b/Client/game_sa/CPlayerPedSA.cpp @@ -132,21 +132,12 @@ 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(); 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 9f48bc63d3..d80aade494 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 439553941d..1c4652a0c0 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 2d8ba9cb32..ac9dee056f 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 1eb7082596..2ae4b8719b 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 bb3791d6ac..ee03568a4c 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 *reinterpret_cast(this) == 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 91fb5440e0..b190429c82 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -165,22 +165,34 @@ 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. + DWORD dwOffset = 0; + + switch (static_cast(GetVehicleInterface()->m_vehicleClass)) + { + case VehicleClass::AUTOMOBILE: + case VehicleClass::MONSTER_TRUCK: + case VehicleClass::QUAD: + case VehicleClass::HELI: + case VehicleClass::PLANE: + case VehicleClass::TRAILER: + { + dwOffset = 1464; + } + case VehicleClass::TRAIN: + { + dwOffset = 1496; + } + default: + break; + } if (dwOffset != 0) { for (unsigned int i = 0; i < sizeof(m_doors) / sizeof(m_doors[0]); ++i) { DWORD dwInterface = (DWORD)GetInterface(); - DWORD dwDoorAddress = dwInterface + 1464 + i * 24; + DWORD dwDoorAddress = dwInterface + dwOffset + i * 24; m_doors[i].SetInterface((CDoorSAInterface*)dwDoorAddress); } } @@ -192,7 +204,7 @@ CVehicleSA::~CVehicleSA() { if (!BeingDeleted) { - if ((DWORD)m_pInterface->vtbl != VTBL_CPlaceable) + if (!m_pInterface->IsPlaceableVTBL()) { GetVehicleInterface()->m_pVehicle = nullptr; @@ -226,13 +238,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); @@ -596,27 +602,11 @@ CDoorSA* CVehicleSA::GetDoor(unsigned char ucDoor) return 0; } +static const int s_iCarNodeIndexes[6] = {0x10, 0x11, 0x0A, 0x08, 0x0B, 0x09}; + 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 - } + return GetVehicleInterface()->OpenDoor(nullptr, s_iCarNodeIndexes[ucDoor], ucDoor, fRatio, bMakeNoise); } void CVehicleSA::SetSwingingDoorsAllowed(bool bAllowed) @@ -737,47 +727,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, nullptr); } bool CVehicleSA::IsUpsideDown() @@ -1072,19 +1027,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) @@ -1120,20 +1063,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() @@ -1378,16 +1308,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) @@ -1488,7 +1409,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); @@ -1698,19 +1619,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(); } @@ -1746,7 +1659,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 58632dabbf..72c344de7f 100644 --- a/Client/game_sa/CVehicleSA.h +++ b/Client/game_sa/CVehicleSA.h @@ -70,9 +70,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 @@ -103,55 +100,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 @@ -258,6 +206,53 @@ class CAutoPilot class CVehicleSAInterface : public CPhysicalSAInterface { +public: + // Some virtual functions are not defined propertly + virtual void ProcessEntityCollision() = 0; + virtual void ProcessControlCollisionCheck() = 0; + virtual void ProcessControlInputs() = 0; + virtual void GetComponentWorldPosition() = 0; + virtual void IsComponentPresent() = 0; + virtual void OpenDoor(CEntitySAInterface* entity, std::uint32_t doorFrameId, std::uint32_t doorId, float ratio, bool makeNoise) = 0; + virtual void ProcessOpenDoor() = 0; + virtual void GetDoorAngleOpenRatio() = 0; + virtual void GetDoorAngleOpenRatio_() = 0; + virtual void IsDoorReady() = 0; + virtual void IsDoorReady_() = 0; + virtual void IsDoorFullyOpen() = 0; + virtual void IsDoorFullyOpen_() = 0; + virtual void IsDoorClosed() = 0; + virtual void IsDoorClosed_() = 0; + virtual void IsDoorMissing() = 0; + virtual void IsDoorMissing_() = 0; + virtual void IsOpenTopCar() = 0; + virtual void RemoveRefsToVehicle() = 0; + virtual void BlowUpCar(CEntitySAInterface* creator, std::uint32_t unknown) = 0; + virtual void BlowUpCarCutSceneNoExtras() = 0; + virtual void SetUpWheelColModel() = 0; + virtual void BurstTyre(std::uint8_t tireId, bool unused) = 0; + virtual void IsRoomForPedToLeaveCar() = 0; + virtual void ProcessDrivingAnims() = 0; + virtual void GetRideAnimData() = 0; + virtual void SetupSuspensionLines() = 0; + virtual void AddMovingCollisionSpeed() = 0; + virtual void Fix() = 0; + virtual void SetupDamageAfterLoad() = 0; + virtual void DoBurstAndSoftGroundRatios() = 0; + virtual void GetHeightAboveRoad() = 0; + virtual void PlayCarHorn() = 0; + virtual void GetNumContactWheels() = 0; + virtual void VehicleDamage() = 0; + virtual void CanPedStepOutCar() = 0; + virtual void CanPedJumpOutCar() = 0; + virtual bool GetTowHitchPos(CVector* pVector, CVehicleSAInterface* anotherVehicle) = 0; + virtual bool GetTowbarPos(CVector* pVector, bool ignoreModelType, CVehicleSAInterface* pTrailer) = 0; + virtual void SetTowLink() = 0; + virtual bool BreakTowLink() = 0; + virtual void FindWheelWidth() = 0; + virtual void Save() = 0; + virtual void Load() = 0; + public: CAEVehicleAudioEntitySAInterface m_VehicleAudioEntity; // 312 @@ -375,7 +370,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 a60e360464..3e695e3981 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; } } } diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index 28d5b1f551..b634450ba7 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -2757,14 +2757,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; @@ -2775,7 +2775,7 @@ void CMultiplayerSA::SetCenterOfWorld(CEntity* entity, CVector* vecPosition, FLO { /*if ( bActiveEntityForStreamingIsFakePed ) { - delete activeEntityForStreaming->Placeable.matrix; + delete activeEntityForStreaming->matrix; delete activeEntityForStreaming; } @@ -3212,10 +3212,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; @@ -6366,13 +6366,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); @@ -6445,7 +6445,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 fd47e12ba8..486b6a4336 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 b346f25874..0654572dda 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 c17b2aa297..30de5308fe 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 79526c0a04..9396212e41 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; From 56fce1d4703c3eeadc8fa62637f941375a39ceee Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Mon, 30 Sep 2024 23:33:46 +0300 Subject: [PATCH 2/7] Fix camera class definitions --- Client/game_sa/CCameraSA.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Client/game_sa/CCameraSA.h b/Client/game_sa/CCameraSA.h index 2d95f3b3b3..6eb9043baa 100644 --- a/Client/game_sa/CCameraSA.h +++ b/Client/game_sa/CCameraSA.h @@ -128,15 +128,6 @@ class CCameraSAInterface : public CPlaceableSAInterface bool m_bAllowShootingWith2PlayersInCar; bool m_bDisableFirstPersonInCar; static bool m_bUseMouse3rdPerson; -#ifndef FINALBUILD - bool bStaticFrustum; -#endif - - // for debug keyboard stuff -#ifndef MASTER - unsigned char display_kbd_debug; - float kbd_fov_value; -#endif // MASTER // The following fields allow the level designers to specify the camera for 2 player games. short m_ModeForTwoPlayersSeparateCars; From 2d0b7a4ae2c807f2975ddbffbbb36279a63d8df1 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Tue, 1 Oct 2024 18:49:20 +0300 Subject: [PATCH 3/7] Fix methods declaration --- Client/game_sa/CEntitySA.cpp | 2 +- Client/game_sa/CEntitySA.h | 25 +++++++++ Client/game_sa/CPhysicalSA.h | 4 ++ Client/game_sa/CPlaceableSA.h | 23 +------- Client/game_sa/CVehicleSA.cpp | 5 +- Client/game_sa/CVehicleSA.h | 99 +++++++++++++++++++---------------- 6 files changed, 87 insertions(+), 71 deletions(-) diff --git a/Client/game_sa/CEntitySA.cpp b/Client/game_sa/CEntitySA.cpp index 63f7c51302..cc9cabbc26 100644 --- a/Client/game_sa/CEntitySA.cpp +++ b/Client/game_sa/CEntitySA.cpp @@ -142,7 +142,7 @@ void CEntitySA::Teleport(float fX, float fY, float fZ) if (m_pInterface->matrix) { SetPosition(fX, fY, fZ); - m_pInterface->Teleport(fX, fY, fZ, true); + m_pInterface->Teleport(CVector(fX, fY, fZ), true); } else { diff --git a/Client/game_sa/CEntitySA.h b/Client/game_sa/CEntitySA.h index 177291b32f..1d278b6183 100644 --- a/Client/game_sa/CEntitySA.h +++ b/Client/game_sa/CEntitySA.h @@ -29,6 +29,7 @@ // not in CEntity really #define FUNC_RpAnimBlendClumpGetAssociation 0x4D6870 +class CPhysicalSAInterface; class CRect; /** @@ -81,6 +82,30 @@ static_assert(sizeof(XYZStore) == 0x1FC, "Invalid size for XYZStore"); class CEntitySAInterface : public CPlaceableSAInterface { +public: + 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; + public: RpClump* m_pRwObject; // 24 /********** BEGIN CFLAGS **************/ diff --git a/Client/game_sa/CPhysicalSA.h b/Client/game_sa/CPhysicalSA.h index 2b1234150c..bf44e4ced7 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 index 318701a335..b97edf2819 100644 --- a/Client/game_sa/CPlaceableSA.h +++ b/Client/game_sa/CPlaceableSA.h @@ -22,28 +22,7 @@ class CSimpleTransformSAInterface // 16 bytes class CPlaceableSAInterface { public: - virtual void* Destructor(bool deletedFromPool) = 0; // - virtual void Add_CRect() = 0; - virtual void Add() = 0; // - virtual void Remove() = 0; - virtual void SetIsStatic() = 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 void GetBoundRect() = 0; - virtual void ProcessControl() = 0; // - virtual void ProcessCollision() = 0; - virtual void ProcessShift() = 0; - virtual void TestCollision() = 0; - virtual void Teleport(float x, float y, float z, bool resetRotation) = 0; // - virtual void SpecialEntityPreCollisionStuff() = 0; - virtual void SpecialEntityCalcCollisionSteps() = 0; - virtual void PreRender() = 0; // - virtual void Render() = 0; // - virtual void SetupLighting() = 0; // - virtual void* RemoveLighting(bool) = 0; // - virtual void FlagToDestroyWhenNextProcessed() = 0; // + virtual void* Destructor(bool free) = 0; bool IsPlaceableVTBL() const { return *reinterpret_cast(this) == VTBL_CPlaceable; }; bool HasVTBL() const { return *reinterpret_cast(this) != 0; }; diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index b190429c82..d0651ebce5 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -602,10 +602,9 @@ CDoorSA* CVehicleSA::GetDoor(unsigned char ucDoor) return 0; } -static const int s_iCarNodeIndexes[6] = {0x10, 0x11, 0x0A, 0x08, 0x0B, 0x09}; - void CVehicleSA::OpenDoor(unsigned char ucDoor, float fRatio, bool bMakeNoise) { + static const int s_iCarNodeIndexes[6] = {0x10, 0x11, 0x0A, 0x08, 0x0B, 0x09}; return GetVehicleInterface()->OpenDoor(nullptr, s_iCarNodeIndexes[ucDoor], ucDoor, fRatio, bMakeNoise); } @@ -732,7 +731,7 @@ bool CVehicleSA::GetTowBarPos(CVector* pVector, CVehicle* pTrailer) bool CVehicleSA::GetTowHitchPos(CVector* pVector) { - return GetVehicleInterface()->GetTowHitchPos(pVector, nullptr); + return GetVehicleInterface()->GetTowHitchPos(pVector, true, nullptr); } bool CVehicleSA::IsUpsideDown() diff --git a/Client/game_sa/CVehicleSA.h b/Client/game_sa/CVehicleSA.h index 72c344de7f..eb9eccdba9 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 @@ -207,51 +208,59 @@ class CAutoPilot class CVehicleSAInterface : public CPhysicalSAInterface { public: - // Some virtual functions are not defined propertly - virtual void ProcessEntityCollision() = 0; - virtual void ProcessControlCollisionCheck() = 0; - virtual void ProcessControlInputs() = 0; - virtual void GetComponentWorldPosition() = 0; - virtual void IsComponentPresent() = 0; - virtual void OpenDoor(CEntitySAInterface* entity, std::uint32_t doorFrameId, std::uint32_t doorId, float ratio, bool makeNoise) = 0; - virtual void ProcessOpenDoor() = 0; - virtual void GetDoorAngleOpenRatio() = 0; - virtual void GetDoorAngleOpenRatio_() = 0; - virtual void IsDoorReady() = 0; - virtual void IsDoorReady_() = 0; - virtual void IsDoorFullyOpen() = 0; - virtual void IsDoorFullyOpen_() = 0; - virtual void IsDoorClosed() = 0; - virtual void IsDoorClosed_() = 0; - virtual void IsDoorMissing() = 0; - virtual void IsDoorMissing_() = 0; - virtual void IsOpenTopCar() = 0; - virtual void RemoveRefsToVehicle() = 0; - virtual void BlowUpCar(CEntitySAInterface* creator, std::uint32_t unknown) = 0; - virtual void BlowUpCarCutSceneNoExtras() = 0; - virtual void SetUpWheelColModel() = 0; - virtual void BurstTyre(std::uint8_t tireId, bool unused) = 0; - virtual void IsRoomForPedToLeaveCar() = 0; - virtual void ProcessDrivingAnims() = 0; - virtual void GetRideAnimData() = 0; - virtual void SetupSuspensionLines() = 0; - virtual void AddMovingCollisionSpeed() = 0; - virtual void Fix() = 0; - virtual void SetupDamageAfterLoad() = 0; - virtual void DoBurstAndSoftGroundRatios() = 0; - virtual void GetHeightAboveRoad() = 0; - virtual void PlayCarHorn() = 0; - virtual void GetNumContactWheels() = 0; - virtual void VehicleDamage() = 0; - virtual void CanPedStepOutCar() = 0; - virtual void CanPedJumpOutCar() = 0; - virtual bool GetTowHitchPos(CVector* pVector, CVehicleSAInterface* anotherVehicle) = 0; - virtual bool GetTowbarPos(CVector* pVector, bool ignoreModelType, CVehicleSAInterface* pTrailer) = 0; - virtual void SetTowLink() = 0; - virtual bool BreakTowLink() = 0; - virtual void FindWheelWidth() = 0; - virtual void Save() = 0; - virtual void Load() = 0; + 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; public: CAEVehicleAudioEntitySAInterface m_VehicleAudioEntity; // 312 From a72a16f6696811353983673a6c12a27fd6fd5973 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Wed, 2 Oct 2024 18:56:41 +0300 Subject: [PATCH 4/7] use constexpr --- Client/game_sa/CPlaceableSA.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Client/game_sa/CPlaceableSA.h b/Client/game_sa/CPlaceableSA.h index b97edf2819..f65ca12ec3 100644 --- a/Client/game_sa/CPlaceableSA.h +++ b/Client/game_sa/CPlaceableSA.h @@ -10,7 +10,7 @@ #include #include -#define VTBL_CPlaceable 0x863C40 +constexpr std::uint32_t VTBL_CPlaceable = 0x863C40; class CSimpleTransformSAInterface // 16 bytes { @@ -24,8 +24,8 @@ class CPlaceableSAInterface public: virtual void* Destructor(bool free) = 0; - bool IsPlaceableVTBL() const { return *reinterpret_cast(this) == VTBL_CPlaceable; }; - bool HasVTBL() const { return *reinterpret_cast(this) != 0; }; + bool IsPlaceableVTBL() const { return *reinterpret_cast(this) == (void*)VTBL_CPlaceable; }; + bool HasVTBL() const { return *reinterpret_cast(this) != nullptr; }; public: CSimpleTransformSAInterface m_transform; From 4f5aae156931667b4f65aca1ae7cdffcf2b31a87 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Thu, 3 Oct 2024 21:51:52 +0300 Subject: [PATCH 5/7] Fix IsUsesEntityDeleteRwObject --- Client/game_sa/CEntitySA.h | 2 +- Client/game_sa/CModelInfoSA.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Client/game_sa/CEntitySA.h b/Client/game_sa/CEntitySA.h index f37e75d0c4..067a47e9fc 100644 --- a/Client/game_sa/CEntitySA.h +++ b/Client/game_sa/CEntitySA.h @@ -217,7 +217,7 @@ class CEntitySAInterface : public CPlaceableSAInterface ((CStencilShadow_dtorByOwner)0x711730)(this); }; - bool IsUsesEntityDeleteRwObject() { return *(*reinterpret_cast(this) + 0x20) == 0x00534030; }; + bool IsUsesEntityDeleteRwObject() const { return *reinterpret_cast(*reinterpret_cast(this) + 0x20) == (void*)0x00534030; }; }; static_assert(sizeof(CEntitySAInterface) == 0x38, "Invalid size for CEntitySAInterface"); diff --git a/Client/game_sa/CModelInfoSA.cpp b/Client/game_sa/CModelInfoSA.cpp index 0552f03f95..e915b72f20 100644 --- a/Client/game_sa/CModelInfoSA.cpp +++ b/Client/game_sa/CModelInfoSA.cpp @@ -992,7 +992,7 @@ void CModelInfoSA::StaticFlushPendingRestreamIPL() i / 2 % NUM_StreamSectorRows, i / 2 / NUM_StreamSectorCols)); // Assert in debug #if MTA_DEBUG - assert(!pEntity->IsUsesEntityDeleteRwObject()); + assert(pEntity->IsUsesEntityDeleteRwObject()); #endif pSectorEntry = (DWORD*)pSectorEntry[1]; continue; From ae6025192d8267455d639ebec961a8d1daefd9a0 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Thu, 3 Oct 2024 22:56:33 +0300 Subject: [PATCH 6/7] Fix doors --- Client/game_sa/CVehicleSA.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index d0651ebce5..26058784c6 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -166,7 +166,7 @@ void CVehicleSA::Init() SetColor(m_RGBColors[0], m_RGBColors[1], m_RGBColors[2], m_RGBColors[3], 0); // Initialize doors depending on the vehicle type. - DWORD dwOffset = 0; + std::uint32_t doorArrayOffset; switch (static_cast(GetVehicleInterface()->m_vehicleClass)) { @@ -177,22 +177,25 @@ void CVehicleSA::Init() case VehicleClass::PLANE: case VehicleClass::TRAILER: { - dwOffset = 1464; + doorArrayOffset = 1464; + break; } case VehicleClass::TRAIN: { - dwOffset = 1496; + doorArrayOffset = 1496; + break; } default: + doorArrayOffset = 0; break; } - if (dwOffset != 0) + if (doorArrayOffset != 0) { - for (unsigned int i = 0; i < sizeof(m_doors) / sizeof(m_doors[0]); ++i) + for (std::uint32_t i = 0; i < sizeof(m_doors) / sizeof(m_doors[0]); ++i) { - DWORD dwInterface = (DWORD)GetInterface(); - DWORD dwDoorAddress = dwInterface + dwOffset + i * 24; + std::uint32_t dwInterface = (std::uint32_t)GetInterface(); + std::uint32_t dwDoorAddress = dwInterface + doorArrayOffset + i * 24; m_doors[i].SetInterface((CDoorSAInterface*)dwDoorAddress); } } From 0d55a2441e6fef501ecdda3d6589ad5e32270290 Mon Sep 17 00:00:00 2001 From: Uladzislau Nikalayevich Date: Sat, 26 Oct 2024 03:58:46 +0300 Subject: [PATCH 7/7] Small fixes --- Client/game_sa/CBuildingsPoolSA.h | 4 ++-- Client/game_sa/CEntitySA.h | 2 -- Client/game_sa/CModelInfoSA.cpp | 5 +++-- Client/game_sa/CPlaceableSA.h | 6 ++++-- Client/game_sa/CProjectileSA.h | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Client/game_sa/CBuildingsPoolSA.h b/Client/game_sa/CBuildingsPoolSA.h index 863e916e5f..f9db9f44c9 100644 --- a/Client/game_sa/CBuildingsPoolSA.h +++ b/Client/game_sa/CBuildingsPoolSA.h @@ -43,8 +43,8 @@ class CBuildingsPoolSA : public CBuildingsPool SVectorPoolData m_buildingPool{MAX_BUILDINGS}; CPoolSAInterface** m_ppBuildingPoolInterface; - typedef std::uint8_t building_buffer_t[sizeof(CBuildingSAInterface)]; - typedef std::array, MAX_BUILDINGS> backup_array_t; + 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/CEntitySA.h b/Client/game_sa/CEntitySA.h index 067a47e9fc..585dee903a 100644 --- a/Client/game_sa/CEntitySA.h +++ b/Client/game_sa/CEntitySA.h @@ -216,8 +216,6 @@ class CEntitySAInterface : public CPlaceableSAInterface using CStencilShadow_dtorByOwner = void*(__cdecl*)(CEntitySAInterface * pEntity); ((CStencilShadow_dtorByOwner)0x711730)(this); }; - - bool IsUsesEntityDeleteRwObject() const { return *reinterpret_cast(*reinterpret_cast(this) + 0x20) == (void*)0x00534030; }; }; static_assert(sizeof(CEntitySAInterface) == 0x38, "Invalid size for CEntitySAInterface"); diff --git a/Client/game_sa/CModelInfoSA.cpp b/Client/game_sa/CModelInfoSA.cpp index 3000fa0c75..07f50f0a73 100644 --- a/Client/game_sa/CModelInfoSA.cpp +++ b/Client/game_sa/CModelInfoSA.cpp @@ -985,14 +985,15 @@ void CModelInfoSA::StaticFlushPendingRestreamIPL() CEntitySAInterface* pEntity = (CEntitySAInterface*)pSectorEntry[0]; // Possible bug - pEntity seems to be invalid here occasionally - if (!pEntity->IsUsesEntityDeleteRwObject()) + 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->IsUsesEntityDeleteRwObject()); + assert(static_cast(pEntity->GetVTBL())[CEntity_DeleteRwObject_VTBL_OFFSET] != 0x00534030); #endif pSectorEntry = (DWORD*)pSectorEntry[1]; continue; diff --git a/Client/game_sa/CPlaceableSA.h b/Client/game_sa/CPlaceableSA.h index a0508f07ae..df088b3cbf 100644 --- a/Client/game_sa/CPlaceableSA.h +++ b/Client/game_sa/CPlaceableSA.h @@ -22,8 +22,10 @@ class CPlaceableSAInterface public: virtual void* Destructor(bool free) = 0; - bool IsPlaceableVTBL() const { return *reinterpret_cast(this) == (void*)0x863C40; } - bool HasVTBL() const { return *reinterpret_cast(this) != nullptr; } + 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); } diff --git a/Client/game_sa/CProjectileSA.h b/Client/game_sa/CProjectileSA.h index ee03568a4c..669a566a0f 100644 --- a/Client/game_sa/CProjectileSA.h +++ b/Client/game_sa/CProjectileSA.h @@ -17,7 +17,7 @@ class CProjectileSAInterface : public CObjectSAInterface // entirely inherited from CObject { public: - bool IsProjectableVTBL() const { return *reinterpret_cast(this) == 0x867030; }; + bool IsProjectableVTBL() const { return GetVTBL() == (void*)0x867030; }; }; class CProjectileSA : public virtual CProjectile, public virtual CObjectSA