/// From which solution will this metabolizer attempt to metabolize chemicals
/// </summary>
[DataField("solution")]
- public string SolutionName = BloodstreamComponent.DefaultChemicalsSolutionName;
+ public string SolutionName = BloodstreamComponent.DefaultBloodSolutionName;
/// <summary>
/// Does this component use a solution on it's parent entity (the body) or itself
private void OnComponentInit(Entity<BloodstreamComponent> entity, ref ComponentInit args)
{
if (!SolutionContainer.EnsureSolution(entity.Owner,
- entity.Comp.ChemicalSolutionName,
- out var chemicalSolution) ||
- !SolutionContainer.EnsureSolution(entity.Owner,
entity.Comp.BloodSolutionName,
out var bloodSolution) ||
!SolutionContainer.EnsureSolution(entity.Owner,
out var tempSolution))
return;
- chemicalSolution.MaxVolume = entity.Comp.ChemicalMaxVolume;
- bloodSolution.MaxVolume = entity.Comp.BloodMaxVolume;
+ bloodSolution.MaxVolume = entity.Comp.BloodReferenceSolution.Volume * entity.Comp.MaxVolumeModifier;
tempSolution.MaxVolume = entity.Comp.BleedPuddleThreshold * 4; // give some leeway, for chemstream as well
// Fill blood solution with BLOOD
// The DNA string might not be initialized yet, but the reagent data gets updated in the GenerateDnaEvent subscription
- var solution = entity.Comp.BloodReagents.Clone();
- solution.ScaleTo(entity.Comp.BloodMaxVolume - bloodSolution.Volume);
+ var solution = entity.Comp.BloodReferenceSolution.Clone();
+ solution.ScaleTo(entity.Comp.BloodReferenceSolution.Volume - bloodSolution.Volume);
solution.SetReagentData(GetEntityBloodData(entity.Owner));
bloodSolution.AddSolution(solution, PrototypeManager);
}
+using System.Linq;
using Content.Server.Body.Components;
using Content.Shared.Body.Events;
using Content.Shared.Body.Organ;
using Content.Shared.EntityEffects.Effects.Body;
using Content.Shared.EntityEffects.Effects.Solution;
using Content.Shared.FixedPoint;
-using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Random.Helpers;
using Robust.Shared.Collections;
return;
}
+ // Copy the solution do not edit the original solution list
+ var list = solution.Contents.ToList();
+
+ // Collecting blood reagent for filtering
+ var bloodList = new List<string>();
+ var ev = new MetabolismExclusionEvent(bloodList);
+ RaiseLocalEvent(solutionEntityUid.Value, ref ev);
+
// randomize the reagent list so we don't have any weird quirks
// like alphabetical order or insertion order mattering for processing
- var list = solution.Contents.ToArray();
_random.Shuffle(list);
+ bool isDead = _mobStateSystem.IsDead(solutionEntityUid.Value);
+
int reagents = 0;
foreach (var (reagent, quantity) in list)
{
if (!_prototypeManager.TryIndex<ReagentPrototype>(reagent.Prototype, out var proto))
continue;
+ // Skip blood reagents
+ if (bloodList.Contains(reagent.Prototype))
+ continue;
+
var mostToRemove = FixedPoint2.Zero;
if (proto.Metabolisms 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 (TryComp<MobStateComponent>(solutionEntityUid.Value, out var state))
- {
- if (!proto.WorksOnTheDead && _mobStateSystem.IsDead(solutionEntityUid.Value, state))
- continue;
- }
+ if (isDead && !proto.WorksOnTheDead)
+ continue;
var actualEntity = ent.Comp2?.Body ?? solutionEntityUid.Value;
// Take our portion of the adjusted solution for this target
var individualInjection = solutionToInject.SplitSolution(volumePerBloodstream);
// Inject our portion into the target's bloodstream
- if (_bloodstream.TryAddToChemicals(targetBloodstream.AsNullable(), individualInjection))
+ if (_bloodstream.TryAddToBloodstream(targetBloodstream.AsNullable(), individualInjection))
anySuccess = true;
}
if (!TryComp<BloodstreamComponent>(entity, out var bloodstream))
return;
- if (!_solutionContainerSystem.ResolveSolution(entity, bloodstream.ChemicalSolutionName, ref bloodstream.ChemicalSolution, out var chemSolution) || chemSolution.AvailableVolume <= 0)
+ if (!_solutionContainerSystem.ResolveSolution(entity, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution) || bloodSolution.AvailableVolume <= 0)
return;
var blockIngestion = _internals.AreInternalsWorking(entity);
var cloneSolution = solution.Clone();
var availableTransfer = FixedPoint2.Min(cloneSolution.Volume, component.TransferRate);
- var transferAmount = FixedPoint2.Min(availableTransfer, chemSolution.AvailableVolume);
+ var transferAmount = FixedPoint2.Min(availableTransfer, bloodSolution.AvailableVolume);
var transferSolution = cloneSolution.SplitSolution(transferAmount);
foreach (var reagentQuantity in transferSolution.Contents.ToArray())
if (blockIngestion)
return;
- if (_blood.TryAddToChemicals((entity, bloodstream), transferSolution))
+ if (_blood.TryAddToBloodstream((entity, bloodstream), transferSolution))
{
// Log solution addition by smoke
_logger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(entity):target} ingested smoke {SharedSolutionContainerSystem.ToPrettyString(transferSolution)}");
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Timing;
+using Content.Server.Body.Systems;
namespace Content.Server.Medical;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
+ [Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
public override void Initialize()
{
_solutionContainerSystem.ResolveSolution(target, bloodstream.BloodSolutionName,
ref bloodstream.BloodSolution, out var bloodSolution))
{
- bloodAmount = bloodSolution.FillFraction;
+ bloodAmount = _bloodstreamSystem.GetBloodLevel(target);
bleeding = bloodstream.BleedAmount > 0;
}
}
_reactiveSystem.DoEntityReaction(containerManager.Owner, inhaledSolution, ReactionMethod.Ingestion);
- _bloodstreamSystem.TryAddToChemicals((containerManager.Owner, bloodstream), inhaledSolution);
+ _bloodstreamSystem.TryAddToBloodstream((containerManager.Owner, bloodstream), inhaledSolution);
}
_timer -= UpdateTimer;
zombiecomp.BeforeZombifiedSkinColor = huApComp.SkinColor;
zombiecomp.BeforeZombifiedEyeColor = huApComp.EyeColor;
zombiecomp.BeforeZombifiedCustomBaseLayers = new(huApComp.CustomBaseLayers);
- if (TryComp<BloodstreamComponent>(target, out var stream) && stream.BloodReagents is { } reagents)
+ if (TryComp<BloodstreamComponent>(target, out var stream) && stream.BloodReferenceSolution is { } reagents)
zombiecomp.BeforeZombifiedBloodReagents = reagents.Clone();
_humanoidAppearance.SetSkinColor(target, zombiecomp.SkinColor, verify: false, humanoid: huApComp);
[Access(typeof(SharedBloodstreamSystem))]
public sealed partial class BloodstreamComponent : Component
{
- public const string DefaultChemicalsSolutionName = "chemicals";
public const string DefaultBloodSolutionName = "bloodstream";
public const string DefaultBloodTemporarySolutionName = "bloodstreamTemporary";
// TODO probably damage bleed thresholds.
/// <summary>
- /// Max volume of internal chemical solution storage
+ /// Modifier applied to <see cref="BloodReferenceSolution.Volume"/> to determine maximum volume for bloodstream.
/// </summary>
[DataField]
- public FixedPoint2 ChemicalMaxVolume = FixedPoint2.New(250);
+ public float MaxVolumeModifier = 2f;
/// <summary>
- /// Max volume of internal blood storage,
- /// and starting level of blood.
- /// </summary>
- [DataField]
- public FixedPoint2 BloodMaxVolume = FixedPoint2.New(300);
-
- /// <summary>
- /// Which reagents are considered this entities 'blood'?
+ /// Defines which reagents are considered as 'blood' and how much of it is normal.
/// </summary>
/// <remarks>
/// Slime-people might use slime as their blood or something like that.
/// </remarks>
[DataField, AutoNetworkedField]
- public Solution BloodReagents = new([new("Blood", 1)]);
+ public Solution BloodReferenceSolution = new([new("Blood", 300)]);
/// <summary>
/// Name/Key that <see cref="BloodSolution"/> is indexed by.
[DataField]
public string BloodSolutionName = DefaultBloodSolutionName;
- /// <summary>
- /// Name/Key that <see cref="ChemicalSolution"/> is indexed by.
- /// </summary>
- [DataField]
- public string ChemicalSolutionName = DefaultChemicalsSolutionName;
-
/// <summary>
/// Name/Key that <see cref="TemporarySolution"/> is indexed by.
/// </summary>
[ViewVariables]
public Entity<SolutionComponent>? BloodSolution;
- /// <summary>
- /// Internal solution for reagent storage
- /// </summary>
- [ViewVariables]
- public Entity<SolutionComponent>? ChemicalSolution;
-
/// <summary>
/// Temporary blood solution.
/// When blood is lost, it goes to this solution, and when this
/// What solution should this stomach push reagents into, on the body?
/// </summary>
[DataField]
- public string BodySolutionName = "chemicals";
+ public string BodySolutionName = BloodstreamComponent.DefaultBloodSolutionName;
/// <summary>
/// Time between reagents being ingested and them being
--- /dev/null
+namespace Content.Shared.Body.Events;
+
+/// <summary>
+/// Event called by <see cref="Content.Server.Body.Systems.MetabolizerSystem"/> to get a list of
+/// blood like reagents for metabolism to skip.
+/// </summary>
+[ByRefEvent]
+public readonly record struct MetabolismExclusionEvent(List<string> ReagentList);
\ No newline at end of file
+using System.Linq;
using Content.Shared.Alert;
using Content.Shared.Body.Components;
using Content.Shared.Body.Events;
SubscribeLocalEvent<BloodstreamComponent, BeingGibbedEvent>(OnBeingGibbed);
SubscribeLocalEvent<BloodstreamComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
SubscribeLocalEvent<BloodstreamComponent, RejuvenateEvent>(OnRejuvenate);
+ SubscribeLocalEvent<BloodstreamComponent, MetabolismExclusionEvent>(OnMetabolismExclusion);
}
public override void Update(float frameTime)
if (!SolutionContainer.ResolveSolution(uid, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution))
continue;
- // Adds blood to their blood level if it is below the maximum; Blood regeneration. Must be alive.
- if (bloodSolution.Volume < bloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid))
- {
- TryModifyBloodLevel((uid, bloodstream), bloodstream.BloodRefreshAmount);
- }
+ // Blood level regulation. Must be alive.
+ TryRegulateBloodLevel(uid, bloodstream.BloodRefreshAmount);
// Removes blood from the bloodstream based on bleed amount (bleed rate)
// as well as stop their bleeding to a certain extent.
RaiseLocalEvent(uid, ref ev);
// Blood is removed from the bloodstream at a 1-1 rate with the bleed amount
- TryModifyBloodLevel((uid, bloodstream), -ev.BleedAmount);
+ TryBleedOut((uid, bloodstream), ev.BleedAmount);
// Bleed rate is reduced by the bleed reduction amount in the bloodstream component.
TryModifyBleedAmount((uid, bloodstream), -ev.BleedReductionAmount);
}
// deal bloodloss damage if their blood level is below a threshold.
- var bloodPercentage = GetBloodLevelPercentage((uid, bloodstream));
+ var bloodPercentage = GetBloodLevel(uid);
if (bloodPercentage < bloodstream.BloodlossThreshold && !_mobStateSystem.IsDead(uid))
{
// bloodloss damage is based on the base value, and modified by how low your blood level is.
if (args.Entity == entity.Comp.BloodSolution?.Owner)
entity.Comp.BloodSolution = null;
- if (args.Entity == entity.Comp.ChemicalSolution?.Owner)
- entity.Comp.ChemicalSolution = null;
-
if (args.Entity == entity.Comp.TemporarySolution?.Owner)
entity.Comp.TemporarySolution = null;
}
private void OnReactionAttempt(Entity<BloodstreamComponent> ent, ref SolutionRelayEvent<ReactionAttemptEvent> args)
{
if (args.Name != ent.Comp.BloodSolutionName
- && args.Name != ent.Comp.ChemicalSolutionName
&& args.Name != ent.Comp.BloodTemporarySolutionName)
{
return;
var prob = Math.Clamp(totalFloat / 25, 0, 1);
if (totalFloat > 0 && rand.Prob(prob))
{
- TryModifyBloodLevel(ent.AsNullable(), -total / 5);
+ TryBleedOut(ent.AsNullable(), total / 5);
_audio.PlayPredicted(ent.Comp.InstantBloodSound, ent, args.Origin);
}
}
// If the mob's blood level is below the damage threshhold, the pale message is added.
- if (GetBloodLevelPercentage(ent.AsNullable()) < ent.Comp.BloodlossThreshold)
+ if (GetBloodLevel(ent.AsNullable()) < ent.Comp.BloodlossThreshold)
{
args.Message.PushNewline();
args.Message.AddMarkupOrThrow(Loc.GetString("bloodstream-component-looks-pale", ("target", ent.Owner)));
{
TryModifyBleedAmount(ent.AsNullable(), -ent.Comp.BleedAmount);
- if (SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution, out var bloodSolution))
- TryModifyBloodLevel(ent.AsNullable(), bloodSolution.AvailableVolume);
+ if (SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution))
+ {
+ SolutionContainer.RemoveAllSolution(ent.Comp.BloodSolution.Value);
+ TryModifyBloodLevel(ent.AsNullable(), ent.Comp.BloodReferenceSolution.Volume);
+ }
+ }
- if (SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.ChemicalSolutionName, ref ent.Comp.ChemicalSolution))
- SolutionContainer.RemoveAllSolution(ent.Comp.ChemicalSolution.Value);
+ private void OnMetabolismExclusion(Entity<BloodstreamComponent> ent, ref MetabolismExclusionEvent args)
+ {
+ // Adding all blood reagents for filtering blood in metabolizer
+ foreach (var (reagentId, _) in ent.Comp.BloodReferenceSolution)
+ {
+ args.ReagentList.Add(reagentId.Prototype);
+ }
}
/// <summary>
- /// Returns the current blood level as a percentage (between 0 and 1).
+ /// This returns the minimum amount of *usable* blood.
+ /// For multi reagent bloodstreams, if you have 100 of Reagent Y need 100, and 50 of Reagent X and need 100,
+ /// this will return 0.5f
/// </summary>
- public float GetBloodLevelPercentage(Entity<BloodstreamComponent?> ent)
+ /// <returns>Returns the current blood level as a value from 0 to <see cref="BloodstreamComponent.MaxVolumeModifier"/></returns>
+ public float GetBloodLevel(Entity<BloodstreamComponent?> entity)
{
- if (!Resolve(ent, ref ent.Comp)
- || !SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution, out var bloodSolution))
+ if (!Resolve(entity, ref entity.Comp)
+ || !SolutionContainer.ResolveSolution(entity.Owner, entity.Comp.BloodSolutionName, ref entity.Comp.BloodSolution, out var bloodSolution)
+ || entity.Comp.BloodReferenceSolution.Volume == 0)
{
return 0.0f;
}
- return bloodSolution.FillFraction;
+ var totalBloodLevel = FixedPoint2.New(entity.Comp.MaxVolumeModifier); // Can't go above max volume factor...
+
+ foreach (var (reagentId, quantity) in entity.Comp.BloodReferenceSolution.Contents)
+ {
+ // Ideally we use a different calculation for blood pressure, this just defines how much *usable* blood you have!
+ totalBloodLevel = FixedPoint2.Min(totalBloodLevel, bloodSolution.GetTotalPrototypeQuantity(reagentId.Prototype) / quantity);
+ }
+
+ return (float)totalBloodLevel;
}
/// <summary>
/// <summary>
/// Attempt to transfer a provided solution to internal solution.
/// </summary>
- public bool TryAddToChemicals(Entity<BloodstreamComponent?> ent, Solution solution)
+ public bool TryAddToBloodstream(Entity<BloodstreamComponent?> ent, Solution solution)
{
if (!Resolve(ent, ref ent.Comp, logMissing: false)
- || !SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.ChemicalSolutionName, ref ent.Comp.ChemicalSolution))
+ || !SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution))
return false;
- if (SolutionContainer.TryAddSolution(ent.Comp.ChemicalSolution.Value, solution))
+ if (SolutionContainer.TryAddSolution(ent.Comp.BloodSolution.Value, solution))
return true;
return false;
}
/// <summary>
- /// Removes a certain amount of all reagents except of a single excluded one from the bloodstream.
+ /// Removes a certain amount of all reagents except of a single excluded one from the bloodstream and blood itself.
/// </summary>
- public bool FlushChemicals(Entity<BloodstreamComponent?> ent, ProtoId<ReagentPrototype>? excludedReagentID, FixedPoint2 quantity)
+ /// <returns>
+ /// Solution of removed chemicals or null if none were removed.
+ /// </returns>
+ public Solution? FlushChemicals(Entity<BloodstreamComponent?> ent, FixedPoint2 quantity, ProtoId<ReagentPrototype>? excludedReagent = null )
{
if (!Resolve(ent, ref ent.Comp, logMissing: false)
- || !SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.ChemicalSolutionName, ref ent.Comp.ChemicalSolution, out var chemSolution))
+ || !SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution, out var bloodSolution))
+ return null;
+
+ var flushedSolution = new Solution();
+
+ for (var i = bloodSolution.Contents.Count - 1; i >= 0; i--)
+ {
+ var (reagentId, _) = bloodSolution.Contents[i];
+ if (ent.Comp.BloodReferenceSolution.ContainsPrototype(reagentId.Prototype) || reagentId.Prototype == excludedReagent)
+ continue;
+
+ var reagentFlushAmount = SolutionContainer.RemoveReagent(ent.Comp.BloodSolution.Value, reagentId, quantity);
+ flushedSolution.AddReagent(reagentId, reagentFlushAmount);
+ }
+
+ return flushedSolution.Volume == 0 ? null : flushedSolution;
+ }
+
+ /// <summary>
+ /// A simple helper that tries to move blood volume up or down by a specified amount.
+ /// Blood will not go over normal volume for this entity's bloodstream.
+ /// </summary>
+ public bool TryModifyBloodLevel(Entity<BloodstreamComponent?> ent, FixedPoint2 amount)
+ {
+ var reference = 1f;
+
+ if (amount < 0)
+ {
+ reference = 0f;
+ amount *= -1;
+ }
+
+ return TryRegulateBloodLevel(ent, amount, reference);
+ }
+
+ /// <summary>
+ /// Attempts to bring an entity's blood level to a modified equilibrium volume.
+ /// </summary>
+ /// <param name="ent">Entity whose bloodstream we're modifying.</param>
+ /// <param name="amount">The absolute maximum amount of blood we can add or remove.</param>
+ /// <param name="referenceFactor">The modifier for an entity's blood equilibrium, try to hit an entity's default blood volume multiplied by this value.</param>
+ /// <remarks>This CANNOT go above maximum blood volume!</remarks>
+ /// <returns>False if we were unable to regulate blood level. This may return true even if blood level doesn't change!</returns>
+ public bool TryRegulateBloodLevel(Entity<BloodstreamComponent?> ent, FixedPoint2 amount, float referenceFactor = 1f)
+ {
+ if (!Resolve(ent, ref ent.Comp, logMissing: false)
+ || !SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution, out var bloodSolution)
+ || amount == 0)
return false;
- for (var i = chemSolution.Contents.Count - 1; i >= 0; i--)
+ referenceFactor = Math.Clamp(referenceFactor, 0f, ent.Comp.MaxVolumeModifier);
+
+ foreach (var (referenceReagent, referenceQuantity) in ent.Comp.BloodReferenceSolution)
{
- var (reagentId, _) = chemSolution.Contents[i];
- if (reagentId.Prototype != excludedReagentID)
+ var error = referenceQuantity * referenceFactor - bloodSolution.GetTotalPrototypeQuantity(referenceReagent.Prototype);
+ var adjustedAmount = amount * referenceQuantity / ent.Comp.BloodReferenceSolution.Volume;
+
+ if (error > 0)
{
- SolutionContainer.RemoveReagent(ent.Comp.ChemicalSolution.Value, reagentId, quantity);
+ error = FixedPoint2.Min(error, adjustedAmount);
+ var reagentToAdd = new ReagentId(referenceReagent.Prototype, GetEntityBloodData(ent));
+ bloodSolution.AddReagent(reagentToAdd, error);
+ }
+ else if (error < 0)
+ {
+ // invert the error since we're removing reagents...
+ error = FixedPoint2.Min( -error, adjustedAmount);
+ bloodSolution.RemoveReagent(referenceReagent, error);
}
}
}
/// <summary>
- /// Attempts to modify the blood level of this entity directly.
+ /// Removes blood by spilling out the bloodstream.
/// </summary>
- public bool TryModifyBloodLevel(Entity<BloodstreamComponent?> ent, FixedPoint2 amount)
+ public bool TryBleedOut(Entity<BloodstreamComponent?> ent, FixedPoint2 amount)
{
if (!Resolve(ent, ref ent.Comp, logMissing: false)
- || !SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution, out var bloodSolution))
- return false;
-
- if (amount >= 0)
+ || !SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution)
+ || amount <= 0)
{
- var min = FixedPoint2.Min(bloodSolution.AvailableVolume, amount);
- var solution = ent.Comp.BloodReagents.Clone();
- solution.ScaleTo(min);
- solution.SetReagentData(GetEntityBloodData(ent));
- SolutionContainer.AddSolution(ent.Comp.BloodSolution.Value, solution);
- return min == amount;
+ return false;
}
- // Removal is more involved,
- // since we also wanna handle moving it to the temporary solution
- // and then spilling it if necessary.
- var newSol = SolutionContainer.SplitSolution(ent.Comp.BloodSolution.Value, -amount);
+ var leakedBlood = SolutionContainer.SplitSolution(ent.Comp.BloodSolution.Value, amount);
if (!SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodTemporarySolutionName, ref ent.Comp.TemporarySolution, out var tempSolution))
return true;
- tempSolution.AddSolution(newSol, PrototypeManager);
+ tempSolution.AddSolution(leakedBlood, PrototypeManager);
if (tempSolution.Volume > ent.Comp.BleedPuddleThreshold)
{
- // Pass some of the chemstream into the spilled blood.
- if (SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.ChemicalSolutionName, ref ent.Comp.ChemicalSolution))
- {
- var temp = SolutionContainer.SplitSolution(ent.Comp.ChemicalSolution.Value, tempSolution.Volume / 10);
- tempSolution.AddSolution(temp, PrototypeManager);
- }
-
_puddle.TrySpillAt(ent.Owner, tempSolution, out _, sound: false);
tempSolution.RemoveAllSolution();
SolutionContainer.RemoveAllSolution(ent.Comp.BloodSolution.Value);
}
- if (SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.ChemicalSolutionName, ref ent.Comp.ChemicalSolution, out var chemSolution))
- {
- tempSol.MaxVolume += chemSolution.MaxVolume;
- tempSol.AddSolution(chemSolution, PrototypeManager);
- SolutionContainer.RemoveAllSolution(ent.Comp.ChemicalSolution.Value);
- }
-
if (SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodTemporarySolutionName, ref ent.Comp.TemporarySolution, out var tempSolution))
{
tempSol.MaxVolume += tempSolution.MaxVolume;
if (!SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution, out var bloodSolution))
{
- ent.Comp.BloodReagents = reagents.Clone();
- DirtyField(ent, ent.Comp, nameof(BloodstreamComponent.BloodReagents));
+ ent.Comp.BloodReferenceSolution = reagents.Clone();
+ DirtyField(ent, ent.Comp, nameof(BloodstreamComponent.BloodReferenceSolution));
return;
}
var currentVolume = FixedPoint2.Zero;
- foreach (var reagent in ent.Comp.BloodReagents)
+ foreach (var reagent in ent.Comp.BloodReferenceSolution)
{
currentVolume += bloodSolution.RemoveReagent(reagent.Reagent, quantity: bloodSolution.Volume, ignoreReagentData: true);
}
- ent.Comp.BloodReagents = reagents.Clone();
- DirtyField(ent, ent.Comp, nameof(BloodstreamComponent.BloodReagents));
+ ent.Comp.BloodReferenceSolution = reagents.Clone();
+ DirtyField(ent, ent.Comp, nameof(BloodstreamComponent.BloodReferenceSolution));
if (currentVolume == FixedPoint2.Zero)
return;
- var solution = ent.Comp.BloodReagents.Clone();
+ var solution = ent.Comp.BloodReferenceSolution.Clone();
solution.ScaleSolution(currentVolume / solution.Volume);
solution.SetReagentData(GetEntityBloodData(ent));
SolutionContainer.AddSolution(ent.Comp.BloodSolution.Value, solution);
EntityUid user)
{
// Get transfer amount. May be smaller than _transferAmount if not enough room
- if (!SolutionContainer.ResolveSolution(target.Owner, target.Comp.ChemicalSolutionName,
- ref target.Comp.ChemicalSolution, out var chemSolution))
+ if (!SolutionContainer.ResolveSolution(target.Owner, target.Comp.BloodSolutionName,
+ ref target.Comp.BloodSolution, out var bloodSolution))
{
LocId msg = target.Owner == user ? "injector-component-cannot-inject-message-self" : "injector-component-cannot-inject-message";
_popup.PopupClient(
return false;
}
- var realTransferAmount = FixedPoint2.Min(injector.Comp.CurrentTransferAmount, chemSolution.AvailableVolume);
+ var realTransferAmount = FixedPoint2.Min(injector.Comp.CurrentTransferAmount, bloodSolution.AvailableVolume);
if (realTransferAmount <= 0)
{
LocId msg = target.Owner == user ? "injector-component-cannot-inject-message-self" : "injector-component-cannot-inject-message";
}
// Move units from attackSolution to targetSolution
- var removedSolution = SolutionContainer.SplitSolution(target.Comp.ChemicalSolution.Value, realTransferAmount);
+ var removedSolution = SolutionContainer.SplitSolution(target.Comp.BloodSolution.Value, realTransferAmount);
- _blood.TryAddToChemicals(target.AsNullable(), removedSolution);
+ _blood.TryAddToBloodstream(target.AsNullable(), removedSolution);
_reactiveSystem.DoEntityReaction(target, removedSolution, ReactionMethod.Injection);
private void DrawFromBlood(Entity<InjectorComponent> injector, Entity<BloodstreamComponent> target,
Entity<SolutionComponent> injectorSolution, FixedPoint2 transferAmount, EntityUid user)
{
- var drawAmount = (float)transferAmount;
-
- if (SolutionContainer.ResolveSolution(target.Owner, target.Comp.ChemicalSolutionName,
- ref target.Comp.ChemicalSolution))
- {
- var chemTemp = SolutionContainer.SplitSolution(target.Comp.ChemicalSolution.Value, drawAmount * 0.15f);
- SolutionContainer.TryAddSolution(injectorSolution, chemTemp);
- drawAmount -= (float)chemTemp.Volume;
- }
-
if (SolutionContainer.ResolveSolution(target.Owner, target.Comp.BloodSolutionName,
ref target.Comp.BloodSolution))
{
- var bloodTemp = SolutionContainer.SplitSolution(target.Comp.BloodSolution.Value, drawAmount);
+ var bloodTemp = SolutionContainer.SplitSolution(target.Comp.BloodSolution.Value, transferAmount);
SolutionContainer.TryAddSolution(injectorSolution, bloodTemp);
}
// Grant ichor if the devoured thing meets the dragon's food preference
if (args.Args.Target != null && _whitelistSystem.IsWhitelistPassOrNull(ent.Comp.FoodPreferenceWhitelist, (EntityUid)args.Args.Target))
{
- _bloodstreamSystem.TryAddToChemicals(ent.Owner, ichorInjection);
+ _bloodstreamSystem.TryAddToBloodstream(ent.Owner, ichorInjection);
}
// If the devoured thing meets the stomach whitelist criteria, add it to the stomach
{
var scale = args.Scale * args.Effect.CleanseRate;
- _bloodstream.FlushChemicals((entity, entity), args.Effect.Excluded, scale);
+ _bloodstream.FlushChemicals((entity, entity), scale, args.Effect.Excluded);
}
}
&& _bloodstreamQuery.TryComp(patient, out var bloodstream))
{
var solutionToInject = _solutionContainer.SplitSolution(containerSolution.Value, cryoPod.BeakerTransferAmount);
- _bloodstream.TryAddToChemicals((patient.Value, bloodstream), solutionToInject);
+ _bloodstream.TryAddToBloodstream((patient.Value, bloodstream), solutionToInject);
_reactive.DoEntityReaction(patient.Value, solutionToInject, ReactionMethod.Injection);
}
}
// Is ent missing blood that we can restore?
if (healing.Comp.ModifyBloodLevel > 0
&& _solutionContainerSystem.ResolveSolution(target.Owner, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution)
- && bloodSolution.Volume < bloodSolution.MaxVolume)
+ && _bloodstreamSystem.GetBloodLevel((target, bloodstream)) < 1)
{
return true;
}
{
var vomitAmount = solutionSize;
- // Takes 10% of the chemicals removed from the chem stream
- if (_solutionContainer.ResolveSolution(uid, bloodStream.ChemicalSolutionName, ref bloodStream.ChemicalSolution))
+ // Flushes small portion of the chemicals removed from the bloodstream stream
+ if (_solutionContainer.ResolveSolution(uid, bloodStream.BloodSolutionName, ref bloodStream.BloodSolution))
{
- var vomitChemstreamAmount = _solutionContainer.SplitSolution(bloodStream.ChemicalSolution.Value, vomitAmount);
- vomitChemstreamAmount.ScaleSolution(ChemMultiplier);
- solution.AddSolution(vomitChemstreamAmount, _proto);
-
- vomitAmount -= (float)vomitChemstreamAmount.Volume;
+ var vomitChemstreamAmount = _bloodstream.FlushChemicals((uid, bloodStream), vomitAmount);
+
+ if (vomitChemstreamAmount != null)
+ {
+ vomitChemstreamAmount.ScaleSolution(ChemMultiplier);
+ solution.AddSolution(vomitChemstreamAmount, _proto);
+ vomitAmount -= (float)vomitChemstreamAmount.Volume;
+ }
}
// Makes a vomit solution the size of 90% of the chemicals removed from the chemstream
/// </summary>
private void ReactWithEntity(Entity<RootableComponent, BloodstreamComponent> ent, Entity<PuddleComponent> puddleEntity, Solution solution)
{
- if (!_solutionContainer.ResolveSolution(ent.Owner, ent.Comp2.ChemicalSolutionName, ref ent.Comp2.ChemicalSolution, out var chemSolution) || chemSolution.AvailableVolume <= 0)
+ if (!_solutionContainer.ResolveSolution(ent.Owner, ent.Comp2.BloodSolutionName, ref ent.Comp2.BloodSolution, out var bloodSolution) || bloodSolution.AvailableVolume <= 0)
return;
var availableTransfer = FixedPoint2.Min(solution.Volume, ent.Comp1.TransferRate);
- var transferAmount = FixedPoint2.Min(availableTransfer, chemSolution.AvailableVolume);
+ var transferAmount = FixedPoint2.Min(availableTransfer, bloodSolution.AvailableVolume);
var transferSolution = _solutionContainer.SplitSolution(puddleEntity.Comp.Solution!.Value, transferAmount);
_reactive.DoEntityReaction(ent, transferSolution, ReactionMethod.Ingestion);
// Log solution addition by puddle.
- if (_blood.TryAddToChemicals((ent, ent.Comp2), transferSolution))
+ if (_blood.TryAddToBloodstream((ent, ent.Comp2), transferSolution))
_logger.Add(LogType.ForceFeed, LogImpact.Medium, $"{ToPrettyString(ent):target} absorbed puddle {SharedSolutionContainerSystem.ToPrettyString(transferSolution)}");
}
- type: SentienceTarget
flavorKind: station-event-random-sentience-flavor-organic
- type: Bloodstream
- bloodMaxVolume: 50
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 50
- type: ReplacementAccent
accent: mouse
- type: MeleeWeapon
- Bee
- Trash
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: InsectBlood
- Quantity: 1
- bloodMaxVolume: 0.1
+ Quantity: 0.1
- type: MobPrice
price: 50
- type: NPCRetaliation
factions:
- SimpleHostile
- type: Bloodstream
- bloodMaxVolume: 0.1
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 0.1
- type: ZombieImmune
interactSuccessSound:
path: /Audio/Animals/chicken_cluck_happy.ogg
- type: Bloodstream
- bloodMaxVolume: 100
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 100
- type: EggLayer
eggSpawn:
- id: FoodEgg
Dead:
Base: cockroach_dead
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: InsectBlood
- Quantity: 1
- bloodMaxVolume: 20
+ Quantity: 20
- type: Edible
- type: FlavorProfile
flavors:
damageContainer: Biological
damageModifierSet: Moth
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: InsectBlood
- Quantity: 1
+ Quantity: 20
- type: Respirator
damage:
types:
interactSuccessSound:
path: /Audio/Animals/duck_quack_happy.ogg
- type: Bloodstream
- bloodMaxVolume: 100
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 100
- type: EggLayer
eggSpawn:
- id: FoodEgg
tags:
- Trash
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: InsectBlood
- Quantity: 1
- bloodMaxVolume: 0.1
+ Quantity: 0.1
- type: MobPrice
price: 50
- type: Destructible
- type: ReplacementAccent
accent: crab
- type: Bloodstream
- bloodMaxVolume: 50
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: CopperBlood
- Quantity: 1
+ Quantity: 50
- type: Tag
tags:
- VimPilot
interactSuccessSound:
path: /Audio/Animals/goose_honk.ogg
- type: Bloodstream
- bloodMaxVolume: 100
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 100
- type: NpcFactionMember
factions:
- Passive
- id: FoodMeat
amount: 4
- type: Bloodstream
- bloodMaxVolume: 300
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 300
# if you fuck with the gorilla he will harambe you
- type: MeleeWeapon
soundHit:
types:
Piercing: 0
- type: Bloodstream
- bloodMaxVolume: 50
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 50
- type: CanEscapeInventory
- type: MobPrice
price: 50
- type: RadiationSource
intensity: 0.3
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: UnstableMutagen
- Quantity: 1
+ Quantity: 50
- type: SolutionContainerManager
solutions:
food:
interactSuccessSound:
path: /Audio/Animals/lizard_happy.ogg
- type: Bloodstream
- bloodMaxVolume: 150
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 150
- type: Damageable
damageContainer: Biological
damageModifierSet: Scale
interactFailureString: petting-failure-generic
interactSuccessSpawn: EffectHearts
- type: Bloodstream
- bloodMaxVolume: 50
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 50
- type: entity
name: frog
interactSuccessSound:
path: /Audio/Animals/frog_ribbit.ogg
- type: Bloodstream
- bloodMaxVolume: 50
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 50
- type: Tag
tags:
- VimPilot
interactSuccessSound:
path: /Audio/Animals/parrot_raught.ogg
- type: Bloodstream
- bloodMaxVolume: 50
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 50
- type: entity
parent: MobParrotBase
interactFailureString: petting-failure-generic
interactSuccessSpawn: EffectHearts
- type: Bloodstream
- bloodMaxVolume: 50
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 50
- type: Damageable
damageContainer: Biological
damageModifierSet: Scale
- type: Spider
- type: IgnoreSpiderWeb
- type: Bloodstream
- bloodMaxVolume: 150
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: CopperBlood
- Quantity: 1
+ Quantity: 150
- type: Speech
speechVerb: Arachnid
speechSounds: Arachnid
- type: Speech
speechVerb: Cluwne
- type: Bloodstream
- bloodMaxVolume: 150
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Laughter
- Quantity: 1
+ Quantity: 150
- type: entity
name: wizard spider
parent: MobGiantSpider
attributes:
gender: epicene
- type: Bloodstream
- bloodMaxVolume: 100
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 100
- type: MeleeWeapon
angle: 0
animation: WeaponArcBite
attributes:
gender: epicene
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: DemonsBlood
- Quantity: 1
+ Quantity: 150
- type: Damageable
damageContainer: BiologicalMetaphysical
damageModifierSet: Infernal
interactSuccessSound:
path: /Audio/Animals/fox_squeak.ogg
- type: Bloodstream
- bloodMaxVolume: 60
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 60
- type: CanEscapeInventory
baseResistTime: 3
- type: MobPrice
speciesId: cat
templateId: pet
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Sap
- Quantity: 1
- bloodMaxVolume: 60
+ Quantity: 60
- type: DamageStateVisuals
states:
Alive:
- id: FoodMeat
amount: 4
- type: Bloodstream
- bloodMaxVolume: 300
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 300
# Horns though
- type: MeleeWeapon
damage:
- type: ReplacementAccent
accent: xeno
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: FerrochromicAcid
- Quantity: 1
- bloodMaxVolume: 75 #we don't want the map to become pools of blood
+ Quantity: 75 #we don't want the map to become pools of blood
bloodlossDamage:
types:
Bloodloss:
baseWalkSpeed : 2.00
baseSprintSpeed : 2.00
- type: Bloodstream
- bloodMaxVolume: 350
- chemicalMaxVolume: 0
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 350
- type: MobThresholds
thresholds:
0: Alive
capacity: 1
count: 1
- type: Bloodstream
- bloodMaxVolume: 200
- chemicalMaxVolume: 0
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 200
- type: NpcFactionMember
factions:
- SimpleHostile
- type: Input
context: "human"
- type: Bloodstream
- bloodMaxVolume: 300
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Laughter
- Quantity: 1
+ Quantity: 300
- type: entity
name: behonker
parent: BaseMobBehonker
speedModifierThresholds:
50: 0.4
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Water
- Quantity: 1
- chemicalMaxVolume: 100
+ Quantity: 100
- type: StatusEffects
allowed:
- Electrocution
suffix: Beer
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Beer
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#cfa85f"
- type: Sprite
suffix: Pax
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Pax
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#AAAAAA"
- type: Sprite
suffix: Nocturine
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Nocturine
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#128e80"
- type: Sprite
suffix: THC
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: THC
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#808080"
- type: Sprite
suffix: Bicaridine
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Bicaridine
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#ffaa00"
- type: Sprite
suffix: Toxin
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Toxin
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#cf3600"
- type: Sprite
suffix: Napalm
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Napalm
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#FA00AF"
- type: Sprite
suffix: Omnizine
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Omnizine
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#fcf7f9"
- type: Sprite
suffix: Mute Toxin
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: MuteToxin
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#0f0f0f"
- type: Sprite
suffix: Norepinephric Acid
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: NorepinephricAcid
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#96a8b5"
- type: Sprite
suffix: Ephedrine
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Ephedrine
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#D2FFFA"
- type: Sprite
suffix: Robust Harvest
components:
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: RobustHarvest
- Quantity: 1
+ Quantity: 100
- type: PointLight
color: "#3e901c"
- type: Sprite
- id: FoodMeat
amount: 1
- type: Bloodstream
- bloodMaxVolume: 100
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 100
- type: CombatMode
- type: MeleeWeapon
soundHit:
- id: FoodMeat
amount: 1
- type: Bloodstream
- bloodMaxVolume: 100
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 100
- type: CombatMode
- type: MeleeWeapon
soundHit:
- map: [ "enum.DamageStateVisualLayers.Base" ]
state: alive
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: JuiceTomato
- Quantity: 1
- bloodMaxVolume: 50
- chemicalMaxVolume: 30
+ Quantity: 50
- type: DamageStateVisuals
states:
Alive:
- RadiationProtection
- Adrenaline
- type: Bloodstream
- bloodMaxVolume: 150
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 150
- type: MobPrice
price: 150
- type: FloatingVisuals
damageContainer: Biological
damageModifierSet: Slime
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Slime
- Quantity: 1
+ Quantity: 150
bloodlossDamage:
types:
Bloodloss:
critThreshold: 150
- type: MovementAlwaysTouching
- type: Bloodstream
- bloodMaxVolume: 300
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Cryoxadone
- Quantity: 1
+ Quantity: 300
- type: CombatMode
- type: Temperature
heatDamageThreshold: 500
amount: 1
prob: 0.5
- type: Bloodstream
- bloodMaxVolume: 250
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Cryoxadone
- Quantity: 1
+ Quantity: 250
- type: Fixtures
fixtures:
fix1:
amount: 1
prob: 0.3
- type: Bloodstream
- bloodMaxVolume: 200
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Cryoxadone
- Quantity: 1
+ Quantity: 200
- type: Fixtures
fixtures:
fix1:
- type: CombatMode
combatToggleAction: ActionCombatModeToggleOff
- type: Bloodstream
- bloodMaxVolume: 30
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Cryoxadone
- Quantity: 1
+ Quantity: 30
- type: CanEscapeInventory
- type: MobPrice
price: 50
- id: FoodMeatXeno
amount: 1
- type: Bloodstream
- bloodMaxVolume: 50
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 50
- type: CombatMode
- type: MeleeWeapon
soundHit:
- type: Stamina
critThreshold: 200
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: FluorosulfuricAcid
- Quantity: 1
- bloodMaxVolume: 650
+ Quantity: 650
- type: MeleeWeapon
altDisarm: false
angle: 0
- type: Stamina
critThreshold: 200
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: FluorosulfuricAcid
- Quantity: 1
- bloodMaxVolume: 300
+ Quantity: 300
- type: MeleeWeapon
altDisarm: false
angle: 0
abstract: true
components:
- type: Bloodstream
- bloodMaxVolume: 650
+ bloodReferenceSolution:
+ reagents:
+ - ReagentId: Blood
+ Quantity: 650
- type: GhostRole
allowMovement: true
allowSpeech: true
- !type:WashCreamPie
# Damage (Self)
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: CopperBlood
- Quantity: 1
+ Quantity: 300
# Damage (Others)
- type: MeleeWeapon
animation: WeaponArcBite
- id: FoodMeatPlant
amount: 5
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Sap
- Quantity: 1
+ Quantity: 300
- type: Reactive
groups:
Flammable: [ Touch ]
- id: FoodBakedCookie #should be replaced with gingerbread sheets or something... provided you're willing to make a full spriteset of those.
amount: 5
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: Sugar
- Quantity: 1
+ Quantity: 100
- ReagentId: Butter
- Quantity: 2
+ Quantity: 200
- type: Fixtures
fixtures:
fix1:
- id: FoodMeat
amount: 5
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: InsectBlood
- Quantity: 1
+ Quantity: 300
- type: DamageVisuals
damageOverlayGroups:
Brute:
Burn:
sprite: Mobs/Effects/burn_damage.rsi
- type: Bloodstream
- bloodReagents: # TODO Color slime blood based on their slime color or smth
+ bloodReferenceSolution: # TODO Color slime blood based on their slime color or smth
reagents:
- ReagentId: Slime
- Quantity: 1
+ Quantity: 300
- type: Barotrauma
damage:
types:
Burn:
sprite: Mobs/Effects/burn_damage.rsi
- type: Bloodstream
- bloodReagents:
+ bloodReferenceSolution:
reagents:
- ReagentId: AmmoniaBlood
- Quantity: 1
+ Quantity: 300
- type: MeleeWeapon
soundHit:
collection: AlienClaw
components:
- type: SolutionContainerManager
- type: InjectableSolution
- solution: chemicals
+ solution: bloodstream
- type: Bloodstream
bloodlossDamage:
types:
- type: reaction
id: RedMead
+ requiredMixerCategories:
+ - Stir
reactants:
Mead:
amount: 1
- type: reaction
id: SpaceGlue
+ requiredMixerCategories:
+ - Stir # prevents turning slimes to glue, TODO: make it react only X units per second; make bloodstream an open thermal system
minTemp: 370
reactants:
SpaceLube:
- type: reaction
id: SapBoiling
+ requiredMixerCategories:
+ - Stir # prevents cooking diona from inside out, TODO: make it react only X units per second; make bloodstream an open thermal system
impact: Low
minTemp: 377
reactants: