diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs index 5aba04bdf8..4a7711032e 100644 --- a/Content.Client/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.cs @@ -1,5 +1,6 @@ using System.Numerics; using Content.Client.Animations; +using Content.Client.Gameplay; using Content.Client.Items; using Content.Client.Weapons.Ranged.Components; using Content.Shared.Camera; @@ -13,6 +14,7 @@ using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Input; using Robust.Client.Player; +using Robust.Client.State; using Robust.Shared.Animations; using Robust.Shared.Input; using Robust.Shared.Map; @@ -30,6 +32,7 @@ public sealed partial class GunSystem : SharedGunSystem [Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IInputManager _inputManager = default!; [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IStateManager _state = default!; [Dependency] private readonly AnimationPlayerSystem _animPlayer = default!; [Dependency] private readonly InputSystem _inputSystem = default!; [Dependency] private readonly SharedCameraRecoilSystem _recoil = default!; @@ -174,10 +177,15 @@ public sealed partial class GunSystem : SharedGunSystem // Define target coordinates relative to gun entity, so that network latency on moving grids doesn't fuck up the target location. var coordinates = EntityCoordinates.FromMap(entity, mousePos, TransformSystem, EntityManager); + NetEntity? target = null; + if (_state.CurrentState is GameplayStateBase screen) + target = GetNetEntity(screen.GetClickedEntity(mousePos)); + Log.Debug($"Sending shoot request tick {Timing.CurTick} / {Timing.CurTime}"); EntityManager.RaisePredictiveEvent(new RequestShootEvent { + Target = target, Coordinates = GetNetCoordinates(coordinates), Gun = GetNetEntity(gunUid), }); diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs index f495f29e4a..986cac98dd 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs @@ -278,6 +278,13 @@ public sealed partial class GunSystem : SharedGunSystem private void ShootOrThrow(EntityUid uid, Vector2 mapDirection, Vector2 gunVelocity, GunComponent gun, EntityUid gunUid, EntityUid? user) { + if (gun.Target is { } target && !TerminatingOrDeleted(target)) + { + var targeted = EnsureComp(uid); + targeted.Target = target; + Dirty(uid, targeted); + } + // Do a throw if (!HasComp(uid)) { diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs index 0c2fcc0579..ee747554e1 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs @@ -10,12 +10,15 @@ using Content.Shared.Item; using Content.Shared.Mobs.Components; using Content.Shared.Movement.Events; using Content.Shared.Pointing; +using Content.Shared.Projectiles; using Content.Shared.Pulling.Events; using Content.Shared.Speech; using Content.Shared.Standing; using Content.Shared.Strip.Components; using Content.Shared.Throwing; +using Content.Shared.Weapons.Ranged.Components; using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Events; namespace Content.Shared.Mobs.Systems; @@ -43,6 +46,7 @@ public partial class MobStateSystem SubscribeLocalEvent(OnSleepAttempt); SubscribeLocalEvent(OnCombatModeShouldHandInteract); SubscribeLocalEvent(OnAttemptPacifiedAttack); + SubscribeLocalEvent(OnPreventCollide); } private void OnStateExitSubscribers(EntityUid target, MobStateComponent component, MobState state) @@ -175,5 +179,21 @@ public partial class MobStateSystem args.Cancelled = true; } + private void OnPreventCollide(Entity ent, ref PreventCollideEvent args) + { + if (args.Cancelled) + return; + + if (IsAlive(ent, ent)) + return; + + var other = args.OtherEntity; + if (HasComp(other) && + CompOrNull(other)?.Target != ent.Owner) + { + args.Cancelled = true; + } + } + #endregion } diff --git a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs index 5a335e7e5c..b404221abf 100644 --- a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs @@ -1,5 +1,3 @@ -using Content.Shared.Damage; -using Content.Shared.Tag; using Content.Shared.Weapons.Ranged.Events; using Content.Shared.Weapons.Ranged.Systems; using Robust.Shared.Audio; @@ -139,6 +137,12 @@ public sealed partial class GunComponent : Component [ViewVariables] public EntityCoordinates? ShootCoordinates = null; + /// + /// Who the gun is being requested to shoot at directly. + /// + [ViewVariables] + public EntityUid? Target = null; + /// /// The base value for how many shots to fire per burst. /// diff --git a/Content.Shared/Weapons/Ranged/Components/TargetedProjectileComponent.cs b/Content.Shared/Weapons/Ranged/Components/TargetedProjectileComponent.cs new file mode 100644 index 0000000000..b804176497 --- /dev/null +++ b/Content.Shared/Weapons/Ranged/Components/TargetedProjectileComponent.cs @@ -0,0 +1,12 @@ +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Shared.GameStates; + +namespace Content.Shared.Weapons.Ranged.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedGunSystem))] +public sealed partial class TargetedProjectileComponent : Component +{ + [DataField, AutoNetworkedField] + public EntityUid Target; +} diff --git a/Content.Shared/Weapons/Ranged/Events/RequestShootEvent.cs b/Content.Shared/Weapons/Ranged/Events/RequestShootEvent.cs index 21e90b2108..f5c4dd72b4 100644 --- a/Content.Shared/Weapons/Ranged/Events/RequestShootEvent.cs +++ b/Content.Shared/Weapons/Ranged/Events/RequestShootEvent.cs @@ -11,4 +11,5 @@ public sealed class RequestShootEvent : EntityEventArgs { public NetEntity Gun; public NetCoordinates Coordinates; + public NetEntity? Target; } diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index 51e2e1358f..4e51ca2b62 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -136,6 +136,7 @@ public abstract partial class SharedGunSystem : EntitySystem return; gun.ShootCoordinates = GetCoordinates(msg.Coordinates); + gun.Target = GetEntity(msg.Target); AttemptShoot(user.Value, ent, gun); } @@ -196,6 +197,7 @@ public abstract partial class SharedGunSystem : EntitySystem gun.ShotCounter = 0; gun.ShootCoordinates = null; + gun.Target = null; Dirty(uid, gun); }