diff --git a/Client/game_sa/CGameSA.cpp b/Client/game_sa/CGameSA.cpp index a65e84a1f69..ea64ab976ac 100644 --- a/Client/game_sa/CGameSA.cpp +++ b/Client/game_sa/CGameSA.cpp @@ -664,7 +664,7 @@ void CGameSA::SetCoronaZTestEnabled(bool isEnabled) m_isCoronaZTestEnabled = isEnabled; } -void CGameSA::SetWaterCreaturesEnabled(bool isEnabled) +void CGameSA::SetWaterCreaturesEnabled(bool isEnabled) { if (isEnabled == m_areWaterCreaturesEnabled) return; @@ -684,6 +684,29 @@ void CGameSA::SetWaterCreaturesEnabled(bool isEnabled) m_areWaterCreaturesEnabled = isEnabled; } +void CGameSA::SetTunnelWeatherBlendEnabled(bool isEnabled) +{ + if (isEnabled == m_isTunnelWeatherBlendEnabled) + return; + // CWeather::UpdateInTunnelness + DWORD functionAddress = 0x72B630; + if (isEnabled) + { + // Restore original bytes: 83 EC 20 + MemPut(functionAddress, 0x83); // Restore 83 + MemPut(functionAddress + 1, 0xEC); // Restore EC + MemPut(functionAddress + 2, 0x20); // Restore 20 + } + else + { + // Patch CWeather::UpdateInTunnelness (Found By AlexTMjugador) + MemPut(functionAddress, 0xC3); // Write C3 (RET) + MemPut(functionAddress + 1, 0x90); // Write 90 (NOP) + MemPut(functionAddress + 2, 0x90); // Write 90 (NOP) + } + m_isTunnelWeatherBlendEnabled = isEnabled; +} + void CGameSA::SetBurnFlippedCarsEnabled(bool isEnabled) { if (isEnabled == m_isBurnFlippedCarsEnabled) diff --git a/Client/game_sa/CGameSA.h b/Client/game_sa/CGameSA.h index 29d9a9ef73d..976c1d5db0a 100644 --- a/Client/game_sa/CGameSA.h +++ b/Client/game_sa/CGameSA.h @@ -244,6 +244,10 @@ class CGameSA : public CGame bool IsRoadSignsTextEnabled() const noexcept override { return m_isRoadSignsTextEnabled; } void SetRoadSignsTextEnabled(bool isEnabled) override; + bool IsTunnelWeatherBlendEnabled() const noexcept override { return m_isTunnelWeatherBlendEnabled; } + void SetTunnelWeatherBlendEnabled(bool isEnabled) override; + + unsigned long GetMinuteDuration(); void SetMinuteDuration(unsigned long ulTime); @@ -363,6 +367,7 @@ class CGameSA : public CGame int m_iCheckStatus; bool m_bUnderworldWarp; bool m_isCoronaZTestEnabled{true}; + bool m_isTunnelWeatherBlendEnabled{true}; bool m_areWaterCreaturesEnabled{true}; bool m_isBurnFlippedCarsEnabled{true}; bool m_isFireballDestructEnabled{true}; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index d89255c5487..b07cf64564a 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -6108,6 +6108,9 @@ bool CClientGame::SetWorldSpecialProperty(WorldSpecialProperty property, bool is case WorldSpecialProperty::ROADSIGNSTEXT: g_pGame->SetRoadSignsTextEnabled(isEnabled); return true; + case WorldSpecialProperty::TUNNELWEATHERBLEND: + g_pGame->SetTunnelWeatherBlendEnabled(isEnabled); + return true; } return false; } @@ -6143,6 +6146,8 @@ bool CClientGame::IsWorldSpecialProperty(WorldSpecialProperty property) return g_pGame->IsExtendedWaterCannonsEnabled(); case WorldSpecialProperty::ROADSIGNSTEXT: return g_pGame->IsRoadSignsTextEnabled(); + case WorldSpecialProperty::TUNNELWEATHERBLEND: + return g_pGame->IsTunnelWeatherBlendEnabled(); } return false; } diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index dd95351ed60..b7a78669af5 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -2390,6 +2390,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream) g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::FIREBALLDESTRUCT, wsProps.data2.fireballdestruct); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::ROADSIGNSTEXT, wsProps.data3.roadsignstext); g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::EXTENDEDWATERCANNONS, wsProps.data4.extendedwatercannons); + g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::TUNNELWEATHERBLEND, wsProps.data5.tunnelweatherblend); float fJetpackMaxHeight = 100; if (!bitStream.Read(fJetpackMaxHeight)) diff --git a/Client/sdk/game/CGame.h b/Client/sdk/game/CGame.h index c529609ee56..a1d792813e1 100644 --- a/Client/sdk/game/CGame.h +++ b/Client/sdk/game/CGame.h @@ -225,6 +225,9 @@ class __declspec(novtable) CGame virtual bool IsRoadSignsTextEnabled() const noexcept = 0; virtual void SetRoadSignsTextEnabled(bool isEnabled) = 0; + virtual bool IsTunnelWeatherBlendEnabled() const noexcept = 0; + virtual void SetTunnelWeatherBlendEnabled(bool isEnabled) = 0; + virtual CWeapon* CreateWeapon() = 0; virtual CWeaponStat* CreateWeaponStat(eWeaponType weaponType, eWeaponSkill weaponSkill) = 0; @@ -269,4 +272,5 @@ class __declspec(novtable) CGame virtual void RestoreGameBuildings() = 0; virtual bool SetBuildingPoolSize(size_t size) = 0; + }; diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 75fc4aaae6e..23d527c1749 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -248,6 +248,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti m_WorldSpecialProps[WorldSpecialProperty::FIREBALLDESTRUCT] = true; m_WorldSpecialProps[WorldSpecialProperty::EXTENDEDWATERCANNONS] = true; m_WorldSpecialProps[WorldSpecialProperty::ROADSIGNSTEXT] = true; + m_WorldSpecialProps[WorldSpecialProperty::TUNNELWEATHERBLEND] = 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 965d998905a..e62547b3fb9 100644 --- a/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp @@ -191,6 +191,7 @@ bool CMapInfoPacket::Write(NetBitStreamInterface& BitStream) const wsProps.data2.fireballdestruct = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::FIREBALLDESTRUCT); wsProps.data3.roadsignstext = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::ROADSIGNSTEXT); wsProps.data4.extendedwatercannons = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::EXTENDEDWATERCANNONS); + wsProps.data5.tunnelweatherblend = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::TUNNELWEATHERBLEND); BitStream.Write(&wsProps); } diff --git a/Shared/mods/deathmatch/logic/Enums.cpp b/Shared/mods/deathmatch/logic/Enums.cpp index b51348b9e8c..1e3d0b20031 100644 --- a/Shared/mods/deathmatch/logic/Enums.cpp +++ b/Shared/mods/deathmatch/logic/Enums.cpp @@ -100,6 +100,7 @@ ADD_ENUM(WorldSpecialProperty::BURNFLIPPEDCARS, "burnflippedcars") ADD_ENUM(WorldSpecialProperty::FIREBALLDESTRUCT, "fireballdestruct") ADD_ENUM(WorldSpecialProperty::EXTENDEDWATERCANNONS, "extendedwatercannons") ADD_ENUM(WorldSpecialProperty::ROADSIGNSTEXT, "roadsignstext") +ADD_ENUM(WorldSpecialProperty::TUNNELWEATHERBLEND, "tunnelweatherblend") 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 92646789621..e975d0d9074 100644 --- a/Shared/mods/deathmatch/logic/Enums.h +++ b/Shared/mods/deathmatch/logic/Enums.h @@ -90,6 +90,7 @@ enum class WorldSpecialProperty FIREBALLDESTRUCT, ROADSIGNSTEXT, EXTENDEDWATERCANNONS, + TUNNELWEATHERBLEND, }; DECLARE_ENUM_CLASS(WorldSpecialProperty); diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 636f90d8eb5..1e9b8215b3e 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -2040,6 +2040,10 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure { BITCOUNT4 = 1 }; + enum + { + BITCOUNT5 = 1 + }; bool Read(NetBitStreamInterface& bitStream) { @@ -2059,6 +2063,11 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure else data4.extendedwatercannons = true; + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_TunnelWeatherBlend)) + isOK &= bitStream.ReadBits(reinterpret_cast(&data5), BITCOUNT5); + else + data5.tunnelweatherblend = true; + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // isOK &= bitStream.ReadBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2079,6 +2088,9 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_ExtendedWaterCannons)) bitStream.WriteBits(reinterpret_cast(&data4), BITCOUNT4); + if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_TunnelWeatherBlend)) + bitStream.WriteBits(reinterpret_cast(&data5), BITCOUNT5); + //// Example for adding item: // if (bitStream.Can(eBitStreamVersion::YourProperty)) // bitStream.WriteBits(reinterpret_cast(&data9), BITCOUNT9); @@ -2116,6 +2128,11 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure bool extendedwatercannons : 1; } data4; + struct + { + bool tunnelweatherblend : 1; + } data5; + SWorldSpecialPropertiesStateSync() { // Set default states @@ -2134,6 +2151,7 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure data2.fireballdestruct = true; data3.roadsignstext = true; data4.extendedwatercannons = true; + data5.tunnelweatherblend = true; } }; diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index 9c32320d537..e0de0f91720 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -556,6 +556,11 @@ enum class eBitStreamVersion : unsigned short // 2024-06-16 PedSync_Revision, + // Add "extendedwatercannons" to setWorldSpecialPropertyEnabled + // 2024-06-30 + WorldSpecialProperty_TunnelWeatherBlend, + + // 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,