117 lines
4.2 KiB
C#
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 ReagentUnit _initialMaxVolume;
|
|
|
|
/// <summary>
|
|
/// Empty volume of internal solution
|
|
/// </summary>
|
|
public ReagentUnit EmptyVolume => _internalSolution.EmptyVolume;
|
|
|
|
public override void ExposeData(ObjectSerializer serializer)
|
|
{
|
|
base.ExposeData(serializer);
|
|
serializer.DataField(ref _initialMaxVolume, "maxVolume", ReagentUnit.New(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);
|
|
}
|
|
}
|
|
}
|