diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 5637800213..85c5e0d51e 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -3333,14 +3333,20 @@ void CClientPed::SetTargetRotation(float fRotation) SetCurrentRotation(fRotation); } -void CClientPed::SetTargetRotation(unsigned long ulDelay, float fRotation, float fCameraRotation) +void CClientPed::SetTargetRotation(unsigned long ulDelay, std::optional rotation, std::optional cameraRotation) { m_ulBeginRotationTime = CClientTime::GetTime(); m_ulEndRotationTime = m_ulBeginRotationTime + ulDelay; - m_fBeginRotation = (m_pPlayerPed) ? m_pPlayerPed->GetCurrentRotation() : m_fCurrentRotation; - m_fTargetRotationA = fRotation; - m_fBeginCameraRotation = GetCameraRotation(); - m_fTargetCameraRotation = fCameraRotation; + if (rotation.has_value()) + { + m_fBeginRotation = (m_pPlayerPed) ? m_pPlayerPed->GetCurrentRotation() : m_fCurrentRotation; + m_fTargetRotationA = rotation.value(); + } + if (cameraRotation.has_value()) + { + m_fBeginCameraRotation = GetCameraRotation(); + m_fTargetCameraRotation = cameraRotation.value(); + } } // Temporary diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index 576c967ad4..65d84a0a4a 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -105,6 +105,7 @@ struct SLastSyncedPedData CVector vPosition; CVector vVelocity; float fRotation; + float cameraRotation{}; bool bOnFire; bool bIsInWater; bool isReloadingWeapon; @@ -205,7 +206,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule float GetCurrentRotation(); void SetCurrentRotation(float fRotation, bool bIncludeTarget = true); void SetTargetRotation(float fRotation); - void SetTargetRotation(unsigned long ulDelay, float fRotation, float fCameraRotation); + void SetTargetRotation(unsigned long ulDelay, std::optional rotation, std::optional cameraRotation); float GetCameraRotation(); void SetCameraRotation(float fRotation); diff --git a/Client/mods/deathmatch/logic/CPedSync.cpp b/Client/mods/deathmatch/logic/CPedSync.cpp index 25ee0b5142..c1252ed7a6 100644 --- a/Client/mods/deathmatch/logic/CPedSync.cpp +++ b/Client/mods/deathmatch/logic/CPedSync.cpp @@ -124,6 +124,14 @@ void CPedSync::Packet_PedStartSync(NetBitStreamInterface& BitStream) float fHealth, fArmor; BitStream.Read(fHealth); BitStream.Read(fArmor); + + if (BitStream.Can(eBitStreamVersion::PedSync_CameraRotation)) + { + float cameraRotation{}; + BitStream.Read(cameraRotation); + + pPed->SetCameraRotation(cameraRotation); + } // Set data pPed->SetPosition(vecPosition); @@ -179,10 +187,15 @@ void CPedSync::Packet_PedSync(NetBitStreamInterface& BitStream) unsigned char ucFlags = 0; BitStream.Read(ucFlags); + std::uint8_t flags2{}; + if (BitStream.Can(eBitStreamVersion::PedSync_CameraRotation)) + BitStream.Read(flags2); + CVector vecPosition{ CVector::NoInit{} }, vecMoveSpeed{ CVector::NoInit{} }; float fRotation, fHealth, fArmor; bool bOnFire; bool bIsInWater; + float cameraRotation; if (BitStream.Can(eBitStreamVersion::PedSync_Revision)) { @@ -231,6 +244,13 @@ void CPedSync::Packet_PedSync(NetBitStreamInterface& BitStream) if (ucFlags & 0x10) BitStream.Read(fArmor); + if (flags2 & 0x01) + { + SCameraRotationSync camRotation; + BitStream.Read(&camRotation); + cameraRotation = camRotation.data.fRotation; + } + // And the burning state if (BitStream.Version() >= 0x04E && ucFlags & 0x20) BitStream.ReadBit(bOnFire); @@ -246,13 +266,15 @@ void CPedSync::Packet_PedSync(NetBitStreamInterface& BitStream) if (ucFlags & 0x01) pPed->SetTargetPosition(vecPosition, PED_SYNC_RATE); if (ucFlags & 0x02) - pPed->SetTargetRotation(PED_SYNC_RATE, fRotation, 0.0f); + pPed->SetTargetRotation(PED_SYNC_RATE, fRotation, std::nullopt); if (ucFlags & 0x04) pPed->SetMoveSpeed(vecMoveSpeed); if (ucFlags & 0x08) pPed->LockHealth(fHealth); if (ucFlags & 0x10) pPed->LockArmor(fArmor); + if (flags2 & 0x01) + pPed->SetTargetRotation(PED_SYNC_RATE, std::nullopt, cameraRotation); if (BitStream.Version() >= 0x04E && ucFlags & 0x20) pPed->SetOnFire(bOnFire); if (BitStream.Version() >= 0x55 && ucFlags & 0x40) @@ -312,8 +334,12 @@ void CPedSync::WritePedInformation(NetBitStreamInterface* pBitStream, CClientPed if (pPed->HasSyncedAnim() && (!pPed->IsRunningAnimation() || pPed->m_animationOverridedByClient)) ucFlags |= 0x80; + std::uint8_t flags2{}; + if (!IsNearlyEqual(pPed->GetCameraRotation(), pPed->m_LastSyncedData->cameraRotation) && pBitStream->Can(eBitStreamVersion::PedSync_CameraRotation)) + flags2 |= 0x01; + // Do we really have to sync this ped? - if (ucFlags == 0) + if (ucFlags == 0 && flags2 == 0) return; // Write the ped id @@ -325,6 +351,10 @@ void CPedSync::WritePedInformation(NetBitStreamInterface* pBitStream, CClientPed // Write flags pBitStream->Write(ucFlags); + // Write flags 2 + if (pBitStream->Can(eBitStreamVersion::PedSync_CameraRotation)) + pBitStream->Write(flags2); + // Write position if needed if (ucFlags & 0x01) { @@ -389,6 +419,14 @@ void CPedSync::WritePedInformation(NetBitStreamInterface* pBitStream, CClientPed pPed->m_LastSyncedData->fArmour = pPed->GetArmor(); } + if (flags2 & 0x01) + { + SCameraRotationSync camRotation; + camRotation.data.fRotation = pPed->GetCameraRotation(); + pBitStream->Write(&camRotation); + pPed->m_LastSyncedData->cameraRotation = camRotation.data.fRotation; + } + if (ucFlags & 0x20 && pBitStream->Version() >= 0x04E) { pBitStream->WriteBit(pPed->IsOnFire()); diff --git a/Server/mods/deathmatch/logic/CPed.h b/Server/mods/deathmatch/logic/CPed.h index 063744484b..8feba67070 100644 --- a/Server/mods/deathmatch/logic/CPed.h +++ b/Server/mods/deathmatch/logic/CPed.h @@ -236,6 +236,9 @@ class CPed : public CElement float GetRotation() { return m_fRotation; } void SetRotation(float fRotation) { m_fRotation = fRotation; } + float GetCameraRotation() const { return m_cameraRotation; } + void SetCameraRotation(float fRotation) { m_cameraRotation = fRotation; } + void GetRotation(CVector& vecRotation); void GetMatrix(CMatrix& matrix); void SetMatrix(const CMatrix& matrix); @@ -346,6 +349,7 @@ class CPed : public CElement bool m_reloadingWeapon{}; CVehicle* m_pJackingVehicle; SPlayerAnimData m_animData{}; + float m_cameraRotation{}; CVehicle* m_pVehicle; unsigned int m_uiVehicleSeat; diff --git a/Server/mods/deathmatch/logic/CPedSync.cpp b/Server/mods/deathmatch/logic/CPedSync.cpp index 1880ea6dff..60166f7a3a 100644 --- a/Server/mods/deathmatch/logic/CPedSync.cpp +++ b/Server/mods/deathmatch/logic/CPedSync.cpp @@ -277,6 +277,9 @@ void CPedSync::Packet_PedSync(CPedSyncPacket& Packet) if (Data.ucFlags & 0x10) pPed->SetArmor(Data.fArmor); + if (Data.flags2 & 0x01) + pPed->SetCameraRotation(Data.cameraRotation); + if (Data.ucFlags & 0x20) pPed->SetOnFire(Data.bOnFire); diff --git a/Server/mods/deathmatch/logic/packets/CPedStartSyncPacket.cpp b/Server/mods/deathmatch/logic/packets/CPedStartSyncPacket.cpp index fa7c87d02f..4516a10d5d 100644 --- a/Server/mods/deathmatch/logic/packets/CPedStartSyncPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CPedStartSyncPacket.cpp @@ -37,5 +37,8 @@ bool CPedStartSyncPacket::Write(NetBitStreamInterface& BitStream) const BitStream.Write(m_pPed->GetHealth()); BitStream.Write(m_pPed->GetArmor()); + if (BitStream.Can(eBitStreamVersion::PedSync_CameraRotation)) + BitStream.Write(m_pPed->GetCameraRotation()); + return true; } diff --git a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp index 32e2d84272..34ad0d7a78 100644 --- a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp @@ -38,6 +38,14 @@ bool CPedSyncPacket::Read(NetBitStreamInterface& BitStream) return false; Data.ucFlags = ucFlags; + if (BitStream.Can(eBitStreamVersion::PedSync_CameraRotation)) + { + if (!BitStream.Read(Data.flags2)) + return false; + } + else + Data.flags2 = 0; + // Did we recieve position? if (ucFlags & 0x01) { @@ -57,6 +65,14 @@ bool CPedSyncPacket::Read(NetBitStreamInterface& BitStream) return false; } + if (Data.flags2 & 0x01) + { + SCameraRotationSync camRotation; + if (!BitStream.Read(&camRotation)) + return false; + Data.cameraRotation = camRotation.data.fRotation; + } + // On Fire if (ucFlags & 0x20) { @@ -100,6 +116,9 @@ bool CPedSyncPacket::Write(NetBitStreamInterface& BitStream) const BitStream.Write(Data.ucFlags); + if (BitStream.Can(eBitStreamVersion::PedSync_CameraRotation)) + BitStream.Write(Data.flags2); + if (BitStream.Can(eBitStreamVersion::PedSync_Revision)) { // Position and rotation @@ -140,6 +159,14 @@ bool CPedSyncPacket::Write(NetBitStreamInterface& BitStream) const BitStream.Write(Data.fHealth); if (Data.ucFlags & 0x10) BitStream.Write(Data.fArmor); + + if (Data.flags2 & 0x01) + { + SCameraRotationSync camRotation; + camRotation.data.fRotation = Data.cameraRotation; + BitStream.Write(&camRotation); + } + if (Data.ucFlags & 0x20) BitStream.WriteBit(Data.bOnFire); if (Data.ucFlags & 0x60 && BitStream.Can(eBitStreamVersion::IsPedReloadingWeapon)) diff --git a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h index ae18d288bb..0dcb05edc7 100644 --- a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h +++ b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h @@ -23,6 +23,7 @@ class CPedSyncPacket final : public CPacket { ElementID ID; unsigned char ucFlags; + std::uint8_t flags2; unsigned char ucSyncTimeContext; SPositionSync position; SPedRotationSync rotation; @@ -32,6 +33,7 @@ class CPedSyncPacket final : public CPacket bool bOnFire; bool bIsInWater; bool isReloadingWeapon; + float cameraRotation; bool ReadSpatialData(NetBitStreamInterface& BitStream); // Backward compatibility diff --git a/Shared/sdk/SharedUtil.Math.h b/Shared/sdk/SharedUtil.Math.h index 73c7c532df..1f81000fca 100644 --- a/Shared/sdk/SharedUtil.Math.h +++ b/Shared/sdk/SharedUtil.Math.h @@ -113,4 +113,9 @@ namespace SharedUtil { return std::uniform_real_distribution{minRange, maxRange}(randomEngine); } + + inline bool IsNearlyEqual(float a, float b, float epsilon = std::numeric_limits().epsilon()) noexcept + { + return std::fabs(a - b) <= epsilon; + } } // namespace SharedUtil diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index f69c7cc0f7..f0a61b6666 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -608,6 +608,10 @@ enum class eBitStreamVersion : unsigned short // 2025-01-10 WorldSpecialProperty_FlyingComponents, + // Ped's camera synchronization + // 2025-01-29 + PedSync_CameraRotation, + // 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,