]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Remove gun .Owners (#14585)
authormetalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Sat, 11 Mar 2023 09:08:22 +0000 (20:08 +1100)
committerGitHub <noreply@github.com>
Sat, 11 Mar 2023 09:08:22 +0000 (20:08 +1100)
18 files changed:
Content.Client/Weapons/Ranged/GunSpreadOverlay.cs
Content.Client/Weapons/Ranged/Systems/GunSystem.AmmoCounter.cs
Content.Client/Weapons/Ranged/Systems/GunSystem.cs
Content.Server/NPC/Systems/NPCCombatSystem.Ranged.cs
Content.Server/Singularity/EntitySystems/EmitterSystem.cs
Content.Server/Weapons/Ranged/Systems/GunSystem.Revolver.cs
Content.Server/Weapons/Ranged/Systems/GunSystem.cs
Content.Shared/Weapons/Ranged/Events/TakeAmmoEvent.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.BasicEntity.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Battery.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Cartridges.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.ChamberMagazine.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Container.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Interactions.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Magazine.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Revolver.cs
Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs

index b817bffee4ef321769847d04da406cab2a492a44..d179f3f63f983fd60ce2a7f6785c024842be2a58 100644 (file)
@@ -36,20 +36,24 @@ public sealed class GunSpreadOverlay : Overlay
         var player = _player.LocalPlayer?.ControlledEntity;
 
         if (player == null ||
-            !_entManager.TryGetComponent<TransformComponent>(player, out var xform)) return;
+            !_entManager.TryGetComponent<TransformComponent>(player, out var xform))
+        {
+            return;
+        }
 
         var mapPos = xform.MapPosition;
 
-        if (mapPos.MapId == MapId.Nullspace) return;
+        if (mapPos.MapId == MapId.Nullspace)
+            return;
 
-        var gun = _guns.GetGun(player.Value);
-
-        if (gun == null) return;
+        if (!_guns.TryGetGun(player.Value, out var gunUid, out var gun))
+            return;
 
         var mouseScreenPos = _input.MouseScreenPosition;
         var mousePos = _eye.ScreenToMap(mouseScreenPos);
 
-        if (mapPos.MapId != mousePos.MapId) return;
+        if (mapPos.MapId != mousePos.MapId)
+            return;
 
         // (☞゚ヮ゚)☞
         var maxSpread = gun.MaxAngle;
index afb4229bb7b93e65feb609e6ed2e66dfa370fe8b..10f789b42a187769b728e1a2314eddcfdb76e82d 100644 (file)
@@ -27,7 +27,8 @@ public sealed partial class GunSystem
     /// <param name="component"></param>
     private void RefreshControl(EntityUid uid, AmmoCounterComponent? component = null)
     {
-        if (!Resolve(uid, ref component, false)) return;
+        if (!Resolve(uid, ref component, false))
+            return;
 
         component.Control?.Dispose();
         component.Control = null;
@@ -44,7 +45,8 @@ public sealed partial class GunSystem
 
     private void UpdateAmmoCount(EntityUid uid, AmmoCounterComponent component)
     {
-        if (component.Control == null) return;
+        if (component.Control == null)
+            return;
 
         var ev = new UpdateAmmoCounterEvent()
         {
@@ -59,7 +61,8 @@ public sealed partial class GunSystem
         // Don't use resolves because the method is shared and there's no compref and I'm trying to
         // share as much code as possible
         if (!Timing.IsFirstTimePredicted ||
-            !TryComp<AmmoCounterComponent>(uid, out var clientComp)) return;
+            !TryComp<AmmoCounterComponent>(uid, out var clientComp))
+            return;
 
         UpdateAmmoCount(uid, clientComp);
     }
index 2c52865cd60e4556d26af95b446fd54ce43dbe64..f41c50fc90f9e4981462631c5b4215a2814d8caa 100644 (file)
@@ -12,10 +12,8 @@ using Robust.Client.Graphics;
 using Robust.Client.Input;
 using Robust.Client.Player;
 using Robust.Shared.Animations;
-using Robust.Shared.Audio;
 using Robust.Shared.Input;
 using Robust.Shared.Map;
-using Robust.Shared.Player;
 using Robust.Shared.Utility;
 using SharedGunSystem = Content.Shared.Weapons.Ranged.Systems.SharedGunSystem;
 
@@ -35,7 +33,9 @@ public sealed partial class GunSystem : SharedGunSystem
         get => _spreadOverlay;
         set
         {
-            if (_spreadOverlay == value) return;
+            if (_spreadOverlay == value)
+                return;
+
             _spreadOverlay = value;
             var overlayManager = IoCManager.Resolve<IOverlayManager>();
 
@@ -131,9 +131,8 @@ public sealed partial class GunSystem : SharedGunSystem
         }
 
         var entity = entityNull.Value;
-        var gun = GetGun(entity);
 
-        if (gun == null)
+        if (!TryGetGun(entity, out var gunUid, out var gun))
         {
             return;
         }
@@ -141,7 +140,7 @@ public sealed partial class GunSystem : SharedGunSystem
         if (_inputSystem.CmdStates.GetState(EngineKeyFunctions.Use) != BoundKeyState.Down)
         {
             if (gun.ShotCounter != 0)
-                EntityManager.RaisePredictiveEvent(new RequestStopShootEvent { Gun = gun.Owner });
+                EntityManager.RaisePredictiveEvent(new RequestStopShootEvent { Gun = gunUid });
             return;
         }
 
@@ -153,40 +152,40 @@ public sealed partial class GunSystem : SharedGunSystem
         if (mousePos.MapId == MapId.Nullspace)
         {
             if (gun.ShotCounter != 0)
-                EntityManager.RaisePredictiveEvent(new RequestStopShootEvent { Gun = gun.Owner });
+                EntityManager.RaisePredictiveEvent(new RequestStopShootEvent { Gun = gunUid });
 
             return;
         }
 
         // 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, EntityManager);
+        var coordinates = EntityCoordinates.FromMap(entity, mousePos, Transform, EntityManager);
 
         Sawmill.Debug($"Sending shoot request tick {Timing.CurTick} / {Timing.CurTime}");
 
         EntityManager.RaisePredictiveEvent(new RequestShootEvent
         {
             Coordinates = coordinates,
-            Gun = gun.Owner,
+            Gun = gunUid,
         });
     }
 
-    public override void Shoot(GunComponent gun, List<IShootable> ammo, EntityCoordinates fromCoordinates, EntityCoordinates toCoordinates, EntityUid? user = null)
+    public override void Shoot(EntityUid gunUid, GunComponent gun, List<(EntityUid? Entity, IShootable Shootable)> ammo, EntityCoordinates fromCoordinates, EntityCoordinates toCoordinates, EntityUid? user = null)
     {
         // Rather than splitting client / server for every ammo provider it's easier
         // to just delete the spawned entities. This is for programmer sanity despite the wasted perf.
         // This also means any ammo specific stuff can be grabbed as necessary.
-        var direction = fromCoordinates.ToMapPos(EntityManager) - toCoordinates.ToMapPos(EntityManager);
+        var direction = fromCoordinates.ToMapPos(EntityManager, Transform) - toCoordinates.ToMapPos(EntityManager, Transform);
 
-        foreach (var ent in ammo)
+        foreach (var (ent, shootable) in ammo)
         {
-            switch (ent)
+            switch (shootable)
             {
                 case CartridgeAmmoComponent cartridge:
                     if (!cartridge.Spent)
                     {
-                        SetCartridgeSpent(cartridge, true);
-                        MuzzleFlash(gun.Owner, cartridge, user);
-                        Audio.PlayPredicted(gun.SoundGunshot, gun.Owner, user);
+                        SetCartridgeSpent(ent!.Value, cartridge, true);
+                        MuzzleFlash(gunUid, cartridge, user);
+                        Audio.PlayPredicted(gun.SoundGunshot, gunUid, user);
                         Recoil(user, direction);
                         // TODO: Can't predict entity deletions.
                         //if (cartridge.DeleteOnSpawn)
@@ -194,24 +193,24 @@ public sealed partial class GunSystem : SharedGunSystem
                     }
                     else
                     {
-                        Audio.PlayPredicted(gun.SoundEmpty, gun.Owner, user);
+                        Audio.PlayPredicted(gun.SoundEmpty, gunUid, user);
                     }
 
-                    if (cartridge.Owner.IsClientSide())
-                        Del(cartridge.Owner);
+                    if (ent!.Value.IsClientSide())
+                        Del(ent.Value);
 
                     break;
                 case AmmoComponent newAmmo:
-                    MuzzleFlash(gun.Owner, newAmmo, user);
-                    Audio.PlayPredicted(gun.SoundGunshot, gun.Owner, user);
+                    MuzzleFlash(gunUid, newAmmo, user);
+                    Audio.PlayPredicted(gun.SoundGunshot, gunUid, user);
                     Recoil(user, direction);
-                    if (newAmmo.Owner.IsClientSide())
-                        Del(newAmmo.Owner);
+                    if (ent!.Value.IsClientSide())
+                        Del(ent.Value);
                     else
-                        RemComp<AmmoComponent>(newAmmo.Owner);
+                        RemComp<AmmoComponent>(ent.Value);
                     break;
                 case HitscanPrototype:
-                    Audio.PlayPredicted(gun.SoundGunshot, gun.Owner, user);
+                    Audio.PlayPredicted(gun.SoundGunshot, gunUid, user);
                     Recoil(user, direction);
                     break;
             }
@@ -220,13 +219,17 @@ public sealed partial class GunSystem : SharedGunSystem
 
     private void Recoil(EntityUid? user, Vector2 recoil)
     {
-        if (!Timing.IsFirstTimePredicted || user == null || recoil == Vector2.Zero) return;
+        if (!Timing.IsFirstTimePredicted || user == null || recoil == Vector2.Zero)
+            return;
+
         _recoil.KickCamera(user.Value, recoil.Normalized * 0.5f);
     }
 
     protected override void Popup(string message, EntityUid? uid, EntityUid? user)
     {
-        if (uid == null || user == null || !Timing.IsFirstTimePredicted) return;
+        if (uid == null || user == null || !Timing.IsFirstTimePredicted)
+            return;
+
         PopupSystem.PopupEntity(message, uid.Value, user.Value);
     }
 
index 3149f2a5f1dc92b6ea119633581f769b3122ffae..19367703b9710097ffab15d20d5bf880df4ae28b 100644 (file)
@@ -49,8 +49,9 @@ public sealed partial class NPCCombatSystem
         var bodyQuery = GetEntityQuery<PhysicsComponent>();
         var xformQuery = GetEntityQuery<TransformComponent>();
         var combatQuery = GetEntityQuery<SharedCombatModeComponent>();
+        var query = EntityQueryEnumerator<NPCRangedCombatComponent, TransformComponent>();
 
-        foreach (var (comp, xform) in EntityQuery<NPCRangedCombatComponent, TransformComponent>())
+        while (query.MoveNext(out var uid, out var comp, out var xform))
         {
             if (comp.Status == CombatStatus.Unspecified)
                 continue;
@@ -70,14 +71,12 @@ public sealed partial class NPCCombatSystem
                 continue;
             }
 
-            if (combatQuery.TryGetComponent(comp.Owner, out var combatMode))
+            if (combatQuery.TryGetComponent(uid, out var combatMode))
             {
                 combatMode.IsInCombatMode = true;
             }
 
-            var gun = _gun.GetGun(comp.Owner);
-
-            if (gun == null)
+            if (!_gun.TryGetGun(uid, out var gunUid, out var gun))
             {
                 comp.Status = CombatStatus.NoWeapon;
                 comp.ShootAccumulator = 0f;
@@ -98,7 +97,7 @@ public sealed partial class NPCCombatSystem
             if (comp.LOSAccumulator < 0f)
             {
                 comp.LOSAccumulator += UnoccludedCooldown;
-                comp.TargetInLOS = _interaction.InRangeUnobstructed(comp.Owner, comp.Target, distance + 0.1f);
+                comp.TargetInLOS = _interaction.InRangeUnobstructed(uid, comp.Target, distance + 0.1f);
             }
 
             if (!comp.TargetInLOS)
@@ -110,7 +109,7 @@ public sealed partial class NPCCombatSystem
 
             if (!oldInLos && comp.SoundTargetInLOS != null)
             {
-                _audio.PlayPvs(comp.SoundTargetInLOS, comp.Owner);
+                _audio.PlayPvs(comp.SoundTargetInLOS, uid);
             }
 
             comp.ShootAccumulator += frameTime;
@@ -127,7 +126,7 @@ public sealed partial class NPCCombatSystem
             var goalRotation = (targetSpot - worldPos).ToWorldAngle();
             var rotationSpeed = comp.RotationSpeed;
 
-            if (!_rotate.TryRotateTo(comp.Owner, goalRotation, frameTime, comp.AccuracyThreshold, rotationSpeed?.Theta ?? double.MaxValue, xform))
+            if (!_rotate.TryRotateTo(uid, goalRotation, frameTime, comp.AccuracyThreshold, rotationSpeed?.Theta ?? double.MaxValue, xform))
             {
                 continue;
             }
@@ -154,7 +153,7 @@ public sealed partial class NPCCombatSystem
                 targetCordinates = new EntityCoordinates(xform.MapUid!.Value, targetSpot);
             }
 
-            _gun.AttemptShoot(comp.Owner, gun, targetCordinates);
+            _gun.AttemptShoot(uid, gunUid, gun, targetCordinates);
         }
     }
 }
index 10dd6f74ceef99e6fbf207b666222e19dd368834..869a98a615789b0fae7af4a9df051a686a590888 100644 (file)
@@ -298,7 +298,7 @@ namespace Content.Server.Singularity.EntitySystems
             _projectile.SetShooter(proj, uid);
 
             var targetPos = new EntityCoordinates(uid, (0, -1));
-            _gun.Shoot(guncomp, ent, xform.Coordinates, targetPos);
+            _gun.Shoot(uid, guncomp, ent, xform.Coordinates, targetPos);
         }
 
         private void UpdateAppearance(EmitterComponent component)
index 73e815f2c41f51a9d5f66d6127d8b5b33870b2af..6ff47507299f0615555d2b11df1d73f7d98d59b2 100644 (file)
@@ -4,12 +4,13 @@ namespace Content.Server.Weapons.Ranged.Systems;
 
 public sealed partial class GunSystem
 {
-    protected override void SpinRevolver(RevolverAmmoProviderComponent component, EntityUid? user = null)
+    protected override void SpinRevolver(EntityUid revolverUid, RevolverAmmoProviderComponent component, EntityUid? user = null)
     {
-        base.SpinRevolver(component, user);
+        base.SpinRevolver(revolverUid, component, user);
         var index = Random.Next(component.Capacity);
 
-        if (component.CurrentIndex == index) return;
+        if (component.CurrentIndex == index)
+            return;
 
         component.CurrentIndex = index;
         Dirty(component);
index f5c9b31ccc9141c01725a89b18f768f2fcaff3b7..cb67880a00a53d408264a4ebfe61f6353392b445 100644 (file)
@@ -4,7 +4,6 @@ using Content.Server.Cargo.Systems;
 using Content.Server.Examine;
 using Content.Server.Interaction;
 using Content.Server.Stunnable;
-using Content.Server.Weapons.Melee;
 using Content.Server.Weapons.Ranged.Components;
 using Content.Shared.Damage;
 using Content.Shared.Damage.Systems;
@@ -30,13 +29,13 @@ namespace Content.Server.Weapons.Ranged.Systems;
 
 public sealed partial class GunSystem : SharedGunSystem
 {
+    [Dependency] private readonly IAdminLogManager _adminLogger = default!;
     [Dependency] private readonly IComponentFactory _factory = default!;
     [Dependency] private readonly ExamineSystem _examine = default!;
     [Dependency] private readonly InteractionSystem _interaction = default!;
     [Dependency] private readonly PricingSystem _pricing = default!;
     [Dependency] private readonly StaminaSystem _stamina = default!;
     [Dependency] private readonly StunSystem _stun = default!;
-    [Dependency] private readonly IAdminLogManager _adminLogger = default!;
 
     public const float DamagePitchVariation = SharedMeleeWeaponSystem.DamagePitchVariation;
     public const float GunClumsyChance = 0.5f;
@@ -63,9 +62,10 @@ public sealed partial class GunSystem : SharedGunSystem
         args.Price += price * component.UnspawnedCount;
     }
 
-    public override void Shoot(GunComponent gun, List<IShootable> ammo, EntityCoordinates fromCoordinates, EntityCoordinates toCoordinates, EntityUid? user = null)
+    public override void Shoot(EntityUid gunUid, GunComponent gun, List<(EntityUid? Entity, IShootable Shootable)> ammo, EntityCoordinates fromCoordinates, EntityCoordinates toCoordinates, EntityUid? user = null)
     {
         // Try a clumsy roll
+        // TODO: Who put this here
         if (TryComp<ClumsyComponent>(user, out var clumsy))
         {
             for (var i = 0; i < ammo.Count; i++)
@@ -77,38 +77,38 @@ public sealed partial class GunSystem : SharedGunSystem
                     _stun.TryParalyze(user.Value, TimeSpan.FromSeconds(3f), true);
 
                     // Apply salt to the wound ("Honk!")
-                    Audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/bang.ogg"), gun.Owner);
-                    Audio.PlayPvs(new SoundPathSpecifier("/Audio/Items/bikehorn.ogg"), gun.Owner);
+                    Audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/bang.ogg"), gunUid);
+                    Audio.PlayPvs(new SoundPathSpecifier("/Audio/Items/bikehorn.ogg"), gunUid);
 
                     PopupSystem.PopupEntity(Loc.GetString("gun-clumsy"), user.Value);
-                    _adminLogger.Add(LogType.EntityDelete, LogImpact.Medium, $"Clumsy fire by {ToPrettyString(user.Value)} deleted {ToPrettyString(gun.Owner)}");
-                    Del(gun.Owner);
+                    _adminLogger.Add(LogType.EntityDelete, LogImpact.Medium, $"Clumsy fire by {ToPrettyString(user.Value)} deleted {ToPrettyString(gunUid)}");
+                    Del(gunUid);
                     return;
                 }
             }
         }
 
-        var fromMap = fromCoordinates.ToMap(EntityManager);
-        var toMap = toCoordinates.ToMapPos(EntityManager);
+        var fromMap = fromCoordinates.ToMap(EntityManager, Transform);
+        var toMap = toCoordinates.ToMapPos(EntityManager, Transform);
         var mapDirection = toMap - fromMap.Position;
         var mapAngle = mapDirection.ToAngle();
         var angle = GetRecoilAngle(Timing.CurTime, gun, mapDirection.ToAngle());
 
         // If applicable, this ensures the projectile is parented to grid on spawn, instead of the map.
-        EntityCoordinates fromEnt = MapManager.TryFindGridAt(fromMap, out var grid)
+        var fromEnt = MapManager.TryFindGridAt(fromMap, out var grid)
             ? fromCoordinates.WithEntityId(grid.Owner, EntityManager)
-            : new(MapManager.GetMapEntityId(fromMap.MapId), fromMap.Position);
+            : new EntityCoordinates(MapManager.GetMapEntityId(fromMap.MapId), fromMap.Position);
 
         // Update shot based on the recoil
         toMap = fromMap.Position + angle.ToVec() * mapDirection.Length;
         mapDirection = toMap - fromMap.Position;
-        var gunVelocity = Physics.GetMapLinearVelocity(gun.Owner);
+        var gunVelocity = Physics.GetMapLinearVelocity(gunUid);
 
         // I must be high because this was getting tripped even when true.
         // DebugTools.Assert(direction != Vector2.Zero);
         var shotProjectiles = new List<EntityUid>(ammo.Count);
 
-        foreach (var shootable in ammo)
+        foreach (var (ent, shootable) in ammo)
         {
             switch (shootable)
             {
@@ -135,46 +135,45 @@ public sealed partial class GunSystem : SharedGunSystem
                             shotProjectiles.Add(uid);
                         }
 
-                        //signal ChemicalAmmo to transfer solution
-                        RaiseLocalEvent(cartridge.Owner, new AmmoShotEvent()
+                        RaiseLocalEvent(ent!.Value, new AmmoShotEvent()
                         {
                             FiredProjectiles = shotProjectiles,
                         });
 
-                        SetCartridgeSpent(cartridge, true);
-                        MuzzleFlash(gun.Owner, cartridge, user);
-                        Audio.PlayPredicted(gun.SoundGunshot, gun.Owner, user);
+                        SetCartridgeSpent(ent.Value, cartridge, true);
+                        MuzzleFlash(gunUid, cartridge, user);
+                        Audio.PlayPredicted(gun.SoundGunshot, gunUid, user);
 
                         if (cartridge.DeleteOnSpawn)
-                            Del(cartridge.Owner);
+                            Del(ent.Value);
                     }
                     else
                     {
-                        Audio.PlayPredicted(gun.SoundEmpty, gun.Owner, user);
+                        Audio.PlayPredicted(gun.SoundEmpty, gunUid, user);
                     }
 
                     // Something like ballistic might want to leave it in the container still
-                    if (!cartridge.DeleteOnSpawn && !Containers.IsEntityInContainer(cartridge.Owner))
-                        EjectCartridge(cartridge.Owner);
+                    if (!cartridge.DeleteOnSpawn && !Containers.IsEntityInContainer(ent!.Value))
+                        EjectCartridge(ent.Value);
 
                     Dirty(cartridge);
                     break;
                 // Ammo shoots itself
                 case AmmoComponent newAmmo:
-                    shotProjectiles.Add(newAmmo.Owner);
-                    MuzzleFlash(gun.Owner, newAmmo, user);
-                    Audio.PlayPredicted(gun.SoundGunshot, gun.Owner, user);
+                    shotProjectiles.Add(ent!.Value);
+                    MuzzleFlash(gunUid, newAmmo, user);
+                    Audio.PlayPredicted(gun.SoundGunshot, gunUid, user);
 
                     // Do a throw
-                    if (!HasComp<ProjectileComponent>(newAmmo.Owner))
+                    if (!HasComp<ProjectileComponent>(ent.Value))
                     {
-                        RemComp<AmmoComponent>(newAmmo.Owner);
+                        RemComp<AmmoComponent>(ent.Value);
                         // TODO: Someone can probably yeet this a billion miles so need to pre-validate input somewhere up the call stack.
-                        ThrowingSystem.TryThrow(newAmmo.Owner, mapDirection, gun.ProjectileSpeed, user);
+                        ThrowingSystem.TryThrow(ent.Value, mapDirection, gun.ProjectileSpeed, user);
                         break;
                     }
 
-                    ShootProjectile(newAmmo.Owner, mapDirection, gunVelocity, user, gun.ProjectileSpeed);
+                    ShootProjectile(ent.Value, mapDirection, gunVelocity, user, gun.ProjectileSpeed);
                     break;
                 case HitscanPrototype hitscan:
                     var ray = new CollisionRay(fromMap.Position, mapDirection.Normalized, hitscan.CollisionMask);
@@ -194,7 +193,6 @@ public sealed partial class GunSystem : SharedGunSystem
 
                         var dmg = hitscan.Damage;
 
-                        bool deleted = false;
                         string hitName = ToPrettyString(hitEntity);
                         if (dmg != null)
                             dmg = Damageable.TryChangeDamage(hitEntity, dmg, origin: user);
@@ -202,9 +200,7 @@ public sealed partial class GunSystem : SharedGunSystem
                         // check null again, as TryChangeDamage returns modified damage values
                         if (dmg != null)
                         {
-                            deleted = Deleted(hitEntity);
-
-                            if (!deleted)
+                            if (!Deleted(hitEntity))
                             {
                                 if (dmg.Total > FixedPoint2.Zero)
                                     RaiseNetworkEvent(new DamageEffectEvent(Color.Red, new List<EntityUid> {result.HitEntity}), Filter.Pvs(hitEntity, entityManager: EntityManager));
@@ -230,17 +226,17 @@ public sealed partial class GunSystem : SharedGunSystem
                         FireEffects(fromCoordinates, hitscan.MaxLength, mapDirection.ToAngle(), hitscan);
                     }
 
-                    Audio.PlayPredicted(gun.SoundGunshot, gun.Owner, user);
+                    Audio.PlayPredicted(gun.SoundGunshot, gunUid, user);
                     break;
                 default:
                     throw new ArgumentOutOfRangeException();
             }
         }
 
-        RaiseLocalEvent(gun.Owner, new AmmoShotEvent()
+        RaiseLocalEvent(gunUid, new AmmoShotEvent()
         {
             FiredProjectiles = shotProjectiles,
-        }, false);
+        });
     }
 
     public void ShootProjectile(EntityUid uid, Vector2 direction, Vector2 gunVelocity, EntityUid? user = null, float speed = 20f)
@@ -259,7 +255,7 @@ public sealed partial class GunSystem : SharedGunSystem
             Projectiles.SetShooter(projectile, user.Value);
         }
 
-        Transform(uid).WorldRotation = direction.ToWorldAngle();
+        Transform.SetWorldRotation(uid, direction.ToWorldAngle());
     }
 
     /// <summary>
@@ -320,7 +316,7 @@ public sealed partial class GunSystem : SharedGunSystem
 
         if (!forceWeaponSound && modifiedDamage != null && modifiedDamage.Total > 0 && TryComp<RangedDamageSoundComponent>(otherEntity, out var rangedSound))
         {
-            var type = MeleeWeaponSystem.GetHighestDamageSound(modifiedDamage, ProtoManager);
+            var type = SharedMeleeWeaponSystem.GetHighestDamageSound(modifiedDamage, ProtoManager);
 
             if (type != null && rangedSound.SoundTypes?.TryGetValue(type, out var damageSoundType) == true)
             {
@@ -354,12 +350,14 @@ public sealed partial class GunSystem : SharedGunSystem
 
         // We'll get the effects relative to the grid / map of the firer
         // Look you could probably optimise this a bit with redundant transforms at this point.
-        if (TryComp<TransformComponent>(gridUid, out var gridXform))
+        var xformQuery = GetEntityQuery<TransformComponent>();
+
+        if (xformQuery.TryGetComponent(gridUid, out var gridXform))
         {
-            var (_, gridRot, gridInvMatrix) = gridXform.GetWorldPositionRotationInvMatrix();
+            var (_, gridRot, gridInvMatrix) = Transform.GetWorldPositionRotationInvMatrix(gridUid.Value, xformQuery);
 
             fromCoordinates = new EntityCoordinates(gridUid.Value,
-                gridInvMatrix.Transform(fromCoordinates.ToMapPos(EntityManager)));
+                gridInvMatrix.Transform(fromCoordinates.ToMapPos(EntityManager, Transform)));
 
             // Use the fallback angle I guess?
             angle -= gridRot;
index 5ad53fd970f0e8d882e42603354932e4f420ef2e..a28816d8e202581948107147fc97b16b5b8e080f 100644 (file)
@@ -7,16 +7,16 @@ namespace Content.Shared.Weapons.Ranged.Events;
 /// </summary>
 public sealed class TakeAmmoEvent : EntityEventArgs
 {
-    public EntityUid? User;
+    public readonly EntityUid? User;
     public readonly int Shots;
-    public List<IShootable> Ammo;
+    public List<(EntityUid? Entity, IShootable Shootable)> Ammo;
 
     /// <summary>
     /// Coordinates to spawn the ammo at.
     /// </summary>
     public EntityCoordinates Coordinates;
 
-    public TakeAmmoEvent(int shots, List<IShootable> ammo, EntityCoordinates coordinates, EntityUid? user)
+    public TakeAmmoEvent(int shots, List<(EntityUid? Entity, IShootable Shootable)> ammo, EntityCoordinates coordinates, EntityUid? user)
     {
         Shots = shots;
         Ammo = ammo;
index dcaaec58ab879f6a23c9104ebb14e40ffae5d288..3bd3e9d7897b8bca6f8ea8d3fb5edf9a4d31c9ae 100644 (file)
@@ -8,7 +8,6 @@ using Robust.Shared.Containers;
 using Robust.Shared.GameStates;
 using Robust.Shared.Map;
 using Robust.Shared.Serialization;
-using Robust.Shared.Utility;
 
 namespace Content.Shared.Weapons.Ranged.Systems;
 
@@ -32,22 +31,24 @@ public abstract partial class SharedGunSystem
 
     private void OnBallisticUse(EntityUid uid, BallisticAmmoProviderComponent component, UseInHandEvent args)
     {
-        ManualCycle(component, Transform(uid).MapPosition, args.User);
+        ManualCycle(uid, component, Transform(uid).MapPosition, args.User);
         args.Handled = true;
     }
 
     private void OnBallisticInteractUsing(EntityUid uid, BallisticAmmoProviderComponent component, InteractUsingEvent args)
     {
-        if (args.Handled || component.Whitelist?.IsValid(args.Used, EntityManager) != true) return;
+        if (args.Handled || component.Whitelist?.IsValid(args.Used, EntityManager) != true)
+            return;
 
-        if (GetBallisticShots(component) >= component.Capacity) return;
+        if (GetBallisticShots(component) >= component.Capacity)
+            return;
 
         component.Entities.Add(args.Used);
         component.Container.Insert(args.Used);
         // Not predicted so
         Audio.PlayPredicted(component.SoundInsert, uid, args.User);
         args.Handled = true;
-        UpdateBallisticAppearance(component);
+        UpdateBallisticAppearance(uid, component);
         Dirty(component);
     }
 
@@ -93,20 +94,20 @@ public abstract partial class SharedGunSystem
             RaiseLocalEvent(ammoProvider, evInsert);
         }
 
-        List<IShootable> ammo = new();
+        List<(EntityUid? Entity, IShootable Shootable)> ammo = new();
         var evTakeAmmo = new TakeAmmoEvent(1, ammo, Transform(args.Used).Coordinates, args.User);
         RaiseLocalEvent(args.Used, evTakeAmmo);
 
-        foreach (var shot in ammo)
+        foreach (var (ent, _) in ammo)
         {
-            if (shot is not AmmoComponent cast)
+            if (ent == null)
                 continue;
 
-            if (!targetComponent.Whitelist.IsValid(cast.Owner))
+            if (!targetComponent.Whitelist.IsValid(ent.Value))
             {
                 Popup(
                     Loc.GetString("gun-ballistic-transfer-invalid",
-                        ("ammoEntity", cast.Owner),
+                        ("ammoEntity", ent.Value),
                         ("targetEntity", args.Target.Value)),
                     args.Used,
                     args.User);
@@ -114,27 +115,28 @@ public abstract partial class SharedGunSystem
                 // TODO: For better or worse, this will play a sound, but it's the
                 // more future-proof thing to do than copying the same code
                 // that OnBallisticInteractUsing has, sans sound.
-                SimulateInsertAmmo(cast.Owner, args.Used, Transform(args.Used).Coordinates);
+                SimulateInsertAmmo(ent.Value, args.Used, Transform(args.Used).Coordinates);
             }
             else
             {
-                SimulateInsertAmmo(cast.Owner, args.Target.Value, Transform(args.Target.Value).Coordinates);
+                SimulateInsertAmmo(ent.Value, args.Target.Value, Transform(args.Target.Value).Coordinates);
             }
 
-            if (cast.Owner.IsClientSide())
-                Del(cast.Owner);
+            if (ent.Value.IsClientSide())
+                Del(ent.Value);
         }
     }
 
     private void OnBallisticVerb(EntityUid uid, BallisticAmmoProviderComponent component, GetVerbsEvent<Verb> args)
     {
-        if (!args.CanAccess || !args.CanInteract || args.Hands == null) return;
+        if (!args.CanAccess || !args.CanInteract || args.Hands == null)
+            return;
 
         args.Verbs.Add(new Verb()
         {
             Text = Loc.GetString("gun-ballistic-cycle"),
             Disabled = GetBallisticShots(component) == 0,
-            Act = () => ManualCycle(component, Transform(uid).MapPosition, args.User),
+            Act = () => ManualCycle(uid, component, Transform(uid).MapPosition, args.User),
         });
     }
 
@@ -146,17 +148,17 @@ public abstract partial class SharedGunSystem
         args.PushMarkup(Loc.GetString("gun-magazine-examine", ("color", AmmoExamineColor), ("count", GetBallisticShots(component))));
     }
 
-    private void ManualCycle(BallisticAmmoProviderComponent component, MapCoordinates coordinates, EntityUid? user = null)
+    private void ManualCycle(EntityUid uid, BallisticAmmoProviderComponent component, MapCoordinates coordinates, EntityUid? user = null, GunComponent? gunComp = null)
     {
         // Reset shotting for cycling
-        if (TryComp<GunComponent>(component.Owner, out var gunComp) &&
+        if (Resolve(uid, ref gunComp, false) &&
             gunComp is { FireRate: > 0f })
         {
             gunComp.NextFire = Timing.CurTime + TimeSpan.FromSeconds(1 / gunComp.FireRate);
         }
 
         Dirty(component);
-        Audio.PlayPredicted(component.SoundRack, component.Owner, user);
+        Audio.PlayPredicted(component.SoundRack, uid, user);
 
         var shots = GetBallisticShots(component);
         component.Cycled = true;
@@ -165,9 +167,9 @@ public abstract partial class SharedGunSystem
 
         var text = Loc.GetString(shots == 0 ? "gun-ballistic-cycled-empty" : "gun-ballistic-cycled");
 
-        Popup(text, component.Owner, user);
-        UpdateBallisticAppearance(component);
-        UpdateAmmoCount(component.Owner);
+        Popup(text, uid, user);
+        UpdateBallisticAppearance(uid, component);
+        UpdateAmmoCount(uid);
     }
 
     protected abstract void Cycle(BallisticAmmoProviderComponent component, MapCoordinates coordinates);
@@ -184,7 +186,8 @@ public abstract partial class SharedGunSystem
 
     private void OnBallisticHandleState(EntityUid uid, BallisticAmmoProviderComponent component, ref ComponentHandleState args)
     {
-        if (args.Current is not BallisticAmmoProviderComponentState state) return;
+        if (args.Current is not BallisticAmmoProviderComponentState state)
+            return;
 
         component.Cycled = state.Cycled;
         component.UnspawnedCount = state.UnspawnedCount;
@@ -222,7 +225,8 @@ public abstract partial class SharedGunSystem
     {
         for (var i = 0; i < args.Shots; i++)
         {
-            if (!component.Cycled) break;
+            if (!component.Cycled)
+                break;
 
             EntityUid entity;
 
@@ -230,7 +234,7 @@ public abstract partial class SharedGunSystem
             {
                 entity = component.Entities[^1];
 
-                args.Ammo.Add(EnsureComp<AmmoComponent>(entity));
+                args.Ammo.Add((entity, EnsureComp<AmmoComponent>(entity)));
 
                 // Leave the entity as is if it doesn't auto cycle
                 // TODO: Suss this out with NewAmmoComponent as I don't think it gets removed from container properly
@@ -246,7 +250,7 @@ public abstract partial class SharedGunSystem
             {
                 component.UnspawnedCount--;
                 entity = Spawn(component.FillProto, args.Coordinates);
-                args.Ammo.Add(EnsureComp<AmmoComponent>(entity));
+                args.Ammo.Add((entity, EnsureComp<AmmoComponent>(entity)));
 
                 // Put it back in if it doesn't auto-cycle
                 if (HasComp<CartridgeAmmoComponent>(entity) && !component.AutoCycle)
@@ -269,7 +273,7 @@ public abstract partial class SharedGunSystem
             }
         }
 
-        UpdateBallisticAppearance(component);
+        UpdateBallisticAppearance(uid, component);
         Dirty(component);
     }
 
@@ -279,13 +283,13 @@ public abstract partial class SharedGunSystem
         args.Capacity = component.Capacity;
     }
 
-    private void UpdateBallisticAppearance(BallisticAmmoProviderComponent component)
+    private void UpdateBallisticAppearance(EntityUid uid, BallisticAmmoProviderComponent component)
     {
-        if (!Timing.IsFirstTimePredicted || !TryComp<AppearanceComponent>(component.Owner, out var appearance))
+        if (!Timing.IsFirstTimePredicted || !TryComp<AppearanceComponent>(uid, out var appearance))
             return;
 
-        Appearance.SetData(appearance.Owner, AmmoVisuals.AmmoCount, GetBallisticShots(component), appearance);
-        Appearance.SetData(appearance.Owner, AmmoVisuals.AmmoMax, component.Capacity, appearance);
+        Appearance.SetData(uid, AmmoVisuals.AmmoCount, GetBallisticShots(component), appearance);
+        Appearance.SetData(uid, AmmoVisuals.AmmoMax, component.Capacity, appearance);
     }
 
     [Serializable, NetSerializable]
index 73d8effe736ec942fe3e4cfec0b4e106b998f5b3..58c3f01d16c98bfbde69780cfc452742c321ac02 100644 (file)
@@ -38,7 +38,7 @@ public abstract partial class SharedGunSystem
             Dirty(component);
         }
 
-        UpdateBasicEntityAppearance(component);
+        UpdateBasicEntityAppearance(uid, component);
     }
 
     private void OnBasicEntityTakeAmmo(EntityUid uid, BasicEntityAmmoProviderComponent component, TakeAmmoEvent args)
@@ -54,10 +54,10 @@ public abstract partial class SharedGunSystem
             }
 
             var ent = Spawn(component.Proto, args.Coordinates);
-            args.Ammo.Add(EnsureComp<AmmoComponent>(ent));
+            args.Ammo.Add((ent, EnsureComp<AmmoComponent>(ent)));
         }
 
-        UpdateBasicEntityAppearance(component);
+        UpdateBasicEntityAppearance(uid, component);
         Dirty(component);
     }
 
@@ -67,13 +67,14 @@ public abstract partial class SharedGunSystem
         args.Count = component.Count ?? int.MaxValue;
     }
 
-    private void UpdateBasicEntityAppearance(BasicEntityAmmoProviderComponent component)
+    private void UpdateBasicEntityAppearance(EntityUid uid, BasicEntityAmmoProviderComponent component)
     {
-        if (!Timing.IsFirstTimePredicted || !TryComp<AppearanceComponent>(component.Owner, out var appearance)) return;
+        if (!Timing.IsFirstTimePredicted || !TryComp<AppearanceComponent>(uid, out var appearance))
+            return;
 
-        Appearance.SetData(appearance.Owner, AmmoVisuals.HasAmmo, component.Count != 0, appearance);
-        Appearance.SetData(appearance.Owner, AmmoVisuals.AmmoCount, component.Count ?? int.MaxValue, appearance);
-        Appearance.SetData(appearance.Owner, AmmoVisuals.AmmoMax, component.Capacity ?? int.MaxValue, appearance);
+        Appearance.SetData(uid, AmmoVisuals.HasAmmo, component.Count != 0, appearance);
+        Appearance.SetData(uid, AmmoVisuals.AmmoCount, component.Count ?? int.MaxValue, appearance);
+        Appearance.SetData(uid, AmmoVisuals.AmmoMax, component.Capacity ?? int.MaxValue, appearance);
     }
 
     #region Public API
@@ -88,7 +89,7 @@ public abstract partial class SharedGunSystem
 
         component.Count = count;
         Dirty(component);
-        UpdateBasicEntityAppearance(component);
+        UpdateBasicEntityAppearance(uid, component);
 
         return true;
     }
index 207429703979cdddbdaf944a9aac9bddfa4cd05d..1d6c85f6f15c9a9865acea8ba6e3562aa8de75ba 100644 (file)
@@ -29,7 +29,8 @@ public abstract partial class SharedGunSystem
 
     private void OnBatteryHandleState(EntityUid uid, BatteryAmmoProviderComponent component, ref ComponentHandleState args)
     {
-        if (args.Current is not BatteryAmmoProviderComponentState state) return;
+        if (args.Current is not BatteryAmmoProviderComponentState state)
+            return;
 
         component.Shots = state.Shots;
         component.Capacity = state.MaxShots;
@@ -56,7 +57,8 @@ public abstract partial class SharedGunSystem
         var shots = Math.Min(args.Shots, component.Shots);
 
         // Don't dirty if it's an empty fire.
-        if (shots == 0) return;
+        if (shots == 0)
+            return;
 
         for (var i = 0; i < shots; i++)
         {
@@ -90,15 +92,15 @@ public abstract partial class SharedGunSystem
         Appearance.SetData(uid, AmmoVisuals.AmmoMax, component.Capacity, appearance);
     }
 
-    private IShootable GetShootable(BatteryAmmoProviderComponent component, EntityCoordinates coordinates)
+    private (EntityUid? Entity, IShootable) GetShootable(BatteryAmmoProviderComponent component, EntityCoordinates coordinates)
     {
         switch (component)
         {
             case ProjectileBatteryAmmoProviderComponent proj:
                 var ent = Spawn(proj.Prototype, coordinates);
-                return EnsureComp<AmmoComponent>(ent);
+                return (ent, EnsureComp<AmmoComponent>(ent));
             case HitscanBatteryAmmoProviderComponent hitscan:
-                return ProtoManager.Index<HitscanPrototype>(hitscan.Prototype);
+                return (null, ProtoManager.Index<HitscanPrototype>(hitscan.Prototype));
             default:
                 throw new ArgumentOutOfRangeException();
         }
index 6d2c6163e3e912148f32e58130739943d82a7a60..14ed2df95091d1080c36966a0558ed5648a8b190 100644 (file)
@@ -14,7 +14,9 @@ public abstract partial class SharedGunSystem
 
     private void OnCartridgeHandleState(EntityUid uid, CartridgeAmmoComponent component, ref ComponentHandleState args)
     {
-        if (args.Current is not CartridgeAmmoComponentState state) return;
+        if (args.Current is not CartridgeAmmoComponentState state)
+            return;
+
         component.Spent = state.Spent;
     }
 
index db7350e35f70c9076753c8fa38455490d4b91c42..39e3a83a36aadc82ad3096fa96f9842b89cdf352 100644 (file)
@@ -27,7 +27,7 @@ public abstract partial class SharedGunSystem
         if (!args.IsInDetailsRange)
             return;
 
-        var (count, _) = GetChamberMagazineCountCapacity(component);
+        var (count, _) = GetChamberMagazineCountCapacity(uid, component);
         args.PushMarkup(Loc.GetString("gun-magazine-examine", ("color", AmmoExamineColor), ("count", count)));
     }
 
@@ -41,7 +41,9 @@ public abstract partial class SharedGunSystem
         }
 
         entity = slot.ContainedEntity;
-        if (entity == null) return false;
+        if (entity == null)
+            return false;
+
         container.Remove(entity.Value);
         return true;
     }
@@ -57,10 +59,10 @@ public abstract partial class SharedGunSystem
         return slot.ContainedEntity;
     }
 
-    protected (int, int) GetChamberMagazineCountCapacity(ChamberMagazineAmmoProviderComponent component)
+    protected (int, int) GetChamberMagazineCountCapacity(EntityUid uid, ChamberMagazineAmmoProviderComponent component)
     {
-        var count = GetChamberEntity(component.Owner) != null ? 1 : 0;
-        var (magCount, magCapacity) = GetMagazineCountCapacity(component);
+        var count = GetChamberEntity(uid) != null ? 1 : 0;
+        var (magCount, magCapacity) = GetMagazineCountCapacity(uid, component);
         return (count + magCount, magCapacity);
     }
 
@@ -81,7 +83,7 @@ public abstract partial class SharedGunSystem
 
         if (TryTakeChamberEntity(uid, out var chamberEnt))
         {
-            args.Ammo.Add(EnsureComp<AmmoComponent>(chamberEnt.Value));
+            args.Ammo.Add((chamberEnt.Value, EnsureComp<AmmoComponent>(chamberEnt.Value)));
         }
 
         var magEnt = GetMagazineEntity(uid);
@@ -90,15 +92,15 @@ public abstract partial class SharedGunSystem
         if (magEnt != null)
         {
             // We pass in Shots not Shots - 1 as we'll take the last entity and move it into the chamber.
-            var relayedArgs = new TakeAmmoEvent(args.Shots, new List<IShootable>(), args.Coordinates, args.User);
-            RaiseLocalEvent(magEnt.Value, relayedArgs, false);
+            var relayedArgs = new TakeAmmoEvent(args.Shots, new List<(EntityUid? Entity, IShootable Shootable)>(), args.Coordinates, args.User);
+            RaiseLocalEvent(magEnt.Value, relayedArgs);
 
             // Put in the nth slot back into the chamber
             // Rest of the ammo gets shot
             if (relayedArgs.Ammo.Count > 0)
             {
-                var newChamberEnt = ((AmmoComponent) relayedArgs.Ammo[^1]).Owner;
-                TryInsertChamber(uid, newChamberEnt);
+                var newChamberEnt = relayedArgs.Ammo[^1].Entity;
+                TryInsertChamber(uid, newChamberEnt!.Value);
             }
 
             // Anything above the chamber-refill amount gets fired.
@@ -117,7 +119,7 @@ public abstract partial class SharedGunSystem
         const int capacity = 1;
 
         var ammoEv = new GetAmmoCountEvent();
-        RaiseLocalEvent(magEnt.Value, ref ammoEv, false);
+        RaiseLocalEvent(magEnt.Value, ref ammoEv);
 
         FinaliseMagazineTakeAmmo(uid, component, args, count + ammoEv.Count, capacity + ammoEv.Capacity, appearance);
     }
index 453daded3019d5b43b4d236573823290d2205291..204faecdb6bbfa661e32327802991a0230f29a25 100644 (file)
@@ -32,7 +32,7 @@ public partial class SharedGunSystem
             if (_netMan.IsServer)
                 container.Remove(ent);
 
-            args.Ammo.Add(EnsureComp<AmmoComponent>(ent));
+            args.Ammo.Add((ent, EnsureComp<AmmoComponent>(ent)));
         }
     }
 
index 2b04c41e3308c60b6a76853695da2dd92769ca62..953881d7d6b7c6d1a5d93c49dbe411a4874d9352 100644 (file)
@@ -33,7 +33,7 @@ public abstract partial class SharedGunSystem
 
         AlternativeVerb verb = new()
         {
-            Act = () => SelectFire(component, nextMode, args.User),
+            Act = () => SelectFire(uid, component, nextMode, args.User),
             Text = Loc.GetString("gun-selector-verb", ("mode", GetLocSelector(nextMode))),
             Icon = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/VerbIcons/fold.svg.192dpi.png")),
         };
@@ -47,7 +47,9 @@ public abstract partial class SharedGunSystem
 
         foreach (var mode in Enum.GetValues<SelectiveFire>())
         {
-            if ((mode & component.AvailableModes) == 0x0) continue;
+            if ((mode & component.AvailableModes) == 0x0)
+                continue;
+
             modes.Add(mode);
         }
 
@@ -55,9 +57,10 @@ public abstract partial class SharedGunSystem
         return modes[(index + 1) % modes.Count];
     }
 
-    private void SelectFire(GunComponent component, SelectiveFire fire, EntityUid? user = null)
+    private void SelectFire(EntityUid uid, GunComponent component, SelectiveFire fire, EntityUid? user = null)
     {
-        if (component.SelectedMode == fire) return;
+        if (component.SelectedMode == fire)
+            return;
 
         DebugTools.Assert((component.AvailableModes  & fire) != 0x0);
         component.SelectedMode = fire;
@@ -69,22 +72,23 @@ public abstract partial class SharedGunSystem
         else
             component.NextFire += cooldown;
 
-        Audio.PlayPredicted(component.SoundModeToggle, component.Owner, user);
-        Popup(Loc.GetString("gun-selected-mode", ("mode", GetLocSelector(fire))), component.Owner, user);
+        Audio.PlayPredicted(component.SoundModeToggle, uid, user);
+        Popup(Loc.GetString("gun-selected-mode", ("mode", GetLocSelector(fire))), uid, user);
         Dirty(component);
     }
 
     /// <summary>
     /// Cycles the gun's <see cref="SelectiveFire"/> to the next available one.
     /// </summary>
-    public void CycleFire(GunComponent component, EntityUid? user = null)
+    public void CycleFire(EntityUid uid, GunComponent component, EntityUid? user = null)
     {
         // Noop
-        if (component.SelectedMode == component.AvailableModes) return;
+        if (component.SelectedMode == component.AvailableModes)
+            return;
 
         DebugTools.Assert((component.AvailableModes & component.SelectedMode) == component.SelectedMode);
         var nextMode = GetNextMode(component);
-        SelectFire(component, nextMode, user);
+        SelectFire(uid, component, nextMode, user);
     }
 
     // TODO: Actions need doing for guns anyway.
@@ -95,6 +99,6 @@ public abstract partial class SharedGunSystem
 
     private void OnCycleMode(EntityUid uid, GunComponent component, CycleModeEvent args)
     {
-        SelectFire(component, args.Mode, args.Performer);
+        SelectFire(uid, component, args.Mode, args.Performer);
     }
 }
index cabd0d06839ddb3183e7df951de45938fe91c19b..2faa6da9609e6b6be6e0321ee163ee1518c76ec5 100644 (file)
@@ -26,7 +26,7 @@ public abstract partial class SharedGunSystem
         if (!args.IsInDetailsRange)
             return;
 
-        var (count, _) = GetMagazineCountCapacity(component);
+        var (count, _) = GetMagazineCountCapacity(uid, component);
         args.PushMarkup(Loc.GetString("gun-magazine-examine", ("color", AmmoExamineColor), ("count", count)));
     }
 
@@ -34,23 +34,25 @@ public abstract partial class SharedGunSystem
     {
         var magEnt = GetMagazineEntity(uid);
 
-        if (magEnt == null) return;
+        if (magEnt == null)
+            return;
 
         RaiseLocalEvent(magEnt.Value, args);
         UpdateAmmoCount(uid);
-        UpdateMagazineAppearance(component, magEnt.Value);
+        UpdateMagazineAppearance(uid, component, magEnt.Value);
     }
 
     private void OnMagazineVerb(EntityUid uid, MagazineAmmoProviderComponent component, GetVerbsEvent<AlternativeVerb> args)
     {
-        if (!args.CanInteract || !args.CanAccess) return;
+        if (!args.CanInteract || !args.CanAccess)
+            return;
 
         var magEnt = GetMagazineEntity(uid);
 
         if (magEnt != null)
         {
             RaiseLocalEvent(magEnt.Value, args);
-            UpdateMagazineAppearance(component, magEnt.Value);
+            UpdateMagazineAppearance(magEnt.Value, component, magEnt.Value);
         }
     }
 
@@ -66,11 +68,11 @@ public abstract partial class SharedGunSystem
         Appearance.SetData(uid, AmmoVisuals.MagLoaded, GetMagazineEntity(uid) != null, appearance);
     }
 
-    protected (int, int) GetMagazineCountCapacity(MagazineAmmoProviderComponent component)
+    protected (int, int) GetMagazineCountCapacity(EntityUid uid, MagazineAmmoProviderComponent component)
     {
         var count = 0;
         var capacity = 1;
-        var magEnt = GetMagazineEntity(component.Owner);
+        var magEnt = GetMagazineEntity(uid);
 
         if (magEnt != null)
         {
@@ -86,7 +88,11 @@ public abstract partial class SharedGunSystem
     protected EntityUid? GetMagazineEntity(EntityUid uid)
     {
         if (!Containers.TryGetContainer(uid, MagazineSlot, out var container) ||
-            container is not ContainerSlot slot) return null;
+            container is not ContainerSlot slot)
+        {
+            return null;
+        }
+
         return slot.ContainedEntity;
     }
 
@@ -102,11 +108,11 @@ public abstract partial class SharedGunSystem
         }
 
         // Pass the event onwards.
-        RaiseLocalEvent(magEntity.Value, args, false);
+        RaiseLocalEvent(magEntity.Value, args);
         // Should be Dirtied by what other ammoprovider is handling it.
 
         var ammoEv = new GetAmmoCountEvent();
-        RaiseLocalEvent(magEntity.Value, ref ammoEv, false);
+        RaiseLocalEvent(magEntity.Value, ref ammoEv);
         FinaliseMagazineTakeAmmo(uid, component, args, ammoEv.Count, ammoEv.Capacity, appearance);
     }
 
@@ -115,23 +121,23 @@ public abstract partial class SharedGunSystem
         // If no ammo then check for autoeject
         if (component.AutoEject && args.Ammo.Count == 0)
         {
-            EjectMagazine(component);
+            EjectMagazine(uid, component);
             Audio.PlayPredicted(component.SoundAutoEject, uid, args.User);
         }
 
-        UpdateMagazineAppearance(appearance, true, count, capacity);
+        UpdateMagazineAppearance(uid, appearance, true, count, capacity);
     }
 
-    private void UpdateMagazineAppearance(MagazineAmmoProviderComponent component, EntityUid magEnt)
+    private void UpdateMagazineAppearance(EntityUid uid, MagazineAmmoProviderComponent component, EntityUid magEnt)
     {
-        TryComp<AppearanceComponent>(component.Owner, out var appearance);
+        TryComp<AppearanceComponent>(uid, out var appearance);
 
         var count = 0;
         var capacity = 0;
 
         if (component is ChamberMagazineAmmoProviderComponent chamber)
         {
-            count = GetChamberEntity(chamber.Owner) != null ? 1 : 0;
+            count = GetChamberEntity(uid) != null ? 1 : 0;
             capacity = 1;
         }
 
@@ -143,27 +149,28 @@ public abstract partial class SharedGunSystem
             capacity += addCapacity;
         }
 
-        UpdateMagazineAppearance(appearance, true, count, capacity);
+        UpdateMagazineAppearance(uid, appearance, true, count, capacity);
     }
 
-    private void UpdateMagazineAppearance(AppearanceComponent? appearance, bool magLoaded, int count, int capacity)
+    private void UpdateMagazineAppearance(EntityUid uid, AppearanceComponent? appearance, bool magLoaded, int count, int capacity)
     {
         if (appearance == null)
             return;
 
         // Copy the magazine's appearance data
-        Appearance.SetData(appearance.Owner, AmmoVisuals.MagLoaded, magLoaded, appearance);
-        Appearance.SetData(appearance.Owner, AmmoVisuals.HasAmmo, count != 0, appearance);
-        Appearance.SetData(appearance.Owner, AmmoVisuals.AmmoCount, count, appearance);
-        Appearance.SetData(appearance.Owner, AmmoVisuals.AmmoMax, capacity, appearance);
+        Appearance.SetData(uid, AmmoVisuals.MagLoaded, magLoaded, appearance);
+        Appearance.SetData(uid, AmmoVisuals.HasAmmo, count != 0, appearance);
+        Appearance.SetData(uid, AmmoVisuals.AmmoCount, count, appearance);
+        Appearance.SetData(uid, AmmoVisuals.AmmoMax, capacity, appearance);
     }
 
-    private void EjectMagazine(MagazineAmmoProviderComponent component)
+    private void EjectMagazine(EntityUid uid, MagazineAmmoProviderComponent component)
     {
-        var ent = GetMagazineEntity(component.Owner);
+        var ent = GetMagazineEntity(uid);
 
-        if (ent == null) return;
+        if (ent == null)
+            return;
 
-        _slots.TryEject(component.Owner, MagazineSlot, null, out var a, excludeUserAudio: true);
+        _slots.TryEject(uid, MagazineSlot, null, out var a, excludeUserAudio: true);
     }
 }
index 8f9a2475bb3d7be3b03da7c68f604bdd6abb5cf2..040d3f5713fcc4c4fe1fc1e270ad57347347d7ef 100644 (file)
@@ -34,9 +34,10 @@ public partial class SharedGunSystem
 
     private void OnRevolverInteractUsing(EntityUid uid, RevolverAmmoProviderComponent component, InteractUsingEvent args)
     {
-        if (args.Handled) return;
+        if (args.Handled)
+            return;
 
-        if (TryRevolverInsert(component, args.Used, args.User))
+        if (TryRevolverInsert(uid, component, args.Used, args.User))
             args.Handled = true;
     }
 
@@ -52,7 +53,8 @@ public partial class SharedGunSystem
 
     private void OnRevolverHandleState(EntityUid uid, RevolverAmmoProviderComponent component, ref ComponentHandleState args)
     {
-        if (args.Current is not RevolverAmmoProviderComponentState state) return;
+        if (args.Current is not RevolverAmmoProviderComponentState state)
+            return;
 
         var oldIndex = component.CurrentIndex;
         component.CurrentIndex = state.CurrentIndex;
@@ -73,7 +75,7 @@ public partial class SharedGunSystem
         }
     }
 
-    public bool TryRevolverInsert(RevolverAmmoProviderComponent component, EntityUid uid, EntityUid? user)
+    public bool TryRevolverInsert(EntityUid revolverUid, RevolverAmmoProviderComponent component, EntityUid uid, EntityUid? user)
     {
         if (component.Whitelist?.IsValid(uid, EntityManager) == false)
             return false;
@@ -93,19 +95,19 @@ public partial class SharedGunSystem
 
             if (freeSlots == 0)
             {
-                Popup(Loc.GetString("gun-revolver-full"), component.Owner, user);
+                Popup(Loc.GetString("gun-revolver-full"), revolverUid, user);
                 return false;
             }
 
             var xformQuery = GetEntityQuery<TransformComponent>();
             var xform = xformQuery.GetComponent(uid);
-            var ammo = new List<IShootable>(freeSlots);
+            var ammo = new List<(EntityUid? Entity, IShootable Shootable)>(freeSlots);
             var ev = new TakeAmmoEvent(freeSlots, ammo, xform.Coordinates, user);
             RaiseLocalEvent(uid, ev);
 
             if (ev.Ammo.Count == 0)
             {
-                Popup(Loc.GetString("gun-speedloader-empty"), component.Owner, user);
+                Popup(Loc.GetString("gun-speedloader-empty"), revolverUid, user);
                 return false;
             }
 
@@ -119,29 +121,29 @@ public partial class SharedGunSystem
                     continue;
                 }
 
-                var ent = ev.Ammo.Last();
+                var ent = ev.Ammo.Last().Entity;
                 ev.Ammo.RemoveAt(ev.Ammo.Count - 1);
 
-                if (ent is not AmmoComponent ammoComp)
+                if (ent == null)
                 {
                     Sawmill.Error($"Tried to load hitscan into a revolver which is unsupported");
                     continue;
                 }
 
-                component.AmmoSlots[index] = ammoComp.Owner;
-                component.AmmoContainer.Insert(ammoComp.Owner, EntityManager);
+                component.AmmoSlots[index] = ent.Value;
+                component.AmmoContainer.Insert(ent.Value, EntityManager);
 
                 if (ev.Ammo.Count == 0)
                     break;
             }
 
             DebugTools.Assert(ammo.Count == 0);
-            UpdateRevolverAppearance(component);
+            UpdateRevolverAppearance(revolverUid, component);
             UpdateAmmoCount(uid);
             Dirty(component);
 
-            Audio.PlayPredicted(component.SoundInsert, component.Owner, user);
-            Popup(Loc.GetString("gun-revolver-insert"), component.Owner, user);
+            Audio.PlayPredicted(component.SoundInsert, revolverUid, user);
+            Popup(Loc.GetString("gun-revolver-insert"), revolverUid, user);
             return true;
         }
 
@@ -151,30 +153,35 @@ public partial class SharedGunSystem
             var index = (component.CurrentIndex + i) % component.Capacity;
 
             if (component.AmmoSlots[index] != null ||
-                component.Chambers[index] != null) continue;
+                component.Chambers[index] != null)
+            {
+                continue;
+            }
 
             component.AmmoSlots[index] = uid;
             component.AmmoContainer.Insert(uid);
-            Audio.PlayPredicted(component.SoundInsert, component.Owner, user);
-            Popup(Loc.GetString("gun-revolver-insert"), component.Owner, user);
-            UpdateRevolverAppearance(component);
+            Audio.PlayPredicted(component.SoundInsert, revolverUid, user);
+            Popup(Loc.GetString("gun-revolver-insert"), revolverUid, user);
+            UpdateRevolverAppearance(revolverUid, component);
             UpdateAmmoCount(uid);
             Dirty(component);
             return true;
         }
-        Popup(Loc.GetString("gun-revolver-full"), component.Owner, user);
+
+        Popup(Loc.GetString("gun-revolver-full"), revolverUid, user);
         return false;
     }
 
     private void OnRevolverVerbs(EntityUid uid, RevolverAmmoProviderComponent component, GetVerbsEvent<AlternativeVerb> args)
     {
-        if (!args.CanAccess || !args.CanInteract || args.Hands == null) return;
+        if (!args.CanAccess || !args.CanInteract || args.Hands == null)
+            return;
 
         args.Verbs.Add(new AlternativeVerb()
         {
             Text = Loc.GetString("gun-revolver-empty"),
             Disabled = !AnyRevolverCartridges(component),
-            Act = () => EmptyRevolver(component, args.User),
+            Act = () => EmptyRevolver(uid, component, args.User),
             Priority = 1
         });
 
@@ -182,7 +189,7 @@ public partial class SharedGunSystem
         {
             Text = Loc.GetString("gun-revolver-spin"),
             // Category = VerbCategory.G,
-            Act = () => SpinRevolver(component, args.User)
+            Act = () => SpinRevolver(uid, component, args.User)
         });
     }
 
@@ -191,7 +198,10 @@ public partial class SharedGunSystem
         for (var i = 0; i < component.Capacity; i++)
         {
             if (component.Chambers[i] != null ||
-                component.AmmoSlots[i] != null) return true;
+                component.AmmoSlots[i] != null)
+            {
+                return true;
+            }
         }
 
         return false;
@@ -238,9 +248,9 @@ public partial class SharedGunSystem
         return count;
     }
 
-    public void EmptyRevolver(RevolverAmmoProviderComponent component, EntityUid? user = null)
+    public void EmptyRevolver(EntityUid revolverUid, RevolverAmmoProviderComponent component, EntityUid? user = null)
     {
-        var xform = Transform(component.Owner);
+        var xform = Transform(revolverUid);
         var mapCoordinates = xform.MapPosition;
         var anyEmpty = false;
 
@@ -259,7 +269,7 @@ public partial class SharedGunSystem
                     var uid = Spawn(component.FillPrototype, mapCoordinates);
 
                     if (TryComp<CartridgeAmmoComponent>(uid, out var cartridge))
-                        SetCartridgeSpent(cartridge, !(bool) chamber);
+                        SetCartridgeSpent(uid, cartridge, !(bool) chamber);
 
                     EjectCartridge(uid);
                 }
@@ -281,28 +291,28 @@ public partial class SharedGunSystem
 
         if (anyEmpty)
         {
-            Audio.PlayPredicted(component.SoundEject, component.Owner, user);
-            UpdateAmmoCount(component.Owner);
-            UpdateRevolverAppearance(component);
+            Audio.PlayPredicted(component.SoundEject, revolverUid, user);
+            UpdateAmmoCount(revolverUid);
+            UpdateRevolverAppearance(revolverUid, component);
             Dirty(component);
         }
     }
 
-    private void UpdateRevolverAppearance(RevolverAmmoProviderComponent component)
+    private void UpdateRevolverAppearance(EntityUid uid, RevolverAmmoProviderComponent component)
     {
-        if (!TryComp<AppearanceComponent>(component.Owner, out var appearance))
+        if (!TryComp<AppearanceComponent>(uid, out var appearance))
             return;
 
         var count = GetRevolverCount(component);
-        Appearance.SetData(component.Owner, AmmoVisuals.HasAmmo, count != 0, appearance);
-        Appearance.SetData(component.Owner, AmmoVisuals.AmmoCount, count, appearance);
-        Appearance.SetData(component.Owner, AmmoVisuals.AmmoMax, component.Capacity, appearance);
+        Appearance.SetData(uid, AmmoVisuals.HasAmmo, count != 0, appearance);
+        Appearance.SetData(uid, AmmoVisuals.AmmoCount, count, appearance);
+        Appearance.SetData(uid, AmmoVisuals.AmmoMax, component.Capacity, appearance);
     }
 
-    protected virtual void SpinRevolver(RevolverAmmoProviderComponent component, EntityUid? user = null)
+    protected virtual void SpinRevolver(EntityUid revolverUid, RevolverAmmoProviderComponent component, EntityUid? user = null)
     {
-        Audio.PlayPredicted(component.SoundSpin, component.Owner, user);
-        Popup(Loc.GetString("gun-revolver-spun"), component.Owner, user);
+        Audio.PlayPredicted(component.SoundSpin, revolverUid, user);
+        Popup(Loc.GetString("gun-revolver-spun"), revolverUid, user);
     }
 
     private void OnRevolverTakeAmmo(EntityUid uid, RevolverAmmoProviderComponent component, TakeAmmoEvent args)
@@ -327,14 +337,15 @@ public partial class SharedGunSystem
                     if (TryComp<CartridgeAmmoComponent>(ent, out var cartridge))
                     {
                         component.Chambers[index] = false;
-                        SetCartridgeSpent(cartridge, true);
-                        args.Ammo.Add(EnsureComp<AmmoComponent>(Spawn(cartridge.Prototype, args.Coordinates)));
+                        SetCartridgeSpent(ent, cartridge, true);
+                        var spawned = Spawn(cartridge.Prototype, args.Coordinates);
+                        args.Ammo.Add((spawned, EnsureComp<AmmoComponent>(spawned)));
                         Del(ent);
                         continue;
                     }
 
                     component.Chambers[i] = null;
-                    args.Ammo.Add(EnsureComp<AmmoComponent>(ent));
+                    args.Ammo.Add((ent, EnsureComp<AmmoComponent>(ent)));
                 }
             }
             else if (component.AmmoSlots[index] != null)
@@ -343,21 +354,23 @@ public partial class SharedGunSystem
 
                 if (TryComp<CartridgeAmmoComponent>(ent, out var cartridge))
                 {
-                    if (cartridge.Spent) continue;
+                    if (cartridge.Spent)
+                        continue;
 
-                    SetCartridgeSpent(cartridge, true);
-                    args.Ammo.Add(EnsureComp<AmmoComponent>(Spawn(cartridge.Prototype, args.Coordinates)));
+                    SetCartridgeSpent(ent.Value, cartridge, true);
+                    var spawned = Spawn(cartridge.Prototype, args.Coordinates);
+                    args.Ammo.Add((spawned, EnsureComp<AmmoComponent>(spawned)));
                     continue;
                 }
 
                 component.AmmoContainer.Remove(ent.Value);
                 component.AmmoSlots[index] = null;
-                args.Ammo.Add(EnsureComp<AmmoComponent>(ent.Value));
+                args.Ammo.Add((ent.Value, EnsureComp<AmmoComponent>(ent.Value)));
                 Transform(ent.Value).Coordinates = args.Coordinates;
             }
         }
 
-        UpdateRevolverAppearance(component);
+        UpdateRevolverAppearance(uid, component);
         Dirty(component);
     }
 
index 55e2dbfd9cb73f25d648926b3b9c137b1f4fd070..84f5922d69cd0619d336b1563558bf40c00cb515 100644 (file)
@@ -1,6 +1,6 @@
+using System.Diagnostics.CodeAnalysis;
 using Content.Shared.Actions;
 using Content.Shared.Administration.Logs;
-using Content.Shared.Audio;
 using Content.Shared.CombatMode;
 using Content.Shared.Containers.ItemSlots;
 using Content.Shared.Damage;
@@ -22,7 +22,6 @@ using Robust.Shared.Map;
 using Robust.Shared.Network;
 using Robust.Shared.Physics.Systems;
 using Robust.Shared.Physics.Components;
-using Robust.Shared.Player;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Random;
 using Robust.Shared.Serialization;
@@ -53,6 +52,7 @@ public abstract partial class SharedGunSystem : EntitySystem
     [Dependency] protected readonly SharedAudioSystem Audio = default!;
     [Dependency] private   readonly SharedGravitySystem _gravity = default!;
     [Dependency] protected readonly SharedProjectileSystem Projectiles = default!;
+    [Dependency] protected readonly SharedTransformSystem Transform = default!;
 
     protected ISawmill Sawmill = default!;
 
@@ -107,27 +107,31 @@ public abstract partial class SharedGunSystem : EntitySystem
     {
         var user = args.SenderSession.AttachedEntity;
 
-        if (user == null) return;
-
-        var gun = GetGun(user.Value);
+        if (user == null ||
+            !TryGetGun(user.Value, out var ent, out var gun))
+            return;
 
-        if (gun?.Owner != msg.Gun) return;
+        if (ent != msg.Gun)
+            return;
 
         gun.ShootCoordinates = msg.Coordinates;
         Sawmill.Debug($"Set shoot coordinates to {gun.ShootCoordinates}");
-        AttemptShoot(user.Value, gun);
+        AttemptShoot(user.Value, ent, gun);
     }
 
     private void OnStopShootRequest(RequestStopShootEvent ev, EntitySessionEventArgs args)
     {
         if (args.SenderSession.AttachedEntity == null ||
-            !TryComp<GunComponent>(ev.Gun, out var gun)) return;
-
-        var userGun = GetGun(args.SenderSession.AttachedEntity.Value);
+            !TryComp<GunComponent>(ev.Gun, out var gun) ||
+            !TryGetGun(args.SenderSession.AttachedEntity.Value, out _, out var userGun))
+        {
+            return;
+        }
 
-        if (userGun != gun) return;
+        if (userGun != gun)
+            return;
 
-        StopShooting(gun);
+        StopShooting(ev.Gun, gun);
     }
 
     private void OnGetState(EntityUid uid, GunComponent component, ref ComponentGetState args)
@@ -147,7 +151,8 @@ public abstract partial class SharedGunSystem : EntitySystem
 
     private void OnHandleState(EntityUid uid, GunComponent component, ref ComponentHandleState args)
     {
-        if (args.Current is not GunComponentState state) return;
+        if (args.Current is not GunComponentState state)
+            return;
 
         Sawmill.Debug($"Handle state: setting shot count from {component.ShotCounter} to {state.ShotCounter}");
         component.FireRate = state.FireRate;
@@ -168,27 +173,40 @@ public abstract partial class SharedGunSystem : EntitySystem
         return true;
     }
 
-    public GunComponent? GetGun(EntityUid entity)
+    public bool TryGetGun(EntityUid entity, out EntityUid gunEntity, [NotNullWhen(true)] out GunComponent? gunComp)
     {
+        gunEntity = default;
+        gunComp = null;
+
         if (!_combatMode.IsInCombatMode(entity))
-            return null;
+            return false;
 
         if (EntityManager.TryGetComponent(entity, out SharedHandsComponent? hands) &&
             hands.ActiveHandEntity is { } held &&
             TryComp(held, out GunComponent? gun))
         {
-            return gun;
+            gunEntity = held;
+            gunComp = gun;
+            return true;
         }
 
         // Last resort is check if the entity itself is a gun.
-        return !TryComp(entity, out gun) ? null : gun;
+        if (TryComp(entity, out gun))
+        {
+            gunEntity = entity;
+            gunComp = gun;
+            return true;
+        }
+
+        return false;
     }
 
-    private void StopShooting(GunComponent gun)
+    private void StopShooting(EntityUid uid, GunComponent gun)
     {
-        if (gun.ShotCounter == 0) return;
+        if (gun.ShotCounter == 0)
+            return;
 
-        Sawmill.Debug($"Stopped shooting {ToPrettyString(gun.Owner)}");
+        Sawmill.Debug($"Stopped shooting {ToPrettyString(uid)}");
         gun.ShotCounter = 0;
         gun.ShootCoordinates = null;
         Dirty(gun);
@@ -197,14 +215,14 @@ public abstract partial class SharedGunSystem : EntitySystem
     /// <summary>
     /// Attempts to shoot at the target coordinates. Resets the shot counter after every shot.
     /// </summary>
-    public void AttemptShoot(EntityUid user, GunComponent gun, EntityCoordinates toCoordinates)
+    public void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun, EntityCoordinates toCoordinates)
     {
         gun.ShootCoordinates = toCoordinates;
-        AttemptShoot(user, gun);
+        AttemptShoot(user, gunUid, gun);
         gun.ShotCounter = 0;
     }
 
-    private void AttemptShoot(EntityUid user, GunComponent gun)
+    private void AttemptShoot(EntityUid user, EntityUid gunUid, GunComponent gun)
     {
         if (gun.FireRate <= 0f)
             return;
@@ -260,22 +278,22 @@ public abstract partial class SharedGunSystem : EntitySystem
 
         var fromCoordinates = Transform(user).Coordinates;
         // Remove ammo
-        var ev = new TakeAmmoEvent(shots, new List<IShootable>(), fromCoordinates, user);
+        var ev = new TakeAmmoEvent(shots, new List<(EntityUid? Entity, IShootable Shootable)>(), fromCoordinates, user);
 
         // Listen it just makes the other code around it easier if shots == 0 to do this.
         if (shots > 0)
-            RaiseLocalEvent(gun.Owner, ev, false);
+            RaiseLocalEvent(gunUid, ev);
 
         DebugTools.Assert(ev.Ammo.Count <= shots);
         DebugTools.Assert(shots >= 0);
-        UpdateAmmoCount(gun.Owner);
+        UpdateAmmoCount(gunUid);
 
         // Even if we don't actually shoot update the ShotCounter. This is to avoid spamming empty sounds
         // where the gun may be SemiAuto or Burst.
         gun.ShotCounter += shots;
 
         var attemptEv = new AttemptShootEvent(user);
-        RaiseLocalEvent(gun.Owner, ref attemptEv);
+        RaiseLocalEvent(gunUid, ref attemptEv);
 
         if (ev.Ammo.Count <= 0 || attemptEv.Cancelled)
         {
@@ -286,7 +304,7 @@ public abstract partial class SharedGunSystem : EntitySystem
                 // Don't spam safety sounds at gun fire rate, play it at a reduced rate.
                 // May cause prediction issues? Needs more tweaking
                 gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds));
-                Audio.PlayPredicted(gun.SoundEmpty, gun.Owner, user);
+                Audio.PlayPredicted(gun.SoundEmpty, gunUid, user);
                 Dirty(gun);
                 return;
             }
@@ -295,19 +313,20 @@ public abstract partial class SharedGunSystem : EntitySystem
         }
 
         // Shoot confirmed - sounds also played here in case it's invalid (e.g. cartridge already spent).
-        Shoot(gun, ev.Ammo, fromCoordinates, toCoordinates.Value, user);
+        Shoot(gunUid, gun, ev.Ammo, fromCoordinates, toCoordinates.Value, user);
         var shotEv = new GunShotEvent(user);
-        RaiseLocalEvent(gun.Owner, ref shotEv);
+        RaiseLocalEvent(gunUid, ref shotEv);
         // Projectiles cause impulses especially important in non gravity environments
         if (TryComp<PhysicsComponent>(user, out var userPhysics))
         {
             if (_gravity.IsWeightless(user, userPhysics))
-                CauseImpulse(fromCoordinates, toCoordinates.Value, userPhysics);
+                CauseImpulse(fromCoordinates, toCoordinates.Value, user, userPhysics);
         }
         Dirty(gun);
     }
 
     public void Shoot(
+        EntityUid gunUid,
         GunComponent gun,
         EntityUid ammo,
         EntityCoordinates fromCoordinates,
@@ -315,26 +334,17 @@ public abstract partial class SharedGunSystem : EntitySystem
         EntityUid? user = null)
     {
         var shootable = EnsureComp<AmmoComponent>(ammo);
-        Shoot(gun, new List<IShootable>(1) { shootable }, fromCoordinates, toCoordinates, user);
+        Shoot(gunUid, gun, new List<(EntityUid? Entity, IShootable Shootable)>(1) { (ammo, shootable) }, fromCoordinates, toCoordinates, user);
     }
 
     public abstract void Shoot(
+        EntityUid gunUid,
         GunComponent gun,
-        List<IShootable> ammo,
+        List<(EntityUid? Entity, IShootable Shootable)> ammo,
         EntityCoordinates fromCoordinates,
         EntityCoordinates toCoordinates,
         EntityUid? user = null);
 
-    public void Shoot(
-        GunComponent gun,
-        IShootable ammo,
-        EntityCoordinates fromCoordinates,
-        EntityCoordinates toCoordinates,
-        EntityUid? user = null)
-    {
-        Shoot(gun, new List<IShootable>(1) { ammo }, fromCoordinates, toCoordinates, user);
-    }
-
     protected abstract void Popup(string message, EntityUid? uid, EntityUid? user);
 
     /// <summary>
@@ -342,13 +352,13 @@ public abstract partial class SharedGunSystem : EntitySystem
     /// </summary>
     protected virtual void UpdateAmmoCount(EntityUid uid) {}
 
-    protected void SetCartridgeSpent(CartridgeAmmoComponent cartridge, bool spent)
+    protected void SetCartridgeSpent(EntityUid uid, CartridgeAmmoComponent cartridge, bool spent)
     {
         if (cartridge.Spent != spent)
             Dirty(cartridge);
 
         cartridge.Spent = spent;
-        Appearance.SetData(cartridge.Owner, AmmoVisuals.Spent, spent);
+        Appearance.SetData(uid, AmmoVisuals.Spent, spent);
     }
 
     /// <summary>
@@ -385,15 +395,15 @@ public abstract partial class SharedGunSystem : EntitySystem
         CreateEffect(gun, ev, user);
     }
 
-    public void CauseImpulse(EntityCoordinates fromCoordinates, EntityCoordinates toCoordinates, PhysicsComponent userPhysics)
+    public void CauseImpulse(EntityCoordinates fromCoordinates, EntityCoordinates toCoordinates, EntityUid user, PhysicsComponent userPhysics)
     {
-        var fromMap = fromCoordinates.ToMapPos(EntityManager);
-        var toMap = toCoordinates.ToMapPos(EntityManager);
+        var fromMap = fromCoordinates.ToMapPos(EntityManager, Transform);
+        var toMap = toCoordinates.ToMapPos(EntityManager, Transform);
         var shotDirection = (toMap - fromMap).Normalized;
 
         const float impulseStrength = 5.0f;
         var impulseVector =  shotDirection * impulseStrength;
-        Physics.ApplyLinearImpulse(userPhysics.Owner, -impulseVector, body: userPhysics);
+        Physics.ApplyLinearImpulse(user, -impulseVector, body: userPhysics);
     }
     protected abstract void CreateEffect(EntityUid uid, MuzzleFlashEvent message, EntityUid? user = null);