2020-08-13 14:40:27 +02:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using Content.Server.Chemistry;
|
|
|
|
|
|
using Content.Server.GameObjects.Components.GUI;
|
|
|
|
|
|
using Content.Server.GameObjects.EntitySystems;
|
2019-07-31 05:10:06 -07:00
|
|
|
|
using Content.Shared.Chemistry;
|
2020-04-12 14:44:14 +02:00
|
|
|
|
using Content.Shared.GameObjects.Components.Chemistry;
|
2020-08-13 14:40:27 +02:00
|
|
|
|
using Content.Shared.GameObjects.EntitySystems;
|
|
|
|
|
|
using Content.Shared.GameObjects.Verbs;
|
2020-04-09 16:43:56 +05:00
|
|
|
|
using Content.Shared.Utility;
|
|
|
|
|
|
using Robust.Server.GameObjects;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
using Robust.Server.GameObjects.EntitySystems;
|
2019-07-31 15:02:36 +02:00
|
|
|
|
using Robust.Shared.GameObjects;
|
2020-08-13 14:40:27 +02:00
|
|
|
|
using Robust.Shared.GameObjects.Systems;
|
2019-07-31 05:10:06 -07:00
|
|
|
|
using Robust.Shared.Interfaces.GameObjects;
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
using Robust.Shared.IoC;
|
|
|
|
|
|
using Robust.Shared.Localization;
|
2020-04-08 15:53:15 +05:00
|
|
|
|
using Robust.Shared.Maths;
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
using Robust.Shared.Prototypes;
|
2020-04-08 15:53:15 +05:00
|
|
|
|
using Robust.Shared.Serialization;
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
using Robust.Shared.Utility;
|
2020-04-08 15:53:15 +05:00
|
|
|
|
using Robust.Shared.ViewVariables;
|
2019-07-31 05:10:06 -07:00
|
|
|
|
|
|
|
|
|
|
namespace Content.Server.GameObjects.Components.Chemistry
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
2020-04-08 15:53:15 +05:00
|
|
|
|
/// ECS component that manages a liquid solution of reagents.
|
2019-07-31 05:10:06 -07:00
|
|
|
|
/// </summary>
|
2019-07-31 15:02:36 +02:00
|
|
|
|
[RegisterComponent]
|
Bodysystem and damagesystem rework (#1544)
* Things and stuff with grids, unfinished w/ code debug changes.
* Updated submodule and also lost some progress cause I fucked it up xd
* First unfinished draft of the BodySystem. Doesn't compile.
* More changes to make it compile, but still just a framework. Doesn't do anything at the moment.
* Many cleanup changes.
* Revert "Merge branch 'master' of https://github.com/GlassEclipse/space-station-14 into body_system"
This reverts commit ddd4aebbc76cf2a0b7b102f72b93d55a0816c88c, reversing
changes made to 12d0dd752706bdda8879393bd8191a1199a0c978.
* Commit human.yml
* Updated a lot of things to be more classy, more progress overall, etc. etc.
* Latest update with many changes
* Minor changes
* Fixed Travis build bug
* Adds first draft of Body Scanner console, apparently I also forgot to tie Mechanisms into body parts so now a heart just sits in the Torso like a good boy :)
* Commit rest of stuff
* Latest changes
* Latest changes again
* 14 naked cowboys
* Yay!
* Latest changes (probably doesnt compile)
* Surgery!!!!!!!!!~1116y
* Cleaned some stuff up
* More cleanup
* Refactoring of code. Basic surgery path now done.
* Removed readme, has been added to HackMD
* Fixes typo (and thus test errors)
* WIP changes, committing so I can pull latest master changes
* Still working on that god awful merge
* Latest changes
* Latest changes!!
* Beginning of refactor to BoundUserInterface
* Surgery!
* Latest changes - fixes pr change requests and random fixes
* oops
* Fixes bodypart recursion
* Beginning of work on revamping the damage system.
* More latest changes
* Latest changes
* Finished merge
* Commit before removing old healthcode
* Almost done with removing speciescomponent...
* It compiles!!!
* yahoo more work
* Fixes to make it work
* Merge conflict fixes
* Deleting species visualizer was a mistake
* IDE warnings are VERBOTEN
* makes the server not kill itself on startup, some cleanup (#1)
* Namespaces, comments and exception fixes
* Fix conveyor and conveyor switch serialization
SS14 in reactive when
* Move damage, acts and body to shared
Damage cleanup
Comment cleanup
* Rename SpeciesComponent to RotationComponent and cleanup
Damage cleanup
Comment cleanup
* Fix nullable warnings
* Address old reviews
Fix off welder suicide damage type, deathmatch and suspicion
* Fix new test fail with units being able to accept items when unpowered
* Remove RotationComponent, change references to IBodyManagerComponent
* Add a bloodstream to humans
* More cleanups
* Add body conduits, connections, connectors substances and valves
* Revert "Add body conduits, connections, connectors substances and valves"
This reverts commit 9ab0b50e6b15fe98852d7b0836c0cdbf4bd76d20.
* Implement the heart mechanism behavior with the circulatory network
* Added network property to mechanism behaviors
* Changed human organ sprites and added missing ones
* Fix tests
* Add individual body part sprite rendering
* Fix error where dropped mechanisms are not initialized
* Implement client/server body damage
* Make DamageContainer take care of raising events
* Reimplement medical scanner with the new body system
* Improve the medical scanner ui
* Merge conflict fixes
* Fix crash when colliding with something
* Fix microwave suicides and eyes sprite rendering
* Fix nullable reference error
* Fix up surgery client side
* Fix missing using from merge conflict
* Add breathing
*inhale
* Merge conflict fixes
* Fix accumulatedframetime being reset to 0 instead of decreased by the threshold
https://github.com/space-wizards/space-station-14/pull/1617
* Use and add to the new AtmosHelpers
* Fix feet
* Add proper coloring to dropped body parts
* Fix Urist's lungs being too strong
* Merge conflict fixes
* Merge conflict fixes
* Merge conflict fixes
Co-authored-by: GlassEclipse <tsymall5@gmail.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
2020-08-17 01:42:42 +02:00
|
|
|
|
public class SolutionComponent : SharedSolutionComponent, IExamine
|
2019-07-31 05:10:06 -07:00
|
|
|
|
{
|
2020-08-24 14:10:28 +02:00
|
|
|
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
|
|
|
|
|
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
|
2019-10-11 16:57:16 -04:00
|
|
|
|
private IEnumerable<ReactionPrototype> _reactions;
|
|
|
|
|
|
private AudioSystem _audioSystem;
|
2020-04-08 15:53:15 +05:00
|
|
|
|
private ChemistrySystem _chemistrySystem;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
|
2020-04-09 16:43:56 +05:00
|
|
|
|
private SpriteComponent _spriteComponent;
|
|
|
|
|
|
|
2020-04-09 20:38:31 +05:00
|
|
|
|
private Solution _containedSolution = new Solution();
|
2020-04-12 14:44:14 +02:00
|
|
|
|
private ReagentUnit _maxVolume;
|
2020-04-08 15:53:15 +05:00
|
|
|
|
private SolutionCaps _capabilities;
|
2020-06-08 14:14:37 +02:00
|
|
|
|
private string _fillInitState;
|
2020-04-09 16:43:56 +05:00
|
|
|
|
private int _fillInitSteps;
|
2020-07-07 13:19:00 -04:00
|
|
|
|
private string _fillPathString = "Objects/Specific/Chemistry/fillings.rsi";
|
2020-04-09 16:43:56 +05:00
|
|
|
|
private ResourcePath _fillPath;
|
|
|
|
|
|
private SpriteSpecifier _fillSprite;
|
2020-04-09 20:38:31 +05:00
|
|
|
|
|
2020-04-08 15:53:15 +05:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// The maximum volume of the container.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[ViewVariables(VVAccess.ReadWrite)]
|
2020-04-12 14:44:14 +02:00
|
|
|
|
public ReagentUnit MaxVolume
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
2020-04-08 15:53:15 +05:00
|
|
|
|
get => _maxVolume;
|
|
|
|
|
|
set => _maxVolume = value; // Note that the contents won't spill out if the capacity is reduced.
|
2020-02-23 19:47:33 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-08 15:53:15 +05:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// The total volume of all the of the reagents in the container.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[ViewVariables]
|
2020-04-12 14:44:14 +02:00
|
|
|
|
public ReagentUnit CurrentVolume => _containedSolution.TotalVolume;
|
2020-04-08 15:53:15 +05:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// The volume without reagents remaining in the container.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[ViewVariables]
|
2020-04-12 14:44:14 +02:00
|
|
|
|
public ReagentUnit EmptyVolume => MaxVolume - CurrentVolume;
|
2020-04-08 15:53:15 +05:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// The current blended color of all the reagents in the container.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[ViewVariables(VVAccess.ReadWrite)]
|
|
|
|
|
|
public Color SubstanceColor { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// The current capabilities of this container (is the top open to pour? can I inject it into another object?).
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[ViewVariables(VVAccess.ReadWrite)]
|
|
|
|
|
|
public SolutionCaps Capabilities
|
2020-02-23 19:47:33 -05:00
|
|
|
|
{
|
2020-04-08 15:53:15 +05:00
|
|
|
|
get => _capabilities;
|
|
|
|
|
|
set => _capabilities = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-09 20:38:31 +05:00
|
|
|
|
[ViewVariables]
|
|
|
|
|
|
public Solution Solution
|
|
|
|
|
|
{
|
|
|
|
|
|
get => _containedSolution;
|
|
|
|
|
|
set => _containedSolution = value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-08 15:53:15 +05:00
|
|
|
|
public IReadOnlyList<Solution.ReagentQuantity> ReagentList => _containedSolution.Contents;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Shortcut for Capabilities PourIn flag to avoid binary operators.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool CanPourIn => (Capabilities & SolutionCaps.PourIn) != 0;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Shortcut for Capabilities PourOut flag to avoid binary operators.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool CanPourOut => (Capabilities & SolutionCaps.PourOut) != 0;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Shortcut for Capabilities Injectable flag
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool Injectable => (Capabilities & SolutionCaps.Injectable) != 0;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Shortcut for Capabilities Injector flag
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool Injector => (Capabilities & SolutionCaps.Injector) != 0;
|
|
|
|
|
|
|
2020-04-18 01:10:26 +02:00
|
|
|
|
public bool NoExamine => (Capabilities & SolutionCaps.NoExamine) != 0;
|
|
|
|
|
|
|
2020-04-08 15:53:15 +05:00
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
|
public override void ExposeData(ObjectSerializer serializer)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.ExposeData(serializer);
|
|
|
|
|
|
|
2020-04-12 14:44:14 +02:00
|
|
|
|
serializer.DataField(ref _maxVolume, "maxVol", ReagentUnit.New(0));
|
2020-04-08 15:53:15 +05:00
|
|
|
|
serializer.DataField(ref _containedSolution, "contents", _containedSolution);
|
|
|
|
|
|
serializer.DataField(ref _capabilities, "caps", SolutionCaps.None);
|
2020-04-09 16:43:56 +05:00
|
|
|
|
serializer.DataField(ref _fillInitState, "fillingState", "");
|
|
|
|
|
|
serializer.DataField(ref _fillInitSteps, "fillingSteps", 7);
|
2020-04-08 15:53:15 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Initialize()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Initialize();
|
2020-05-31 12:40:36 -05:00
|
|
|
|
_audioSystem = EntitySystem.Get<AudioSystem>();
|
2020-04-08 15:53:15 +05:00
|
|
|
|
_chemistrySystem = _entitySystemManager.GetEntitySystem<ChemistrySystem>();
|
|
|
|
|
|
_reactions = _prototypeManager.EnumeratePrototypes<ReactionPrototype>();
|
|
|
|
|
|
}
|
2019-10-11 16:57:16 -04:00
|
|
|
|
|
|
|
|
|
|
protected override void Startup()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Startup();
|
2020-04-08 15:53:15 +05:00
|
|
|
|
RecalculateColor();
|
2020-04-09 16:43:56 +05:00
|
|
|
|
if (!string.IsNullOrEmpty(_fillInitState))
|
|
|
|
|
|
{
|
|
|
|
|
|
_spriteComponent = Owner.GetComponent<SpriteComponent>();
|
|
|
|
|
|
_fillPath = new ResourcePath(_fillPathString);
|
|
|
|
|
|
_fillSprite = new SpriteSpecifier.Rsi(_fillPath, _fillInitState + (_fillInitSteps - 1));
|
|
|
|
|
|
_spriteComponent.AddLayerWithSprite(_fillSprite);
|
|
|
|
|
|
UpdateFillIcon();
|
|
|
|
|
|
}
|
2020-02-23 19:47:33 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-08 15:53:15 +05:00
|
|
|
|
public void RemoveAllSolution()
|
2020-02-23 19:47:33 -05:00
|
|
|
|
{
|
2020-04-08 15:53:15 +05:00
|
|
|
|
_containedSolution.RemoveAllSolution();
|
2020-04-09 16:43:56 +05:00
|
|
|
|
OnSolutionChanged(false);
|
2020-04-08 15:53:15 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-12 14:44:14 +02:00
|
|
|
|
public bool TryRemoveReagent(string reagentId, ReagentUnit quantity)
|
2020-04-08 15:53:15 +05:00
|
|
|
|
{
|
|
|
|
|
|
if (!ContainsReagent(reagentId, out var currentQuantity)) return false;
|
|
|
|
|
|
|
|
|
|
|
|
_containedSolution.RemoveReagent(reagentId, quantity);
|
2020-04-09 16:43:56 +05:00
|
|
|
|
OnSolutionChanged(false);
|
2020-04-08 15:53:15 +05:00
|
|
|
|
return true;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-11-12 08:20:03 +11:00
|
|
|
|
/// <summary>
|
2020-04-08 15:53:15 +05:00
|
|
|
|
/// Attempt to remove the specified quantity from this solution
|
2019-11-12 08:20:03 +11:00
|
|
|
|
/// </summary>
|
2020-04-08 15:53:15 +05:00
|
|
|
|
/// <param name="quantity">Quantity of this solution to remove</param>
|
|
|
|
|
|
/// <returns>Whether or not the solution was successfully removed</returns>
|
2020-04-12 14:44:14 +02:00
|
|
|
|
public bool TryRemoveSolution(ReagentUnit quantity)
|
2019-11-12 08:20:03 +11:00
|
|
|
|
{
|
2020-04-08 15:53:15 +05:00
|
|
|
|
if (CurrentVolume == 0)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
_containedSolution.RemoveSolution(quantity);
|
2020-04-09 16:43:56 +05:00
|
|
|
|
OnSolutionChanged(false);
|
2020-04-08 15:53:15 +05:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-12 14:44:14 +02:00
|
|
|
|
public Solution SplitSolution(ReagentUnit quantity)
|
2020-04-08 15:53:15 +05:00
|
|
|
|
{
|
|
|
|
|
|
var solutionSplit = _containedSolution.SplitSolution(quantity);
|
2020-04-09 16:43:56 +05:00
|
|
|
|
OnSolutionChanged(false);
|
2020-04-08 15:53:15 +05:00
|
|
|
|
return solutionSplit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected void RecalculateColor()
|
|
|
|
|
|
{
|
2020-04-09 16:43:56 +05:00
|
|
|
|
if (_containedSolution.TotalVolume == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
SubstanceColor = Color.Transparent;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2020-04-08 15:53:15 +05:00
|
|
|
|
|
|
|
|
|
|
Color mixColor = default;
|
2020-04-12 14:44:14 +02:00
|
|
|
|
var runningTotalQuantity = ReagentUnit.New(0);
|
2020-04-08 15:53:15 +05:00
|
|
|
|
|
|
|
|
|
|
foreach (var reagent in _containedSolution)
|
|
|
|
|
|
{
|
|
|
|
|
|
runningTotalQuantity += reagent.Quantity;
|
|
|
|
|
|
|
|
|
|
|
|
if(!_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
if (mixColor == default)
|
|
|
|
|
|
mixColor = proto.SubstanceColor;
|
2020-04-09 16:43:56 +05:00
|
|
|
|
mixColor = Color.InterpolateBetween(mixColor, proto.SubstanceColor,
|
2020-04-12 14:44:14 +02:00
|
|
|
|
(1 / runningTotalQuantity.Float()) * reagent.Quantity.Float());
|
2020-04-08 15:53:15 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-09 16:43:56 +05:00
|
|
|
|
SubstanceColor = mixColor;
|
2019-11-12 08:20:03 +11:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-07-31 05:10:06 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Transfers solution from the held container to the target container.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Verb]
|
|
|
|
|
|
private sealed class FillTargetVerb : Verb<SolutionComponent>
|
2019-10-13 22:49:07 +02:00
|
|
|
|
{
|
2020-05-23 03:09:44 +02:00
|
|
|
|
protected override void GetData(IEntity user, SolutionComponent component, VerbData data)
|
2019-07-31 05:10:06 -07:00
|
|
|
|
{
|
2020-06-22 18:54:56 +02:00
|
|
|
|
if (!ActionBlockerSystem.CanInteract(user) ||
|
|
|
|
|
|
!user.TryGetComponent<HandsComponent>(out var hands) ||
|
|
|
|
|
|
hands.GetActiveHand == null ||
|
2020-07-08 02:53:50 +02:00
|
|
|
|
hands.GetActiveHand.Owner == component.Owner ||
|
2020-06-22 18:54:56 +02:00
|
|
|
|
!hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var solution))
|
2019-07-31 05:10:06 -07:00
|
|
|
|
{
|
2020-06-22 18:54:56 +02:00
|
|
|
|
data.Visibility = VerbVisibility.Invisible;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ((solution.Capabilities & SolutionCaps.PourOut) != 0 &&
|
|
|
|
|
|
(component.Capabilities & SolutionCaps.PourIn) != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var heldEntityName = hands.GetActiveHand.Owner?.Prototype?.Name ?? "<Item>";
|
|
|
|
|
|
var myName = component.Owner.Prototype?.Name ?? "<Item>";
|
|
|
|
|
|
|
|
|
|
|
|
data.Text= $"Transfer liquid from [{heldEntityName}] to [{myName}].";
|
|
|
|
|
|
return;
|
2019-07-31 05:10:06 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-05-23 03:09:44 +02:00
|
|
|
|
data.Visibility = VerbVisibility.Invisible;
|
2019-07-31 05:10:06 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void Activate(IEntity user, SolutionComponent component)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!user.TryGetComponent<HandsComponent>(out var hands))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (hands.GetActiveHand == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (!hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var handSolutionComp))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if ((handSolutionComp.Capabilities & SolutionCaps.PourOut) == 0 || (component.Capabilities & SolutionCaps.PourIn) == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2020-04-05 11:36:12 +02:00
|
|
|
|
var transferQuantity = ReagentUnit.Min(component.MaxVolume - component.CurrentVolume, handSolutionComp.CurrentVolume, ReagentUnit.New(10));
|
2019-07-31 05:10:06 -07:00
|
|
|
|
|
|
|
|
|
|
// nothing to transfer
|
|
|
|
|
|
if (transferQuantity <= 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
var transferSolution = handSolutionComp.SplitSolution(transferQuantity);
|
|
|
|
|
|
component.TryAddSolution(transferSolution);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-05-31 19:29:06 +01:00
|
|
|
|
void IExamine.Examine(FormattedMessage message, bool inDetailsRange)
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
{
|
2020-04-18 01:10:26 +02:00
|
|
|
|
if (NoExamine)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-08-23 12:53:09 +02:00
|
|
|
|
message.AddText(Loc.GetString("Contains:\n"));
|
2020-04-08 15:53:15 +05:00
|
|
|
|
if (ReagentList.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
message.AddText("Nothing.\n");
|
|
|
|
|
|
}
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
foreach (var reagent in ReagentList)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto))
|
|
|
|
|
|
{
|
2020-05-31 19:29:06 +01:00
|
|
|
|
if (inDetailsRange)
|
|
|
|
|
|
{
|
|
|
|
|
|
message.AddText($"{proto.Name}: {reagent.Quantity}u\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2020-06-07 08:55:15 -05:00
|
|
|
|
//This is trash but it shows the general idea
|
2020-05-31 19:29:06 +01:00
|
|
|
|
var color = proto.SubstanceColor;
|
|
|
|
|
|
var colorIsh = "Red";
|
|
|
|
|
|
if (color.G > color.R)
|
|
|
|
|
|
{
|
|
|
|
|
|
colorIsh = "Green";
|
|
|
|
|
|
}
|
|
|
|
|
|
if (color.B > color.G && color.B > color.R)
|
|
|
|
|
|
{
|
|
|
|
|
|
colorIsh = "Blue";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-08-23 12:53:09 +02:00
|
|
|
|
message.AddText(Loc.GetString("A {0} liquid\n", colorIsh));
|
2020-05-31 19:29:06 +01:00
|
|
|
|
}
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2020-08-23 12:53:09 +02:00
|
|
|
|
message.AddText(Loc.GetString("Unknown reagent: {0}u\n", reagent.Quantity));
|
Reagent dispensers (#360)
* Expose more private values of Solution and SolutionComponent
Expose SolutionComponent.ContainedSolution and Solution.Contents. Both needed by ReagentDispenserComponent.
* Implement IExamine for SolutionComponent
Allows players to see the contents of a solution by examining the entity which contains it.
* Implement ReagentDispenserComponent
Adds ReagentDispenserComponent. A component which can add or remove reagents from a solution container. It's written in a general way so that it can be used for things such as the Chemical dispensers in chemistry, but also the booze and soda dispensers in the bar.
The chemicals it may dispense are defined in yaml, similar to the way that vending machines define which entities they can dispense, by defining a reagent pack.
* Add chemical dispenser and equipment
Adds the chemical dispenser, beaker, large beaker, dropper, and a few more chemicals.
* Add booze and soda dispensers.
Adds the booze and soda dispensers, and a few chemicals for them to dispense. There's no drink mixing or drunkenness yet.
* Update engine submodule.
* Remove unneeded and commented out code
Had a few WIP notes and debug code bits I forgot to remove beforehand.
* Make SolutionComponent._containedSolution and it's values private again
- Remove `SolutionComponent.ContainedSolution` property, replace with specific access functions to maintain safety.
- Make Solution.Contents return a `ReadOnlyCollection` instead of `_contents` to prevent uncontrolled access to the Solution values.
- Add `SolutionComponent.RemoveAllSolution()`
* Update Content.Shared/Chemistry/Solution.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Update Content.Shared/GameObjects/Components/Chemistry/SolutionComponent.cs
Commits a suggestion from RemieRichards to match the coding style of the rest of the codebase. Using `IReadOnlyList` instead of `IReadOnlyCollection`.
Co-Authored-By: Remie Richards <remierichards@gmail.com>
* Add import for IReadOnlyList to Shared/SolutionComponent.cs
* Add documentation
* Improve localization
Improve use of ILocalizationManager.
* Resolve ReagentDispenserWindow._localizationManager before using it
Forgot to do this in the last commit, resulting in a crash. Oops.
* Add SolutionCaps.FitsInDispenser. Use in ReagentDispenserComponent.
Used to limit large containers like buckets or mop buckets from being placed in a dispenser. Both have large capacities (500) and weren't designed to hold certain chemicals like a beaker is, so for now they can be blocked from being put in a dispenser by giving them that flag.
* Add colors to new reagents
* Update engine submodule
2019-10-05 09:10:05 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-07-31 05:10:06 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Transfers solution from a target container to the held container.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Verb]
|
|
|
|
|
|
private sealed class EmptyTargetVerb : Verb<SolutionComponent>
|
|
|
|
|
|
{
|
2020-05-23 03:09:44 +02:00
|
|
|
|
protected override void GetData(IEntity user, SolutionComponent component, VerbData data)
|
2019-07-31 05:10:06 -07:00
|
|
|
|
{
|
2020-06-22 18:54:56 +02:00
|
|
|
|
if (!ActionBlockerSystem.CanInteract(user) ||
|
|
|
|
|
|
!user.TryGetComponent<HandsComponent>(out var hands) ||
|
|
|
|
|
|
hands.GetActiveHand == null ||
|
2020-07-08 02:53:50 +02:00
|
|
|
|
hands.GetActiveHand.Owner == component.Owner ||
|
2020-06-22 18:54:56 +02:00
|
|
|
|
!hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var solution))
|
2019-07-31 05:10:06 -07:00
|
|
|
|
{
|
2020-06-22 18:54:56 +02:00
|
|
|
|
data.Visibility = VerbVisibility.Invisible;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ((solution.Capabilities & SolutionCaps.PourIn) != 0 &&
|
|
|
|
|
|
(component.Capabilities & SolutionCaps.PourOut) != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var heldEntityName = hands.GetActiveHand.Owner?.Prototype?.Name ?? "<Item>";
|
|
|
|
|
|
var myName = component.Owner.Prototype?.Name ?? "<Item>";
|
|
|
|
|
|
|
|
|
|
|
|
data.Text = $"Transfer liquid from [{myName}] to [{heldEntityName}].";
|
|
|
|
|
|
return;
|
2019-07-31 05:10:06 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-05-23 03:09:44 +02:00
|
|
|
|
data.Visibility = VerbVisibility.Invisible;
|
2019-07-31 05:10:06 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void Activate(IEntity user, SolutionComponent component)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!user.TryGetComponent<HandsComponent>(out var hands))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (hands.GetActiveHand == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if(!hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var handSolutionComp))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if ((handSolutionComp.Capabilities & SolutionCaps.PourIn) == 0 || (component.Capabilities & SolutionCaps.PourOut) == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2020-04-05 11:36:12 +02:00
|
|
|
|
var transferQuantity = ReagentUnit.Min(handSolutionComp.MaxVolume - handSolutionComp.CurrentVolume, component.CurrentVolume, ReagentUnit.New(10));
|
2019-07-31 05:10:06 -07:00
|
|
|
|
|
|
|
|
|
|
// pulling from an empty container, pointless to continue
|
|
|
|
|
|
if (transferQuantity <= 0)
|
|
|
|
|
|
return;
|
2019-07-31 15:02:36 +02:00
|
|
|
|
|
2019-07-31 05:10:06 -07:00
|
|
|
|
var transferSolution = component.SplitSolution(transferQuantity);
|
|
|
|
|
|
handSolutionComp.TryAddSolution(transferSolution);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-10-11 16:57:16 -04:00
|
|
|
|
|
|
|
|
|
|
private void CheckForReaction()
|
|
|
|
|
|
{
|
2019-12-04 07:51:05 -05:00
|
|
|
|
bool checkForNewReaction = false;
|
|
|
|
|
|
while (true)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
2020-04-08 19:07:33 +02:00
|
|
|
|
//TODO: make a hashmap at startup and then look up reagents in the contents for a reaction
|
2019-12-04 07:51:05 -05:00
|
|
|
|
//Check the solution for every reaction
|
|
|
|
|
|
foreach (var reaction in _reactions)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
2020-03-14 12:55:07 +01:00
|
|
|
|
if (SolutionValidReaction(reaction, out var unitReactions))
|
2019-12-04 07:51:05 -05:00
|
|
|
|
{
|
|
|
|
|
|
PerformReaction(reaction, unitReactions);
|
2020-03-06 20:11:24 +01:00
|
|
|
|
checkForNewReaction = true;
|
2019-12-04 07:51:05 -05:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Check for a new reaction if a reaction occurs, run loop again.
|
|
|
|
|
|
if (checkForNewReaction)
|
|
|
|
|
|
{
|
|
|
|
|
|
checkForNewReaction = false;
|
|
|
|
|
|
continue;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
}
|
2019-12-04 07:51:05 -05:00
|
|
|
|
return;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-05 11:36:12 +02:00
|
|
|
|
public bool TryAddReagent(string reagentId, ReagentUnit quantity, out ReagentUnit acceptedQuantity, bool skipReactionCheck = false, bool skipColor = false)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
2020-04-12 14:44:14 +02:00
|
|
|
|
var toAcceptQuantity = MaxVolume - _containedSolution.TotalVolume;
|
2020-03-14 12:55:07 +01:00
|
|
|
|
if (quantity > toAcceptQuantity)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
2020-03-14 12:55:07 +01:00
|
|
|
|
acceptedQuantity = toAcceptQuantity;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
if (acceptedQuantity == 0) return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
acceptedQuantity = quantity;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-12 14:44:14 +02:00
|
|
|
|
_containedSolution.AddReagent(reagentId, acceptedQuantity);
|
2019-11-12 08:20:03 +11:00
|
|
|
|
if (!skipColor) {
|
|
|
|
|
|
RecalculateColor();
|
|
|
|
|
|
}
|
2019-10-11 16:57:16 -04:00
|
|
|
|
if(!skipReactionCheck)
|
|
|
|
|
|
CheckForReaction();
|
2020-04-09 16:43:56 +05:00
|
|
|
|
OnSolutionChanged(skipColor);
|
2019-10-11 16:57:16 -04:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-11-12 08:20:03 +11:00
|
|
|
|
public bool TryAddSolution(Solution solution, bool skipReactionCheck = false, bool skipColor = false)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
2020-04-12 14:44:14 +02:00
|
|
|
|
if (solution.TotalVolume > (MaxVolume - _containedSolution.TotalVolume))
|
2019-10-11 16:57:16 -04:00
|
|
|
|
return false;
|
|
|
|
|
|
|
2020-04-12 14:44:14 +02:00
|
|
|
|
_containedSolution.AddSolution(solution);
|
2019-11-12 08:20:03 +11:00
|
|
|
|
if (!skipColor) {
|
|
|
|
|
|
RecalculateColor();
|
|
|
|
|
|
}
|
2019-10-11 16:57:16 -04:00
|
|
|
|
if(!skipReactionCheck)
|
|
|
|
|
|
CheckForReaction();
|
2020-04-09 16:43:56 +05:00
|
|
|
|
OnSolutionChanged(skipColor);
|
2019-10-11 16:57:16 -04:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Checks if a solution has the reactants required to cause a specified reaction.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="solution">The solution to check for reaction conditions.</param>
|
|
|
|
|
|
/// <param name="reaction">The reaction whose reactants will be checked for in the solution.</param>
|
|
|
|
|
|
/// <param name="unitReactions">The number of times the reaction can occur with the given solution.</param>
|
|
|
|
|
|
/// <returns></returns>
|
2020-04-05 11:36:12 +02:00
|
|
|
|
private bool SolutionValidReaction(ReactionPrototype reaction, out ReagentUnit unitReactions)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
2020-04-05 11:36:12 +02:00
|
|
|
|
unitReactions = ReagentUnit.MaxValue; //Set to some impossibly large number initially
|
2019-10-11 16:57:16 -04:00
|
|
|
|
foreach (var reactant in reaction.Reactants)
|
|
|
|
|
|
{
|
2020-04-05 11:36:12 +02:00
|
|
|
|
if (!ContainsReagent(reactant.Key, out ReagentUnit reagentQuantity))
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2020-04-05 11:36:12 +02:00
|
|
|
|
var currentUnitReactions = reagentQuantity / reactant.Value.Amount;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
if (currentUnitReactions < unitReactions)
|
|
|
|
|
|
{
|
|
|
|
|
|
unitReactions = currentUnitReactions;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (unitReactions == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Perform a reaction on a solution. This assumes all reaction criteria have already been checked and are met.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="solution">Solution to be reacted.</param>
|
|
|
|
|
|
/// <param name="reaction">Reaction to occur.</param>
|
|
|
|
|
|
/// <param name="unitReactions">The number of times to cause this reaction.</param>
|
2020-04-05 11:36:12 +02:00
|
|
|
|
private void PerformReaction(ReactionPrototype reaction, ReagentUnit unitReactions)
|
2019-10-11 16:57:16 -04:00
|
|
|
|
{
|
|
|
|
|
|
//Remove non-catalysts
|
|
|
|
|
|
foreach (var reactant in reaction.Reactants)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!reactant.Value.Catalyst)
|
|
|
|
|
|
{
|
2020-04-05 11:36:12 +02:00
|
|
|
|
var amountToRemove = unitReactions * reactant.Value.Amount;
|
2019-10-11 16:57:16 -04:00
|
|
|
|
TryRemoveReagent(reactant.Key, amountToRemove);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//Add products
|
|
|
|
|
|
foreach (var product in reaction.Products)
|
|
|
|
|
|
{
|
2020-04-05 11:36:12 +02:00
|
|
|
|
TryAddReagent(product.Key, product.Value * unitReactions, out var acceptedQuantity, true);
|
2019-10-11 16:57:16 -04:00
|
|
|
|
}
|
|
|
|
|
|
//Trigger reaction effects
|
|
|
|
|
|
foreach (var effect in reaction.Effects)
|
|
|
|
|
|
{
|
2020-06-13 01:28:28 -04:00
|
|
|
|
effect.React(Owner, unitReactions.Double());
|
2019-10-11 16:57:16 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Play reaction sound client-side
|
2020-07-20 06:26:16 -04:00
|
|
|
|
_audioSystem.PlayAtCoords("/Audio/Effects/Chemistry/bubbles.ogg", Owner.Transform.GridPosition);
|
2019-10-11 16:57:16 -04:00
|
|
|
|
}
|
2020-04-08 15:53:15 +05:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Check if the solution contains the specified reagent.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="reagentId">The reagent to check for.</param>
|
|
|
|
|
|
/// <param name="quantity">Output the quantity of the reagent if it is contained, 0 if it isn't.</param>
|
|
|
|
|
|
/// <returns>Return true if the solution contains the reagent.</returns>
|
2020-04-12 14:44:14 +02:00
|
|
|
|
public bool ContainsReagent(string reagentId, out ReagentUnit quantity)
|
2020-04-08 15:53:15 +05:00
|
|
|
|
{
|
|
|
|
|
|
foreach (var reagent in _containedSolution.Contents)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (reagent.ReagentId == reagentId)
|
|
|
|
|
|
{
|
|
|
|
|
|
quantity = reagent.Quantity;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-04-12 14:44:14 +02:00
|
|
|
|
quantity = ReagentUnit.New(0);
|
2020-04-08 15:53:15 +05:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public string GetMajorReagentId()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_containedSolution.Contents.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return "";
|
|
|
|
|
|
}
|
|
|
|
|
|
var majorReagent = _containedSolution.Contents.OrderByDescending(reagent => reagent.Quantity).First();;
|
|
|
|
|
|
return majorReagent.ReagentId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-09 16:43:56 +05:00
|
|
|
|
protected void UpdateFillIcon()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrEmpty(_fillInitState)) return;
|
|
|
|
|
|
|
2020-04-12 14:44:14 +02:00
|
|
|
|
var percentage = (CurrentVolume / MaxVolume).Double();
|
2020-04-09 16:43:56 +05:00
|
|
|
|
var level = ContentHelpers.RoundToLevels(percentage * 100, 100, _fillInitSteps);
|
|
|
|
|
|
|
|
|
|
|
|
//Transformed glass uses special fancy sprites so we don't bother
|
|
|
|
|
|
if (level == 0 || Owner.TryGetComponent<TransformableContainerComponent>(out var transformableContainerComponent)
|
|
|
|
|
|
&& transformableContainerComponent.Transformed)
|
|
|
|
|
|
{
|
|
|
|
|
|
_spriteComponent.LayerSetColor(1, Color.Transparent);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
_fillSprite = new SpriteSpecifier.Rsi(_fillPath, _fillInitState+level);
|
|
|
|
|
|
_spriteComponent.LayerSetSprite(1, _fillSprite);
|
|
|
|
|
|
_spriteComponent.LayerSetColor(1,SubstanceColor);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected virtual void OnSolutionChanged(bool skipColor)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!skipColor)
|
|
|
|
|
|
RecalculateColor();
|
|
|
|
|
|
|
|
|
|
|
|
UpdateFillIcon();
|
|
|
|
|
|
_chemistrySystem.HandleSolutionChange(Owner);
|
|
|
|
|
|
}
|
2019-07-31 05:10:06 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|