Skip to content

Commit b432dc6

Browse files
Shotgun spread refactor (space-wizards#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 <retron404@gmail.com>
1 parent 64273cb commit b432dc6

File tree

6 files changed

+144
-61
lines changed

6 files changed

+144
-61
lines changed

‎Content.Server/Weapons/Ranged/Systems/GunSystem.cs‎

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -129,36 +129,15 @@ public override void Shoot(EntityUid gunUid, GunComponent gun, List<(EntityUid?
129129
case CartridgeAmmoComponent cartridge:
130130
if (!cartridge.Spent)
131131
{
132-
if (cartridge.Count > 1)
133-
{
134-
var ev = new GunGetAmmoSpreadEvent(cartridge.Spread);
135-
RaiseLocalEvent(gunUid, ref ev);
136-
137-
var angles = LinearSpread(mapAngle - ev.Spread / 2,
138-
mapAngle + ev.Spread / 2, cartridge.Count);
139-
140-
for (var i = 0; i < cartridge.Count; i++)
141-
{
142-
var uid = Spawn(cartridge.Prototype, fromEnt);
143-
ShootOrThrow(uid, angles[i].ToVec(), gunVelocity, gun, gunUid, user);
144-
shotProjectiles.Add(uid);
145-
}
146-
}
147-
else
148-
{
149-
var uid = Spawn(cartridge.Prototype, fromEnt);
150-
ShootOrThrow(uid, mapDirection, gunVelocity, gun, gunUid, user);
151-
shotProjectiles.Add(uid);
152-
}
132+
var uid = Spawn(cartridge.Prototype, fromEnt);
133+
CreateAndFireProjectiles(uid, cartridge);
153134

154135
RaiseLocalEvent(ent!.Value, new AmmoShotEvent()
155136
{
156137
FiredProjectiles = shotProjectiles,
157138
});
158139

159140
SetCartridgeSpent(ent.Value, cartridge, true);
160-
MuzzleFlash(gunUid, cartridge, mapDirection.ToAngle(), user);
161-
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
162141

163142
if (cartridge.DeleteOnSpawn)
164143
Del(ent.Value);
@@ -177,10 +156,10 @@ public override void Shoot(EntityUid gunUid, GunComponent gun, List<(EntityUid?
177156
break;
178157
// Ammo shoots itself
179158
case AmmoComponent newAmmo:
180-
shotProjectiles.Add(ent!.Value);
181-
MuzzleFlash(gunUid, newAmmo, mapDirection.ToAngle(), user);
182-
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
183-
ShootOrThrow(ent.Value, mapDirection, gunVelocity, gun, gunUid, user);
159+
if (ent == null)
160+
break;
161+
CreateAndFireProjectiles(ent.Value, newAmmo);
162+
184163
break;
185164
case HitscanPrototype hitscan:
186165

@@ -295,6 +274,36 @@ public override void Shoot(EntityUid gunUid, GunComponent gun, List<(EntityUid?
295274
{
296275
FiredProjectiles = shotProjectiles,
297276
});
277+
278+
void CreateAndFireProjectiles(EntityUid ammoEnt, AmmoComponent ammoComp)
279+
{
280+
if (TryComp<ProjectileSpreadComponent>(ammoEnt, out var ammoSpreadComp))
281+
{
282+
var spreadEvent = new GunGetAmmoSpreadEvent(ammoSpreadComp.Spread);
283+
RaiseLocalEvent(gunUid, ref spreadEvent);
284+
285+
var angles = LinearSpread(mapAngle - spreadEvent.Spread / 2,
286+
mapAngle + spreadEvent.Spread / 2, ammoSpreadComp.Count);
287+
288+
ShootOrThrow(ammoEnt, angles[0].ToVec(), gunVelocity, gun, gunUid, user);
289+
shotProjectiles.Add(ammoEnt);
290+
291+
for (var i = 1; i < ammoSpreadComp.Count; i++)
292+
{
293+
var newuid = Spawn(ammoSpreadComp.Proto, fromEnt);
294+
ShootOrThrow(newuid, angles[i].ToVec(), gunVelocity, gun, gunUid, user);
295+
shotProjectiles.Add(ammoEnt);
296+
}
297+
}
298+
else
299+
{
300+
ShootOrThrow(ammoEnt, mapDirection, gunVelocity, gun, gunUid, user);
301+
shotProjectiles.Add(ammoEnt);
302+
}
303+
304+
MuzzleFlash(gunUid, ammoComp, mapDirection.ToAngle(), user);
305+
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
306+
}
298307
}
299308

300309
private void ShootOrThrow(EntityUid uid, Vector2 mapDirection, Vector2 gunVelocity, GunComponent gun, EntityUid gunUid, EntityUid? user)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using Content.Shared.Weapons.Ranged.Systems;
2+
using Robust.Shared.GameStates;
3+
using Robust.Shared.Prototypes;
4+
5+
namespace Content.Shared.Projectiles;
6+
7+
/// <summary>
8+
/// Spawns a spread of the projectiles when fired
9+
/// </summary>
10+
[RegisterComponent, NetworkedComponent, Access(typeof(SharedGunSystem))]
11+
public sealed partial class ProjectileSpreadComponent : Component
12+
{
13+
/// <summary>
14+
/// The entity prototype that will be fired by the rest of the spread.
15+
/// Will generally be the same entity prototype as the first projectile being fired.
16+
/// Needed for ammo components that do not specify a fired prototype, unlike cartridges.
17+
/// </summary>
18+
[DataField(required: true)]
19+
public EntProtoId Proto;
20+
21+
/// <summary>
22+
/// How much the ammo spreads when shot, in degrees. Does nothing if count is 0.
23+
/// </summary>
24+
[DataField]
25+
public Angle Spread = Angle.FromDegrees(5);
26+
27+
/// <summary>
28+
/// How many prototypes are spawned when shot.
29+
/// </summary>
30+
[DataField]
31+
public int Count = 1;
32+
}

‎Content.Shared/Weapons/Ranged/Components/AmmoComponent.cs‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,6 @@ public sealed partial class CartridgeAmmoComponent : AmmoComponent
3030
[AutoNetworkedField]
3131
public bool Spent = false;
3232

33-
/// <summary>
34-
/// How much the ammo spreads when shot, in degrees. Does nothing if count is 0.
35-
/// </summary>
36-
[ViewVariables(VVAccess.ReadWrite), DataField("spread")]
37-
public Angle Spread = Angle.FromDegrees(5);
38-
39-
/// <summary>
40-
/// How many prototypes are spawned when shot.
41-
/// </summary>
42-
[ViewVariables(VVAccess.ReadWrite), DataField("count")]
43-
public int Count = 1;
44-
4533
/// <summary>
4634
/// Caseless ammunition.
4735
/// </summary>

‎Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/shotgun.yml‎

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
- Cartridge
1010
- ShellShotgun
1111
- type: CartridgeAmmo
12-
count: 6
13-
spread: 15
1412
soundEject:
1513
collection: ShellEject
1614
- type: Sprite
@@ -32,7 +30,6 @@
3230
map: [ "enum.AmmoVisualLayers.Base" ]
3331
- type: CartridgeAmmo
3432
proto: PelletShotgunBeanbag
35-
count: 1
3633
- type: SpentAmmoVisuals
3734
state: "beanbag"
3835

@@ -47,8 +44,6 @@
4744
map: [ "enum.AmmoVisualLayers.Base" ]
4845
- type: CartridgeAmmo
4946
proto: PelletShotgunSlug
50-
count: 1
51-
spread: 0
5247
- type: SpentAmmoVisuals
5348
state: "slug"
5449

@@ -63,7 +58,6 @@
6358
map: [ "enum.AmmoVisualLayers.Base" ]
6459
- type: CartridgeAmmo
6560
proto: PelletShotgunFlare
66-
count: 1
6761
- type: SpentAmmoVisuals
6862
state: "flare"
6963

@@ -77,7 +71,7 @@
7771
- state: base
7872
map: [ "enum.AmmoVisualLayers.Base" ]
7973
- type: CartridgeAmmo
80-
proto: PelletShotgun
74+
proto: PelletShotgunSpread
8175

8276
- type: entity
8377
id: ShellShotgunIncendiary
@@ -89,7 +83,7 @@
8983
- state: incendiary
9084
map: [ "enum.AmmoVisualLayers.Base" ]
9185
- type: CartridgeAmmo
92-
proto: PelletShotgunIncendiary
86+
proto: PelletShotgunIncendiarySpread
9387
- type: SpentAmmoVisuals
9488
state: "incendiary"
9589

@@ -103,7 +97,7 @@
10397
- state: practice
10498
map: [ "enum.AmmoVisualLayers.Base" ]
10599
- type: CartridgeAmmo
106-
proto: PelletShotgunPractice
100+
proto: PelletShotgunPracticeSpread
107101
- type: SpentAmmoVisuals
108102
state: "practice"
109103

@@ -118,7 +112,6 @@
118112
map: [ "enum.AmmoVisualLayers.Base" ]
119113
- type: CartridgeAmmo
120114
proto: PelletShotgunTranquilizer
121-
count: 1
122115
- type: ChemicalAmmo
123116
- type: SolutionContainerManager
124117
solutions:
@@ -145,9 +138,7 @@
145138
graph: ImprovisedShotgunShellGraph
146139
node: shell
147140
- type: CartridgeAmmo
148-
count: 10
149-
spread: 45
150-
proto: PelletShotgunImprovised
141+
proto: PelletShotgunImprovisedSpread
151142
- type: SpentAmmoVisuals
152143
state: "improvised"
153144

@@ -161,8 +152,6 @@
161152
- state: depleted-uranium
162153
map: [ "enum.AmmoVisualLayers.Base" ]
163154
- type: CartridgeAmmo
164-
count: 5
165-
spread: 6
166-
proto: PelletShotgunUranium
155+
proto: PelletShotgunUraniumSpread
167156
- type: SpentAmmoVisuals
168157
state: "depleted-uranium"

‎Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/shotgun.yml‎

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@
4242
types:
4343
Piercing: 10
4444

45+
- type: entity
46+
id: PelletShotgunSpread
47+
noSpawn: true
48+
parent: PelletShotgun
49+
components:
50+
- type: ProjectileSpread
51+
proto: PelletShotgun
52+
count: 6
53+
spread: 15
54+
4555
- type: entity
4656
id: PelletShotgunIncendiary
4757
name: pellet (.50 incendiary)
@@ -59,6 +69,16 @@
5969
- type: IgnitionSource
6070
ignited: true
6171

72+
- type: entity
73+
id: PelletShotgunIncendiarySpread
74+
noSpawn: true
75+
parent: PelletShotgunIncendiary
76+
components:
77+
- type: ProjectileSpread
78+
proto: PelletShotgunIncendiary
79+
count: 6
80+
spread: 15
81+
6282
- type: entity
6383
id: PelletShotgunPractice
6484
name: pellet (.50 practice)
@@ -73,6 +93,16 @@
7393
types:
7494
Blunt: 1
7595

96+
- type: entity
97+
id: PelletShotgunPracticeSpread
98+
noSpawn: true
99+
parent: PelletShotgunPractice
100+
components:
101+
- type: ProjectileSpread
102+
proto: PelletShotgunPractice
103+
count: 6
104+
spread: 15
105+
76106
- type: entity
77107
id: PelletShotgunImprovised
78108
name: improvised pellet
@@ -88,6 +118,15 @@
88118
Piercing: 3
89119
Slash: 3
90120

121+
- type: entity
122+
id: PelletShotgunImprovisedSpread
123+
noSpawn: true
124+
parent: PelletShotgunImprovised
125+
components:
126+
- type: ProjectileSpread
127+
proto: PelletShotgunImprovised
128+
count: 10
129+
spread: 45
91130

92131
- type: entity
93132
id: PelletShotgunTranquilizer
@@ -178,6 +217,16 @@
178217
Radiation: 5
179218
Piercing: 5
180219

220+
- type: entity
221+
id: PelletShotgunUraniumSpread
222+
noSpawn: true
223+
parent: PelletShotgunUranium
224+
components:
225+
- type: ProjectileSpread
226+
proto: PelletShotgunUranium
227+
count: 5
228+
spread: 6
229+
181230
- type: entity
182231
id: PelletGrapeshot #tally fucking ho
183232
name: grapeshot pellet
@@ -196,6 +245,16 @@
196245
Piercing: 25
197246
Structural: 5
198247

248+
- type: entity
249+
id: PelletGrapeshotSpread
250+
noSpawn: true
251+
parent: PelletGrapeshot
252+
components:
253+
- type: ProjectileSpread
254+
proto: PelletGrapeshot
255+
count: 5
256+
spread: 40
257+
199258
- type: entity
200259
id: PelletGlass
201260
name: glass shard
@@ -215,3 +274,13 @@
215274
damage:
216275
types:
217276
Slash: 25
277+
278+
- type: entity
279+
id: PelletGlassSpread
280+
parent: PelletGlass
281+
noSpawn: true
282+
components:
283+
- type: ProjectileSpread
284+
proto: PelletGlass
285+
count: 5
286+
spread: 10

‎Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/explosives.yml‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,7 @@
175175
parent: BaseCannonBall
176176
components:
177177
- type: CartridgeAmmo
178-
proto: PelletGrapeshot
179-
count: 5
180-
spread: 40
178+
proto: PelletGrapeshotSpread
181179
deleteOnSpawn: true
182180
- type: Sprite
183181
sprite: Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi
@@ -190,9 +188,7 @@
190188
parent: BaseCannonBall
191189
components:
192190
- type: CartridgeAmmo
193-
proto: PelletGlass
194-
count: 5
195-
spread: 10
191+
proto: PelletGlassSpread
196192
deleteOnSpawn: true
197193
- type: Sprite
198194
sprite: Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi

0 commit comments

Comments
 (0)