Better DNA forensics & ReagentData (#26699)
* Added the ability for blood to track DNA using ReagentData; Forensic Scanner now accounts for solution DNA, non-DNA holders have "Unknown DNA" * Removes touch DNA for puddles, adds DNA to vomit * DNA now leaves traces in containers and those marked without don't show DNA on scan (except for puddles), gibbed parts have DNA * Fix stupid metamorphic glass bug grrr * Removed SpillableComponent since DnaSubstanceTraceComponent is used instead * Removes data field from maps, adds DNA tracking for some missed items * Give default value, fix missing values. * Fixes recipe bug * Review changes * Make the Data list into a nullable type * Revert map changes * Move gibbed unknown DNA to forensicssystem
This commit is contained in:
@@ -8,10 +8,12 @@ using Content.Shared.Alert;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.Drunk;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Forensics;
|
||||
using Content.Shared.HealthExaminable;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Popups;
|
||||
@@ -54,6 +56,7 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
SubscribeLocalEvent<BloodstreamComponent, ReactionAttemptEvent>(OnReactionAttempt);
|
||||
SubscribeLocalEvent<BloodstreamComponent, SolutionRelayEvent<ReactionAttemptEvent>>(OnReactionAttempt);
|
||||
SubscribeLocalEvent<BloodstreamComponent, RejuvenateEvent>(OnRejuvenate);
|
||||
SubscribeLocalEvent<BloodstreamComponent, GenerateDnaEvent>(OnDnaGenerated);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<BloodstreamComponent> ent, ref MapInitEvent args)
|
||||
@@ -183,8 +186,18 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
bloodSolution.MaxVolume = entity.Comp.BloodMaxVolume;
|
||||
tempSolution.MaxVolume = entity.Comp.BleedPuddleThreshold * 4; // give some leeway, for chemstream as well
|
||||
|
||||
// Ensure blood that should have DNA has it; must be run here, in case DnaComponent has not yet been initialized
|
||||
|
||||
if (TryComp<DnaComponent>(entity.Owner, out var donorComp) && donorComp.DNA == String.Empty)
|
||||
{
|
||||
donorComp.DNA = _forensicsSystem.GenerateDNA();
|
||||
|
||||
var ev = new GenerateDnaEvent { Owner = entity.Owner, DNA = donorComp.DNA };
|
||||
RaiseLocalEvent(entity.Owner, ref ev);
|
||||
}
|
||||
|
||||
// Fill blood solution with BLOOD
|
||||
bloodSolution.AddReagent(entity.Comp.BloodReagent, entity.Comp.BloodMaxVolume - bloodSolution.Volume);
|
||||
bloodSolution.AddReagent(new ReagentId(entity.Comp.BloodReagent, GetEntityBloodData(entity.Owner)), entity.Comp.BloodMaxVolume - bloodSolution.Volume);
|
||||
}
|
||||
|
||||
private void OnDamageChanged(Entity<BloodstreamComponent> ent, ref DamageChangedEvent args)
|
||||
@@ -349,7 +362,7 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
}
|
||||
|
||||
if (amount >= 0)
|
||||
return _solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, amount, out _);
|
||||
return _solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, amount, null, GetEntityBloodData(uid));
|
||||
|
||||
// Removal is more involved,
|
||||
// since we also wanna handle moving it to the temporary solution
|
||||
@@ -370,10 +383,7 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
tempSolution.AddSolution(temp, _prototypeManager);
|
||||
}
|
||||
|
||||
if (_puddleSystem.TrySpillAt(uid, tempSolution, out var puddleUid, sound: false))
|
||||
{
|
||||
_forensicsSystem.TransferDna(puddleUid, uid, canDnaBeCleaned: false);
|
||||
}
|
||||
_puddleSystem.TrySpillAt(uid, tempSolution, out var puddleUid, sound: false);
|
||||
|
||||
tempSolution.RemoveAllSolution();
|
||||
}
|
||||
@@ -436,10 +446,7 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
_solutionContainerSystem.RemoveAllSolution(component.TemporarySolution.Value);
|
||||
}
|
||||
|
||||
if (_puddleSystem.TrySpillAt(uid, tempSol, out var puddleUid))
|
||||
{
|
||||
_forensicsSystem.TransferDna(puddleUid, uid, canDnaBeCleaned: false);
|
||||
}
|
||||
_puddleSystem.TrySpillAt(uid, tempSol, out var puddleUid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -464,6 +471,40 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
component.BloodReagent = reagent;
|
||||
|
||||
if (currentVolume > 0)
|
||||
_solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, currentVolume, out _);
|
||||
_solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, currentVolume, null, GetEntityBloodData(uid));
|
||||
}
|
||||
|
||||
private void OnDnaGenerated(Entity<BloodstreamComponent> entity, ref GenerateDnaEvent args)
|
||||
{
|
||||
if (_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.BloodSolutionName, ref entity.Comp.BloodSolution, out var bloodSolution))
|
||||
{
|
||||
foreach (var reagent in bloodSolution.Contents)
|
||||
{
|
||||
List<ReagentData> reagentData = reagent.Reagent.EnsureReagentData();
|
||||
reagentData.RemoveAll(x => x is DnaData);
|
||||
reagentData.AddRange(GetEntityBloodData(entity.Owner));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the reagent data for blood that a specific entity should have.
|
||||
/// </summary>
|
||||
public List<ReagentData> GetEntityBloodData(EntityUid uid)
|
||||
{
|
||||
var bloodData = new List<ReagentData>();
|
||||
var dnaData = new DnaData();
|
||||
|
||||
if (TryComp<DnaComponent>(uid, out var donorComp))
|
||||
{
|
||||
dnaData.DNA = donorComp.DNA;
|
||||
} else
|
||||
{
|
||||
dnaData.DNA = Loc.GetString("forensics-dna-unknown");
|
||||
}
|
||||
|
||||
bloodData.Add(dnaData);
|
||||
|
||||
return bloodData;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user