From 6213c51fd58fae31ebaf09edc90bf25d82c1cf22 Mon Sep 17 00:00:00 2001 From: "Ignaz \"Ian\" Kraft" Date: Mon, 1 Dec 2025 06:35:21 +0100 Subject: [PATCH] multi reagent bloodstream (#41489) * multi reagent bloodstream * pluralize the comments * fix TryModifyBloodLevel return logic * now with quantity * now with solution * implement suggestions * fix forensics * minor thing * Nevermind undo that caps matters. --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> --- .../Body/Systems/BloodstreamSystem.cs | 5 +- .../BiomassReclaimerComponent.cs | 5 +- .../BiomassReclaimerSystem.cs | 15 +++-- .../Zombies/ZombieSystem.Transform.cs | 7 +- Content.Server/Zombies/ZombieSystem.cs | 2 +- .../Body/Components/BloodstreamComponent.cs | 5 +- .../Body/Systems/SharedBloodstreamSystem.cs | 59 ++++++++++++----- .../Chemistry/Components/Solution.cs | 48 +++++++++++++- Content.Shared/Chemistry/Reagent/DNAData.cs | 11 +++- .../Chemistry/Reagent/ReagentQuantity.cs | 26 +++++++- Content.Shared/Zombies/ZombieComponent.cs | 14 ++-- .../Prototypes/Entities/Mobs/NPCs/animals.yml | 51 +++++++++++---- .../Entities/Mobs/NPCs/argocyte.yml | 5 +- .../Entities/Mobs/NPCs/behonker.yml | 6 +- .../Entities/Mobs/NPCs/elemental.yml | 65 +++++++++++++++---- .../Entities/Mobs/NPCs/miscellaneous.yml | 5 +- .../Prototypes/Entities/Mobs/NPCs/slimes.yml | 5 +- .../Prototypes/Entities/Mobs/NPCs/space.yml | 20 ++++-- .../Prototypes/Entities/Mobs/NPCs/xeno.yml | 10 ++- .../Entities/Mobs/Species/arachnid.yml | 5 +- .../Entities/Mobs/Species/diona.yml | 5 +- .../Entities/Mobs/Species/gingerbread.yml | 7 +- .../Prototypes/Entities/Mobs/Species/moth.yml | 5 +- .../Entities/Mobs/Species/slime.yml | 5 +- .../Prototypes/Entities/Mobs/Species/vox.yml | 5 +- 25 files changed, 307 insertions(+), 89 deletions(-) diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index c2185750af..a58deec494 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -37,7 +37,10 @@ public sealed class BloodstreamSystem : SharedBloodstreamSystem // Fill blood solution with BLOOD // The DNA string might not be initialized yet, but the reagent data gets updated in the GenerateDnaEvent subscription - bloodSolution.AddReagent(new ReagentId(entity.Comp.BloodReagent, GetEntityBloodData(entity.Owner)), entity.Comp.BloodMaxVolume - bloodSolution.Volume); + var solution = entity.Comp.BloodReagents.Clone(); + solution.ScaleTo(entity.Comp.BloodMaxVolume - bloodSolution.Volume); + solution.SetReagentData(GetEntityBloodData(entity.Owner)); + bloodSolution.AddSolution(solution, PrototypeManager); } // forensics is not predicted yet diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs index 61d36f98b9..bc295545b0 100644 --- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs +++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared.Chemistry.Components; using Content.Shared.Storage; namespace Content.Server.Medical.BiomassReclaimer @@ -34,10 +35,10 @@ namespace Content.Server.Medical.BiomassReclaimer public float CurrentExpectedYield = 0f; /// - /// The reagent that will be spilled while processing a mob. + /// The reagents that will be spilled while processing a mob. /// [ViewVariables] - public string? BloodReagent; + public Solution? BloodReagents = null; /// /// Entities that can be randomly spawned while processing a mob. diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs index e029071574..83dcd9cf7c 100644 --- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs +++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs @@ -7,7 +7,7 @@ using Content.Shared.Administration.Logs; using Content.Shared.Audio; using Content.Shared.Body.Components; using Content.Shared.CCVar; -using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Climbing.Events; using Content.Shared.Construction.Components; using Content.Shared.Database; @@ -45,6 +45,7 @@ namespace Content.Server.Medical.BiomassReclaimer [Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly PuddleSystem _puddleSystem = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solution = default!; [Dependency] private readonly ThrowingSystem _throwing = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; @@ -68,10 +69,8 @@ namespace Content.Server.Medical.BiomassReclaimer if (reclaimer.RandomMessTimer <= 0) { - if (_robustRandom.Prob(0.2f) && reclaimer.BloodReagent is not null) + if (_robustRandom.Prob(0.2f) && reclaimer.BloodReagents is { } blood) { - Solution blood = new(); - blood.AddReagent(reclaimer.BloodReagent, 50); _puddleSystem.TrySpillAt(uid, blood, out _); } if (_robustRandom.Prob(0.03f) && reclaimer.SpawnedEntities.Count > 0) @@ -92,7 +91,7 @@ namespace Content.Server.Medical.BiomassReclaimer reclaimer.CurrentExpectedYield = reclaimer.CurrentExpectedYield - actualYield; // store non-integer leftovers _material.SpawnMultipleFromMaterial(actualYield, BiomassPrototype, Transform(uid).Coordinates); - reclaimer.BloodReagent = null; + reclaimer.BloodReagents = null; reclaimer.SpawnedEntities.Clear(); RemCompDeferred(uid); } @@ -208,9 +207,11 @@ namespace Content.Server.Medical.BiomassReclaimer var component = ent.Comp; AddComp(ent); - if (TryComp(toProcess, out var stream)) + if (TryComp(toProcess, out var stream) && + _solution.ResolveSolution(toProcess, stream.BloodSolutionName, ref stream.BloodSolution, out var solution)) { - component.BloodReagent = stream.BloodReagent; + component.BloodReagents = solution.Clone(); + component.BloodReagents.ScaleSolution(50 / component.BloodReagents.Volume); } if (TryComp(toProcess, out var butcherableComponent)) { diff --git a/Content.Server/Zombies/ZombieSystem.Transform.cs b/Content.Server/Zombies/ZombieSystem.Transform.cs index 43a06f2614..cfa22b2a14 100644 --- a/Content.Server/Zombies/ZombieSystem.Transform.cs +++ b/Content.Server/Zombies/ZombieSystem.Transform.cs @@ -16,7 +16,6 @@ using Content.Server.Speech.Components; using Content.Shared.Body.Components; using Content.Shared.CombatMode; using Content.Shared.CombatMode.Pacification; -using Content.Shared.Damage.Components; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Humanoid; @@ -194,8 +193,8 @@ public sealed partial class ZombieSystem zombiecomp.BeforeZombifiedSkinColor = huApComp.SkinColor; zombiecomp.BeforeZombifiedEyeColor = huApComp.EyeColor; zombiecomp.BeforeZombifiedCustomBaseLayers = new(huApComp.CustomBaseLayers); - if (TryComp(target, out var stream)) - zombiecomp.BeforeZombifiedBloodReagent = stream.BloodReagent; + if (TryComp(target, out var stream) && stream.BloodReagents is { } reagents) + zombiecomp.BeforeZombifiedBloodReagents = reagents.Clone(); _humanoidAppearance.SetSkinColor(target, zombiecomp.SkinColor, verify: false, humanoid: huApComp); @@ -229,7 +228,7 @@ public sealed partial class ZombieSystem //NOTE: they are supposed to bleed, just not take damage _bloodstream.SetBloodLossThreshold(target, 0f); //Give them zombie blood - _bloodstream.ChangeBloodReagent(target, zombiecomp.NewBloodReagent); + _bloodstream.ChangeBloodReagents(target, zombiecomp.NewBloodReagents); //This is specifically here to combat insuls, because frying zombies on grilles is funny as shit. _inventory.TryUnequip(target, "gloves", true, true); diff --git a/Content.Server/Zombies/ZombieSystem.cs b/Content.Server/Zombies/ZombieSystem.cs index 72c5236930..b840e7203e 100644 --- a/Content.Server/Zombies/ZombieSystem.cs +++ b/Content.Server/Zombies/ZombieSystem.cs @@ -305,7 +305,7 @@ namespace Content.Server.Zombies appcomp.EyeColor = zombiecomp.BeforeZombifiedEyeColor; } _humanoidAppearance.SetSkinColor(target, zombiecomp.BeforeZombifiedSkinColor, false); - _bloodstream.ChangeBloodReagent(target, zombiecomp.BeforeZombifiedBloodReagent); + _bloodstream.ChangeBloodReagents(target, zombiecomp.BeforeZombifiedBloodReagents); return true; } diff --git a/Content.Shared/Body/Components/BloodstreamComponent.cs b/Content.Shared/Body/Components/BloodstreamComponent.cs index 51814eaba9..2ebfae6f33 100644 --- a/Content.Shared/Body/Components/BloodstreamComponent.cs +++ b/Content.Shared/Body/Components/BloodstreamComponent.cs @@ -1,7 +1,6 @@ using Content.Shared.Alert; using Content.Shared.Body.Systems; using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Reagent; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; @@ -152,13 +151,13 @@ public sealed partial class BloodstreamComponent : Component public FixedPoint2 BloodMaxVolume = FixedPoint2.New(300); /// - /// Which reagent is considered this entities 'blood'? + /// Which reagents are considered this entities 'blood'? /// /// /// Slime-people might use slime as their blood or something like that. /// [DataField, AutoNetworkedField] - public ProtoId BloodReagent = "Blood"; + public Solution BloodReagents = new([new("Blood", 1)]); /// /// Name/Key that is indexed by. diff --git a/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs b/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs index 688e3ccb92..e108cbfb27 100644 --- a/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs +++ b/Content.Shared/Body/Systems/SharedBloodstreamSystem.cs @@ -29,9 +29,9 @@ public abstract class SharedBloodstreamSystem : EntitySystem { public static readonly EntProtoId Bloodloss = "StatusEffectBloodloss"; + [Dependency] protected readonly IPrototypeManager PrototypeManager = default!; [Dependency] protected readonly SharedSolutionContainerSystem SolutionContainer = default!; [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedPuddleSystem _puddle = default!; @@ -193,7 +193,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem } // TODO probably cache this or something. humans get hurt a lot - if (!_prototypeManager.Resolve(ent.Comp.DamageBleedModifiers, out var modifiers)) + if (!PrototypeManager.Resolve(ent.Comp.DamageBleedModifiers, out var modifiers)) return; // some reagents may deal and heal different damage types in the same tick, which means DamageIncreased will be true @@ -366,11 +366,18 @@ public abstract class SharedBloodstreamSystem : EntitySystem public bool TryModifyBloodLevel(Entity ent, FixedPoint2 amount) { if (!Resolve(ent, ref ent.Comp, logMissing: false) - || !SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution)) + || !SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution, out var bloodSolution)) return false; if (amount >= 0) - return SolutionContainer.TryAddReagent(ent.Comp.BloodSolution.Value, ent.Comp.BloodReagent, amount, null, GetEntityBloodData(ent)); + { + 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; + } // Removal is more involved, // since we also wanna handle moving it to the temporary solution @@ -380,7 +387,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem if (!SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodTemporarySolutionName, ref ent.Comp.TemporarySolution, out var tempSolution)) return true; - tempSolution.AddSolution(newSol, _prototypeManager); + tempSolution.AddSolution(newSol, PrototypeManager); if (tempSolution.Volume > ent.Comp.BleedPuddleThreshold) { @@ -388,7 +395,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem 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); + tempSolution.AddSolution(temp, PrototypeManager); } _puddle.TrySpillAt(ent.Owner, tempSolution, out _, sound: false); @@ -439,21 +446,21 @@ public abstract class SharedBloodstreamSystem : EntitySystem if (SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution, out var bloodSolution)) { tempSol.MaxVolume += bloodSolution.MaxVolume; - tempSol.AddSolution(bloodSolution, _prototypeManager); + tempSol.AddSolution(bloodSolution, PrototypeManager); 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); + 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; - tempSol.AddSolution(tempSolution, _prototypeManager); + tempSol.AddSolution(tempSolution, PrototypeManager); SolutionContainer.RemoveAllSolution(ent.Comp.TemporarySolution.Value); } @@ -463,27 +470,45 @@ public abstract class SharedBloodstreamSystem : EntitySystem /// /// Change what someone's blood is made of, on the fly. /// + [Obsolete("ChangeBloodReagent is obsolete, please use ChangeBloodReagents.")] public void ChangeBloodReagent(Entity ent, ProtoId reagent) { - if (!Resolve(ent, ref ent.Comp, logMissing: false) - || reagent == ent.Comp.BloodReagent) + ChangeBloodReagents(ent, new([new(reagent, 1)])); + } + + /// + /// Change what someone's blood is made of, on the fly. + /// + public void ChangeBloodReagents(Entity ent, Solution reagents) + { + if (!Resolve(ent, ref ent.Comp, logMissing: false)) { return; } if (!SolutionContainer.ResolveSolution(ent.Owner, ent.Comp.BloodSolutionName, ref ent.Comp.BloodSolution, out var bloodSolution)) { - ent.Comp.BloodReagent = reagent; + ent.Comp.BloodReagents = reagents.Clone(); + DirtyField(ent, ent.Comp, nameof(BloodstreamComponent.BloodReagents)); return; } - var currentVolume = bloodSolution.RemoveReagent(ent.Comp.BloodReagent, bloodSolution.Volume, ignoreReagentData: true); + var currentVolume = FixedPoint2.Zero; + foreach (var reagent in ent.Comp.BloodReagents) + { + currentVolume += bloodSolution.RemoveReagent(reagent.Reagent, quantity: bloodSolution.Volume, ignoreReagentData: true); + } + + ent.Comp.BloodReagents = reagents.Clone(); + DirtyField(ent, ent.Comp, nameof(BloodstreamComponent.BloodReagents)); - ent.Comp.BloodReagent = reagent; - DirtyField(ent, ent.Comp, nameof(BloodstreamComponent.BloodReagent)); + if (currentVolume == FixedPoint2.Zero) + return; - if (currentVolume > 0) - SolutionContainer.TryAddReagent(ent.Comp.BloodSolution.Value, ent.Comp.BloodReagent, currentVolume, null, GetEntityBloodData(ent)); + var solution = ent.Comp.BloodReagents.Clone(); + solution.ScaleSolution(currentVolume / solution.Volume); + solution.SetReagentData(GetEntityBloodData(ent)); + SolutionContainer.AddSolution(ent.Comp.BloodSolution.Value, solution); } /// diff --git a/Content.Shared/Chemistry/Components/Solution.cs b/Content.Shared/Chemistry/Components/Solution.cs index df09f7f3f6..cd0314419a 100644 --- a/Content.Shared/Chemistry/Components/Solution.cs +++ b/Content.Shared/Chemistry/Components/Solution.cs @@ -167,7 +167,12 @@ namespace Content.Shared.Chemistry.Components public Solution(Solution solution) { - Contents = solution.Contents.ShallowClone(); + Contents = new(solution.Contents.Count); + foreach (var item in solution.Contents) + { + Contents.Add(item.Clone()); + } + Volume = solution.Volume; MaxVolume = solution.MaxVolume; Temperature = solution.Temperature; @@ -474,6 +479,37 @@ namespace Content.Shared.Chemistry.Components ValidateSolution(); } + /// + /// Scales the amount of solution. + /// + /// The scalar to modify the solution by. + public void ScaleSolution(FixedPoint2 scale) + { + ScaleSolution(scale.Float()); + } + + /// + /// Scales the amount of solution to a given target. + /// + /// The volume the solutions should have after scaling. + public void ScaleTo(FixedPoint2 target) + { + if (Volume == FixedPoint2.Zero || Volume == target) + return; + + if (target == FixedPoint2.Zero) + { + RemoveAllSolution(); + return; + } + + var nearestIntScale = (int)Math.Ceiling(target.Float() / Volume.Float()); + ScaleSolution(nearestIntScale); + + var overflow = Volume - target; + RemoveSolution(overflow); + } + /// /// Attempts to remove an amount of reagent from the solution. /// @@ -965,5 +1001,15 @@ namespace Content.Shared.Chemistry.Components } return dict; } + + public void SetReagentData(List? data) + { + for (var i = 0; i < Contents.Count; i++) + { + var old = Contents[i]; + Contents[i] = new ReagentQuantity(new ReagentId(old.Reagent.Prototype, data), old.Quantity); + } + ValidateSolution(); + } } } diff --git a/Content.Shared/Chemistry/Reagent/DNAData.cs b/Content.Shared/Chemistry/Reagent/DNAData.cs index e75e994ece..5a88c0b41c 100644 --- a/Content.Shared/Chemistry/Reagent/DNAData.cs +++ b/Content.Shared/Chemistry/Reagent/DNAData.cs @@ -1,4 +1,3 @@ -using Content.Shared.FixedPoint; using Robust.Shared.Serialization; namespace Content.Shared.Chemistry.Reagent; @@ -7,9 +6,15 @@ namespace Content.Shared.Chemistry.Reagent; public sealed partial class DnaData : ReagentData { [DataField] - public string DNA = String.Empty; + public string DNA = string.Empty; - public override ReagentData Clone() => this; + public override ReagentData Clone() + { + return new DnaData + { + DNA = DNA, + }; + } public override bool Equals(ReagentData? other) { diff --git a/Content.Shared/Chemistry/Reagent/ReagentQuantity.cs b/Content.Shared/Chemistry/Reagent/ReagentQuantity.cs index cc5b52fbe2..22c1a3e0e5 100644 --- a/Content.Shared/Chemistry/Reagent/ReagentQuantity.cs +++ b/Content.Shared/Chemistry/Reagent/ReagentQuantity.cs @@ -8,9 +8,9 @@ namespace Content.Shared.Chemistry.Reagent; /// [Serializable, NetSerializable] [DataDefinition] -public partial struct ReagentQuantity : IEquatable +public partial struct ReagentQuantity : IEquatable, IRobustCloneable { - [DataField("Quantity", required:true)] + [DataField("Quantity", required: true)] public FixedPoint2 Quantity { get; private set; } [IncludeDataField] @@ -28,6 +28,28 @@ public partial struct ReagentQuantity : IEquatable Quantity = quantity; } + public ReagentQuantity(ReagentQuantity reagentQuantity) + { + Quantity = reagentQuantity.Quantity; + if (reagentQuantity.Reagent.Data is not { } data) + { + Reagent = new ReagentId(reagentQuantity.Reagent.Prototype, null); + return; + } + + List copy = new(data.Count); + foreach (var item in data) + { + copy.Add(item.Clone()); + } + Reagent = new ReagentId(reagentQuantity.Reagent.Prototype, copy); + } + + public readonly ReagentQuantity Clone() + { + return new ReagentQuantity(this); + } + public ReagentQuantity() : this(default, default) { } diff --git a/Content.Shared/Zombies/ZombieComponent.cs b/Content.Shared/Zombies/ZombieComponent.cs index 2a69a7553f..4c941f1767 100644 --- a/Content.Shared/Zombies/ZombieComponent.cs +++ b/Content.Shared/Zombies/ZombieComponent.cs @@ -1,7 +1,7 @@ using Content.Shared.Chat.Prototypes; +using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Damage; -using Content.Shared.FixedPoint; using Content.Shared.Humanoid; using Content.Shared.Roles; using Content.Shared.StatusIcon; @@ -165,14 +165,14 @@ public sealed partial class ZombieComponent : Component public SoundSpecifier BiteSound = new SoundPathSpecifier("/Audio/Effects/bite.ogg"); /// - /// The blood reagent of the humanoid to restore in case of cloning + /// The blood reagents of the humanoid to restore in case of cloning /// - [DataField("beforeZombifiedBloodReagent")] - public string BeforeZombifiedBloodReagent = string.Empty; + [DataField("beforeZombifiedBloodReagents")] + public Solution BeforeZombifiedBloodReagents = new(); /// - /// The blood reagent to give the zombie. In case you want zombies that bleed milk, or something. + /// The blood reagents to give the zombie. In case you want zombies that bleed milk, or something. /// - [DataField("newBloodReagent", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string NewBloodReagent = "ZombieBlood"; + [DataField("newBloodReagents")] + public Solution NewBloodReagents = new([new("ZombieBlood", 1)]); } diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index d3d1b23dcc..9965167256 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -140,7 +140,10 @@ - Bee - Trash - type: Bloodstream - bloodReagent: InsectBlood + bloodReagents: + reagents: + - ReagentId: InsectBlood + Quantity: 1 bloodMaxVolume: 0.1 - type: MobPrice price: 50 @@ -388,7 +391,10 @@ Dead: Base: cockroach_dead - type: Bloodstream - bloodReagent: InsectBlood + bloodReagents: + reagents: + - ReagentId: InsectBlood + Quantity: 1 bloodMaxVolume: 20 - type: Edible - type: FlavorProfile @@ -552,7 +558,10 @@ damageContainer: Biological damageModifierSet: Moth - type: Bloodstream - bloodReagent: InsectBlood + bloodReagents: + reagents: + - ReagentId: InsectBlood + Quantity: 1 - type: Respirator damage: types: @@ -832,7 +841,10 @@ tags: - Trash - type: Bloodstream - bloodReagent: InsectBlood + bloodReagents: + reagents: + - ReagentId: InsectBlood + Quantity: 1 bloodMaxVolume: 0.1 - type: MobPrice price: 50 @@ -990,7 +1002,10 @@ accent: crab - type: Bloodstream bloodMaxVolume: 50 - bloodReagent: CopperBlood + bloodReagents: + reagents: + - ReagentId: CopperBlood + Quantity: 1 - type: Tag tags: - VimPilot @@ -1996,7 +2011,10 @@ - type: RadiationSource intensity: 0.3 - type: Bloodstream - bloodReagent: UnstableMutagen + bloodReagents: + reagents: + - ReagentId: UnstableMutagen + Quantity: 1 - type: SolutionContainerManager solutions: food: @@ -2515,7 +2533,10 @@ - type: IgnoreSpiderWeb - type: Bloodstream bloodMaxVolume: 150 - bloodReagent: CopperBlood + bloodReagents: + reagents: + - ReagentId: CopperBlood + Quantity: 1 - type: Speech speechVerb: Arachnid speechSounds: Arachnid @@ -2661,8 +2682,10 @@ speechVerb: Cluwne - type: Bloodstream bloodMaxVolume: 150 - bloodReagent: Laughter - + bloodReagents: + reagents: + - ReagentId: Laughter + Quantity: 1 - type: entity name: wizard spider parent: MobGiantSpider @@ -2991,7 +3014,10 @@ attributes: gender: epicene - type: Bloodstream - bloodReagent: DemonsBlood + bloodReagents: + reagents: + - ReagentId: DemonsBlood + Quantity: 1 - type: Damageable damageContainer: BiologicalMetaphysical damageModifierSet: Infernal @@ -3631,7 +3657,10 @@ speciesId: cat templateId: pet - type: Bloodstream - bloodReagent: Sap + bloodReagents: + reagents: + - ReagentId: Sap + Quantity: 1 bloodMaxVolume: 60 - type: DamageStateVisuals states: diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/argocyte.yml b/Resources/Prototypes/Entities/Mobs/NPCs/argocyte.yml index 36ddf71d4b..4c9f851ba0 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/argocyte.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/argocyte.yml @@ -18,7 +18,10 @@ - type: ReplacementAccent accent: xeno - type: Bloodstream - bloodReagent: FerrochromicAcid + bloodReagents: + reagents: + - ReagentId: FerrochromicAcid + Quantity: 1 bloodMaxVolume: 75 #we don't want the map to become pools of blood bloodlossDamage: types: diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml b/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml index 1cb00ef760..23e3230937 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/behonker.yml @@ -115,8 +115,10 @@ context: "human" - type: Bloodstream bloodMaxVolume: 300 - bloodReagent: Laughter - + bloodReagents: + reagents: + - ReagentId: Laughter + Quantity: 1 - type: entity name: behonker parent: BaseMobBehonker diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml index eef5f48838..79df100598 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml @@ -349,7 +349,10 @@ speedModifierThresholds: 50: 0.4 - type: Bloodstream - bloodReagent: Water + bloodReagents: + reagents: + - ReagentId: Water + Quantity: 1 chemicalMaxVolume: 100 - type: StatusEffects allowed: @@ -418,7 +421,10 @@ suffix: Beer components: - type: Bloodstream - bloodReagent: Beer + bloodReagents: + reagents: + - ReagentId: Beer + Quantity: 1 - type: PointLight color: "#cfa85f" - type: Sprite @@ -435,7 +441,10 @@ suffix: Pax components: - type: Bloodstream - bloodReagent: Pax + bloodReagents: + reagents: + - ReagentId: Pax + Quantity: 1 - type: PointLight color: "#AAAAAA" - type: Sprite @@ -455,7 +464,10 @@ suffix: Nocturine components: - type: Bloodstream - bloodReagent: Nocturine + bloodReagents: + reagents: + - ReagentId: Nocturine + Quantity: 1 - type: PointLight color: "#128e80" - type: Sprite @@ -475,7 +487,10 @@ suffix: THC components: - type: Bloodstream - bloodReagent: THC + bloodReagents: + reagents: + - ReagentId: THC + Quantity: 1 - type: PointLight color: "#808080" - type: Sprite @@ -492,7 +507,10 @@ suffix: Bicaridine components: - type: Bloodstream - bloodReagent: Bicaridine + bloodReagents: + reagents: + - ReagentId: Bicaridine + Quantity: 1 - type: PointLight color: "#ffaa00" - type: Sprite @@ -509,7 +527,10 @@ suffix: Toxin components: - type: Bloodstream - bloodReagent: Toxin + bloodReagents: + reagents: + - ReagentId: Toxin + Quantity: 1 - type: PointLight color: "#cf3600" - type: Sprite @@ -526,7 +547,10 @@ suffix: Napalm components: - type: Bloodstream - bloodReagent: Napalm + bloodReagents: + reagents: + - ReagentId: Napalm + Quantity: 1 - type: PointLight color: "#FA00AF" - type: Sprite @@ -543,7 +567,10 @@ suffix: Omnizine components: - type: Bloodstream - bloodReagent: Omnizine + bloodReagents: + reagents: + - ReagentId: Omnizine + Quantity: 1 - type: PointLight color: "#fcf7f9" - type: Sprite @@ -560,7 +587,10 @@ suffix: Mute Toxin components: - type: Bloodstream - bloodReagent: MuteToxin + bloodReagents: + reagents: + - ReagentId: MuteToxin + Quantity: 1 - type: PointLight color: "#0f0f0f" - type: Sprite @@ -577,7 +607,10 @@ suffix: Norepinephric Acid components: - type: Bloodstream - bloodReagent: NorepinephricAcid + bloodReagents: + reagents: + - ReagentId: NorepinephricAcid + Quantity: 1 - type: PointLight color: "#96a8b5" - type: Sprite @@ -594,7 +627,10 @@ suffix: Ephedrine components: - type: Bloodstream - bloodReagent: Ephedrine + bloodReagents: + reagents: + - ReagentId: Ephedrine + Quantity: 1 - type: PointLight color: "#D2FFFA" - type: Sprite @@ -611,7 +647,10 @@ suffix: Robust Harvest components: - type: Bloodstream - bloodReagent: RobustHarvest + bloodReagents: + reagents: + - ReagentId: RobustHarvest + Quantity: 1 - type: PointLight color: "#3e901c" - type: Sprite diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml b/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml index 00aa20db18..a4ba443046 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/miscellaneous.yml @@ -150,7 +150,10 @@ - map: [ "enum.DamageStateVisualLayers.Base" ] state: alive - type: Bloodstream - bloodReagent: JuiceTomato + bloodReagents: + reagents: + - ReagentId: JuiceTomato + Quantity: 1 bloodMaxVolume: 50 chemicalMaxVolume: 30 - type: DamageStateVisuals diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml b/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml index 95cf95bcbc..74c6bb1468 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml @@ -53,7 +53,10 @@ damageContainer: Biological damageModifierSet: Slime - type: Bloodstream - bloodReagent: Slime + bloodReagents: + reagents: + - ReagentId: Slime + Quantity: 1 bloodlossDamage: types: Bloodloss: diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/space.yml b/Resources/Prototypes/Entities/Mobs/NPCs/space.yml index 45c0b46d23..8acc571ccf 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/space.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/space.yml @@ -40,7 +40,10 @@ - type: MovementAlwaysTouching - type: Bloodstream bloodMaxVolume: 300 - bloodReagent: Cryoxadone + bloodReagents: + reagents: + - ReagentId: Cryoxadone + Quantity: 1 - type: CombatMode - type: Temperature heatDamageThreshold: 500 @@ -217,7 +220,10 @@ prob: 0.5 - type: Bloodstream bloodMaxVolume: 250 - bloodReagent: Cryoxadone + bloodReagents: + reagents: + - ReagentId: Cryoxadone + Quantity: 1 - type: Fixtures fixtures: fix1: @@ -320,7 +326,10 @@ prob: 0.3 - type: Bloodstream bloodMaxVolume: 200 - bloodReagent: Cryoxadone + bloodReagents: + reagents: + - ReagentId: Cryoxadone + Quantity: 1 - type: Fixtures fixtures: fix1: @@ -494,7 +503,10 @@ combatToggleAction: ActionCombatModeToggleOff - type: Bloodstream bloodMaxVolume: 30 - bloodReagent: Cryoxadone + bloodReagents: + reagents: + - ReagentId: Cryoxadone + Quantity: 1 - type: CanEscapeInventory - type: MobPrice price: 50 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index ba8ee70b1a..f1c860364b 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -67,7 +67,10 @@ - type: Stamina critThreshold: 200 - type: Bloodstream - bloodReagent: FluorosulfuricAcid + bloodReagents: + reagents: + - ReagentId: FluorosulfuricAcid + Quantity: 1 bloodMaxVolume: 650 - type: MeleeWeapon altDisarm: false @@ -492,7 +495,10 @@ - type: Stamina critThreshold: 200 - type: Bloodstream - bloodReagent: FluorosulfuricAcid + bloodReagents: + reagents: + - ReagentId: FluorosulfuricAcid + Quantity: 1 bloodMaxVolume: 300 - type: MeleeWeapon altDisarm: false diff --git a/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml b/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml index 0624e9670a..e38e93a930 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/arachnid.yml @@ -42,7 +42,10 @@ - !type:WashCreamPie # Damage (Self) - type: Bloodstream - bloodReagent: CopperBlood + bloodReagents: + reagents: + - ReagentId: CopperBlood + Quantity: 1 # Damage (Others) - type: MeleeWeapon animation: WeaponArcBite diff --git a/Resources/Prototypes/Entities/Mobs/Species/diona.yml b/Resources/Prototypes/Entities/Mobs/Species/diona.yml index 6cad3bdfc5..4dafbf99b9 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/diona.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/diona.yml @@ -33,7 +33,10 @@ - id: FoodMeatPlant amount: 5 - type: Bloodstream - bloodReagent: Sap + bloodReagents: + reagents: + - ReagentId: Sap + Quantity: 1 - type: Reactive groups: Flammable: [ Touch ] diff --git a/Resources/Prototypes/Entities/Mobs/Species/gingerbread.yml b/Resources/Prototypes/Entities/Mobs/Species/gingerbread.yml index cc4b506dc8..7844c80082 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/gingerbread.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/gingerbread.yml @@ -29,7 +29,12 @@ - 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 - bloodReagent: Sugar + bloodReagents: + reagents: + - ReagentId: Sugar + Quantity: 1 + - ReagentId: Butter + Quantity: 2 - type: Fixtures fixtures: fix1: diff --git a/Resources/Prototypes/Entities/Mobs/Species/moth.yml b/Resources/Prototypes/Entities/Mobs/Species/moth.yml index 9503c2f56d..d0adbcc28f 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/moth.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/moth.yml @@ -33,7 +33,10 @@ - id: FoodMeat amount: 5 - type: Bloodstream - bloodReagent: InsectBlood + bloodReagents: + reagents: + - ReagentId: InsectBlood + Quantity: 1 - type: DamageVisuals damageOverlayGroups: Brute: diff --git a/Resources/Prototypes/Entities/Mobs/Species/slime.yml b/Resources/Prototypes/Entities/Mobs/Species/slime.yml index 1ca590d496..89115dd1c2 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/slime.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/slime.yml @@ -68,7 +68,10 @@ Burn: sprite: Mobs/Effects/burn_damage.rsi - type: Bloodstream - bloodReagent: Slime # TODO Color slime blood based on their slime color or smth + bloodReagents: # TODO Color slime blood based on their slime color or smth + reagents: + - ReagentId: Slime + Quantity: 1 - type: Barotrauma damage: types: diff --git a/Resources/Prototypes/Entities/Mobs/Species/vox.yml b/Resources/Prototypes/Entities/Mobs/Species/vox.yml index d6ff814970..ecc0cea5cd 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/vox.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/vox.yml @@ -89,7 +89,10 @@ Burn: sprite: Mobs/Effects/burn_damage.rsi - type: Bloodstream - bloodReagent: AmmoniaBlood + bloodReagents: + reagents: + - ReagentId: AmmoniaBlood + Quantity: 1 - type: MeleeWeapon soundHit: collection: AlienClaw -- 2.52.0