Files
tbd-station-14/Content.Server/GameObjects/Components/Metabolism/BloodstreamComponent.cs
moneyl 1b7860aeda Add injectors + injected reagent metabolism via BloodstreamCompo… (#730)
* Add BloodstreamComponent and BloodstreamSystem

New component for metabolizing reagents that other organs like the stomach pass their input reagents to.

* Change StomachComponent to put ingested reagents in bloodstream after delay

Now StomachComponent does not metabolize any reagents. Instead, it tracks how long each reagent has been inside it, and once they pass "digestionDelay" they'll be put inside the bloodstream, where the bloodstream will handle metabolism of the reagent.

* Add reagent injectors

Injects reagents straight into the bloodstream when used on mobs with bloodstreams. Also allows draw/inject from beakers. Does not support drawing blood/reagents from the bloodstream yet.

* Address code review

Make use of `Loc` static class instead of using `ILocalizationManager`. Localize InjectorToggleMode enum properly.
2020-02-24 01:47:33 +01:00

117 lines
4.2 KiB
C#

using System.Linq;
using Content.Server.GameObjects.Components.Chemistry;
using Content.Server.GameObjects.EntitySystems;
using Content.Shared.Chemistry;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Metabolism
{
/// <summary>
/// Handles all metabolism for mobs. All delivery methods eventually bring reagents
/// to the bloodstream. For example, injectors put reagents directly into the bloodstream,
/// and the stomach does with some delay.
/// </summary>
[RegisterComponent]
public class BloodstreamComponent : Component
{
#pragma warning disable 649
[Dependency] private readonly IPrototypeManager _prototypeManager;
#pragma warning restore 649
public override string Name => "Bloodstream";
/// <summary>
/// Internal solution for reagent storage
/// </summary>
[ViewVariables]
private SolutionComponent _internalSolution;
/// <summary>
/// Max volume of internal solution storage
/// </summary>
[ViewVariables]
private int _initialMaxVolume;
/// <summary>
/// Empty volume of internal solution
/// </summary>
public int EmptyVolume => _internalSolution.EmptyVolume;
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
serializer.DataField(ref _initialMaxVolume, "maxVolume", 250);
}
public override void Initialize()
{
base.Initialize();
//Create and setup internal solution storage
_internalSolution = new SolutionComponent();
_internalSolution.InitializeFromPrototype();
_internalSolution.Init();
_internalSolution.MaxVolume = _initialMaxVolume;
_internalSolution.Owner = Owner; //Manually set owner to avoid crash when VV'ing this
}
/// <summary>
/// Attempt to transfer provided solution to internal solution. Only supports complete transfers
/// </summary>
/// <param name="solution">Solution to be transferred</param>
/// <returns>Whether or not transfer was a success</returns>
public bool TryTransferSolution(Solution solution)
{
//For now doesn't support partial transfers
if (solution.TotalVolume + _internalSolution.CurrentVolume > _internalSolution.MaxVolume)
{
return false;
}
_internalSolution.TryAddSolution(solution, false, true);
return true;
}
/// <summary>
/// Loops through each reagent in _internalSolution, and calls the IMetabolizable for each of them./>
/// </summary>
/// <param name="tickTime">The time since the last metabolism tick in seconds.</param>
private void Metabolize(float tickTime)
{
if (_internalSolution.CurrentVolume == 0)
{
return;
}
//Run metabolism for each reagent, remove metabolized reagents
foreach (var reagent in _internalSolution.ReagentList.ToList()) //Using ToList here lets us edit reagents while iterating
{
if (!_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto))
{
continue;
}
//Run metabolism code for each reagent
foreach (var metabolizable in proto.Metabolism)
{
int reagentDelta = metabolizable.Metabolize(Owner, reagent.ReagentId, tickTime);
_internalSolution.TryRemoveReagent(reagent.ReagentId, reagentDelta);
}
}
}
/// <summary>
/// Triggers metabolism of the reagents inside _internalSolution. Called by <see cref="BloodstreamSystem"/>
/// </summary>
/// <param name="tickTime">The time since the last metabolism tick in seconds.</param>
public void OnUpdate(float tickTime)
{
Metabolize(tickTime);
}
}
}