Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions Client/game_sa/CBuildingSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
#include "CBuildingSA.h"
#include <game/CWorld.h>
#include "CGameSA.h"
#include "CMatrixLinkSA.h"
#include "CDynamicPool.h"

extern CGameSA* pGame;

static CDynamicPool<CMatrixLinkSAInterface, PoolGrowAddStrategy<0, 500>> g_matrixPool{};

CBuildingSA::CBuildingSA(CBuildingSAInterface* pInterface)
{
SetInterface(pInterface);
Expand Down Expand Up @@ -65,3 +69,42 @@ void CBuildingSA::SetLod(CBuilding* pLod)
}
}
}

void CBuildingSA::AllocateMatrix()
{
auto* newMatrix = g_matrixPool.AllocateItem();
std::memset(newMatrix, 0, sizeof(CMatrixLinkSAInterface));
newMatrix->SetTranslateOnly(m_pInterface->Placeable.m_transform.m_translate);

m_pInterface->Placeable.matrix = reinterpret_cast<CMatrix_Padded*>(newMatrix);
}

void CBuildingSA::ReallocateMatrix()
{
if (!m_pInterface->HasMatrix())
return;

auto* newMatrix = g_matrixPool.AllocateItem();
std::memcpy(newMatrix, m_pInterface->Placeable.matrix, sizeof(CMatrixLinkSAInterface));
newMatrix->m_pOwner = nullptr;
newMatrix->m_pPrev = nullptr;
newMatrix->m_pNext = nullptr;

m_pInterface->RemoveMatrix();
m_pInterface->Placeable.matrix = reinterpret_cast<CMatrix_Padded*>(newMatrix);
}

void CBuildingSA::RemoveAllocatedMatrix()
{
if (!m_pInterface->HasMatrix())
return;

CMatrixLinkSAInterface* pMatrix = reinterpret_cast<CMatrixLinkSAInterface*>(m_pInterface->Placeable.matrix);

if (pMatrix->m_pOwner || (pMatrix->m_pNext && pMatrix->m_pPrev))
return;

g_matrixPool.RemoveItem(reinterpret_cast<CMatrixLinkSAInterface*>(m_pInterface->Placeable.matrix));
g_matrixPool.SetCapacity(0);
m_pInterface->Placeable.matrix = nullptr;
}
4 changes: 4 additions & 0 deletions Client/game_sa/CBuildingSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ class CBuildingSA final : public virtual CBuilding, public virtual CEntitySA
CBuildingSAInterface* GetBuildingInterface() { return static_cast<CBuildingSAInterface*>(GetInterface()); };

void SetLod(CBuilding* pLod) override;

void AllocateMatrix();
void ReallocateMatrix();
void RemoveAllocatedMatrix();
};
40 changes: 29 additions & 11 deletions Client/game_sa/CBuildingsPoolSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ CClientEntity* CBuildingsPoolSA::GetClientBuilding(CBuildingSAInterface* pGameIn
return m_buildingPool.entities[poolIndex].pClientEntity;
}

CBuilding* CBuildingsPoolSA::AddBuilding(CClientBuilding* pClientBuilding, uint16_t modelId, CVector* vPos, CVector4D* vRot, uint8_t interior)
CBuilding* CBuildingsPoolSA::AddBuilding(CClientBuilding* pClientBuilding, uint16_t modelId, CVector* vPos, CVector* vRot, uint8_t interior)
{
if (!HasFreeBuildingSlot())
return nullptr;
Expand All @@ -72,15 +72,12 @@ CBuilding* CBuildingsPoolSA::AddBuilding(CClientBuilding* pClientBuilding, uint1
modelInfo->SetObjectPropertiesGroup(MODEL_PROPERTIES_GROUP_STATIC);

// Load building
SFileObjectInstance instance;
SFileObjectInstance instance{};
instance.modelID = modelId;
instance.lod = -1;
instance.interiorID = interior;
instance.position = *vPos;
instance.rotation = *vRot;

// Fix strange SA rotation
instance.rotation.fW = -instance.rotation.fW;
instance.rotation = {};

auto pBuilding = static_cast<CBuildingSAInterface*>(CFileLoaderSA::LoadObjectInstance(&instance));

Expand All @@ -98,6 +95,22 @@ CBuilding* CBuildingsPoolSA::AddBuilding(CClientBuilding* pClientBuilding, uint1

// Add building in world
auto pBuildingSA = new CBuildingSA(pBuilding);

if (pBuilding->HasMatrix())
{
// Edge case for the traincross2 (1374) model
// LoadObjectInstance allocates a matrix for the model
// We need allocate our own matrix and put the old matrix in the original pool
pBuildingSA->ReallocateMatrix();
}
else if (vRot->fX != 0 || vRot->fY != 0)
{
// Allocate matrix in our unlimited storage instead of using the shared pool.
pBuildingSA->AllocateMatrix();
}

pBuilding->SetOrientation(vRot->fX, vRot->fY, vRot->fZ);

pGame->GetWorld()->Add(pBuildingSA, CBuildingPool_Constructor);

// Add CBuildingSA object in pool
Expand All @@ -116,6 +129,10 @@ void CBuildingsPoolSA::RemoveBuilding(CBuilding* pBuilding)
if (dwElementIndexInPool == UINT_MAX)
return;

// Remove references to allocated matrix
auto* pBuildingSA = m_buildingPool.entities[dwElementIndexInPool].pEntity;
pBuildingSA->RemoveAllocatedMatrix();

// Remove building from cover list
pGame->GetCoverManager()->RemoveCover(pInterface);

Expand All @@ -128,23 +145,24 @@ void CBuildingsPoolSA::RemoveBuilding(CBuilding* pBuilding)
// Remove building from world
pGame->GetWorld()->Remove(pInterface, CBuildingPool_Destructor);

std::uint16_t modelId = pInterface->m_nModelIndex;

// Call virtual destructor
((void*(__thiscall*)(void*, char))pInterface->vtbl->SCALAR_DELETING_DESTRUCTOR)(pInterface, 0);

// Remove col reference
auto modelInfo = pGame->GetModelInfo(pBuilding->GetModelIndex());
auto modelInfo = pGame->GetModelInfo(modelId);
modelInfo->RemoveColRef();

// Remove building from SA pool
(*m_ppBuildingPoolInterface)->Release(dwElementIndexInPool);

// Remove from BuildingSA pool
auto* pBuildingSA = m_buildingPool.entities[dwElementIndexInPool].pEntity;
m_buildingPool.entities[dwElementIndexInPool] = {nullptr, nullptr};

// Delete it from memory
delete pBuildingSA;

// Remove building from SA pool
(*m_ppBuildingPoolInterface)->Release(dwElementIndexInPool);

// Decrease the count of elements in the pool
--m_buildingPool.count;
}
Expand Down
2 changes: 1 addition & 1 deletion Client/game_sa/CBuildingsPoolSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class CBuildingsPoolSA : public CBuildingsPool
CBuildingsPoolSA();
~CBuildingsPoolSA() = default;

CBuilding* AddBuilding(CClientBuilding*, uint16_t modelId, CVector* vPos, CVector4D* vRot, uint8_t interior);
CBuilding* AddBuilding(CClientBuilding*, uint16_t modelId, CVector* vPos, CVector* vRot, uint8_t interior);
void RemoveBuilding(CBuilding* pBuilding);
bool HasFreeBuildingSlot();

Expand Down
16 changes: 3 additions & 13 deletions Client/game_sa/CEntitySA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,21 +213,11 @@ void CEntitySA::Render()
void CEntitySA::SetOrientation(float fX, float fY, float fZ)
{
pGame->GetWorld()->Remove(this, CEntity_SetOrientation);
DWORD dwThis = (DWORD)m_pInterface;
DWORD dwFunc = FUNC_SetOrientation;
_asm
{
// ChrML: I've switched the X and Z at this level because that's how the real rotation
// is. GTA has kinda swapped them in this function.

push fZ
push fY
push fX
mov ecx, dwThis
call dwFunc
}
m_pInterface->SetOrientation(fX, fY, fZ);

dwFunc = 0x446F90;
DWORD dwThis = (DWORD)m_pInterface;
DWORD dwFunc = 0x446F90;
_asm
{
mov ecx, dwThis
Expand Down
6 changes: 5 additions & 1 deletion Client/game_sa/CEntitySA.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#define FUNC_GetDistanceFromCentreOfMassToBaseOfModel 0x536BE0

#define FUNC_SetRwObjectAlpha 0x5332C0
#define FUNC_SetOrientation 0x439A80

#define FUNC_CMatrix__ConvertToEulerAngles 0x59A840
#define FUNC_CMatrix__ConvertFromEulerAngles 0x59AA40
Expand Down Expand Up @@ -246,6 +245,11 @@ class CEntitySAInterface
((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();
Expand Down
26 changes: 26 additions & 0 deletions Client/game_sa/CMatrixLinkSA.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CMatrixLinkSA.h
*
* Multi Theft Auto is available from https://www.multitheftauto.com/
*
*****************************************************************************/

#pragma once

#include "CMatrixSA.h"

class CPlaceableSAInterface;

class CMatrixLinkSAInterface : public CMatrixSAInterface
{
public:
CMatrixLinkSAInterface() : CMatrixSAInterface{}, m_pOwner{}, m_pPrev{}, m_pNext{} {}

public:
CPlaceableSAInterface* m_pOwner;
CMatrixLinkSAInterface* m_pPrev;
CMatrixLinkSAInterface* m_pNext;
};
10 changes: 10 additions & 0 deletions Client/game_sa/CMatrixSA.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CMatrixSA.cpp
*
* Multi Theft Auto is available from https://www.multitheftauto.com/
*
*****************************************************************************/

#include "StdInc.h"
#include "CMatrixSA.h"

Expand Down
11 changes: 11 additions & 0 deletions Client/game_sa/CMatrixSA.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CMatrixSA.h
*
* Multi Theft Auto is available from https://www.multitheftauto.com/
*
*****************************************************************************/

#pragma once
#include "CVector.h"
#include "CRenderWareSA.h"
Expand All @@ -19,6 +29,7 @@ class CMatrixSAInterface
RwMatrix* m_pAttachMatrix = nullptr;
bool m_bOwnsAttachedMatrix = false; // do we need to delete attaching matrix at detaching

CMatrixSAInterface() : m_right{}, flags{}, m_forward{}, pad1{}, m_up{}, pad2{}, m_pos{}, pad3{} {};
CMatrixSAInterface(CMatrixSAInterface const& matrix);
CMatrixSAInterface(RwMatrix* matrix, bool temporary); // like previous + attach
~CMatrixSAInterface(); // destructor detaches matrix if attached
Expand Down
5 changes: 1 addition & 4 deletions Client/mods/deathmatch/logic/CClientBuilding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,7 @@ void CClientBuilding::Create()
if (m_bBeingDeleted)
return;

CVector4D vRot4D;
ConvertZXYEulersToQuaternion(m_vRot, vRot4D);

m_pBuilding = g_pGame->GetPools()->GetBuildingsPool().AddBuilding(this, m_usModelId, &m_vPos, &vRot4D, m_interior);
m_pBuilding = g_pGame->GetPools()->GetBuildingsPool().AddBuilding(this, m_usModelId, &m_vPos, &m_vRot, m_interior);

if (!m_pBuilding)
return;
Expand Down
2 changes: 1 addition & 1 deletion Client/sdk/game/CBuildingsPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class CBuildingsPool
public:

// Buildings pool
virtual CBuilding* AddBuilding(class CClientBuilding*, std::uint16_t modelId, CVector* vPos, CVector4D* vRot, std::uint8_t interior) = 0;
virtual CBuilding* AddBuilding(class CClientBuilding*, std::uint16_t modelId, CVector* vPos, CVector* vRot, std::uint8_t interior) = 0;
virtual void RemoveBuilding(CBuilding* pObject) = 0;
virtual bool HasFreeBuildingSlot() = 0;
virtual bool Resize(int size) = 0;
Expand Down
16 changes: 0 additions & 16 deletions Shared/mods/deathmatch/logic/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,22 +256,6 @@ inline float GetSmallestWrapUnsigned(float fValue, float fHigh)

void RotateVector(CVector& vecLine, const CVector& vecRotation);

inline void ConvertZXYEulersToQuaternion(const CVector& vecFrom, CVector4D &vecTo)
{
const float c1 = cos(vecFrom.fX * 0.5f);
const float c2 = cos(vecFrom.fY * 0.5f);
const float c3 = cos(vecFrom.fZ * 0.5f);

const float s1 = sin(vecFrom.fX * 0.5f);
const float s2 = sin(vecFrom.fY * 0.5f);
const float s3 = sin(vecFrom.fZ * 0.5f);

vecTo.fX = s1 * c2 * c3 - c1 * s2 * s3;
vecTo.fY = c1 * s2 * c3 + s1 * c2 * s3;
vecTo.fZ = c1 * c2 * s3 + s1 * s2 * c3;
vecTo.fW = c1 * c2 * c3 - s1 * s2 * s3;
}

#ifdef MTA_CLIENT
// Misc utility functions
unsigned int StripUnwantedCharacters(char* szText, unsigned char cReplace = ' ');
Expand Down
Loading