Basic liver mechanism (#3424)

* Basic liver mechanism

* makes the stupid thing work
This commit is contained in:
ike709
2021-02-27 19:58:08 -06:00
committed by GitHub
parent a9a96f2edc
commit 7b3e25b3ef
5 changed files with 136 additions and 45 deletions

View File

@@ -0,0 +1,116 @@
#nullable enable
using System.Linq;
using Content.Server.GameObjects.Components.Body.Circulatory;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components.Body.Networks;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Body.Behavior
{
/// <summary>
/// Metabolizes reagents in <see cref="SharedBloodstreamComponent"/> after they are digested.
/// </summary>
public class LiverBehavior : MechanismBehavior
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private float _accumulatedFrameTime;
/// <summary>
/// Whether the liver is functional.
/// </summary>
[ViewVariables] private bool _liverFailing = false;
/// <summary>
/// Modifier for alcohol damage.
/// </summary>
[ViewVariables] private float _alcoholLethality = 0.005f;
/// <summary>
/// Modifier for alcohol damage.
/// </summary>
[ViewVariables] private float _alcoholExponent = 1.6f;
/// <summary>
/// Toxin volume that can be purged without damage.
/// </summary>
[ViewVariables] private float _toxinTolerance = 3f;
/// <summary>
/// Toxin damage modifier.
/// </summary>
[ViewVariables] private float _toxinLethality = 0.01f;
/// <summary>
/// Loops through each reagent in _internalSolution,
/// and calls <see cref="IMetabolizable.Metabolize"/> for each of them.
/// Also handles toxins and alcohol.
/// </summary>
/// <param name="frameTime">
/// The time since the last update in seconds.
/// </param>
public override void Update(float frameTime)
{
if (Body == null)
{
return;
}
_accumulatedFrameTime += frameTime;
// Update at most once per second
if (_accumulatedFrameTime < 1)
{
return;
}
_accumulatedFrameTime -= 1;
if (!Body.Owner.TryGetComponent(out BloodstreamComponent? bloodstream))
{
return;
}
if (bloodstream.Solution.CurrentVolume <= ReagentUnit.Zero)
{
return;
}
// Run metabolism for each reagent, remove metabolized reagents
// Using ToList here lets us edit reagents while iterating
foreach (var reagent in bloodstream.Solution.ReagentList.ToList())
{
if (!_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype? prototype))
{
continue;
}
//TODO BODY Check if it's a Toxin. If volume < _toxinTolerance, just remove it. If greater, add damage = volume * _toxinLethality
//TODO BODY Check if it has BoozePower > 0. Affect drunkenness, apply damage. Proposed formula (SS13-derived): damage = sqrt(volume) * BoozePower^_alcoholExponent * _alcoholLethality / 10
//TODO BODY Liver failure.
//TODO Make sure reagent prototypes actually have the toxin and boozepower vars set.
// Run metabolism code for each reagent
foreach (var metabolizable in prototype.Metabolism)
{
var reagentDelta = metabolizable.Metabolize(Body.Owner, reagent.ReagentId, frameTime);
bloodstream.Solution.TryRemoveReagent(reagent.ReagentId, reagentDelta);
}
}
}
public override void ExposeData(ObjectSerializer serializer)
{
//Uses typical human values for defaults.
base.ExposeData(serializer);
serializer.DataField(ref _alcoholLethality, "alcoholLethality", 0.005f);
serializer.DataField(ref _alcoholExponent, "alcoholExponent", 1.6f);
serializer.DataField(ref _toxinTolerance, "toxinTolerance", 3f);
serializer.DataField(ref _toxinLethality, "toxinLethality", 0.01f);
}
}
}

View File

@@ -1,6 +1,7 @@
#nullable enable #nullable enable
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Content.Server.GameObjects.Components.Body.Circulatory;
using Content.Server.GameObjects.Components.Chemistry; using Content.Server.GameObjects.Components.Chemistry;
using Content.Shared.Chemistry; using Content.Shared.Chemistry;
using Content.Shared.GameObjects.Components.Body.Networks; using Content.Shared.GameObjects.Components.Body.Networks;
@@ -44,8 +45,8 @@ namespace Content.Server.GameObjects.Components.Body.Behavior
_accumulatedFrameTime -= 1; _accumulatedFrameTime -= 1;
if (!Owner.TryGetComponent(out SharedSolutionContainerComponent? solution) || if (!Body.Owner.TryGetComponent(out SolutionContainerComponent? solution) ||
!Body.Owner.TryGetComponent(out SharedBloodstreamComponent? bloodstream)) !Body.Owner.TryGetComponent(out BloodstreamComponent? bloodstream))
{ {
return; return;
} }
@@ -138,10 +139,10 @@ namespace Content.Server.GameObjects.Components.Body.Behavior
public bool TryTransferSolution(Solution solution) public bool TryTransferSolution(Solution solution)
{ {
if (!CanTransferSolution(solution)) if (Body == null || !CanTransferSolution(solution))
return false; return false;
if (!Owner.TryGetComponent(out SharedSolutionContainerComponent? solutionComponent)) if (!Body.Owner.TryGetComponent(out SolutionContainerComponent? solutionComponent))
{ {
return false; return false;
} }

View File

@@ -9,14 +9,12 @@ using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Temperature; using Content.Server.GameObjects.Components.Temperature;
using Content.Shared.Alert; using Content.Shared.Alert;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Chemistry;
using Content.Shared.Damage; using Content.Shared.Damage;
using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Body;
using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Damage;
using Content.Shared.GameObjects.Components.Mobs.State; using Content.Shared.GameObjects.Components.Mobs.State;
using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.EntitySystems.ActionBlocker;
using Content.Shared.Interfaces; using Content.Shared.Interfaces;
using Content.Shared.Interfaces.Chemistry;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
@@ -317,43 +315,7 @@ namespace Content.Server.GameObjects.Components.Metabolism
} }
/// <summary> /// <summary>
/// Loops through each reagent in _internalSolution, /// Processes gases in the bloodstream.
/// and calls <see cref="IMetabolizable.Metabolize"/> for each of them.
/// </summary>
/// <param name="frameTime">The time since the last metabolism tick in seconds.</param>
private void ProcessNutrients(float frameTime)
{
if (!Owner.TryGetComponent(out BloodstreamComponent? bloodstream))
{
return;
}
if (bloodstream.Solution.CurrentVolume == 0)
{
return;
}
// Run metabolism for each reagent, remove metabolized reagents
// Using ToList here lets us edit reagents while iterating
foreach (var reagent in bloodstream.Solution.ReagentList.ToList())
{
if (!_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype? prototype))
{
continue;
}
// Run metabolism code for each reagent
foreach (var metabolizable in prototype.Metabolism)
{
var reagentDelta = metabolizable.Metabolize(Owner, reagent.ReagentId, frameTime);
bloodstream.Solution.TryRemoveReagent(reagent.ReagentId, reagentDelta);
}
}
}
/// <summary>
/// Processes gases in the bloodstream and triggers metabolism of the
/// reagents inside of it.
/// </summary> /// </summary>
/// <param name="frameTime"> /// <param name="frameTime">
/// The time since the last metabolism tick in seconds. /// The time since the last metabolism tick in seconds.
@@ -374,7 +336,6 @@ namespace Content.Server.GameObjects.Components.Metabolism
} }
ProcessGases(_accumulatedFrameTime); ProcessGases(_accumulatedFrameTime);
ProcessNutrients(_accumulatedFrameTime);
ProcessThermalRegulation(_accumulatedFrameTime); ProcessThermalRegulation(_accumulatedFrameTime);
_accumulatedFrameTime -= 1; _accumulatedFrameTime -= 1;

View File

@@ -29,6 +29,8 @@ namespace Content.Shared.Chemistry
private List<ITileReaction> _tileReactions = default!; private List<ITileReaction> _tileReactions = default!;
private List<IPlantMetabolizable> _plantMetabolism = default!; private List<IPlantMetabolizable> _plantMetabolism = default!;
private float _customPlantMetabolism; private float _customPlantMetabolism;
private bool _toxin;
private int _boozePower;
public string ID => _id; public string ID => _id;
public string Name => _name; public string Name => _name;
@@ -36,6 +38,9 @@ namespace Content.Shared.Chemistry
public string PhysicalDescription => _physicalDescription; public string PhysicalDescription => _physicalDescription;
public Color SubstanceColor => _substanceColor; public Color SubstanceColor => _substanceColor;
public bool Toxin => _toxin;
public int BoozePower => _boozePower;
//List of metabolism effects this reagent has, should really only be used server-side. //List of metabolism effects this reagent has, should really only be used server-side.
public IReadOnlyList<IMetabolizable> Metabolism => _metabolism; public IReadOnlyList<IMetabolizable> Metabolism => _metabolism;
public IReadOnlyList<ITileReaction> TileReactions => _tileReactions; public IReadOnlyList<ITileReaction> TileReactions => _tileReactions;
@@ -58,6 +63,8 @@ namespace Content.Shared.Chemistry
serializer.DataField(ref _substanceColor, "color", Color.White); serializer.DataField(ref _substanceColor, "color", Color.White);
serializer.DataField(ref _spritePath, "spritePath", string.Empty); serializer.DataField(ref _spritePath, "spritePath", string.Empty);
serializer.DataField(ref _customPlantMetabolism, "customPlantMetabolism", 1f); serializer.DataField(ref _customPlantMetabolism, "customPlantMetabolism", 1f);
serializer.DataField(ref _toxin, "toxin", false);
serializer.DataField(ref _boozePower, "boozePower", 0);
if (_moduleManager.IsServerModule) if (_moduleManager.IsServerModule)
{ {

View File

@@ -108,7 +108,7 @@
id: LiverHuman id: LiverHuman
parent: BaseHumanOrgan parent: BaseHumanOrgan
name: "human liver" name: "human liver"
description: "Filters impurities out of a bloodstream and provides other important functionality to a human." description: "Filters impurities out of a bloodstream and provides other important functionality to a human, such as reagent metabolization."
components: components:
- type: Sprite - type: Sprite
netsync: false netsync: false
@@ -118,6 +118,12 @@
durability: 15 durability: 15
size: 1 size: 1
compatibility: Biological compatibility: Biological
behaviors:
- !type:LiverBehavior
alcoholLethality: 0.005
alcoholExponent: 1.6
toxinTolerance: 3
toxinLethality: 0.01
- type: entity - type: entity
id: KidneysHuman id: KidneysHuman