[Bugfix/Optimization] Metabolize Foreign Blood (#41892)

* Metabolize foreign blood

* fix

* misc

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
This commit is contained in:
Princess Cheeseballs
2025-12-18 00:48:30 -08:00
committed by GitHub
parent 13ddce2a09
commit c93fea42dd
6 changed files with 39 additions and 17 deletions

View File

@@ -30,12 +30,12 @@ public sealed class BloodstreamSystem : SharedBloodstreamSystem
bloodSolution.MaxVolume = entity.Comp.BloodReferenceSolution.Volume * entity.Comp.MaxVolumeModifier;
tempSolution.MaxVolume = entity.Comp.BleedPuddleThreshold * 4; // give some leeway, for chemstream as well
entity.Comp.BloodReferenceSolution.SetReagentData(GetEntityBloodData((entity, entity.Comp)));
// 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.BloodReferenceSolution.Clone();
solution.ScaleTo(entity.Comp.BloodReferenceSolution.Volume - bloodSolution.Volume);
solution.SetReagentData(GetEntityBloodData(entity.Owner));
bloodSolution.AddSolution(solution, PrototypeManager);
}
@@ -44,11 +44,14 @@ public sealed class BloodstreamSystem : SharedBloodstreamSystem
{
if (SolutionContainer.ResolveSolution(entity.Owner, entity.Comp.BloodSolutionName, ref entity.Comp.BloodSolution, out var bloodSolution))
{
var data = NewEntityBloodData(entity);
entity.Comp.BloodReferenceSolution.SetReagentData(data);
foreach (var reagent in bloodSolution.Contents)
{
List<ReagentData> reagentData = reagent.Reagent.EnsureReagentData();
reagentData.RemoveAll(x => x is DnaData);
reagentData.AddRange(GetEntityBloodData(entity.Owner));
reagentData.AddRange(data);
}
}
else

View File

@@ -16,7 +16,6 @@ using Content.Shared.EntityEffects.Effects.Body;
using Content.Shared.EntityEffects.Effects.Solution;
using Content.Shared.FixedPoint;
using Content.Shared.Mobs.Systems;
using Content.Shared.Random.Helpers;
using Robust.Shared.Collections;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
@@ -138,8 +137,7 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
var list = solution.Contents.ToList();
// Collecting blood reagent for filtering
var bloodList = new List<string>();
var ev = new MetabolismExclusionEvent(bloodList);
var ev = new MetabolismExclusionEvent();
RaiseLocalEvent(solutionEntityUid.Value, ref ev);
// randomize the reagent list so we don't have any weird quirks
@@ -155,7 +153,7 @@ public sealed class MetabolizerSystem : SharedMetabolizerSystem
continue;
// Skip blood reagents
if (bloodList.Contains(reagent.Prototype))
if (ev.Reagents.Contains(reagent))
continue;
var mostToRemove = FixedPoint2.Zero;

View File

@@ -1,6 +1,7 @@
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;
@@ -137,9 +138,9 @@ public sealed partial class BloodstreamComponent : Component
// TODO probably damage bleed thresholds.
/// <summary>
/// Modifier applied to <see cref="BloodReferenceSolution.Volume"/> to determine maximum volume for bloodstream.
/// Modifier applied to <see cref="BloodstreamComponent.BloodReferenceSolution.Volume"/> to determine maximum volume for bloodstream.
/// </summary>
[DataField]
[DataField, AutoNetworkedField]
public float MaxVolumeModifier = 2f;
/// <summary>
@@ -151,6 +152,13 @@ public sealed partial class BloodstreamComponent : Component
[DataField, AutoNetworkedField]
public Solution BloodReferenceSolution = new([new("Blood", 300)]);
/// <summary>
/// Caches the blood data of an entity.
/// This is modified by DNA on init so it's not savable.
/// </summary>
[ViewVariables(VVAccess.ReadOnly)]
public List<ReagentData>? BloodData;
/// <summary>
/// Name/Key that <see cref="BloodSolution"/> is indexed by.
/// </summary>

View File

@@ -1,3 +1,5 @@
using Content.Shared.Chemistry.Reagent;
namespace Content.Shared.Body.Events;
/// <summary>
@@ -5,4 +7,7 @@ namespace Content.Shared.Body.Events;
/// blood like reagents for metabolism to skip.
/// </summary>
[ByRefEvent]
public readonly record struct MetabolismExclusionEvent(List<string> ReagentList);
public readonly record struct MetabolismExclusionEvent()
{
public readonly List<ReagentId> Reagents = [];
}

View File

@@ -296,9 +296,9 @@ public abstract class SharedBloodstreamSystem : EntitySystem
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)
foreach (var (reagent, _) in ent.Comp.BloodReferenceSolution)
{
args.ReagentList.Add(reagentId.Prototype);
args.Reagents.Add(reagent);
}
}
@@ -424,8 +424,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem
if (error > 0)
{
error = FixedPoint2.Min(error, adjustedAmount);
var reagentToAdd = new ReagentId(referenceReagent.Prototype, GetEntityBloodData(ent));
bloodSolution.AddReagent(reagentToAdd, error);
bloodSolution.AddReagent(referenceReagent, error);
}
else if (error < 0)
{
@@ -561,14 +560,24 @@ public abstract class SharedBloodstreamSystem : EntitySystem
var solution = ent.Comp.BloodReferenceSolution.Clone();
solution.ScaleSolution(currentVolume / solution.Volume);
solution.SetReagentData(GetEntityBloodData(ent));
SolutionContainer.AddSolution(ent.Comp.BloodSolution.Value, solution);
}
/// <summary>
/// Get the reagent data for blood that a specific entity should have.
/// </summary>
public List<ReagentData> GetEntityBloodData(EntityUid uid)
public List<ReagentData> GetEntityBloodData(Entity<BloodstreamComponent?> entity)
{
if (!Resolve(entity, ref entity.Comp))
return NewEntityBloodData(entity);
return entity.Comp.BloodData ?? NewEntityBloodData(entity);
}
/// <summary>
/// Gets new blood data for this entity and caches it in <see cref="BloodstreamComponent.BloodData"/>
/// </summary>
protected List<ReagentData> NewEntityBloodData(EntityUid uid)
{
var bloodData = new List<ReagentData>();
var dnaData = new DnaData();
@@ -579,7 +588,6 @@ public abstract class SharedBloodstreamSystem : EntitySystem
dnaData.DNA = Loc.GetString("forensics-dna-unknown");
bloodData.Add(dnaData);
return bloodData;
}
}

View File

@@ -121,7 +121,7 @@ public sealed class VomitSystem : EntitySystem
}
// Makes a vomit solution the size of 90% of the chemicals removed from the chemstream
solution.AddReagent(new ReagentId(VomitPrototype, _bloodstream.GetEntityBloodData(uid)), vomitAmount);
solution.AddReagent(new ReagentId(VomitPrototype, _bloodstream.GetEntityBloodData((uid, bloodStream))), vomitAmount);
}
if (_puddle.TrySpillAt(uid, solution, out var puddle, false))