magazine fill repeating doafter (#19780)

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas
2023-09-04 05:49:49 +01:00
committed by GitHub
parent 892fc7c07b
commit 5ead3d5108
2 changed files with 49 additions and 12 deletions

View File

@@ -53,4 +53,10 @@ public sealed partial class BallisticAmmoProviderComponent : Component
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("mayTransfer")] [ViewVariables(VVAccess.ReadWrite), DataField("mayTransfer")]
public bool MayTransfer = false; public bool MayTransfer = false;
/// <summary>
/// DoAfter delay for filling a bullet into another ballistic ammo provider.
/// </summary>
[DataField("fillDelay")]
public TimeSpan FillDelay = TimeSpan.FromSeconds(0.5);
} }

View File

@@ -1,3 +1,4 @@
using Content.Shared.DoAfter;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Interaction.Events; using Content.Shared.Interaction.Events;
@@ -13,6 +14,8 @@ namespace Content.Shared.Weapons.Ranged.Systems;
public abstract partial class SharedGunSystem public abstract partial class SharedGunSystem
{ {
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
protected virtual void InitializeBallistic() protected virtual void InitializeBallistic()
{ {
SubscribeLocalEvent<BallisticAmmoProviderComponent, ComponentInit>(OnBallisticInit); SubscribeLocalEvent<BallisticAmmoProviderComponent, ComponentInit>(OnBallisticInit);
@@ -24,6 +27,7 @@ public abstract partial class SharedGunSystem
SubscribeLocalEvent<BallisticAmmoProviderComponent, GetVerbsEvent<Verb>>(OnBallisticVerb); SubscribeLocalEvent<BallisticAmmoProviderComponent, GetVerbsEvent<Verb>>(OnBallisticVerb);
SubscribeLocalEvent<BallisticAmmoProviderComponent, InteractUsingEvent>(OnBallisticInteractUsing); SubscribeLocalEvent<BallisticAmmoProviderComponent, InteractUsingEvent>(OnBallisticInteractUsing);
SubscribeLocalEvent<BallisticAmmoProviderComponent, AfterInteractEvent>(OnBallisticAfterInteract); SubscribeLocalEvent<BallisticAmmoProviderComponent, AfterInteractEvent>(OnBallisticAfterInteract);
SubscribeLocalEvent<BallisticAmmoProviderComponent, AmmoFillDoAfterEvent>(OnBallisticAmmoFillDoAfter);
SubscribeLocalEvent<BallisticAmmoProviderComponent, UseInHandEvent>(OnBallisticUse); SubscribeLocalEvent<BallisticAmmoProviderComponent, UseInHandEvent>(OnBallisticUse);
} }
@@ -61,7 +65,7 @@ public abstract partial class SharedGunSystem
args.Target == null || args.Target == null ||
args.Used == args.Target || args.Used == args.Target ||
Deleted(args.Target) || Deleted(args.Target) ||
!TryComp(args.Target, out BallisticAmmoProviderComponent? targetComponent) || !TryComp<BallisticAmmoProviderComponent>(args.Target, out var targetComponent) ||
targetComponent.Whitelist == null) targetComponent.Whitelist == null)
{ {
return; return;
@@ -69,7 +73,23 @@ public abstract partial class SharedGunSystem
args.Handled = true; args.Handled = true;
if (targetComponent.Entities.Count + targetComponent.UnspawnedCount == targetComponent.Capacity) _doAfter.TryStartDoAfter(new DoAfterArgs(args.User, component.FillDelay, new AmmoFillDoAfterEvent(), used: uid, target: args.Target, eventTarget: uid)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
BreakOnDamage = false,
NeedHand = true
});
}
private void OnBallisticAmmoFillDoAfter(EntityUid uid, BallisticAmmoProviderComponent component, AmmoFillDoAfterEvent args)
{
if (Deleted(args.Target) ||
!TryComp<BallisticAmmoProviderComponent>(args.Target, out var target) ||
target.Whitelist == null)
return;
if (target.Entities.Count + target.UnspawnedCount == target.Capacity)
{ {
Popup( Popup(
Loc.GetString("gun-ballistic-transfer-target-full", Loc.GetString("gun-ballistic-transfer-target-full",
@@ -83,8 +103,8 @@ public abstract partial class SharedGunSystem
{ {
Popup( Popup(
Loc.GetString("gun-ballistic-transfer-empty", Loc.GetString("gun-ballistic-transfer-empty",
("entity", args.Used)), ("entity", uid)),
args.Used, uid,
args.User); args.User);
return; return;
} }
@@ -96,27 +116,25 @@ public abstract partial class SharedGunSystem
} }
List<(EntityUid? Entity, IShootable Shootable)> ammo = new(); List<(EntityUid? Entity, IShootable Shootable)> ammo = new();
var evTakeAmmo = new TakeAmmoEvent(1, ammo, Transform(args.Used).Coordinates, args.User); var evTakeAmmo = new TakeAmmoEvent(1, ammo, Transform(uid).Coordinates, args.User);
RaiseLocalEvent(args.Used, evTakeAmmo); RaiseLocalEvent(uid, evTakeAmmo);
foreach (var (ent, _) in ammo) foreach (var (ent, _) in ammo)
{ {
if (ent == null) if (ent == null)
continue; continue;
if (!targetComponent.Whitelist.IsValid(ent.Value)) if (!target.Whitelist.IsValid(ent.Value))
{ {
Popup( Popup(
Loc.GetString("gun-ballistic-transfer-invalid", Loc.GetString("gun-ballistic-transfer-invalid",
("ammoEntity", ent.Value), ("ammoEntity", ent.Value),
("targetEntity", args.Target.Value)), ("targetEntity", args.Target.Value)),
args.Used, uid,
args.User); args.User);
// TODO: For better or worse, this will play a sound, but it's the // play sound to be cool
// more future-proof thing to do than copying the same code SimulateInsertAmmo(ent.Value, uid, Transform(uid).Coordinates);
// that OnBallisticInteractUsing has, sans sound.
SimulateInsertAmmo(ent.Value, args.Used, Transform(args.Used).Coordinates);
} }
else else
{ {
@@ -126,6 +144,11 @@ public abstract partial class SharedGunSystem
if (ent.Value.IsClientSide()) if (ent.Value.IsClientSide())
Del(ent.Value); Del(ent.Value);
} }
// repeat if there is more space in the target and more ammo to fill it
var moreSpace = target.Entities.Count + target.UnspawnedCount < target.Capacity;
var moreAmmo = component.Entities.Count + component.UnspawnedCount > 0;
args.Repeat = moreSpace && moreAmmo;
} }
private void OnBallisticVerb(EntityUid uid, BallisticAmmoProviderComponent component, GetVerbsEvent<Verb> args) private void OnBallisticVerb(EntityUid uid, BallisticAmmoProviderComponent component, GetVerbsEvent<Verb> args)
@@ -247,3 +270,11 @@ public abstract partial class SharedGunSystem
Appearance.SetData(uid, AmmoVisuals.AmmoMax, component.Capacity, appearance); Appearance.SetData(uid, AmmoVisuals.AmmoMax, component.Capacity, appearance);
} }
} }
/// <summary>
/// DoAfter event for filling one ballistic ammo provider from another.
/// </summary>
[Serializable, NetSerializable]
public sealed partial class AmmoFillDoAfterEvent : SimpleDoAfterEvent
{
}