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:
90
Content.Shared/Nutrition/EntitySystems/SharedDrinkSystem.cs
Normal file
90
Content.Shared/Nutrition/EntitySystems/SharedDrinkSystem.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Nutrition.Components;
|
||||
|
||||
namespace Content.Shared.Nutrition.EntitySystems;
|
||||
|
||||
public abstract partial class SharedDrinkSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
|
||||
[Dependency] private readonly OpenableSystem _openable = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DrinkComponent, AttemptShakeEvent>(OnAttemptShake);
|
||||
SubscribeLocalEvent<DrinkComponent, ExaminedEvent>(OnExamined);
|
||||
}
|
||||
|
||||
protected void OnAttemptShake(Entity<DrinkComponent> entity, ref AttemptShakeEvent args)
|
||||
{
|
||||
if (IsEmpty(entity, entity.Comp))
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
protected void OnExamined(Entity<DrinkComponent> entity, ref ExaminedEvent args)
|
||||
{
|
||||
TryComp<OpenableComponent>(entity, out var openable);
|
||||
if (_openable.IsClosed(entity.Owner, null, openable) || !args.IsInDetailsRange || !entity.Comp.Examinable)
|
||||
return;
|
||||
|
||||
var empty = IsEmpty(entity, entity.Comp);
|
||||
if (empty)
|
||||
{
|
||||
args.PushMarkup(Loc.GetString("drink-component-on-examine-is-empty"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasComp<ExaminableSolutionComponent>(entity))
|
||||
{
|
||||
//provide exact measurement for beakers
|
||||
args.PushText(Loc.GetString("drink-component-on-examine-exact-volume", ("amount", DrinkVolume(entity, entity.Comp))));
|
||||
}
|
||||
else
|
||||
{
|
||||
//general approximation
|
||||
var remainingString = (int) _solutionContainer.PercentFull(entity) switch
|
||||
{
|
||||
100 => "drink-component-on-examine-is-full",
|
||||
> 66 => "drink-component-on-examine-is-mostly-full",
|
||||
> 33 => HalfEmptyOrHalfFull(args),
|
||||
_ => "drink-component-on-examine-is-mostly-empty",
|
||||
};
|
||||
args.PushMarkup(Loc.GetString(remainingString));
|
||||
}
|
||||
}
|
||||
|
||||
protected FixedPoint2 DrinkVolume(EntityUid uid, DrinkComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return FixedPoint2.Zero;
|
||||
|
||||
if (!_solutionContainer.TryGetSolution(uid, component.Solution, out _, out var sol))
|
||||
return FixedPoint2.Zero;
|
||||
|
||||
return sol.Volume;
|
||||
}
|
||||
|
||||
protected bool IsEmpty(EntityUid uid, DrinkComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return true;
|
||||
|
||||
return DrinkVolume(uid, component) <= 0;
|
||||
}
|
||||
|
||||
// some see half empty, and others see half full
|
||||
private string HalfEmptyOrHalfFull(ExaminedEvent args)
|
||||
{
|
||||
string remainingString = "drink-component-on-examine-is-half-full";
|
||||
|
||||
if (TryComp<MetaDataComponent>(args.Examiner, out var examiner) && examiner.EntityName.Length > 0
|
||||
&& string.Compare(examiner.EntityName.Substring(0, 1), "m", StringComparison.InvariantCultureIgnoreCase) > 0)
|
||||
remainingString = "drink-component-on-examine-is-half-empty";
|
||||
|
||||
return remainingString;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user