Forráskód Böngészése

Some fixes for simulated client weapon activations, although target position is still not replicating correctly

Signed-off-by: kberg-amzn <[email protected]>
kberg-amzn 4 éve
szülő
commit
5c5710bafd

+ 2 - 3
Gem/Code/Source/AutoGen/NetworkWeaponsComponent.AutoComponent.xml

@@ -7,7 +7,7 @@
     OverrideController="true" 
     OverrideController="true" 
     OverrideInclude="Source/Components/NetworkWeaponsComponent.h"
     OverrideInclude="Source/Components/NetworkWeaponsComponent.h"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-    
+
     <ComponentRelation Constraint="Required" HasController="true" Name="NetworkAnimationComponent" Namespace="MultiplayerSample" Include="Source/Components/NetworkAnimationComponent.h" />
     <ComponentRelation Constraint="Required" HasController="true" Name="NetworkAnimationComponent" Namespace="MultiplayerSample" Include="Source/Components/NetworkAnimationComponent.h" />
     <ComponentRelation Constraint="Required" HasController="true" Name="SimplePlayerCameraComponent" Namespace="MultiplayerSample" Include="Source/Components/SimplePlayerCameraComponent.h" />
     <ComponentRelation Constraint="Required" HasController="true" Name="SimplePlayerCameraComponent" Namespace="MultiplayerSample" Include="Source/Components/SimplePlayerCameraComponent.h" />
 
 
@@ -16,9 +16,8 @@
     <NetworkInput Type="bool" Name="Draw" Init="false" />
     <NetworkInput Type="bool" Name="Draw" Init="false" />
     <NetworkInput Type="WeaponActivationBitset" Name="Firing"  Init="" />
     <NetworkInput Type="WeaponActivationBitset" Name="Firing"  Init="" />
 
 
-    <NetworkProperty Type="AZ::Vector3" Name="TargetPosition"   Init="AZ::Vector3::CreateZero()" Container="Object"       ReplicateFrom="Authority" ReplicateTo="Client"     IsPublic="false" IsRewindable="false" IsPredictable="false" ExposeToEditor="false" GenerateEventBindings="false" Description="Target position the weapons component is currently aiming at" />
     <NetworkProperty Type="FireParams"  Name="ActivationParams" Init=""  Container="Array" Count="MaxWeaponsPerComponent" ReplicateFrom="Authority" ReplicateTo="Client"     IsPublic="false" IsRewindable="false" IsPredictable="false" ExposeToEditor="false" GenerateEventBindings="false" Description="Parameters for the current weapon activation" />
     <NetworkProperty Type="FireParams"  Name="ActivationParams" Init=""  Container="Array" Count="MaxWeaponsPerComponent" ReplicateFrom="Authority" ReplicateTo="Client"     IsPublic="false" IsRewindable="false" IsPredictable="false" ExposeToEditor="false" GenerateEventBindings="false" Description="Parameters for the current weapon activation" />
-    <NetworkProperty Type="uint8_t"     Name="ActivationCounts" Init="0" Container="Array" Count="MaxWeaponsPerComponent" ReplicateFrom="Authority" ReplicateTo="Client"     IsPublic="false" IsRewindable="false" IsPredictable="false" ExposeToEditor="false" GenerateEventBindings="false" Description="The number of activations" />
+    <NetworkProperty Type="uint8_t"     Name="ActivationCounts" Init="0" Container="Array" Count="MaxWeaponsPerComponent" ReplicateFrom="Authority" ReplicateTo="Client"     IsPublic="false" IsRewindable="false" IsPredictable="false" ExposeToEditor="false" GenerateEventBindings="true"  Description="The number of activations" />
     <NetworkProperty Type="WeaponState" Name="WeaponStates"     Init=""  Container="Array" Count="MaxWeaponsPerComponent" ReplicateFrom="Authority" ReplicateTo="Autonomous" IsPublic="false" IsRewindable="false" IsPredictable="true"  ExposeToEditor="false" GenerateEventBindings="false" Description="The predictable states of the weapons" />
     <NetworkProperty Type="WeaponState" Name="WeaponStates"     Init=""  Container="Array" Count="MaxWeaponsPerComponent" ReplicateFrom="Authority" ReplicateTo="Autonomous" IsPublic="false" IsRewindable="false" IsPredictable="true"  ExposeToEditor="false" GenerateEventBindings="false" Description="The predictable states of the weapons" />
 
 
     <ArchetypeProperty Type="WeaponParams"  Name="WeaponParams"  Init="" Container="Array" Count="MaxWeaponsPerComponent" ExposeToEditor="true" Description="Parameters for the weapons attached to this NetworkWeaponsComponent" />
     <ArchetypeProperty Type="WeaponParams"  Name="WeaponParams"  Init="" Container="Array" Count="MaxWeaponsPerComponent" ExposeToEditor="true" Description="Parameters for the weapons attached to this NetworkWeaponsComponent" />

+ 2 - 2
Gem/Code/Source/Components/NetworkAnimationComponent.h

@@ -47,8 +47,8 @@ namespace MultiplayerSample
 
 
         int32_t GetBoneIdByName(const char* boneName) const;
         int32_t GetBoneIdByName(const char* boneName) const;
 
 
-        bool GetJointTransformByName(const char* a_BoneName, AZ::Transform& outJointTransform) const;
-        bool GetJointTransformById(int32_t a_BoneId, AZ::Transform& outJointTransform) const;
+        bool GetJointTransformByName(const char* boneName, AZ::Transform& outJointTransform) const;
+        bool GetJointTransformById(int32_t boneId, AZ::Transform& outJointTransform) const;
 
 
     private:
     private:
         void OnPreRender(float deltaTime, float blendFactor);
         void OnPreRender(float deltaTime, float blendFactor);

+ 200 - 44
Gem/Code/Source/Components/NetworkWeaponsComponent.cpp

@@ -27,8 +27,16 @@ namespace MultiplayerSample
         NetworkWeaponsComponentBase::Reflect(context);
         NetworkWeaponsComponentBase::Reflect(context);
     }
     }
 
 
+    NetworkWeaponsComponent::NetworkWeaponsComponent()
+        : NetworkWeaponsComponentBase()
+        , m_activationCountHandler([this](int32_t index, uint8_t value) { OnUpdateActivationCounts(index, value); })
+    {
+        ;
+    }
+
     void NetworkWeaponsComponent::OnInit()
     void NetworkWeaponsComponent::OnInit()
     {
     {
+        AZStd::uninitialized_fill_n(m_fireBoneJointIds.data(), MaxWeaponsPerComponent, InvalidBoneId);
     }
     }
 
 
     void NetworkWeaponsComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
     void NetworkWeaponsComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
@@ -46,6 +54,11 @@ namespace MultiplayerSample
             m_weapons[weaponIndex] = AZStd::move(CreateWeapon(constructParams));
             m_weapons[weaponIndex] = AZStd::move(CreateWeapon(constructParams));
         }
         }
 
 
+        if (IsNetEntityRoleClient())
+        {
+            ActivationCountsAddEvent(m_activationCountHandler);
+        }
+
         if (m_debugDraw == nullptr)
         if (m_debugDraw == nullptr)
         {
         {
             m_debugDraw = DebugDraw::DebugDrawRequestBus::FindFirstHandler();
             m_debugDraw = DebugDraw::DebugDrawRequestBus::FindFirstHandler();
@@ -54,10 +67,45 @@ namespace MultiplayerSample
 
 
     void NetworkWeaponsComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
     void NetworkWeaponsComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
     {
     {
+        ;
     }
     }
 
 
-    void NetworkWeaponsComponent::HandleSendConfirmHit([[maybe_unused]] AzNetworking::IConnection* invokingConnection, [[maybe_unused]] const WeaponIndex& WeaponIndex, [[maybe_unused]] const HitEvent& HitEvent)
+    void NetworkWeaponsComponent::HandleSendConfirmHit([[maybe_unused]] AzNetworking::IConnection* invokingConnection, const WeaponIndex& weaponIndex, const HitEvent& hitEvent)
     {
     {
+        if (GetWeapon(weaponIndex) == nullptr)
+        {
+            AZLOG_ERROR("Got confirmed hit for null weapon index");
+            return;
+        }
+
+        WeaponHitInfo weaponHitInfo(*GetWeapon(weaponIndex), hitEvent);
+        OnWeaponConfirmHit(weaponHitInfo);
+    }
+
+    void NetworkWeaponsComponent::ActivateWeaponWithParams(WeaponIndex weaponIndex, WeaponState& weaponState, const FireParams& fireParams, bool validateActivations)
+    {
+        const uint32_t weaponIndexInt = aznumeric_cast<uint32_t>(weaponIndex);
+
+        // Temp hack for weapon firing due to late ebus binding in 1.14
+        if (m_fireBoneJointIds[weaponIndexInt] == InvalidBoneId)
+        {
+            const char* fireBoneName = GetFireBoneNames(weaponIndexInt).c_str();
+            m_fireBoneJointIds[weaponIndexInt] = GetNetworkAnimationComponent()->GetBoneIdByName(fireBoneName);
+        }
+
+        AZ::Transform fireBoneTransform;
+        if (!GetNetworkAnimationComponent()->GetJointTransformById(m_fireBoneJointIds[weaponIndexInt], fireBoneTransform))
+        {
+            AZLOG_WARN("Failed to get transform for fire bone %s, joint Id %u", GetFireBoneNames(weaponIndexInt).c_str(), m_fireBoneJointIds[weaponIndexInt]);
+        }
+
+        const AZ::Vector3    position = fireBoneTransform.GetTranslation();
+        const AZ::Quaternion orientation = AZ::Quaternion::CreateShortestArc(AZ::Vector3::CreateAxisX(), (fireParams.m_targetPosition - position).GetNormalized());
+        const AZ::Transform  transform = AZ::Transform::CreateFromQuaternionAndTranslation(orientation, position);
+        ActivateEvent activateEvent{ transform, fireParams.m_targetPosition, GetNetEntityId(), Multiplayer::InvalidNetEntityId };
+
+        IWeapon* weapon = GetWeapon(weaponIndex);
+        weapon->Activate(weaponState, GetEntityHandle(), activateEvent, validateActivations);
     }
     }
 
 
     IWeapon* NetworkWeaponsComponent::GetWeapon(WeaponIndex weaponIndex) const
     IWeapon* NetworkWeaponsComponent::GetWeapon(WeaponIndex weaponIndex) const
@@ -67,12 +115,18 @@ namespace MultiplayerSample
 
 
     void NetworkWeaponsComponent::OnWeaponActivate([[maybe_unused]] const WeaponActivationInfo& activationInfo)
     void NetworkWeaponsComponent::OnWeaponActivate([[maybe_unused]] const WeaponActivationInfo& activationInfo)
     {
     {
+        // If we're replaying inputs then early out
+        if (GetNetBindComponent()->IsReprocessingInput())
+        {
+            return;
+        }
+
         if (cl_WeaponsDrawDebug && m_debugDraw)
         if (cl_WeaponsDrawDebug && m_debugDraw)
         {
         {
             m_debugDraw->DrawSphereAtLocation
             m_debugDraw->DrawSphereAtLocation
             (
             (
                 activationInfo.m_activateEvent.m_initialTransform.GetTranslation(),
                 activationInfo.m_activateEvent.m_initialTransform.GetTranslation(),
-                0.5f, 
+                0.25f, 
                 AZ::Colors::GreenYellow,
                 AZ::Colors::GreenYellow,
                 10.0f
                 10.0f
             );
             );
@@ -80,26 +134,138 @@ namespace MultiplayerSample
             m_debugDraw->DrawSphereAtLocation
             m_debugDraw->DrawSphereAtLocation
             (
             (
                 activationInfo.m_activateEvent.m_targetPosition,
                 activationInfo.m_activateEvent.m_targetPosition,
-                0.5f,
+                0.25f,
                 AZ::Colors::Crimson,
                 AZ::Colors::Crimson,
                 10.0f
                 10.0f
             );
             );
         }
         }
+
+        AZLOG
+        (
+            NET_TraceWeapons,
+            "Weapon activated with target position %f x %f x %f",
+            activationInfo.m_activateEvent.m_targetPosition.GetX(),
+            activationInfo.m_activateEvent.m_targetPosition.GetY(),
+            activationInfo.m_activateEvent.m_targetPosition.GetZ()
+        );
+
     }
     }
 
 
-    void NetworkWeaponsComponent::OnWeaponPredictHit([[maybe_unused]] const WeaponHitInfo& hitInfo)
+    void NetworkWeaponsComponent::OnWeaponPredictHit(const WeaponHitInfo& hitInfo)
     {
     {
+        // If we're replaying inputs then early out
+        if (GetNetBindComponent()->IsReprocessingInput())
+        {
+            return;
+        }
+
+        for (uint32_t i = 0; i < hitInfo.m_hitEvent.m_hitEntities.size(); ++i)
+        {
+            const HitEntity& hitEntity = hitInfo.m_hitEvent.m_hitEntities[i];
+
+            if (cl_WeaponsDrawDebug && m_debugDraw)
+            {
+                m_debugDraw->DrawSphereAtLocation
+                (
+                    hitEntity.m_hitPosition,
+                    1.0f,
+                    AZ::Colors::OrangeRed,
+                    10.0f
+                );
+            }
+
+            AZLOG
+            (
+                NET_TraceWeapons,
+                "Predicted hit on entity %u at position %f x %f x %f",
+                hitEntity.m_hitNetEntityId,
+                hitEntity.m_hitPosition.GetX(),
+                hitEntity.m_hitPosition.GetY(),
+                hitEntity.m_hitPosition.GetZ()
+            );
+        }
     }
     }
 
 
-    void NetworkWeaponsComponent::OnWeaponConfirmHit([[maybe_unused]] const WeaponHitInfo& hitInfo)
+    void NetworkWeaponsComponent::OnWeaponConfirmHit(const WeaponHitInfo& hitInfo)
     {
     {
+        // If we're replaying inputs then early out
+        if (GetNetBindComponent()->IsReprocessingInput())
+        {
+            return;
+        }
+
+        // If we're a simulated weapon, or if the weapon is not predictive, then issue material hit effects since the predicted callback above will not get triggered
+        [[maybe_unused]] bool shouldIssueMaterialEffects = !HasController() || !hitInfo.m_weapon.GetParams().m_locallyPredicted;
+
+        for (uint32_t i = 0; i < hitInfo.m_hitEvent.m_hitEntities.size(); ++i)
+        {
+            const HitEntity& hitEntity = hitInfo.m_hitEvent.m_hitEntities[i];
+
+            if (cl_WeaponsDrawDebug && m_debugDraw)
+            {
+                m_debugDraw->DrawSphereAtLocation
+                (
+                    hitEntity.m_hitPosition,
+                    1.0f,
+                    AZ::Colors::Red,
+                    10.0f
+                );
+            }
+
+            AZLOG
+            (
+                NET_TraceWeapons,
+                "Confirmed hit on entity %u at position %f x %f x %f",
+                hitEntity.m_hitNetEntityId,
+                hitEntity.m_hitPosition.GetX(),
+                hitEntity.m_hitPosition.GetY(),
+                hitEntity.m_hitPosition.GetZ()
+            );
+        }
+    }
+
+    void NetworkWeaponsComponent::OnUpdateActivationCounts(int32_t index, uint8_t value)
+    {
+        IWeapon* weapon = GetWeapon(aznumeric_cast<WeaponIndex>(index));
+
+        if (weapon == nullptr)
+        {
+            return;
+        }
+
+        if (HasController() && weapon->GetParams().m_locallyPredicted)
+        {
+            // If this is a predicted weapon, exit out because autonomous weapons predict activations
+            return;
+        }
+
+        AZLOG(NET_TraceWeapons, "Client activation event for weapon index %u", index);
+
+        WeaponState& weaponState = m_simulatedWeaponStates[index];
+        const FireParams& fireParams = GetActivationParams(index);
+        weapon->SetFireParams(fireParams);
+
+        AZLOG
+        (
+            NET_TraceWeapons,
+            "UpdateActivationCounts fire params target %f x %f x %f",
+            fireParams.m_targetPosition.GetX(),
+            fireParams.m_targetPosition.GetY(),
+            fireParams.m_targetPosition.GetZ()
+        );
+
+        while (weaponState.m_activationCount != value)
+        {
+            const bool validateActivations = false;
+            ActivateWeaponWithParams(aznumeric_cast<WeaponIndex>(index), weaponState, fireParams, validateActivations);
+        }
     }
     }
 
 
 
 
     NetworkWeaponsComponentController::NetworkWeaponsComponentController(NetworkWeaponsComponent& parent)
     NetworkWeaponsComponentController::NetworkWeaponsComponentController(NetworkWeaponsComponent& parent)
         : NetworkWeaponsComponentControllerBase(parent)
         : NetworkWeaponsComponentControllerBase(parent)
     {
     {
-        AZStd::uninitialized_fill_n(m_fireBoneJointIds.data(), MaxWeaponsPerComponent, InvalidBoneId);
+        ;
     }
     }
 
 
     void NetworkWeaponsComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
     void NetworkWeaponsComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating)
@@ -144,9 +310,9 @@ namespace MultiplayerSample
 
 
         const AZ::Transform worldTm = GetParent().GetEntity()->GetTransform()->GetWorldTM();
         const AZ::Transform worldTm = GetParent().GetEntity()->GetTransform()->GetWorldTM();
 
 
-        for (uint32_t weaponIndex = 0; weaponIndex < MaxWeaponsPerComponent; ++weaponIndex)
+        for (uint32_t weaponIndexInt = 0; weaponIndexInt < MaxWeaponsPerComponent; ++weaponIndexInt)
         {
         {
-            if (weaponInput->m_firing.GetBit(aznumeric_cast<uint32_t>(weaponIndex)))
+            if (weaponInput->m_firing.GetBit(weaponIndexInt))
             {
             {
                 const AZ::Vector3& aimAngles = GetSimplePlayerCameraComponentController()->GetAimAngles();
                 const AZ::Vector3& aimAngles = GetSimplePlayerCameraComponentController()->GetAimAngles();
                 const AZ::Quaternion aimRotation = AZ::Quaternion::CreateRotationZ(aimAngles.GetZ()) * AZ::Quaternion::CreateRotationX(aimAngles.GetX());
                 const AZ::Quaternion aimRotation = AZ::Quaternion::CreateRotationZ(aimAngles.GetZ()) * AZ::Quaternion::CreateRotationX(aimAngles.GetX());
@@ -154,7 +320,7 @@ namespace MultiplayerSample
                 const AZ::Vector3 fwd = AZ::Vector3::CreateAxisY();
                 const AZ::Vector3 fwd = AZ::Vector3::CreateAxisY();
                 const AZ::Vector3 aimTarget = worldTm.GetTranslation() + aimRotation.TransformVector(fwd * 5.0f);
                 const AZ::Vector3 aimTarget = worldTm.GetTranslation() + aimRotation.TransformVector(fwd * 5.0f);
                 FireParams fireParams{ aimTarget, Multiplayer::InvalidNetEntityId };
                 FireParams fireParams{ aimTarget, Multiplayer::InvalidNetEntityId };
-                TryStartFire(aznumeric_cast<WeaponIndex>(weaponIndex), fireParams);
+                TryStartFire(aznumeric_cast<WeaponIndex>(weaponIndexInt), fireParams);
             }
             }
         }
         }
 
 
@@ -163,49 +329,37 @@ namespace MultiplayerSample
 
 
     void NetworkWeaponsComponentController::UpdateWeaponFiring([[maybe_unused]] float deltaTime)
     void NetworkWeaponsComponentController::UpdateWeaponFiring([[maybe_unused]] float deltaTime)
     {
     {
-        for (uint32_t weaponIndex = 0; weaponIndex < MaxWeaponsPerComponent; ++weaponIndex)
+        for (uint32_t weaponIndexInt = 0; weaponIndexInt < MaxWeaponsPerComponent; ++weaponIndexInt)
         {
         {
-            IWeapon* weapon = GetParent().GetWeapon(aznumeric_cast<WeaponIndex>(weaponIndex));
+            IWeapon* weapon = GetParent().GetWeapon(aznumeric_cast<WeaponIndex>(weaponIndexInt));
 
 
             if ((weapon == nullptr) || !weapon->GetParams().m_locallyPredicted)
             if ((weapon == nullptr) || !weapon->GetParams().m_locallyPredicted)
             {
             {
                 continue;
                 continue;
             }
             }
 
 
-            WeaponState& weaponState = ModifyWeaponStates(aznumeric_cast<uint32_t>(weaponIndex));
+            WeaponState& weaponState = ModifyWeaponStates(weaponIndexInt);
             if ((weaponState.m_status == WeaponStatus::Firing) && (weaponState.m_cooldownTime <= 0.0f))
             if ((weaponState.m_status == WeaponStatus::Firing) && (weaponState.m_cooldownTime <= 0.0f))
             {
             {
-                AZLOG(NET_TraceWeapons, "Weapon predicted activation event for weapon index %u", aznumeric_cast<uint32_t>(weaponIndex));
-
-                // Temp hack for weapon firing due to late ebus binding in 1.14
-                if (m_fireBoneJointIds[weaponIndex] == InvalidBoneId)
-                {
-                    const char* fireBoneName = GetFireBoneNames(aznumeric_cast<uint32_t>(weaponIndex)).c_str();
-                    m_fireBoneJointIds[weaponIndex] = GetNetworkAnimationComponentController()->GetParent().GetBoneIdByName(fireBoneName);
-                }
-
-                AZ::Transform fireBoneTransform;
-                if (!GetNetworkAnimationComponentController()->GetParent().GetJointTransformById(m_fireBoneJointIds[weaponIndex], fireBoneTransform))
-                {
-                    AZLOG_WARN("Failed to get transform for fire bone %s, joint Id %u", GetFireBoneNames(aznumeric_cast<uint32_t>(weaponIndex)).c_str(), m_fireBoneJointIds[weaponIndex]);
-                }
-
-                const FireParams&    fireParams = weapon->GetFireParams();
-                const AZ::Vector3    position = fireBoneTransform.GetTranslation();
-                const AZ::Quaternion orientation = AZ::Quaternion::CreateShortestArc(AZ::Vector3::CreateAxisX(), (fireParams.m_targetPosition - position).GetNormalized());
-                const AZ::Transform  transform = AZ::Transform::CreateFromQuaternionAndTranslation(orientation, position);
-                ActivateEvent activateEvent{ transform, fireParams.m_targetPosition, GetNetEntityId(), Multiplayer::InvalidNetEntityId };
+                AZLOG(NET_TraceWeapons, "Weapon predicted activation event for weapon index %u", weaponIndexInt);
 
 
-                const bool isReplay = GetNetBindComponent()->IsReprocessingInput();
-                bool dispatchHitEvents = weapon->GetParams().m_locallyPredicted;
-                bool dispatchActivateEvents = weapon->GetParams().m_locallyPredicted;
-                bool skipGathers = false;
-
-                weapon->Activate(deltaTime, weaponState, GetEntityHandle(), activateEvent, dispatchHitEvents, dispatchActivateEvents, skipGathers);
+                const bool validateActivations = true;
+                const FireParams& fireParams = weapon->GetFireParams();
+                GetParent().ActivateWeaponWithParams(aznumeric_cast<WeaponIndex>(weaponIndexInt), weaponState, fireParams, validateActivations);
 
 
                 if (IsAuthority())
                 if (IsAuthority())
                 {
                 {
-                    SetActivationCounts(aznumeric_cast<uint32_t>(weaponIndex), weaponState.m_activationCount);
+                    AZLOG
+                    (
+                        NET_TraceWeapons,
+                        "UpdateActivationCounts fire params target %f x %f x %f",
+                        fireParams.m_targetPosition.GetX(),
+                        fireParams.m_targetPosition.GetY(),
+                        fireParams.m_targetPosition.GetZ()
+                    );
+
+                    SetActivationParams(weaponIndexInt, fireParams);
+                    SetActivationCounts(weaponIndexInt, weaponState.m_activationCount);
                 }
                 }
             }
             }
             weapon->UpdateWeaponState(weaponState, deltaTime);
             weapon->UpdateWeaponState(weaponState, deltaTime);
@@ -214,21 +368,23 @@ namespace MultiplayerSample
 
 
     bool NetworkWeaponsComponentController::TryStartFire(WeaponIndex weaponIndex, const FireParams& fireParams)
     bool NetworkWeaponsComponentController::TryStartFire(WeaponIndex weaponIndex, const FireParams& fireParams)
     {
     {
-        AZLOG(NET_TraceWeapons, "Weapon start fire on %u", aznumeric_cast<uint32_t>(weaponIndex));
+        const uint32_t weaponIndexInt = aznumeric_cast<uint32_t>(weaponIndex);
+        AZLOG(NET_TraceWeapons, "Weapon start fire on %u", weaponIndexInt);
 
 
         IWeapon* weapon = GetParent().GetWeapon(weaponIndex);
         IWeapon* weapon = GetParent().GetWeapon(weaponIndex);
-
         if (weapon == nullptr)
         if (weapon == nullptr)
         {
         {
             return false;
             return false;
         }
         }
 
 
-        WeaponState& weaponState = ModifyWeaponStates(aznumeric_cast<uint32_t>(weaponIndex));
-
+        WeaponState& weaponState = ModifyWeaponStates(weaponIndexInt);
         if (weapon->TryStartFire(weaponState, fireParams))
         if (weapon->TryStartFire(weaponState, fireParams))
         {
         {
             const uint32_t animBit = static_cast<uint32_t>(weapon->GetParams().m_animFlag);
             const uint32_t animBit = static_cast<uint32_t>(weapon->GetParams().m_animFlag);
-            GetNetworkAnimationComponentController()->ModifyActiveAnimStates().SetBit(animBit, true);
+            if (!GetNetworkAnimationComponentController()->GetActiveAnimStates().GetBit(animBit))
+            {
+                GetNetworkAnimationComponentController()->ModifyActiveAnimStates().SetBit(animBit, true);
+            }
             return true;
             return true;
         }
         }
 
 

+ 10 - 3
Gem/Code/Source/Components/NetworkWeaponsComponent.h

@@ -32,11 +32,14 @@ namespace MultiplayerSample
 
 
         static void Reflect(AZ::ReflectContext* context);
         static void Reflect(AZ::ReflectContext* context);
 
 
+        NetworkWeaponsComponent();
+
         void OnInit() override;
         void OnInit() override;
         void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
         void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
         void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
         void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
 
 
-        void HandleSendConfirmHit(AzNetworking::IConnection* invokingConnection, const WeaponIndex& WeaponIndex, const HitEvent& HitEvent) override;
+        void HandleSendConfirmHit(AzNetworking::IConnection* invokingConnection, const WeaponIndex& weaponIndex, const HitEvent& hitEvent) override;
+        void ActivateWeaponWithParams(WeaponIndex weaponIndex, WeaponState& weaponState, const FireParams& fireParams, bool validateActivations);
 
 
         IWeapon* GetWeapon(WeaponIndex weaponIndex) const;
         IWeapon* GetWeapon(WeaponIndex weaponIndex) const;
 
 
@@ -48,9 +51,15 @@ namespace MultiplayerSample
         void OnWeaponConfirmHit(const WeaponHitInfo& hitInfo) override;
         void OnWeaponConfirmHit(const WeaponHitInfo& hitInfo) override;
         //! @}
         //! @}
 
 
+        void OnUpdateActivationCounts(int32_t index, uint8_t value);
+
         using WeaponPointer = AZStd::unique_ptr<IWeapon>;
         using WeaponPointer = AZStd::unique_ptr<IWeapon>;
         AZStd::array<WeaponPointer, MaxWeaponsPerComponent> m_weapons;
         AZStd::array<WeaponPointer, MaxWeaponsPerComponent> m_weapons;
 
 
+        AZ::Event<int32_t, uint8_t>::Handler m_activationCountHandler;
+        AZStd::array<WeaponState, MaxWeaponsPerComponent> m_simulatedWeaponStates;
+        AZStd::array<int32_t, MaxWeaponsPerComponent> m_fireBoneJointIds;
+
         DebugDraw::DebugDrawRequests* m_debugDraw = nullptr;
         DebugDraw::DebugDrawRequests* m_debugDraw = nullptr;
     };
     };
 
 
@@ -86,7 +95,5 @@ namespace MultiplayerSample
 
 
         bool m_weaponDrawn = false;
         bool m_weaponDrawn = false;
         WeaponActivationBitset m_weaponFiring;
         WeaponActivationBitset m_weaponFiring;
-
-        AZStd::array<int32_t, MaxWeaponsPerComponent> m_fireBoneJointIds;
     };
     };
 }
 }

+ 1 - 1
Gem/Code/Source/Components/WasdPlayerMovementComponent.cpp

@@ -171,7 +171,7 @@ namespace MultiplayerSample
 
 
     float WasdPlayerMovementComponentController::NormalizeHeading(float heading) const
     float WasdPlayerMovementComponentController::NormalizeHeading(float heading) const
     {
     {
-        // Ensure a_Heading in range [-pi, +pi]
+        // Ensure heading in range [-pi, +pi]
         if (heading > AZ::Constants::Pi)
         if (heading > AZ::Constants::Pi)
         {
         {
             return static_cast<float>(heading - AZ::Constants::TwoPi);
             return static_cast<float>(heading - AZ::Constants::TwoPi);

+ 2 - 3
Gem/Code/Source/Weapons/BaseWeapon.cpp

@@ -166,7 +166,7 @@ namespace MultiplayerSample
             hitEvent.m_hitEntities.emplace_back(HitEntity{ gatherResult.m_position, gatherResult.m_netEntityId });
             hitEvent.m_hitEntities.emplace_back(HitEntity{ gatherResult.m_position, gatherResult.m_netEntityId });
         }
         }
 
 
-        WeaponHitInfo hitInfo(*this, eventData.m_initialTransform.GetTranslation(), hitEvent);
+        WeaponHitInfo hitInfo(*this, hitEvent);
         m_weaponListener.OnWeaponPredictHit(hitInfo);
         m_weaponListener.OnWeaponPredictHit(hitInfo);
     }
     }
 
 
@@ -177,9 +177,8 @@ namespace MultiplayerSample
         ;
         ;
     }
     }
 
 
-    WeaponHitInfo::WeaponHitInfo(const IWeapon& weapon, const AZ::Vector3& gatherOrigin, const HitEvent& hitEvent)
+    WeaponHitInfo::WeaponHitInfo(const IWeapon& weapon, const HitEvent& hitEvent)
         : m_weapon(weapon)
         : m_weapon(weapon)
-        , m_gatherOrigin(gatherOrigin)
         , m_hitEvent(hitEvent)
         , m_hitEvent(hitEvent)
     {
     {
         ;
         ;

+ 11 - 19
Gem/Code/Source/Weapons/IWeapon.h

@@ -76,22 +76,16 @@ namespace MultiplayerSample
         virtual void SetFireParams(const FireParams& fireParams) = 0;
         virtual void SetFireParams(const FireParams& fireParams) = 0;
 
 
         //! Internally called on every weapon activation.
         //! Internally called on every weapon activation.
-        //! @param deltaTime              the time in seconds this activate event corresponds to
-        //! @param weaponState            the weapons internal state structure
-        //! @param weaponOwner            the weapons owning entity
-        //! @param eventData              contains details of the activation event
-        //! @param dispatchHitEvents      if true, the Activate call will invoke hit events for gathered entities
-        //! @param dispatchActivateEvents if true, the Activate call will invoke activate events for valid activations
-        //! @param forceSkipGather        if true, skip the gather step of the activation
+        //! @param weaponState        the weapons internal state structure
+        //! @param weaponOwner        the weapons owning entity
+        //! @param eventData          contains details of the activation event
+        //! @param validateActivation if true, the Activate call will only invoke if it passes validation
         virtual void Activate
         virtual void Activate
         (
         (
-            float deltaTime,
             WeaponState& weaponState,
             WeaponState& weaponState,
             const Multiplayer::ConstNetworkEntityHandle weaponOwner,
             const Multiplayer::ConstNetworkEntityHandle weaponOwner,
             ActivateEvent& eventData,
             ActivateEvent& eventData,
-            bool dispatchHitEvents,
-            bool dispatchActivateEvents,
-            bool forceSkipGather
+            bool validateActivation
         ) = 0;
         ) = 0;
 
 
         //! Ticks the active shots for this weapon.
         //! Ticks the active shots for this weapon.
@@ -136,14 +130,12 @@ namespace MultiplayerSample
     struct WeaponHitInfo
     struct WeaponHitInfo
     {
     {
         //! Full constructor.
         //! Full constructor.
-        //! @param a_Weapon       reference to the weapon instance which produced the hit
-        //! @param a_GatherOrigin the origin point for any gather operations (center of explosion, muzzle of lasergun, etc..)
-        //! @param a_HitEvent     specific details about the weapon hit event
-        WeaponHitInfo(const IWeapon& weapon, const AZ::Vector3& gatherOrigin, const HitEvent& hitEvent);
-
-        const IWeapon& m_weapon;       //< Reference to the weapon instance which produced the hit
-        AZ::Vector3    m_gatherOrigin; //< Origin point for any gather operations (center of explosion, muzzle of lasergun, etc..)
-        HitEvent       m_hitEvent;     //< Specific details about the weapon hit event
+        //! @param weapon   reference to the weapon instance which produced the hit
+        //! @param hitEvent specific details about the weapon hit event
+        WeaponHitInfo(const IWeapon& weapon, const HitEvent& hitEvent);
+
+        const IWeapon& m_weapon; //< Reference to the weapon instance which produced the hit
+        HitEvent m_hitEvent;     //< Specific details about the weapon hit event
 
 
         WeaponHitInfo& operator =(const WeaponHitInfo&) = delete; // Don't allow copying, these guys get dispatched under special conditions
         WeaponHitInfo& operator =(const WeaponHitInfo&) = delete; // Don't allow copying, these guys get dispatched under special conditions
     };
     };

+ 1 - 4
Gem/Code/Source/Weapons/ProjectileWeapon.cpp

@@ -17,13 +17,10 @@ namespace MultiplayerSample
 
 
     void ProjectileWeapon::Activate
     void ProjectileWeapon::Activate
     (
     (
-        [[maybe_unused]] float deltaTime,
         [[maybe_unused]] WeaponState& weaponState,
         [[maybe_unused]] WeaponState& weaponState,
         [[maybe_unused]] const Multiplayer::ConstNetworkEntityHandle weaponOwner,
         [[maybe_unused]] const Multiplayer::ConstNetworkEntityHandle weaponOwner,
         [[maybe_unused]] ActivateEvent& eventData,
         [[maybe_unused]] ActivateEvent& eventData,
-        [[maybe_unused]] bool dispatchHitEvents,
-        [[maybe_unused]] bool dispatchActivateEvents,
-        [[maybe_unused]] bool forceSkipGather
+        [[maybe_unused]] bool validateActivation
     )
     )
     {
     {
         ; // need to port this code
         ; // need to port this code

+ 1 - 4
Gem/Code/Source/Weapons/ProjectileWeapon.h

@@ -29,13 +29,10 @@ namespace MultiplayerSample
         //! @{
         //! @{
         void Activate
         void Activate
         (
         (
-            float deltaTime,
             WeaponState& weaponState,
             WeaponState& weaponState,
             const Multiplayer::ConstNetworkEntityHandle weaponOwner,
             const Multiplayer::ConstNetworkEntityHandle weaponOwner,
             ActivateEvent& eventData,
             ActivateEvent& eventData,
-            bool dispatchHitEvents,
-            bool dispatchActivateEvents,
-            bool forceSkipGather
+            bool validateActivation
         ) override;
         ) override;
 
 
         void TickActiveShots(WeaponState& weaponState, float deltaTime) override;
         void TickActiveShots(WeaponState& weaponState, float deltaTime) override;

+ 5 - 21
Gem/Code/Source/Weapons/TraceWeapon.cpp

@@ -17,28 +17,15 @@ namespace MultiplayerSample
 
 
     void TraceWeapon::Activate
     void TraceWeapon::Activate
     (
     (
-        [[maybe_unused]] float deltaTime,
         WeaponState& weaponState,
         WeaponState& weaponState,
         [[maybe_unused]] const Multiplayer::ConstNetworkEntityHandle weaponOwner,
         [[maybe_unused]] const Multiplayer::ConstNetworkEntityHandle weaponOwner,
         ActivateEvent& eventData,
         ActivateEvent& eventData,
-        bool dispatchHitEvents,
-        bool dispatchActivateEvents,
-        bool forceSkipGather
+        bool validateActivation
     )
     )
     {
     {
-        const bool validate = dispatchHitEvents; // Perform activation validation if we're actually going to dispatch hit events
-        if (ActivateInternal(weaponState, validate))
+        if (ActivateInternal(weaponState, validateActivation))
         {
         {
-            if (!dispatchHitEvents)
-            {
-                // Skip out on all the remaining activation logic if this is a replay.. We do not want to spawn particles or sounds or other effects during a replay event
-                return;
-            }
-
-            if (dispatchActivateEvents)
-            {
-                m_weaponListener.OnWeaponActivate(WeaponActivationInfo(*this, eventData));
-            }
+            m_weaponListener.OnWeaponActivate(WeaponActivationInfo(*this, eventData));
 
 
             const bool isMultiSegmented = (m_weaponParams.m_gatherParams.m_travelSpeed > 0.0f);
             const bool isMultiSegmented = (m_weaponParams.m_gatherParams.m_travelSpeed > 0.0f);
 
 
@@ -48,12 +35,9 @@ namespace MultiplayerSample
                 ActiveShot activeShot{ eventData.m_initialTransform, eventData.m_targetPosition, LifetimeSec{ 0.0f } };
                 ActiveShot activeShot{ eventData.m_initialTransform, eventData.m_targetPosition, LifetimeSec{ 0.0f } };
                 weaponState.m_activeShots.emplace_back(activeShot);
                 weaponState.m_activeShots.emplace_back(activeShot);
             }
             }
-            else if (!forceSkipGather)
+            else if (GatherEntities(eventData, gatherResults))
             {
             {
-                if (GatherEntities(eventData, gatherResults))
-                {
-                    DispatchHitEvents(gatherResults, eventData, m_gatheredNetEntityIds);
-                }
+                DispatchHitEvents(gatherResults, eventData, m_gatheredNetEntityIds);
             }
             }
         }
         }
     }
     }

+ 2 - 5
Gem/Code/Source/Weapons/TraceWeapon.h

@@ -29,16 +29,13 @@ namespace MultiplayerSample
         //! @{
         //! @{
         void Activate
         void Activate
         (
         (
-            float deltaTime,
             WeaponState& weaponState,
             WeaponState& weaponState,
             const Multiplayer::ConstNetworkEntityHandle weaponOwner,
             const Multiplayer::ConstNetworkEntityHandle weaponOwner,
             ActivateEvent& eventData,
             ActivateEvent& eventData,
-            bool dispatchHitEvents,
-            bool dispatchActivateEvents,
-            bool forceSkipGather
+            bool validateActivation
         ) override;
         ) override;
 
 
-        void TickActiveShots(WeaponState& a_WeaponState, float a_DeltaTime) override;
+        void TickActiveShots(WeaponState& weaponState, float deltaTime) override;
         //! @}
         //! @}
 
 
         // Do not allow assignment
         // Do not allow assignment

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 408 - 377
Levels/SampleBase/SampleBase.prefab


Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott