From 0be609143830d27f79faf1c160d5ee015ad408fe Mon Sep 17 00:00:00 2001 From: FileEX Date: Sat, 20 Jul 2024 04:48:10 +0200 Subject: [PATCH 01/10] New function --- Client/game_sa/CBikeSA.h | 21 ++++- Client/game_sa/CVehicleSA.cpp | 85 ++++++++++++++++--- Client/game_sa/CVehicleSA.h | 4 +- .../mods/deathmatch/logic/CClientVehicle.cpp | 8 ++ Client/mods/deathmatch/logic/CClientVehicle.h | 2 + .../logic/luadefs/CLuaVehicleDefs.cpp | 64 ++++++++++++++ .../logic/luadefs/CLuaVehicleDefs.h | 2 + Client/multiplayer_sa/CMultiplayerSA.cpp | 49 +++++++++++ Client/sdk/game/CDamageManager.h | 43 ++++++++++ Client/sdk/game/CVehicle.h | 2 +- 10 files changed, 264 insertions(+), 16 deletions(-) diff --git a/Client/game_sa/CBikeSA.h b/Client/game_sa/CBikeSA.h index 65602ae5250..5f4b2776f4e 100644 --- a/Client/game_sa/CBikeSA.h +++ b/Client/game_sa/CBikeSA.h @@ -14,6 +14,25 @@ #include #include "CVehicleSA.h" +namespace eBikeNode +{ + enum + { + NONE = 0, + CHASIS, + FORKS_FRONT, + FORKS_REAR, + WHEEL_FRONT, + WHEEL_REAR, + MUDGUARD, + HANDLEBARS, + MISC_A, + MISC_B, + + NUM_NODES + }; +} + struct sRideAnimData { int32 iAnimGroup; @@ -29,7 +48,7 @@ static_assert(sizeof(sRideAnimData) == 0x1C, "Invalid size for sRideAnimData"); class CBikeSAInterface : public CVehicleSAInterface { public: - int32 m_apModelNodes[10]; + RwFrame* m_apModelNodes[eBikeNode::NUM_NODES]; int8 m_bLeanMatrixCalculated; int8 pad0[3]; // Maybe prev value is int32 int8 m_mLeanMatrix[72]; diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index c2c612d5c7a..3f64825dc64 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -1507,27 +1507,86 @@ void CVehicleSA::SetGravity(const CVector* pvecGravity) m_vecGravity = *pvecGravity; } -CObject* CVehicleSA::SpawnFlyingComponent(int i_1, unsigned int ui_2) +bool CVehicleSA::Custom_SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType, RwFrame* frame) { - DWORD dwReturn; - DWORD dwThis = (DWORD)GetInterface(); + if (!frame) + return false; + + DWORD dwInterface = (DWORD)GetInterface(); DWORD dwFunc = FUNC_CAutomobile__SpawnFlyingComponent; + _asm { - mov ecx, dwThis - push ui_2 - push i_1 - call dwFunc - mov dwReturn, eax + mov ecx, dwInterface + push frame + push collisionType + push nodeID + call dwFunc } - CObject* pObject = NULL; - if (dwReturn) + return true; +} + +bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType) +{ + VehicleClass vehicleType = static_cast(GetVehicleInterface()->m_vehicleClass); + std::uint8_t nodeIndex = static_cast(nodeID); + + if (nodeIndex < 1) + return false; + + // CBike, CBmx, CBoat and CTrain don't inherit CAutomobile so let's do it manually! + // By default, the CAutomobile::SpawnFlyingComponent function is available only for classes inheriting from CAutomobile, + // but we want the function to also be available for other vehicle classes + switch (vehicleType) { - SClientEntity* pObjectClientEntity = pGame->GetPools()->GetObject((DWORD*)dwReturn); - pObject = pObjectClientEntity ? pObjectClientEntity->pEntity : nullptr; + case VehicleClass::AUTOMOBILE: + case VehicleClass::MONSTER_TRUCK: + case VehicleClass::PLANE: + case VehicleClass::HELI: + case VehicleClass::TRAILER: + case VehicleClass::QUAD: + { + CAutomobileSAInterface* automobileInterface = static_cast(GetVehicleInterface()); + if (!automobileInterface) + return false; + + if (!Custom_SpawnFlyingComponent(nodeID, collisionType, automobileInterface->m_aCarNodes[nodeIndex])) + return false; + + break; + } + case VehicleClass::TRAIN: + { + CTrainSAInterface* trainInterface = static_cast(GetVehicleInterface()); + if (!trainInterface) + return false; + + if (nodeIndex >= sizeof(trainInterface->m_aTrainNodes) / sizeof(RwFrame*)) + return false; + + if (!Custom_SpawnFlyingComponent(nodeID, collisionType, trainInterface->m_aTrainNodes[nodeIndex])) + return false; + + break; + } + case VehicleClass::BIKE: + { + CBikeSAInterface* bikeInterface = static_cast(GetVehicleInterface()); + if (!bikeInterface) + return false; + + if (nodeIndex >= sizeof(bikeInterface->m_apModelNodes) / sizeof(RwFrame*)) + return false; + + if (Custom_SpawnFlyingComponent(nodeID, collisionType, bikeInterface->m_apModelNodes[nodeIndex])) + return false; + + break; + } } - return pObject; + + return true; } void CVehicleSA::SetWheelVisibility(eWheelPosition wheel, bool bVisible) diff --git a/Client/game_sa/CVehicleSA.h b/Client/game_sa/CVehicleSA.h index f9847d4c33f..e57f59ea5b4 100644 --- a/Client/game_sa/CVehicleSA.h +++ b/Client/game_sa/CVehicleSA.h @@ -604,7 +604,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(eCarNodes nodeID, eCarComponentCollisionTypes collisionType); void SetWheelVisibility(eWheelPosition wheel, bool bVisible); CVector GetWheelPosition(eWheelPosition wheel); @@ -687,4 +687,6 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA void CopyGlobalSuspensionLinesToPrivate(); SVehicleFrame* GetVehicleComponent(const SString& vehicleComponent); void FinalizeFramesList(); + + bool Custom_SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType, RwFrame* nodesArray); }; diff --git a/Client/mods/deathmatch/logic/CClientVehicle.cpp b/Client/mods/deathmatch/logic/CClientVehicle.cpp index 42b2215adcf..826b180790d 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.cpp +++ b/Client/mods/deathmatch/logic/CClientVehicle.cpp @@ -5031,3 +5031,11 @@ void CClientVehicle::ResetWheelScale() m_bWheelScaleChanged = false; } + +bool CClientVehicle::SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType) +{ + if (!m_pVehicle) + return false; + + return m_pVehicle->SpawnFlyingComponent(nodeID, collisionType); +} diff --git a/Client/mods/deathmatch/logic/CClientVehicle.h b/Client/mods/deathmatch/logic/CClientVehicle.h index ff87ef00dc2..cddebe0004b 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.h +++ b/Client/mods/deathmatch/logic/CClientVehicle.h @@ -543,6 +543,8 @@ class CClientVehicle : public CClientStreamElement bool SetDummyPosition(eVehicleDummies dummy, const CVector& position); bool ResetDummyPositions(); + bool SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType); + protected: void ConvertComponentRotationBase(const SString& vehicleComponent, CVector& vecInOutRotation, EComponentBaseType inputBase, EComponentBaseType outputBase); void ConvertComponentPositionBase(const SString& vehicleComponent, CVector& vecInOutPosition, EComponentBaseType inputBase, EComponentBaseType outputBase); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index b26b2163e42..c52e4e9ad25 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -154,6 +154,8 @@ void CLuaVehicleDefs::LoadFunctions() {"setVehicleVariant", ArgumentParser}, {"setVehicleWheelScale", ArgumentParser}, {"setVehicleModelWheelSize", ArgumentParser}, + + {"spawnVehicleFlyingComponent", ArgumentParser}, }; // Add functions @@ -299,6 +301,8 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "addUpgrade", "addVehicleUpgrade"); lua_classfunction(luaVM, "removeUpgrade", "removeVehicleUpgrade"); + lua_classfunction(luaVM, "spawnFlyingComponent", "spawnVehicleFlyingComponent"); + lua_classvariable(luaVM, "locked", "setVehicleLocked", "isVehicleLocked"); lua_classvariable(luaVM, "controller", NULL, "getVehicleController"); lua_classvariable(luaVM, "occupants", NULL, "getVehicleOccupants"); @@ -4174,3 +4178,63 @@ bool CLuaVehicleDefs::BlowVehicle(CClientEntity* entity, std::optional wit { return CStaticFunctionDefinitions::BlowVehicle(*entity, withExplosion); } + +bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeID, std::optional componentCollisionType) +{ + if (nodeID < 1 || nodeID >= static_cast(eCarNodes::CAR_NUM_NODES)) + throw std::invalid_argument("Invalid component index"); + + if (componentCollisionType.has_value() && componentCollisionType.value() >= static_cast(eCarComponentCollisionTypes::COL_NUM)) + throw std::invalid_argument("Invalid collision type index"); + + eCarNodes nodeIndex = static_cast(nodeID); + eCarComponentCollisionTypes collisionType = eCarComponentCollisionTypes::COL_PANEL; + + if (!componentCollisionType.has_value()) + { + switch (nodeIndex) + { + case eCarNodes::CAR_WHEEL_RF: + case eCarNodes::CAR_WHEEL_RB: + case eCarNodes::CAR_WHEEL_LF: + case eCarNodes::CAR_WHEEL_LB: + { + collisionType = eCarComponentCollisionTypes::COL_WHEEL; + break; + } + case eCarNodes::CAR_DOOR_RF: + case eCarNodes::CAR_DOOR_RR: + case eCarNodes::CAR_DOOR_LF: + case eCarNodes::CAR_DOOR_LR: + { + collisionType = eCarComponentCollisionTypes::COL_DOOR; + break; + } + case eCarNodes::CAR_BUMP_FRONT: + case eCarNodes::CAR_BUMP_REAR: + case eCarNodes::CAR_WHEEL_LM: + case eCarNodes::CAR_WHEEL_RM: + { + collisionType = eCarComponentCollisionTypes::COL_BUMPER; + break; + } + case eCarNodes::CAR_BOOT: + { + collisionType = eCarComponentCollisionTypes::COL_BOOT; + break; + } + case eCarNodes::CAR_BONNET: + { + collisionType = eCarComponentCollisionTypes::COL_BONNET; + break; + } + default: + { + collisionType = eCarComponentCollisionTypes::COL_PANEL; + break; + } + } + } + + return vehicle->SpawnFlyingComponent(nodeIndex, collisionType); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h index cf73032a7f8..909abd64b89 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h @@ -176,4 +176,6 @@ class CLuaVehicleDefs : public CLuaDefs LUA_DECLARE(SetVehicleComponentVisible); LUA_DECLARE(GetVehicleComponentVisible); LUA_DECLARE(GetVehicleComponents); + + static bool SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeID, std::optional componentCollisionType); }; diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index 04efccecb13..0e59740cc7f 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -307,6 +307,9 @@ const DWORD RETURN_Idle_CWorld_ProcessPedsAfterPreRender = 0x53EA08; #define HOOKPOS_CCollision__CheckCameraCollisionObjects 0x41AB8E +#define HOOKPOS_CAutomobile_SpawnFlyingComponent 0x6A85B0 +#define HOOKPOS_CAutomobile_SpawnFlyingComponent2 0x6A862E + CPed* pContextSwitchedPed = 0; CVector vecCenterOfWorld; FLOAT fFalseHeading; @@ -582,6 +585,9 @@ void HOOK_CWeapon__TakePhotograph(); void HOOK_CCollision__CheckCameraCollisionObjects(); +void HOOK_CAutomobile_SpawnFlyingComponent_1(); +void HOOK_CAutomobile_SpawnFlyingComponent_2(); + CMultiplayerSA::CMultiplayerSA() { // Unprotect all of the GTASA code at once and leave it that way @@ -791,6 +797,9 @@ void CMultiplayerSA::InitHooks() HookInstall(HOOKPOS_CCollision__CheckCameraCollisionObjects, (DWORD)HOOK_CCollision__CheckCameraCollisionObjects, 6 + 4); + HookInstall(HOOKPOS_CAutomobile_SpawnFlyingComponent, (DWORD)HOOK_CAutomobile_SpawnFlyingComponent_1, 7); + HookInstall(HOOKPOS_CAutomobile_SpawnFlyingComponent2, (DWORD)HOOK_CAutomobile_SpawnFlyingComponent_2, 7); + // Disable GTA setting g_bGotFocus to false when we minimize MemSet((void*)ADDR_GotFocus, 0x90, 10); @@ -7479,3 +7488,43 @@ void _declspec(naked) HOOK_CCollision__CheckCameraCollisionObjects() out2: jmp RETURN_CCollision__CheckCameraCollisionObjects_2 } } + +// These hooks modify the function to take an additional direct argument RwFrame* +// so that the function can be used for vehicles that do not inherit CAutomobile +static constexpr DWORD CONTINUE_CAutomobile_SpawnFlyingComponent_1 = 0x6A85B7; +void _declspec(naked) HOOK_CAutomobile_SpawnFlyingComponent_1() +{ + _asm + { + mov eax, [esp+90h+0xC] + test eax, eax + jz continueDefault + + jmp CONTINUE_CAutomobile_SpawnFlyingComponent_1 + + continueDefault: + mov eax, [ebx+edi*4+648h] + jmp CONTINUE_CAutomobile_SpawnFlyingComponent_1 + } +} + +static constexpr DWORD CONTINUE_CAutomobile_SpawnFlyingComponent_2 = 0x6A8635; +void _declspec(naked) HOOK_CAutomobile_SpawnFlyingComponent_2() +{ + _asm + { + push eax + mov eax, [esp+94h+0xC] + test eax, eax + jz continueDefault + + mov ecx, eax + pop eax + jmp CONTINUE_CAutomobile_SpawnFlyingComponent_2 + + continueDefault: + pop eax + mov ecx, [ebx+edi*4+648h] + jmp CONTINUE_CAutomobile_SpawnFlyingComponent_2 + } +} diff --git a/Client/sdk/game/CDamageManager.h b/Client/sdk/game/CDamageManager.h index 81fda712678..1ed3819af90 100644 --- a/Client/sdk/game/CDamageManager.h +++ b/Client/sdk/game/CDamageManager.h @@ -121,6 +121,49 @@ enum eLights MAX_LIGHTS // MUST BE 16 OR LESS }; +enum class eCarNodes +{ + CAR_NODE_NONE, + CAR_CHASIS, + CAR_WHEEL_RF, + CAR_WHEEL_RM, + CAR_WHEEL_RB, + CAR_WHEEL_LF, + CAR_WHEEL_LM, + CAR_WHEEL_LB, + CAR_DOOR_RF, + CAR_DOOR_RR, + CAR_DOOR_LF, + CAR_DOOR_LR, + CAR_BUMP_FRONT, + CAR_BUMP_REAR, + CAR_WING_RF, + CAR_WING_LF, + CAR_BONNET, + CAR_BOOT, + CAR_WINDSCREEN, + CAR_EXHAUST, + CAR_MISC_A, + CAR_MISC_B, + CAR_MISC_C, + CAR_MISC_D, + CAR_MISC_E, + + CAR_NUM_NODES +}; + +enum class eCarComponentCollisionTypes +{ + COL_BUMPER, + COL_WHEEL, + COL_DOOR, + COL_BONNET, + COL_BOOT, + COL_PANEL, + + COL_NUM +}; + class CDamageManager { public: diff --git a/Client/sdk/game/CVehicle.h b/Client/sdk/game/CVehicle.h index 356fe404705..15a99574f06 100644 --- a/Client/sdk/game/CVehicle.h +++ b/Client/sdk/game/CVehicle.h @@ -264,7 +264,7 @@ class CVehicle : public virtual CPhysical virtual SColor GetHeadLightColor() = 0; virtual void SetHeadLightColor(const SColor color) = 0; - virtual CObject* SpawnFlyingComponent(int i_1, unsigned int ui_2) = 0; + virtual bool SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType) = 0; virtual void SetWheelVisibility(eWheelPosition wheel, bool bVisible) = 0; virtual CVector GetWheelPosition(eWheelPosition wheel) = 0; From e61a498dbaaba3d8ba81205010e025619faf9756 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sat, 20 Jul 2024 23:24:25 +0200 Subject: [PATCH 02/10] Basic continuation --- Client/game_sa/CBikeSA.h | 4 +- Client/game_sa/CBmxSA.h | 19 +++ Client/game_sa/CBoatSA.h | 23 +++- Client/game_sa/CVehicleSA.cpp | 115 ++++++++++++------ Client/game_sa/CVehicleSA.h | 16 ++- .../mods/deathmatch/logic/CClientVehicle.cpp | 4 +- Client/mods/deathmatch/logic/CClientVehicle.h | 2 +- .../logic/luadefs/CLuaVehicleDefs.cpp | 14 ++- .../logic/luadefs/CLuaVehicleDefs.h | 2 +- Client/multiplayer_sa/CMultiplayerSA.cpp | 49 -------- Client/sdk/game/CDamageManager.h | 2 +- Client/sdk/game/CVehicle.h | 2 +- 12 files changed, 147 insertions(+), 105 deletions(-) diff --git a/Client/game_sa/CBikeSA.h b/Client/game_sa/CBikeSA.h index 5f4b2776f4e..5a890dfb98d 100644 --- a/Client/game_sa/CBikeSA.h +++ b/Client/game_sa/CBikeSA.h @@ -14,7 +14,7 @@ #include #include "CVehicleSA.h" -namespace eBikeNode +namespace eBikeNodes { enum { @@ -48,7 +48,7 @@ static_assert(sizeof(sRideAnimData) == 0x1C, "Invalid size for sRideAnimData"); class CBikeSAInterface : public CVehicleSAInterface { public: - RwFrame* m_apModelNodes[eBikeNode::NUM_NODES]; + RwFrame* m_apModelNodes[eBikeNodes::NUM_NODES]; int8 m_bLeanMatrixCalculated; int8 pad0[3]; // Maybe prev value is int32 int8 m_mLeanMatrix[72]; diff --git a/Client/game_sa/CBmxSA.h b/Client/game_sa/CBmxSA.h index 250a8bd5e6e..8134448c13f 100644 --- a/Client/game_sa/CBmxSA.h +++ b/Client/game_sa/CBmxSA.h @@ -14,6 +14,25 @@ #include #include "CBikeSA.h" +namespace eBmxNodes +{ + enum + { + NONE = 0, + CHASIS, + FORKS_FRONT, + FORKS_REAR, + WHEEL_FRONT, + WHEEL_REAR, + HANDLEBARS, + CHAINSET, + PEDAL_R, + PEDAL_L, + + NUM_NODES + }; +} + class CBmxSAInterface : public CBikeSAInterface { // fill this diff --git a/Client/game_sa/CBoatSA.h b/Client/game_sa/CBoatSA.h index 34f90003c73..8c36c9d25bb 100644 --- a/Client/game_sa/CBoatSA.h +++ b/Client/game_sa/CBoatSA.h @@ -14,12 +14,33 @@ #include #include "CVehicleSA.h" +namespace eBoatNodes +{ + enum + { + 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[eBoatNodes::NUM_NODES]; // 1456 uint32 pad2[3]; // 1500 uint16 pad3; // 1512 uint8 pad4[2]; // 1514 diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index 3f64825dc64..d0460e0bfbf 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -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" @@ -1507,38 +1508,17 @@ void CVehicleSA::SetGravity(const CVector* pvecGravity) m_vecGravity = *pvecGravity; } -bool CVehicleSA::Custom_SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType, RwFrame* frame) +bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType, std::int32_t removalTime) { - if (!frame) - return false; - - DWORD dwInterface = (DWORD)GetInterface(); - DWORD dwFunc = FUNC_CAutomobile__SpawnFlyingComponent; - - _asm - { - mov ecx, dwInterface - push frame - push collisionType - push nodeID - call dwFunc - } - - return true; -} - -bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType) -{ - VehicleClass vehicleType = static_cast(GetVehicleInterface()->m_vehicleClass); - std::uint8_t nodeIndex = static_cast(nodeID); - + const std::uint8_t nodeIndex = static_cast(nodeID); if (nodeIndex < 1) return false; + DWORD nodesOffset = OFFSET_CAutomobile_Nodes; + RwFrame* defaultBikeChassisFrame; + // CBike, CBmx, CBoat and CTrain don't inherit CAutomobile so let's do it manually! - // By default, the CAutomobile::SpawnFlyingComponent function is available only for classes inheriting from CAutomobile, - // but we want the function to also be available for other vehicle classes - switch (vehicleType) + switch (static_cast(GetVehicleInterface()->m_vehicleClass)) { case VehicleClass::AUTOMOBILE: case VehicleClass::MONSTER_TRUCK: @@ -1547,43 +1527,98 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTy case VehicleClass::TRAILER: case VehicleClass::QUAD: { - CAutomobileSAInterface* automobileInterface = static_cast(GetVehicleInterface()); - if (!automobileInterface) - return false; - - if (!Custom_SpawnFlyingComponent(nodeID, collisionType, automobileInterface->m_aCarNodes[nodeIndex])) - return false; - + nodesOffset = OFFSET_CAutomobile_Nodes; break; } case VehicleClass::TRAIN: { - CTrainSAInterface* trainInterface = static_cast(GetVehicleInterface()); + auto* trainInterface = static_cast(GetVehicleInterface()); if (!trainInterface) return false; if (nodeIndex >= sizeof(trainInterface->m_aTrainNodes) / sizeof(RwFrame*)) return false; - if (!Custom_SpawnFlyingComponent(nodeID, collisionType, trainInterface->m_aTrainNodes[nodeIndex])) - return false; - + nodesOffset = OFFSET_CTrain_Nodes; break; } case VehicleClass::BIKE: + case VehicleClass::BMX: { - CBikeSAInterface* bikeInterface = static_cast(GetVehicleInterface()); + auto* bikeInterface = static_cast(GetVehicleInterface()); if (!bikeInterface) return false; if (nodeIndex >= sizeof(bikeInterface->m_apModelNodes) / sizeof(RwFrame*)) return false; - if (Custom_SpawnFlyingComponent(nodeID, collisionType, bikeInterface->m_apModelNodes[nodeIndex])) + // Set the correct "bike_chassis" frame for bikes + if (nodeIndex == 1) + { + defaultBikeChassisFrame = bikeInterface->m_apModelNodes[1]; + if (defaultBikeChassisFrame && std::strcmp(defaultBikeChassisFrame->szName, "chassis_dummy") == 0) + { + RwFrame* correctChassisFrame = ((RwFrame*(__cdecl*)(RpClump*, const char*))FUNC_CClumpModelInfo_GetFrameFromName)(bikeInterface->m_pRwObject, "chassis"); + if (correctChassisFrame) + bikeInterface->m_apModelNodes[1] = correctChassisFrame; + } + } + + nodesOffset = OFFSET_CBike_Nodes; + break; + } + case VehicleClass::BOAT: + { + auto* boatInterface = static_cast(GetVehicleInterface()); + if (!boatInterface) + return false; + + if (nodeIndex >= sizeof(boatInterface->pBoatParts) / sizeof(RwFrame*)) return false; + nodesOffset = OFFSET_CBoat_Nodes; break; } + default: + return false; + } + + // Patch nodes array + MemPut(0x6A85B3, nodesOffset); + MemPut(0x6A8631, nodesOffset); + + DWORD dwInterface = (DWORD)GetInterface(); + DWORD dwFunc = FUNC_CAutomobile__SpawnFlyingComponent; + DWORD dwReturn; + _asm + { + mov ecx, dwInterface + push collisionType + push nodeID + call dwFunc + mov dwReturn, eax + } + + // Restore default nodes array + MemPut(0x6A85B3, 0x648); + MemPut(0x6A8631, 0x648); + + // Restore default chassis frame for bikes + if (nodeIndex == 1 && defaultBikeChassisFrame) + { + auto* bikeInterface = static_cast(GetVehicleInterface()); + if (bikeInterface && bikeInterface->m_apModelNodes) + bikeInterface->m_apModelNodes[1] = defaultBikeChassisFrame; + } + + if (removalTime > -1) + { + auto* componentObject = reinterpret_cast((DWORD*)dwReturn); + if (!componentObject) + return; + + int CTimer_ms = *(int*)0xB7CB84; // CTimer::m_snTimeInMilliseconds + componentObject->uiObjectRemovalTime = CTimer_ms + static_cast(removalTime); } return true; diff --git a/Client/game_sa/CVehicleSA.h b/Client/game_sa/CVehicleSA.h index e57f59ea5b4..ccc06a1ba54 100644 --- a/Client/game_sa/CVehicleSA.h +++ b/Client/game_sa/CVehicleSA.h @@ -94,6 +94,18 @@ 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 0x5A0 +#define OFFSET_CBike_Nodes 0x5A0 +#define OFFSET_CBoat_Nodes 0x5B0 + struct SRailNodeSA { short sX; // x coordinate times 8 @@ -604,7 +616,7 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA SharedUtil::SColor GetHeadLightColor() { return m_HeadLightColor; } void SetHeadLightColor(const SharedUtil::SColor color) { m_HeadLightColor = color; } - bool SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType); + bool SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType, std::int32_t removalTime = -1); void SetWheelVisibility(eWheelPosition wheel, bool bVisible); CVector GetWheelPosition(eWheelPosition wheel); @@ -687,6 +699,4 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA void CopyGlobalSuspensionLinesToPrivate(); SVehicleFrame* GetVehicleComponent(const SString& vehicleComponent); void FinalizeFramesList(); - - bool Custom_SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType, RwFrame* nodesArray); }; diff --git a/Client/mods/deathmatch/logic/CClientVehicle.cpp b/Client/mods/deathmatch/logic/CClientVehicle.cpp index 826b180790d..735ce28decf 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.cpp +++ b/Client/mods/deathmatch/logic/CClientVehicle.cpp @@ -5032,10 +5032,10 @@ void CClientVehicle::ResetWheelScale() m_bWheelScaleChanged = false; } -bool CClientVehicle::SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType) +bool CClientVehicle::SpawnFlyingComponent(const eCarNodes& nodeID, const eCarComponentCollisionTypes& collisionType, std::int32_t removalTime) { if (!m_pVehicle) return false; - return m_pVehicle->SpawnFlyingComponent(nodeID, collisionType); + return m_pVehicle->SpawnFlyingComponent(nodeID, collisionType, removalTime); } diff --git a/Client/mods/deathmatch/logic/CClientVehicle.h b/Client/mods/deathmatch/logic/CClientVehicle.h index cddebe0004b..a569d3ad798 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.h +++ b/Client/mods/deathmatch/logic/CClientVehicle.h @@ -543,7 +543,7 @@ class CClientVehicle : public CClientStreamElement bool SetDummyPosition(eVehicleDummies dummy, const CVector& position); bool ResetDummyPositions(); - bool SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType); + bool SpawnFlyingComponent(const eCarNodes& nodeID, const eCarComponentCollisionTypes& collisionType, std::int32_t removalTime); protected: void ConvertComponentRotationBase(const SString& vehicleComponent, CVector& vecInOutRotation, EComponentBaseType inputBase, EComponentBaseType outputBase); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index c52e4e9ad25..6692e88dc61 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -4179,7 +4179,7 @@ bool CLuaVehicleDefs::BlowVehicle(CClientEntity* entity, std::optional wit return CStaticFunctionDefinitions::BlowVehicle(*entity, withExplosion); } -bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeID, std::optional componentCollisionType) +bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeID, std::optional componentCollisionType, std::optional removalTime) { if (nodeID < 1 || nodeID >= static_cast(eCarNodes::CAR_NUM_NODES)) throw std::invalid_argument("Invalid component index"); @@ -4187,8 +4187,8 @@ bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, if (componentCollisionType.has_value() && componentCollisionType.value() >= static_cast(eCarComponentCollisionTypes::COL_NUM)) throw std::invalid_argument("Invalid collision type index"); - eCarNodes nodeIndex = static_cast(nodeID); - eCarComponentCollisionTypes collisionType = eCarComponentCollisionTypes::COL_PANEL; + const eCarNodes& nodeIndex = static_cast(nodeID); + eCarComponentCollisionTypes collisionType; if (!componentCollisionType.has_value()) { @@ -4219,11 +4219,13 @@ bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, break; } case eCarNodes::CAR_BOOT: + case eCarNodes::CAR_CHASSIS: { collisionType = eCarComponentCollisionTypes::COL_BOOT; break; } case eCarNodes::CAR_BONNET: + case eCarNodes::CAR_WINDSCREEN: { collisionType = eCarComponentCollisionTypes::COL_BONNET; break; @@ -4235,6 +4237,10 @@ bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, } } } + else + { + collisionType = static_cast(componentCollisionType.value()); + } - return vehicle->SpawnFlyingComponent(nodeIndex, collisionType); + return vehicle->SpawnFlyingComponent(nodeIndex, collisionType, removalTime.value_or(-1)); } diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h index 909abd64b89..7c5980ba750 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h @@ -177,5 +177,5 @@ class CLuaVehicleDefs : public CLuaDefs LUA_DECLARE(GetVehicleComponentVisible); LUA_DECLARE(GetVehicleComponents); - static bool SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeID, std::optional componentCollisionType); + static bool SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeID, std::optional componentCollisionType, std::optional removalTime); }; diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index 0e59740cc7f..04efccecb13 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -307,9 +307,6 @@ const DWORD RETURN_Idle_CWorld_ProcessPedsAfterPreRender = 0x53EA08; #define HOOKPOS_CCollision__CheckCameraCollisionObjects 0x41AB8E -#define HOOKPOS_CAutomobile_SpawnFlyingComponent 0x6A85B0 -#define HOOKPOS_CAutomobile_SpawnFlyingComponent2 0x6A862E - CPed* pContextSwitchedPed = 0; CVector vecCenterOfWorld; FLOAT fFalseHeading; @@ -585,9 +582,6 @@ void HOOK_CWeapon__TakePhotograph(); void HOOK_CCollision__CheckCameraCollisionObjects(); -void HOOK_CAutomobile_SpawnFlyingComponent_1(); -void HOOK_CAutomobile_SpawnFlyingComponent_2(); - CMultiplayerSA::CMultiplayerSA() { // Unprotect all of the GTASA code at once and leave it that way @@ -797,9 +791,6 @@ void CMultiplayerSA::InitHooks() HookInstall(HOOKPOS_CCollision__CheckCameraCollisionObjects, (DWORD)HOOK_CCollision__CheckCameraCollisionObjects, 6 + 4); - HookInstall(HOOKPOS_CAutomobile_SpawnFlyingComponent, (DWORD)HOOK_CAutomobile_SpawnFlyingComponent_1, 7); - HookInstall(HOOKPOS_CAutomobile_SpawnFlyingComponent2, (DWORD)HOOK_CAutomobile_SpawnFlyingComponent_2, 7); - // Disable GTA setting g_bGotFocus to false when we minimize MemSet((void*)ADDR_GotFocus, 0x90, 10); @@ -7488,43 +7479,3 @@ void _declspec(naked) HOOK_CCollision__CheckCameraCollisionObjects() out2: jmp RETURN_CCollision__CheckCameraCollisionObjects_2 } } - -// These hooks modify the function to take an additional direct argument RwFrame* -// so that the function can be used for vehicles that do not inherit CAutomobile -static constexpr DWORD CONTINUE_CAutomobile_SpawnFlyingComponent_1 = 0x6A85B7; -void _declspec(naked) HOOK_CAutomobile_SpawnFlyingComponent_1() -{ - _asm - { - mov eax, [esp+90h+0xC] - test eax, eax - jz continueDefault - - jmp CONTINUE_CAutomobile_SpawnFlyingComponent_1 - - continueDefault: - mov eax, [ebx+edi*4+648h] - jmp CONTINUE_CAutomobile_SpawnFlyingComponent_1 - } -} - -static constexpr DWORD CONTINUE_CAutomobile_SpawnFlyingComponent_2 = 0x6A8635; -void _declspec(naked) HOOK_CAutomobile_SpawnFlyingComponent_2() -{ - _asm - { - push eax - mov eax, [esp+94h+0xC] - test eax, eax - jz continueDefault - - mov ecx, eax - pop eax - jmp CONTINUE_CAutomobile_SpawnFlyingComponent_2 - - continueDefault: - pop eax - mov ecx, [ebx+edi*4+648h] - jmp CONTINUE_CAutomobile_SpawnFlyingComponent_2 - } -} diff --git a/Client/sdk/game/CDamageManager.h b/Client/sdk/game/CDamageManager.h index 1ed3819af90..53cc445228a 100644 --- a/Client/sdk/game/CDamageManager.h +++ b/Client/sdk/game/CDamageManager.h @@ -124,7 +124,7 @@ enum eLights enum class eCarNodes { CAR_NODE_NONE, - CAR_CHASIS, + CAR_CHASSIS, CAR_WHEEL_RF, CAR_WHEEL_RM, CAR_WHEEL_RB, diff --git a/Client/sdk/game/CVehicle.h b/Client/sdk/game/CVehicle.h index 15a99574f06..dd246f2ff21 100644 --- a/Client/sdk/game/CVehicle.h +++ b/Client/sdk/game/CVehicle.h @@ -264,7 +264,7 @@ class CVehicle : public virtual CPhysical virtual SColor GetHeadLightColor() = 0; virtual void SetHeadLightColor(const SColor color) = 0; - virtual bool SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType) = 0; + virtual bool SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType, std::int32_t removalTime = -1) = 0; virtual void SetWheelVisibility(eWheelPosition wheel, bool bVisible) = 0; virtual CVector GetWheelPosition(eWheelPosition wheel) = 0; From d64d5bd21502718cf53ad8832548bb919ff01e13 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 21 Jul 2024 02:03:52 +0200 Subject: [PATCH 03/10] Enum clean up --- Client/game_sa/CAutomobileSA.h | 36 +--------- Client/game_sa/CVehicleSA.cpp | 13 ++-- Client/game_sa/CVehicleSA.h | 2 +- .../logic/luadefs/CLuaVehicleDefs.cpp | 53 +++++++------- .../logic/luadefs/CLuaVehicleDefs.h | 2 +- Client/sdk/game/CDamageManager.h | 70 +++++++++---------- Client/sdk/game/CVehicle.h | 2 +- 7 files changed, 72 insertions(+), 106 deletions(-) diff --git a/Client/game_sa/CAutomobileSA.h b/Client/game_sa/CAutomobileSA.h index 701030a5a9d..936861c29ee 100644 --- a/Client/game_sa/CAutomobileSA.h +++ b/Client/game_sa/CAutomobileSA.h @@ -20,39 +20,7 @@ #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 - }; -}; +#define MAX_NODES 25 class CBouncingPanelSAInterface { @@ -70,7 +38,7 @@ class CAutomobileSAInterface : public CVehicleSAInterface public: CDamageManagerSAInterface m_damageManager; CDoorSAInterface m_doors[MAX_DOORS]; - RwFrame* m_aCarNodes[eCarNode::NUM_NODES]; + RwFrame* m_aCarNodes[MAX_NODES]; CBouncingPanelSAInterface m_panels[3]; CDoorSAInterface m_swingingChassis; CColPointSAInterface m_wheelColPoint[MAX_WHEELS]; diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index d0460e0bfbf..0f40cb4f0c3 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -1508,9 +1508,8 @@ void CVehicleSA::SetGravity(const CVector* pvecGravity) m_vecGravity = *pvecGravity; } -bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType, std::int32_t removalTime) +bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisionTypes collisionType, std::int32_t removalTime) { - const std::uint8_t nodeIndex = static_cast(nodeID); if (nodeIndex < 1) return false; @@ -1594,7 +1593,7 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTy { mov ecx, dwInterface push collisionType - push nodeID + push nodeIndex call dwFunc mov dwReturn, eax } @@ -1631,16 +1630,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[CAR_NODE_WHEEL_LF]; break; case REAR_LEFT_WHEEL: - pFrame = vehicle->m_aCarNodes[eCarNode::WHEEL_LB]; + pFrame = vehicle->m_aCarNodes[CAR_NODE_WHEEL_LB]; break; case FRONT_RIGHT_WHEEL: - pFrame = vehicle->m_aCarNodes[eCarNode::WHEEL_RF]; + pFrame = vehicle->m_aCarNodes[CAR_NODE_WHEEL_RF]; break; case REAR_RIGHT_WHEEL: - pFrame = vehicle->m_aCarNodes[eCarNode::WHEEL_RB]; + pFrame = vehicle->m_aCarNodes[CAR_NODE_WHEEL_RB]; break; default: break; diff --git a/Client/game_sa/CVehicleSA.h b/Client/game_sa/CVehicleSA.h index ccc06a1ba54..a857f9dd7d1 100644 --- a/Client/game_sa/CVehicleSA.h +++ b/Client/game_sa/CVehicleSA.h @@ -616,7 +616,7 @@ class CVehicleSA : public virtual CVehicle, public virtual CPhysicalSA SharedUtil::SColor GetHeadLightColor() { return m_HeadLightColor; } void SetHeadLightColor(const SharedUtil::SColor color) { m_HeadLightColor = color; } - bool SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType, std::int32_t removalTime = -1); + bool SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisionTypes collisionType, std::int32_t removalTime = -1); void SetWheelVisibility(eWheelPosition wheel, bool bVisible); CVector GetWheelPosition(eWheelPosition wheel); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index 6692e88dc61..b3fc0f79c8e 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -4179,60 +4179,59 @@ bool CLuaVehicleDefs::BlowVehicle(CClientEntity* entity, std::optional wit return CStaticFunctionDefinitions::BlowVehicle(*entity, withExplosion); } -bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeID, std::optional componentCollisionType, std::optional removalTime) +bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeIndex, std::optional componentCollisionType, std::optional removalTime) { - if (nodeID < 1 || nodeID >= static_cast(eCarNodes::CAR_NUM_NODES)) + if (nodeIndex < 1 || nodeIndex >= CAR_NUM_NODES) throw std::invalid_argument("Invalid component index"); - if (componentCollisionType.has_value() && componentCollisionType.value() >= static_cast(eCarComponentCollisionTypes::COL_NUM)) + if (componentCollisionType.has_value() && componentCollisionType.value() >= COL_NODES_NUM) throw std::invalid_argument("Invalid collision type index"); - const eCarNodes& nodeIndex = static_cast(nodeID); eCarComponentCollisionTypes collisionType; if (!componentCollisionType.has_value()) { switch (nodeIndex) { - case eCarNodes::CAR_WHEEL_RF: - case eCarNodes::CAR_WHEEL_RB: - case eCarNodes::CAR_WHEEL_LF: - case eCarNodes::CAR_WHEEL_LB: + case CAR_NODE_WHEEL_RF: + case CAR_NODE_WHEEL_RB: + case CAR_NODE_WHEEL_LF: + case CAR_NODE_WHEEL_LB: { - collisionType = eCarComponentCollisionTypes::COL_WHEEL; + collisionType = COL_NODE_WHEEL; break; } - case eCarNodes::CAR_DOOR_RF: - case eCarNodes::CAR_DOOR_RR: - case eCarNodes::CAR_DOOR_LF: - case eCarNodes::CAR_DOOR_LR: + case CAR_NODE_DOOR_RF: + case CAR_NODE_DOOR_RR: + case CAR_NODE_DOOR_LF: + case CAR_NODE_DOOR_LR: { - collisionType = eCarComponentCollisionTypes::COL_DOOR; + collisionType = COL_NODE_DOOR; break; } - case eCarNodes::CAR_BUMP_FRONT: - case eCarNodes::CAR_BUMP_REAR: - case eCarNodes::CAR_WHEEL_LM: - case eCarNodes::CAR_WHEEL_RM: + case CAR_NODE_BUMP_FRONT: + case CAR_NODE_BUMP_REAR: + case CAR_NODE_WHEEL_LM: + case CAR_NODE_WHEEL_RM: { - collisionType = eCarComponentCollisionTypes::COL_BUMPER; + collisionType = COL_NODE_BUMPER; break; } - case eCarNodes::CAR_BOOT: - case eCarNodes::CAR_CHASSIS: + case CAR_NODE_BOOT: + case CAR_NODE_CHASSIS: { - collisionType = eCarComponentCollisionTypes::COL_BOOT; + collisionType = COL_NODE_BOOT; break; } - case eCarNodes::CAR_BONNET: - case eCarNodes::CAR_WINDSCREEN: + case CAR_NODE_BONNET: + case CAR_NODE_WINDSCREEN: { - collisionType = eCarComponentCollisionTypes::COL_BONNET; + collisionType = COL_NODE_BONNET; break; } default: { - collisionType = eCarComponentCollisionTypes::COL_PANEL; + collisionType = COL_NODE_PANEL; break; } } @@ -4242,5 +4241,5 @@ bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, collisionType = static_cast(componentCollisionType.value()); } - return vehicle->SpawnFlyingComponent(nodeIndex, collisionType, removalTime.value_or(-1)); + return vehicle->SpawnFlyingComponent(static_cast(nodeIndex), collisionType, removalTime.value_or(-1)); } diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h index 7c5980ba750..9f00c52e2ad 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h @@ -177,5 +177,5 @@ class CLuaVehicleDefs : public CLuaDefs LUA_DECLARE(GetVehicleComponentVisible); LUA_DECLARE(GetVehicleComponents); - static bool SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeID, std::optional componentCollisionType, std::optional removalTime); + static bool SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeIndex, std::optional componentCollisionType, std::optional removalTime); }; diff --git a/Client/sdk/game/CDamageManager.h b/Client/sdk/game/CDamageManager.h index 53cc445228a..d5579254a8c 100644 --- a/Client/sdk/game/CDamageManager.h +++ b/Client/sdk/game/CDamageManager.h @@ -121,47 +121,47 @@ enum eLights MAX_LIGHTS // MUST BE 16 OR LESS }; -enum class eCarNodes +enum eCarNodes { - CAR_NODE_NONE, - CAR_CHASSIS, - CAR_WHEEL_RF, - CAR_WHEEL_RM, - CAR_WHEEL_RB, - CAR_WHEEL_LF, - CAR_WHEEL_LM, - CAR_WHEEL_LB, - CAR_DOOR_RF, - CAR_DOOR_RR, - CAR_DOOR_LF, - CAR_DOOR_LR, - CAR_BUMP_FRONT, - CAR_BUMP_REAR, - CAR_WING_RF, - CAR_WING_LF, - CAR_BONNET, - CAR_BOOT, - CAR_WINDSCREEN, - CAR_EXHAUST, - CAR_MISC_A, - CAR_MISC_B, - CAR_MISC_C, - CAR_MISC_D, - CAR_MISC_E, + CAR_NODE_NONE = 0, + CAR_NODE_CHASSIS, + CAR_NODE_WHEEL_RF, + CAR_NODE_WHEEL_RM, + CAR_NODE_WHEEL_RB, + CAR_NODE_WHEEL_LF, + CAR_NODE_WHEEL_LM, + CAR_NODE_WHEEL_LB, + CAR_NODE_DOOR_RF, + CAR_NODE_DOOR_RR, + CAR_NODE_DOOR_LF, + CAR_NODE_DOOR_LR, + CAR_NODE_BUMP_FRONT, + CAR_NODE_BUMP_REAR, + CAR_NODE_WING_RF, + CAR_NODE_WING_LF, + CAR_NODE_BONNET, + CAR_NODE_BOOT, + CAR_NODE_WINDSCREEN, + CAR_NODE_EXHAUST, + CAR_NODE_MISC_A, + CAR_NODE_MISC_B, + CAR_NODE_MISC_C, + CAR_NODE_MISC_D, + CAR_NODE_MISC_E, CAR_NUM_NODES }; -enum class eCarComponentCollisionTypes +enum eCarComponentCollisionTypes { - COL_BUMPER, - COL_WHEEL, - COL_DOOR, - COL_BONNET, - COL_BOOT, - COL_PANEL, - - COL_NUM + COL_NODE_BUMPER = 0, + COL_NODE_WHEEL, + COL_NODE_DOOR, + COL_NODE_BONNET, + COL_NODE_BOOT, + COL_NODE_PANEL, + + COL_NODES_NUM }; class CDamageManager diff --git a/Client/sdk/game/CVehicle.h b/Client/sdk/game/CVehicle.h index dd246f2ff21..94ffb578089 100644 --- a/Client/sdk/game/CVehicle.h +++ b/Client/sdk/game/CVehicle.h @@ -264,7 +264,7 @@ class CVehicle : public virtual CPhysical virtual SColor GetHeadLightColor() = 0; virtual void SetHeadLightColor(const SColor color) = 0; - virtual bool SpawnFlyingComponent(eCarNodes nodeID, eCarComponentCollisionTypes collisionType, std::int32_t removalTime = -1) = 0; + virtual bool SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisionTypes collisionType, std::int32_t removalTime = -1) = 0; virtual void SetWheelVisibility(eWheelPosition wheel, bool bVisible) = 0; virtual CVector GetWheelPosition(eWheelPosition wheel) = 0; From d788a648f97f7faadb493e2cb4b36f3bc45607cc Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 21 Jul 2024 03:17:03 +0200 Subject: [PATCH 04/10] Serverside --- Client/game_sa/CVehicleSA.h | 2 +- .../logic/luadefs/CLuaVehicleDefs.cpp | 1 - .../deathmatch/logic/rpc/CVehicleRPCs.cpp | 17 ++++++ .../mods/deathmatch/logic/rpc/CVehicleRPCs.h | 1 + .../logic/CPerfStat.RPCPacketUsage.cpp | 1 + .../logic/CStaticFunctionDefinitions.cpp | 11 ++++ .../logic/CStaticFunctionDefinitions.h | 1 + Server/mods/deathmatch/logic/CVehicle.h | 43 +++++++++++++ .../logic/luadefs/CLuaVehicleDefs.cpp | 61 +++++++++++++++++++ .../logic/luadefs/CLuaVehicleDefs.h | 2 + Shared/sdk/net/rpc_enums.h | 2 + 11 files changed, 140 insertions(+), 2 deletions(-) diff --git a/Client/game_sa/CVehicleSA.h b/Client/game_sa/CVehicleSA.h index a857f9dd7d1..868f3649587 100644 --- a/Client/game_sa/CVehicleSA.h +++ b/Client/game_sa/CVehicleSA.h @@ -102,7 +102,7 @@ struct RwTexture; // CBike::m_apModelNodes // CBoat::pBoatParts #define OFFSET_CAutomobile_Nodes 0x648 -#define OFFSET_CTrain_Nodes 0x5A0 +#define OFFSET_CTrain_Nodes 0x668 #define OFFSET_CBike_Nodes 0x5A0 #define OFFSET_CBoat_Nodes 0x5B0 diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index b3fc0f79c8e..310cb7200ed 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -154,7 +154,6 @@ void CLuaVehicleDefs::LoadFunctions() {"setVehicleVariant", ArgumentParser}, {"setVehicleWheelScale", ArgumentParser}, {"setVehicleModelWheelSize", ArgumentParser}, - {"spawnVehicleFlyingComponent", ArgumentParser}, }; diff --git a/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp index be586965db3..576ca0e3e75 100644 --- a/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp @@ -52,6 +52,7 @@ void CVehicleRPCs::LoadFunctions() AddHandler(REMOVE_VEHICLE_SIRENS, RemoveVehicleSirens, "removeVehicleSirens"); AddHandler(SET_VEHICLE_SIRENS, SetVehicleSirens, "setVehicleSirens"); AddHandler(SET_VEHICLE_PLATE_TEXT, SetVehiclePlateText, "setVehiclePlateText"); + AddHandler(SPAWN_VEHICLE_FLYING_COMPONENT, SpawnVehicleFlyingComponent, "spawnVehicleFlyingComponent"); } void CVehicleRPCs::DestroyAllVehicles(NetBitStreamInterface& bitStream) @@ -653,3 +654,19 @@ void CVehicleRPCs::SetVehiclePlateText(CClientEntity* pSourceEntity, NetBitStrea } } } + +void CVehicleRPCs::SpawnVehicleFlyingComponent(CClientEntity* const sourceEntity, NetBitStreamInterface& bitStream) +{ + CClientVehicle* vehicle = m_pVehicleManager->Get(sourceEntity->GetID()); + if (!vehicle) + return; + + std::uint8_t nodeIndex; + std::uint8_t collisionType; + std::int32_t removalTime; + + if (bitStream.Read(nodeIndex) && bitStream.Read(collisionType) && bitStream.Read(removalTime)) + { + vehicle->SpawnFlyingComponent(static_cast(nodeIndex), static_cast(collisionType), removalTime); + } +} diff --git a/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.h b/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.h index e63d609fdff..6d4e9f5d197 100644 --- a/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.h +++ b/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.h @@ -57,4 +57,5 @@ class CVehicleRPCs : public CRPCFunctions DECLARE_ELEMENT_RPC(RemoveVehicleSirens); DECLARE_ELEMENT_RPC(SetVehicleSirens); DECLARE_ELEMENT_RPC(SetVehiclePlateText); + DECLARE_ELEMENT_RPC(SpawnVehicleFlyingComponent); }; diff --git a/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp b/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp index 2f9cfa8ce91..f7566d32431 100644 --- a/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp +++ b/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp @@ -226,6 +226,7 @@ ADD_ENUM1(SET_COLPOLYGON_HEIGHT) ADD_ENUM1(SET_OBJECT_BREAKABLE) ADD_ENUM1(BREAK_OBJECT) ADD_ENUM1(SET_PLAYER_SCRIPT_DEBUG_LEVEL) +ADD_ENUM1(SPAWN_VEHICLE_FLYING_COMPONENT) IMPLEMENT_ENUM_END("eElementRPCFunctions") DECLARE_ENUM(CRPCFunctions::eRPCFunctions); diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index c7ce99d91ea..6301026967b 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -12463,3 +12463,14 @@ bool CStaticFunctionDefinitions::SetColPolygonHeight(CColPolygon* pColPolygon, f return false; } + +bool CStaticFunctionDefinitions::SpawnVehicleFlyingComponent(CVehicle* const vehicle, std::uint8_t nodeIndex, std::uint8_t collisionType, std::int32_t removalTime) +{ + CBitStream bitStream; + bitStream.pBitStream->Write(nodeIndex); + bitStream.pBitStream->Write(collisionType); + bitStream.pBitStream->Write(removalTime); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(vehicle, SPAWN_VEHICLE_FLYING_COMPONENT, *bitStream.pBitStream)); + + return true; +} diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h index 2f260e3ea59..9ee241b64dc 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -241,6 +241,7 @@ class CStaticFunctionDefinitions // Vehicle create/destroy functions static CVehicle* CreateVehicle(CResource* pResource, unsigned short usModel, const CVector& vecPosition, const CVector& vecRotation, const char* szRegPlate, unsigned char ucVariant, unsigned char ucVariant2, bool bSynced); + static bool SpawnVehicleFlyingComponent(CVehicle* const vehicle, std::uint8_t nodeIndex, std::uint8_t collisionType, std::int32_t removalTime = -1); // Vehicle get functions static bool GetVehicleVariant(CVehicle* pVehicle, unsigned char& ucVariant, unsigned char& ucVariant2); diff --git a/Server/mods/deathmatch/logic/CVehicle.h b/Server/mods/deathmatch/logic/CVehicle.h index 10de01e6259..d269d7ed6df 100644 --- a/Server/mods/deathmatch/logic/CVehicle.h +++ b/Server/mods/deathmatch/logic/CVehicle.h @@ -111,6 +111,49 @@ enum eVehicleType VEHICLE_TRAILER }; +enum eCarNodes +{ + CAR_NODE_NONE = 0, + CAR_NODE_CHASSIS, + CAR_NODE_WHEEL_RF, + CAR_NODE_WHEEL_RM, + CAR_NODE_WHEEL_RB, + CAR_NODE_WHEEL_LF, + CAR_NODE_WHEEL_LM, + CAR_NODE_WHEEL_LB, + CAR_NODE_DOOR_RF, + CAR_NODE_DOOR_RR, + CAR_NODE_DOOR_LF, + CAR_NODE_DOOR_LR, + CAR_NODE_BUMP_FRONT, + CAR_NODE_BUMP_REAR, + CAR_NODE_WING_RF, + CAR_NODE_WING_LF, + CAR_NODE_BONNET, + CAR_NODE_BOOT, + CAR_NODE_WINDSCREEN, + CAR_NODE_EXHAUST, + CAR_NODE_MISC_A, + CAR_NODE_MISC_B, + CAR_NODE_MISC_C, + CAR_NODE_MISC_D, + CAR_NODE_MISC_E, + + CAR_NUM_NODES +}; + +enum eCarComponentCollisionTypes +{ + COL_NODE_BUMPER = 0, + COL_NODE_WHEEL, + COL_NODE_DOOR, + COL_NODE_BONNET, + COL_NODE_BOOT, + COL_NODE_PANEL, + + COL_NODES_NUM +}; + #define SIREN_TYPE_FIRST 1 #define SIREN_TYPE_LAST 6 #define SIREN_ID_MAX 7 diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index 294ea7310cb..34fd4b92821 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -22,6 +22,7 @@ void CLuaVehicleDefs::LoadFunctions() constexpr static const std::pair functions[]{ // Vehicle create/destroy funcs {"createVehicle", CreateVehicle}, + {"spawnVehicleFlyingComponent", ArgumentParser}, // Vehicle get funcs {"getVehicleType", GetVehicleType}, @@ -241,6 +242,7 @@ void CLuaVehicleDefs::AddClass(lua_State* luaVM) // lua_classfunction(luaVM, "setTrack", "setTrainTrack"); lua_classfunction(luaVM, "setTrainPosition", "setTrainPosition"); lua_classfunction(luaVM, "setTrainSpeed", "setTrainSpeed"); // Reduce confusion + lua_classfunction(luaVM, "spawnFlyingComponent", "spawnVehicleFlyingComponent"); lua_classvariable(luaVM, "damageProof", "setVehicleDamageProof", "isVehicleDamageProof"); lua_classvariable(luaVM, "locked", "setVehicleLocked", "isVehicleLocked"); @@ -2982,3 +2984,62 @@ int CLuaVehicleDefs::SetVehiclePlateText(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CVehicle* const vehicle, std::uint8_t nodeIndex, std::optional componentCollisionType, std::optional removalTime) +{ + if (nodeIndex < 1 || nodeIndex >= CAR_NUM_NODES) + throw std::invalid_argument("Invalid component index"); + + if (componentCollisionType.has_value() && componentCollisionType.value() >= COL_NODES_NUM) + throw std::invalid_argument("Invalid collision type index"); + + if (!componentCollisionType.has_value()) + { + switch (nodeIndex) + { + case CAR_NODE_WHEEL_RF: + case CAR_NODE_WHEEL_RB: + case CAR_NODE_WHEEL_LF: + case CAR_NODE_WHEEL_LB: + { + componentCollisionType = COL_NODE_WHEEL; + break; + } + case CAR_NODE_DOOR_RF: + case CAR_NODE_DOOR_RR: + case CAR_NODE_DOOR_LF: + case CAR_NODE_DOOR_LR: + { + componentCollisionType = COL_NODE_DOOR; + break; + } + case CAR_NODE_BUMP_FRONT: + case CAR_NODE_BUMP_REAR: + case CAR_NODE_WHEEL_LM: + case CAR_NODE_WHEEL_RM: + { + componentCollisionType = COL_NODE_BUMPER; + break; + } + case CAR_NODE_BOOT: + case CAR_NODE_CHASSIS: + { + componentCollisionType = COL_NODE_BOOT; + break; + } + case CAR_NODE_BONNET: + case CAR_NODE_WINDSCREEN: + { + componentCollisionType = COL_NODE_BONNET; + break; + } + default: + { + componentCollisionType = COL_NODE_PANEL; + break; + } + } + } + + return CStaticFunctionDefinitions::SpawnVehicleFlyingComponent(vehicle, nodeIndex, componentCollisionType.value(), removalTime.value_or(-1)); +} diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h index 3200e2ada38..b3497361138 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.h @@ -125,4 +125,6 @@ class CLuaVehicleDefs : public CLuaDefs LUA_DECLARE(GetVehicleSirens); LUA_DECLARE(GetVehicleSirenParams); LUA_DECLARE(SetVehiclePlateText); + + static bool SpawnVehicleFlyingComponent(CVehicle* const vehicle, std::uint8_t nodeIndex, std::optional componentCollisionType, std::optional removalTime); }; diff --git a/Shared/sdk/net/rpc_enums.h b/Shared/sdk/net/rpc_enums.h index e4ce53df298..efa0d276307 100644 --- a/Shared/sdk/net/rpc_enums.h +++ b/Shared/sdk/net/rpc_enums.h @@ -283,5 +283,7 @@ enum eElementRPCFunctions SET_MARKER_TARGET_ARROW_PROPERTIES, + SPAWN_VEHICLE_FLYING_COMPONENT, + NUM_RPC_FUNCS // Add above this line }; From 79a5cdea7a1a0b26fcbaf0e68133cb3bef079c7a Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 21 Jul 2024 03:38:56 +0200 Subject: [PATCH 05/10] Small change --- Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp index 576ca0e3e75..a21b84f49b7 100644 --- a/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp @@ -666,7 +666,5 @@ void CVehicleRPCs::SpawnVehicleFlyingComponent(CClientEntity* const sourceEntity std::int32_t removalTime; if (bitStream.Read(nodeIndex) && bitStream.Read(collisionType) && bitStream.Read(removalTime)) - { vehicle->SpawnFlyingComponent(static_cast(nodeIndex), static_cast(collisionType), removalTime); - } } From ae74b29ae7b38da6bb8d31c58032bfbf3744f27f Mon Sep 17 00:00:00 2001 From: FileEX Date: Fri, 9 Aug 2024 23:47:44 +0200 Subject: [PATCH 06/10] Review --- Client/game_sa/CVehicleSA.cpp | 39 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index 0f40cb4f0c3..9a516fca817 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -1551,19 +1551,18 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisio if (nodeIndex >= sizeof(bikeInterface->m_apModelNodes) / sizeof(RwFrame*)) return false; + nodesOffset = OFFSET_CBike_Nodes; + if (nodeIndex != 1) + break; + // Set the correct "bike_chassis" frame for bikes - if (nodeIndex == 1) + defaultBikeChassisFrame = bikeInterface->m_apModelNodes[1]; + if (defaultBikeChassisFrame && std::strcmp(defaultBikeChassisFrame->szName, "chassis_dummy") == 0) { - defaultBikeChassisFrame = bikeInterface->m_apModelNodes[1]; - if (defaultBikeChassisFrame && std::strcmp(defaultBikeChassisFrame->szName, "chassis_dummy") == 0) - { - RwFrame* correctChassisFrame = ((RwFrame*(__cdecl*)(RpClump*, const char*))FUNC_CClumpModelInfo_GetFrameFromName)(bikeInterface->m_pRwObject, "chassis"); - if (correctChassisFrame) - bikeInterface->m_apModelNodes[1] = correctChassisFrame; - } + RwFrame* correctChassisFrame = ((RwFrame * (__cdecl*)(RpClump*, const char*))FUNC_CClumpModelInfo_GetFrameFromName)(bikeInterface->m_pRwObject, "chassis"); + if (correctChassisFrame) + bikeInterface->m_apModelNodes[1] = correctChassisFrame; } - - nodesOffset = OFFSET_CBike_Nodes; break; } case VehicleClass::BOAT: @@ -1582,7 +1581,7 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisio return false; } - // Patch nodes array + // Patch nodes array in CAutomobile::SpawnFlyingComponent MemPut(0x6A85B3, nodesOffset); MemPut(0x6A8631, nodesOffset); @@ -1598,7 +1597,7 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisio mov dwReturn, eax } - // Restore default nodes array + // Restore default nodes array in CAutomobile::SpawnFlyingComponent MemPut(0x6A85B3, 0x648); MemPut(0x6A8631, 0x648); @@ -1610,15 +1609,15 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisio bikeInterface->m_apModelNodes[1] = defaultBikeChassisFrame; } - if (removalTime > -1) - { - auto* componentObject = reinterpret_cast((DWORD*)dwReturn); - if (!componentObject) - return; + if (removalTime <= -1) + return true; - int CTimer_ms = *(int*)0xB7CB84; // CTimer::m_snTimeInMilliseconds - componentObject->uiObjectRemovalTime = CTimer_ms + static_cast(removalTime); - } + auto* componentObject = reinterpret_cast((DWORD*)dwReturn); + if (!componentObject) + return; + + int CTimer_ms = *(int*)0xB7CB84; // CTimer::m_snTimeInMilliseconds + componentObject->uiObjectRemovalTime = CTimer_ms + static_cast(removalTime); return true; } From 549cc8f5f2effcbbf0fbe0689d9029a40816400d Mon Sep 17 00:00:00 2001 From: FileEX Date: Fri, 13 Sep 2024 13:29:15 +0200 Subject: [PATCH 07/10] Update CAutomobileSA.h --- Client/game_sa/CAutomobileSA.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Client/game_sa/CAutomobileSA.h b/Client/game_sa/CAutomobileSA.h index 936861c29ee..4ba7ad5c7fa 100644 --- a/Client/game_sa/CAutomobileSA.h +++ b/Client/game_sa/CAutomobileSA.h @@ -20,7 +20,7 @@ #define MAX_PASSENGER_COUNT 8 #define MAX_DOORS 6 // also in CDamageManager -#define MAX_NODES 25 +#define CAR_NODES_NUM 25 class CBouncingPanelSAInterface { @@ -38,7 +38,7 @@ class CAutomobileSAInterface : public CVehicleSAInterface public: CDamageManagerSAInterface m_damageManager; CDoorSAInterface m_doors[MAX_DOORS]; - RwFrame* m_aCarNodes[MAX_NODES]; + RwFrame* m_aCarNodes[CAR_NODES_NUM]; CBouncingPanelSAInterface m_panels[3]; CDoorSAInterface m_swingingChassis; CColPointSAInterface m_wheelColPoint[MAX_WHEELS]; From 4bf5d32cdffe46e90dd89f45ad05f108780ce061 Mon Sep 17 00:00:00 2001 From: FileEX Date: Fri, 13 Sep 2024 16:34:24 +0200 Subject: [PATCH 08/10] Clean up --- Client/game_sa/CAutomobileSA.h | 3 +- Client/game_sa/CBikeSA.h | 31 ++--- Client/game_sa/CBmxSA.h | 29 ++-- Client/game_sa/CBoatSA.h | 35 +++-- Client/game_sa/CTrainSA.h | 44 +++--- Client/game_sa/CVehicleSA.cpp | 53 +++---- Client/game_sa/CVehicleSA.h | 4 +- .../logic/luadefs/CLuaVehicleDefs.cpp | 129 +++++++++--------- .../deathmatch/logic/rpc/CVehicleRPCs.cpp | 3 +- Client/sdk/game/CDamageManager.h | 58 ++++---- Client/sdk/game/CVehicle.h | 2 +- Server/mods/deathmatch/logic/CVehicle.h | 58 ++++---- .../logic/luadefs/CLuaVehicleDefs.cpp | 55 ++++---- 13 files changed, 237 insertions(+), 267 deletions(-) diff --git a/Client/game_sa/CAutomobileSA.h b/Client/game_sa/CAutomobileSA.h index 4ba7ad5c7fa..921c6638b3c 100644 --- a/Client/game_sa/CAutomobileSA.h +++ b/Client/game_sa/CAutomobileSA.h @@ -20,7 +20,6 @@ #define MAX_PASSENGER_COUNT 8 #define MAX_DOORS 6 // also in CDamageManager -#define CAR_NODES_NUM 25 class CBouncingPanelSAInterface { @@ -38,7 +37,7 @@ class CAutomobileSAInterface : public CVehicleSAInterface public: CDamageManagerSAInterface m_damageManager; CDoorSAInterface m_doors[MAX_DOORS]; - RwFrame* m_aCarNodes[CAR_NODES_NUM]; + RwFrame* m_aCarNodes[static_cast(eCarNodes::NUM_NODES)]; CBouncingPanelSAInterface m_panels[3]; CDoorSAInterface m_swingingChassis; CColPointSAInterface m_wheelColPoint[MAX_WHEELS]; diff --git a/Client/game_sa/CBikeSA.h b/Client/game_sa/CBikeSA.h index 5a890dfb98d..083592e5fda 100644 --- a/Client/game_sa/CBikeSA.h +++ b/Client/game_sa/CBikeSA.h @@ -14,24 +14,21 @@ #include #include "CVehicleSA.h" -namespace eBikeNodes +enum class eBikeNodes { - enum - { - NONE = 0, - CHASIS, - FORKS_FRONT, - FORKS_REAR, - WHEEL_FRONT, - WHEEL_REAR, - MUDGUARD, - HANDLEBARS, - MISC_A, - MISC_B, + NONE = 0, + CHASSIS, + FORKS_FRONT, + FORKS_REAR, + WHEEL_FRONT, + WHEEL_REAR, + MUDGUARD, + HANDLEBARS, + MISC_A, + MISC_B, - NUM_NODES - }; -} + NUM_NODES +}; struct sRideAnimData { @@ -48,7 +45,7 @@ static_assert(sizeof(sRideAnimData) == 0x1C, "Invalid size for sRideAnimData"); class CBikeSAInterface : public CVehicleSAInterface { public: - RwFrame* m_apModelNodes[eBikeNodes::NUM_NODES]; + RwFrame* m_apModelNodes[static_cast(eBikeNodes::NUM_NODES)]; int8 m_bLeanMatrixCalculated; int8 pad0[3]; // Maybe prev value is int32 int8 m_mLeanMatrix[72]; diff --git a/Client/game_sa/CBmxSA.h b/Client/game_sa/CBmxSA.h index 8134448c13f..dd64755c6dd 100644 --- a/Client/game_sa/CBmxSA.h +++ b/Client/game_sa/CBmxSA.h @@ -14,24 +14,21 @@ #include #include "CBikeSA.h" -namespace eBmxNodes +enum class eBmxNodes { - enum - { - NONE = 0, - CHASIS, - FORKS_FRONT, - FORKS_REAR, - WHEEL_FRONT, - WHEEL_REAR, - HANDLEBARS, - CHAINSET, - PEDAL_R, - PEDAL_L, + NONE = 0, + CHASSIS, + FORKS_FRONT, + FORKS_REAR, + WHEEL_FRONT, + WHEEL_REAR, + HANDLEBARS, + CHAINSET, + PEDAL_R, + PEDAL_L, - NUM_NODES - }; -} + NUM_NODES +}; class CBmxSAInterface : public CBikeSAInterface { diff --git a/Client/game_sa/CBoatSA.h b/Client/game_sa/CBoatSA.h index 8c36c9d25bb..6df3268bf08 100644 --- a/Client/game_sa/CBoatSA.h +++ b/Client/game_sa/CBoatSA.h @@ -14,33 +14,30 @@ #include #include "CVehicleSA.h" -namespace eBoatNodes +enum class eBoatNodes { - enum - { - NONE = 0, - MOVING, - WINDSCREEN, - RUDDER, - FLAP_LEFT, - FLAP_RIGHT, - REARFLAP_LEFT, - REARFLAP_RIGHT, - STATIC_PROP, - MOVING_PROP, - STATIC_PROP2, - MOVING_PROP2, + NONE = 0, + MOVING, + WINDSCREEN, + RUDDER, + FLAP_LEFT, + FLAP_RIGHT, + REARFLAP_LEFT, + REARFLAP_RIGHT, + STATIC_PROP, + MOVING_PROP, + STATIC_PROP2, + MOVING_PROP2, - NUM_NODES - }; -} + NUM_NODES +}; class CBoatSAInterface : public CVehicleSAInterface { public: uint32 pad1[3]; // 1440 uint32 BoatFlags; // 1452 - RwFrame* pBoatParts[eBoatNodes::NUM_NODES]; // 1456 + RwFrame* pBoatParts[static_cast(eBoatNodes::NUM_NODES)]; // 1456 uint32 pad2[3]; // 1500 uint16 pad3; // 1512 uint8 pad4[2]; // 1514 diff --git a/Client/game_sa/CTrainSA.h b/Client/game_sa/CTrainSA.h index 969fa907eef..84b25a6108d 100644 --- a/Client/game_sa/CTrainSA.h +++ b/Client/game_sa/CTrainSA.h @@ -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 @@ -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(eTrainNodes::NUM_NODES)]; }; static_assert(sizeof(CTrainSAInterface) == 0x6AC, "Invalid size for CTrainSAInterface"); diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index 0d77d4e878b..e44c8b1f3cc 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -1502,13 +1502,13 @@ void CVehicleSA::SetGravity(const CVector* pvecGravity) m_vecGravity = *pvecGravity; } -bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisionTypes collisionType, std::int32_t removalTime) +bool CVehicleSA::SpawnFlyingComponent(const eCarNodes& nodeIndex, const eCarComponentCollisionTypes& collisionType, std::int32_t removalTime) { - if (nodeIndex < 1) + if (nodeIndex == eCarNodes::NONE) return false; DWORD nodesOffset = OFFSET_CAutomobile_Nodes; - RwFrame* defaultBikeChassisFrame; + RwFrame* defaultBikeChassisFrame = nullptr; // CBike, CBmx, CBoat and CTrain don't inherit CAutomobile so let's do it manually! switch (static_cast(GetVehicleInterface()->m_vehicleClass)) @@ -1525,11 +1525,7 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisio } case VehicleClass::TRAIN: { - auto* trainInterface = static_cast(GetVehicleInterface()); - if (!trainInterface) - return false; - - if (nodeIndex >= sizeof(trainInterface->m_aTrainNodes) / sizeof(RwFrame*)) + if (static_cast(nodeIndex) >= eTrainNodes::NUM_NODES) return false; nodesOffset = OFFSET_CTrain_Nodes; @@ -1542,18 +1538,18 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisio if (!bikeInterface) return false; - if (nodeIndex >= sizeof(bikeInterface->m_apModelNodes) / sizeof(RwFrame*)) + if (static_cast(nodeIndex) >= eBikeNodes::NUM_NODES) return false; nodesOffset = OFFSET_CBike_Nodes; - if (nodeIndex != 1) + if (static_cast(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 = ((RwFrame * (__cdecl*)(RpClump*, const char*))FUNC_CClumpModelInfo_GetFrameFromName)(bikeInterface->m_pRwObject, "chassis"); + RwFrame* correctChassisFrame = RwFrameFindFrame(RpGetFrame(bikeInterface->m_pRwObject), "chassis"); if (correctChassisFrame) bikeInterface->m_apModelNodes[1] = correctChassisFrame; } @@ -1561,11 +1557,7 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisio } case VehicleClass::BOAT: { - auto* boatInterface = static_cast(GetVehicleInterface()); - if (!boatInterface) - return false; - - if (nodeIndex >= sizeof(boatInterface->pBoatParts) / sizeof(RwFrame*)) + if (static_cast(nodeIndex) >= eBoatNodes::NUM_NODES) return false; nodesOffset = OFFSET_CBoat_Nodes; @@ -1579,24 +1571,15 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisio MemPut(0x6A85B3, nodesOffset); MemPut(0x6A8631, nodesOffset); - DWORD dwInterface = (DWORD)GetInterface(); - DWORD dwFunc = FUNC_CAutomobile__SpawnFlyingComponent; - DWORD dwReturn; - _asm - { - mov ecx, dwInterface - push collisionType - push nodeIndex - call dwFunc - mov dwReturn, eax - } + auto* componentObject = ((CObjectSAInterface * (__thiscall*)(CVehicleSAInterface*, int, int)) FUNC_CAutomobile__SpawnFlyingComponent)(GetVehicleInterface(), static_cast(nodeIndex), static_cast(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 (nodeIndex == 1 && defaultBikeChassisFrame) + if (static_cast(nodeIndex) == eBikeNodes::CHASSIS && defaultBikeChassisFrame) { auto* bikeInterface = static_cast(GetVehicleInterface()); if (bikeInterface && bikeInterface->m_apModelNodes) @@ -1606,11 +1589,7 @@ bool CVehicleSA::SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisio if (removalTime <= -1) return true; - auto* componentObject = reinterpret_cast((DWORD*)dwReturn); - if (!componentObject) - return; - - int CTimer_ms = *(int*)0xB7CB84; // CTimer::m_snTimeInMilliseconds + std::uint32_t CTimer_ms = *reinterpret_cast(VAR_CTimer_snTimeInMilliseconds); componentObject->uiObjectRemovalTime = CTimer_ms + static_cast(removalTime); return true; @@ -1623,16 +1602,16 @@ void CVehicleSA::SetWheelVisibility(eWheelPosition wheel, bool bVisible) switch (wheel) { case FRONT_LEFT_WHEEL: - pFrame = vehicle->m_aCarNodes[CAR_NODE_WHEEL_LF]; + pFrame = vehicle->m_aCarNodes[static_cast(eCarNodes::WHEEL_LF)]; break; case REAR_LEFT_WHEEL: - pFrame = vehicle->m_aCarNodes[CAR_NODE_WHEEL_LB]; + pFrame = vehicle->m_aCarNodes[static_cast(eCarNodes::WHEEL_LB)]; break; case FRONT_RIGHT_WHEEL: - pFrame = vehicle->m_aCarNodes[CAR_NODE_WHEEL_RF]; + pFrame = vehicle->m_aCarNodes[static_cast(eCarNodes::WHEEL_RF)]; break; case REAR_RIGHT_WHEEL: - pFrame = vehicle->m_aCarNodes[CAR_NODE_WHEEL_RB]; + pFrame = vehicle->m_aCarNodes[static_cast(eCarNodes::WHEEL_RB)]; break; default: break; diff --git a/Client/game_sa/CVehicleSA.h b/Client/game_sa/CVehicleSA.h index bc5019ab5dc..382a071ac11 100644 --- a/Client/game_sa/CVehicleSA.h +++ b/Client/game_sa/CVehicleSA.h @@ -106,6 +106,8 @@ struct RwTexture; #define OFFSET_CBike_Nodes 0x5A0 #define OFFSET_CBoat_Nodes 0x5B0 +#define VAR_CTimer_snTimeInMilliseconds 0xB7CB84 + struct SRailNodeSA { short sX; // x coordinate times 8 @@ -616,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; } - bool SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisionTypes collisionType, std::int32_t removalTime = -1); + bool SpawnFlyingComponent(const eCarNodes& nodeIndex, const eCarComponentCollisionTypes& collisionType, std::int32_t removalTime = -1); void SetWheelVisibility(eWheelPosition wheel, bool bVisible); CVector GetWheelPosition(eWheelPosition wheel); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index 0a225664226..6ac42bf386c 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -4236,71 +4236,6 @@ bool CLuaVehicleDefs::BlowVehicle(CClientEntity* entity, std::optional wit { return CStaticFunctionDefinitions::BlowVehicle(*entity, withExplosion); } - -bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeIndex, std::optional componentCollisionType, std::optional removalTime) -{ - if (nodeIndex < 1 || nodeIndex >= CAR_NUM_NODES) - throw std::invalid_argument("Invalid component index"); - - if (componentCollisionType.has_value() && componentCollisionType.value() >= COL_NODES_NUM) - throw std::invalid_argument("Invalid collision type index"); - - eCarComponentCollisionTypes collisionType; - - if (!componentCollisionType.has_value()) - { - switch (nodeIndex) - { - case CAR_NODE_WHEEL_RF: - case CAR_NODE_WHEEL_RB: - case CAR_NODE_WHEEL_LF: - case CAR_NODE_WHEEL_LB: - { - collisionType = COL_NODE_WHEEL; - break; - } - case CAR_NODE_DOOR_RF: - case CAR_NODE_DOOR_RR: - case CAR_NODE_DOOR_LF: - case CAR_NODE_DOOR_LR: - { - collisionType = COL_NODE_DOOR; - break; - } - case CAR_NODE_BUMP_FRONT: - case CAR_NODE_BUMP_REAR: - case CAR_NODE_WHEEL_LM: - case CAR_NODE_WHEEL_RM: - { - collisionType = COL_NODE_BUMPER; - break; - } - case CAR_NODE_BOOT: - case CAR_NODE_CHASSIS: - { - collisionType = COL_NODE_BOOT; - break; - } - case CAR_NODE_BONNET: - case CAR_NODE_WINDSCREEN: - { - collisionType = COL_NODE_BONNET; - break; - } - default: - { - collisionType = COL_NODE_PANEL; - break; - } - } - } - else - { - collisionType = static_cast(componentCollisionType.value()); - } - - return vehicle->SpawnFlyingComponent(static_cast(nodeIndex), collisionType, removalTime.value_or(-1)); -} std::variant, 4>> CLuaVehicleDefs::GetVehicleEntryPoints(CClientVehicle* vehicle) { @@ -4341,3 +4276,67 @@ std::variant> CLuaVehicleDefs::OOP_GetVehicleEntryP return entryPoints; } + +bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CClientVehicle* const vehicle, std::uint8_t nodeIndex, std::optional componentCollisionType, + std::optional removalTime) +{ + auto partNodeIndex = static_cast(nodeIndex); + auto collisionType = componentCollisionType.has_value() ? static_cast(componentCollisionType.value()) + : eCarComponentCollisionTypes::COL_NODE_PANEL; + + if (nodeIndex < 1 || partNodeIndex >= eCarNodes::NUM_NODES) + throw std::invalid_argument("Invalid component index"); + + if (collisionType >= eCarComponentCollisionTypes::COL_NODES_NUM) + throw std::invalid_argument("Invalid collision type index"); + + if (!componentCollisionType.has_value()) + { + switch (partNodeIndex) + { + case eCarNodes::WHEEL_RF: + case eCarNodes::WHEEL_RB: + case eCarNodes::WHEEL_LF: + case eCarNodes::WHEEL_LB: + { + collisionType = eCarComponentCollisionTypes::COL_NODE_WHEEL; + break; + } + case eCarNodes::DOOR_RF: + case eCarNodes::DOOR_RR: + case eCarNodes::DOOR_LF: + case eCarNodes::DOOR_LR: + { + collisionType = eCarComponentCollisionTypes::COL_NODE_DOOR; + break; + } + case eCarNodes::BUMP_FRONT: + case eCarNodes::BUMP_REAR: + case eCarNodes::WHEEL_LM: + case eCarNodes::WHEEL_RM: + { + collisionType = eCarComponentCollisionTypes::COL_NODE_BUMPER; + break; + } + case eCarNodes::BOOT: + case eCarNodes::CHASSIS: + { + collisionType = eCarComponentCollisionTypes::COL_NODE_BOOT; + break; + } + case eCarNodes::BONNET: + case eCarNodes::WINDSCREEN: + { + collisionType = eCarComponentCollisionTypes::COL_NODE_BONNET; + break; + } + default: + { + collisionType = eCarComponentCollisionTypes::COL_NODE_PANEL; + break; + } + } + } + + return vehicle->SpawnFlyingComponent(partNodeIndex, collisionType, removalTime.value_or(-1)); +} diff --git a/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp index a21b84f49b7..7915c2c7d41 100644 --- a/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CVehicleRPCs.cpp @@ -661,8 +661,7 @@ void CVehicleRPCs::SpawnVehicleFlyingComponent(CClientEntity* const sourceEntity if (!vehicle) return; - std::uint8_t nodeIndex; - std::uint8_t collisionType; + std::uint8_t nodeIndex, collisionType; std::int32_t removalTime; if (bitStream.Read(nodeIndex) && bitStream.Read(collisionType) && bitStream.Read(removalTime)) diff --git a/Client/sdk/game/CDamageManager.h b/Client/sdk/game/CDamageManager.h index d5579254a8c..9c4fcc23487 100644 --- a/Client/sdk/game/CDamageManager.h +++ b/Client/sdk/game/CDamageManager.h @@ -121,38 +121,38 @@ enum eLights MAX_LIGHTS // MUST BE 16 OR LESS }; -enum eCarNodes +enum class eCarNodes { - CAR_NODE_NONE = 0, - CAR_NODE_CHASSIS, - CAR_NODE_WHEEL_RF, - CAR_NODE_WHEEL_RM, - CAR_NODE_WHEEL_RB, - CAR_NODE_WHEEL_LF, - CAR_NODE_WHEEL_LM, - CAR_NODE_WHEEL_LB, - CAR_NODE_DOOR_RF, - CAR_NODE_DOOR_RR, - CAR_NODE_DOOR_LF, - CAR_NODE_DOOR_LR, - CAR_NODE_BUMP_FRONT, - CAR_NODE_BUMP_REAR, - CAR_NODE_WING_RF, - CAR_NODE_WING_LF, - CAR_NODE_BONNET, - CAR_NODE_BOOT, - CAR_NODE_WINDSCREEN, - CAR_NODE_EXHAUST, - CAR_NODE_MISC_A, - CAR_NODE_MISC_B, - CAR_NODE_MISC_C, - CAR_NODE_MISC_D, - CAR_NODE_MISC_E, - - CAR_NUM_NODES + NONE = 0, + CHASSIS, + WHEEL_RF, + WHEEL_RM, + WHEEL_RB, + WHEEL_LF, + WHEEL_LM, + WHEEL_LB, + DOOR_RF, + DOOR_RR, + DOOR_LF, + DOOR_LR, + BUMP_FRONT, + BUMP_REAR, + WING_RF, + WING_LF, + BONNET, + BOOT, + WINDSCREEN, + EXHAUST, + MISC_A, + MISC_B, + MISC_C, + MISC_D, + MISC_E, + + NUM_NODES }; -enum eCarComponentCollisionTypes +enum class eCarComponentCollisionTypes { COL_NODE_BUMPER = 0, COL_NODE_WHEEL, diff --git a/Client/sdk/game/CVehicle.h b/Client/sdk/game/CVehicle.h index 94ffb578089..a5a4f1cdd43 100644 --- a/Client/sdk/game/CVehicle.h +++ b/Client/sdk/game/CVehicle.h @@ -264,7 +264,7 @@ class CVehicle : public virtual CPhysical virtual SColor GetHeadLightColor() = 0; virtual void SetHeadLightColor(const SColor color) = 0; - virtual bool SpawnFlyingComponent(eCarNodes nodeIndex, eCarComponentCollisionTypes collisionType, std::int32_t removalTime = -1) = 0; + virtual bool SpawnFlyingComponent(const eCarNodes& nodeIndex, const eCarComponentCollisionTypes& collisionType, std::int32_t removalTime = -1) = 0; virtual void SetWheelVisibility(eWheelPosition wheel, bool bVisible) = 0; virtual CVector GetWheelPosition(eWheelPosition wheel) = 0; diff --git a/Server/mods/deathmatch/logic/CVehicle.h b/Server/mods/deathmatch/logic/CVehicle.h index d269d7ed6df..d5dbb43243a 100644 --- a/Server/mods/deathmatch/logic/CVehicle.h +++ b/Server/mods/deathmatch/logic/CVehicle.h @@ -111,38 +111,38 @@ enum eVehicleType VEHICLE_TRAILER }; -enum eCarNodes +enum class eCarNodes { - CAR_NODE_NONE = 0, - CAR_NODE_CHASSIS, - CAR_NODE_WHEEL_RF, - CAR_NODE_WHEEL_RM, - CAR_NODE_WHEEL_RB, - CAR_NODE_WHEEL_LF, - CAR_NODE_WHEEL_LM, - CAR_NODE_WHEEL_LB, - CAR_NODE_DOOR_RF, - CAR_NODE_DOOR_RR, - CAR_NODE_DOOR_LF, - CAR_NODE_DOOR_LR, - CAR_NODE_BUMP_FRONT, - CAR_NODE_BUMP_REAR, - CAR_NODE_WING_RF, - CAR_NODE_WING_LF, - CAR_NODE_BONNET, - CAR_NODE_BOOT, - CAR_NODE_WINDSCREEN, - CAR_NODE_EXHAUST, - CAR_NODE_MISC_A, - CAR_NODE_MISC_B, - CAR_NODE_MISC_C, - CAR_NODE_MISC_D, - CAR_NODE_MISC_E, - - CAR_NUM_NODES + NONE = 0, + CHASSIS, + WHEEL_RF, + WHEEL_RM, + WHEEL_RB, + WHEEL_LF, + WHEEL_LM, + WHEEL_LB, + DOOR_RF, + DOOR_RR, + DOOR_LF, + DOOR_LR, + BUMP_FRONT, + BUMP_REAR, + WING_RF, + WING_LF, + BONNET, + BOOT, + WINDSCREEN, + EXHAUST, + MISC_A, + MISC_B, + MISC_C, + MISC_D, + MISC_E, + + NUM_NODES }; -enum eCarComponentCollisionTypes +enum class eCarComponentCollisionTypes { COL_NODE_BUMPER = 0, COL_NODE_WHEEL, diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp index 34fd4b92821..d34d8fe579f 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaVehicleDefs.cpp @@ -2987,59 +2987,62 @@ int CLuaVehicleDefs::SetVehiclePlateText(lua_State* luaVM) bool CLuaVehicleDefs::SpawnVehicleFlyingComponent(CVehicle* const vehicle, std::uint8_t nodeIndex, std::optional componentCollisionType, std::optional removalTime) { - if (nodeIndex < 1 || nodeIndex >= CAR_NUM_NODES) + auto partNodeIndex = static_cast(nodeIndex); + auto collisionType = componentCollisionType.has_value() ? static_cast(componentCollisionType.value()) : eCarComponentCollisionTypes::COL_NODE_PANEL; + + if (nodeIndex < 1 || partNodeIndex >= eCarNodes::NUM_NODES) throw std::invalid_argument("Invalid component index"); - if (componentCollisionType.has_value() && componentCollisionType.value() >= COL_NODES_NUM) + if (collisionType >= eCarComponentCollisionTypes::COL_NODES_NUM) throw std::invalid_argument("Invalid collision type index"); if (!componentCollisionType.has_value()) { - switch (nodeIndex) + switch (partNodeIndex) { - case CAR_NODE_WHEEL_RF: - case CAR_NODE_WHEEL_RB: - case CAR_NODE_WHEEL_LF: - case CAR_NODE_WHEEL_LB: + case eCarNodes::WHEEL_RF: + case eCarNodes::WHEEL_RB: + case eCarNodes::WHEEL_LF: + case eCarNodes::WHEEL_LB: { - componentCollisionType = COL_NODE_WHEEL; + collisionType = eCarComponentCollisionTypes::COL_NODE_WHEEL; break; } - case CAR_NODE_DOOR_RF: - case CAR_NODE_DOOR_RR: - case CAR_NODE_DOOR_LF: - case CAR_NODE_DOOR_LR: + case eCarNodes::DOOR_RF: + case eCarNodes::DOOR_RR: + case eCarNodes::DOOR_LF: + case eCarNodes::DOOR_LR: { - componentCollisionType = COL_NODE_DOOR; + collisionType = eCarComponentCollisionTypes::COL_NODE_DOOR; break; } - case CAR_NODE_BUMP_FRONT: - case CAR_NODE_BUMP_REAR: - case CAR_NODE_WHEEL_LM: - case CAR_NODE_WHEEL_RM: + case eCarNodes::BUMP_FRONT: + case eCarNodes::BUMP_REAR: + case eCarNodes::WHEEL_LM: + case eCarNodes::WHEEL_RM: { - componentCollisionType = COL_NODE_BUMPER; + collisionType = eCarComponentCollisionTypes::COL_NODE_BUMPER; break; } - case CAR_NODE_BOOT: - case CAR_NODE_CHASSIS: + case eCarNodes::BOOT: + case eCarNodes::CHASSIS: { - componentCollisionType = COL_NODE_BOOT; + collisionType = eCarComponentCollisionTypes::COL_NODE_BOOT; break; } - case CAR_NODE_BONNET: - case CAR_NODE_WINDSCREEN: + case eCarNodes::BONNET: + case eCarNodes::WINDSCREEN: { - componentCollisionType = COL_NODE_BONNET; + collisionType = eCarComponentCollisionTypes::COL_NODE_BONNET; break; } default: { - componentCollisionType = COL_NODE_PANEL; + collisionType = eCarComponentCollisionTypes::COL_NODE_PANEL; break; } } } - return CStaticFunctionDefinitions::SpawnVehicleFlyingComponent(vehicle, nodeIndex, componentCollisionType.value(), removalTime.value_or(-1)); + return CStaticFunctionDefinitions::SpawnVehicleFlyingComponent(vehicle, nodeIndex, static_cast(collisionType), removalTime.value_or(-1)); } From 1b31ad575ed21b46b3438f0a70665b55c2590039 Mon Sep 17 00:00:00 2001 From: FileEX Date: Fri, 13 Sep 2024 16:53:10 +0200 Subject: [PATCH 09/10] Update CVehicleSA.cpp --- Client/game_sa/CVehicleSA.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index e44c8b1f3cc..8f00d741856 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -1586,7 +1586,7 @@ bool CVehicleSA::SpawnFlyingComponent(const eCarNodes& nodeIndex, const eCarComp bikeInterface->m_apModelNodes[1] = defaultBikeChassisFrame; } - if (removalTime <= -1) + if (removalTime <= -1 || !componentObject) return true; std::uint32_t CTimer_ms = *reinterpret_cast(VAR_CTimer_snTimeInMilliseconds); From 3a9395d0221050e3a7909e7c35d76d1636eb4f72 Mon Sep 17 00:00:00 2001 From: FileEX Date: Sun, 13 Oct 2024 00:22:57 +0200 Subject: [PATCH 10/10] Little changes --- Client/game_sa/CVehicleSA.cpp | 5 +++-- Client/game_sa/CVehicleSA.h | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Client/game_sa/CVehicleSA.cpp b/Client/game_sa/CVehicleSA.cpp index 8f00d741856..ff4edf29dfa 100644 --- a/Client/game_sa/CVehicleSA.cpp +++ b/Client/game_sa/CVehicleSA.cpp @@ -1589,9 +1589,10 @@ bool CVehicleSA::SpawnFlyingComponent(const eCarNodes& nodeIndex, const eCarComp if (removalTime <= -1 || !componentObject) return true; - std::uint32_t CTimer_ms = *reinterpret_cast(VAR_CTimer_snTimeInMilliseconds); - componentObject->uiObjectRemovalTime = CTimer_ms + static_cast(removalTime); + // Set double-sided + componentObject->bBackfaceCulled = true; + componentObject->uiObjectRemovalTime = pGame->GetSystemTime() + static_cast(removalTime); return true; } diff --git a/Client/game_sa/CVehicleSA.h b/Client/game_sa/CVehicleSA.h index 382a071ac11..9674a165cde 100644 --- a/Client/game_sa/CVehicleSA.h +++ b/Client/game_sa/CVehicleSA.h @@ -106,8 +106,6 @@ struct RwTexture; #define OFFSET_CBike_Nodes 0x5A0 #define OFFSET_CBoat_Nodes 0x5B0 -#define VAR_CTimer_snTimeInMilliseconds 0xB7CB84 - struct SRailNodeSA { short sX; // x coordinate times 8