Replace metabolism groups with metabolism stages (#42172)

* Replace metabolism groups with metabolism stages

* return to return

* killed

* yaml linted

* yaml linted again

* margarine

* bugfixes and balancing tweaks
This commit is contained in:
pathetic meowmeow
2026-01-22 20:50:33 -05:00
committed by GitHub
parent f3db27da10
commit ff1af35afb
59 changed files with 1041 additions and 1508 deletions

View File

@@ -1,6 +0,0 @@
using Content.Shared.Body.Systems;
namespace Content.Client.Body.Systems;
/// <inheritdoc/>
public sealed class MetabolizerSystem : SharedMetabolizerSystem;

View File

@@ -4,11 +4,12 @@ using Content.Client.Chemistry.EntitySystems;
using Content.Client.Guidebook.Richtext;
using Content.Client.Message;
using Content.Client.UserInterface.ControlExtensions;
using Content.Shared.Body.Prototypes;
using Content.Shared.CCVar;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Contraband;
using Content.Shared.Localizations;
using Content.Shared.Metabolism;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
@@ -132,17 +133,18 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
#region Effects
if (_chemistryGuideData.ReagentGuideRegistry.TryGetValue(reagent.ID, out var guideEntryRegistry) &&
guideEntryRegistry.GuideEntries != null &&
guideEntryRegistry.GuideEntries.Values.Any(pair => pair.EffectDescriptions.Any()))
guideEntryRegistry.GuideEntries.Values.Any(pair => pair.EffectDescriptions.Any() || pair.Metabolites?.Any() == true))
{
EffectsDescriptionContainer.Children.Clear();
foreach (var (group, effect) in guideEntryRegistry.GuideEntries)
foreach (var (stage, effect) in guideEntryRegistry.GuideEntries)
{
if (!effect.EffectDescriptions.Any())
var hasMetabolites = effect.Metabolites?.Any() == true;
if (!effect.EffectDescriptions.Any() && !hasMetabolites)
continue;
var groupLabel = new RichTextLabel();
groupLabel.SetMarkup(Loc.GetString("guidebook-reagent-effects-metabolism-group-rate",
("group", _prototype.Index<MetabolismGroupPrototype>(group).LocalizedName), ("rate", effect.MetabolismRate)));
groupLabel.SetMarkup(Loc.GetString("guidebook-reagent-effects-metabolism-stage-rate",
("stage", _prototype.Index<MetabolismStagePrototype>(stage).LocalizedName), ("rate", effect.MetabolismRate)));
var descriptionLabel = new RichTextLabel
{
Margin = new Thickness(25, 0, 10, 0)
@@ -155,9 +157,20 @@ public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISea
{
descMsg.AddMarkupOrThrow(effectString);
i++;
if (i < descriptionsCount)
if (i < descriptionsCount || hasMetabolites)
descMsg.PushNewline();
}
if (hasMetabolites)
{
var metabolites = new List<string>();
foreach (var (metabolite, ratio) in effect.Metabolites!)
{
metabolites.Add(Loc.GetString("guidebook-reagent-effects-metabolite-item", ("rate", (double)ratio), ("reagent", _prototype.Index(metabolite).LocalizedName)));
}
metabolites.Sort();
descMsg.AddMarkupOrThrow(Loc.GetString("guidebook-reagent-effects-metabolites", ("items", ContentLocalizationManager.FormatList(metabolites))));
}
descriptionLabel.SetMessage(descMsg);
EffectsDescriptionContainer.AddChild(groupLabel);

View File

@@ -216,7 +216,7 @@ public sealed partial class CryoPodWindow : FancyWindow
float? result = null;
foreach (var (_, metabolism) in reagentProto.Metabolisms)
foreach (var (_, metabolism) in reagentProto.Metabolisms.Metabolisms)
{
foreach (var effect in metabolism.Effects)
{

View File

@@ -1,98 +0,0 @@
using Content.Shared.Body.Components;
using Content.Server.Body.Systems;
using Content.Shared.Body.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.Body.Components
{
/// <summary>
/// Handles metabolizing various reagents with given effects.
/// </summary>
[RegisterComponent, AutoGenerateComponentPause, Access(typeof(MetabolizerSystem))]
public sealed partial class MetabolizerComponent : Component
{
/// <summary>
/// The next time that reagents will be metabolized.
/// </summary>
[DataField, AutoPausedField]
public TimeSpan NextUpdate;
/// <summary>
/// How often to metabolize reagents.
/// </summary>
/// <returns></returns>
[DataField]
public TimeSpan UpdateInterval = TimeSpan.FromSeconds(1);
/// <summary>
/// Multiplier applied to <see cref="UpdateInterval"/> for adjusting based on metabolic rate multiplier.
/// </summary>
[DataField]
public float UpdateIntervalMultiplier = 1f;
/// <summary>
/// Adjusted update interval based off of the multiplier value.
/// </summary>
[ViewVariables]
public TimeSpan AdjustedUpdateInterval => UpdateInterval * UpdateIntervalMultiplier;
/// <summary>
/// From which solution will this metabolizer attempt to metabolize chemicals
/// </summary>
[DataField("solution")]
public string SolutionName = BloodstreamComponent.DefaultBloodSolutionName;
/// <summary>
/// Does this component use a solution on it's parent entity (the body) or itself
/// </summary>
/// <remarks>
/// Most things will use the parent entity (bloodstream).
/// </remarks>
[DataField]
public bool SolutionOnBody = true;
/// <summary>
/// List of metabolizer types that this organ is. ex. Human, Slime, Felinid, w/e.
/// </summary>
[DataField]
[Access(typeof(MetabolizerSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
public HashSet<ProtoId<MetabolizerTypePrototype>>? MetabolizerTypes;
/// <summary>
/// Should this metabolizer remove chemicals that have no metabolisms defined?
/// As a stop-gap, basically.
/// </summary>
[DataField]
public bool RemoveEmpty;
/// <summary>
/// How many reagents can this metabolizer process at once?
/// Used to nerf 'stacked poisons' where having 5+ different poisons in a syringe, even at low
/// quantity, would be muuuuch better than just one poison acting.
/// </summary>
[DataField("maxReagents")]
public int MaxReagentsProcessable = 3;
/// <summary>
/// A list of metabolism groups that this metabolizer will act on, in order of precedence.
/// </summary>
[DataField("groups")]
public List<MetabolismGroupEntry>? MetabolismGroups;
}
/// <summary>
/// Contains data about how a metabolizer will metabolize a single group.
/// This allows metabolizers to remove certain groups much faster, or not at all.
/// </summary>
[DataDefinition]
public sealed partial class MetabolismGroupEntry
{
[DataField(required: true)]
public ProtoId<MetabolismGroupPrototype> Id;
[DataField("rateModifier")]
public FixedPoint2 MetabolismRateModifier = 1.0;
}
}

View File

@@ -25,10 +25,14 @@ public sealed class BloodstreamSystem : SharedBloodstreamSystem
out var bloodSolution) ||
!SolutionContainer.EnsureSolution(entity.Owner,
entity.Comp.BloodTemporarySolutionName,
out var tempSolution))
out var tempSolution) ||
!SolutionContainer.EnsureSolution(entity.Owner,
entity.Comp.MetabolitesSolutionName,
out var metabolitesSolution))
return;
bloodSolution.MaxVolume = entity.Comp.BloodReferenceSolution.Volume * entity.Comp.MaxVolumeModifier;
metabolitesSolution.MaxVolume = bloodSolution.MaxVolume;
tempSolution.MaxVolume = entity.Comp.BleedPuddleThreshold * 4; // give some leeway, for chemstream as well
entity.Comp.BloodReferenceSolution.SetReagentData(GetEntityBloodData((entity, entity.Comp)));

View File

@@ -8,7 +8,6 @@ using Content.Shared.Atmos;
using Content.Shared.Body;
using Content.Shared.Body.Components;
using Content.Shared.Body.Events;
using Content.Shared.Body.Prototypes;
using Content.Shared.Chat;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
@@ -20,6 +19,7 @@ using Content.Shared.EntityConditions.Conditions.Body;
using Content.Shared.EntityEffects;
using Content.Shared.EntityEffects.Effects.Body;
using Content.Shared.EntityEffects.Effects.Damage;
using Content.Shared.Metabolism;
using Content.Shared.Mobs.Systems;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
@@ -43,7 +43,7 @@ public sealed class RespiratorSystem : EntitySystem
[Dependency] private readonly SharedEntityConditionsSystem _entityConditions = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
private static readonly ProtoId<MetabolismGroupPrototype> GasId = new("Gas");
private static readonly ProtoId<MetabolismStagePrototype> RespirationStage = new("Respiration");
public override void Initialize()
{
@@ -277,7 +277,7 @@ public sealed class RespiratorSystem : EntitySystem
if (!Resolve(lung, ref lung.Comp))
return 0;
if (lung.Comp.MetabolismGroups == null)
if (lung.Comp.Stages == null)
return 0;
float saturation = 0;
@@ -287,7 +287,7 @@ public sealed class RespiratorSystem : EntitySystem
if (reagent.Metabolisms == null)
continue;
if (!reagent.Metabolisms.TryGetValue(GasId, out var entry))
if (!reagent.Metabolisms.Metabolisms.TryGetValue(RespirationStage, out var entry))
continue;
foreach (var effect in entry.Effects)

View File

@@ -35,7 +35,7 @@ public sealed class DumpReagentGuideText : LocalizedEntityCommands
return;
}
foreach (var entry in reagent.Metabolisms.Values)
foreach (var entry in reagent.Metabolisms.Metabolisms.Values)
{
foreach (var effect in entry.Effects)
{

View File

@@ -1,21 +0,0 @@
using System.Linq;
using Content.Server.Body.Components;
using Content.Shared.EntityConditions;
using Content.Shared.EntityConditions.Conditions.Body;
namespace Content.Server.EntityConditions.Conditions;
/// <summary>
/// Returns true if this entity has any of the listed metabolizer types.
/// </summary>
/// <inheritdoc cref="EntityConditionSystem{T, TCondition}"/>
public sealed partial class MetabolizerTypeEntityConditionSystem : EntityConditionSystem<MetabolizerComponent, MetabolizerTypeCondition>
{
protected override void Condition(Entity<MetabolizerComponent> entity, ref EntityConditionEvent<MetabolizerTypeCondition> args)
{
if (entity.Comp.MetabolizerTypes == null)
return;
args.Result = entity.Comp.MetabolizerTypes.Overlaps(args.Condition.Type);
}
}

View File

@@ -1,7 +1,6 @@
using System.Linq;
using System.Text.Json.Serialization;
using Content.Server.Body.Components;
using Content.Shared.Body.Prototypes;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.EntityEffects;
@@ -43,7 +42,7 @@ public sealed class ReagentEntry
Description = proto.LocalizedDescription;
PhysicalDescription = proto.LocalizedPhysicalDescription;
SubstanceColor = proto.SubstanceColor.ToHex();
Metabolisms = proto.Metabolisms?.ToDictionary(x => x.Key.Id, x => x.Value);
Metabolisms = proto.Metabolisms?.Metabolisms.ToDictionary(x => x.Key.Id, x => x.Value);
}
}

View File

@@ -1,5 +1,4 @@
using Content.Shared.Anomaly.Effects;
using Content.Shared.Body.Prototypes;
using Content.Shared.Humanoid.Prototypes;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;

View File

@@ -2,10 +2,10 @@ using Content.Shared.Actions;
using Content.Shared.Bed.Components;
using Content.Shared.Bed.Sleep;
using Content.Shared.Body.Events;
using Content.Shared.Body.Systems;
using Content.Shared.Buckle.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Emag.Systems;
using Content.Shared.Metabolism;
using Content.Shared.Mobs.Systems;
using Content.Shared.Power;
using Content.Shared.Power.EntitySystems;
@@ -20,9 +20,9 @@ public sealed class BedSystem : EntitySystem
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
[Dependency] private readonly EmagSystem _emag = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly MetabolizerSystem _metabolizer = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
[Dependency] private readonly SharedMetabolizerSystem _metabolizer = default!;
[Dependency] private readonly SharedPowerReceiverSystem _powerReceiver = default!;
[Dependency] private readonly SleepingSystem _sleepingSystem = default!;

View File

@@ -22,6 +22,7 @@ public sealed partial class BloodstreamComponent : Component
{
public const string DefaultBloodSolutionName = "bloodstream";
public const string DefaultBloodTemporarySolutionName = "bloodstreamTemporary";
public const string DefaultMetabolitesSolutionName = "metabolites";
/// <summary>
/// The next time that blood level will be updated and bloodloss damage dealt.
@@ -171,6 +172,12 @@ public sealed partial class BloodstreamComponent : Component
[DataField]
public string BloodTemporarySolutionName = DefaultBloodTemporarySolutionName;
/// <summary>
/// Name/Key that <see cref="MetabolitesSolution"/> is indexed by.
/// </summary>
[DataField]
public string MetabolitesSolutionName = DefaultMetabolitesSolutionName;
/// <summary>
/// Internal solution for blood storage
/// </summary>
@@ -185,6 +192,12 @@ public sealed partial class BloodstreamComponent : Component
[ViewVariables]
public Entity<SolutionComponent>? TemporarySolution;
/// <summary>
/// Internal solution for metabolite storage
/// </summary>
[ViewVariables]
public Entity<SolutionComponent>? MetabolitesSolution;
/// <summary>
/// Alert to show when bleeding.
/// </summary>

View File

@@ -1,92 +1,28 @@
using Content.Shared.Body.Systems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Whitelist;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Body.Components
namespace Content.Shared.Body.Components;
[RegisterComponent, NetworkedComponent, Access(typeof(StomachSystem))]
public sealed partial class StomachComponent : Component
{
[RegisterComponent, NetworkedComponent, Access(typeof(StomachSystem))]
public sealed partial class StomachComponent : Component
{
/// <summary>
/// The next time that the stomach will try to digest its contents.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan NextUpdate;
/// <summary>
/// The solution inside of this stomach
/// </summary>
[ViewVariables]
public Entity<SolutionComponent>? Solution;
/// <summary>
/// The interval at which this stomach digests its contents.
/// </summary>
[DataField]
public TimeSpan UpdateInterval = TimeSpan.FromSeconds(1);
/// <summary>
/// A whitelist for what special-digestible-required foods this stomach is capable of eating.
/// </summary>
[DataField]
public EntityWhitelist? SpecialDigestible = null;
/// <summary>
/// Multiplier applied to <see cref="UpdateInterval"/> for adjusting based on metabolic rate multiplier.
/// </summary>
[DataField]
public float UpdateIntervalMultiplier = 1f;
/// <summary>
/// Adjusted update interval based off of the multiplier value.
/// </summary>
[ViewVariables]
public TimeSpan AdjustedUpdateInterval => UpdateInterval * UpdateIntervalMultiplier;
/// <summary>
/// The solution inside of this stomach this transfers reagents to the body.
/// </summary>
[ViewVariables]
public Entity<SolutionComponent>? Solution;
/// <summary>
/// What solution should this stomach push reagents into, on the body?
/// </summary>
[DataField]
public string BodySolutionName = BloodstreamComponent.DefaultBloodSolutionName;
/// <summary>
/// Time between reagents being ingested and them being
/// transferred to <see cref="BloodstreamComponent"/>
/// </summary>
[DataField]
public TimeSpan DigestionDelay = TimeSpan.FromSeconds(20);
/// <summary>
/// A whitelist for what special-digestible-required foods this stomach is capable of eating.
/// </summary>
[DataField]
public EntityWhitelist? SpecialDigestible = null;
/// <summary>
/// Controls whitelist behavior. If true, this stomach can digest <i>only</i> food that passes the whitelist. If false, it can digest normal food <i>and</i> any food that passes the whitelist.
/// </summary>
[DataField]
public bool IsSpecialDigestibleExclusive = true;
/// <summary>
/// Used to track how long each reagent has been in the stomach
/// </summary>
[ViewVariables]
public readonly List<ReagentDelta> ReagentDeltas = new();
/// <summary>
/// Used to track quantity changes when ingesting & digesting reagents
/// </summary>
public sealed class ReagentDelta
{
public readonly ReagentQuantity ReagentQuantity;
public TimeSpan Lifetime { get; private set; }
public ReagentDelta(ReagentQuantity reagentQuantity)
{
ReagentQuantity = reagentQuantity;
Lifetime = TimeSpan.Zero;
}
public void Increment(TimeSpan delta) => Lifetime += delta;
}
}
/// <summary>
/// Controls whitelist behavior. If true, this stomach can digest <i>only</i> food that passes the whitelist. If false, it can digest normal food <i>and</i> any food that passes the whitelist.
/// </summary>
[DataField]
public bool IsSpecialDigestibleExclusive = true;
}

View File

@@ -1,17 +0,0 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Body.Prototypes
{
[Prototype]
public sealed partial class MetabolismGroupPrototype : IPrototype
{
[IdDataField]
public string ID { get; private set; } = default!;
[DataField("name", required: true)]
private LocId Name { get; set; }
[ViewVariables(VVAccess.ReadOnly)]
public string LocalizedName => Loc.GetString(Name);
}
}

View File

@@ -1,17 +0,0 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Body.Prototypes
{
[Prototype]
public sealed partial class MetabolizerTypePrototype : IPrototype
{
[IdDataField]
public string ID { get; private set; } = default!;
[DataField("name", required: true)]
private LocId Name { get; set; }
[ViewVariables(VVAccess.ReadOnly)]
public string LocalizedName => Loc.GetString(Name);
}
}

View File

@@ -2,7 +2,6 @@ using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Body.Components;
using Content.Shared.Body.Prototypes;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Inventory.Events;

View File

@@ -1,20 +0,0 @@
using Content.Shared.Body.Events;
namespace Content.Shared.Body.Systems;
public abstract class SharedMetabolizerSystem : EntitySystem
{
/// <summary>
/// Updates the metabolic rate multiplier for a given entity,
/// raising both <see cref="GetMetabolicMultiplierEvent"/> to determine what the multiplier is and <see cref="ApplyMetabolicMultiplierEvent"/> to update relevant components.
/// </summary>
/// <param name="uid"></param>
public void UpdateMetabolicMultiplier(EntityUid uid)
{
var getEv = new GetMetabolicMultiplierEvent();
RaiseLocalEvent(uid, ref getEv);
var applyEv = new ApplyMetabolicMultiplierEvent(getEv.Multiplier);
RaiseLocalEvent(uid, ref applyEv);
}
}

View File

@@ -1,137 +1,44 @@
using Content.Shared.Body.Components;
using Content.Shared.Body.Events;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Robust.Shared.Containers;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Shared.Body.Systems
namespace Content.Shared.Body.Systems;
public sealed class StomachSystem : EntitySystem
{
public sealed class StomachSystem : EntitySystem
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
public const string DefaultSolutionName = "stomach";
public bool CanTransferSolution(
EntityUid uid,
Solution solution,
StomachComponent? stomach = null,
SolutionContainerManagerComponent? solutions = null)
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
return Resolve(uid, ref stomach, ref solutions, logMissing: false)
&& _solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution, out var stomachSolution)
// TODO: For now no partial transfers. Potentially change by design
&& stomachSolution.CanAddSolution(solution);
}
public const string DefaultSolutionName = "stomach";
public override void Initialize()
public bool TryTransferSolution(
EntityUid uid,
Solution solution,
StomachComponent? stomach = null,
SolutionContainerManagerComponent? solutions = null)
{
if (!Resolve(uid, ref stomach, ref solutions, logMissing: false)
|| !_solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution)
|| !CanTransferSolution(uid, solution, stomach, solutions))
{
SubscribeLocalEvent<StomachComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<StomachComponent, EntityUnpausedEvent>(OnUnpaused);
SubscribeLocalEvent<StomachComponent, EntRemovedFromContainerMessage>(OnEntRemoved);
SubscribeLocalEvent<StomachComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
return false;
}
private void OnMapInit(Entity<StomachComponent> ent, ref MapInitEvent args)
{
ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.AdjustedUpdateInterval;
}
_solutionContainerSystem.TryAddSolution(stomach.Solution.Value, solution);
private void OnUnpaused(Entity<StomachComponent> ent, ref EntityUnpausedEvent args)
{
ent.Comp.NextUpdate += args.PausedTime;
}
private void OnEntRemoved(Entity<StomachComponent> ent, ref EntRemovedFromContainerMessage args)
{
// Make sure the removed entity was our contained solution
if (ent.Comp.Solution is not { } solution || args.Entity != solution.Owner)
return;
// Cleared our cached reference to the solution entity
ent.Comp.Solution = null;
}
public override void Update(float frameTime)
{
var query = EntityQueryEnumerator<StomachComponent, OrganComponent, SolutionContainerManagerComponent>();
while (query.MoveNext(out var uid, out var stomach, out var organ, out var sol))
{
if (_gameTiming.CurTime < stomach.NextUpdate)
continue;
stomach.NextUpdate += stomach.AdjustedUpdateInterval;
// Get our solutions
if (!_solutionContainerSystem.ResolveSolution((uid, sol), DefaultSolutionName, ref stomach.Solution, out var stomachSolution))
continue;
if (organ.Body is not { } body || !_solutionContainerSystem.TryGetSolution(body, stomach.BodySolutionName, out var bodySolution))
continue;
var transferSolution = new Solution();
var queue = new RemQueue<StomachComponent.ReagentDelta>();
foreach (var delta in stomach.ReagentDeltas)
{
delta.Increment(stomach.AdjustedUpdateInterval);
if (delta.Lifetime > stomach.DigestionDelay)
{
if (stomachSolution.TryGetReagent(delta.ReagentQuantity.Reagent, out var reagent))
{
if (reagent.Quantity > delta.ReagentQuantity.Quantity)
reagent = new(reagent.Reagent, delta.ReagentQuantity.Quantity);
stomachSolution.RemoveReagent(reagent);
transferSolution.AddReagent(reagent);
}
queue.Add(delta);
}
}
foreach (var item in queue)
{
stomach.ReagentDeltas.Remove(item);
}
_solutionContainerSystem.UpdateChemicals(stomach.Solution.Value);
// Transfer everything to the body solution!
_solutionContainerSystem.TryAddSolution(bodySolution.Value, transferSolution);
}
}
private void OnApplyMetabolicMultiplier(Entity<StomachComponent> ent, ref ApplyMetabolicMultiplierEvent args)
{
ent.Comp.UpdateIntervalMultiplier = args.Multiplier;
}
public bool CanTransferSolution(
EntityUid uid,
Solution solution,
StomachComponent? stomach = null,
SolutionContainerManagerComponent? solutions = null)
{
return Resolve(uid, ref stomach, ref solutions, logMissing: false)
&& _solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution, out var stomachSolution)
// TODO: For now no partial transfers. Potentially change by design
&& stomachSolution.CanAddSolution(solution);
}
public bool TryTransferSolution(
EntityUid uid,
Solution solution,
StomachComponent? stomach = null,
SolutionContainerManagerComponent? solutions = null)
{
if (!Resolve(uid, ref stomach, ref solutions, logMissing: false)
|| !_solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution)
|| !CanTransferSolution(uid, solution, stomach, solutions))
{
return false;
}
_solutionContainerSystem.TryAddSolution(stomach.Solution.Value, solution);
// Add each reagent to ReagentDeltas. Used to track how long each reagent has been in the stomach
foreach (var reagent in solution.Contents)
{
stomach.ReagentDeltas.Add(new StomachComponent.ReagentDelta(reagent));
}
return true;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown.Mapping;
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
namespace Content.Shared.Chemistry.Reagent;
[TypeSerializer]
public sealed class ReagentMetabolismsSerializer : ITypeInheritanceHandler<ReagentMetabolisms, MappingDataNode>
{
public MappingDataNode PushInheritance(
ISerializationManager serializationManager,
MappingDataNode child,
MappingDataNode parent,
IDependencyCollection dependencies,
ISerializationContext? context)
{
var result = child.Copy();
foreach (var (k, v) in parent)
{
if (result.TryAddCopy(k, v))
continue;
result[k] = serializationManager.CombineMappings(
(MappingDataNode)result[k],
(MappingDataNode)v);
}
return result;
}
}

View File

@@ -2,11 +2,11 @@ using System.Collections.Frozen;
using System.Linq;
using Content.Shared.FixedPoint;
using System.Text.Json.Serialization;
using Content.Shared.Body.Prototypes;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Contraband;
using Content.Shared.EntityEffects;
using Content.Shared.Localizations;
using Content.Shared.Metabolism;
using Content.Shared.Nutrition;
using Content.Shared.Roles;
using Content.Shared.Slippery;
@@ -15,6 +15,7 @@ using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic;
using Robust.Shared.Utility;
namespace Content.Shared.Chemistry.Reagent
@@ -168,8 +169,8 @@ namespace Content.Shared.Chemistry.Reagent
[DataField]
public bool WorksOnTheDead;
[DataField]
public FrozenDictionary<ProtoId<MetabolismGroupPrototype>, ReagentEffectsEntry>? Metabolisms;
[DataField, AlwaysPushInheritance]
public ReagentMetabolisms? Metabolisms;
[DataField]
public Dictionary<ProtoId<ReactiveGroupPrototype>, ReactiveReagentEffectEntry>? ReactiveEffects;
@@ -242,15 +243,14 @@ namespace Content.Shared.Chemistry.Reagent
{
public string ReagentPrototype;
// TODO: Kill Metabolism groups!
public Dictionary<ProtoId<MetabolismGroupPrototype>, ReagentEffectsGuideEntry>? GuideEntries;
public Dictionary<ProtoId<MetabolismStagePrototype>, ReagentEffectsGuideEntry>? GuideEntries;
public List<string>? PlantMetabolisms = null;
public ReagentGuideEntry(ReagentPrototype proto, IPrototypeManager prototype, IEntitySystemManager entSys)
{
ReagentPrototype = proto.ID;
GuideEntries = proto.Metabolisms?
GuideEntries = proto.Metabolisms?.Metabolisms
.Select(x => (x.Key, x.Value.MakeGuideEntry(prototype, entSys, proto)))
.ToDictionary(x => x.Key, x => x.Item2);
if (proto.PlantMetabolisms.Count > 0)
@@ -261,6 +261,12 @@ namespace Content.Shared.Chemistry.Reagent
}
}
[DataDefinition]
public sealed partial class ReagentMetabolisms
{
[IncludeDataField(customTypeSerializer: typeof(DictionarySerializer<ProtoId<MetabolismStagePrototype>, ReagentEffectsEntry>))]
public Dictionary<ProtoId<MetabolismStagePrototype>, ReagentEffectsEntry> Metabolisms;
}
[DataDefinition]
public sealed partial class ReagentEffectsEntry
@@ -269,21 +275,27 @@ namespace Content.Shared.Chemistry.Reagent
/// Amount of reagent to metabolize, per metabolism cycle.
/// </summary>
[JsonPropertyName("rate")]
[DataField("metabolismRate")]
[DataField]
public FixedPoint2 MetabolismRate = FixedPoint2.New(0.5f);
/// <summary>
/// A list of effects to apply when these reagents are metabolized.
/// </summary>
[JsonPropertyName("effects")]
[DataField("effects", required: true)]
public EntityEffect[] Effects = default!;
[DataField]
public EntityEffect[] Effects = Array.Empty<EntityEffect>();
/// <summary>
/// Ratio of this reagent to metabolites for transfer to the next solution by a metabolizer
/// </summary>
[DataField]
public Dictionary<ProtoId<ReagentPrototype>, FixedPoint2>? Metabolites;
public string EntityEffectFormat => "guidebook-reagent-effect-description";
public ReagentEffectsGuideEntry MakeGuideEntry(IPrototypeManager prototype, IEntitySystemManager entSys, ReagentPrototype proto)
{
return new ReagentEffectsGuideEntry(MetabolismRate, proto.GuidebookReagentEffectsDescription(prototype, entSys, Effects, MetabolismRate).ToArray());
return new ReagentEffectsGuideEntry(MetabolismRate, proto.GuidebookReagentEffectsDescription(prototype, entSys, Effects, MetabolismRate).ToArray(), Metabolites);
}
}
@@ -294,10 +306,13 @@ namespace Content.Shared.Chemistry.Reagent
public string[] EffectDescriptions;
public ReagentEffectsGuideEntry(FixedPoint2 metabolismRate, string[] effectDescriptions)
public Dictionary<ProtoId<ReagentPrototype>, FixedPoint2>? Metabolites;
public ReagentEffectsGuideEntry(FixedPoint2 metabolismRate, string[] effectDescriptions, Dictionary<ProtoId<ReagentPrototype>, FixedPoint2>? metabolites)
{
MetabolismRate = metabolismRate;
EffectDescriptions = effectDescriptions;
Metabolites = metabolites;
}
}

View File

@@ -1,5 +1,6 @@
using Content.Shared.Body.Prototypes;
using System.Linq;
using Content.Shared.Localizations;
using Content.Shared.Metabolism;
using Robust.Shared.Prototypes;
namespace Content.Shared.EntityConditions.Conditions.Body;
@@ -29,3 +30,18 @@ public sealed partial class MetabolizerTypeCondition : EntityConditionBase<Metab
("shouldhave", !Inverted));
}
}
/// <summary>
/// Returns true if this entity has any of the listed metabolizer types.
/// </summary>
/// <inheritdoc cref="EntityConditionSystem{T, TCondition}"/>
public sealed partial class MetabolizerTypeEntityConditionSystem : EntityConditionSystem<MetabolizerComponent, MetabolizerTypeCondition>
{
protected override void Condition(Entity<MetabolizerComponent> entity, ref EntityConditionEvent<MetabolizerTypeCondition> args)
{
if (entity.Comp.MetabolizerTypes == null)
return;
args.Result = entity.Comp.MetabolizerTypes.Overlaps(args.Condition.Type);
}
}

View File

@@ -1,52 +0,0 @@
using Content.Shared.Body.Prototypes;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
namespace Content.Shared.EntityEffects.Effects.Solution;
/// <summary>
/// Adjust all reagents in this solution which are metabolized by a given metabolism group.
/// Quantity is modified by scale, quantity is per reagent and not a total.
/// </summary>
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
public sealed partial class AdjustReagentsByGroupEntityEffectSystem : EntityEffectSystem<SolutionComponent, AdjustReagentsByGroup>
{
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
protected override void Effect(Entity<SolutionComponent> entity, ref EntityEffectEvent<AdjustReagentsByGroup> args)
{
var quantity = args.Effect.Amount * args.Scale;
var group = args.Effect.Group;
var solution = entity.Comp.Solution;
foreach (var quant in solution.Contents.ToArray())
{
var proto = _proto.Index<ReagentPrototype>(quant.Reagent.Prototype);
if (proto.Metabolisms == null || !proto.Metabolisms.ContainsKey(group))
continue;
if (quantity > 0)
_solutionContainer.TryAddReagent(entity, proto.ID, quantity);
else
_solutionContainer.RemoveReagent(entity, proto.ID, -quantity);
}
}
}
/// <inheritdoc cref="EntityEffect"/>
public sealed partial class AdjustReagentsByGroup : EntityEffectBase<AdjustReagentsByGroup>
{
/// <summary>
/// The metabolism group being adjusted. All reagents in an affected solution with this group will be adjusted.
/// </summary>
[DataField(required: true)]
public ProtoId<MetabolismGroupPrototype> Group;
[DataField(required: true)]
public FixedPoint2 Amount;
}

View File

@@ -0,0 +1,16 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Metabolism;
[Prototype]
public sealed partial class MetabolismStagePrototype : IPrototype
{
[IdDataField]
public string ID { get; private set; } = default!;
[DataField("name", required: true)]
private LocId Name { get; set; }
[ViewVariables(VVAccess.ReadOnly)]
public string LocalizedName => Loc.GetString(Name);
}

View File

@@ -0,0 +1,148 @@
using Content.Shared.Body.Components;
using Content.Shared.FixedPoint;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Metabolism;
/// <summary>
/// Handles metabolizing various reagents with given effects.
/// </summary>
[RegisterComponent, AutoGenerateComponentPause, Access(typeof(MetabolizerSystem))]
public sealed partial class MetabolizerComponent : Component
{
/// <summary>
/// The next time that reagents will be metabolized.
/// </summary>
[DataField, AutoPausedField]
public TimeSpan NextUpdate;
/// <summary>
/// How often to metabolize reagents.
/// </summary>
/// <returns></returns>
[DataField]
public TimeSpan UpdateInterval = TimeSpan.FromSeconds(1);
/// <summary>
/// Multiplier applied to <see cref="UpdateInterval"/> for adjusting based on metabolic rate multiplier.
/// </summary>
[DataField]
public float UpdateIntervalMultiplier = 1f;
/// <summary>
/// Adjusted update interval based off of the multiplier value.
/// </summary>
[ViewVariables]
public TimeSpan AdjustedUpdateInterval => UpdateInterval * UpdateIntervalMultiplier;
/// <summary>
/// From which solution will this metabolizer attempt to metabolize chemicals for a given stage
/// </summary>
[DataField]
public Dictionary<ProtoId<MetabolismStagePrototype>, MetabolismSolutionEntry> Solutions = new()
{
["Respiration"] = new()
{
SolutionName = "Lung",
SolutionOnBody = false,
TransferSolutionName = BloodstreamComponent.DefaultBloodSolutionName,
MetabolizeAll = true
},
["Digestion"] = new()
{
SolutionName = "stomach",
SolutionOnBody = false,
TransferSolutionName = BloodstreamComponent.DefaultBloodSolutionName,
TransferEfficacy = 0.5
},
["Bloodstream"] = new()
{
SolutionName = BloodstreamComponent.DefaultBloodSolutionName,
TransferSolutionName = BloodstreamComponent.DefaultMetabolitesSolutionName,
},
["Metabolites"] = new()
{
SolutionName = BloodstreamComponent.DefaultMetabolitesSolutionName
}
};
/// <summary>
/// Does this component use a solution on it's parent entity (the body) or itself
/// </summary>
/// <remarks>
/// Most things will use the parent entity (bloodstream).
/// </remarks>
[DataField]
public bool SolutionOnBody = true;
/// <summary>
/// List of metabolizer types that this organ is. ex. Human, Slime, Felinid, w/e.
/// </summary>
[DataField]
[Access(typeof(MetabolizerSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
public HashSet<ProtoId<MetabolizerTypePrototype>>? MetabolizerTypes;
/// <summary>
/// How many reagents can this metabolizer process at once?
/// Used to nerf 'stacked poisons' where having 5+ different poisons in a syringe, even at low
/// quantity, would be muuuuch better than just one poison acting.
/// </summary>
[DataField("maxReagents")]
public int MaxReagentsProcessable = 3;
/// <summary>
/// A list of metabolism stages that this metabolizer will act on, in order of precedence.
/// </summary>
[DataField]
public List<ProtoId<MetabolismStagePrototype>> Stages = new();
}
[DataDefinition]
public sealed partial class MetabolismSolutionEntry
{
/// <summary>
/// From which solution will this metabolizer attempt to metabolize chemicals
/// </summary>
[DataField(required: true)]
public string SolutionName;
/// <summary>
/// Does this metabolizer use a solution on it's parent entity (the body) or itself
/// </summary>
/// <remarks>
/// Most things will use the parent entity (bloodstream).
/// </remarks>
[DataField]
public bool SolutionOnBody = true;
/// <summary>
/// When true, this solution will be metabolized entirely instead of at a certain rate
/// </summary>
[DataField]
public bool MetabolizeAll = false;
/// <summary>
/// Reagents without a metabolism for the current stage will be transferred to this solution
/// </summary>
[DataField]
public string? TransferSolutionName;
/// <summary>
/// Reagents transferred by this metabolizer will transfer at this rate if they don't have a metabolism
/// </summary>
[DataField]
public FixedPoint2 TransferRate = 0.25;
/// <summary>
/// The percentage of transferred reagents that actually make it to the next step in metabolism if they don't have explicit metabolites
/// </summary>
[DataField]
public FixedPoint2 TransferEfficacy = 1;
/// <summary>
/// Does this metabolizer transfer to a solution on the body or on the entity itself
/// </summary>
[DataField]
public bool TransferSolutionOnBody = true;
}

View File

@@ -1,9 +1,8 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.Body.Components;
using Content.Shared.Body;
using Content.Shared.Body.Events;
using Content.Shared.Body.Prototypes;
using Content.Shared.Body.Systems;
using Content.Shared.Body;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
@@ -21,10 +20,10 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server.Body.Systems;
namespace Content.Shared.Metabolism;
/// <inheritdoc/>
public sealed class MetabolizerSystem : SharedMetabolizerSystem
public sealed class MetabolizerSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
@@ -36,7 +35,6 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
private EntityQuery<OrganComponent> _organQuery;
private EntityQuery<SolutionContainerManagerComponent> _solutionQuery;
private static readonly ProtoId<MetabolismGroupPrototype> Gas = "Gas";
public override void Initialize()
{
@@ -45,7 +43,6 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
_organQuery = GetEntityQuery<OrganComponent>();
_solutionQuery = GetEntityQuery<SolutionContainerManagerComponent>();
SubscribeLocalEvent<MetabolizerComponent, ComponentInit>(OnMetabolizerInit);
SubscribeLocalEvent<MetabolizerComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<MetabolizerComponent, BodyRelayedEvent<ApplyMetabolicMultiplierEvent>>(OnApplyMetabolicMultiplier);
}
@@ -55,18 +52,6 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.AdjustedUpdateInterval;
}
private void OnMetabolizerInit(Entity<MetabolizerComponent> entity, ref ComponentInit args)
{
if (!entity.Comp.SolutionOnBody)
{
_solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName, out _);
}
else if (_organQuery.CompOrNull(entity)?.Body is { } body)
{
_solutionContainerSystem.EnsureSolution(body, entity.Comp.SolutionName, out _);
}
}
private void OnApplyMetabolicMultiplier(Entity<MetabolizerComponent> ent, ref BodyRelayedEvent<ApplyMetabolicMultiplierEvent> args)
{
ent.Comp.UpdateIntervalMultiplier = args.Args.Multiplier;
@@ -95,56 +80,86 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
}
}
private void TryMetabolize(Entity<MetabolizerComponent, OrganComponent?, SolutionContainerManagerComponent?> ent)
/// <summary>
/// Updates the metabolic rate multiplier for a given entity,
/// raising both <see cref="GetMetabolicMultiplierEvent"/> to determine what the multiplier is and <see cref="ApplyMetabolicMultiplierEvent"/> to update relevant components.
/// </summary>
/// <param name="uid"></param>
public void UpdateMetabolicMultiplier(EntityUid uid)
{
_organQuery.Resolve(ent, ref ent.Comp2, logMissing: false);
var getEv = new GetMetabolicMultiplierEvent();
RaiseLocalEvent(uid, ref getEv);
// First step is get the solution we actually care about
var solutionName = ent.Comp1.SolutionName;
Solution? solution = null;
Entity<SolutionComponent>? soln = default!;
EntityUid? solutionEntityUid = null;
var applyEv = new ApplyMetabolicMultiplierEvent(getEv.Multiplier);
RaiseLocalEvent(uid, ref applyEv);
}
if (ent.Comp1.SolutionOnBody)
private bool LookupSolution(
Entity<MetabolizerComponent, OrganComponent?, SolutionContainerManagerComponent?> ent,
MetabolismSolutionEntry solutionData,
bool lookupTransfer,
[NotNullWhen(true)] out Solution? solution,
[NotNullWhen(true)] out Entity<SolutionComponent>? solutionEntity,
[NotNullWhen(true)] out EntityUid? solutionOwner
)
{
solution = null;
solutionEntity = null;
solutionOwner = null;
var solutionName = lookupTransfer ? solutionData.TransferSolutionName : solutionData.SolutionName;
if (solutionName is null)
return false;
if (lookupTransfer ? solutionData.TransferSolutionOnBody : solutionData.SolutionOnBody)
{
if (ent.Comp2?.Body is { } body)
{
if (!_solutionQuery.Resolve(body, ref ent.Comp3, logMissing: false))
return;
if (!_solutionQuery.TryComp(body, out var bodySolution))
return false;
_solutionContainerSystem.TryGetSolution((body, ent.Comp3), solutionName, out soln, out solution);
solutionEntityUid = body;
solutionOwner = body;
return _solutionContainerSystem.TryGetSolution((body, bodySolution), solutionName, out solutionEntity, out solution);
}
}
else
{
if (!_solutionQuery.Resolve(ent, ref ent.Comp3, logMissing: false))
return;
return false;
_solutionContainerSystem.TryGetSolution((ent, ent), solutionName, out soln, out solution);
solutionEntityUid = ent;
solutionOwner = ent;
return _solutionContainerSystem.TryGetSolution((ent, ent), solutionName, out solutionEntity, out solution);
}
if (solutionEntityUid is null
|| soln is null
|| solution is null
|| solution.Contents.Count == 0)
{
return false;
}
private void TryMetabolizeStage(Entity<MetabolizerComponent, OrganComponent?, SolutionContainerManagerComponent?> ent, ProtoId<MetabolismStagePrototype> stage)
{
if (!ent.Comp1.Solutions.TryGetValue(stage, out var solutionData))
return;
}
if (!LookupSolution(ent, solutionData, false, out var solution, out var solutionEntity, out var solutionOwner))
return;
if (solution.Contents.Count == 0)
return;
LookupSolution(ent, solutionData, true, out var transferSolution, out var transferSolutionEntity, out _);
// Copy the solution do not edit the original solution list
var list = solution.Contents.ToList();
// Collecting blood reagent for filtering
var ev = new MetabolismExclusionEvent();
RaiseLocalEvent(solutionEntityUid.Value, ref ev);
RaiseLocalEvent(solutionOwner.Value, ref ev);
// randomize the reagent list so we don't have any weird quirks
// like alphabetical order or insertion order mattering for processing
_random.Shuffle(list);
bool isDead = _mobStateSystem.IsDead(solutionEntityUid.Value);
var isDead = _mobStateSystem.IsDead(solutionOwner.Value);
int reagents = 0;
foreach (var (reagent, quantity) in list)
@@ -156,10 +171,16 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
if (ev.Reagents.Contains(reagent))
continue;
var mostToRemove = FixedPoint2.Zero;
if (proto.Metabolisms is null)
if (proto.Metabolisms is null || !proto.Metabolisms.Metabolisms.TryGetValue(stage, out var entry))
{
if (ent.Comp1.RemoveEmpty)
var mostToTransfer = FixedPoint2.Clamp(solutionData.TransferRate, 0, quantity);
if (transferSolution is not null)
{
solution.RemoveReagent(reagent, mostToTransfer);
transferSolution.AddReagent(reagent, mostToTransfer * solutionData.TransferEfficacy);
}
else
{
solution.RemoveReagent(reagent, FixedPoint2.New(1));
}
@@ -167,73 +188,58 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
continue;
}
var rate = solutionData.MetabolizeAll ? quantity : entry.MetabolismRate;
// Remove $rate, as long as there's enough reagent there to actually remove that much
var mostToRemove = FixedPoint2.Clamp(rate, 0, quantity);
// we're done here entirely if this is true
if (reagents >= ent.Comp1.MaxReagentsProcessable)
return;
var scale = (float) mostToRemove;
if (!solutionData.MetabolizeAll)
scale /= (float) rate;
// loop over all our groups and see which ones apply
if (ent.Comp1.MetabolismGroups is null)
// if it's possible for them to be dead, and they are,
// then we shouldn't process any effects, but should probably
// still remove reagents
if (isDead && !proto.WorksOnTheDead)
continue;
// TODO: Kill MetabolismGroups!
foreach (var group in ent.Comp1.MetabolismGroups)
var actualEntity = ent.Comp2?.Body ?? solutionOwner.Value;
// do all effects, if conditions apply
foreach (var effect in entry.Effects)
{
if (!proto.Metabolisms.TryGetValue(group.Id, out var entry))
if (scale < effect.MinScale)
continue;
var rate = entry.MetabolismRate * group.MetabolismRateModifier;
// Remove $rate, as long as there's enough reagent there to actually remove that much
mostToRemove = FixedPoint2.Clamp(rate, 0, quantity);
var scale = (float) mostToRemove;
// TODO: This is a very stupid workaround to lungs heavily relying on scale = reagent quantity. Needs lung and metabolism refactors to remove.
// TODO: Lungs just need to have their scale be equal to the mols consumed, scale needs to be not hardcoded either and configurable per metabolizer...
if (group.Id != Gas)
scale /= (float) entry.MetabolismRate;
// if it's possible for them to be dead, and they are,
// then we shouldn't process any effects, but should probably
// still remove reagents
if (isDead && !proto.WorksOnTheDead)
if (effect.Probability < 1.0f && !_random.Prob(effect.Probability))
continue;
var actualEntity = ent.Comp2?.Body ?? solutionEntityUid.Value;
// See if conditions apply
if (effect.Conditions != null && !CanMetabolizeEffect(actualEntity, ent, solutionEntity.Value, effect.Conditions))
continue;
// do all effects, if conditions apply
foreach (var effect in entry.Effects)
ApplyEffect(effect);
}
// TODO: We should have to do this with metabolism. ReagentEffect struct needs refactoring and so does metabolism!
void ApplyEffect(EntityEffect effect)
{
switch (effect)
{
if (scale < effect.MinScale)
continue;
if (effect.Probability < 1.0f && !_random.Prob(effect.Probability))
continue;
// See if conditions apply
if (effect.Conditions != null && !CanMetabolizeEffect(actualEntity, ent, soln.Value, effect.Conditions))
continue;
ApplyEffect(effect);
}
// TODO: We should have to do this with metabolism. ReagentEffect struct needs refactoring and so does metabolism!
void ApplyEffect(EntityEffect effect)
{
switch (effect)
{
case ModifyLungGas:
_entityEffects.ApplyEffect(ent, effect, scale);
break;
case AdjustReagent:
_entityEffects.ApplyEffect(soln.Value, effect, scale);
break;
default:
_entityEffects.ApplyEffect(actualEntity, effect, scale);
break;
}
case ModifyLungGas:
_entityEffects.ApplyEffect(ent, effect, scale);
break;
case AdjustReagent:
_entityEffects.ApplyEffect(solutionEntity.Value, effect, scale);
break;
default:
_entityEffects.ApplyEffect(actualEntity, effect, scale);
break;
}
}
@@ -244,10 +250,32 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
// We have processed a reagant, so count it towards the cap
reagents += 1;
if (transferSolution is not null && entry.Metabolites is not null)
{
foreach (var (metabolite, ratio) in entry.Metabolites)
{
transferSolution.AddReagent(metabolite, mostToRemove * ratio);
}
}
}
}
_solutionContainerSystem.UpdateChemicals(soln.Value);
_solutionContainerSystem.UpdateChemicals(solutionEntity.Value);
if (transferSolutionEntity is not null)
{
_solutionContainerSystem.UpdateChemicals(transferSolutionEntity.Value);
}
}
private void TryMetabolize(Entity<MetabolizerComponent, OrganComponent?, SolutionContainerManagerComponent?> ent)
{
_organQuery.Resolve(ent, ref ent.Comp2, logMissing: false);
foreach (var stage in ent.Comp1.Stages)
{
TryMetabolizeStage(ent, stage);
}
}
/// <summary>

View File

@@ -0,0 +1,16 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Metabolism;
[Prototype]
public sealed partial class MetabolizerTypePrototype : IPrototype
{
[IdDataField]
public string ID { get; private set; } = default!;
[DataField("name", required: true)]
private LocId Name { get; set; }
[ViewVariables(VVAccess.ReadOnly)]
public string LocalizedName => Loc.GetString(Name);
}

View File

@@ -220,7 +220,7 @@ public sealed partial class IngestionSystem
if (reagent.Metabolisms == null)
continue;
foreach (var entry in reagent.Metabolisms.Values)
foreach (var entry in reagent.Metabolisms.Metabolisms.Values)
{
foreach (var effect in entry.Effects)
{
@@ -271,7 +271,7 @@ public sealed partial class IngestionSystem
if (reagent.Metabolisms == null)
continue;
foreach (var entry in reagent.Metabolisms.Values)
foreach (var entry in reagent.Metabolisms.Metabolisms.Values)
{
foreach (var effect in entry.Effects)
{

View File

@@ -374,13 +374,16 @@ public sealed partial class IngestionSystem : EntitySystem
_reaction.DoEntityReaction(entity, split, ReactionMethod.Ingestion);
// Everything is good to go item has been successfuly eaten
var afterEv = new IngestedEvent(args.User, entity, split, forceFed);
var afterEv = new IngestedEvent(args.User, entity, split, forceFed, beforeEv.Transfer >= beforeEv.Max);
RaiseLocalEvent(food, ref afterEv);
_stomach.TryTransferSolution(stomachToUse.Value.Owner, split, stomachToUse);
if (!afterEv.Destroy)
{
if (beforeEv.Transfer >= beforeEv.Max)
return;
args.Repeat = afterEv.Repeat;
return;
}
@@ -460,7 +463,7 @@ public sealed partial class IngestionSystem : EntitySystem
{
var targetName = Identity.Entity(args.Target, EntityManager);
var userName = Identity.Entity(args.User, EntityManager);
_popup.PopupEntity(Loc.GetString("edible-force-feed-success", ("user", userName), ("verb", edible.Verb), ("flavors", flavors)), entity, entity);
_popup.PopupEntity(Loc.GetString("edible-force-feed-success", ("user", userName), ("verb", edible.Verb), ("flavors", flavors), ("satiated", args.Satiated)), entity, entity);
_popup.PopupClient(Loc.GetString("edible-force-feed-success-user", ("target", targetName), ("verb", edible.Verb)), args.User, args.User);
@@ -470,7 +473,7 @@ public sealed partial class IngestionSystem : EntitySystem
}
else
{
_popup.PopupPredicted(Loc.GetString(edible.Message, ("food", entity.Owner), ("flavors", flavors)),
_popup.PopupPredicted(Loc.GetString(edible.Message, ("food", entity.Owner), ("flavors", flavors), ("satiated", args.Satiated)),
Loc.GetString(edible.OtherMessage),
args.User,
args.User);

View File

@@ -150,8 +150,9 @@ public record struct IngestingEvent(EntityUid Food, Solution Split, bool ForceFe
/// <param name="Target">Who is doing the eating?</param>
/// <param name="Split">The solution we're currently eating.</param>
/// <param name="ForceFed">Whether we're being fed by someone else, checkec enough I might as well pass it.</param>
/// <param name="Satiated">Whether the entity will stop eating after this.</param>
[ByRefEvent]
public record struct IngestedEvent(EntityUid User, EntityUid Target, Solution Split, bool ForceFed)
public record struct IngestedEvent(EntityUid User, EntityUid Target, Solution Split, bool ForceFed, bool Satiated)
{
// Should we destroy the ingested entity?
public bool Destroy;

View File

@@ -17,7 +17,9 @@ guidebook-reagent-sources-header = Sources
guidebook-reagent-sources-ent-wrapper = [bold]{$name}[/bold] \[1\]
guidebook-reagent-sources-gas-wrapper = [bold]{$name} (gas)[/bold] \[1\]
guidebook-reagent-effects-header = Effects
guidebook-reagent-effects-metabolism-group-rate = [bold]{$group}[/bold] [color=gray]({$rate} units per second)[/color]
guidebook-reagent-effects-metabolism-stage-rate = [bold]{$stage}[/bold] [color=gray]({$rate} units per second)[/color]
guidebook-reagent-effects-metabolite-item = {$reagent} at a rate of { NATURALPERCENT($rate, 2) }
guidebook-reagent-effects-metabolites = Metabolizes into { $items }.
guidebook-reagent-plant-metabolisms-header = Plant Metabolism
guidebook-reagent-plant-metabolisms-rate = [bold]Plant Metabolism[/bold] [color=gray](1 unit every 3 seconds as base)[/color]
guidebook-reagent-physical-description = [italic]Seems to be {$description}.[/italic]

View File

@@ -1,8 +0,0 @@
metabolism-group-poison = Poison
metabolism-group-medicine = Medicine
metabolism-group-narcotic = Narcotic
metabolism-group-alcohol = Alcohol
metabolism-group-food = Food
metabolism-group-drink = Drink
metabolism-group-gas = Gas
metabolism-group-plant-metabolisms = Plant Metabolism

View File

@@ -0,0 +1,6 @@
metabolism-stage-respiration = Respiration
metabolism-stage-digestion = Digestion
metabolism-stage-bloodstream = Bloodstream
metabolism-stage-metabolites = Metabolites
metabolism-stage-plant = Plant Metabolism

View File

@@ -25,11 +25,16 @@ ingestion-verb-drink = Drink
# Edible Component
edible-nom = Nom. {$flavors}
-edible-satiated = { $satiated ->
[true] {" "}You don't feel like you could { $verb } any more.
*[false] {""}
}
edible-nom = Nom. {$flavors}{ -edible-satiated(satiated: $satiated, verb: "eat") }
edible-nom-other = Nom.
edible-slurp = Slurp. {$flavors}
edible-slurp = Slurp. {$flavors}{ -edible-satiated(satiated: $satiated, verb: "drink") }
edible-slurp-other = Slurp.
edible-swallow = You swallow { THE($food) }
edible-swallow = You swallow { THE($food) }.{ -edible-satiated(satiated: $satiated, verb: "swallow") }
edible-gulp = Gulp. {$flavors}
edible-gulp-other = Gulp.
@@ -52,5 +57,5 @@ edible-verb-pill = swallow
## Force feeding
edible-force-feed = {CAPITALIZE(THE($user))} is trying to make you {$verb} something!
edible-force-feed-success = {CAPITALIZE(THE($user))} forced you to {$verb} something! {$flavors}
edible-force-feed-success = {CAPITALIZE(THE($user))} forced you to {$verb} something! {$flavors}{ -edible-satiated(satiated: $satiated, verb: $verb) }
edible-force-feed-success-user = You successfully feed {THE($target)}

View File

@@ -278,14 +278,7 @@
components:
- type: Metabolizer
maxReagents: 6
removeEmpty: true
groups:
- id: Food
- id: Drink
- id: Medicine
- id: Poison
- id: Narcotic
- id: Alcohol
stages: [ Digestion, Bloodstream, Metabolites ]
- type: entity
parent: OrganDionaBrain

View File

@@ -262,15 +262,7 @@
- type: Metabolizer
maxReagents: 6
metabolizerTypes: [ Slime ]
removeEmpty: true
groups:
- id: Food
- id: Drink
- id: Medicine
- id: Poison
- id: Narcotic
- id: Alcohol
rateModifier: 2.5
stages: [ Digestion, Bloodstream, Metabolites ]
- type: entity
parent: [ OrganBaseLungs, OrganSlimePersonInternal, OrganSlimePersonMetabolizer ]

View File

@@ -332,12 +332,7 @@
category: Lungs
- type: Lung
- type: Metabolizer
removeEmpty: true
solutionOnBody: false
solution: "Lung"
groups:
- id: Gas
rateModifier: 100.0
stages: [ Respiration ]
- type: SolutionContainerManager
solutions:
Lung:
@@ -364,10 +359,7 @@
- state: heart-on
- type: Metabolizer
maxReagents: 2
groups:
- id: Medicine
- id: Poison
- id: Narcotic
stages: [ Bloodstream ]
- type: entity
parent: OrganBase
@@ -385,9 +377,7 @@
maxVol: 50
- type: Metabolizer
maxReagents: 3
groups:
- id: Food
- id: Drink
stages: [ Digestion ]
- type: Sprite
layers:
- state: stomach
@@ -410,8 +400,7 @@
heldPrefix: liver
- type: Metabolizer
maxReagents: 1
groups:
- id: Alcohol
stages: [ Metabolites ]
- type: entity
parent: OrganBase
@@ -430,7 +419,6 @@
heldPrefix: kidneys
- type: Metabolizer
maxReagents: 5
removeEmpty: true
- type: entity
id: OrganSpriteHumanInternal

View File

@@ -1,34 +0,0 @@
# Default human metabolism groups.
- type: metabolismGroup
id: Poison
name: metabolism-group-poison
- type: metabolismGroup
id: Medicine
name: metabolism-group-medicine
- type: metabolismGroup
id: Narcotic
name: metabolism-group-narcotic
- type: metabolismGroup
id: Alcohol
name: metabolism-group-alcohol
- type: metabolismGroup
id: Food
name: metabolism-group-food
- type: metabolismGroup
id: Drink
name: metabolism-group-drink
# Used for gases that have effects on being inhaled
- type: metabolismGroup
id: Gas
name: metabolism-group-gas
# Dummy for the guide
- type: metabolismGroup
id: PlantMetabolisms
name: metabolism-group-plant-metabolisms

View File

@@ -0,0 +1,23 @@
# Animal metabolism stages
- type: metabolismStage
id: Respiration
name: metabolism-stage-respiration
- type: metabolismStage
id: Digestion
name: metabolism-stage-digestion
- type: metabolismStage
id: Bloodstream
name: metabolism-stage-bloodstream
- type: metabolismStage
id: Metabolites
name: metabolism-stage-metabolites
# Dummy for the guide
- type: metabolismStage
id: PlantMetabolisms
name: metabolism-stage-plant

View File

@@ -90,9 +90,7 @@
solutionOnBody: false
updateInterval: 0.25
metabolizerTypes: [ Dragon ]
groups:
- id: Medicine
- id: Poison
stages: [ Digestion, Bloodstream ]
- type: Butcherable
spawned:
- id: MaterialBananium1

View File

@@ -115,9 +115,7 @@
solutionOnBody: false
updateInterval: 0.25
metabolizerTypes: [ Dragon ]
groups:
- id: Medicine
- id: Poison
stages: [ Digestion, Bloodstream ]
- type: Butcherable
spawned:
- id: FoodMeatDragon

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
slipData:
requiredSlipSpeed: 3.5
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 3
@@ -26,7 +26,7 @@
parent: BaseDrink
abstract: true
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 2
@@ -49,13 +49,12 @@
requiredSlipSpeed: 3.5
friction: 0.4
metabolisms:
Drink:
Digestion:
metabolites:
Ethanol: 0.12
effects:
- !type:SatiateThirst
factor: 2
- !type:AdjustReagent
reagent: Ethanol
amount: 0.06
reactiveEffects:
Flammable:
methods: [ Touch ]

View File

@@ -8,7 +8,9 @@
color: "#664300"
recognizable: true
metabolisms:
Drink:
Digestion:
metabolites:
Theobromine: 0.1
effects:
- !type:SatiateThirst
factor: 2
@@ -16,9 +18,6 @@
effectProto: StatusEffectDrowsiness
time: 2
type: Remove
- !type:AdjustReagent
reagent: Theobromine
amount: 0.05
metamorphicSprite:
sprite: Objects/Consumable/Drinks/coffeeglass.rsi
state: icon_empty
@@ -36,13 +35,9 @@
color: "#664300"
recognizable: true
metabolisms:
Drink:
effects:
- !type:SatiateThirst
factor: 2
- !type:AdjustReagent
reagent: Theobromine
amount: 0.05
Digestion:
metabolites:
Theobromine: 0.1
- type: reagent
id: Cream
@@ -53,7 +48,7 @@
flavor: creamy
color: "#DFD7AF"
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 1
@@ -67,7 +62,7 @@
flavor: nutty
color: "#f4eadb"
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 4 # Coconut water is 94% water
@@ -81,7 +76,7 @@
flavor: creamy
color: "#FFEABF"
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 2
@@ -101,7 +96,7 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 2
@@ -157,13 +152,12 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
Digestion:
metabolites:
Theobromine: 0.1
effects:
- !type:SatiateThirst
factor: 2
- !type:AdjustReagent
reagent: Theobromine
amount: 0.05
- !type:ModifyStatusEffect
effectProto: StatusEffectDrowsiness
time: 2
@@ -199,13 +193,10 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
effects:
- !type:SatiateThirst
factor: 2
- !type:AdjustReagent
reagent: Theobromine
amount: 0.05
Digestion:
metabolites:
Theobromine: 0.1
- type: reagent
id: JuiceBerryPoison
@@ -217,11 +208,9 @@
flavor: bitter
color: "#6600CC"
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
Poison:
effects:
- !type:HealthChange
damage:
types:
@@ -243,7 +232,7 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 2
@@ -263,7 +252,7 @@
- !type:PlantAdjustWater
amount: 0.9
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 4
@@ -284,7 +273,7 @@
color: "#DEDACD"
recognizable: true
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 4
@@ -307,7 +296,7 @@
flavor: terrible
color: "#faffba"
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: -2
@@ -319,7 +308,7 @@
group: Drinks
physicalDesc: reagent-physical-desc-nothing
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 2
@@ -341,7 +330,7 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 6
@@ -349,8 +338,6 @@
effectProto: StatusEffectDrowsiness
time: 3
type: Remove
Poison:
effects:
- !type:HealthChange
damage:
types:
@@ -382,7 +369,7 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 2
@@ -401,13 +388,9 @@
color: "#8a5a3a"
recognizable: true
metabolisms:
Drink:
effects:
- !type:SatiateThirst
factor: 2
- !type:AdjustReagent
reagent: Theobromine
amount: 0.05
Digestion:
metabolites:
Theobromine: 0.1
metamorphicSprite:
sprite: Objects/Consumable/Drinks/teaglass.rsi
state: icon_empty
@@ -446,11 +429,11 @@
meltingPoint: 0.0
friction: 0.4
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 4
Gas:
Respiration:
effects:
- !type:HealthChange
ignoreResistances: true
@@ -476,7 +459,7 @@
boilingPoint: 100.0
friction: 0.05 # Copied from Ice Crust
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 3 # Slightly worse for quenching thirst than just straight water
@@ -499,7 +482,7 @@
flavor: cheapnoodles
color: "#664300"
metabolisms:
Food:
Digestion:
effects:
- !type:SatiateHunger
factor: 1
@@ -513,7 +496,7 @@
flavor: cheapnoodles
color: "#664300"
metabolisms:
Food:
Digestion:
effects:
- !type:SatiateHunger
factor: 4
@@ -533,13 +516,12 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
Digestion:
metabolites:
Theobromine: 0.1
effects:
- !type:SatiateThirst
factor: 4
- !type:AdjustReagent
reagent: Theobromine
amount: 0.05
- type: reagent
id: Pilk
@@ -550,7 +532,7 @@
flavor: pilk
color: "#e7c69f"
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 1
@@ -606,7 +588,7 @@
flavor: mopwata
color: "#59502b"
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 0.6

View File

@@ -53,16 +53,10 @@
flavor: carrot
color: "#FF8820"
metabolisms:
Drink:
effects:
- !type:SatiateThirst
factor: 2
- !type:AdjustReagent
reagent: Oculine
amount: 0.5
- !type:AdjustReagent
reagent: Nutriment
amount: 0.5
Digestion:
metabolites:
Oculine: 1
Nutriment: 1
- type: reagent
id: JuiceGrape

View File

@@ -14,7 +14,7 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 2
@@ -38,7 +38,7 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 4
@@ -76,7 +76,9 @@
flavor: energydrink
color: "#ffffbf"
metabolisms:
Drink:
Digestion:
metabolites:
Theobromine: 0.2
effects:
- !type:SatiateThirst
factor: 2
@@ -84,9 +86,6 @@
effectProto: StatusEffectDrowsiness
time: 2
type: Remove
- !type:AdjustReagent
reagent: Theobromine
amount: 0.1
fizziness: 0.4
- type: reagent
@@ -204,7 +203,7 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 4
@@ -263,15 +262,12 @@
metamorphicFillBaseName: fill-
metamorphicChangeColor: false
metabolisms:
Drink:
Digestion:
metabolites:
Theobromine: 0.2
effects:
- !type:SatiateThirst
factor: 2
- !type:AdjustReagent
reagent: Theobromine
amount: 0.1
Poison:
effects:
- !type:HealthChange
conditions:
- !type:MetabolizerTypeCondition

View File

@@ -127,7 +127,7 @@
color: saddlebrown
recognizable: true
metabolisms:
Food:
Digestion:
effects:
- !type:SatiateHunger
factor: 0.5
@@ -159,7 +159,7 @@
- !type:PlantAdjustHealth
amount: -2
metabolisms:
Food:
Digestion:
effects:
# eating salt on its own kinda sucks, kids
- !type:SatiateThirst
@@ -178,7 +178,7 @@
tileReactions:
- !type:SpillTileReaction
metabolisms:
Food:
Digestion:
# 12 diona blood for 1 unit of syrup, this stuff better be worthwhile.
effects:
- !type:SatiateHunger

View File

@@ -8,7 +8,7 @@
flavor: nutriment
color: "#24591F"
metabolisms:
Food:
Metabolites:
effects:
- !type:SatiateHunger
plantMetabolism:
@@ -27,7 +27,7 @@
flavor: vitamin
color: "#D3D3D3"
metabolisms:
Food: #This makes it not compete with medicines, a large bonus for something that can heal
Metabolites: #This makes it not compete with medicines, a large bonus for something that can heal
effects:
- !type:HealthChange
probability: 0.5
@@ -56,7 +56,7 @@
flavor: protein
color: "#FFFFE5"
metabolisms:
Food:
Metabolites:
effects:
- !type:HealthChange
probability: 0.5
@@ -78,7 +78,7 @@
color: white
meltingPoint: 146.0
metabolisms:
Food:
Metabolites:
effects:
- !type:SatiateHunger
conditions:

View File

@@ -8,16 +8,13 @@
color: white
recognizable: true
metabolisms:
Food:
Digestion:
metabolites:
Sugar: 0.4
Nutriment: 0.2
effects:
- !type:AdjustReagent
reagent: Sugar
amount: 0.4
- !type:SatiateThirst
factor: -0.2 #its flour
- !type:AdjustReagent
reagent: Nutriment
amount: 0.1
- type: reagent
id: Cornmeal
@@ -28,13 +25,12 @@
flavor: corn #so corn doesnt taste chalky
color: tan
metabolisms:
Food:
Digestion:
metabolites:
Nutriment: 0.2
effects:
- !type:SatiateThirst
factor: -0.2 #its cornflour
- !type:AdjustReagent
reagent: Nutriment
amount: 0.1
- type: reagent
id: Oats
@@ -45,14 +41,10 @@
flavor: oats
color: tan
metabolisms:
Food:
effects:
- !type:AdjustReagent
reagent: Sugar
amount: 0.2
- !type:AdjustReagent
reagent: Nutriment
amount: 0.3
Digestion:
metabolites:
Sugar: 0.4
Nutriment: 0.6
- type: reagent
id: Enzyme
@@ -73,11 +65,9 @@
color: white
recognizable: true
metabolisms:
Food:
effects:
- !type:AdjustReagent
reagent: UncookedAnimalProteins
amount: 0.5
Digestion:
metabolites:
UncookedAnimalProteins: 1
- type: reagent
id: EggCooked
@@ -89,11 +79,9 @@
color: white
recognizable: true
metabolisms:
Food:
effects:
- !type:AdjustReagent
reagent: Protein
amount: 1
Digestion:
metabolites:
Protein: 2
- type: reagent
id: Blackpepper
@@ -105,7 +93,7 @@
color: black
recognizable: true
metabolisms:
Food:
Digestion:
effects:
- !type:Emote
emote: Cough
@@ -134,14 +122,11 @@
color: tan
recognizable: true
metabolisms:
Food:
Digestion:
metabolites:
Water: 0.8
Vitamin: 0.2
effects:
- !type:AdjustReagent
reagent: Water
amount: 0.4
- !type:AdjustReagent
reagent: Vitamin
amount: 0.1
- !type:Vomit
probability: 0.1
conditions:
@@ -159,14 +144,10 @@
color: white
recognizable: true
metabolisms:
Food:
effects:
- !type:AdjustReagent
reagent: Sugar
amount: 0.4
- !type:AdjustReagent
reagent: Nutriment
amount: 0.1
Digestion:
metabolites:
Sugar: 0.8
Nutriment: 0.2
- type: reagent
id: OilOlive
@@ -179,11 +160,9 @@
color: olive
recognizable: true
metabolisms:
Food:
effects:
- !type:AdjustReagent
reagent: Nutriment
amount: 0.75
Digestion:
metabolites:
Nutriment: 1.5
- type: reagent
id: Oil
@@ -213,27 +192,24 @@
meltingPoint: 146
boilingPoint: 410 # Really high boiling point compared to its melting
metabolisms:
Food:
Digestion:
metabolites:
Nutriment: 1.5
effects:
- !type:AdjustReagent
reagent: Nutriment #Oils enhance nutrition
amount: 0.75
Poison:
effects:
- !type:AdjustTemperature
amount: 250 # thermal energy, not temp
- !type:HealthChange
conditions:
- !type:ReagentCondition
reagent: CapsaicinOil
min: 5
damage:
types:
Caustic: 1
- !type:PopupMessage
type: Local
messages: [ "capsaicin-effect-light-burn" ]
probability: 0.2
- !type:AdjustTemperature
amount: 250 # thermal energy, not temp
- !type:HealthChange
conditions:
- !type:ReagentCondition
reagent: CapsaicinOil
min: 5
damage:
types:
Caustic: 1
- !type:PopupMessage
type: Local
messages: [ "capsaicin-effect-light-burn" ]
probability: 0.2
- type: reagent
id: CocoaPowder #Candy and chocolate
@@ -245,7 +221,7 @@
color: "#800000"
meltingPoint: 146.0
metabolisms:
Food:
Digestion:
effects:
- !type:SatiateHunger
conditions:
@@ -273,11 +249,9 @@
boilingPoint: 100.0
recognizable: true
metabolisms:
Food:
effects:
- !type:AdjustReagent
reagent: Nutriment
amount: 0.75
Digestion:
metabolites:
Nutriment: 1.5
- type: reagent
id: TeaPowder
@@ -288,13 +262,12 @@
color: "#7F8400"
group: Foods
metabolisms:
Food:
Digestion:
metabolites:
Nutriment: 0.2
effects:
- !type:SatiateThirst
factor: -0.2
- !type:AdjustReagent
reagent: Nutriment
amount: 0.1
- type: reagent
id: FrostOil
@@ -305,12 +278,9 @@
flavor: cold
color: skyblue
metabolisms:
Food:
effects:
- !type:AdjustReagent
reagent: Nutriment #Oils enhance nutrition
amount: 0.75
Poison:
Digestion:
metabolites:
Nutriment: 1.5
effects:
- !type:AdjustTemperature
amount: -250 # thermal energy, not temp

View File

@@ -15,7 +15,9 @@
standsout: true
physicalDesc: reagent-physical-desc-ferrous
metabolisms:
Drink:
Digestion:
metabolites:
UncookedAnimalProteins: 0.2
effects:
- !type:SatiateThirst
factor: 1.0
@@ -23,13 +25,6 @@
- !type:MetabolizerTypeCondition
type: [ Human ]
inverted: true
Food:
effects:
- !type:AdjustReagent
reagent: UncookedAnimalProteins
amount: 0.1
Medicine:
effects:
- !type:HealthChange
conditions:
- !type:MetabolizerTypeCondition
@@ -71,7 +66,7 @@
tileReactions:
- !type:SpillTileReaction
metabolisms:
Food:
Digestion:
# Delicious!
effects:
- !type:SatiateHunger
@@ -103,7 +98,7 @@
tileReactions:
- !type:SpillTileReaction
metabolisms:
Food:
Digestion:
# Sweet!
effects:
- !type:SatiateHunger
@@ -146,12 +141,12 @@
flavor: bitter
color: "#2b0700"
metabolisms:
Drink:
Digestion:
# Disgusting!
effects:
- !type:SatiateThirst
factor: -0.5
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -170,7 +165,7 @@
color: "#f4692e"
recognizable: true
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 1.5
@@ -222,13 +217,12 @@
requiredSlipSpeed: 4.0 #It's not as slippery as water
friction: 0.4
metabolisms:
Drink:
Digestion:
metabolites:
Nutriment: 0.1
effects:
- !type:SatiateThirst
factor: 0.5
- !type:AdjustReagent
reagent: Nutriment
amount: 0.1
footstepSound:
collection: FootstepBlood
params:
@@ -243,12 +237,10 @@
flavor: mindful
color: "#C584B8"
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateHunger
factor: 1.5
Poison:
effects:
- !type:HealthChange
damage:
types:

View File

@@ -10,7 +10,7 @@
- !type:PlantAdjustNutrition
amount: 2
metabolisms:
Food:
Digestion:
effects:
- !type:SatiateHunger
conditions:
@@ -34,7 +34,7 @@
probability: 0.3
amount: 0.4
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:SatiateHunger
conditions:
@@ -62,7 +62,7 @@
- !type:PlantAdjustPests
amount: -6
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -90,7 +90,7 @@
- !type:PlantAdjustMutationMod
amount: 0.1
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -122,7 +122,7 @@
amount: 1
- !type:RobustHarvest {}
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -146,8 +146,6 @@
Asphyxiation: 1
Heat: 2
Poison: 1
Medicine:
effects:
- !type:Polymorph
prototype: TreeMorph
conditions:
@@ -187,7 +185,7 @@
- !type:PlantAdjustWeeds
amount: -6
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -213,13 +211,13 @@
- !type:PlantAdjustHealth
amount: 0.5
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
types:
Caustic: 1
Gas:
Respiration:
effects:
- !type:HealthChange
conditions:
@@ -303,7 +301,7 @@
amount: 1
- !type:PlantDiethylamine {}
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:

View File

@@ -18,7 +18,7 @@
boilingPoint: 55.5
meltingPoint: -50.0
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -35,7 +35,7 @@
boilingPoint: 4200.0
meltingPoint: 3550.0
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -60,7 +60,7 @@
physicalDesc: reagent-physical-desc-alkaline
color: "#e5420b"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -84,7 +84,7 @@
- Science
color: "#776291"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -123,7 +123,7 @@
boilingPoint: 353.2
meltingPoint: 278.7
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -148,14 +148,12 @@
boilingPoint: 1661.0
meltingPoint: 596.0
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
types:
Heat: 1.5
Medicine:
effects:
- !type:Vomit
conditions:
- !type:ReagentCondition
@@ -181,7 +179,7 @@
physicalDesc: reagent-physical-desc-grainy
color: "#F0F0F0"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:SatiateThirst
factor: -5 # This is basically industrial dessicant
@@ -209,7 +207,7 @@
physicalDesc: reagent-physical-desc-refreshing
color: "#bf1365"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:

View File

@@ -11,7 +11,7 @@
boilingPoint: 111.0
meltingPoint: -5.0
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -60,7 +60,7 @@
requiredSlipSpeed: 3.5
friction: 0.3 # Slightly less friction than water, but not as bad as space lube
metabolisms:
Food:
Digestion:
effects:
- !type:Vomit
conditions:
@@ -68,8 +68,6 @@
reagent: SoapReagent
min: 6
probability: 0.20
Drink:
effects:
- !type:Vomit
conditions:
- !type:ReagentCondition
@@ -115,13 +113,13 @@
- !type:ModifyBleed
amount: -1.5
metabolisms:
Narcotic:
Bloodstream:
effects:
- !type:ModifyStatusEffect
effectProto: StatusEffectSeeingRainbow
time: 5
type: Add
Drink:
Digestion:
effects:
- !type:GenericStatusEffect
key: Muted

View File

@@ -40,7 +40,7 @@
- !type:PlantAdjustHealth
amount: -1
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -58,7 +58,7 @@
boilingPoint: 2595.0
meltingPoint: 1083.0
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.1
effects:
- !type:HealthChange
@@ -69,8 +69,6 @@
damage:
types:
Poison: 0.1
Medicine:
effects:
- !type:ModifyBloodLevel
conditions:
- !type:MetabolizerTypeCondition
@@ -97,7 +95,7 @@
- !type:PlantAdjustHealth
amount: -2
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -148,7 +146,7 @@
boilingPoint: 2862.0
meltingPoint: 1538.0
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.1
effects:
- !type:HealthChange
@@ -158,8 +156,6 @@
damage:
types:
Poison: 0.1
Medicine:
effects:
- !type:ModifyBloodLevel
conditions:
- !type:MetabolizerTypeCondition
@@ -178,7 +174,7 @@
meltingPoint: 180.5
boilingPoint: 1330.0
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.1
effects:
- !type:HealthChange
@@ -205,7 +201,7 @@
meltingPoint: -38.83
boilingPoint: 356.73
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -267,7 +263,7 @@
boilingPoint: 3265.0
meltingPoint: 1414.0
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -296,7 +292,7 @@
boilingPoint: 445.0
meltingPoint: 120.0
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -335,7 +331,7 @@
probability: 0.2
amount: 0.1
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:

View File

@@ -12,7 +12,7 @@
maxOnTileWhitelist:
tags: [ Carpet ]
metabolisms:
Poison:
Bloodstream:
effects:
- !type:PopupMessage
type: Local
@@ -35,7 +35,7 @@
flavor: fiber
color: "#808080"
metabolisms:
Food:
Digestion:
effects:
- !type:SatiateHunger
conditions:
@@ -62,7 +62,7 @@
- !type:CleanTileReaction # Bees are extremely obsessive about cleanliness within what they consider their hive.
cleanCost: 0 # Consume absolutely zero bees. Buzz buzz.
metabolisms:
Poison:
Bloodstream:
effects:
- !type:PopupMessage
type: Local
@@ -163,8 +163,8 @@
flavor: shocking
color: "#FDD023"
metabolisms:
Poison:
metabolismRate : 2.0
Bloodstream:
metabolismRate: 2.0
effects:
- !type:Electrocute
siemensCoefficient: 0.5
@@ -193,7 +193,7 @@
emote: Scream
probability: 0.7
metabolisms:
Poison:
Bloodstream:
metabolismRate : 3.00
effects:
- !type:HealthChange
@@ -248,7 +248,7 @@
effects:
- !type:Extinguish # cold
metabolisms:
Poison:
Bloodstream:
metabolismRate : 0.45
effects:
- !type:HealthChange
@@ -314,7 +314,7 @@
slipData:
requiredSlipSpeed: 3.5 #clown juice gotta slip
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:Emote
emote: Laugh
@@ -335,7 +335,7 @@
flavor: weh
color: "#59b23a"
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.25
effects:
- !type:Emote
@@ -370,7 +370,7 @@
flavor: hew
color: "#a64dc5"
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.25
effects:
- !type:Emote
@@ -405,7 +405,7 @@
flavor: dogfood
color: "#ed9715"
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.2
effects:
- !type:HealthChange
@@ -439,7 +439,7 @@
flavor: cannedtuna
color: "#d8bed8"
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.2
effects:
- !type:HealthChange
@@ -490,7 +490,7 @@
flavor: dogfood
color: "#b87333"
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.2
effects:
- !type:HealthChange

View File

@@ -11,7 +11,7 @@
boilingPoint: -183.0
meltingPoint: -218.4
metabolisms:
Poison:
Bloodstream:
effects:
- !type:Oxygenate
conditions:
@@ -42,7 +42,7 @@
type: [ Vox ]
clear: true
time: 5
Gas:
Respiration:
effects:
- !type:Oxygenate
conditions:
@@ -88,7 +88,7 @@
- !type:FlammableTileReaction
temperatureMultiplier: 1.5
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -97,7 +97,7 @@
- !type:AdjustReagent
reagent: Inaprovaline
amount: -2.0
Gas:
Respiration:
effects:
- !type:HealthChange
ignoreResistances: true
@@ -136,13 +136,13 @@
- !type:Flammable
multiplier: 0.8
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
types:
Radiation: 1.5
Gas:
Respiration:
effects:
- !type:HealthChange
ignoreResistances: true
@@ -165,7 +165,7 @@
flavor: bitter
color: "#66ff33"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:Oxygenate
conditions:
@@ -187,7 +187,7 @@
type: [ Plant ]
inverted: true
factor: -4
Gas:
Respiration:
effects:
- !type:Oxygenate
conditions:
@@ -226,13 +226,13 @@
boilingPoint: -195.8
meltingPoint: -210.0
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
types:
Cold: 0.5 # liquid nitrogen is cold
Gas:
Respiration:
effects:
- !type:Oxygenate
conditions:
@@ -264,13 +264,13 @@
boilingPoint: -88
meltingPoint: -90
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
types:
Poison: 1
Gas:
Respiration:
effects:
- !type:Emote
minScale: 0.2
@@ -342,7 +342,7 @@
boilingPoint: -195.8
meltingPoint: -210.0
metabolisms:
Narcotic:
Bloodstream:
effects:
- !type:HealthChange
ignoreResistances: true
@@ -367,7 +367,7 @@
probability: 0.1
conditions:
minScale: 2
Gas:
Respiration:
effects:
- !type:HealthChange
minScale: 0.5

View File

@@ -9,7 +9,7 @@
flavor: medicine
color: "#081a80"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:ModifyStatusEffect
effectProto: StatusEffectScrambled
@@ -27,7 +27,7 @@
flavor: medicine
color: "#3a1d8a"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -81,7 +81,7 @@
flavor: medicine
color: "#64ffe6"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:AdjustReagent
reagent: Histamine
@@ -107,7 +107,7 @@
flavor: medicine
color: "#2d5708"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:ModifyStatusEffect
effectProto: StatusEffectDrunk
@@ -127,7 +127,7 @@
flavor: medicine
color: "#bd5902"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -145,7 +145,7 @@
flavor: medicine
color: "#ffaa00"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:EvenHealthChange
damage:
@@ -187,7 +187,7 @@
amount: 5
- !type:PlantCryoxadone {}
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:EvenHealthChange
conditions:
@@ -210,7 +210,7 @@
flavor: medicine
color: "#32cd32"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
conditions:
@@ -229,7 +229,7 @@
flavor: medicine
color: "#215263"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -263,7 +263,7 @@
flavor: medicine
color: "#0041a8"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -289,7 +289,7 @@
flavor: medicine
color: "#4da0bd"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -323,7 +323,7 @@
flavor: medicine
color: "#d2fffa"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:AdjustReagent
conditions:
@@ -395,7 +395,7 @@
flavor: medicine
color: "#4cb580"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -428,7 +428,7 @@
flavor: medicine
color: "#422912"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:Vomit
conditions:
@@ -446,7 +446,7 @@
flavor: medicine
color: "#731024"
metabolisms:
Medicine:
Bloodstream:
metabolismRate: 0.1 # Smaller doses stabilize critical people for longer. Gives it a specific usecase as to not be entirely outclassed by dex+
effects:
- !type:HealthChange
@@ -469,7 +469,7 @@
flavor: medicine
color: "#bf3d19"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -504,7 +504,7 @@
flavor: medicine
color: "#ff7db5"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -538,7 +538,7 @@
flavor: medicine
color: "#ff867d"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
probability: 0.3
@@ -589,7 +589,7 @@
- !type:PlantPhalanximine
minScale: 4
metabolisms:
Medicine:
Bloodstream:
metabolismRate: 0.1
effects:
- !type:HealthChange
@@ -624,7 +624,7 @@
flavor: violets
color: "#9423FF"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -652,7 +652,7 @@
flavor: medicine
color: "#86caf7"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:CureZombieInfection
conditions:
@@ -669,7 +669,7 @@
flavor: medicine
color: "#1274b5"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:CureZombieInfection
innoculate: true
@@ -687,7 +687,7 @@
flavor: medicine
color: "#FFE774"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:ModifyBleed
amount: -0.5
@@ -701,7 +701,7 @@
flavor: salty
color: "#0064C8"
metabolisms:
Drink:
Bloodstream:
effects:
- !type:SatiateThirst
factor: 6
@@ -717,7 +717,7 @@
flavor: medicine
color: "#f4dab8"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -736,7 +736,7 @@
- !type:PlantAdjustToxins
amount: -5
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -759,7 +759,7 @@
flavor: medicine
color: "#d49a2f"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -786,7 +786,7 @@
flavor: medicine
color: "#ba7d7d"
metabolisms:
Medicine:
Bloodstream:
effects:
# Medium-large quantities can hurt you instead,
# but still technically stop your bleeding.
@@ -810,7 +810,7 @@
flavor: medicine
color: "#00e5ff"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
conditions:
@@ -836,7 +836,7 @@
flavor: medicine
color: "#2690b5"
metabolisms:
Medicine:
Bloodstream:
effects:
# what the hell, this isn't satiating at all!!
- !type:SatiateHunger
@@ -852,7 +852,7 @@
flavor: medicine
color: "#fcf7f9"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:EvenHealthChange
damage:
@@ -870,7 +870,7 @@
flavor: medicine
color: "#520e30"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:EvenHealthChange
conditions:
@@ -928,7 +928,7 @@
flavor: medicine
color: "#404040"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:EyeDamage
@@ -941,7 +941,7 @@
flavor: magical
color: "#b50ee8"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:MakeSentient
conditions:
@@ -958,7 +958,7 @@
flavor: medicine
color: "#d5d5e4"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:Jitter
- !type:GenericStatusEffect
@@ -988,7 +988,7 @@
flavor: medicine
color: "#b0abaa"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:ModifyStatusEffect
effectProto: StatusEffectDrowsiness
@@ -1014,7 +1014,7 @@
flavor: sweet
color: "#e0a5b9"
metabolisms:
Medicine:
Bloodstream:
metabolismRate: 0.25
effects:
- !type:HealthChange
@@ -1074,7 +1074,7 @@
flavor: syrupy
color: "#283332"
metabolisms:
Medicine:
Bloodstream:
metabolismRate: 0.25
effects:
- !type:HealthChange
@@ -1100,7 +1100,7 @@
flavor: fizzy
color: "#b9bf93"
metabolisms:
Medicine:
Bloodstream:
metabolismRate: 0.25
effects:
- !type:HealthChange
@@ -1126,7 +1126,7 @@
flavor: sour
color: "#ff3636"
metabolisms:
Medicine:
Bloodstream:
metabolismRate: 0.25
effects:
- !type:HealthChange
@@ -1154,7 +1154,7 @@
flavor: holy
color: "#91C3F7"
metabolisms:
Drink:
Digestion:
effects:
- !type:SatiateThirst
factor: 3
@@ -1197,7 +1197,7 @@
flavor: syrupy
color: "#aa4308"
metabolisms:
Medicine:
Bloodstream:
metabolismRate: 0.1 # slow metabolism to not be a godly combat med, its for treating burn victims efficiently
effects:
- !type:HealthChange
@@ -1237,7 +1237,7 @@
flavor: metallic
color: "#8147ff"
metabolisms:
Medicine:
Bloodstream:
metabolismRate: 0.25
effects:
# heals shocks and removes shock chems
@@ -1285,7 +1285,7 @@
color: "#b5e36d"
worksOnTheDead: true
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:ReduceRotting
seconds: 20
@@ -1306,7 +1306,7 @@
color: "#0cbfe9"
worksOnTheDead: true
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:EvenHealthChange
conditions:
@@ -1343,7 +1343,7 @@
amount: 5
- !type:PlantCryoxadone {}
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:EvenHealthChange
conditions:
@@ -1370,7 +1370,7 @@
color: "#89f77f"
worksOnTheDead: true
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:EvenHealthChange
conditions:
@@ -1388,7 +1388,7 @@
flavor: sweet
color: "#A0A0A0"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:PopupMessage
conditions:
@@ -1409,7 +1409,7 @@
flavor: bitter
color: "#07E79E"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:HealthChange
conditions:
@@ -1453,7 +1453,7 @@
flavor: medicine
color: "#baa15d"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:GenericStatusEffect
key: RadiationProtection
@@ -1478,7 +1478,7 @@
flavor: medicine
color: "#27870a"
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:Emote
emote: Yawn
@@ -1532,7 +1532,7 @@
flavor: medicine
color: "#d0e21b"
metabolisms:
Medicine:
Bloodstream:
effects: # One day this could be useful for treating blood clots, if we get those
- !type:ModifyStatusEffect
effectProto: StatusEffectAnticoagulant

View File

@@ -10,7 +10,7 @@
boilingPoint: 212.0 # Dexosyephedrine vape when?
meltingPoint: 170.0
metabolisms:
Poison:
Bloodstream:
# Main effects
effects:
- !type:HealthChange
@@ -28,8 +28,7 @@
types:
Poison: 3 # this is added to the base damage of the meth.
Asphyxiation: 2
Narcotic:
effects:
# Main effects
- !type:MovementSpeedModifier
walkSpeedModifier: 1.20
@@ -58,8 +57,7 @@
effectProto: StatusEffectDrowsiness
time: 10
type: Remove
Medicine:
effects:
# Side effects
- !type:ResetNarcolepsy
conditions:
@@ -78,7 +76,7 @@
boilingPoint: 255.0
meltingPoint: 36.0
metabolisms:
Narcotic:
Bloodstream:
effects:
# Main effects
- !type:MovementSpeedModifier
@@ -117,8 +115,6 @@
effectProto: StatusEffectDrowsiness
time: 10
type: Remove
Medicine:
effects:
# Side effects
- !type:ResetNarcolepsy
conditions:
@@ -138,7 +134,7 @@
boilingPoint: 212.0
meltingPoint: 170.0
metabolisms:
Narcotic:
Bloodstream:
effects:
# Main effects
- !type:MovementSpeedModifier
@@ -189,8 +185,6 @@
min: 1
reagent: ChloralHydrate
amount: -10
Medicine:
effects:
# Main effects
- !type:ModifyBleed
amount: -1.5
@@ -230,7 +224,7 @@
- !type:PlantAdjustHealth
amount: -1
metabolisms:
Narcotic:
Bloodstream:
effects:
- !type:ModifyStatusEffect
effectProto: StatusEffectSeeingRainbow
@@ -260,7 +254,7 @@
flavor: bitter
color: "#215263"
metabolisms:
Narcotic:
Bloodstream:
effects:
- !type:MovementSpeedModifier
walkSpeedModifier: 0.65
@@ -287,7 +281,7 @@
flavor: bitter
color: "#63806e"
metabolisms:
Narcotic:
Bloodstream:
effects:
- !type:ModifyStatusEffect
effectProto: StatusEffectSeeingRainbow
@@ -303,7 +297,7 @@
flavor: bitter
color: "#ffff00"
metabolisms:
Narcotic:
Bloodstream:
effects:
- !type:ModifyStatusEffect
effectProto: StatusEffectSeeingRainbow
@@ -322,7 +316,7 @@
boilingPoint: 444.0
meltingPoint: 128.0
metabolisms:
Narcotic:
Bloodstream:
effects: # It would be nice to have speech slurred or mumbly, but accents are a bit iffy atm. Same for distortion effects.
- !type:MovementSpeedModifier
walkSpeedModifier: 0.65
@@ -347,7 +341,7 @@
boilingPoint: 255.0
meltingPoint: 36.0
metabolisms:
Narcotic:
Bloodstream:
effects:
- !type:GenericStatusEffect
key: Muted
@@ -367,7 +361,7 @@
boilingPoint: 255.0
meltingPoint: 36.0
metabolisms:
Narcotic:
Bloodstream:
effects:
- !type:PopupMessage
type: Local
@@ -415,7 +409,7 @@
boilingPoint: 255.0
meltingPoint: 36.0
metabolisms:
Narcotic:
Bloodstream:
effects:
- !type:PopupMessage
type: Local
@@ -472,7 +466,7 @@
flavor: paintthinner
color: "#EE35FF"
metabolisms:
Narcotic:
Bloodstream:
effects:
- !type:Emote
emote: Laugh

View File

@@ -28,7 +28,7 @@
- !type:FlammableTileReaction
temperatureMultiplier: 2
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -55,7 +55,7 @@
- !type:Flammable
multiplier: 0.4
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -76,7 +76,7 @@
flavor: bitter
color: "#D4872A"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -108,7 +108,7 @@
tileReactions:
- !type:PryTileReaction
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -165,15 +165,13 @@
tileReactions:
- !type:FlammableTileReaction {}
metabolisms:
Food:
Bloodstream:
effects:
- !type:SatiateThirst
factor: 1
conditions:
- !type:MetabolizerTypeCondition
type: [Vox]
Poison:
effects:
- !type:HealthChange
conditions:
- !type:MetabolizerTypeCondition

View File

@@ -13,7 +13,7 @@
- !type:PlantAdjustHealth
amount: -5
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -36,7 +36,7 @@
- !type:PlantAdjustHealth
amount: -5
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -59,7 +59,7 @@
allowedDepartments:
- Medical
metabolisms:
Poison:
Bloodstream:
effects:
- !type:Emote
emote: Yawn
@@ -90,7 +90,7 @@
color: "#acc91a"
physicalDesc: reagent-physical-desc-putrid
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -113,7 +113,7 @@
recognizable: true
physicalDesc: reagent-physical-desc-fuzzy
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -151,7 +151,7 @@
emote: Scream
probability: 0.3
metabolisms:
Poison:
Bloodstream:
metabolismRate : 3.00 # High damage, high metabolism rate. You need a lot of units to crit. Simulates acid burning through you fast.
effects:
- !type:HealthChange
@@ -176,7 +176,7 @@
color: "#48b3b8"
physicalDesc: reagent-physical-desc-ferrous
metabolisms:
Drink:
Bloodstream:
effects:
- !type:SatiateThirst
factor: -1.5
@@ -211,7 +211,7 @@
emote: Scream
probability: 0.2
metabolisms:
Poison:
Bloodstream:
metabolismRate: 3.00 # High damage, high metabolism rate. You need a lot of units to crit. Simulates acid burning through you fast.
effects:
- !type:HealthChange
@@ -260,7 +260,7 @@
emote: Scream
probability: 0.1
metabolisms:
Poison:
Bloodstream:
metabolismRate: 3.00 # Okay damage, high metabolism rate. You need a lot of units to crit. Simulates acid burning through you fast.
effects:
- !type:HealthChange
@@ -287,13 +287,13 @@
- Botanist
flavor: bitter
color: "#00ff5f"
boilingPoint: 340282300000000000000000000000000000000 # Ethidium bromide, which doesn't boil.
boilingPoint: 340282300 # Ethidium bromide, which doesn't boil.
meltingPoint: 261.0
plantMetabolism:
- !type:PlantAdjustMutationLevel
amount: 1
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -309,7 +309,7 @@
contrabandSeverity: Major
color: "#5f959c"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -328,7 +328,7 @@
contrabandSeverity: Syndicate
color: "#6b0007"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -347,7 +347,7 @@
- !type:PlantAdjustToxins
amount: 10
metabolisms:
Poison:
Bloodstream:
effects:
- !type:ModifyStatusEffect
effectProto: StatusEffectSeeingRainbow
@@ -363,7 +363,7 @@
physicalDesc: reagent-physical-desc-abrasive
color: "#FA6464"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
probability: 0.1
@@ -406,7 +406,7 @@
meltingPoint: 351
boilingPoint: 554 # I'm not a chemist, but it boils at 295, lower than melting point, idk how it works so I gave it higher value
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.05
effects:
- !type:HealthChange
@@ -431,7 +431,7 @@
contrabandSeverity: Major
color: "#D6CE7B"
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.2
effects:
- !type:HealthChange
@@ -448,7 +448,7 @@
flavor: bitter
color: "#000000"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
damage:
@@ -466,7 +466,7 @@
color: "#7e916e"
worksOnTheDead: true
metabolisms:
Medicine:
Bloodstream:
effects:
- !type:CauseZombieInfection
conditions:
@@ -483,7 +483,7 @@
flavor: bitter
color: "#FFFFE5"
metabolisms:
Food:
Digestion:
effects:
- !type:PopupMessage
conditions:
@@ -537,7 +537,7 @@
flavor: bitter
color: "#F2E9D2"
metabolisms:
Poison:
Digestion:
metabolismRate: 0.05
effects:
- !type:HealthChange
@@ -562,7 +562,7 @@
- Medical
color: "#AAAAAA"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:GenericStatusEffect
key: Pacified
@@ -578,7 +578,7 @@
flavor: bitter
color: "#F2E9D2"
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.05
effects:
- !type:Emote
@@ -608,7 +608,7 @@
contrabandSeverity: Major
color: "#5C6274"
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.03 # Effectively once every 30 seconds.
effects:
- !type:HealthChange
@@ -625,7 +625,7 @@
contrabandSeverity: Major
color: "#EBFF8E"
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.2
effects:
- !type:HealthChange
@@ -648,7 +648,7 @@
- !type:PlantAdjustToxins
amount: 10
metabolisms:
Poison:
Bloodstream:
effects:
- !type:Jitter
conditions:
@@ -673,8 +673,8 @@
flavor: shocking
color: "#FDD023"
metabolisms:
Poison:
metabolismRate : 2.0
Bloodstream:
metabolismRate: 2.0
effects:
- !type:Electrocute
electrocuteTime: 1
@@ -691,7 +691,7 @@
flavor: mothballs #why does weightloss juice taste like mothballs
color: "#F0FFF0"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:HealthChange
conditions:
@@ -714,7 +714,7 @@
color: "#00b408"
physicalDesc: reagent-physical-desc-nondescript
metabolisms:
Poison:
Bloodstream:
metabolismRate: 0.2 # Slower metabolism so it can build up over time for slowdown
effects:
- !type:HealthChange
@@ -754,7 +754,7 @@
flavor: trashy
physicalDesc: reagent-physical-desc-nondescript
metabolisms:
Food:
Digestion:
effects:
- !type:SatiateHunger
factor: 1
@@ -772,7 +772,7 @@
flavor: sharp
color: "#96424f"
metabolisms:
Poison:
Bloodstream:
effects:
- !type:ModifyStatusEffect
effectProto: StatusEffectHemorrhage