From b432dc612520e08e5409af76d31a5e7fa42ea247 Mon Sep 17 00:00:00 2001 From: RiceMar1244 <138547931+RiceMar1244@users.noreply.github.com> Date: Sat, 3 Aug 2024 09:26:32 -0400 Subject: [PATCH] Shotgun spread refactor (#27773) * 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 --- .../Weapons/Ranged/Systems/GunSystem.cs | 63 +++++++++-------- .../Projectiles/ProjectileSpreadComponent.cs | 32 +++++++++ .../Ranged/Components/AmmoComponent.cs | 12 ---- .../Guns/Ammunition/Cartridges/shotgun.yml | 21 ++---- .../Guns/Ammunition/Projectiles/shotgun.yml | 69 +++++++++++++++++++ .../Weapons/Guns/Ammunition/explosives.yml | 8 +-- 6 files changed, 144 insertions(+), 61 deletions(-) create mode 100644 Content.Shared/Projectiles/ProjectileSpreadComponent.cs diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs index 29f9198818..3a5fa4540a 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs @@ -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(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 index 0000000000..1edffe3ba5 --- /dev/null +++ b/Content.Shared/Projectiles/ProjectileSpreadComponent.cs @@ -0,0 +1,32 @@ +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Projectiles; + +/// +/// Spawns a spread of the projectiles when fired +/// +[RegisterComponent, NetworkedComponent, Access(typeof(SharedGunSystem))] +public sealed partial class ProjectileSpreadComponent : Component +{ + /// + /// 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. + /// + [DataField(required: true)] + public EntProtoId Proto; + + /// + /// How much the ammo spreads when shot, in degrees. Does nothing if count is 0. + /// + [DataField] + public Angle Spread = Angle.FromDegrees(5); + + /// + /// How many prototypes are spawned when shot. + /// + [DataField] + public int Count = 1; +} diff --git a/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs b/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs index 62af124252..3e1111a97d 100644 --- a/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs @@ -30,18 +30,6 @@ public sealed partial class CartridgeAmmoComponent : AmmoComponent [AutoNetworkedField] public bool Spent = false; - /// - /// How much the ammo spreads when shot, in degrees. Does nothing if count is 0. - /// - [ViewVariables(VVAccess.ReadWrite), DataField("spread")] - public Angle Spread = Angle.FromDegrees(5); - - /// - /// How many prototypes are spawned when shot. - /// - [ViewVariables(VVAccess.ReadWrite), DataField("count")] - public int Count = 1; - /// /// Caseless ammunition. /// diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml index 57b95cb901..1d90fab7c2 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml @@ -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" @@ -103,7 +97,7 @@ - state: practice map: [ "enum.AmmoVisualLayers.Base" ] - type: CartridgeAmmo - proto: PelletShotgunPractice + proto: PelletShotgunPracticeSpread - type: SpentAmmoVisuals state: "practice" @@ -118,7 +112,6 @@ map: [ "enum.AmmoVisualLayers.Base" ] - type: CartridgeAmmo proto: PelletShotgunTranquilizer - count: 1 - type: ChemicalAmmo - type: SolutionContainerManager solutions: @@ -145,9 +138,7 @@ graph: ImprovisedShotgunShellGraph node: shell - type: CartridgeAmmo - count: 10 - spread: 45 - proto: PelletShotgunImprovised + proto: PelletShotgunImprovisedSpread - type: SpentAmmoVisuals state: "improvised" @@ -161,8 +152,6 @@ - state: depleted-uranium map: [ "enum.AmmoVisualLayers.Base" ] - type: CartridgeAmmo - count: 5 - spread: 6 - proto: PelletShotgunUranium + proto: PelletShotgunUraniumSpread - type: SpentAmmoVisuals state: "depleted-uranium" diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/shotgun.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/shotgun.yml index 6e4570e1a1..ce79b6f417 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/shotgun.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/shotgun.yml @@ -42,6 +42,16 @@ 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) @@ -59,6 +69,16 @@ - 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) @@ -73,6 +93,16 @@ 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 @@ -88,6 +118,15 @@ 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 @@ -178,6 +217,16 @@ 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 @@ -196,6 +245,16 @@ 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 @@ -215,3 +274,13 @@ damage: types: Slash: 25 + +- type: entity + id: PelletGlassSpread + parent: PelletGlass + noSpawn: true + components: + - type: ProjectileSpread + proto: PelletGlass + count: 5 + spread: 10 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/explosives.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/explosives.yml index 152de7e92f..04d405e881 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/explosives.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/explosives.yml @@ -175,9 +175,7 @@ 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 @@ -190,9 +188,7 @@ 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 -- 2.52.0