+++ /dev/null
-using Content.Shared.Extinguisher;
-using Robust.Shared.GameStates;
-
-namespace Content.Client.Extinguisher;
-
-[RegisterComponent]
-public sealed partial class FireExtinguisherComponent : SharedFireExtinguisherComponent;
+++ /dev/null
-using Content.Shared.Extinguisher;
-using Robust.Shared.GameStates;
-
-namespace Content.Server.Extinguisher;
-
-[RegisterComponent]
-[Access(typeof(FireExtinguisherSystem))]
-public sealed partial class FireExtinguisherComponent : SharedFireExtinguisherComponent
-{
-}
+++ /dev/null
-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));
- }
-}
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;
{
base.Initialize();
- SubscribeLocalEvent<SprayComponent, AfterInteractEvent>(OnAfterInteract, after: new[] { typeof(FireExtinguisherSystem) });
+ SubscribeLocalEvent<SprayComponent, AfterInteractEvent>(OnAfterInteract);
}
private void OnAfterInteract(Entity<SprayComponent> entity, ref AfterInteractEvent args)
return;
var ev = new SprayAttemptEvent(args.User);
- RaiseLocalEvent(entity, ev);
+ RaiseLocalEvent(entity, ref ev);
if (ev.Cancelled)
return;
_useDelay.TryResetDelay((entity, useDelay));
}
}
-
-public sealed class SprayAttemptEvent : CancellableEntityEventArgs
-{
- public EntityUid User;
-
- public SprayAttemptEvent(EntityUid user)
- {
- User = user;
- }
-}
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;
: "comp-solution-transfer-fill-normal";
_popup.PopupClient(Loc.GetString(msg, ("owner", args.Target), ("amount", transferred), ("target", uid)), uid, args.User);
-
- args.Handled = true;
return;
}
}
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;
}
}
}
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)}");
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);
+++ /dev/null
-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
-}
--- /dev/null
+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");
+}
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;
+ }
+}
--- /dev/null
+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();
+ }
+ }
+}
- 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
- type: DrainableSolution
solution: spray
- type: SolutionTransfer
+ maxTransferAmount: 100
+ transferAmount: 100
- type: UseDelay
- type: Spray
transferAmount: 10
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:
- 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
- type: PhysicalComposition
materialComposition:
Steel: 50
- Glass: 40
\ No newline at end of file
+ Glass: 40