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 19 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()); };
};
6 changes: 6 additions & 0 deletions Client/game_sa/CFileLoaderSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ void CFileLoaderSA::StaticSetHooks()
HookInstall(0x538690, (DWORD)CFileLoader_LoadObjectInstance, 5);
}

CEntitySAInterface* CFileLoaderSA::LoadObjectInstance(SFileObjectInstance* obj)
{
// Second argument is model name. It's unused in the function
return ((CEntitySAInterface * (__cdecl*)(SFileObjectInstance*, const char*))0x538090)(obj, nullptr);
}

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();

static 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
118 changes: 117 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,107 @@ 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;

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

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

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

// 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 +780,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 +807,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