Proto-kinetic crusher (#16277)
Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
This commit is contained in:
@@ -13,11 +13,12 @@ using Content.Shared.Projectiles;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Throwing;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared.Weapons.Melee;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Content.Shared.Weapons.Ranged.Components;
|
||||
using Content.Shared.Weapons.Ranged.Events;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Physics.Components;
|
||||
@@ -70,7 +71,7 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
Sawmill.Level = LogLevel.Info;
|
||||
SubscribeAllEvent<RequestShootEvent>(OnShootRequest);
|
||||
SubscribeAllEvent<RequestStopShootEvent>(OnStopShootRequest);
|
||||
SubscribeLocalEvent<GunComponent, MeleeAttackAttemptEvent>(OnGunMeleeAttempt);
|
||||
SubscribeLocalEvent<GunComponent, MeleeHitEvent>(OnGunMelee);
|
||||
|
||||
// Ammo providers
|
||||
InitializeBallistic();
|
||||
@@ -103,19 +104,23 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
#endif
|
||||
}
|
||||
|
||||
private void OnGunMelee(EntityUid uid, GunComponent component, MeleeHitEvent args)
|
||||
{
|
||||
if (!TryComp<MeleeWeaponComponent>(uid, out var melee))
|
||||
return;
|
||||
|
||||
if (melee.NextAttack > component.NextFire)
|
||||
{
|
||||
component.NextFire = melee.NextAttack;
|
||||
Dirty(component);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGunUnpaused(EntityUid uid, GunComponent component, ref EntityUnpausedEvent args)
|
||||
{
|
||||
component.NextFire += args.PausedTime;
|
||||
}
|
||||
|
||||
private void OnGunMeleeAttempt(EntityUid uid, GunComponent component, ref MeleeAttackAttemptEvent args)
|
||||
{
|
||||
if (TagSystem.HasTag(args.User, "GunsDisabled"))
|
||||
return;
|
||||
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
private void OnShootRequest(RequestShootEvent msg, EntitySessionEventArgs args)
|
||||
{
|
||||
var user = args.SenderSession.AttachedEntity;
|
||||
@@ -214,15 +219,12 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
if (toCoordinates == null)
|
||||
return;
|
||||
|
||||
if (TagSystem.HasTag(user, "GunsDisabled"))
|
||||
{
|
||||
if (Timing.IsFirstTimePredicted)
|
||||
Popup(Loc.GetString("gun-disabled"), user, user);
|
||||
return;
|
||||
}
|
||||
|
||||
var curTime = Timing.CurTime;
|
||||
|
||||
// Maybe Raise an event for this? CanAttack doesn't seem appropriate.
|
||||
if (TryComp<MeleeWeaponComponent>(gunUid, out var melee) && melee.NextAttack > curTime)
|
||||
return;
|
||||
|
||||
// Need to do this to play the clicking sound for empty automatic weapons
|
||||
// but not play anything for burst fire.
|
||||
if (gun.NextFire > curTime)
|
||||
@@ -232,7 +234,8 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
|
||||
// First shot
|
||||
// Previously we checked shotcounter but in some cases all the bullets got dumped at once
|
||||
if (gun.NextFire < curTime - fireRate)
|
||||
// curTime - fireRate is insufficient because if you time it just right you can get a 3rd shot out slightly quicker.
|
||||
if (gun.NextFire < curTime - fireRate || gun.ShotCounter == 0 && gun.NextFire < curTime)
|
||||
gun.NextFire = curTime;
|
||||
|
||||
var shots = 0;
|
||||
@@ -263,6 +266,20 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
throw new ArgumentOutOfRangeException($"No implemented shooting behavior for {gun.SelectedMode}!");
|
||||
}
|
||||
|
||||
var attemptEv = new AttemptShootEvent(user, null);
|
||||
RaiseLocalEvent(gunUid, ref attemptEv);
|
||||
|
||||
if (attemptEv.Cancelled)
|
||||
{
|
||||
if (attemptEv.Message != null)
|
||||
{
|
||||
PopupSystem.PopupClient(attemptEv.Message, gunUid, user);
|
||||
}
|
||||
|
||||
gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds));
|
||||
return;
|
||||
}
|
||||
|
||||
var fromCoordinates = Transform(user).Coordinates;
|
||||
// Remove ammo
|
||||
var ev = new TakeAmmoEvent(shots, new List<(EntityUid? Entity, IShootable Shootable)>(), fromCoordinates, user);
|
||||
@@ -279,10 +296,7 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
// where the gun may be SemiAuto or Burst.
|
||||
gun.ShotCounter += shots;
|
||||
|
||||
var attemptEv = new AttemptShootEvent(user);
|
||||
RaiseLocalEvent(gunUid, ref attemptEv);
|
||||
|
||||
if (ev.Ammo.Count <= 0 || attemptEv.Cancelled)
|
||||
if (ev.Ammo.Count <= 0)
|
||||
{
|
||||
// Play empty gun sounds if relevant
|
||||
// If they're firing an existing clip then don't play anything.
|
||||
@@ -415,7 +429,7 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
/// <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]
|
||||
public record struct AttemptShootEvent(EntityUid User, bool Cancelled = false, bool ThrowItems = false);
|
||||
public record struct AttemptShootEvent(EntityUid User, string? Message, bool Cancelled = false, bool ThrowItems = false);
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on the gun after firing.
|
||||
|
||||
Reference in New Issue
Block a user