Merge pull request #3424 from deltanedas/surgery-cleanup-2-ops

surgery dirtiness cleanup 2: judgement day
This commit is contained in:
deltanedas 2025-04-12 15:52:21 +01:00 committed by GitHub
parent 93440a50e1
commit 776fa6822b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 53 additions and 47 deletions

View File

@ -6,9 +6,9 @@ using Robust.Shared.Containers;
namespace Content.Client._DV.Surgery;
/// <summary>
/// This gets the examine tooltip and sanitize verb predicted on the client so there's no pop-in after latency
/// This shows the item status for dirty surgery tools.
/// </summary>
public sealed class SurgeryCleanTooltipSystem : EntitySystem
public sealed class SurgeryCleanStatusSystem : EntitySystem
{
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;

View File

@ -11,10 +11,12 @@ using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Eye.Blinding.Systems;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared._DV.Surgery; // DeltaV: expanded anesthesia
using Content.Shared.FixedPoint; // DeltaV: surgery cross contamination
using Content.Shared.Forensics.Components; // DeltaV: surgery cross contamination
using Content.Shared.Damage.Prototypes; // DeltaV: surgery cross contamination
// Begin DeltaV Additions
using Content.Shared._DV.Surgery;
using Content.Shared.FixedPoint;
using Content.Shared.Forensics.Components;
using Content.Shared.Damage.Prototypes;
// End DeltaV Additions
using Content.Shared._Shitmed.Medical.Surgery;
using Content.Shared._Shitmed.Medical.Surgery.Conditions;
using Content.Shared._Shitmed.Medical.Surgery.Effects.Step;
@ -44,7 +46,9 @@ public sealed class SurgerySystem : SharedSurgerySystem
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly RottingSystem _rot = default!;
[Dependency] private readonly BlindableSystem _blindableSystem = default!;
[Dependency] private readonly InventorySystem _inventory = default!; // DeltaV: surgery cross contamination
[Dependency] private readonly InventorySystem _inventory = default!; // DeltaV - surgery cross contamination
private readonly HashSet<string> _dirtyDnas = new(); // DeltaV
public override void Initialize()
{
@ -52,11 +56,11 @@ public sealed class SurgerySystem : SharedSurgerySystem
SubscribeLocalEvent<SurgeryToolComponent, GetVerbsEvent<UtilityVerb>>(OnUtilityVerb);
SubscribeLocalEvent<SurgeryTargetComponent, SurgeryStepDamageEvent>(OnSurgeryStepDamage);
SubscribeLocalEvent<SurgeryTargetComponent, SurgeryDirtinessEvent>(OnSurgerySanitation); // DeltaV: surgery cross contamination
SubscribeLocalEvent<SurgeryContaminableComponent, SurgeryDirtinessEvent>(OnSurgeryDirtiness); // DeltaV
// You might be wondering "why aren't we using StepEvent for these two?" reason being that StepEvent fires off regardless of success on the previous functions
// so this would heal entities even if you had a used or incorrect organ.
SubscribeLocalEvent<SurgerySpecialDamageChangeEffectComponent, SurgeryStepDamageChangeEvent>(OnSurgerySpecialDamageChange);
SubscribeLocalEvent<SurgeryDamageChangeEffectComponent, SurgeryStepEvent>(OnSurgeryDamageChange); // DeltaV: Use SurgeryStepEvent so steps can actually damage the patient
SubscribeLocalEvent<SurgeryDamageChangeEffectComponent, SurgeryStepEvent>(OnSurgeryDamageChange); // DeltaV - Use SurgeryStepEvent so steps can actually damage the patient
SubscribeLocalEvent<SurgeryStepEmoteEffectComponent, SurgeryStepEvent>(OnStepScreamComplete);
SubscribeLocalEvent<SurgeryStepSpawnEffectComponent, SurgeryStepEvent>(OnStepSpawnComplete);
}
@ -147,44 +151,43 @@ public sealed class SurgerySystem : SharedSurgerySystem
private void OnSurgeryStepDamage(Entity<SurgeryTargetComponent> ent, ref SurgeryStepDamageEvent args) =>
SetDamage(args.Body, args.Damage, args.PartMultiplier, args.User, args.Part);
// Begin DeltaV: surgery cross contamination
// Begin DeltaV Additions - surgery cross contamination
public FixedPoint2 TotalDirtiness(EntityUid user, List<EntityUid> tools, Entity<DnaComponent, SurgeryContaminableComponent> target)
{
var total = FixedPoint2.Zero;
var dnas = new HashSet<string>();
_dirtyDnas.Clear();
// TODO: make this use event(s)
if (HasComp<SurgerySelfDirtyComponent>(user))
{
total += _clean.Dirtiness(user);
dnas.UnionWith(_clean.CrossContaminants(user));
_dirtyDnas.UnionWith(_clean.CrossContaminants(user));
}
else
{
if (_inventory.TryGetSlotEntity(user, "gloves", out var glovesEntity))
{
total += _clean.Dirtiness(glovesEntity.Value);
dnas.UnionWith(_clean.CrossContaminants(glovesEntity.Value));
_dirtyDnas.UnionWith(_clean.CrossContaminants(glovesEntity.Value));
}
foreach (var tool in tools)
{
total += _clean.Dirtiness(tool);
dnas.UnionWith(_clean.CrossContaminants(tool));
_dirtyDnas.UnionWith(_clean.CrossContaminants(tool));
}
}
if (target.Comp1.DNA is {} dna)
dnas.Remove(dna);
_dirtyDnas.Remove(dna);
return total + dnas.Count * target.Comp2.CrossContaminationDirtinessLevel;
return total + _dirtyDnas.Count * target.Comp2.CrossContaminationDirtinessLevel;
}
public FixedPoint2 DamageToBeDealt(Entity<SurgeryContaminableComponent> ent, FixedPoint2 dirtiness)
{
if (ent.Comp.DirtinessThreshold > dirtiness)
{
return 0;
}
var exceedsAmount = (dirtiness - ent.Comp.DirtinessThreshold).Float();
var additionalDamage = (1f / ent.Comp.InverseDamageCoefficient.Float()) * (exceedsAmount * exceedsAmount);
@ -192,21 +195,18 @@ public sealed class SurgerySystem : SharedSurgerySystem
return FixedPoint2.Min(FixedPoint2.New(additionalDamage) + ent.Comp.BaseDamage, ent.Comp.ToxinStepLimit);
}
private void OnSurgerySanitation(Entity<SurgeryTargetComponent> target, ref Content.Shared._DV.Surgery.SurgeryDirtinessEvent args)
private void OnSurgeryDirtiness(Entity<SurgeryContaminableComponent> ent, ref SurgeryDirtinessEvent args)
{
if (!TryComp<SurgeryContaminableComponent>(target.Owner, out var contaminableComp))
if (!TryComp<DnaComponent>(ent, out var dnaComp))
return;
if (!TryComp<DnaComponent>(target.Owner, out var dnaComp))
return;
var dirtiness = TotalDirtiness(args.User, args.Tools, new(target.Owner, dnaComp, contaminableComp));
var damage = DamageToBeDealt(new(target.Owner, contaminableComp), dirtiness);
var dirtiness = TotalDirtiness(args.User, args.Tools, (ent, dnaComp, ent));
var damage = DamageToBeDealt(ent, dirtiness);
if (damage > 0)
{
var sepsis = new DamageSpecifier(_prototypes.Index<DamageTypePrototype>("Poison"), damage);
SetDamage(target.Owner, sepsis, 0.5f, args.User, args.Part);
var sepsis = new DamageSpecifier(_prototypes.Index(ent.Comp.SepsisDamageType), damage);
SetDamage(ent, sepsis, 0.5f, args.User, args.Part);
}
if (!TryComp<SurgeryStepDirtinessComponent>(args.Step, out var surgicalStepDirtiness))
@ -226,16 +226,21 @@ public sealed class SurgerySystem : SharedSurgerySystem
}
foreach (var tool in args.Tools)
{
// don't dirty random non-surgery items like soap or clothes
// ideally Tools would only contain the (highest quality) tool used for the step
if (!HasComp<SurgeryToolComponent>(tool))
continue;
_clean.AddDirt(tool, surgicalStepDirtiness.ToolDirtiness);
_clean.AddDna(tool, dnaComp.DNA);
}
}
// End DeltaV: surgery cross contamination
// End DeltaV Additions
private void OnSurgeryDamageChange(Entity<SurgeryDamageChangeEffectComponent> ent, ref SurgeryStepEvent args) // DeltaV
{
var damageChange = ent.Comp.Damage;
if (HasComp<AnesthesiaComponent>(args.Body) || _mobState.IsDead(args.Body)) // DeltaV: anesthesia
if (HasComp<AnesthesiaComponent>(args.Body) || _mobState.IsDead(args.Body)) // DeltaV - anesthesia
damageChange = damageChange * ent.Comp.SleepModifier;
SetDamage(args.Body, damageChange, 0.5f, args.User, args.Part);
@ -243,11 +248,11 @@ public sealed class SurgerySystem : SharedSurgerySystem
private void OnSurgerySpecialDamageChange(Entity<SurgerySpecialDamageChangeEffectComponent> ent, ref SurgeryStepDamageChangeEvent args)
{
// Begin DeltaV - this shit was killed
/* DeltaV - this shit was killed
// Im killing this shit soon too, inshallah.
// if (ent.Comp.DamageType == "Rot")
// _rot.ReduceAccumulator(args.Body, TimeSpan.FromSeconds(2147483648)); // BEHOLD, SHITCODE THAT I JUST COPY PASTED. I'll redo it at some point, pinky swear :)
// End DeltaV - this shit was killed
if (ent.Comp.DamageType == "Rot")
_rot.ReduceAccumulator(args.Body, TimeSpan.FromSeconds(2147483648)); // BEHOLD, SHITCODE THAT I JUST COPY PASTED. I'll redo it at some point, pinky swear :)
*/
/*else if (ent.Comp.DamageType == "Eye"
&& TryComp(ent, out BlindableComponent? blindComp)
&& blindComp.EyeDamage > 0)
@ -256,7 +261,7 @@ public sealed class SurgerySystem : SharedSurgerySystem
private void OnStepScreamComplete(Entity<SurgeryStepEmoteEffectComponent> ent, ref SurgeryStepEvent args)
{
if (HasComp<AnesthesiaComponent>(args.Body)) // DeltaV: anesthesia
if (HasComp<AnesthesiaComponent>(args.Body)) // DeltaV
return;
_chat.TryEmoteWithChat(args.Body, ent.Comp.Emote);

View File

@ -49,21 +49,13 @@ public sealed class SurgeryCleanSystem : EntitySystem
args.Verbs.Add(verb);
}
// no separate examine for DNAs as they are both cleaned at the same time.
private void OnDirtyExamined(Entity<SurgeryDirtinessComponent> ent, ref ExaminedEvent args)
{
var stage = (int)Math.Ceiling(ent.Comp.Dirtiness.Double() / 20.0);
// no separate examine for DNAs as they are both cleaned at the same time.
var description = stage switch {
0 => "surgery-cleanliness-0",
1 => "surgery-cleanliness-1",
2 => "surgery-cleanliness-2",
3 => "surgery-cleanliness-3",
4 => "surgery-cleanliness-4",
_ => "surgery-cleanliness-5",
};
args.PushMarkup(Loc.GetString(description));
// dirtiness -> stage ranges from 0.0 -> 0 to 100.0 -> 5
args.PushMarkup(Loc.GetString($"surgery-cleanliness-{stage}"));
}
public bool RequiresCleaning(EntityUid target)

View File

@ -1,11 +1,14 @@
using Content.Shared._Shitmed.Medical.Surgery;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared._DV.Surgery;
/// <summary>
/// Component that indicates how an entity should respond to unsanitary surgery conditions
/// Component that indicates how an entity should respond to unsanitary surgery conditions
/// It also causes surgery tools to become dirty/cross contaminated when operated on.
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
public sealed partial class SurgeryContaminableComponent : Component
@ -22,6 +25,12 @@ public sealed partial class SurgeryContaminableComponent : Component
[DataField]
public FixedPoint2 DirtinessThreshold = 50.0;
/// <summary>
/// The damage type to deal for sepsis.
/// </summary>
[DataField]
public ProtoId<DamageTypePrototype> SepsisDamageType = "Poison";
/// <summary>
/// The base amount of toxin damage to deal above the threshold
/// </summary>

View File

@ -229,7 +229,6 @@
- type: LayingDown # WD EDIT
- type: Targeting # Shitmed Change
- type: SurgeryTarget # Shitmed Change
- type: SurgeryContaminable # DeltaV - surgery cross contamination
- type: entity
save: false

View File

@ -118,6 +118,7 @@
- type: LightningTarget
priority: 2
lightningExplode: false
- type: SurgeryContaminable # DeltaV - surgery cross contamination
# Used for mobs that can enter combat mode and can attack.
- type: entity