diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs index 2459d1d29e..74ee7bdbbf 100644 --- a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs @@ -2,6 +2,7 @@ using System.Numerics; using Content.Client.Items; using Content.Client.Weapons.Ranged.Components; using Content.Shared.Camera; +using Content.Shared.CombatMode; using Content.Shared.Spawners.Components; using Content.Shared.Weapons.Ranged; using Content.Shared.Weapons.Ranged.Components; @@ -126,7 +127,7 @@ public sealed partial class GunSystem : SharedGunSystem var entityNull = _player.LocalPlayer?.ControlledEntity; - if (entityNull == null) + if (entityNull == null || !TryComp(entityNull, out var combat) || !combat.IsInCombatMode) { return; } diff --git a/Content.Server/NPC/Components/NPCSteeringComponent.cs b/Content.Server/NPC/Components/NPCSteeringComponent.cs index d1ec137aa9..521e0688a1 100644 --- a/Content.Server/NPC/Components/NPCSteeringComponent.cs +++ b/Content.Server/NPC/Components/NPCSteeringComponent.cs @@ -39,6 +39,12 @@ public sealed class NPCSteeringComponent : Component #endregion + /// + /// Set to true from other systems if you wish to force the NPC to move closer. + /// + [DataField("forceMove")] + public bool ForceMove = false; + /// /// Next time we can change our steering direction. /// diff --git a/Content.Server/NPC/Systems/NPCCombatSystem.Ranged.cs b/Content.Server/NPC/Systems/NPCCombatSystem.Ranged.cs index cbec56aeb3..10ec54c895 100644 --- a/Content.Server/NPC/Systems/NPCCombatSystem.Ranged.cs +++ b/Content.Server/NPC/Systems/NPCCombatSystem.Ranged.cs @@ -1,6 +1,7 @@ using Content.Server.NPC.Components; using Content.Shared.CombatMode; using Content.Shared.Interaction; +using Content.Shared.Physics; using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Events; using Robust.Shared.Map; @@ -132,13 +133,20 @@ public sealed partial class NPCCombatSystem if (comp.LOSAccumulator < 0f) { comp.LOSAccumulator += UnoccludedCooldown; - comp.TargetInLOS = _interaction.InRangeUnobstructed(uid, comp.Target, distance + 0.1f); + // For consistency with NPC steering. + comp.TargetInLOS = _interaction.InRangeUnobstructed(uid, Transform(comp.Target).Coordinates, distance + 0.1f); } if (!comp.TargetInLOS) { comp.ShootAccumulator = 0f; comp.Status = CombatStatus.NotInSight; + + if (TryComp(uid, out steering)) + { + steering.ForceMove = true; + } + continue; } @@ -188,8 +196,14 @@ public sealed partial class NPCCombatSystem targetCordinates = new EntityCoordinates(xform.MapUid!.Value, targetSpot); } - _gun.AttemptShoot(uid, gunUid, gun, targetCordinates); comp.Status = CombatStatus.Normal; + + if (gun.NextFire > _timing.CurTime) + { + return; + } + + _gun.AttemptShoot(uid, gunUid, gun, targetCordinates); } } } diff --git a/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs b/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs index 8be04ec116..920db537df 100644 --- a/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs +++ b/Content.Server/NPC/Systems/NPCSteeringSystem.Context.cs @@ -81,7 +81,7 @@ public sealed partial class NPCSteeringSystem // Check if we're in LOS if that's required. // TODO: Need something uhh better not sure on the interaction between these. - if (steering.ArriveOnLineOfSight) + if (!steering.ForceMove && steering.ArriveOnLineOfSight) { // TODO: use vision range inLos = _interaction.InRangeUnobstructed(uid, steering.Coordinates, 10f); @@ -105,6 +105,7 @@ public sealed partial class NPCSteeringSystem else { steering.LineOfSightTimer = 0f; + steering.ForceMove = false; } // We've arrived, nothing else matters. diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index 8866fcf55a..a24d2bf358 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -126,8 +126,11 @@ public abstract partial class SharedGunSystem : EntitySystem var user = args.SenderSession.AttachedEntity; if (user == null || + !_combatMode.IsInCombatMode(user) || !TryGetGun(user.Value, out var ent, out var gun)) + { return; + } if (ent != msg.Gun) return; @@ -165,9 +168,6 @@ public abstract partial class SharedGunSystem : EntitySystem gunEntity = default; gunComp = null; - if (!_combatMode.IsInCombatMode(entity)) - return false; - if (EntityManager.TryGetComponent(entity, out HandsComponent? hands) && hands.ActiveHandEntity is { } held && TryComp(held, out GunComponent? gun)) diff --git a/Resources/Prototypes/NPCs/Combat/gun.yml b/Resources/Prototypes/NPCs/Combat/gun.yml index 21066440b8..2b5ccd9fa5 100644 --- a/Resources/Prototypes/NPCs/Combat/gun.yml +++ b/Resources/Prototypes/NPCs/Combat/gun.yml @@ -71,6 +71,7 @@ - !type:HTNPrimitiveTask preconditions: + - !type:ActiveHandFreePrecondition - !type:TargetInRangePrecondition targetKey: Target rangeKey: InteractRange diff --git a/Resources/Prototypes/NPCs/Combat/melee.yml b/Resources/Prototypes/NPCs/Combat/melee.yml index aab6e4d148..e35dc82050 100644 --- a/Resources/Prototypes/NPCs/Combat/melee.yml +++ b/Resources/Prototypes/NPCs/Combat/melee.yml @@ -38,6 +38,7 @@ - !type:HTNPrimitiveTask preconditions: + - !type:ActiveHandFreePrecondition - !type:TargetInRangePrecondition targetKey: Target rangeKey: InteractRange