diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index b8a89c11094..8cfc337c44e 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -4412,6 +4412,21 @@ bool CClientGame::ApplyPedDamageFromGame(eWeaponType weaponUsed, float fDamage, } pDamagedPed->GetGamePlayer()->SetHealth(fPreviousHealth); pDamagedPed->GetGamePlayer()->SetArmor(fPreviousArmor); + + if (IS_PLAYER(pDamagedPed) && pDamagedPed->IsLocalPlayer() && g_pNet->CanServerBitStream(eBitStreamVersion::PlayerDamageCancelled)) + { + if (auto* stream = g_pNet->AllocateNetBitStream()) + { + stream->Write(pInflictingEntity ? pInflictingEntity->GetID() : 0); + stream->Write(static_cast(weaponUsed)); + stream->Write(static_cast(hitZone)); + stream->Write(fDamage); + + g_pNet->SendPacket(PACKET_ID_PLAYER_DAMAGE_CANCELLED, stream, PACKET_PRIORITY_HIGH, PACKET_RELIABILITY_RELIABLE_ORDERED); + g_pNet->DeallocateNetBitStream(stream); + } + } + return false; } diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index 0d684789dfd..d276919b1ea 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -59,6 +59,7 @@ #include "packets/CPlayerListPacket.h" #include "packets/CPlayerClothesPacket.h" #include "packets/CPlayerWorldSpecialPropertyPacket.h" +#include "packets/CPlayerDamageCancelledPacket.h" #include "packets/CServerInfoSyncPacket.h" #include "packets/CLuaPacket.h" #include "../utils/COpenPortsTester.h" @@ -1322,6 +1323,12 @@ bool CGame::ProcessPacket(CPacket& Packet) return true; } + case PACKET_ID_PLAYER_DAMAGE_CANCELLED: + { + Packet_PlayerDamageCancelled(static_cast(Packet)); + return true; + } + default: break; } @@ -1642,6 +1649,7 @@ void CGame::AddBuiltInEvents() m_Events.AddEvent("onPlayerChangesProtectedData", "element, key, value", nullptr, false); m_Events.AddEvent("onPlayerChangesWorldSpecialProperty", "property, enabled", nullptr, false); m_Events.AddEvent("onPlayerTeleport", "previousX, previousY, previousZ, currentX, currentY, currentZ", nullptr, false); + m_Events.AddEvent("onPlayerDamageCancelled", "attacker, cause, bodypart, loss", nullptr, false); // Ped events m_Events.AddEvent("onPedVehicleEnter", "vehicle, seat, jacked", NULL, false); @@ -4307,6 +4315,32 @@ void CGame::Packet_PlayerWorldSpecialProperty(CPlayerWorldSpecialPropertyPacket& player->CallEvent("onPlayerChangesWorldSpecialProperty", arguments, nullptr); } +void CGame::Packet_PlayerDamageCancelled(CPlayerDamageCancelledPacket& packet) +{ + CPlayer* player = packet.GetSourcePlayer(); + + if (!player) + return; + + const std::uint32_t attacker = packet.GetAttacker(); + const std::uint8_t cause = packet.GetCause(); + const std::uint8_t bodypart = packet.GetBodypart(); + const float loss = packet.GetLoss(); + + CLuaArguments arguments; + + if (GetElementFromId(attacker)) + arguments.PushElement(GetElementFromId(attacker)); + else + arguments.PushNil(); + + arguments.PushNumber(cause); + arguments.PushNumber(bodypart); + arguments.PushNumber(loss); + + player->CallEvent("onPlayerDamageCancelled", arguments, nullptr); +} + void CGame::Packet_PlayerModInfo(CPlayerModInfoPacket& Packet) { CPlayer* pPlayer = Packet.GetSourcePlayer(); diff --git a/Server/mods/deathmatch/logic/CGame.h b/Server/mods/deathmatch/logic/CGame.h index c4344a81805..a0e624b835d 100644 --- a/Server/mods/deathmatch/logic/CGame.h +++ b/Server/mods/deathmatch/logic/CGame.h @@ -519,6 +519,7 @@ class CGame void Packet_PlayerNetworkStatus(class CPlayerNetworkStatusPacket& Packet); void Packet_PlayerResourceStart(class CPlayerResourceStartPacket& Packet); void Packet_PlayerWorldSpecialProperty(class CPlayerWorldSpecialPropertyPacket& packet) noexcept; + void Packet_PlayerDamageCancelled(class CPlayerDamageCancelledPacket& packet); static void PlayerCompleteConnect(CPlayer* pPlayer); diff --git a/Server/mods/deathmatch/logic/CPacketTranslator.cpp b/Server/mods/deathmatch/logic/CPacketTranslator.cpp index 3cf0fa09653..428c16f6883 100644 --- a/Server/mods/deathmatch/logic/CPacketTranslator.cpp +++ b/Server/mods/deathmatch/logic/CPacketTranslator.cpp @@ -49,6 +49,7 @@ #include "packets/CPlayerNetworkStatusPacket.h" #include "packets/CPlayerResourceStartPacket.h" #include "packets/CPlayerWorldSpecialPropertyPacket.h" +#include "packets/CPlayerDamageCancelledPacket.h" CPacketTranslator::CPacketTranslator(CPlayerManager* pPlayerManager) { @@ -217,6 +218,10 @@ CPacket* CPacketTranslator::Translate(const NetServerPlayerID& Socket, ePacketID pTemp = new CPlayerWorldSpecialPropertyPacket; break; + case PACKET_ID_PLAYER_DAMAGE_CANCELLED: + pTemp = new CPlayerDamageCancelledPacket; + break; + default: break; } diff --git a/Server/mods/deathmatch/logic/packets/CPlayerDamageCancelledPacket.cpp b/Server/mods/deathmatch/logic/packets/CPlayerDamageCancelledPacket.cpp new file mode 100644 index 00000000000..7f8c69087ff --- /dev/null +++ b/Server/mods/deathmatch/logic/packets/CPlayerDamageCancelledPacket.cpp @@ -0,0 +1,22 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: mods/deathmatch/logic/packets/CPlayerDamageCancelledPacket.cpp + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" +#include "CPlayerDamageCancelledPacket.h" + +bool CPlayerDamageCancelledPacket::Read(NetBitStreamInterface& stream) +{ + stream.Read(m_attacker); + stream.Read(m_cause); + stream.Read(m_bodypart); + stream.Read(m_loss); + + return true; +} diff --git a/Server/mods/deathmatch/logic/packets/CPlayerDamageCancelledPacket.h b/Server/mods/deathmatch/logic/packets/CPlayerDamageCancelledPacket.h new file mode 100644 index 00000000000..a5a2279d555 --- /dev/null +++ b/Server/mods/deathmatch/logic/packets/CPlayerDamageCancelledPacket.h @@ -0,0 +1,38 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: mods/deathmatch/logic/packets/CPlayerDamageCancelledPacket.h + * + * Multi Theft Auto is available from https://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include +#include +#include "CPacket.h" + +class CPlayerDamageCancelledPacket final : public CPacket +{ +public: + CPlayerDamageCancelledPacket() noexcept {} + + ePacketID GetPacketID() const noexcept { return PACKET_ID_PLAYER_DAMAGE_CANCELLED; } + unsigned long GetFlags() const noexcept { return PACKET_HIGH_PRIORITY | PACKET_RELIABLE | PACKET_SEQUENCED; } + virtual ePacketOrdering GetPacketOrdering() const noexcept { return PACKET_ORDERING_DEFAULT; } + + bool Read(NetBitStreamInterface& stream); + + std::uint32_t GetAttacker() const noexcept { return m_attacker; } + std::uint8_t GetCause() const noexcept { return m_cause; } + std::uint8_t GetBodypart() const noexcept { return m_bodypart; } + float GetLoss() const noexcept { return m_loss; } + +private: + std::uint32_t m_attacker; + std::uint8_t m_cause; + std::uint8_t m_bodypart; + float m_loss; +}; diff --git a/Shared/mods/deathmatch/logic/Enums.cpp b/Shared/mods/deathmatch/logic/Enums.cpp index 28f0ffe7a20..f92fb78b098 100644 --- a/Shared/mods/deathmatch/logic/Enums.cpp +++ b/Shared/mods/deathmatch/logic/Enums.cpp @@ -216,4 +216,5 @@ ADD_ENUM1(PACKET_ID_SERVER_INFO_SYNC) ADD_ENUM1(PACKET_ID_DISCORD_JOIN) ADD_ENUM1(PACKET_ID_PLAYER_RESOURCE_START) ADD_ENUM1(PACKET_ID_PLAYER_WORLD_SPECIAL_PROPERTY) +ADD_ENUM1(PACKET_ID_PLAYER_DAMAGE_CANCELLED) IMPLEMENT_ENUM_END("ePacketID") diff --git a/Shared/sdk/net/Packets.h b/Shared/sdk/net/Packets.h index 411af7cb88a..54eab8eff35 100644 --- a/Shared/sdk/net/Packets.h +++ b/Shared/sdk/net/Packets.h @@ -151,5 +151,6 @@ enum ePacketID PACKET_ID_SERVER_INFO_SYNC, PACKET_ID_DISCORD_JOIN, PACKET_ID_PLAYER_RESOURCE_START, - PACKET_ID_PLAYER_WORLD_SPECIAL_PROPERTY + PACKET_ID_PLAYER_WORLD_SPECIAL_PROPERTY, + PACKET_ID_PLAYER_DAMAGE_CANCELLED }; diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index f0a61b66667..47c500fca6c 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -612,6 +612,10 @@ enum class eBitStreamVersion : unsigned short // 2025-01-29 PedSync_CameraRotation, + // Add onPlayerDamageCancelled + // 2025-02-21 + PlayerDamageCancelled, + // 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,