Skip to content

Commit

Permalink
Add new function spawnVehicleFlyingComponent (#3592)
Browse files Browse the repository at this point in the history
  • Loading branch information
FileEX authored Oct 8, 2024
1 parent 73a09d6 commit 9f54cfc
Show file tree
Hide file tree
Showing 22 changed files with 442 additions and 81 deletions.
35 changes: 1 addition & 34 deletions Client/game_sa/CAutomobileSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,6 @@
#define MAX_PASSENGER_COUNT 8
#define MAX_DOORS 6 // also in CDamageManager

namespace eCarNode
{
enum
{
NONE = 0,
CHASSIS = 1,
WHEEL_RF = 2,
WHEEL_RM = 3,
WHEEL_RB = 4,
WHEEL_LF = 5,
WHEEL_LM = 6,
WHEEL_LB = 7,
DOOR_RF = 8,
DOOR_RR = 9,
DOOR_LF = 10,
DOOR_LR = 11,
BUMP_FRONT = 12,
BUMP_REAR = 13,
WING_RF = 14,
WING_LF = 15,
BONNET = 16,
BOOT = 17,
WINDSCREEN = 18,
EXHAUST = 19,
MISC_A = 20,
MISC_B = 21,
MISC_C = 22,
MISC_D = 23,
MISC_E = 24,
NUM_NODES
};
};

class CBouncingPanelSAInterface
{
public:
Expand All @@ -70,7 +37,7 @@ class CAutomobileSAInterface : public CVehicleSAInterface
public:
CDamageManagerSAInterface m_damageManager;
CDoorSAInterface m_doors[MAX_DOORS];
RwFrame* m_aCarNodes[eCarNode::NUM_NODES];
RwFrame* m_aCarNodes[static_cast<std::size_t>(eCarNodes::NUM_NODES)];
CBouncingPanelSAInterface m_panels[3];
CDoorSAInterface m_swingingChassis;
CColPointSAInterface m_wheelColPoint[MAX_WHEELS];
Expand Down
18 changes: 17 additions & 1 deletion Client/game_sa/CBikeSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@
#include <game/CBike.h>
#include "CVehicleSA.h"

enum class eBikeNodes
{
NONE = 0,
CHASSIS,
FORKS_FRONT,
FORKS_REAR,
WHEEL_FRONT,
WHEEL_REAR,
MUDGUARD,
HANDLEBARS,
MISC_A,
MISC_B,

NUM_NODES
};

struct sRideAnimData
{
int32 iAnimGroup;
Expand All @@ -29,7 +45,7 @@ static_assert(sizeof(sRideAnimData) == 0x1C, "Invalid size for sRideAnimData");
class CBikeSAInterface : public CVehicleSAInterface
{
public:
int32 m_apModelNodes[10];
RwFrame* m_apModelNodes[static_cast<std::size_t>(eBikeNodes::NUM_NODES)];
int8 m_bLeanMatrixCalculated;
int8 pad0[3]; // Maybe prev value is int32
int8 m_mLeanMatrix[72];
Expand Down
16 changes: 16 additions & 0 deletions Client/game_sa/CBmxSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@
#include <game/CBmx.h>
#include "CBikeSA.h"

enum class eBmxNodes
{
NONE = 0,
CHASSIS,
FORKS_FRONT,
FORKS_REAR,
WHEEL_FRONT,
WHEEL_REAR,
HANDLEBARS,
CHAINSET,
PEDAL_R,
PEDAL_L,

NUM_NODES
};

class CBmxSAInterface : public CBikeSAInterface
{
// fill this
Expand Down
20 changes: 19 additions & 1 deletion Client/game_sa/CBoatSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,30 @@
#include <game/CBoat.h>
#include "CVehicleSA.h"

enum class eBoatNodes
{
NONE = 0,
MOVING,
WINDSCREEN,
RUDDER,
FLAP_LEFT,
FLAP_RIGHT,
REARFLAP_LEFT,
REARFLAP_RIGHT,
STATIC_PROP,
MOVING_PROP,
STATIC_PROP2,
MOVING_PROP2,

NUM_NODES
};

class CBoatSAInterface : public CVehicleSAInterface
{
public:
uint32 pad1[3]; // 1440
uint32 BoatFlags; // 1452
RwFrame* pBoatParts[11]; // 1456 [[ find out correct size
RwFrame* pBoatParts[static_cast<std::size_t>(eBoatNodes::NUM_NODES)]; // 1456
uint32 pad2[3]; // 1500
uint16 pad3; // 1512
uint8 pad4[2]; // 1514
Expand Down
44 changes: 21 additions & 23 deletions Client/game_sa/CTrainSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,27 @@
#include "CVehicleSA.h"
#include "CDoorSA.h"

namespace eTrainNode
enum class eTrainNodes
{
enum
{
NONE = 0,
DOOR_LF = 1,
DOOR_RF = 2,
WHEEL_RF1 = 3,
WHEEL_RF2 = 4,
WHEEL_RF3 = 5,
WHEEL_RB1 = 6,
WHEEL_RB2 = 7,
WHEEL_RB3 = 8,
WHEEL_LF1 = 9,
WHEEL_LF2 = 10,
WHEEL_LF3 = 11,
WHEEL_LB1 = 12,
WHEEL_LB2 = 13,
WHEEL_LB3 = 14,
BOGIE_FRONT = 15,
BOGIE_REAR = 16,
NUM_NODES
};
NONE = 0,
DOOR_LF,
DOOR_RF,
WHEEL_RF1,
WHEEL_RF2,
WHEEL_RF3,
WHEEL_RB1,
WHEEL_RB2,
WHEEL_RB3,
WHEEL_LF1,
WHEEL_LF2,
WHEEL_LF3,
WHEEL_LB1,
WHEEL_LB2,
WHEEL_LB3,
BOGIE_FRONT,
BOGIE_REAR,

NUM_NODES
};

enum class eTrainPassengersGenerationState : unsigned char
Expand Down Expand Up @@ -101,7 +99,7 @@ class CTrainSAInterface : public CVehicleSAInterface
CTrainSAInterface* m_prevCarriage;
CTrainSAInterface* m_nextCarriage;
CDoorSAInterface m_aDoors[MAX_DOORS];
RwFrame* m_aTrainNodes[eTrainNode::NUM_NODES];
RwFrame* m_aTrainNodes[static_cast<std::size_t>(eTrainNodes::NUM_NODES)];
};
static_assert(sizeof(CTrainSAInterface) == 0x6AC, "Invalid size for CTrainSAInterface");

Expand Down
109 changes: 90 additions & 19 deletions Client/game_sa/CVehicleSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "CTrainSA.h"
#include "CPlaneSA.h"
#include "CVehicleSA.h"
#include "CBoatSA.h"
#include "CVisibilityPluginsSA.h"
#include "CWorldSA.h"
#include "gamesa_renderware.h"
Expand Down Expand Up @@ -1504,27 +1505,97 @@ void CVehicleSA::SetGravity(const CVector* pvecGravity)
m_vecGravity = *pvecGravity;
}

CObject* CVehicleSA::SpawnFlyingComponent(int i_1, unsigned int ui_2)
bool CVehicleSA::SpawnFlyingComponent(const eCarNodes& nodeIndex, const eCarComponentCollisionTypes& collisionType, std::int32_t removalTime)
{
DWORD dwReturn;
DWORD dwThis = (DWORD)GetInterface();
DWORD dwFunc = FUNC_CAutomobile__SpawnFlyingComponent;
_asm
if (nodeIndex == eCarNodes::NONE)
return false;

DWORD nodesOffset = OFFSET_CAutomobile_Nodes;
RwFrame* defaultBikeChassisFrame = nullptr;

// CBike, CBmx, CBoat and CTrain don't inherit CAutomobile so let's do it manually!
switch (static_cast<VehicleClass>(GetVehicleInterface()->m_vehicleClass))
{
mov ecx, dwThis
push ui_2
push i_1
call dwFunc
mov dwReturn, eax
case VehicleClass::AUTOMOBILE:
case VehicleClass::MONSTER_TRUCK:
case VehicleClass::PLANE:
case VehicleClass::HELI:
case VehicleClass::TRAILER:
case VehicleClass::QUAD:
{
nodesOffset = OFFSET_CAutomobile_Nodes;
break;
}
case VehicleClass::TRAIN:
{
if (static_cast<eTrainNodes>(nodeIndex) >= eTrainNodes::NUM_NODES)
return false;

nodesOffset = OFFSET_CTrain_Nodes;
break;
}
case VehicleClass::BIKE:
case VehicleClass::BMX:
{
auto* bikeInterface = static_cast<CBikeSAInterface*>(GetVehicleInterface());
if (!bikeInterface)
return false;

if (static_cast<eBikeNodes>(nodeIndex) >= eBikeNodes::NUM_NODES)
return false;

nodesOffset = OFFSET_CBike_Nodes;
if (static_cast<eBikeNodes>(nodeIndex) != eBikeNodes::CHASSIS)
break;

// Set the correct "bike_chassis" frame for bikes
defaultBikeChassisFrame = bikeInterface->m_apModelNodes[1];
if (defaultBikeChassisFrame && std::strcmp(defaultBikeChassisFrame->szName, "chassis_dummy") == 0)
{
RwFrame* correctChassisFrame = RwFrameFindFrame(RpGetFrame(bikeInterface->m_pRwObject), "chassis");
if (correctChassisFrame)
bikeInterface->m_apModelNodes[1] = correctChassisFrame;
}
break;
}
case VehicleClass::BOAT:
{
if (static_cast<eBoatNodes>(nodeIndex) >= eBoatNodes::NUM_NODES)
return false;

nodesOffset = OFFSET_CBoat_Nodes;
break;
}
default:
return false;
}

CObject* pObject = NULL;
if (dwReturn)
// Patch nodes array in CAutomobile::SpawnFlyingComponent
MemPut(0x6A85B3, nodesOffset);
MemPut(0x6A8631, nodesOffset);

auto* componentObject = ((CObjectSAInterface * (__thiscall*)(CVehicleSAInterface*, int, int)) FUNC_CAutomobile__SpawnFlyingComponent)(GetVehicleInterface(), static_cast<int>(nodeIndex), static_cast<int>(collisionType));

// Restore default nodes array in CAutomobile::SpawnFlyingComponent
// CAutomobile::m_aCarNodes offset
MemPut(0x6A85B3, 0x648);
MemPut(0x6A8631, 0x648);

// Restore default chassis frame for bikes
if (static_cast<eBikeNodes>(nodeIndex) == eBikeNodes::CHASSIS && defaultBikeChassisFrame)
{
SClientEntity<CObjectSA>* pObjectClientEntity = pGame->GetPools()->GetObject((DWORD*)dwReturn);
pObject = pObjectClientEntity ? pObjectClientEntity->pEntity : nullptr;
auto* bikeInterface = static_cast<CBikeSAInterface*>(GetVehicleInterface());
if (bikeInterface && bikeInterface->m_apModelNodes)
bikeInterface->m_apModelNodes[1] = defaultBikeChassisFrame;
}
return pObject;

if (removalTime <= -1 || !componentObject)
return true;

std::uint32_t CTimer_ms = *reinterpret_cast<std::uint32_t*>(VAR_CTimer_snTimeInMilliseconds);
componentObject->uiObjectRemovalTime = CTimer_ms + static_cast<std::uint32_t>(removalTime);

return true;
}

void CVehicleSA::SetWheelVisibility(eWheelPosition wheel, bool bVisible)
Expand All @@ -1534,16 +1605,16 @@ void CVehicleSA::SetWheelVisibility(eWheelPosition wheel, bool bVisible)
switch (wheel)
{
case FRONT_LEFT_WHEEL:
pFrame = vehicle->m_aCarNodes[eCarNode::WHEEL_LF];
pFrame = vehicle->m_aCarNodes[static_cast<std::size_t>(eCarNodes::WHEEL_LF)];
break;
case REAR_LEFT_WHEEL:
pFrame = vehicle->m_aCarNodes[eCarNode::WHEEL_LB];
pFrame = vehicle->m_aCarNodes[static_cast<std::size_t>(eCarNodes::WHEEL_LB)];
break;
case FRONT_RIGHT_WHEEL:
pFrame = vehicle->m_aCarNodes[eCarNode::WHEEL_RF];
pFrame = vehicle->m_aCarNodes[static_cast<std::size_t>(eCarNodes::WHEEL_RF)];
break;
case REAR_RIGHT_WHEEL:
pFrame = vehicle->m_aCarNodes[eCarNode::WHEEL_RB];
pFrame = vehicle->m_aCarNodes[static_cast<std::size_t>(eCarNodes::WHEEL_RB)];
break;
default:
break;
Expand Down
16 changes: 15 additions & 1 deletion Client/game_sa/CVehicleSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,20 @@ struct RwTexture;
#define FUNC_CAutomobile_OnVehiclePreRender 0x6ABCFD
#define FUNC_CVehicle_DoSunGlare 0x6DD6F0

// CClumpModelInfo::GetFrameFromName
#define FUNC_CClumpModelInfo_GetFrameFromName 0x4C5400

// CAutomobile::m_aCarNodes
// CTrain::m_aTrainNodes
// CBike::m_apModelNodes
// CBoat::pBoatParts
#define OFFSET_CAutomobile_Nodes 0x648
#define OFFSET_CTrain_Nodes 0x668
#define OFFSET_CBike_Nodes 0x5A0
#define OFFSET_CBoat_Nodes 0x5B0

#define VAR_CTimer_snTimeInMilliseconds 0xB7CB84

struct SRailNodeSA
{
short sX; // x coordinate times 8
Expand Down Expand Up @@ -604,7 +618,7 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA
SharedUtil::SColor GetHeadLightColor() { return m_HeadLightColor; }
void SetHeadLightColor(const SharedUtil::SColor color) { m_HeadLightColor = color; }

CObject* SpawnFlyingComponent(int i_1, unsigned int ui_2);
bool SpawnFlyingComponent(const eCarNodes& nodeIndex, const eCarComponentCollisionTypes& collisionType, std::int32_t removalTime = -1);
void SetWheelVisibility(eWheelPosition wheel, bool bVisible);
CVector GetWheelPosition(eWheelPosition wheel);

Expand Down
8 changes: 8 additions & 0 deletions Client/mods/deathmatch/logic/CClientVehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5037,6 +5037,14 @@ void CClientVehicle::ResetWheelScale()
m_bWheelScaleChanged = false;
}

bool CClientVehicle::SpawnFlyingComponent(const eCarNodes& nodeID, const eCarComponentCollisionTypes& collisionType, std::int32_t removalTime)
{
if (!m_pVehicle)
return false;

return m_pVehicle->SpawnFlyingComponent(nodeID, collisionType, removalTime);
}

CVector CClientVehicle::GetEntryPoint(std::uint32_t entryPointIndex)
{
static const uint32_t lookup[4] = {10, 8, 11, 9};
Expand Down
2 changes: 2 additions & 0 deletions Client/mods/deathmatch/logic/CClientVehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,8 @@ class CClientVehicle : public CClientStreamElement
bool SetDummyPosition(eVehicleDummies dummy, const CVector& position);
bool ResetDummyPositions();

bool SpawnFlyingComponent(const eCarNodes& nodeID, const eCarComponentCollisionTypes& collisionType, std::int32_t removalTime);

CVector GetEntryPoint(std::uint32_t entryPointIndex);

protected:
Expand Down
Loading

0 comments on commit 9f54cfc

Please sign in to comment.