Files
tbd-station-14/Content.Shared/Nutrition/Components/PressurizedSolutionComponent.cs
Tayrtahn cfa94be4c2 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
2024-04-18 11:49:58 +10:00

107 lines
4.1 KiB
C#

using Content.Shared.Nutrition.EntitySystems;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
namespace Content.Shared.Nutrition.Components;
/// <summary>
/// Represents a solution container that can hold the pressure from a solution that
/// gets fizzy when aggitated, and can spray the solution when opened or thrown.
/// Handles simulating the fizziness of the solution, responding to aggitating events,
/// and spraying the solution out when opening or throwing the entity.
/// </summary>
[NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
[RegisterComponent, Access(typeof(PressurizedSolutionSystem))]
public sealed partial class PressurizedSolutionComponent : Component
{
/// <summary>
/// The name of the solution to use.
/// </summary>
[DataField]
public string Solution = "drink";
/// <summary>
/// The sound to play when the solution sprays out of the container.
/// </summary>
[DataField]
public SoundSpecifier SpraySound = new SoundPathSpecifier("/Audio/Items/soda_spray.ogg");
/// <summary>
/// The longest amount of time that the solution can remain fizzy after being aggitated.
/// Put another way, how long the solution will remain fizzy when aggitated the maximum amount.
/// Used to calculate the current fizziness level.
/// </summary>
[DataField]
public TimeSpan FizzinessMaxDuration = TimeSpan.FromSeconds(120);
/// <summary>
/// The time at which the solution will be fully settled after being shaken.
/// </summary>
[DataField, AutoNetworkedField, AutoPausedField]
public TimeSpan FizzySettleTime;
/// <summary>
/// How much to increase the solution's fizziness each time it's shaken.
/// This assumes the solution has maximum fizzability.
/// A value of 1 will maximize it with a single shake, and a value of
/// 0.5 will increase it by half with each shake.
/// </summary>
[DataField]
public float FizzinessAddedOnShake = 1.0f;
/// <summary>
/// How much to increase the solution's fizziness when it lands after being thrown.
/// This assumes the solution has maximum fizzability.
/// </summary>
[DataField]
public float FizzinessAddedOnLand = 0.25f;
/// <summary>
/// How much to modify the chance of spraying when the entity is opened.
/// Increasing this effectively increases the fizziness value when checking if it should spray.
/// </summary>
[DataField]
public float SprayChanceModOnOpened = -0.01f; // Just enough to prevent spraying at 0 fizziness
/// <summary>
/// How much to modify the chance of spraying when the entity is shaken.
/// Increasing this effectively increases the fizziness value when checking if it should spray.
/// </summary>
[DataField]
public float SprayChanceModOnShake = -1; // No spraying when shaken by default
/// <summary>
/// How much to modify the chance of spraying when the entity lands after being thrown.
/// Increasing this effectively increases the fizziness value when checking if it should spray.
/// </summary>
[DataField]
public float SprayChanceModOnLand = 0.25f;
/// <summary>
/// Holds the current randomly-rolled threshold value for spraying.
/// If fizziness exceeds this value when the entity is opened, it will spray.
/// By rolling this value when the entity is aggitated, we can have randomization
/// while still having prediction!
/// </summary>
[DataField, AutoNetworkedField]
public float SprayFizzinessThresholdRoll;
/// <summary>
/// Popup message shown to user when sprayed by the solution.
/// </summary>
[DataField]
public LocId SprayHolderMessageSelf = "pressurized-solution-spray-holder-self";
/// <summary>
/// Popup message shown to others when a user is sprayed by the solution.
/// </summary>
[DataField]
public LocId SprayHolderMessageOthers = "pressurized-solution-spray-holder-others";
/// <summary>
/// Popup message shown above the entity when the solution sprays without a target.
/// </summary>
[DataField]
public LocId SprayGroundMessage = "pressurized-solution-spray-ground";
}