]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Shotgun spread refactor (#27773)
authorRiceMar1244 <138547931+RiceMar1244@users.noreply.github.com>
Sat, 3 Aug 2024 13:26:32 +0000 (09:26 -0400)
committerGitHub <noreply@github.com>
Sat, 3 Aug 2024 13:26:32 +0000 (09:26 -0400)
* Moves spread data to new component

* Refactors shotgun spread code

* Makes shotgun cartridges and projectiles use new component

* Attempts to fix nullable build error

* Fixes hitscan weapons that I broke :(

* Saviour commit?

---------

Co-authored-by: EmoGarbage404 <retron404@gmail.com>
Content.Server/Weapons/Ranged/Systems/GunSystem.cs
Content.Shared/Projectiles/ProjectileSpreadComponent.cs [new file with mode: 0644]
Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs
Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/shotgun.yml
Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/explosives.yml

index 29f91988182f11bd46b8d3ea978771774f467a1e..3a5fa4540afe73d80d35a56ad0808ae1c74359c3 100644 (file)
@@ -129,27 +129,8 @@ public sealed partial class GunSystem : SharedGunSystem
                 case CartridgeAmmoComponent cartridge:
                     if (!cartridge.Spent)
                     {
-                        if (cartridge.Count > 1)
-                        {
-                            var ev = new GunGetAmmoSpreadEvent(cartridge.Spread);
-                            RaiseLocalEvent(gunUid, ref ev);
-
-                            var angles = LinearSpread(mapAngle - ev.Spread / 2,
-                                mapAngle + ev.Spread / 2, cartridge.Count);
-
-                            for (var i = 0; i < cartridge.Count; i++)
-                            {
-                                var uid = Spawn(cartridge.Prototype, fromEnt);
-                                ShootOrThrow(uid, angles[i].ToVec(), gunVelocity, gun, gunUid, user);
-                                shotProjectiles.Add(uid);
-                            }
-                        }
-                        else
-                        {
-                            var uid = Spawn(cartridge.Prototype, fromEnt);
-                            ShootOrThrow(uid, mapDirection, gunVelocity, gun, gunUid, user);
-                            shotProjectiles.Add(uid);
-                        }
+                        var uid = Spawn(cartridge.Prototype, fromEnt);
+                        CreateAndFireProjectiles(uid, cartridge);
 
                         RaiseLocalEvent(ent!.Value, new AmmoShotEvent()
                         {
@@ -157,8 +138,6 @@ public sealed partial class GunSystem : SharedGunSystem
                         });
 
                         SetCartridgeSpent(ent.Value, cartridge, true);
-                        MuzzleFlash(gunUid, cartridge, mapDirection.ToAngle(), user);
-                        Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
 
                         if (cartridge.DeleteOnSpawn)
                             Del(ent.Value);
@@ -177,10 +156,10 @@ public sealed partial class GunSystem : SharedGunSystem
                     break;
                 // Ammo shoots itself
                 case AmmoComponent newAmmo:
-                    shotProjectiles.Add(ent!.Value);
-                    MuzzleFlash(gunUid, newAmmo, mapDirection.ToAngle(), user);
-                    Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
-                    ShootOrThrow(ent.Value, mapDirection, gunVelocity, gun, gunUid, user);
+                    if (ent == null)
+                        break;
+                    CreateAndFireProjectiles(ent.Value, newAmmo);
+
                     break;
                 case HitscanPrototype hitscan:
 
@@ -295,6 +274,36 @@ public sealed partial class GunSystem : SharedGunSystem
         {
             FiredProjectiles = shotProjectiles,
         });
+
+        void CreateAndFireProjectiles(EntityUid ammoEnt, AmmoComponent ammoComp)
+        {
+            if (TryComp<ProjectileSpreadComponent>(ammoEnt, out var ammoSpreadComp))
+            {
+                var spreadEvent = new GunGetAmmoSpreadEvent(ammoSpreadComp.Spread);
+                RaiseLocalEvent(gunUid, ref spreadEvent);
+
+                var angles = LinearSpread(mapAngle - spreadEvent.Spread / 2,
+                    mapAngle + spreadEvent.Spread / 2, ammoSpreadComp.Count);
+
+                ShootOrThrow(ammoEnt, angles[0].ToVec(), gunVelocity, gun, gunUid, user);
+                shotProjectiles.Add(ammoEnt);
+
+                for (var i = 1; i < ammoSpreadComp.Count; i++)
+                {
+                    var newuid = Spawn(ammoSpreadComp.Proto, fromEnt);
+                    ShootOrThrow(newuid, angles[i].ToVec(), gunVelocity, gun, gunUid, user);
+                    shotProjectiles.Add(ammoEnt);
+                }
+            }
+            else
+            {
+                ShootOrThrow(ammoEnt, mapDirection, gunVelocity, gun, gunUid, user);
+                shotProjectiles.Add(ammoEnt);
+            }
+
+            MuzzleFlash(gunUid, ammoComp, mapDirection.ToAngle(), user);
+            Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
+        }
     }
 
     private void ShootOrThrow(EntityUid uid, Vector2 mapDirection, Vector2 gunVelocity, GunComponent gun, EntityUid gunUid, EntityUid? user)
diff --git a/Content.Shared/Projectiles/ProjectileSpreadComponent.cs b/Content.Shared/Projectiles/ProjectileSpreadComponent.cs
new file mode 100644 (file)
index 0000000..1edffe3
--- /dev/null
@@ -0,0 +1,32 @@
+using Content.Shared.Weapons.Ranged.Systems;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Projectiles;
+
+/// <summary>
+/// Spawns a spread of the projectiles when fired
+/// </summary>
+[RegisterComponent, NetworkedComponent, Access(typeof(SharedGunSystem))]
+public sealed partial class ProjectileSpreadComponent : Component
+{
+    /// <summary>
+    /// The entity prototype that will be fired by the rest of the spread.
+    /// Will generally be the same entity prototype as the first projectile being fired.
+    /// Needed for ammo components that do not specify a fired prototype, unlike cartridges.
+    /// </summary>
+    [DataField(required: true)]
+    public EntProtoId Proto;
+
+    /// <summary>
+    /// How much the ammo spreads when shot, in degrees. Does nothing if count is 0.
+    /// </summary>
+    [DataField]
+    public Angle Spread = Angle.FromDegrees(5);
+
+    /// <summary>
+    /// How many prototypes are spawned when shot.
+    /// </summary>
+    [DataField]
+    public int Count = 1;
+}
index 62af124252b9ced999ea6b0e5c8a1a49f5497d1e..3e1111a97d177b008e8d51f673b5d933f63dc818 100644 (file)
@@ -30,18 +30,6 @@ public sealed partial class CartridgeAmmoComponent : AmmoComponent
     [AutoNetworkedField]
     public bool Spent = false;
 
-    /// <summary>
-    /// How much the ammo spreads when shot, in degrees. Does nothing if count is 0.
-    /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField("spread")]
-    public Angle Spread = Angle.FromDegrees(5);
-
-    /// <summary>
-    /// How many prototypes are spawned when shot.
-    /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField("count")]
-    public int Count = 1;
-
     /// <summary>
     /// Caseless ammunition.
     /// </summary>
index 57b95cb9016b31801d035ca9a2022f5c017b1ba7..1d90fab7c2cc9b30b3ef95906cbead71b8a302fd 100644 (file)
@@ -9,8 +9,6 @@
     - Cartridge
     - ShellShotgun
   - type: CartridgeAmmo
-    count: 6
-    spread: 15
     soundEject:
       collection: ShellEject
   - type: Sprite
@@ -32,7 +30,6 @@
         map: [ "enum.AmmoVisualLayers.Base" ]
   - type: CartridgeAmmo
     proto: PelletShotgunBeanbag
-    count: 1
   - type: SpentAmmoVisuals
     state: "beanbag"
 
@@ -47,8 +44,6 @@
         map: [ "enum.AmmoVisualLayers.Base" ]
   - type: CartridgeAmmo
     proto: PelletShotgunSlug
-    count: 1
-    spread: 0
   - type: SpentAmmoVisuals
     state: "slug"
 
@@ -63,7 +58,6 @@
         map: [ "enum.AmmoVisualLayers.Base" ]
   - type: CartridgeAmmo
     proto: PelletShotgunFlare
-    count: 1
   - type: SpentAmmoVisuals
     state: "flare"
 
@@ -77,7 +71,7 @@
       - state: base
         map: [ "enum.AmmoVisualLayers.Base" ]
   - type: CartridgeAmmo
-    proto: PelletShotgun
+    proto: PelletShotgunSpread
 
 - type: entity
   id: ShellShotgunIncendiary
@@ -89,7 +83,7 @@
       - state: incendiary
         map: [ "enum.AmmoVisualLayers.Base" ]
   - type: CartridgeAmmo
-    proto: PelletShotgunIncendiary
+    proto: PelletShotgunIncendiarySpread
   - type: SpentAmmoVisuals
     state: "incendiary"
 
       - state: practice
         map: [ "enum.AmmoVisualLayers.Base" ]
   - type: CartridgeAmmo
-    proto: PelletShotgunPractice
+    proto: PelletShotgunPracticeSpread
   - type: SpentAmmoVisuals
     state: "practice"
 
         map: [ "enum.AmmoVisualLayers.Base" ]
   - type: CartridgeAmmo
     proto: PelletShotgunTranquilizer
-    count: 1
   - type: ChemicalAmmo
   - type: SolutionContainerManager
     solutions:
     graph: ImprovisedShotgunShellGraph
     node: shell
   - type: CartridgeAmmo
-    count: 10
-    spread: 45 
-    proto: PelletShotgunImprovised
+    proto: PelletShotgunImprovisedSpread
   - type: SpentAmmoVisuals
     state: "improvised"
 
         - state: depleted-uranium
           map: [ "enum.AmmoVisualLayers.Base" ]
     - type: CartridgeAmmo
-      count: 5
-      spread: 6
-      proto: PelletShotgunUranium
+      proto: PelletShotgunUraniumSpread
     - type: SpentAmmoVisuals
       state: "depleted-uranium"
index 6e4570e1a160976e2987a05dbbcf0119d444674e..ce79b6f417467a9ee75b1f8b7b31a3a571f7362c 100644 (file)
       types:
         Piercing: 10
 
+- type: entity
+  id: PelletShotgunSpread
+  noSpawn: true
+  parent: PelletShotgun
+  components:
+  - type: ProjectileSpread
+    proto: PelletShotgun
+    count: 6
+    spread: 15
+
 - type: entity
   id: PelletShotgunIncendiary
   name: pellet (.50 incendiary)
   - type: IgnitionSource
     ignited: true
 
+- type: entity
+  id: PelletShotgunIncendiarySpread
+  noSpawn: true
+  parent: PelletShotgunIncendiary
+  components:
+  - type: ProjectileSpread
+    proto: PelletShotgunIncendiary
+    count: 6
+    spread: 15
+
 - type: entity
   id: PelletShotgunPractice
   name: pellet (.50 practice)
       types:
         Blunt: 1
 
+- type: entity
+  id: PelletShotgunPracticeSpread
+  noSpawn: true
+  parent: PelletShotgunPractice
+  components:
+  - type: ProjectileSpread
+    proto: PelletShotgunPractice
+    count: 6
+    spread: 15
+
 - type: entity
   id: PelletShotgunImprovised
   name: improvised pellet
         Piercing: 3
         Slash: 3
 
+- type: entity
+  id: PelletShotgunImprovisedSpread
+  noSpawn: true
+  parent: PelletShotgunImprovised
+  components:
+  - type: ProjectileSpread
+    proto: PelletShotgunImprovised
+    count: 10
+    spread: 45
 
 - type: entity
   id: PelletShotgunTranquilizer
         Radiation: 5
         Piercing: 5
 
+- type: entity
+  id: PelletShotgunUraniumSpread
+  noSpawn: true
+  parent: PelletShotgunUranium
+  components:
+  - type: ProjectileSpread
+    proto: PelletShotgunUranium
+    count: 5
+    spread: 6
+
 - type: entity
   id: PelletGrapeshot #tally fucking ho
   name: grapeshot pellet
         Piercing: 25
         Structural: 5
 
+- type: entity
+  id: PelletGrapeshotSpread
+  noSpawn: true
+  parent: PelletGrapeshot
+  components:
+  - type: ProjectileSpread
+    proto: PelletGrapeshot
+    count: 5
+    spread: 40
+
 - type: entity
   id: PelletGlass
   name: glass shard
     damage:
       types:
         Slash: 25
+
+- type: entity
+  id: PelletGlassSpread
+  parent: PelletGlass
+  noSpawn: true
+  components:
+  - type: ProjectileSpread
+    proto: PelletGlass
+    count: 5
+    spread: 10
index 152de7e92f2e173784eaac87d16b866d7f7da10e..04d405e88159255440f4bbe175e20706c0082af8 100644 (file)
   parent: BaseCannonBall
   components:
   - type: CartridgeAmmo
-    proto: PelletGrapeshot
-    count: 5
-    spread: 40
+    proto: PelletGrapeshotSpread
     deleteOnSpawn: true
   - type: Sprite
     sprite: Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi
   parent: BaseCannonBall
   components:
   - type: CartridgeAmmo
-    proto: PelletGlass
-    count: 5
-    spread: 10
+    proto: PelletGlassSpread
     deleteOnSpawn: true
   - type: Sprite
     sprite: Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi