diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index b769ccd953..91a1901056 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -3085,6 +3085,7 @@ void CClientGame::UpdateMimics() bool bSunbathing = m_pLocalPlayer->IsSunbathing(); bool bDoingDriveby = m_pLocalPlayer->IsDoingGangDriveby(); bool bStealthAiming = m_pLocalPlayer->IsStealthAiming(); + bool reloadingWeapon = m_pLocalPlayer->IsReloadingWeapon(); // Is the current weapon goggles (44 or 45) or a camera (43), or a detonator (40), don't apply the fire key if (weaponSlot == 11 || weaponSlot == 12 || ucWeaponType == 43) @@ -3143,6 +3144,9 @@ void CClientGame::UpdateMimics() pMimic->SetDoingGangDriveby(bDoingDriveby); pMimic->SetStealthAiming(bStealthAiming); + if (reloadingWeapon) + pMimic->ReloadWeapon(); + Controller.ShockButtonL = 0; if (m_bMimicLag) diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 30554d60b6..c849a0b8a7 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -6008,51 +6008,42 @@ void CClientPed::SetSpeechEnabled(bool bEnabled) m_bSpeechEnabled = bEnabled; } -bool CClientPed::CanReloadWeapon() +bool CClientPed::CanReloadWeapon() noexcept { - unsigned long ulNow = CClientTime::GetTime(); - CControllerState Current; - GetControllerState(Current); - int iWeaponType = GetWeapon()->GetType(); - // Hes not Aiming, ducked or if he is ducked he is not currently moving and he hasn't moved while crouching in the last 300ms (sometimes the crouching move - // anim runs over and kills the reload animation) - if (Current.RightShoulder1 == false && (!IsDucked() || (Current.LeftStickX == 0 && Current.LeftStickY == 0)) && - ulNow - m_ulLastTimeMovedWhileCrouched > 300) - { - // Ignore certain weapons (anything without clip ammo) - if (iWeaponType >= WEAPONTYPE_PISTOL && iWeaponType <= WEAPONTYPE_TEC9 && iWeaponType != WEAPONTYPE_SHOTGUN) - { - return true; - } - } - return false; + const auto time = CClientTime::GetTime(); + CControllerState state; + GetControllerState(state); + + const auto weapon = GetWeapon()->GetType(); + + if (state.RightShoulder1 || (IsDucked() && (state.LeftStickX != 0 || state.LeftStickY != 0)) || time - m_ulLastTimeMovedWhileCrouched <= 300) + return false; + + if (weapon < WEAPONTYPE_PISTOL || weapon > WEAPONTYPE_TEC9 || weapon == WEAPONTYPE_SHOTGUN) + return false; + + return true; } -bool CClientPed::ReloadWeapon() +bool CClientPed::ReloadWeapon() noexcept { - if (m_pTaskManager) - { - CWeapon* pWeapon = GetWeapon(); - CTask* pTask = m_pTaskManager->GetTaskSecondary(TASK_SECONDARY_ATTACK); + if (!m_pTaskManager) + return false; - // Check his control states for anything that can cancel the anim instantly and make sure he is not firing - if (CanReloadWeapon() && (!pTask || (pTask && pTask->GetTaskType() != TASK_SIMPLE_USE_GUN))) - { - // Play anim + reload - pWeapon->SetState(WEAPONSTATE_RELOADING); + auto* weapon = GetWeapon(); + auto* task = m_pTaskManager->GetTaskSecondary(TASK_SECONDARY_ATTACK); - return true; - } - } - return false; + if (!CanReloadWeapon() || (task && task->GetTaskType() == TASK_SIMPLE_USE_GUN)) + return false; + + weapon->SetState(WEAPONSTATE_RELOADING); + return true; } -bool CClientPed::IsReloadingWeapon() +bool CClientPed::IsReloadingWeapon() noexcept { - if (CWeapon* weapon = GetWeapon(); weapon != nullptr) - return weapon->GetState() == WEAPONSTATE_RELOADING; - else - return false; + auto* weapon = GetWeapon(); + return weapon && weapon->GetState() == WEAPONSTATE_RELOADING; } bool CClientPed::ShouldBeStealthAiming() diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index 4286d64e91..f76f69d17a 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -107,6 +107,7 @@ struct SLastSyncedPedData float fRotation; bool bOnFire; bool bIsInWater; + bool isReloadingWeapon; }; struct SRestoreWeaponItem @@ -495,9 +496,9 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule bool GetBulletImpactData(CClientEntity** ppVictim = 0, CVector* pvecHitPosition = 0); void ClearBulletImpactData() { m_bBulletImpactData = false; } - bool CanReloadWeapon(); - bool ReloadWeapon(); - bool IsReloadingWeapon(); + bool CanReloadWeapon() noexcept; + bool ReloadWeapon() noexcept; + bool IsReloadingWeapon() noexcept; bool ShouldBeStealthAiming(); bool IsStealthAiming() { return m_bStealthAiming; } diff --git a/Client/mods/deathmatch/logic/CNetAPI.cpp b/Client/mods/deathmatch/logic/CNetAPI.cpp index ee4b9727b1..3927c3af4d 100644 --- a/Client/mods/deathmatch/logic/CNetAPI.cpp +++ b/Client/mods/deathmatch/logic/CNetAPI.cpp @@ -1118,6 +1118,9 @@ void CNetAPI::WritePlayerPuresync(CClientPlayer* pPlayerModel, NetBitStreamInter flags.data.bSyncingVelocity = (!flags.data.bIsOnGround || (pPlayerModel->GetPlayerSyncCount() % 4) == 0); flags.data.bStealthAiming = (pPlayerModel->IsStealthAiming() == true); + if (BitStream.Can(eBitStreamVersion::IsPedReloadingWeapon)) + flags.data2.isReloadingWeapon = (pPlayerModel->IsReloadingWeapon() == true); + if (pPlayerWeapon->GetSlot() > 15) flags.data.bHasAWeapon = false; diff --git a/Client/mods/deathmatch/logic/CPedSync.cpp b/Client/mods/deathmatch/logic/CPedSync.cpp index a0e3b6b9ca..25ee0b5142 100644 --- a/Client/mods/deathmatch/logic/CPedSync.cpp +++ b/Client/mods/deathmatch/logic/CPedSync.cpp @@ -307,6 +307,8 @@ void CPedSync::WritePedInformation(NetBitStreamInterface* pBitStream, CClientPed ucFlags |= 0x20; if (pPed->IsInWater() != pPed->m_LastSyncedData->bIsInWater) ucFlags |= 0x40; + if (pPed->IsReloadingWeapon() != pPed->m_LastSyncedData->isReloadingWeapon && pBitStream->Can(eBitStreamVersion::IsPedReloadingWeapon)) + ucFlags |= 0x60; if (pPed->HasSyncedAnim() && (!pPed->IsRunningAnimation() || pPed->m_animationOverridedByClient)) ucFlags |= 0x80; @@ -380,6 +382,7 @@ void CPedSync::WritePedInformation(NetBitStreamInterface* pBitStream, CClientPed pBitStream->Write(pPed->GetHealth()); pPed->m_LastSyncedData->fHealth = pPed->GetHealth(); } + if (ucFlags & 0x10) { pBitStream->Write(pPed->GetArmor()); @@ -398,6 +401,14 @@ void CPedSync::WritePedInformation(NetBitStreamInterface* pBitStream, CClientPed pPed->m_LastSyncedData->bIsInWater = pPed->IsInWater(); } + if (ucFlags & 0x60 && pBitStream->Can(eBitStreamVersion::IsPedReloadingWeapon)) + { + bool isReloadingWeapon = pPed->IsReloadingWeapon(); + + pBitStream->WriteBit(isReloadingWeapon); + pPed->m_LastSyncedData->isReloadingWeapon = isReloadingWeapon; + } + // The animation has been overwritten or interrupted by the client if (ucFlags & 0x80 && pBitStream->Can(eBitStreamVersion::AnimationsSync)) { diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index 8aa0d5d1f6..34040db19e 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -114,7 +114,7 @@ void CLuaPedDefs::LoadFunctions() {"isPedChoking", IsPedChoking}, {"isPedDucked", IsPedDucked}, {"isPedDead", IsPedDead}, - {"isPedReloadingWeapon", IsPedReloadingWeapon}, + {"isPedReloadingWeapon", ArgumentParserWarn}, {"killPedTask", ArgumentParser}, }; @@ -1233,25 +1233,11 @@ int CLuaPedDefs::GivePedWeapon(lua_State* luaVM) return 1; } -int CLuaPedDefs::IsPedReloadingWeapon(lua_State* luaVM) +bool CLuaPedDefs::IsPedReloadingWeapon(CClientPed* const ped) noexcept { - // Verify the argument - CClientPed* pPed = NULL; - CScriptArgReader argStream(luaVM); - argStream.ReadUserData(pPed); - - if (!argStream.HasErrors()) - { - lua_pushboolean(luaVM, pPed->IsReloadingWeapon()); - return 1; - } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); - - lua_pushboolean(luaVM, false); - return 1; + return ped->IsReloadingWeapon(); } - + int CLuaPedDefs::GetPedClothes(lua_State* luaVM) { // Verify the argument diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index 76b9771332..0d9cc3500c 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -93,7 +93,7 @@ class CLuaPedDefs : public CLuaDefs static bool SetPedArmor(CClientPed* const ped, const float armor); LUA_DECLARE(SetPedWeaponSlot); LUA_DECLARE(GivePedWeapon); - LUA_DECLARE(IsPedReloadingWeapon); + static bool IsPedReloadingWeapon(CClientPed* const ped) noexcept; LUA_DECLARE(AddPedClothes); LUA_DECLARE(RemovePedClothes); LUA_DECLARE(SetPedControlState); diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index fe8d5397fe..a92857f103 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -1610,6 +1610,8 @@ void CGame::AddBuiltInEvents() m_Events.AddEvent("onPlayerTarget", "target", NULL, false); m_Events.AddEvent("onPlayerWasted", "ammo, killer, weapon, bodypart, isStealth, animGroup, animID", nullptr, false); m_Events.AddEvent("onPlayerWeaponSwitch", "previous, current", NULL, false); + m_Events.AddEvent("onPlayerWeaponFire", "weapon, endX, endY, endZ, hitElement, startX, startY, startZ", nullptr, false); + m_Events.AddEvent("onPlayerWeaponReload", "weapon, clip, ammo", nullptr, false); m_Events.AddEvent("onPlayerMarkerHit", "marker, matchingDimension", NULL, false); m_Events.AddEvent("onPlayerMarkerLeave", "marker, matchingDimension", NULL, false); m_Events.AddEvent("onPlayerPickupHit", "pickup", NULL, false); @@ -1644,6 +1646,7 @@ void CGame::AddBuiltInEvents() m_Events.AddEvent("onPedVehicleExit", "vehicle, reason, jacker", NULL, false); m_Events.AddEvent("onPedWasted", "ammo, killer, weapon, bodypart, isStealth, animGroup, animID", nullptr, false); m_Events.AddEvent("onPedWeaponSwitch", "previous, current", NULL, false); + m_Events.AddEvent("onPedWeaponReload", "weapon, clip, ammo", nullptr, false); m_Events.AddEvent("onPedDamage", "loss", NULL, false); // Element events @@ -1699,7 +1702,6 @@ void CGame::AddBuiltInEvents() // Weapon events m_Events.AddEvent("onWeaponFire", "", NULL, false); - m_Events.AddEvent("onPlayerWeaponFire", "weapon, endX, endY, endZ, hitElement, startX, startY, startZ", NULL, false); } void CGame::ProcessTrafficLights(long long llCurrentTime) diff --git a/Server/mods/deathmatch/logic/CPed.h b/Server/mods/deathmatch/logic/CPed.h index daa5c8e0c0..f50aed2ae4 100644 --- a/Server/mods/deathmatch/logic/CPed.h +++ b/Server/mods/deathmatch/logic/CPed.h @@ -286,6 +286,9 @@ class CPed : public CElement bool IsStealthAiming() { return m_bStealthAiming; } void SetStealthAiming(bool bAiming) { m_bStealthAiming = bAiming; } + bool IsReloadingWeapon() const noexcept { return m_reloadingWeapon; } + void SetReloadingWeapon(bool state) noexcept { m_reloadingWeapon = state; } + bool GetCollisionEnabled() { return m_bCollisionsEnabled; } void SetCollisionEnabled(bool bCollisionEnabled) { m_bCollisionsEnabled = bCollisionEnabled; } @@ -340,6 +343,7 @@ class CPed : public CElement bool m_bHeadless; bool m_bFrozen; bool m_bStealthAiming; + bool m_reloadingWeapon{}; CVehicle* m_pJackingVehicle; SPlayerAnimData m_animData{}; diff --git a/Server/mods/deathmatch/logic/CPedSync.cpp b/Server/mods/deathmatch/logic/CPedSync.cpp index f911ab027c..1880ea6dff 100644 --- a/Server/mods/deathmatch/logic/CPedSync.cpp +++ b/Server/mods/deathmatch/logic/CPedSync.cpp @@ -283,6 +283,11 @@ void CPedSync::Packet_PedSync(CPedSyncPacket& Packet) if (Data.ucFlags & 0x40) pPed->SetInWater(Data.bIsInWater); + if (Data.ucFlags & 0x60) + { + pPed->SetReloadingWeapon(Data.isReloadingWeapon); + } + if (Data.ucFlags & 0x80) pPed->SetAnimationData({}); diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index e80745b184..bd58cd8488 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -4508,19 +4508,41 @@ bool CStaticFunctionDefinitions::SetPedFrozen(CElement* pElement, bool bIsFrozen } return false; } -bool CStaticFunctionDefinitions::reloadPedWeapon(CElement* pElement) -{ + +bool CStaticFunctionDefinitions::ReloadPedWeapon(CElement* pElement) noexcept { assert(pElement); - RUN_CHILDREN(reloadPedWeapon(*iter)) + RUN_CHILDREN(ReloadPedWeapon(*iter)) - if (IS_PED(pElement)) - { - CPed* pPed = static_cast(pElement); - CBitStream BitStream; - m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pPed, RELOAD_PED_WEAPON, *BitStream.pBitStream)); - return true; - } - return false; + if (!IS_PED(pElement)) + return false; + + CPed* ped = static_cast(pElement); + + bool result; + CLuaArguments arguments; + + std::uint8_t weapon = ped->GetWeaponType(); + std::uint16_t clip = ped->GetWeaponAmmoInClip(); + std::uint16_t ammo = ped->GetWeaponTotalAmmo(); + + arguments.PushNumber(weapon); + arguments.PushNumber(clip); + arguments.PushNumber(ammo); + + if (IS_PLAYER(pElement)) + result = ped->CallEvent("onPlayerWeaponReload", arguments); + else + result = ped->CallEvent("onPedWeaponReload", arguments); + + if (!result) + return false; + + CBitStream stream; + + ped->SetReloadingWeapon(true); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(ped, RELOAD_PED_WEAPON, *stream.pBitStream)); + + return true; } bool CStaticFunctionDefinitions::GetCameraMatrix(CPlayer* pPlayer, CVector& vecPosition, CVector& vecLookAt, float& fRoll, float& fFOV) diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h index 52ce191c26..1bf1beb45a 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -218,7 +218,7 @@ class CStaticFunctionDefinitions static bool SetPedOnFire(CElement* pElement, bool bIsOnFire); static bool SetPedHeadless(CElement* pElement, bool bIsHeadless); static bool SetPedFrozen(CElement* pElement, bool bIsFrozen); - static bool reloadPedWeapon(CElement* pElement); + static bool ReloadPedWeapon(CElement* pElement) noexcept; static bool SetWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, float fData); static bool SetWeaponProperty(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, int sData); static bool SetWeaponPropertyFlag(eWeaponProperty eProperty, eWeaponType eWeapon, eWeaponSkill eSkillLevel, bool bEnable); diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index 8a5a3c8591..366daac57b 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -48,6 +48,7 @@ void CLuaPedDefs::LoadFunctions() {"getPedOccupiedVehicle", GetPedOccupiedVehicle}, {"getPedOccupiedVehicleSeat", GetPedOccupiedVehicleSeat}, {"isPedInVehicle", IsPedInVehicle}, + {"isPedReloadingWeapon", ArgumentParser}, // Ped set functions {"setPedArmor", SetPedArmor}, @@ -71,7 +72,7 @@ void CLuaPedDefs::LoadFunctions() {"setPedOnFire", SetPedOnFire}, {"setPedHeadless", SetPedHeadless}, {"setPedFrozen", SetPedFrozen}, - {"reloadPedWeapon", reloadPedWeapon}, + {"reloadPedWeapon", ArgumentParserWarn}, // Weapon give/take functions {"giveWeapon", GiveWeapon}, @@ -118,6 +119,7 @@ void CLuaPedDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "isFrozen", "isPedFrozen"); lua_classfunction(luaVM, "isHeadless", "isPedHeadless"); lua_classfunction(luaVM, "isWearingJetpack", "isPedWearingJetpack"); // introduced in 1.5.5-9.13846 + lua_classfunction(luaVM, "isReloadingWeapon", "isPedReloadingWeapon"); lua_classfunction(luaVM, "getArmor", "getPedArmor"); lua_classfunction(luaVM, "getFightingStyle", "getPedFightingStyle"); @@ -169,6 +171,7 @@ void CLuaPedDefs::AddClass(lua_State* luaVM) lua_classvariable(luaVM, "vehicle", "warpPedIntoVehicle", "getPedOccupiedVehicle", OOP_WarpPedIntoVehicle, GetPedOccupiedVehicle); lua_classvariable(luaVM, "walkingStyle", "setPedWalkingStyle", "getPedWalkingStyle"); lua_classvariable(luaVM, "jetpack", "setPedWearingJetpack", "isPedWearingJetpack"); // introduced in 1.5.5-9.13846 + lua_classvariable(luaVM, "reloadingWeapon", nullptr, "isPedReloadingWeapon"); // TODO(qaisjp): setting this to any value will kill the ped. add OOP_KillPed that only allows `true`. lua_classvariable(luaVM, "dead", "killPed", "isPedDead"); @@ -289,28 +292,15 @@ int CLuaPedDefs::GetPedWeaponSlot(lua_State* luaVM) return 1; } -int CLuaPedDefs::reloadPedWeapon(lua_State* luaVM) +bool CLuaPedDefs::ReloadPedWeapon(lua_State* vm, CPed* const ped) noexcept { - CElement* pPed; - - CScriptArgReader argStream(luaVM); - argStream.ReadUserData(pPed); - - if (!argStream.HasErrors()) - { - LogWarningIfPlayerHasNotJoinedYet(luaVM, pPed); - - if (CStaticFunctionDefinitions::reloadPedWeapon(pPed)) - { - lua_pushboolean(luaVM, true); - return 1; - } - } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + LogWarningIfPlayerHasNotJoinedYet(vm, ped); + return CStaticFunctionDefinitions::ReloadPedWeapon(ped); +} - lua_pushboolean(luaVM, false); - return 1; +bool CLuaPedDefs::IsPedReloadingWeapon(CPed* const ped) noexcept +{ + return ped->IsReloadingWeapon(); } int CLuaPedDefs::IsPedDoingGangDriveby(lua_State* luaVM) diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index 0348b5db61..3592247298 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -53,6 +53,7 @@ class CLuaPedDefs : public CLuaDefs LUA_DECLARE(IsPedInVehicle); LUA_DECLARE(GetPedAmmoInClip); LUA_DECLARE(GetPedTotalAmmo); + static bool IsPedReloadingWeapon(CPed* const ped) noexcept; // Ped set functions LUA_DECLARE(SetPedArmor); @@ -78,5 +79,5 @@ class CLuaPedDefs : public CLuaDefs LUA_DECLARE(SetPedOnFire); LUA_DECLARE(SetPedHeadless); LUA_DECLARE(SetPedFrozen); - LUA_DECLARE(reloadPedWeapon); + static bool ReloadPedWeapon(lua_State* vm, CPed* const ped) noexcept; }; diff --git a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp index 7af83dcb51..32e2d84272 100644 --- a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.cpp @@ -64,6 +64,12 @@ bool CPedSyncPacket::Read(NetBitStreamInterface& BitStream) return false; } + if (ucFlags & 0x60 && BitStream.Can(eBitStreamVersion::IsPedReloadingWeapon)) + { + if (!BitStream.ReadBit(Data.isReloadingWeapon)) + return false; + } + // In Water if (ucFlags & 0x40) { @@ -136,6 +142,8 @@ bool CPedSyncPacket::Write(NetBitStreamInterface& BitStream) const BitStream.Write(Data.fArmor); if (Data.ucFlags & 0x20) BitStream.WriteBit(Data.bOnFire); + if (Data.ucFlags & 0x60 && BitStream.Can(eBitStreamVersion::IsPedReloadingWeapon)) + BitStream.Write(Data.isReloadingWeapon); if (Data.ucFlags & 0x40) BitStream.Write(Data.bIsInWater); diff --git a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h index f200be509b..ae18d288bb 100644 --- a/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h +++ b/Server/mods/deathmatch/logic/packets/CPedSyncPacket.h @@ -31,6 +31,7 @@ class CPedSyncPacket final : public CPacket float fArmor; bool bOnFire; bool bIsInWater; + bool isReloadingWeapon; bool ReadSpatialData(NetBitStreamInterface& BitStream); // Backward compatibility diff --git a/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp b/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp index 399d3c0b35..49496f67b6 100644 --- a/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp @@ -62,6 +62,9 @@ bool CPlayerPuresyncPacket::Read(NetBitStreamInterface& BitStream) pSourcePlayer->SetOnFire(flags.data.bIsOnFire); pSourcePlayer->SetStealthAiming(flags.data.bStealthAiming); + if (BitStream.Can(eBitStreamVersion::IsPedReloadingWeapon)) + pSourcePlayer->SetReloadingWeapon(flags.data2.isReloadingWeapon); + // Contact element CElement* pContactElement = NULL; if (flags.data.bHasContact) @@ -341,6 +344,9 @@ bool CPlayerPuresyncPacket::Write(NetBitStreamInterface& BitStream) const flags.data.bSyncingVelocity = (!flags.data.bIsOnGround || pSourcePlayer->IsSyncingVelocity()); flags.data.bStealthAiming = (pSourcePlayer->IsStealthAiming() == true); + if (pSourcePlayer->CanBitStream(eBitStreamVersion::IsPedReloadingWeapon)) + flags.data2.isReloadingWeapon = pSourcePlayer->IsReloadingWeapon(); + CVector vecPosition = pSourcePlayer->GetPosition(); if (pContactElement) pSourcePlayer->GetContactPosition(vecPosition); diff --git a/Shared/sdk/net/SyncStructures.h b/Shared/sdk/net/SyncStructures.h index 0e42407aae..07c4171e20 100644 --- a/Shared/sdk/net/SyncStructures.h +++ b/Shared/sdk/net/SyncStructures.h @@ -547,8 +547,30 @@ struct SPlayerPuresyncFlags : public ISyncStructure BITCOUNT = 12 }; - bool Read(NetBitStreamInterface& bitStream) { return bitStream.ReadBits((char*)&data, BITCOUNT); } - void Write(NetBitStreamInterface& bitStream) const { bitStream.WriteBits((const char*)&data, BITCOUNT); } + enum + { + BITCOUNT2 = 1 + }; + + bool Read(NetBitStreamInterface& stream) + { + bool ok = stream.ReadBits((char*)&data, BITCOUNT); + + if (stream.Can(eBitStreamVersion::IsPedReloadingWeapon)) + ok &= stream.ReadBits((char*)&data2, BITCOUNT2); + else + data2.isReloadingWeapon = 0; + + return ok; + } + + void Write(NetBitStreamInterface& stream) const + { + stream.WriteBits((const char*)&data, BITCOUNT); + + if (stream.Can(eBitStreamVersion::IsPedReloadingWeapon)) + stream.WriteBits((const char*)&data2, BITCOUNT2); + } struct { @@ -565,6 +587,11 @@ struct SPlayerPuresyncFlags : public ISyncStructure bool bSyncingVelocity : 1; bool bStealthAiming : 1; } data; + + struct + { + bool isReloadingWeapon : 1; + } data2; }; struct SPedRotationSync : public ISyncStructure diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index ea7fbcc230..5189e85ee1 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -600,6 +600,10 @@ enum class eBitStreamVersion : unsigned short // 2025-01-01 AnimationsSync, + // Add server side isPedReloadingWeapon + // 2025-01-09 + IsPedReloadingWeapon, + // 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,