pneumatic cannon fixes (#14705)
Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
@@ -169,7 +169,8 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shoot(EntityUid gunUid, GunComponent gun, List<(EntityUid? Entity, IShootable Shootable)> 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, bool throwItems = false)
|
||||||
{
|
{
|
||||||
// Rather than splitting client / server for every ammo provider it's easier
|
// 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.
|
// to just delete the spawned entities. This is for programmer sanity despite the wasted perf.
|
||||||
@@ -178,6 +179,16 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
|
|
||||||
foreach (var (ent, shootable) in ammo)
|
foreach (var (ent, shootable) in ammo)
|
||||||
{
|
{
|
||||||
|
if (throwItems)
|
||||||
|
{
|
||||||
|
Recoil(user, direction);
|
||||||
|
if (ent!.Value.IsClientSide())
|
||||||
|
Del(ent.Value);
|
||||||
|
else
|
||||||
|
RemComp<AmmoComponent>(ent.Value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (shootable)
|
switch (shootable)
|
||||||
{
|
{
|
||||||
case CartridgeAmmoComponent cartridge:
|
case CartridgeAmmoComponent cartridge:
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ public sealed class PneumaticCannonSystem : SharedPneumaticCannonSystem
|
|||||||
if (!TryComp<GasTankComponent>(args.EntityUid, out var gas))
|
if (!TryComp<GasTankComponent>(args.EntityUid, out var gas))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (gas.Air.TotalMoles >= component.GasUsage)
|
// only accept tanks if it uses gas
|
||||||
|
if (gas.Air.TotalMoles >= component.GasUsage && component.GasUsage > 0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
args.Cancel();
|
args.Cancel();
|
||||||
@@ -71,7 +72,9 @@ public sealed class PneumaticCannonSystem : SharedPneumaticCannonSystem
|
|||||||
|
|
||||||
private void OnShoot(EntityUid uid, PneumaticCannonComponent component, ref GunShotEvent args)
|
private void OnShoot(EntityUid uid, PneumaticCannonComponent component, ref GunShotEvent args)
|
||||||
{
|
{
|
||||||
if (GetGas(uid) is not { } gas)
|
// require a gas tank if it uses gas
|
||||||
|
var gas = GetGas(uid);
|
||||||
|
if (gas == null && component.GasUsage > 0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(TryComp<StatusEffectsComponent>(args.User, out var status)
|
if(TryComp<StatusEffectsComponent>(args.User, out var status)
|
||||||
@@ -82,6 +85,10 @@ public sealed class PneumaticCannonSystem : SharedPneumaticCannonSystem
|
|||||||
("cannon", component.Owner)), uid, args.User);
|
("cannon", component.Owner)), uid, args.User);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore gas stuff if the cannon doesn't use any
|
||||||
|
if (gas == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// this should always be possible, as we'll eject the gas tank when it no longer is
|
// this should always be possible, as we'll eject the gas tank when it no longer is
|
||||||
var environment = _atmos.GetContainingMixture(component.Owner, false, true);
|
var environment = _atmos.GetContainingMixture(component.Owner, false, true);
|
||||||
var removed = _gasTank.RemoveAir(gas, component.GasUsage);
|
var removed = _gasTank.RemoveAir(gas, component.GasUsage);
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
args.Price += price * component.UnspawnedCount;
|
args.Price += price * component.UnspawnedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shoot(EntityUid gunUid, GunComponent gun, List<(EntityUid? Entity, IShootable Shootable)> 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, bool throwItems = false)
|
||||||
{
|
{
|
||||||
// Try a clumsy roll
|
// Try a clumsy roll
|
||||||
// TODO: Who put this here
|
// TODO: Who put this here
|
||||||
@@ -110,6 +111,21 @@ public sealed partial class GunSystem : SharedGunSystem
|
|||||||
|
|
||||||
foreach (var (ent, shootable) in ammo)
|
foreach (var (ent, shootable) in ammo)
|
||||||
{
|
{
|
||||||
|
// pneumatic cannon doesn't shoot bullets it just throws them, ignore ammo handling
|
||||||
|
if (throwItems)
|
||||||
|
{
|
||||||
|
if (!HasComp<ProjectileComponent>(ent!.Value))
|
||||||
|
{
|
||||||
|
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(ent.Value, mapDirection, gun.ProjectileSpeed, user);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShootProjectile(ent.Value, mapDirection, gunVelocity, user, gun.ProjectileSpeed);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (shootable)
|
switch (shootable)
|
||||||
{
|
{
|
||||||
// Cartridge shoots something else
|
// Cartridge shoots something else
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ public sealed class PneumaticCannonComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("baseProjectileSpeed")]
|
[DataField("baseProjectileSpeed")]
|
||||||
public float BaseProjectileSpeed = 20f;
|
public float BaseProjectileSpeed = 20f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, will throw ammo rather than shoot it.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("throwItems"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool ThrowItems = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -20,6 +20,13 @@ public abstract class SharedPneumaticCannonSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnAttemptShoot(EntityUid uid, PneumaticCannonComponent component, ref AttemptShootEvent args)
|
private void OnAttemptShoot(EntityUid uid, PneumaticCannonComponent component, ref AttemptShootEvent args)
|
||||||
{
|
{
|
||||||
|
// if the cannon doesn't need gas then it will always predict firing
|
||||||
|
if (component.GasUsage == 0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// pneumatic cannon usually doesn't shoot bullets
|
||||||
|
args.ThrowItems = component.ThrowItems;
|
||||||
|
|
||||||
// we don't have atmos on shared, so just predict by the existence of a slot item
|
// we don't have atmos on shared, so just predict by the existence of a slot item
|
||||||
// server will handle auto ejecting/not adding the slot item if it doesnt have enough gas,
|
// server will handle auto ejecting/not adding the slot item if it doesnt have enough gas,
|
||||||
// so this won't mispredict
|
// so this won't mispredict
|
||||||
|
|||||||
@@ -238,7 +238,6 @@ public abstract partial class SharedGunSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var curTime = Timing.CurTime;
|
var curTime = Timing.CurTime;
|
||||||
|
|
||||||
// Need to do this to play the clicking sound for empty automatic weapons
|
// Need to do this to play the clicking sound for empty automatic weapons
|
||||||
@@ -313,7 +312,7 @@ public abstract partial class SharedGunSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shoot confirmed - sounds also played here in case it's invalid (e.g. cartridge already spent).
|
// Shoot confirmed - sounds also played here in case it's invalid (e.g. cartridge already spent).
|
||||||
Shoot(gunUid, gun, ev.Ammo, fromCoordinates, toCoordinates.Value, user);
|
Shoot(gunUid, gun, ev.Ammo, fromCoordinates, toCoordinates.Value, user, throwItems: attemptEv.ThrowItems);
|
||||||
var shotEv = new GunShotEvent(user);
|
var shotEv = new GunShotEvent(user);
|
||||||
RaiseLocalEvent(gunUid, ref shotEv);
|
RaiseLocalEvent(gunUid, ref shotEv);
|
||||||
// Projectiles cause impulses especially important in non gravity environments
|
// Projectiles cause impulses especially important in non gravity environments
|
||||||
@@ -331,10 +330,11 @@ public abstract partial class SharedGunSystem : EntitySystem
|
|||||||
EntityUid ammo,
|
EntityUid ammo,
|
||||||
EntityCoordinates fromCoordinates,
|
EntityCoordinates fromCoordinates,
|
||||||
EntityCoordinates toCoordinates,
|
EntityCoordinates toCoordinates,
|
||||||
EntityUid? user = null)
|
EntityUid? user = null,
|
||||||
|
bool throwItems = false)
|
||||||
{
|
{
|
||||||
var shootable = EnsureComp<AmmoComponent>(ammo);
|
var shootable = EnsureComp<AmmoComponent>(ammo);
|
||||||
Shoot(gunUid, gun, new List<(EntityUid? Entity, IShootable Shootable)>(1) { (ammo, shootable) }, fromCoordinates, toCoordinates, user);
|
Shoot(gunUid, gun, new List<(EntityUid? Entity, IShootable Shootable)>(1) { (ammo, shootable) }, fromCoordinates, toCoordinates, user, throwItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void Shoot(
|
public abstract void Shoot(
|
||||||
@@ -343,7 +343,8 @@ public abstract partial class SharedGunSystem : EntitySystem
|
|||||||
List<(EntityUid? Entity, IShootable Shootable)> ammo,
|
List<(EntityUid? Entity, IShootable Shootable)> ammo,
|
||||||
EntityCoordinates fromCoordinates,
|
EntityCoordinates fromCoordinates,
|
||||||
EntityCoordinates toCoordinates,
|
EntityCoordinates toCoordinates,
|
||||||
EntityUid? user = null);
|
EntityUid? user = null,
|
||||||
|
bool throwItems = false);
|
||||||
|
|
||||||
protected abstract void Popup(string message, EntityUid? uid, EntityUid? user);
|
protected abstract void Popup(string message, EntityUid? uid, EntityUid? user);
|
||||||
|
|
||||||
@@ -438,8 +439,9 @@ public abstract partial class SharedGunSystem : EntitySystem
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="User">The user that attempted to fire this gun.</param>
|
/// <param name="User">The user that attempted to fire this gun.</param>
|
||||||
/// <param name="Cancelled">Set this to true if the shot should be cancelled.</param>
|
/// <param name="Cancelled">Set this to true if the shot should be cancelled.</param>
|
||||||
|
/// <param name="ThrowItems">Set this to true if the ammo shouldn't actually be fired, just thrown.</param>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct AttemptShootEvent(EntityUid User, bool Cancelled=false);
|
public record struct AttemptShootEvent(EntityUid User, bool Cancelled = false, bool ThrowItems = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raised directed on the gun after firing.
|
/// Raised directed on the gun after firing.
|
||||||
|
|||||||
@@ -99,3 +99,36 @@
|
|||||||
containers:
|
containers:
|
||||||
storagebase: !type:Container
|
storagebase: !type:Container
|
||||||
ents: []
|
ents: []
|
||||||
|
|
||||||
|
# shoots bullets instead of throwing them, no other changes
|
||||||
|
- type: entity
|
||||||
|
parent: WeaponImprovisedPneumaticCannon
|
||||||
|
id: WeaponImprovisedPneumaticCannonGun
|
||||||
|
suffix: Gun
|
||||||
|
components:
|
||||||
|
- type: PneumaticCannon
|
||||||
|
throwItems: false
|
||||||
|
|
||||||
|
# doesn't need gas, extra capacity
|
||||||
|
- type: entity
|
||||||
|
parent: WeaponImprovisedPneumaticCannonGun
|
||||||
|
id: WeaponImprovisedPneumaticCannonAdmeme
|
||||||
|
suffix: Admeme
|
||||||
|
components:
|
||||||
|
- type: Item
|
||||||
|
size: 9999
|
||||||
|
- type: Storage
|
||||||
|
capacity: 9999
|
||||||
|
- type: PneumaticCannon
|
||||||
|
gasUsage: 0
|
||||||
|
throwItems: false
|
||||||
|
- type: Gun
|
||||||
|
fireRate: 10
|
||||||
|
selectedMode: FullAuto
|
||||||
|
availableModes:
|
||||||
|
- SemiAuto
|
||||||
|
- FullAuto
|
||||||
|
soundGunshot:
|
||||||
|
path: /Audio/Effects/thunk.ogg
|
||||||
|
soundEmpty:
|
||||||
|
path: /Audio/Items/hiss.ogg
|
||||||
|
|||||||
Reference in New Issue
Block a user