Add ability to shake fizzy drinks so they spray in peoples' faces (#25574)

* Implemented Shakeable

* Prevent shaking open Openables

* Prevent shaking empty drinks. Moved part of DrinkSystem to Shared.

* DrinkSystem can have a little more prediction, as a treat

* Cleanup

* Overhauled PressurizedDrink

* Make soda cans/bottles and champagne shakeable. The drink shaker too, for fun.

* We do a little refactoring.
PressurizedDrink is now PressurizedSolution, and fizziness now only works on solutions containing a reagent marked as fizzy.

* Documentation, cleanup, and tweaks.

* Changed fizziness calculation to use a cubic-out easing curve.

* Removed broken YAML that has avoid the linter's wrath for far too long

* Changed reagent fizzy bool to fizziness float.
Solution fizzability now scales with reagent proportion.

* Rename file to match changed class name

* DoAfter improvements. Cancel if the user moves away; block if no hands.

* Match these filenames too

* And this one

* guh

* Updated to use Shared puddle methods

* Various fixes and improvements.

* Made AttemptShakeEvent a struct

* AttemptAddFizzinessEvent too
This commit is contained in:
Tayrtahn
2024-04-17 21:49:58 -04:00
committed by GitHub
parent 8d64d2bc1e
commit cfa94be4c2
25 changed files with 807 additions and 146 deletions

View File

@@ -16,9 +16,9 @@ namespace Content.Shared.Nutrition.EntitySystems;
/// </summary>
public sealed partial class OpenableSystem : EntitySystem
{
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
[Dependency] protected readonly SharedAudioSystem Audio = default!;
[Dependency] protected readonly SharedPopupSystem Popup = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
public override void Initialize()
{
@@ -31,6 +31,8 @@ public sealed partial class OpenableSystem : EntitySystem
SubscribeLocalEvent<OpenableComponent, AfterInteractEvent>(HandleIfClosed);
SubscribeLocalEvent<OpenableComponent, GetVerbsEvent<Verb>>(AddOpenCloseVerbs);
SubscribeLocalEvent<OpenableComponent, SolutionTransferAttemptEvent>(OnTransferAttempt);
SubscribeLocalEvent<OpenableComponent, AttemptShakeEvent>(OnAttemptShake);
SubscribeLocalEvent<OpenableComponent, AttemptAddFizzinessEvent>(OnAttemptAddFizziness);
}
private void OnInit(EntityUid uid, OpenableComponent comp, ComponentInit args)
@@ -100,6 +102,20 @@ public sealed partial class OpenableSystem : EntitySystem
}
}
private void OnAttemptShake(Entity<OpenableComponent> entity, ref AttemptShakeEvent args)
{
// Prevent shaking open containers
if (entity.Comp.Opened)
args.Cancelled = true;
}
private void OnAttemptAddFizziness(Entity<OpenableComponent> entity, ref AttemptAddFizzinessEvent args)
{
// Can't add fizziness to an open container
if (entity.Comp.Opened)
args.Cancelled = true;
}
/// <summary>
/// Returns true if the entity either does not have OpenableComponent or it is opened.
/// Drinks that don't have OpenableComponent are automatically open, so it returns true.
@@ -126,7 +142,7 @@ public sealed partial class OpenableSystem : EntitySystem
return false;
if (user != null)
Popup.PopupEntity(Loc.GetString(comp.ClosedPopup, ("owner", uid)), user.Value, user.Value);
_popup.PopupEntity(Loc.GetString(comp.ClosedPopup, ("owner", uid)), user.Value, user.Value);
return true;
}
@@ -139,13 +155,13 @@ public sealed partial class OpenableSystem : EntitySystem
if (!Resolve(uid, ref comp))
return;
Appearance.SetData(uid, OpenableVisuals.Opened, comp.Opened, appearance);
_appearance.SetData(uid, OpenableVisuals.Opened, comp.Opened, appearance);
}
/// <summary>
/// Sets the opened field and updates open visuals.
/// </summary>
public void SetOpen(EntityUid uid, bool opened = true, OpenableComponent? comp = null)
public void SetOpen(EntityUid uid, bool opened = true, OpenableComponent? comp = null, EntityUid? user = null)
{
if (!Resolve(uid, ref comp, false) || opened == comp.Opened)
return;
@@ -155,12 +171,12 @@ public sealed partial class OpenableSystem : EntitySystem
if (opened)
{
var ev = new OpenableOpenedEvent();
var ev = new OpenableOpenedEvent(user);
RaiseLocalEvent(uid, ref ev);
}
else
{
var ev = new OpenableClosedEvent();
var ev = new OpenableClosedEvent(user);
RaiseLocalEvent(uid, ref ev);
}
@@ -176,8 +192,8 @@ public sealed partial class OpenableSystem : EntitySystem
if (!Resolve(uid, ref comp, false) || comp.Opened)
return false;
SetOpen(uid, true, comp);
Audio.PlayPredicted(comp.Sound, uid, user);
SetOpen(uid, true, comp, user);
_audio.PlayPredicted(comp.Sound, uid, user);
return true;
}
@@ -190,9 +206,9 @@ public sealed partial class OpenableSystem : EntitySystem
if (!Resolve(uid, ref comp, false) || !comp.Opened || !comp.Closeable)
return false;
SetOpen(uid, false, comp);
SetOpen(uid, false, comp, user);
if (comp.CloseSound != null)
Audio.PlayPredicted(comp.CloseSound, uid, user);
_audio.PlayPredicted(comp.CloseSound, uid, user);
return true;
}
}
@@ -201,10 +217,10 @@ public sealed partial class OpenableSystem : EntitySystem
/// Raised after an Openable is opened.
/// </summary>
[ByRefEvent]
public record struct OpenableOpenedEvent;
public record struct OpenableOpenedEvent(EntityUid? User = null);
/// <summary>
/// Raised after an Openable is closed.
/// </summary>
[ByRefEvent]
public record struct OpenableClosedEvent;
public record struct OpenableClosedEvent(EntityUid? User = null);