Skip to content

Commit

Permalink
Add extendedwatercannons special world property (PR #3365)
Browse files Browse the repository at this point in the history
  • Loading branch information
FileEX committed May 31, 2024
1 parent 06d1f1d commit 13a5395
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 0 deletions.
74 changes: 74 additions & 0 deletions Client/game_sa/CGameSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,80 @@ void CGameSA::SetFireballDestructEnabled(bool isEnabled)
m_isFireballDestructEnabled = isEnabled;
}

void CGameSA::SetExtendedWaterCannonsEnabled(bool isEnabled)
{
if (isEnabled == m_isExtendedWaterCannonsEnabled)
return;

// Allocate memory for new bigger array or use default aCannons array
void* aCannons = isEnabled ? malloc(MAX_WATER_CANNONS * SIZE_CWaterCannon) : (void*)ARRAY_aCannons;

int newLimit = isEnabled ? MAX_WATER_CANNONS : NUM_CWaterCannon_DefaultLimit; // default: 3
MemSetFast(aCannons, 0, newLimit * SIZE_CWaterCannon); // clear aCannons array

// Get current limit
int currentLimit = *(int*)NUM_WaterCannon_Limit;

// Get current aCannons array
void* currentACannons = *(void**)ARRAY_aCannons_CurrentPtr;

// Call CWaterCannon destructor
for (int i = 0; i < currentLimit; i++)
{
char* currentCannon = (char*)currentACannons + i * SIZE_CWaterCannon;

((void(__thiscall*)(int, void*, bool))FUNC_CAESoundManager_CancelSoundsOwnedByAudioEntity)(STRUCT_CAESoundManager, currentCannon + NUM_CWaterCannon_Audio_Offset, true); // CAESoundManager::CancelSoundsOwnedByAudioEntity to prevent random crashes from CAESound::UpdateParameters
((void(__thiscall*)(void*))FUNC_CWaterCannon_Destructor)(currentCannon); // CWaterCannon::~CWaterCannon
}

// Call CWaterCannon constructor & CWaterCannon::Init
for (int i = 0; i < newLimit; ++i)
{
char* currentCannon = (char*)aCannons + i * SIZE_CWaterCannon;

((void(__thiscall*)(void*))FUNC_CWaterCannon_Constructor)(currentCannon); // CWaterCannon::CWaterCannon
((void(__thiscall*)(void*))FUNC_CWaterCannon_Init)(currentCannon); // CWaterCannon::Init
}

// Patch references to array
MemPut((void*)0x728C83, aCannons); // CWaterCannons::Init
MemPut((void*)0x728CCB, aCannons); // CWaterCannons::UpdateOne
MemPut((void*)0x728CEB, aCannons); // CWaterCannons::UpdateOne
MemPut((void*)0x728D0D, aCannons); // CWaterCannons::UpdateOne
MemPut((void*)0x728D71, aCannons); // CWaterCannons::UpdateOne
MemPutFast((void*)0x729B33, aCannons); // CWaterCannons::Render
MemPut((void*)0x72A3C5, aCannons); // CWaterCannons::UpdateOne
MemPut((void*)0x855432, aCannons); // 0x855431
MemPut((void*)0x856BFD, aCannons); // 0x856BFC

// CWaterCannons::Init
MemPut<BYTE>(0x728C88, newLimit);

// CWaterCannons::Update
MemPut<BYTE>(0x72A3F2, newLimit);

// CWaterCanons::UpdateOne
MemPut<BYTE>(0x728CD4, newLimit);
MemPut<BYTE>(0x728CF6, newLimit);
MemPut<BYTE>(0x728CFF, newLimit);
MemPut<BYTE>(0x728D62, newLimit);

// CWaterCannons::Render
MemPutFast<BYTE>(0x729B38, newLimit);

// 0x85542A
MemPut<BYTE>(0x85542B, newLimit);

// 0x856BF5
MemPut<BYTE>(0x856BF6, newLimit);

// Free previous allocated memory
if (!isEnabled && currentACannons != nullptr)
free(currentACannons);

m_isExtendedWaterCannonsEnabled = isEnabled;
}

void CGameSA::SetRoadSignsTextEnabled(bool isEnabled)
{
if (isEnabled == m_isRoadSignsTextEnabled)
Expand Down
18 changes: 18 additions & 0 deletions Client/game_sa/CGameSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,20 @@ extern unsigned int OBJECTDYNAMICINFO_MAX; // default: 160
#define CHEAT_NEVERWANTED "neverwanted"
#define CHEAT_HEALTARMORMONEY "healtharmormoney"

#define FUNC_CAESoundManager_CancelSoundsOwnedByAudioEntity 0x4EFCD0
#define STRUCT_CAESoundManager 0xB62CB0
#define FUNC_CWaterCannon_Constructor 0x728B10
#define FUNC_CWaterCannon_Destructor 0x728B30
#define FUNC_CWaterCannon_Init 0x728B40
#define ARRAY_aCannons 0xC80740
#define ARRAY_aCannons_CurrentPtr 0x728C83
#define NUM_WaterCannon_Limit 0x728C88
#define SIZE_CWaterCannon 0x3CC
#define NUM_CWaterCannon_Audio_Offset 0x32C
#define NUM_CWaterCannon_DefaultLimit 3

constexpr int MAX_WATER_CANNONS = 30; // extended CWaterCannon limit, it can be increased

struct SCheatSA
{
BYTE* m_byAddress; // Cheat Address
Expand Down Expand Up @@ -223,6 +237,9 @@ class CGameSA : public CGame
bool IsFireballDestructEnabled() const noexcept override { return m_isFireballDestructEnabled; }
void SetFireballDestructEnabled(bool isEnabled) override;

bool IsExtendedWaterCannonsEnabled() const noexcept override { return m_isExtendedWaterCannonsEnabled; }
void SetExtendedWaterCannonsEnabled(bool isEnabled) override;

bool IsRoadSignsTextEnabled() const noexcept override { return m_isRoadSignsTextEnabled; }
void SetRoadSignsTextEnabled(bool isEnabled) override;

Expand Down Expand Up @@ -348,6 +365,7 @@ class CGameSA : public CGame
bool m_isBurnFlippedCarsEnabled{true};
bool m_isFireballDestructEnabled{true};
bool m_isRoadSignsTextEnabled{true};
bool m_isExtendedWaterCannonsEnabled{false};

static unsigned int& ClumpOffset;

Expand Down
4 changes: 4 additions & 0 deletions Client/mods/deathmatch/logic/CClientGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6091,6 +6091,8 @@ bool CClientGame::SetWorldSpecialProperty(WorldSpecialProperty property, bool is
case WorldSpecialProperty::FIREBALLDESTRUCT:
g_pGame->SetFireballDestructEnabled(isEnabled);
return true;
case WorldSpecialProperty::EXTENDEDWATERCANNONS:
g_pGame->SetExtendedWaterCannonsEnabled(isEnabled);
case WorldSpecialProperty::ROADSIGNSTEXT:
g_pGame->SetRoadSignsTextEnabled(isEnabled);
return true;
Expand Down Expand Up @@ -6125,6 +6127,8 @@ bool CClientGame::IsWorldSpecialProperty(WorldSpecialProperty property)
return g_pGame->IsBurnFlippedCarsEnabled();
case WorldSpecialProperty::FIREBALLDESTRUCT:
return g_pGame->IsFireballDestructEnabled();
case WorldSpecialProperty::EXTENDEDWATERCANNONS:
return g_pGame->IsExtendedWaterCannonsEnabled();
case WorldSpecialProperty::ROADSIGNSTEXT:
return g_pGame->IsRoadSignsTextEnabled();
}
Expand Down
1 change: 1 addition & 0 deletions Client/mods/deathmatch/logic/CPacketHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2388,6 +2388,7 @@ void CPacketHandler::Packet_MapInfo(NetBitStreamInterface& bitStream)
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::BURNFLIPPEDCARS, wsProps.data.burnflippedcars);
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::FIREBALLDESTRUCT, wsProps.data2.fireballdestruct);
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::ROADSIGNSTEXT, wsProps.data3.roadsignstext);
g_pClientGame->SetWorldSpecialProperty(WorldSpecialProperty::EXTENDEDWATERCANNONS, wsProps.data4.extendedwatercannons);

float fJetpackMaxHeight = 100;
if (!bitStream.Read(fJetpackMaxHeight))
Expand Down
3 changes: 3 additions & 0 deletions Client/sdk/game/CGame.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ class __declspec(novtable) CGame
virtual bool IsFireballDestructEnabled() const noexcept = 0;
virtual void SetFireballDestructEnabled(bool isEnabled) = 0;

virtual bool IsExtendedWaterCannonsEnabled() const noexcept = 0;
virtual void SetExtendedWaterCannonsEnabled(bool isEnabled) = 0;

virtual bool IsRoadSignsTextEnabled() const noexcept = 0;
virtual void SetRoadSignsTextEnabled(bool isEnabled) = 0;

Expand Down
1 change: 1 addition & 0 deletions Server/mods/deathmatch/logic/CGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ CGame::CGame() : m_FloodProtect(4, 30000, 30000) // Max of 4 connecti
m_WorldSpecialProps[WorldSpecialProperty::WATERCREATURES] = true;
m_WorldSpecialProps[WorldSpecialProperty::BURNFLIPPEDCARS] = true;
m_WorldSpecialProps[WorldSpecialProperty::FIREBALLDESTRUCT] = true;
m_WorldSpecialProps[WorldSpecialProperty::EXTENDEDWATERCANNONS] = true;
m_WorldSpecialProps[WorldSpecialProperty::ROADSIGNSTEXT] = true;

m_JetpackWeapons[WEAPONTYPE_MICRO_UZI] = true;
Expand Down
1 change: 1 addition & 0 deletions Server/mods/deathmatch/logic/packets/CMapInfoPacket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ bool CMapInfoPacket::Write(NetBitStreamInterface& BitStream) const
wsProps.data.burnflippedcars = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::BURNFLIPPEDCARS);
wsProps.data2.fireballdestruct = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::FIREBALLDESTRUCT);
wsProps.data3.roadsignstext = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::ROADSIGNSTEXT);
wsProps.data4.extendedwatercannons = g_pGame->IsWorldSpecialPropertyEnabled(WorldSpecialProperty::EXTENDEDWATERCANNONS);
BitStream.Write(&wsProps);
}

Expand Down
1 change: 1 addition & 0 deletions Shared/mods/deathmatch/logic/Enums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ ADD_ENUM(WorldSpecialProperty::CORONAZTEST, "coronaztest")
ADD_ENUM(WorldSpecialProperty::WATERCREATURES, "watercreatures")
ADD_ENUM(WorldSpecialProperty::BURNFLIPPEDCARS, "burnflippedcars")
ADD_ENUM(WorldSpecialProperty::FIREBALLDESTRUCT, "fireballdestruct")
ADD_ENUM(WorldSpecialProperty::EXTENDEDWATERCANNONS, "extendedwatercannons")
ADD_ENUM(WorldSpecialProperty::ROADSIGNSTEXT, "roadsignstext")
IMPLEMENT_ENUM_CLASS_END("world-special-property")

Expand Down
1 change: 1 addition & 0 deletions Shared/mods/deathmatch/logic/Enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ enum class WorldSpecialProperty
BURNFLIPPEDCARS,
FIREBALLDESTRUCT,
ROADSIGNSTEXT,
EXTENDEDWATERCANNONS,
};
DECLARE_ENUM_CLASS(WorldSpecialProperty);

Expand Down
17 changes: 17 additions & 0 deletions Shared/sdk/net/SyncStructures.h
Original file line number Diff line number Diff line change
Expand Up @@ -2036,6 +2036,10 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure
{
BITCOUNT3 = 1
};
enum
{
BITCOUNT4 = 1
};

bool Read(NetBitStreamInterface& bitStream)
{
Expand All @@ -2050,6 +2054,10 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure
else
data3.roadsignstext = true;

if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_ExtendedWaterCannons))
isOK &= bitStream.ReadBits(reinterpret_cast<char*>(&data4), BITCOUNT4);
else
data4.extendedwatercannons = true;

//// Example for adding item:
// if (bitStream.Can(eBitStreamVersion::YourProperty))
Expand All @@ -2068,6 +2076,9 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure
if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_RoadSignsText))
bitStream.WriteBits(reinterpret_cast<const char*>(&data3), BITCOUNT3);

if (bitStream.Can(eBitStreamVersion::WorldSpecialProperty_ExtendedWaterCannons))
bitStream.WriteBits(reinterpret_cast<const char*>(&data4), BITCOUNT4);

//// Example for adding item:
// if (bitStream.Can(eBitStreamVersion::YourProperty))
// bitStream.WriteBits(reinterpret_cast<const char*>(&data9), BITCOUNT9);
Expand Down Expand Up @@ -2100,6 +2111,11 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure
bool roadsignstext : 1;
} data3;

struct
{
bool extendedwatercannons : 1;
} data4;

SWorldSpecialPropertiesStateSync()
{
// Set default states
Expand All @@ -2117,6 +2133,7 @@ struct SWorldSpecialPropertiesStateSync : public ISyncStructure
data.burnflippedcars = true;
data2.fireballdestruct = true;
data3.roadsignstext = true;
data4.extendedwatercannons = true;
}
};

Expand Down
4 changes: 4 additions & 0 deletions Shared/sdk/net/bitstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,10 @@ enum class eBitStreamVersion : unsigned short
// 2024-05-17
WorldSpecialProperty_RoadSignsText,

// Add "extendedwatercannons" to setWorldSpecialPropertyEnabled
// 2024-05-23
WorldSpecialProperty_ExtendedWaterCannons,

// 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,
Expand Down

0 comments on commit 13a5395

Please sign in to comment.