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 <retron404@gmail.com>
This commit is contained in:
@@ -129,27 +129,8 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
case CartridgeAmmoComponent cartridge:
|
case CartridgeAmmoComponent cartridge:
|
||||||
if (!cartridge.Spent)
|
if (!cartridge.Spent)
|
||||||
{
|
{
|
||||||
if (cartridge.Count > 1)
|
var uid = Spawn(cartridge.Prototype, fromEnt);
|
||||||
{
|
CreateAndFireProjectiles(uid, cartridge);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
RaiseLocalEvent(ent!.Value, new AmmoShotEvent()
|
RaiseLocalEvent(ent!.Value, new AmmoShotEvent()
|
||||||
{
|
{
|
||||||
@@ -157,8 +138,6 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
});
|
});
|
||||||
|
|
||||||
SetCartridgeSpent(ent.Value, cartridge, true);
|
SetCartridgeSpent(ent.Value, cartridge, true);
|
||||||
MuzzleFlash(gunUid, cartridge, mapDirection.ToAngle(), user);
|
|
||||||
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
|
|
||||||
|
|
||||||
if (cartridge.DeleteOnSpawn)
|
if (cartridge.DeleteOnSpawn)
|
||||||
Del(ent.Value);
|
Del(ent.Value);
|
||||||
@@ -177,10 +156,10 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
break;
|
break;
|
||||||
// Ammo shoots itself
|
// Ammo shoots itself
|
||||||
case AmmoComponent newAmmo:
|
case AmmoComponent newAmmo:
|
||||||
shotProjectiles.Add(ent!.Value);
|
if (ent == null)
|
||||||
MuzzleFlash(gunUid, newAmmo, mapDirection.ToAngle(), user);
|
break;
|
||||||
Audio.PlayPredicted(gun.SoundGunshotModified, gunUid, user);
|
CreateAndFireProjectiles(ent.Value, newAmmo);
|
||||||
ShootOrThrow(ent.Value, mapDirection, gunVelocity, gun, gunUid, user);
|
|
||||||
break;
|
break;
|
||||||
case HitscanPrototype hitscan:
|
case HitscanPrototype hitscan:
|
||||||
|
|
||||||
@@ -295,6 +274,36 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
{
|
{
|
||||||
FiredProjectiles = shotProjectiles,
|
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)
|
private void ShootOrThrow(EntityUid uid, Vector2 mapDirection, Vector2 gunVelocity, GunComponent gun, EntityUid gunUid, EntityUid? user)
|
||||||
|
|||||||
32
Content.Shared/Projectiles/ProjectileSpreadComponent.cs
Normal file
32
Content.Shared/Projectiles/ProjectileSpreadComponent.cs
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -30,18 +30,6 @@ public sealed partial class CartridgeAmmoComponent : AmmoComponent
|
|||||||
[AutoNetworkedField]
|
[AutoNetworkedField]
|
||||||
public bool Spent = false;
|
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>
|
/// <summary>
|
||||||
/// Caseless ammunition.
|
/// Caseless ammunition.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
- Cartridge
|
- Cartridge
|
||||||
- ShellShotgun
|
- ShellShotgun
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
count: 6
|
|
||||||
spread: 15
|
|
||||||
soundEject:
|
soundEject:
|
||||||
collection: ShellEject
|
collection: ShellEject
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
@@ -32,7 +30,6 @@
|
|||||||
map: [ "enum.AmmoVisualLayers.Base" ]
|
map: [ "enum.AmmoVisualLayers.Base" ]
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
proto: PelletShotgunBeanbag
|
proto: PelletShotgunBeanbag
|
||||||
count: 1
|
|
||||||
- type: SpentAmmoVisuals
|
- type: SpentAmmoVisuals
|
||||||
state: "beanbag"
|
state: "beanbag"
|
||||||
|
|
||||||
@@ -47,8 +44,6 @@
|
|||||||
map: [ "enum.AmmoVisualLayers.Base" ]
|
map: [ "enum.AmmoVisualLayers.Base" ]
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
proto: PelletShotgunSlug
|
proto: PelletShotgunSlug
|
||||||
count: 1
|
|
||||||
spread: 0
|
|
||||||
- type: SpentAmmoVisuals
|
- type: SpentAmmoVisuals
|
||||||
state: "slug"
|
state: "slug"
|
||||||
|
|
||||||
@@ -63,7 +58,6 @@
|
|||||||
map: [ "enum.AmmoVisualLayers.Base" ]
|
map: [ "enum.AmmoVisualLayers.Base" ]
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
proto: PelletShotgunFlare
|
proto: PelletShotgunFlare
|
||||||
count: 1
|
|
||||||
- type: SpentAmmoVisuals
|
- type: SpentAmmoVisuals
|
||||||
state: "flare"
|
state: "flare"
|
||||||
|
|
||||||
@@ -77,7 +71,7 @@
|
|||||||
- state: base
|
- state: base
|
||||||
map: [ "enum.AmmoVisualLayers.Base" ]
|
map: [ "enum.AmmoVisualLayers.Base" ]
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
proto: PelletShotgun
|
proto: PelletShotgunSpread
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ShellShotgunIncendiary
|
id: ShellShotgunIncendiary
|
||||||
@@ -89,7 +83,7 @@
|
|||||||
- state: incendiary
|
- state: incendiary
|
||||||
map: [ "enum.AmmoVisualLayers.Base" ]
|
map: [ "enum.AmmoVisualLayers.Base" ]
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
proto: PelletShotgunIncendiary
|
proto: PelletShotgunIncendiarySpread
|
||||||
- type: SpentAmmoVisuals
|
- type: SpentAmmoVisuals
|
||||||
state: "incendiary"
|
state: "incendiary"
|
||||||
|
|
||||||
@@ -103,7 +97,7 @@
|
|||||||
- state: practice
|
- state: practice
|
||||||
map: [ "enum.AmmoVisualLayers.Base" ]
|
map: [ "enum.AmmoVisualLayers.Base" ]
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
proto: PelletShotgunPractice
|
proto: PelletShotgunPracticeSpread
|
||||||
- type: SpentAmmoVisuals
|
- type: SpentAmmoVisuals
|
||||||
state: "practice"
|
state: "practice"
|
||||||
|
|
||||||
@@ -118,7 +112,6 @@
|
|||||||
map: [ "enum.AmmoVisualLayers.Base" ]
|
map: [ "enum.AmmoVisualLayers.Base" ]
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
proto: PelletShotgunTranquilizer
|
proto: PelletShotgunTranquilizer
|
||||||
count: 1
|
|
||||||
- type: ChemicalAmmo
|
- type: ChemicalAmmo
|
||||||
- type: SolutionContainerManager
|
- type: SolutionContainerManager
|
||||||
solutions:
|
solutions:
|
||||||
@@ -145,9 +138,7 @@
|
|||||||
graph: ImprovisedShotgunShellGraph
|
graph: ImprovisedShotgunShellGraph
|
||||||
node: shell
|
node: shell
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
count: 10
|
proto: PelletShotgunImprovisedSpread
|
||||||
spread: 45
|
|
||||||
proto: PelletShotgunImprovised
|
|
||||||
- type: SpentAmmoVisuals
|
- type: SpentAmmoVisuals
|
||||||
state: "improvised"
|
state: "improvised"
|
||||||
|
|
||||||
@@ -161,8 +152,6 @@
|
|||||||
- state: depleted-uranium
|
- state: depleted-uranium
|
||||||
map: [ "enum.AmmoVisualLayers.Base" ]
|
map: [ "enum.AmmoVisualLayers.Base" ]
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
count: 5
|
proto: PelletShotgunUraniumSpread
|
||||||
spread: 6
|
|
||||||
proto: PelletShotgunUranium
|
|
||||||
- type: SpentAmmoVisuals
|
- type: SpentAmmoVisuals
|
||||||
state: "depleted-uranium"
|
state: "depleted-uranium"
|
||||||
|
|||||||
@@ -42,6 +42,16 @@
|
|||||||
types:
|
types:
|
||||||
Piercing: 10
|
Piercing: 10
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: PelletShotgunSpread
|
||||||
|
noSpawn: true
|
||||||
|
parent: PelletShotgun
|
||||||
|
components:
|
||||||
|
- type: ProjectileSpread
|
||||||
|
proto: PelletShotgun
|
||||||
|
count: 6
|
||||||
|
spread: 15
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: PelletShotgunIncendiary
|
id: PelletShotgunIncendiary
|
||||||
name: pellet (.50 incendiary)
|
name: pellet (.50 incendiary)
|
||||||
@@ -59,6 +69,16 @@
|
|||||||
- type: IgnitionSource
|
- type: IgnitionSource
|
||||||
ignited: true
|
ignited: true
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: PelletShotgunIncendiarySpread
|
||||||
|
noSpawn: true
|
||||||
|
parent: PelletShotgunIncendiary
|
||||||
|
components:
|
||||||
|
- type: ProjectileSpread
|
||||||
|
proto: PelletShotgunIncendiary
|
||||||
|
count: 6
|
||||||
|
spread: 15
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: PelletShotgunPractice
|
id: PelletShotgunPractice
|
||||||
name: pellet (.50 practice)
|
name: pellet (.50 practice)
|
||||||
@@ -73,6 +93,16 @@
|
|||||||
types:
|
types:
|
||||||
Blunt: 1
|
Blunt: 1
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: PelletShotgunPracticeSpread
|
||||||
|
noSpawn: true
|
||||||
|
parent: PelletShotgunPractice
|
||||||
|
components:
|
||||||
|
- type: ProjectileSpread
|
||||||
|
proto: PelletShotgunPractice
|
||||||
|
count: 6
|
||||||
|
spread: 15
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: PelletShotgunImprovised
|
id: PelletShotgunImprovised
|
||||||
name: improvised pellet
|
name: improvised pellet
|
||||||
@@ -88,6 +118,15 @@
|
|||||||
Piercing: 3
|
Piercing: 3
|
||||||
Slash: 3
|
Slash: 3
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: PelletShotgunImprovisedSpread
|
||||||
|
noSpawn: true
|
||||||
|
parent: PelletShotgunImprovised
|
||||||
|
components:
|
||||||
|
- type: ProjectileSpread
|
||||||
|
proto: PelletShotgunImprovised
|
||||||
|
count: 10
|
||||||
|
spread: 45
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: PelletShotgunTranquilizer
|
id: PelletShotgunTranquilizer
|
||||||
@@ -178,6 +217,16 @@
|
|||||||
Radiation: 5
|
Radiation: 5
|
||||||
Piercing: 5
|
Piercing: 5
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: PelletShotgunUraniumSpread
|
||||||
|
noSpawn: true
|
||||||
|
parent: PelletShotgunUranium
|
||||||
|
components:
|
||||||
|
- type: ProjectileSpread
|
||||||
|
proto: PelletShotgunUranium
|
||||||
|
count: 5
|
||||||
|
spread: 6
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: PelletGrapeshot #tally fucking ho
|
id: PelletGrapeshot #tally fucking ho
|
||||||
name: grapeshot pellet
|
name: grapeshot pellet
|
||||||
@@ -196,6 +245,16 @@
|
|||||||
Piercing: 25
|
Piercing: 25
|
||||||
Structural: 5
|
Structural: 5
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: PelletGrapeshotSpread
|
||||||
|
noSpawn: true
|
||||||
|
parent: PelletGrapeshot
|
||||||
|
components:
|
||||||
|
- type: ProjectileSpread
|
||||||
|
proto: PelletGrapeshot
|
||||||
|
count: 5
|
||||||
|
spread: 40
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: PelletGlass
|
id: PelletGlass
|
||||||
name: glass shard
|
name: glass shard
|
||||||
@@ -215,3 +274,13 @@
|
|||||||
damage:
|
damage:
|
||||||
types:
|
types:
|
||||||
Slash: 25
|
Slash: 25
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: PelletGlassSpread
|
||||||
|
parent: PelletGlass
|
||||||
|
noSpawn: true
|
||||||
|
components:
|
||||||
|
- type: ProjectileSpread
|
||||||
|
proto: PelletGlass
|
||||||
|
count: 5
|
||||||
|
spread: 10
|
||||||
|
|||||||
@@ -175,9 +175,7 @@
|
|||||||
parent: BaseCannonBall
|
parent: BaseCannonBall
|
||||||
components:
|
components:
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
proto: PelletGrapeshot
|
proto: PelletGrapeshotSpread
|
||||||
count: 5
|
|
||||||
spread: 40
|
|
||||||
deleteOnSpawn: true
|
deleteOnSpawn: true
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi
|
sprite: Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi
|
||||||
@@ -190,9 +188,7 @@
|
|||||||
parent: BaseCannonBall
|
parent: BaseCannonBall
|
||||||
components:
|
components:
|
||||||
- type: CartridgeAmmo
|
- type: CartridgeAmmo
|
||||||
proto: PelletGlass
|
proto: PelletGlassSpread
|
||||||
count: 5
|
|
||||||
spread: 10
|
|
||||||
deleteOnSpawn: true
|
deleteOnSpawn: true
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi
|
sprite: Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi
|
||||||
|
|||||||
Reference in New Issue
Block a user