Bug fixes for metabolisable reagents (#4385)

* HealthChangeMetabolism now scales with ticktime and metabolism rate

Both Food and Drink metabolisms scale with ticktime, Now HealthChangeMetabolism also does so.

Additionally, 'healthChange' now correctly scales with the metabolism rate, so it's description is now correct.

* LiverBehaviour now uses correct frameTime

Previously, the liver only metabolised reagants once every second, but incorrectly passes the current frameTime to the metabilism function, not 1 second.

* Stomach now only transfers non-empty solutions.

Makes debugging bloodstream bugs easier if the stomach is not constantly adding empty solution to it.

* Fixed StomachBehaviour using wrong SolutionContainerComponent

Stomach was using the first SolutionContainerComponent in the owner of the body, instead of the container in the owner of the mechanism (stomach). As a result, it used to use the BloodStreamComponent.Solution as a "Stomach".

* Update StomachBehavior.cs

Somach now checks if it still contains a reagant, before transferring it.

* Added argument to IMetabolizable.Metabolize()

Added availableReagent argument to IMetabolizable.Metabolize(), This ensures that this function does not over-metabolize a reagant, which can happen if tickTime*metabolismRate is larger than the available reagant

* Revert "Stomach now only transfers non-empty solutions."

This reverts commit 2a51e2d87e6e17ab76b48e5316ce501ec05ac061.

* Renamed _updateInterval to _updateIntervalSeconds

Also modified doc comment specifying units

* Fix spelling of healthChangeAmount

Changed from healthChangeAmmount to healthChangeAmount

* Fixed comment

comment used to mention _updateInterval, which has been renamed  _updateIntervalSeconds

* Fixed typo in comment

* fixed typos: reagant -> reagent

Most typos were just in comments.

* Make metabolizable classes inherit from DefaultMetabolizable

Also involved changing around IMetabolizable

* Renamed variables

metabolismAmount -> amountMetabolized

* Updated Comments in DefaultMetabolizable

Makes it clearer why DefaultMetabolizable works as it does, and that other classes depend on it.
This commit is contained in:
Leon Friedrich
2021-07-31 14:11:02 +10:00
committed by GitHub
parent 881c9c9856
commit dbc90f202a
7 changed files with 96 additions and 55 deletions

View File

@@ -1,4 +1,4 @@
using Content.Server.Nutrition.Components;
using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Metabolizable;
using Content.Shared.Chemistry.Reagent;
@@ -9,28 +9,27 @@ namespace Content.Server.Chemistry.Metabolism
{
/// <summary>
/// Default metabolism for drink reagents. Attempts to find a ThirstComponent on the target,
/// and to update it's thirst values.
/// and to update it's thirst values. Inherits metabolisation rate logic from DefaultMetabolizable.
/// </summary>
[DataDefinition]
public class DefaultDrink : IMetabolizable
public class DefaultDrink : DefaultMetabolizable
{
//Rate of metabolism in units / second
[DataField("rate")]
public ReagentUnit MetabolismRate { get; set; } = ReagentUnit.New(1);
//How much thirst is satiated when 1u of the reagent is metabolized
[DataField("hydrationFactor")]
public float HydrationFactor { get; set; } = 30.0f;
//Remove reagent at set rate, satiate thirst if a ThirstComponent can be found
ReagentUnit IMetabolizable.Metabolize(IEntity solutionEntity, string reagentId, float tickTime)
public override ReagentUnit Metabolize(IEntity solutionEntity, string reagentId, float tickTime, ReagentUnit availableReagent)
{
var metabolismAmount = MetabolismRate * tickTime;
// use DefaultMetabolism to determine how much reagent we should metabolize
var amountMetabolized = base.Metabolize(solutionEntity, reagentId, tickTime, availableReagent);
// If metabolizing entity has a ThirstComponent, hydrate them.
if (solutionEntity.TryGetComponent(out ThirstComponent? thirst))
thirst.UpdateThirst(metabolismAmount.Float() * HydrationFactor);
thirst.UpdateThirst(amountMetabolized.Float() * HydrationFactor);
//Return amount of reagent to be removed, remove reagent regardless of ThirstComponent presence
return metabolismAmount;
return amountMetabolized;
}
}
}

View File

@@ -1,4 +1,4 @@
using Content.Server.Nutrition.Components;
using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry;
using Content.Shared.Chemistry.Metabolizable;
using Content.Shared.Chemistry.Reagent;
@@ -9,30 +9,30 @@ namespace Content.Server.Chemistry.Metabolism
{
/// <summary>
/// Default metabolism for food reagents. Attempts to find a HungerComponent on the target,
/// and to update it's hunger values.
/// and to update it's hunger values. Inherits metabolisation rate logic from DefaultMetabolizable.
/// </summary>
[DataDefinition]
public class DefaultFood : IMetabolizable
public class DefaultFood : DefaultMetabolizable
{
/// <summary>
/// Rate of metabolism in units / second
/// </summary>
[DataField("rate")] public ReagentUnit MetabolismRate { get; private set; } = ReagentUnit.New(1.0);
/// <summary>
/// How much hunger is satiated when 1u of the reagent is metabolized
/// </summary>
[DataField("nutritionFactor")] public float NutritionFactor { get; set; } = 30.0f;
//Remove reagent at set rate, satiate hunger if a HungerComponent can be found
ReagentUnit IMetabolizable.Metabolize(IEntity solutionEntity, string reagentId, float tickTime)
{
var metabolismAmount = MetabolismRate * tickTime;
if (solutionEntity.TryGetComponent(out HungerComponent? hunger))
hunger.UpdateFood(metabolismAmount.Float() * NutritionFactor);
//Return amount of reagent to be removed, remove reagent regardless of HungerComponent presence
return metabolismAmount;
//Remove reagent at set rate, satiate hunger if a HungerComponent can be found
public override ReagentUnit Metabolize(IEntity solutionEntity, string reagentId, float tickTime, ReagentUnit availableReagent)
{
// use DefaultMetabolism to determine how much reagent we should metabolize
var amountMetabolized = base.Metabolize(solutionEntity, reagentId, tickTime, availableReagent);
// If metabolizing entity has a HungerComponent, feed them.
if (solutionEntity.TryGetComponent(out HungerComponent? hunger))
hunger.UpdateFood(amountMetabolized.Float() * NutritionFactor);
//Return amount of reagent to be removed. Reagent is removed regardless of HungerComponent presence
return amountMetabolized;
}
}
}

View File

@@ -10,16 +10,11 @@ namespace Content.Server.Chemistry.Metabolism
{
/// <summary>
/// Default metabolism for medicine reagents. Attempts to find a DamageableComponent on the target,
/// and to update its damage values.
/// and to update its damage values. Inherits metabolisation rate logic from DefaultMetabolizable.
/// </summary>
[DataDefinition]
public class HealthChangeMetabolism : IMetabolizable
public class HealthChangeMetabolism : DefaultMetabolizable
{
/// <summary>
/// How much of the reagent should be metabolized each sec.
/// </summary>
[DataField("rate")]
public ReagentUnit MetabolismRate { get; set; } = ReagentUnit.New(1);
/// <summary>
/// How much damage is changed when 1u of the reagent is metabolized.
@@ -41,14 +36,23 @@ namespace Content.Server.Chemistry.Metabolism
/// <param name="solutionEntity"></param>
/// <param name="reagentId"></param>
/// <param name="tickTime"></param>
/// <param name="availableReagent">Reagent available to be metabolized.</param>
/// <returns></returns>
ReagentUnit IMetabolizable.Metabolize(IEntity solutionEntity, string reagentId, float tickTime)
public override ReagentUnit Metabolize(IEntity solutionEntity, string reagentId, float tickTime, ReagentUnit availableReagent)
{
// use DefaultMetabolism to determine how much reagent we should metabolize
var amountMetabolized = base.Metabolize(solutionEntity, reagentId, tickTime, availableReagent);
// how much does this much reagent heal for
var healthChangeAmount = HealthChange * amountMetabolized.Float();
if (solutionEntity.TryGetComponent(out IDamageableComponent? health))
{
health.ChangeDamage(DamageType, (int)HealthChange, true);
float decHealthChange = (float) (HealthChange - (int) HealthChange);
_accumulatedHealth += decHealthChange;
// Heal damage by healthChangeAmmount, rounding down to nearest integer
health.ChangeDamage(DamageType, (int) healthChangeAmount, true);
// Store decimal remainder of healthChangeAmmount in _accumulatedHealth
_accumulatedHealth += (healthChangeAmount - (int) healthChangeAmount);
if (_accumulatedHealth >= 1)
{
@@ -62,7 +66,7 @@ namespace Content.Server.Chemistry.Metabolism
_accumulatedHealth += 1;
}
}
return MetabolismRate;
return amountMetabolized;
}
}
}