diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 91a19010566..dcb73b17389 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -6044,6 +6044,9 @@ bool CClientGame::SetWorldSpecialProperty(WorldSpecialProperty property, bool is case WorldSpecialProperty::IGNOREFIRESTATE: g_pGame->SetIgnoreFireStateEnabled(isEnabled); break; + case WorldSpecialProperty::FLYINGCOMPONENTS: + m_pVehicleManager->SetSpawnFlyingComponentEnabled(isEnabled); + break; default: return false; } @@ -6094,6 +6097,8 @@ bool CClientGame::IsWorldSpecialProperty(WorldSpecialProperty property) return g_pGame->IsTunnelWeatherBlendEnabled(); case WorldSpecialProperty::IGNOREFIRESTATE: return g_pGame->IsIgnoreFireStateEnabled(); + case WorldSpecialProperty::FLYINGCOMPONENTS: + return m_pVehicleManager->IsSpawnFlyingComponentEnabled(); } return false; } diff --git a/Client/mods/deathmatch/logic/CClientVehicle.cpp b/Client/mods/deathmatch/logic/CClientVehicle.cpp index ffc1fbdbc1a..0ae45bb270c 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.cpp +++ b/Client/mods/deathmatch/logic/CClientVehicle.cpp @@ -808,10 +808,12 @@ void CClientVehicle::Fix() SFixedArray ucDoorStates; GetInitialDoorStates(ucDoorStates); + + bool flyingComponents = m_pVehicleManager->IsSpawnFlyingComponentEnabled(); for (int i = 0; i < MAX_DOORS; i++) - SetDoorStatus(i, ucDoorStates[i], true); + SetDoorStatus(i, ucDoorStates[i], flyingComponents); for (int i = 0; i < MAX_PANELS; i++) - SetPanelStatus(i, 0); + SetPanelStatus(i, 0, flyingComponents); for (int i = 0; i < MAX_LIGHTS; i++) SetLightStatus(i, 0); for (int i = 0; i < MAX_WHEELS; i++) @@ -2170,11 +2172,12 @@ void CClientVehicle::StreamedInPulse() { // Set the damage model doors CDamageManager* pDamageManager = m_pVehicle->GetDamageManager(); + bool flyingComponents = m_pVehicleManager->IsSpawnFlyingComponentEnabled(); for (int i = 0; i < MAX_DOORS; i++) - pDamageManager->SetDoorStatus(static_cast(i), m_ucDoorStates[i], true); + pDamageManager->SetDoorStatus(static_cast(i), m_ucDoorStates[i], flyingComponents); for (int i = 0; i < MAX_PANELS; i++) - pDamageManager->SetPanelStatus(static_cast(i), m_ucPanelStates[i]); + pDamageManager->SetPanelStatus(static_cast(i), m_ucPanelStates[i], flyingComponents); for (int i = 0; i < MAX_LIGHTS; i++) pDamageManager->SetLightStatus(static_cast(i), m_ucLightStates[i]); } diff --git a/Client/mods/deathmatch/logic/CClientVehicleManager.h b/Client/mods/deathmatch/logic/CClientVehicleManager.h index 2f062d650aa..5f0ad55f615 100644 --- a/Client/mods/deathmatch/logic/CClientVehicleManager.h +++ b/Client/mods/deathmatch/logic/CClientVehicleManager.h @@ -70,9 +70,13 @@ class CClientVehicleManager void OnCreation(CClientVehicle* pVehicle); void OnDestruction(CClientVehicle* pVehicle); + bool IsSpawnFlyingComponentEnabled() const noexcept { return m_spawnFlyingComponentsDuringRecreate; } + void SetSpawnFlyingComponentEnabled(bool isEnabled) noexcept { m_spawnFlyingComponentsDuringRecreate = isEnabled; } + protected: CClientManager* m_pManager; bool m_bCanRemoveFromList; CMappedArray m_List; CMappedArray m_StreamedIn; + bool m_spawnFlyingComponentsDuringRecreate{true}; }; diff --git a/Client/mods/deathmatch/logic/CNetAPI.cpp b/Client/mods/deathmatch/logic/CNetAPI.cpp index 3927c3af4d2..ced1680e3f7 100644 --- a/Client/mods/deathmatch/logic/CNetAPI.cpp +++ b/Client/mods/deathmatch/logic/CNetAPI.cpp @@ -2243,10 +2243,11 @@ void CNetAPI::ReadVehiclePartsState(CClientVehicle* pVehicle, NetBitStreamInterf SVehicleDamageSyncMethodeB damage; BitStream.Read(&damage); + bool flyingComponents = m_pVehicleManager->IsSpawnFlyingComponentEnabled(); if (damage.data.bSyncDoors) for (unsigned int i = 0; i < MAX_DOORS; ++i) - pVehicle->SetDoorStatus(i, damage.data.doors.data.ucStates[i], true); + pVehicle->SetDoorStatus(i, damage.data.doors.data.ucStates[i], flyingComponents); if (damage.data.bSyncWheels) for (unsigned int i = 0; i < MAX_WHEELS; ++i) @@ -2254,7 +2255,7 @@ void CNetAPI::ReadVehiclePartsState(CClientVehicle* pVehicle, NetBitStreamInterf if (damage.data.bSyncPanels) for (unsigned int i = 0; i < MAX_PANELS; ++i) - pVehicle->SetPanelStatus(i, damage.data.panels.data.ucStates[i]); + pVehicle->SetPanelStatus(i, damage.data.panels.data.ucStates[i], flyingComponents); if (damage.data.bSyncLights) for (unsigned int i = 0; i < MAX_LIGHTS; ++i) diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index 9001f6ffdea..094812d816b 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -1628,10 +1628,12 @@ void CPacketHandler::Packet_VehicleDamageSync(NetBitStreamInterface& bitStream) CDeathmatchVehicle* pVehicle = static_cast(g_pClientGame->m_pVehicleManager->Get(ID)); if (pVehicle) { + bool flyingComponents = g_pClientGame->IsWorldSpecialProperty(WorldSpecialProperty::FLYINGCOMPONENTS); + for (unsigned int i = 0; i < MAX_DOORS; ++i) { if (damage.data.bDoorStatesChanged[i]) - pVehicle->SetDoorStatus(i, damage.data.ucDoorStates[i], true); + pVehicle->SetDoorStatus(i, damage.data.ucDoorStates[i], flyingComponents); } for (unsigned int i = 0; i < MAX_WHEELS; ++i) { @@ -1641,7 +1643,7 @@ void CPacketHandler::Packet_VehicleDamageSync(NetBitStreamInterface& bitStream) for (unsigned int i = 0; i < MAX_PANELS; ++i) { if (damage.data.bPanelStatesChanged[i]) - pVehicle->SetPanelStatus(i, damage.data.ucPanelStates[i]); + pVehicle->SetPanelStatus(i, damage.data.ucPanelStates[i], flyingComponents); } for (unsigned int i = 0; i < MAX_LIGHTS; ++i) { @@ -2398,6 +2400,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::EXTENDEDWATERCANNONS, wsProps.data4.extendedwatercannons); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::TUNNELWEATHERBLEND, wsProps.data5.tunnelweatherblend); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::IGNOREFIRESTATE, wsProps.data6.ignoreFireState); + g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::FLYINGCOMPONENTS, wsProps.data7.flyingcomponents); float fJetpackMaxHeight = 100; if (!bitStream.Read(fJetpackMaxHeight)) @@ -3391,13 +3394,14 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream) pVehicle->SetPaintjob(paintjob.data.ucPaintjob); pVehicle->SetColor(vehColor); + bool flyingComponents = g_pClientGame->IsWorldSpecialProperty(WorldSpecialProperty::FLYINGCOMPONENTS); // Setup our damage model for (int i = 0; i < MAX_DOORS; i++) - pVehicle->SetDoorStatus(i, damage.data.ucDoorStates[i], true); + pVehicle->SetDoorStatus(i, damage.data.ucDoorStates[i], flyingComponents); for (int i = 0; i < MAX_WHEELS; i++) pVehicle->SetWheelStatus(i, damage.data.ucWheelStates[i]); for (int i = 0; i < MAX_PANELS; i++) - pVehicle->SetPanelStatus(i, damage.data.ucPanelStates[i]); + pVehicle->SetPanelStatus(i, damage.data.ucPanelStates[i], flyingComponents); for (int i = 0; i < MAX_LIGHTS; i++) pVehicle->SetLightStatus(i, damage.data.ucLightStates[i]); pVehicle->ResetDamageModelSync(); diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index a92857f103f..82ba250ba5c 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -260,6 +260,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_WorldSpecialProps[WorldSpecialProperty::ROADSIGNSTEXT] = true; m_WorldSpecialProps[WorldSpecialProperty::TUNNELWEATHERBLEND] = true; m_WorldSpecialProps[WorldSpecialProperty::IGNOREFIRESTATE] = false; + m_WorldSpecialProps[WorldSpecialProperty::FLYINGCOMPONENTS] = true; m_JetpackWeapons[WEAPONTYPE_MICRO_UZI] = true; m_JetpackWeapons[WEAPONTYPE_TEC9] = true; diff --git a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp index e2adf9a5bce..2bbe9f9f646 100644 --- a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp @@ -193,6 +193,7 @@ bool CMapInfoPacket::Write(NetBitStreamInterface& BitStream) const wsProps.data4.extendedwatercannons = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::EXTENDEDWATERCANNONS); wsProps.data5.tunnelweatherblend = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::TUNNELWEATHERBLEND); wsProps.data6.ignoreFireState = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::IGNOREFIRESTATE); + wsProps.data7.flyingcomponents = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::FLYINGCOMPONENTS); BitStream.Write(&wsProps); } diff --git a/Shared/mods/deathmatch/logic/Enums.cpp b/Shared/mods/deathmatch/logic/Enums.cpp index 64aa8db8f1a..28f0ffe7a20 100644 --- a/Shared/mods/deathmatch/logic/Enums.cpp +++ b/Shared/mods/deathmatch/logic/Enums.cpp @@ -102,6 +102,7 @@ ADD_ENUM(WorldSpecialProperty::EXTENDEDWATERCANNONS, "extendedwatercannons") ADD_ENUM(WorldSpecialProperty::ROADSIGNSTEXT, "roadsignstext") ADD_ENUM(WorldSpecialProperty::TUNNELWEATHERBLEND, "tunnelweatherblend") ADD_ENUM(WorldSpecialProperty::IGNOREFIRESTATE, "ignorefirestate") +ADD_ENUM(WorldSpecialProperty::FLYINGCOMPONENTS, "flyingcomponents") IMPLEMENT_ENUM_CLASS_END("world-special-property") IMPLEMENT_ENUM_BEGIN(ePacketID) diff --git a/Shared/mods/deathmatch/logic/Enums.h b/Shared/mods/deathmatch/logic/Enums.h index 31251797143..bf3a9b9fe46 100644 --- a/Shared/mods/deathmatch/logic/Enums.h +++ b/Shared/mods/deathmatch/logic/Enums.h @@ -92,6 +92,7 @@ enum class WorldSpecialProperty EXTENDEDWATERCANNONS, TUNNELWEATHERBLEND, IGNOREFIRESTATE, + FLYINGCOMPONENTS, }; DECLARE_ENUM_CLASS(WorldSpecialProperty); diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 07c4171e20a..afa32a05f0a 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -2075,6 +2075,10 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure { BITCOUNT6 = 1 }; + enum + { + BITCOUNT7 = 1 + }; bool Read(NetBitStreamInterface& bitStream) { @@ -2103,7 +2107,12 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure isOK &= bitStream.ReadBits(reinterpret_cast(&data6), BITCOUNT6); else data6.ignoreFireState = false; - + + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_FlyingComponents)) + isOK &= bitStream.ReadBits(reinterpret_cast(&data7), BITCOUNT7); + else + data7.flyingcomponents = true; + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // isOK &= bitStream.ReadBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2130,6 +2139,9 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_IgnoreFireState)) bitStream.WriteBits(reinterpret_cast(&data6), BITCOUNT6); + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_FlyingComponents)) + bitStream.WriteBits(reinterpret_cast(&data7), BITCOUNT7); + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // bitStream.WriteBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2177,6 +2189,11 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure bool ignoreFireState : 1; } data6; + struct + { + bool flyingcomponents : 1; + } data7; + SWorldSpecialPropertiesStateSync() { // Set default states @@ -2197,6 +2214,7 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure data4.extendedwatercannons = true; data5.tunnelweatherblend = true; data6.ignoreFireState = false; + data7.flyingcomponents = true; } }; diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index 5189e85ee15..f69c7cc0f76 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -556,7 +556,7 @@ enum class eBitStreamVersion : unsigned short // 2024-06-16 PedSync_Revision, - // Add "extendedwatercannons" to setWorldSpecialPropertyEnabled + // Add "tunnelweatherblend" to setWorldSpecialPropertyEnabled // 2024-06-30 WorldSpecialProperty_TunnelWeatherBlend, @@ -604,6 +604,10 @@ enum class eBitStreamVersion : unsigned short // 2025-01-09 IsPedReloadingWeapon, + // Add "flyingcomponents" to setWorldSpecialPropertyEnabled + // 2025-01-10 + WorldSpecialProperty_FlyingComponents, + // This allows us to automatically increment the BitStreamVersion when things are added to this enum. // Make sure you only add things above this comment. Next,