2121#include " CTrainSA.h"
2222#include " CPlaneSA.h"
2323#include " CVehicleSA.h"
24+ #include " CBoatSA.h"
2425#include " CVisibilityPluginsSA.h"
2526#include " CWorldSA.h"
2627#include " gamesa_renderware.h"
@@ -1504,27 +1505,97 @@ void CVehicleSA::SetGravity(const CVector* pvecGravity)
15041505 m_vecGravity = *pvecGravity;
15051506}
15061507
1507- CObject* CVehicleSA::SpawnFlyingComponent (int i_1, unsigned int ui_2 )
1508+ bool CVehicleSA::SpawnFlyingComponent (const eCarNodes& nodeIndex, const eCarComponentCollisionTypes& collisionType, std:: int32_t removalTime )
15081509{
1509- DWORD dwReturn;
1510- DWORD dwThis = (DWORD)GetInterface ();
1511- DWORD dwFunc = FUNC_CAutomobile__SpawnFlyingComponent;
1512- _asm
1510+ if (nodeIndex == eCarNodes::NONE)
1511+ return false ;
1512+
1513+ DWORD nodesOffset = OFFSET_CAutomobile_Nodes;
1514+ RwFrame* defaultBikeChassisFrame = nullptr ;
1515+
1516+ // CBike, CBmx, CBoat and CTrain don't inherit CAutomobile so let's do it manually!
1517+ switch (static_cast <VehicleClass>(GetVehicleInterface ()->m_vehicleClass ))
15131518 {
1514- mov ecx, dwThis
1515- push ui_2
1516- push i_1
1517- call dwFunc
1518- mov dwReturn, eax
1519+ case VehicleClass::AUTOMOBILE:
1520+ case VehicleClass::MONSTER_TRUCK:
1521+ case VehicleClass::PLANE:
1522+ case VehicleClass::HELI:
1523+ case VehicleClass::TRAILER:
1524+ case VehicleClass::QUAD:
1525+ {
1526+ nodesOffset = OFFSET_CAutomobile_Nodes;
1527+ break ;
1528+ }
1529+ case VehicleClass::TRAIN:
1530+ {
1531+ if (static_cast <eTrainNodes>(nodeIndex) >= eTrainNodes::NUM_NODES)
1532+ return false ;
1533+
1534+ nodesOffset = OFFSET_CTrain_Nodes;
1535+ break ;
1536+ }
1537+ case VehicleClass::BIKE:
1538+ case VehicleClass::BMX:
1539+ {
1540+ auto * bikeInterface = static_cast <CBikeSAInterface*>(GetVehicleInterface ());
1541+ if (!bikeInterface)
1542+ return false ;
1543+
1544+ if (static_cast <eBikeNodes>(nodeIndex) >= eBikeNodes::NUM_NODES)
1545+ return false ;
1546+
1547+ nodesOffset = OFFSET_CBike_Nodes;
1548+ if (static_cast <eBikeNodes>(nodeIndex) != eBikeNodes::CHASSIS)
1549+ break ;
1550+
1551+ // Set the correct "bike_chassis" frame for bikes
1552+ defaultBikeChassisFrame = bikeInterface->m_apModelNodes [1 ];
1553+ if (defaultBikeChassisFrame && std::strcmp (defaultBikeChassisFrame->szName , " chassis_dummy" ) == 0 )
1554+ {
1555+ RwFrame* correctChassisFrame = RwFrameFindFrame (RpGetFrame (bikeInterface->m_pRwObject ), " chassis" );
1556+ if (correctChassisFrame)
1557+ bikeInterface->m_apModelNodes [1 ] = correctChassisFrame;
1558+ }
1559+ break ;
1560+ }
1561+ case VehicleClass::BOAT:
1562+ {
1563+ if (static_cast <eBoatNodes>(nodeIndex) >= eBoatNodes::NUM_NODES)
1564+ return false ;
1565+
1566+ nodesOffset = OFFSET_CBoat_Nodes;
1567+ break ;
1568+ }
1569+ default :
1570+ return false ;
15191571 }
15201572
1521- CObject* pObject = NULL ;
1522- if (dwReturn)
1573+ // Patch nodes array in CAutomobile::SpawnFlyingComponent
1574+ MemPut (0x6A85B3 , nodesOffset);
1575+ MemPut (0x6A8631 , nodesOffset);
1576+
1577+ auto * componentObject = ((CObjectSAInterface * (__thiscall*)(CVehicleSAInterface*, int , int )) FUNC_CAutomobile__SpawnFlyingComponent)(GetVehicleInterface (), static_cast <int >(nodeIndex), static_cast <int >(collisionType));
1578+
1579+ // Restore default nodes array in CAutomobile::SpawnFlyingComponent
1580+ // CAutomobile::m_aCarNodes offset
1581+ MemPut (0x6A85B3 , 0x648 );
1582+ MemPut (0x6A8631 , 0x648 );
1583+
1584+ // Restore default chassis frame for bikes
1585+ if (static_cast <eBikeNodes>(nodeIndex) == eBikeNodes::CHASSIS && defaultBikeChassisFrame)
15231586 {
1524- SClientEntity<CObjectSA>* pObjectClientEntity = pGame->GetPools ()->GetObject ((DWORD*)dwReturn);
1525- pObject = pObjectClientEntity ? pObjectClientEntity->pEntity : nullptr ;
1587+ auto * bikeInterface = static_cast <CBikeSAInterface*>(GetVehicleInterface ());
1588+ if (bikeInterface && bikeInterface->m_apModelNodes )
1589+ bikeInterface->m_apModelNodes [1 ] = defaultBikeChassisFrame;
15261590 }
1527- return pObject;
1591+
1592+ if (removalTime <= -1 || !componentObject)
1593+ return true ;
1594+
1595+ std::uint32_t CTimer_ms = *reinterpret_cast <std::uint32_t *>(VAR_CTimer_snTimeInMilliseconds);
1596+ componentObject->uiObjectRemovalTime = CTimer_ms + static_cast <std::uint32_t >(removalTime);
1597+
1598+ return true ;
15281599}
15291600
15301601void CVehicleSA::SetWheelVisibility (eWheelPosition wheel, bool bVisible)
@@ -1534,16 +1605,16 @@ void CVehicleSA::SetWheelVisibility(eWheelPosition wheel, bool bVisible)
15341605 switch (wheel)
15351606 {
15361607 case FRONT_LEFT_WHEEL:
1537- pFrame = vehicle->m_aCarNodes [eCarNode:: WHEEL_LF];
1608+ pFrame = vehicle->m_aCarNodes [static_cast <std:: size_t >(eCarNodes:: WHEEL_LF) ];
15381609 break ;
15391610 case REAR_LEFT_WHEEL:
1540- pFrame = vehicle->m_aCarNodes [eCarNode:: WHEEL_LB];
1611+ pFrame = vehicle->m_aCarNodes [static_cast <std:: size_t >(eCarNodes:: WHEEL_LB) ];
15411612 break ;
15421613 case FRONT_RIGHT_WHEEL:
1543- pFrame = vehicle->m_aCarNodes [eCarNode:: WHEEL_RF];
1614+ pFrame = vehicle->m_aCarNodes [static_cast <std:: size_t >(eCarNodes:: WHEEL_RF) ];
15441615 break ;
15451616 case REAR_RIGHT_WHEEL:
1546- pFrame = vehicle->m_aCarNodes [eCarNode:: WHEEL_RB];
1617+ pFrame = vehicle->m_aCarNodes [static_cast <std:: size_t >(eCarNodes:: WHEEL_RB) ];
15471618 break ;
15481619 default :
15491620 break ;
0 commit comments