Files
tbd-station-14/Content.Server/GameObjects/Components/Metabolism/BloodstreamComponent.cs

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 decimal 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)
{
var 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);
}
}
}