Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lua API for buildings #3274

Merged
merged 23 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions Client/game_sa/CBuildingSA.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CBuildingSA.cpp
* PURPOSE: Building entity
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#include "StdInc.h"
#include "CBuildingSA.h"

CBuildingSA::CBuildingSA(CBuildingSAInterface* pInterface)
{
SetInterface(pInterface);
}
28 changes: 28 additions & 0 deletions Client/game_sa/CBuildingSA.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: game_sa/CBuildingSA.h
* PURPOSE: Header file for game building class
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/

#pragma once

#include <game/CBuilding.h>
#include "CEntitySA.h"

class CBuildingSAInterface : public CEntitySAInterface
{
};
static_assert(sizeof(CBuildingSAInterface) == 0x38, "Invalid size CBuildingSAInterface");

class CBuildingSA final : public virtual CBuilding, public virtual CEntitySA
{
public:
CBuildingSA(CBuildingSAInterface* pInterface);

CBuildingSAInterface* GetBuildingInterface() { return reinterpret_cast<CBuildingSAInterface*>(GetInterface()); };
};
5 changes: 5 additions & 0 deletions Client/game_sa/CFileLoaderSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ void CFileLoaderSA::StaticSetHooks()
HookInstall(0x538690, (DWORD)CFileLoader_LoadObjectInstance, 5);
}

CEntitySAInterface* CFileLoaderSA::LoadObjectInstance(SFileObjectInstance* obj)
{
return ((CEntitySAInterface * (__cdecl*)(SFileObjectInstance*))0x538090)(obj);
TheNormalnij marked this conversation as resolved.
Show resolved Hide resolved
}

class CAtomicModelInfo
{
public:
Expand Down
2 changes: 2 additions & 0 deletions Client/game_sa/CFileLoaderSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class CFileLoaderSA
CFileLoaderSA();
~CFileLoaderSA();

CEntitySAInterface* LoadObjectInstance(SFileObjectInstance*);

static void StaticSetHooks();
};

Expand Down
2 changes: 2 additions & 0 deletions Client/game_sa/CModelInfoSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ class CModelInfoSA : public CModelInfo
// Vehicle towing functions
bool IsTowableBy(CModelInfo* towingModel) override;

bool IsDynamic() { return m_pInterface ? m_pInterface->usDynamicIndex != 0xffff : false; };

private:
void CopyStreamingInfoFromModel(ushort usCopyFromModelID);
void RwSetSupportedUpgrades(RwFrame* parent, DWORD dwModel);
Expand Down
116 changes: 115 additions & 1 deletion Client/game_sa/CPoolsSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "CBikeSA.h"
#include "CBmxSA.h"
#include "CBoatSA.h"
#include "CBuildingSA.h"
#include "CGameSA.h"
#include "CHeliSA.h"
#include "CMonsterTruckSA.h"
Expand All @@ -24,6 +25,7 @@
#include "CTrainSA.h"
#include "CWorldSA.h"
#include "CKeyGenSA.h"
#include "CFileLoaderSA.h"

extern CGameSA* pGame;

Expand All @@ -33,6 +35,7 @@ CPoolsSA::CPoolsSA()
m_ppObjectPoolInterface = (CPoolSAInterface<CObjectSAInterface>**)0xB7449C;
m_ppVehiclePoolInterface = (CPoolSAInterface<CVehicleSAInterface>**)0xB74494;
m_ppTxdPoolInterface = (CPoolSAInterface<CTextureDictonarySAInterface>**)0xC8800C;
m_ppBuildingPoolInterface = (CPoolSAInterface<CBuildingSAInterface>**)0xB74498;

m_bGetVehicleEnabled = true;
}
Expand Down Expand Up @@ -329,6 +332,105 @@ void CPoolsSA::DeleteAllObjects()
}
}

//////////////////////////////////////////////////////////////////////////////////////////
// BUILDINGS POOL //
//////////////////////////////////////////////////////////////////////////////////////////

inline bool CPoolsSA::AddBuildingToPool(CClientBuilding* pClientBuilding, CBuildingSA* pBuilding)
{
// Grab the new object interface
CBuildingSAInterface* pInterface = pBuilding->GetBuildingInterface();

if (!pInterface)
return false;

DWORD dwElementIndexInPool = GetBuildingPoolIndex((std::uint8_t*)pInterface);
if (dwElementIndexInPool >= MAX_BUILDINGS)
{
return false;
}

m_buildingPool.arrayOfClientEntities[dwElementIndexInPool] = {pBuilding, (CClientEntity*)pClientBuilding};

// Increase the count of objects
++m_buildingPool.ulCount;

return true;
}

CBuilding* CPoolsSA::AddBuilding(CClientBuilding* pClientBuilding, uint16_t modelId, CVector *vPos, CVector4D *vRot, uint8_t interior)
{
if (!HasFreeBuildingSlot())
return nullptr;

// Load building
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;

CFileLoaderSA loader{};
auto pBuilding = static_cast<CBuildingSAInterface*>(loader.LoadObjectInstance(&instance));
TheNormalnij marked this conversation as resolved.
Show resolved Hide resolved

// Disable lod and ipl
pBuilding->m_pLod = nullptr;
pBuilding->m_iplIndex = 0;

// Always stream model collosion
// TODO We can setup collison bounding box and use GTA streamer for it
auto modelInfo = pGame->GetModelInfo(modelId);
modelInfo->AddColRef();

// Add building in world
auto pBuildingSA = new CBuildingSA(pBuilding);
pGame->GetWorld()->Add(pBuildingSA, CBuildingPool_Constructor);

// Add CBuildingSA object in pool
AddBuildingToPool(pClientBuilding, pBuildingSA);

return pBuildingSA;
}

void CPoolsSA::RemoveBuilding(CBuilding* pBuilding)
{
assert(NULL != pBuilding);

CBuildingSAInterface* pInterface = pBuilding->GetBuildingInterface();

DWORD dwElementIndexInPool = GetBuildingPoolIndex((std::uint8_t*)pInterface);
if (dwElementIndexInPool >= MAX_BUILDINGS)
{
return;
}

// Remove building from world
pGame->GetWorld()->Remove(pInterface, CBuildingPool_Destructor);

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

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

// Delete it from memory
delete pBuildingSA;

// Decrease the count of elements in the pool
--m_buildingPool.ulCount;
}

bool CPoolsSA::HasFreeBuildingSlot()
{
return (*m_ppBuildingPoolInterface)->GetFreeSlot() != -1;
}

//////////////////////////////////////////////////////////////////////////////////////////
// PEDS POOL //
//////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -676,7 +778,7 @@ DWORD CPoolsSA::GetPedPoolIndex(std::uint8_t* pInterface)
{
return MAX_PEDS;
}
return ((pInterface - pTheObjects) / dwAlignedSize);
return ((pInterface - pTheObjects) / dwAlignedSize);
}

DWORD CPoolsSA::GetVehiclePoolIndex(std::uint8_t* pInterface)
Expand All @@ -703,6 +805,18 @@ DWORD CPoolsSA::GetObjectPoolIndex(std::uint8_t* pInterface)
return ((pInterface - pTheObjects) / dwAlignedSize);
}

DWORD CPoolsSA::GetBuildingPoolIndex(std::uint8_t* pInterface)
{
DWORD dwAlignedSize = sizeof(CBuildingSAInterface);
std::uint8_t* pTheObjects = (std::uint8_t*)(*m_ppBuildingPoolInterface)->m_pObjects;
DWORD dwMaxIndex = MAX_BUILDINGS - 1;
if (pInterface < pTheObjects || pInterface > pTheObjects + (dwMaxIndex * dwAlignedSize))
{
return MAX_BUILDINGS;
}
return ((pInterface - pTheObjects) / dwAlignedSize);
}

uint CPoolsSA::GetModelIdFromClump(RpClump* pRpClump)
{
// Search our pools for a match
Expand Down
31 changes: 21 additions & 10 deletions Client/game_sa/CPoolsSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "CPedSA.h"
#include "CVehicleSA.h"
#include "CObjectSA.h"
#include "CBuildingSA.h"
#include "CTextureDictonarySA.h"

#define INVALID_POOL_ARRAY_ID 0xFFFFFFFF
Expand Down Expand Up @@ -170,6 +171,15 @@ class CPoolsSA : public CPools
unsigned long GetObjectCount() { return m_objectPool.ulCount; }
void DeleteAllObjects();

// Buildings pool
private:
bool AddBuildingToPool(CClientBuilding* pClientBuilding, CBuildingSA* pBuilding);

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

// Peds pool
CPed* AddPed(CClientPed* pClientPed, unsigned int nModelIndex);
CPed* AddPed(CClientPed* pClientPed, DWORD* pGameInterface);
Expand All @@ -195,6 +205,7 @@ class CPoolsSA : public CPools
DWORD GetPedPoolIndex(std::uint8_t* pInterface);
DWORD GetVehiclePoolIndex(std::uint8_t* pInterfacee);
DWORD GetObjectPoolIndex(std::uint8_t* pInterface);
DWORD GetBuildingPoolIndex(std::uint8_t* pInterface);

int GetNumberOfUsedSpaces(ePools pools);
int GetPoolDefaultCapacity(ePools pool);
Expand Down Expand Up @@ -231,16 +242,16 @@ class CPoolsSA : public CPools
};

// Pools
typedef SPoolData<CVehicleSA, CVehicleSAInterface, MAX_VEHICLES> vehiclePool_t;
typedef SPoolData<CPedSA, CPedSAInterface, MAX_PEDS> pedPool_t;
typedef SPoolData<CObjectSA, CObjectSAInterface, MAX_OBJECTS> objectPool_t;
vehiclePool_t m_vehiclePool;
pedPool_t m_pedPool;
objectPool_t m_objectPool;
CPoolSAInterface<CPedSAInterface>** m_ppPedPoolInterface;
CPoolSAInterface<CObjectSAInterface>** m_ppObjectPoolInterface;
CPoolSAInterface<CVehicleSAInterface>** m_ppVehiclePoolInterface;
CPoolSAInterface<CTextureDictonarySAInterface>** m_ppTxdPoolInterface;
SPoolData<CVehicleSA, CVehicleSAInterface, MAX_VEHICLES> m_vehiclePool;
SPoolData<CPedSA, CPedSAInterface, MAX_PEDS> m_pedPool;
SPoolData<CObjectSA, CObjectSAInterface, MAX_OBJECTS> m_objectPool;
SPoolData<CBuildingSA, CBuildingSAInterface, MAX_BUILDINGS> m_buildingPool;

CPoolSAInterface<CPedSAInterface>** m_ppPedPoolInterface;
CPoolSAInterface<CObjectSAInterface>** m_ppObjectPoolInterface;
CPoolSAInterface<CVehicleSAInterface>** m_ppVehiclePoolInterface;
CPoolSAInterface<CTextureDictonarySAInterface>** m_ppTxdPoolInterface;
CPoolSAInterface<CBuildingSAInterface>** m_ppBuildingPoolInterface;

bool m_bGetVehicleEnabled;
};
Expand Down
2 changes: 2 additions & 0 deletions Client/mods/deathmatch/StdInc.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include <CClientCommon.h>
#include <CClientManager.h>
#include <CClient3DMarker.h>
#include <CClientBuilding.h>
#include <CClientCheckpoint.h>
#include <CClientColShape.h>
#include <CClientColCircle.h>
Expand Down Expand Up @@ -143,6 +144,7 @@
#include <luadefs/CLuaWaterDefs.h>
#include <luadefs/CLuaWeaponDefs.h>
#include <luadefs/CLuaWorldDefs.h>
#include <luadefs/CLuaBuildingDefs.h>
#include <CRemoteCalls.h>

// Shared includes
Expand Down
86 changes: 86 additions & 0 deletions Client/mods/deathmatch/logic/CClientBuilding.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* (Shared logic for modifications)
* LICENSE: See LICENSE in the top level directory
* FILE: mods/shared_logic/CClientBuilding.cpp
* PURPOSE: Buildings handling class
*
*****************************************************************************/

#include "StdInc.h"

CClientBuilding::CClientBuilding(class CClientManager* pManager, ElementID ID, uint16_t usModelId, const CVector &pos, const CVector &rot, uint8_t interior)
: ClassInit(this),
CClientEntity(ID),
m_pBuildingManager(pManager->GetBuildingManager()),
m_usModelId(usModelId),
m_vPos(pos),
m_vRot(rot),
m_interior(interior),
m_pBuilding(nullptr)
{
m_pManager = pManager;
TheNormalnij marked this conversation as resolved.
Show resolved Hide resolved
SetTypeName("building");
m_pBuildingManager->AddToList(this);
Create();
}

CClientBuilding::~CClientBuilding()
{
m_pBuildingManager->RemoveFromList(this);
Destroy();
}

void CClientBuilding::SetPosition(const CVector& vecPosition)
{
if (m_vPos == vecPosition)
return;
m_vPos = vecPosition;
Recreate();
}

void CClientBuilding::SetRotationRadians(const CVector& vecRadians)
{
if (m_vRot == vecRadians)
return;
m_vRot = vecRadians;
Recreate();
}

void CClientBuilding::SetInterior(uint8_t ucInterior)
{
if (m_interior == ucInterior)
return;
m_interior = ucInterior;
TheNormalnij marked this conversation as resolved.
Show resolved Hide resolved
Recreate();
}

void CClientBuilding::SetModel(uint16_t model)
{
if (CClientObjectManager::IsValidModel(model))
{
m_usModelId = model;
Recreate();
}
}

void CClientBuilding::Create()
{
if (m_pBuilding)
return;

CVector4D vRot4D;
ConvertEulersToQuaternion(m_vRot, vRot4D);

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

void CClientBuilding::Destroy()
{
if (m_pBuilding)
{
g_pGame->GetPools()->RemoveBuilding(m_pBuilding);
m_pBuilding = nullptr;
}
}