Proto-kinetic crusher (#16277)

Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
This commit is contained in:
metalgearsloth
2023-05-14 13:15:18 +10:00
committed by GitHub
parent 356bf96039
commit 6417bb4fa0
68 changed files with 926 additions and 312 deletions

View File

@@ -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.