Skip to content

Reimplement projectiles #4353

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
32 changes: 17 additions & 15 deletions Client/game_sa/CFxSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@ class FxSystem_c;
#define FUNC_CFx_TriggerFootSplash 0x4a1150
#define FUNC_FXSystem_c_AddParticle 0x4AA440

struct FxPrtMult_c
{
struct
{
float red;
float green;
float blue;
float alpha;
} m_color;

float m_fSize;
float unk;
float m_fLife;
};

class CFxSAInterface
{
public:
Expand Down Expand Up @@ -61,6 +76,8 @@ class CFxSA : public CFx
public:
CFxSA(CFxSAInterface* pInterface) { m_pInterface = pInterface; }

CFxSAInterface* GetInterface() noexcept { return m_pInterface; }

void AddBlood(CVector& vecPosition, CVector& vecDirection, int iCount, float fBrightness);
void AddWood(CVector& vecPosition, CVector& vecDirection, int iCount, float fBrightness);
void AddSparks(CVector& vecPosition, CVector& vecDirection, float fForce, int iCount, CVector vecAcrossLine, unsigned char ucBlurIf0, float fSpread,
Expand All @@ -80,19 +97,4 @@ class CFxSA : public CFx

private:
CFxSAInterface* m_pInterface;

struct FxPrtMult_c
{
struct
{
float red;
float green;
float blue;
float alpha;
} m_color;

float m_fSize;
float unk;
float m_fLife;
};
};
2 changes: 2 additions & 0 deletions Client/game_sa/CGameSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ CGameSA::CGameSA()
CFireSA::StaticSetHooks();
CPtrNodeSingleLinkPoolSA::StaticSetHooks();
CVehicleAudioSettingsManagerSA::StaticSetHooks();
CAutomobileSA::StaticSetHooks();
CProjectileInfoSA::StaticSetHooks();
}
catch (const std::bad_alloc& e)
{
Expand Down
67 changes: 65 additions & 2 deletions Client/game_sa/CMatrixSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ CMatrixSAInterface::CMatrixSAInterface(RwMatrix* matrix, bool temporary)
// destructor detaches matrix if attached
CMatrixSAInterface::~CMatrixSAInterface()
{
((void(__thiscall*)(CMatrixSAInterface*))0x59ACD0)(this);
if (m_bOwnsAttachedMatrix && m_pAttachMatrix)
((void(__cdecl*)(RwMatrix*))0x7F2A20)(m_pAttachMatrix);

//((void(__thiscall*)(CMatrixSAInterface*))0x59ACD0)(this);
}

void CMatrixSAInterface::ConvertToEulerAngles(float& x, float& y, float& z, std::int32_t flags)
Expand All @@ -36,7 +39,67 @@ void CMatrixSAInterface::ConvertFromEulerAngles(float x, float y, float z, std::
((void(__thiscall*)(CMatrixSAInterface*, float, float, float, std::int32_t))0x59AA40)(this, x, y, z, flags);
}

void CMatrixSAInterface::UpdateRwMatrix(RwMatrix* rwMatrix)
{
rwMatrix->right.x = m_right.fX;
rwMatrix->right.y = m_right.fY;
rwMatrix->right.z = m_right.fZ;

rwMatrix->up.x = m_forward.fX;
rwMatrix->up.y = m_forward.fY;
rwMatrix->up.z = m_forward.fZ;

rwMatrix->at.x = m_up.fX;
rwMatrix->at.y = m_up.fY;
rwMatrix->at.z = m_up.fZ;

rwMatrix->pos.x = m_pos.fX;
rwMatrix->pos.y = m_pos.fY;
rwMatrix->pos.z = m_pos.fZ;

((void(__cdecl*)(RwMatrix*))0x7F18A0)(rwMatrix);
//RwMatrixUpdate(rwMatrix);
}

void CMatrixSAInterface::UpdateRW()
{
((void(__thiscall*)(CMatrixSAInterface*))0x59BBB0)(this);
if (!m_pAttachMatrix)
return;

UpdateRwMatrix(m_pAttachMatrix);
}

void CMatrixSAInterface::SetTranslate(const CVector& position)
{
m_right.fX = 1.0f;
m_right.fY = 0;
m_right.fZ = 0;

m_forward.fX = 0;
m_forward.fY = 1.0f;
m_forward.fZ = 0;

m_up.fX = 0;
m_up.fY = 0;
m_up.fZ = 1.0f;

m_pos = position;
}

void CMatrixSAInterface::RotateZ(float angle)
{
float cos = std::cos(angle);
float sin = std::sin(angle);

m_right.fX = cos * m_right.fX - sin * m_right.fY;
m_right.fY = cos * m_right.fY + sin * m_right.fX;

m_forward.fX = cos * m_forward.fX - sin * m_forward.fY;
m_forward.fY = cos * m_forward.fY + sin * m_forward.fX;

m_up.fX = cos * m_up.fX - sin * m_up.fY;
m_up.fY = cos * m_up.fY + sin * m_up.fX;

m_pos.fX = cos * m_pos.fX - sin * m_pos.fY;
m_pos.fY = cos * m_pos.fY + sin * m_pos.fX;
}
24 changes: 24 additions & 0 deletions Client/game_sa/CMatrixSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,37 @@ class CMatrixSAInterface

void ConvertToEulerAngles(float& x, float& y, float& z, std::int32_t flags);
void ConvertFromEulerAngles(float x, float y, float z, std::int32_t flags);

void UpdateRwMatrix(RwMatrix* rwMatrix);
void UpdateRW();

void SetTranslate(const CVector& position); // 0x59AF40 (CMatrix::Translate)

void RotateZ(float angle);

void SetTranslateOnly(CVector position) { m_pos = position; }

CVector GetPosition() const noexcept { return m_pos; }
CVector GetRight() const noexcept { return m_right; }
CVector GetForward() const noexcept { return m_forward; }
CVector GetUp() const noexcept { return m_up; }

void SetMatrix(const CVector& right, const CVector& forward, const CVector& up, const CVector& pos)
{
m_right = right;
m_forward = forward;
m_up = up;
m_pos = pos;
}

CMatrixSAInterface* operator=(const void* m)
{
RwMatrix* attachedMatrix = m_pAttachMatrix;
std::memcpy(this, m, 64);

if (attachedMatrix)
UpdateRwMatrix(attachedMatrix);

return this;
}
};
23 changes: 7 additions & 16 deletions Client/game_sa/CPedSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,6 @@ void CPedSA::SetModelIndex(std::uint32_t modelIndex)
GetPedInterface()->pedSound.m_bIsFemale = type == 5 || type == 22;
}

bool CPedSA::AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity)
{
CProjectileInfo* projectileInfo = pGame->GetProjectileInfo();
if (!projectileInfo)
return false;

return projectileInfo->AddProjectile(static_cast<CEntitySA*>(this), weaponType, origin, force, const_cast<CVector*>(target), const_cast<CEntity*>(targetEntity));
}

void CPedSA::DetachPedFromEntity()
{
// void __thiscall CPed::DettachPedFromEntity(CPed *this)
Expand Down Expand Up @@ -546,12 +537,12 @@ void CPedSA::Say(const ePedSpeechContext& speechId, float probability)
void CPedSA::GetAttachedSatchels(std::vector<SSatchelsData>& satchelsList) const
{
// Array of projectiles objects
auto** projectilesArray = reinterpret_cast<CProjectileSAInterface**>(ARRAY_CProjectile);
CProjectileSAInterface* projectileInterface = nullptr;
auto** projectilesArray = reinterpret_cast<CProjectileSA**>(ARRAY_CProjectile);
CProjectileSA* projectileInterface = nullptr;

// Array of projectiles infos
auto* projectilesInfoArray = reinterpret_cast<CProjectileInfoSAInterface*>(ARRAY_CProjectileInfo);
CProjectileInfoSAInterface* projectileInfoInterface = nullptr;
auto* projectilesInfoArray = reinterpret_cast<CProjectileInfoSA*>(ARRAY_CProjectileInfo);
CProjectileInfoSA* projectileInfoInterface = nullptr;

satchelsList.reserve(PROJECTILE_COUNT);

Expand All @@ -561,18 +552,18 @@ void CPedSA::GetAttachedSatchels(std::vector<SSatchelsData>& satchelsList) const
projectileInterface = projectilesArray[i];

// is attached to our ped?
if (!projectileInterface || projectileInterface->m_pAttachedEntity != m_pInterface)
if (!projectileInterface || projectileInterface->m_object->m_pAttachedEntity != m_pInterface)
continue;

// index is always the same for both arrays
projectileInfoInterface = &projectilesInfoArray[i];

// We are only interested in satchels
if (!projectileInfoInterface || projectileInfoInterface->dwProjectileType != eWeaponType::WEAPONTYPE_REMOTE_SATCHEL_CHARGE)
if (!projectileInfoInterface || projectileInfoInterface->GetType() != eWeaponType::WEAPONTYPE_REMOTE_SATCHEL_CHARGE)
continue;

// Push satchel into the array. There is no need to check the counter because for satchels it restarts until the player detonates the charges
satchelsList.emplace_back(projectileInterface, &projectileInterface->m_vecAttachedOffset, &projectileInterface->m_vecAttachedRotation);
satchelsList.emplace_back(projectileInterface, &projectileInterface->m_object->m_vecAttachedOffset, &projectileInterface->m_object->m_vecAttachedRotation);
}
}

Expand Down
1 change: 0 additions & 1 deletion Client/game_sa/CPedSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,6 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA
float GetOxygenLevel() const override;
void SetOxygenLevel(float oxygen) override;

bool AddProjectile(eWeaponType weaponType, CVector origin, float force, CVector* target, CEntity* targetEntity) override;
CWeapon* GiveWeapon(eWeaponType weaponType, std::uint32_t ammo, eWeaponSkill skill) override;
CWeapon* GetWeapon(eWeaponSlot weaponSlot) const noexcept override;
CWeapon* GetWeapon(eWeaponType weaponType) const override;
Expand Down
4 changes: 3 additions & 1 deletion Client/game_sa/CPhysicalSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class CPhysicalSAInterface : public CEntitySAInterface
uint32 bAttachedToEntity : 1;
uint32 b0x4000000 : 1;
uint32 bTouchingWater : 1;

uint32 bEnableCollision : 1;
uint32 bDestroyed : 1;
uint32 b0x40000000 : 1;
Expand Down Expand Up @@ -107,7 +108,8 @@ class CPhysicalSAInterface : public CEntitySAInterface
CVector m_vecAttachedRotation; // 268
CVector m_vecUnk; // 280
uint32 m_pad4; // 292
CPtrNodeDoubleLink<void>* m_pControlCodeNodeLink; // 296
//CPtrNodeDoubleLink<void>* m_pControlCodeNodeLink; // 296
CEntitySAInterface* m_entityIgnoredCollision;
float m_fLighting; // 300 surface brightness
float m_fLighting2; // 304 dynamic lighting (unused, always set to 0 in the GTA code)
class CShadowDataSA* m_pShadowData; // 308
Expand Down
7 changes: 7 additions & 0 deletions Client/game_sa/CPlaceableSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <CMatrix_Pad.h>
#include <CVector.h>
#include "CMatrixSA.h"

class CSimpleTransformSAInterface // 16 bytes
{
Expand All @@ -29,6 +30,12 @@ class CPlaceableSAInterface
bool HasMatrix() const noexcept { return matrix != nullptr; }
void RemoveMatrix() { ((void(__thiscall*)(void*))0x54F3B0)(this); }

// Since the m_matrix field has an incorrect type, we currently call the GetMatrix method directly.
// In the future, after a refactor, we can reimplement this method here without needing to call the external function.
CMatrixSAInterface* GetMatrix() { return ((CMatrixSAInterface*(__thiscall*)(CPlaceableSAInterface*))0x411990)(this); }

void SetMatrix(CMatrixSAInterface* matrix) { ((void(__thiscall*)(CPlaceableSAInterface*, CMatrixSAInterface*))0x54F610)(this, matrix); }

void SetOrientation(float x, float y, float z) { ((void(__thiscall*)(CPlaceableSAInterface * pEntity, float, float, float))0x439A80)(this, x, y, z); }

public:
Expand Down
17 changes: 17 additions & 0 deletions Client/game_sa/CPoolsSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1089,3 +1089,20 @@ void CPoolsSA::InvalidateLocalPlayerClientEntity()
{
m_pedPool.arrayOfClientEntities[0] = {m_pedPool.arrayOfClientEntities[0].pEntity, nullptr};
}

std::uint16_t CPoolsSA::GetObjectHandle(CObjectSAInterface* object) const
{
auto pool = *reinterpret_cast<CPoolSAInterface<CObjectSAInterface>**>(CLASS_CPool_Object);
if (!pool || !pool->m_pObjects || !pool->m_byteMap)
return 0xFFFF;

int index = static_cast<int>((reinterpret_cast<std::uintptr_t>(object) - reinterpret_cast<std::uintptr_t>(pool->m_pObjects)) / (sizeof(CObjectSAInterface) + 32));
if (index < 0 || index >= pool->m_nSize)
return 0xFFFF;

const tPoolObjectFlags& flags = pool->m_byteMap[index];
if (flags.bEmpty)
return 0xFFFF;

return static_cast<std::uint16_t>((index << 8) | flags.nId);
}
3 changes: 3 additions & 0 deletions Client/game_sa/CPoolsSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ class CPoolsSA : public CPools
CTxdPool& GetTxdPool() noexcept { return m_TxdPool; };
CPtrNodeSingleLinkPool& GetPtrNodeSingleLinkPool() noexcept override { return m_PtrNodeSingleLinkPool; };

[[nodiscard]]
std::uint16_t GetObjectHandle(CObjectSAInterface* object) const override;

private:
// Pools
SPoolData<CVehicleSA, CVehicleSAInterface, MAX_VEHICLES> m_vehiclePool;
Expand Down
Loading
Loading