fire extinguisher using item toggle (#29906)
* move SprayAttemptEvent to shared * add SolutionTransferredEvent * replace FireExtinguisher with SpraySafety * update fire extinguisher yml * invert visuals * always handle event in solution transfer, it makes popups * instantly fill it * untroll --------- Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
using Content.Shared.Extinguisher;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Client.Extinguisher;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class FireExtinguisherComponent : SharedFireExtinguisherComponent;
|
||||
@@ -1,10 +0,0 @@
|
||||
using Content.Shared.Extinguisher;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Server.Extinguisher;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(FireExtinguisherSystem))]
|
||||
public sealed partial class FireExtinguisherComponent : SharedFireExtinguisherComponent
|
||||
{
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Extinguisher;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
|
||||
namespace Content.Server.Extinguisher;
|
||||
|
||||
public sealed class FireExtinguisherSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FireExtinguisherComponent, ComponentInit>(OnFireExtinguisherInit);
|
||||
SubscribeLocalEvent<FireExtinguisherComponent, UseInHandEvent>(OnUseInHand);
|
||||
SubscribeLocalEvent<FireExtinguisherComponent, AfterInteractEvent>(OnAfterInteract);
|
||||
SubscribeLocalEvent<FireExtinguisherComponent, GetVerbsEvent<InteractionVerb>>(OnGetInteractionVerbs);
|
||||
SubscribeLocalEvent<FireExtinguisherComponent, SprayAttemptEvent>(OnSprayAttempt);
|
||||
}
|
||||
|
||||
private void OnFireExtinguisherInit(Entity<FireExtinguisherComponent> entity, ref ComponentInit args)
|
||||
{
|
||||
if (entity.Comp.HasSafety)
|
||||
{
|
||||
UpdateAppearance((entity.Owner, entity.Comp));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnUseInHand(Entity<FireExtinguisherComponent> entity, ref UseInHandEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
ToggleSafety((entity.Owner, entity.Comp), args.User);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnAfterInteract(Entity<FireExtinguisherComponent> entity, ref AfterInteractEvent args)
|
||||
{
|
||||
if (args.Target == null || !args.CanReach)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (entity.Comp.HasSafety && entity.Comp.Safety)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-safety-on-message"), entity.Owner, args.User);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Target is not { Valid: true } target ||
|
||||
!_solutionContainerSystem.TryGetDrainableSolution(target, out var targetSoln, out var targetSolution) ||
|
||||
!_solutionContainerSystem.TryGetRefillableSolution(entity.Owner, out var containerSoln, out var containerSolution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
// TODO: why is this copy paste shit here just have fire extinguisher cancel transfer when safety is on
|
||||
var transfer = containerSolution.AvailableVolume;
|
||||
if (TryComp<SolutionTransferComponent>(entity.Owner, out var solTrans))
|
||||
{
|
||||
transfer = solTrans.TransferAmount;
|
||||
}
|
||||
transfer = FixedPoint2.Min(transfer, targetSolution.Volume);
|
||||
|
||||
if (transfer > 0)
|
||||
{
|
||||
var drained = _solutionContainerSystem.Drain(target, targetSoln.Value, transfer);
|
||||
_solutionContainerSystem.TryAddSolution(containerSoln.Value, drained);
|
||||
|
||||
_audio.PlayPvs(entity.Comp.RefillSound, entity.Owner);
|
||||
_popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-after-interact-refilled-message", ("owner", entity.Owner)),
|
||||
entity.Owner, args.Target.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGetInteractionVerbs(Entity<FireExtinguisherComponent> entity, ref GetVerbsEvent<InteractionVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract)
|
||||
return;
|
||||
|
||||
var user = args.User;
|
||||
var verb = new InteractionVerb
|
||||
{
|
||||
Act = () => ToggleSafety((entity.Owner, entity.Comp), user),
|
||||
Text = Loc.GetString("fire-extinguisher-component-verb-text"),
|
||||
};
|
||||
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
private void OnSprayAttempt(Entity<FireExtinguisherComponent> entity, ref SprayAttemptEvent args)
|
||||
{
|
||||
if (entity.Comp.HasSafety && entity.Comp.Safety)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("fire-extinguisher-component-safety-on-message"), entity, args.User);
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAppearance(Entity<FireExtinguisherComponent, AppearanceComponent?> entity)
|
||||
{
|
||||
if (!Resolve(entity, ref entity.Comp2, false))
|
||||
return;
|
||||
|
||||
if (entity.Comp1.HasSafety)
|
||||
{
|
||||
_appearance.SetData(entity, FireExtinguisherVisuals.Safety, entity.Comp1.Safety, entity.Comp2);
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleSafety(Entity<FireExtinguisherComponent?> extinguisher, EntityUid user)
|
||||
{
|
||||
if (!Resolve(extinguisher, ref extinguisher.Comp))
|
||||
return;
|
||||
|
||||
extinguisher.Comp.Safety = !extinguisher.Comp.Safety;
|
||||
_audio.PlayPvs(extinguisher.Comp.SafetySound, extinguisher, AudioParams.Default.WithVariation(0.125f).WithVolume(-4f));
|
||||
UpdateAppearance((extinguisher.Owner, extinguisher.Comp));
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Server.Extinguisher;
|
||||
using Content.Server.Fluids.Components;
|
||||
using Content.Server.Gravity;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Fluids;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Timing;
|
||||
using Content.Shared.Vapor;
|
||||
@@ -34,7 +34,7 @@ public sealed class SpraySystem : EntitySystem
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SprayComponent, AfterInteractEvent>(OnAfterInteract, after: new[] { typeof(FireExtinguisherSystem) });
|
||||
SubscribeLocalEvent<SprayComponent, AfterInteractEvent>(OnAfterInteract);
|
||||
}
|
||||
|
||||
private void OnAfterInteract(Entity<SprayComponent> entity, ref AfterInteractEvent args)
|
||||
@@ -48,7 +48,7 @@ public sealed class SpraySystem : EntitySystem
|
||||
return;
|
||||
|
||||
var ev = new SprayAttemptEvent(args.User);
|
||||
RaiseLocalEvent(entity, ev);
|
||||
RaiseLocalEvent(entity, ref ev);
|
||||
if (ev.Cancelled)
|
||||
return;
|
||||
|
||||
@@ -148,13 +148,3 @@ public sealed class SpraySystem : EntitySystem
|
||||
_useDelay.TryResetDelay((entity, useDelay));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SprayAttemptEvent : CancellableEntityEventArgs
|
||||
{
|
||||
public EntityUid User;
|
||||
|
||||
public SprayAttemptEvent(EntityUid user)
|
||||
{
|
||||
User = user;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ public sealed class SolutionTransferSystem : EntitySystem
|
||||
transferAmount = FixedPoint2.Min(transferAmount, maxRefill);
|
||||
|
||||
var transferred = Transfer(args.User, target, targetSoln.Value, uid, ownerSoln.Value, transferAmount);
|
||||
args.Handled = true;
|
||||
if (transferred > 0)
|
||||
{
|
||||
var toTheBrim = ownerRefill.AvailableVolume == 0;
|
||||
@@ -125,8 +126,6 @@ public sealed class SolutionTransferSystem : EntitySystem
|
||||
: "comp-solution-transfer-fill-normal";
|
||||
|
||||
_popup.PopupClient(Loc.GetString(msg, ("owner", args.Target), ("amount", transferred), ("target", uid)), uid, args.User);
|
||||
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -143,13 +142,11 @@ public sealed class SolutionTransferSystem : EntitySystem
|
||||
transferAmount = FixedPoint2.Min(transferAmount, maxRefill);
|
||||
|
||||
var transferred = Transfer(args.User, uid, ownerSoln.Value, target, targetSoln.Value, transferAmount);
|
||||
|
||||
args.Handled = true;
|
||||
if (transferred > 0)
|
||||
{
|
||||
var message = Loc.GetString("comp-solution-transfer-transfer-solution", ("amount", transferred), ("target", target));
|
||||
_popup.PopupClient(message, uid, args.User);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,6 +199,9 @@ public sealed class SolutionTransferSystem : EntitySystem
|
||||
var solution = _solution.SplitSolution(source, actualAmount);
|
||||
_solution.AddSolution(target, solution);
|
||||
|
||||
var ev = new SolutionTransferredEvent(sourceEntity, targetEntity, user, actualAmount);
|
||||
RaiseLocalEvent(targetEntity, ref ev);
|
||||
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Medium,
|
||||
$"{ToPrettyString(user):player} transferred {SharedSolutionContainerSystem.ToPrettyString(solution)} to {ToPrettyString(targetEntity):target}, which now contains {SharedSolutionContainerSystem.ToPrettyString(targetSolution)}");
|
||||
|
||||
@@ -225,3 +225,9 @@ public record struct SolutionTransferAttemptEvent(EntityUid From, EntityUid To,
|
||||
CancelReason = reason;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised on the target entity when a non-zero amount of solution gets transferred.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct SolutionTransferredEvent(EntityUid From, EntityUid To, EntityUid User, FixedPoint2 Amount);
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Extinguisher;
|
||||
|
||||
[NetworkedComponent]
|
||||
public abstract partial class SharedFireExtinguisherComponent : Component
|
||||
{
|
||||
[DataField("refillSound")] public SoundSpecifier RefillSound = new SoundPathSpecifier("/Audio/Effects/refill.ogg");
|
||||
|
||||
[DataField("hasSafety")] public bool HasSafety = true;
|
||||
|
||||
[DataField("safety")] public bool Safety = true;
|
||||
|
||||
[DataField("safetySound")]
|
||||
public SoundSpecifier SafetySound { get; private set; } = new SoundPathSpecifier("/Audio/Machines/button.ogg");
|
||||
}
|
||||
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum FireExtinguisherVisuals : byte
|
||||
{
|
||||
Safety
|
||||
}
|
||||
24
Content.Shared/Fluids/Components/SpraySafetyComponent.cs
Normal file
24
Content.Shared/Fluids/Components/SpraySafetyComponent.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Fluids.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Uses <c>ItemToggle</c> to control safety for a spray item.
|
||||
/// You can't spray or refill it while safety is on.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SpraySafetySystem))]
|
||||
public sealed partial class SpraySafetyComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Popup shown when trying to spray or refill with safety on.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId Popup = "fire-extinguisher-component-safety-on-message";
|
||||
|
||||
/// <summary>
|
||||
/// Sound to play after refilling.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public SoundSpecifier RefillSound = new SoundPathSpecifier("/Audio/Effects/refill.ogg");
|
||||
}
|
||||
@@ -34,3 +34,15 @@ public sealed partial class AbsorbantDoAfterEvent : DoAfterEvent
|
||||
|
||||
public override DoAfterEvent Clone() => this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised when trying to spray something, for example a fire extinguisher.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct SprayAttemptEvent(EntityUid User, bool Cancelled = false)
|
||||
{
|
||||
public void Cancel()
|
||||
{
|
||||
Cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
44
Content.Shared/Fluids/SpraySafetySystem.cs
Normal file
44
Content.Shared/Fluids/SpraySafetySystem.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Fluids.Components;
|
||||
using Content.Shared.Item.ItemToggle;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
|
||||
namespace Content.Shared.Fluids;
|
||||
|
||||
public sealed class SpraySafetySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ItemToggleSystem _toggle = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SpraySafetyComponent, SolutionTransferAttemptEvent>(OnTransferAttempt);
|
||||
SubscribeLocalEvent<SpraySafetyComponent, SolutionTransferredEvent>(OnTransferred);
|
||||
SubscribeLocalEvent<SpraySafetyComponent, SprayAttemptEvent>(OnSprayAttempt);
|
||||
}
|
||||
|
||||
private void OnTransferAttempt(Entity<SpraySafetyComponent> ent, ref SolutionTransferAttemptEvent args)
|
||||
{
|
||||
var (uid, comp) = ent;
|
||||
if (uid == args.To && !_toggle.IsActivated(uid))
|
||||
args.Cancel(Loc.GetString(comp.Popup));
|
||||
}
|
||||
|
||||
private void OnTransferred(Entity<SpraySafetyComponent> ent, ref SolutionTransferredEvent args)
|
||||
{
|
||||
_audio.PlayPredicted(ent.Comp.RefillSound, ent, args.User);
|
||||
}
|
||||
|
||||
private void OnSprayAttempt(Entity<SpraySafetyComponent> ent, ref SprayAttemptEvent args)
|
||||
{
|
||||
if (!_toggle.IsActivated(ent.Owner))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString(ent.Comp.Popup), ent, args.User);
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,8 @@
|
||||
- type: Sprite
|
||||
sprite: Objects/Misc/fire_extinguisher.rsi
|
||||
layers:
|
||||
- state: fire_extinguisher_closed
|
||||
map: [ "enabled" ]
|
||||
- state: fire_extinguisher_closed
|
||||
map: [ "enum.ToggleVisuals.Layer" ]
|
||||
- type: Item
|
||||
sprite: Objects/Misc/fire_extinguisher.rsi
|
||||
size: Normal
|
||||
@@ -24,6 +24,8 @@
|
||||
- type: DrainableSolution
|
||||
solution: spray
|
||||
- type: SolutionTransfer
|
||||
maxTransferAmount: 100
|
||||
transferAmount: 100
|
||||
- type: UseDelay
|
||||
- type: Spray
|
||||
transferAmount: 10
|
||||
@@ -34,8 +36,20 @@
|
||||
vaporAmount: 3
|
||||
vaporSpread: 90
|
||||
sprayVelocity: 2.0
|
||||
- type: FireExtinguisher
|
||||
hasSafety: true
|
||||
- type: ItemToggle
|
||||
soundActivate:
|
||||
path: /Audio/Machines/button.ogg
|
||||
params:
|
||||
variation: 0.125
|
||||
volume: -4
|
||||
soundDeactivate:
|
||||
path: /Audio/Machines/button.ogg
|
||||
params:
|
||||
variation: 0.125
|
||||
volume: -4
|
||||
- type: ToggleVerb
|
||||
text: fire-extinguisher-component-verb-text
|
||||
- type: SpraySafety
|
||||
- type: MeleeWeapon
|
||||
wideAnimationRotation: 180
|
||||
damage:
|
||||
@@ -46,14 +60,14 @@
|
||||
- type: Tool
|
||||
qualities:
|
||||
- Rolling
|
||||
speedModifier: 0.5 # its very big, akward to use
|
||||
speedModifier: 0.5 # its very big, awkward to use
|
||||
- type: Appearance
|
||||
- type: GenericVisualizer
|
||||
visuals:
|
||||
enum.FireExtinguisherVisuals.Safety:
|
||||
enabled:
|
||||
True: { state: fire_extinguisher_closed }
|
||||
False: { state: fire_extinguisher_open }
|
||||
enum.ToggleVisuals.Toggled:
|
||||
enum.ToggleVisuals.Layer:
|
||||
True: { state: fire_extinguisher_open }
|
||||
False: { state: fire_extinguisher_closed }
|
||||
- type: PhysicalComposition
|
||||
materialComposition:
|
||||
Steel: 100
|
||||
@@ -107,4 +121,4 @@
|
||||
- type: PhysicalComposition
|
||||
materialComposition:
|
||||
Steel: 50
|
||||
Glass: 40
|
||||
Glass: 40
|
||||
|
||||
Reference in New Issue
Block a user