From 5eeac512a1f495297d05510071a92890220e584b Mon Sep 17 00:00:00 2001 From: gluesniffler Date: Sun, 17 Nov 2024 15:36:45 -0400 Subject: [PATCH] We're swaying on horseback. --- Content.Server/Body/Systems/BrainSystem.cs | 7 +++- Content.Server/Body/Systems/HeartSystem.cs | 38 +++++++++++++++++++ .../Body/Systems/RespiratorSystem.cs | 4 +- .../DelayedDeath/DelayedDeathComponent.cs | 16 ++++++++ .../DelayedDeath/DelayedDeathSystem.cs | 31 +++++++++++++++ .../Medical/Surgery/SurgerySystem.cs | 38 +++++++------------ .../Body/Organ/DebrainedComponent.cs | 1 - Content.Shared/Body/Organ/OrganComponent.cs | 6 +++ .../Body/Systems/SharedBodySystem.Body.cs | 1 + .../Body/Systems/SharedBodySystem.Organs.cs | 10 ++++- .../Surgery/SharedSurgerySystem.Steps.cs | 6 +++ .../Surgery/SurgeryStepDamageChangeEvent.cs | 9 +++++ .../Prototypes/Body/Organs/Animal/slimes.yml | 2 +- Resources/Prototypes/Body/Organs/diona.yml | 3 +- .../Prototypes/Entities/Mobs/NPCs/slimes.yml | 2 +- 15 files changed, 140 insertions(+), 34 deletions(-) create mode 100644 Content.Server/Body/Systems/HeartSystem.cs create mode 100644 Content.Server/DelayedDeath/DelayedDeathComponent.cs create mode 100644 Content.Server/DelayedDeath/DelayedDeathSystem.cs create mode 100644 Content.Shared/Medical/Surgery/SurgeryStepDamageChangeEvent.cs diff --git a/Content.Server/Body/Systems/BrainSystem.cs b/Content.Server/Body/Systems/BrainSystem.cs index ae14da0e817..aac7fa353ad 100644 --- a/Content.Server/Body/Systems/BrainSystem.cs +++ b/Content.Server/Body/Systems/BrainSystem.cs @@ -1,8 +1,10 @@ using Content.Server.Body.Components; using Content.Server.Ghost.Components; using Content.Shared.Body.Components; +using Content.Shared.Body.Systems; using Content.Shared.Body.Events; using Content.Shared.Body.Organ; +using Content.Server.DelayedDeath; using Content.Shared.Mind; using Content.Shared.Mind.Components; using Content.Shared.Pointing; @@ -12,7 +14,7 @@ namespace Content.Server.Body.Systems public sealed class BrainSystem : EntitySystem { [Dependency] private readonly SharedMindSystem _mindSystem = default!; - + [Dependency] private readonly SharedBodySystem _bodySystem = default!; // Shitmed-Start public override void Initialize() { @@ -30,6 +32,7 @@ private void HandleRemoval(EntityUid uid, BrainComponent _, ref OrganRemovedFrom // Prevents revival, should kill the user within a given timespan too. EnsureComp(args.OldBody); + EnsureComp(args.OldBody); HandleMind(uid, args.OldBody); } private void HandleAddition(EntityUid uid, BrainComponent _, ref OrganAddedToBodyEvent args) @@ -38,6 +41,8 @@ private void HandleAddition(EntityUid uid, BrainComponent _, ref OrganAddedToBod return; RemComp(args.Body); + if (_bodySystem.TryGetBodyOrganComponents(args.Body, out var _)) + RemComp(args.Body); HandleMind(args.Body, uid); } // Shitmed-End diff --git a/Content.Server/Body/Systems/HeartSystem.cs b/Content.Server/Body/Systems/HeartSystem.cs new file mode 100644 index 00000000000..7926c833e3a --- /dev/null +++ b/Content.Server/Body/Systems/HeartSystem.cs @@ -0,0 +1,38 @@ +using Content.Shared.Body.Components; +using Content.Shared.Body.Systems; +using Content.Shared.Body.Events; +using Content.Shared.Body.Organ; +using Content.Server.DelayedDeath; +using Content.Server.Body.Components; +namespace Content.Server.Body.Systems; + +public sealed class HeartSystem : EntitySystem +{ + [Dependency] private readonly SharedBodySystem _bodySystem = default!; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(HandleAddition); + SubscribeLocalEvent(HandleRemoval); + } + + private void HandleRemoval(EntityUid uid, HeartComponent _, ref OrganRemovedFromBodyEvent args) + { + if (TerminatingOrDeleted(uid) || TerminatingOrDeleted(args.OldBody)) + return; + + // TODO: Add some form of very violent bleeding effect. + EnsureComp(args.OldBody); + } + + private void HandleAddition(EntityUid uid, HeartComponent _, ref OrganAddedToBodyEvent args) + { + if (TerminatingOrDeleted(uid) || TerminatingOrDeleted(args.Body)) + return; + + if (_bodySystem.TryGetBodyOrganComponents(args.Body, out var _)) + RemComp(args.Body); + } + // Shitmed-End +} \ No newline at end of file diff --git a/Content.Server/Body/Systems/RespiratorSystem.cs b/Content.Server/Body/Systems/RespiratorSystem.cs index 8b2b19a2ac0..26333938ab2 100644 --- a/Content.Server/Body/Systems/RespiratorSystem.cs +++ b/Content.Server/Body/Systems/RespiratorSystem.cs @@ -72,7 +72,7 @@ public override void Update(float frameTime) UpdateSaturation(uid, -(float) respirator.UpdateInterval.TotalSeconds, respirator); - if (!_mobState.IsIncapacitated(uid) || HasComp(uid)) // Shitmed: cannot breathe in crit or when no brain. + if (!_mobState.IsIncapacitated(uid) && !HasComp(uid)) // Shitmed: cannot breathe in crit or when no brain. { switch (respirator.Status) { @@ -185,7 +185,7 @@ private void TakeSuffocationDamage(Entity ent) RaiseLocalEvent(ent, new MoodEffectEvent("Suffocating")); } - _damageableSys.TryChangeDamage(ent, ent.Comp.Damage, interruptsDoAfters: false); + _damageableSys.TryChangeDamage(ent, HasComp(ent) ? ent.Comp.Damage * 4.5f : ent.Comp.Damage, interruptsDoAfters: false); } private void StopSuffocation(Entity ent) diff --git a/Content.Server/DelayedDeath/DelayedDeathComponent.cs b/Content.Server/DelayedDeath/DelayedDeathComponent.cs new file mode 100644 index 00000000000..2a681cde672 --- /dev/null +++ b/Content.Server/DelayedDeath/DelayedDeathComponent.cs @@ -0,0 +1,16 @@ +namespace Content.Server.DelayedDeath; + +[RegisterComponent] +public sealed partial class DelayedDeathComponent : Component +{ + /// + /// How long it takes to kill the entity. + /// + [DataField] + public float DeathTime = 60; + + /// + /// How long it has been since the delayed death timer started. + /// + public float DeathTimer; +} \ No newline at end of file diff --git a/Content.Server/DelayedDeath/DelayedDeathSystem.cs b/Content.Server/DelayedDeath/DelayedDeathSystem.cs new file mode 100644 index 00000000000..0f7c33dfcc5 --- /dev/null +++ b/Content.Server/DelayedDeath/DelayedDeathSystem.cs @@ -0,0 +1,31 @@ +using Content.Shared.Body.Organ; +using Content.Shared.Body.Events; +using Content.Shared.Damage; +using Content.Shared.Damage.Prototypes; +using Content.Shared.Mobs.Systems; +using Robust.Shared.Timing; +using Robust.Shared.Prototypes; +namespace Content.Server.DelayedDeath; + +public partial class DelayedDeathSystem : EntitySystem +{ + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly IPrototypeManager _prototypes = default!; + public override void Update(float frameTime) + { + base.Update(frameTime); + + using var query = EntityQueryEnumerator(); + while (query.MoveNext(out var ent, out var component)) + { + component.DeathTimer += frameTime; + + if (component.DeathTimer >= component.DeathTime && !_mobState.IsDead(ent)) + { + var damage = new DamageSpecifier(_prototypes.Index("Bloodloss"), 150); + _damageable.TryChangeDamage(ent, damage, partMultiplier: 0f); + } + } + } +} \ No newline at end of file diff --git a/Content.Server/Medical/Surgery/SurgerySystem.cs b/Content.Server/Medical/Surgery/SurgerySystem.cs index 615166390a3..c5c99ac6f89 100644 --- a/Content.Server/Medical/Surgery/SurgerySystem.cs +++ b/Content.Server/Medical/Surgery/SurgerySystem.cs @@ -48,8 +48,10 @@ public override void Initialize() SubscribeLocalEvent(OnToolAfterInteract); SubscribeLocalEvent(OnSurgeryStepDamage); - SubscribeLocalEvent(OnSurgeryDamageChange); - SubscribeLocalEvent(OnSurgerySpecialDamageChange); + // 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(OnSurgerySpecialDamageChange); + SubscribeLocalEvent(OnSurgeryDamageChange); SubscribeLocalEvent(OnStepScreamComplete); SubscribeLocalEvent(OnStepSpawnComplete); SubscribeLocalEvent(OnPrototypesReloaded); @@ -130,15 +132,18 @@ private void OnToolAfterInteract(Entity ent, ref AfterInte private void OnSurgeryStepDamage(Entity ent, ref SurgeryStepDamageEvent args) => SetDamage(args.Body, args.Damage, args.PartMultiplier, args.User, args.Part); - private void OnSurgeryDamageChange(Entity ent, ref SurgeryStepEvent args) + private void OnSurgerySpecialDamageChange(Entity ent, ref SurgeryStepDamageChangeEvent args) { - // This unintentionally punishes the user if they have an organ in another hand that is already used. - // Imo surgery shouldn't let you automatically pick tools on both hands anyway, it should only use the one you've got in your selected hand. - if (ent.Comp.IsConsumable - && args.Tools.Where(tool => TryComp(tool, out var organComp) - && !_body.TrySetOrganUsed(tool, true, organComp)).Any()) - return; + 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) + _blindableSystem.AdjustEyeDamage((args.Body, blindComp), -blindComp!.EyeDamage); + } + private void OnSurgeryDamageChange(Entity ent, ref SurgeryStepDamageChangeEvent args) + { var damageChange = ent.Comp.Damage; if (HasComp(args.Body)) damageChange = damageChange * ent.Comp.SleepModifier; @@ -146,21 +151,6 @@ private void OnSurgeryDamageChange(Entity en SetDamage(args.Body, damageChange, 0.5f, args.User, args.Part); } - private void OnSurgerySpecialDamageChange(Entity ent, ref SurgeryStepEvent args) - { - if (ent.Comp.IsConsumable - && args.Tools.Where(tool => TryComp(tool, out var organComp) - && !_body.TrySetOrganUsed(tool, true, organComp)).Any()) - return; - - 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(args.Body, out BlindableComponent? blindComp) - && blindComp.EyeDamage > 0) - _blindableSystem.AdjustEyeDamage((args.Body, blindComp), -blindComp!.EyeDamage); - } - private void OnStepScreamComplete(Entity ent, ref SurgeryStepEvent args) { if (HasComp(args.Body)) diff --git a/Content.Shared/Body/Organ/DebrainedComponent.cs b/Content.Shared/Body/Organ/DebrainedComponent.cs index 12574bddcc3..c43f151cdef 100644 --- a/Content.Shared/Body/Organ/DebrainedComponent.cs +++ b/Content.Shared/Body/Organ/DebrainedComponent.cs @@ -4,4 +4,3 @@ namespace Content.Shared.Body.Organ; [RegisterComponent] public sealed partial class DebrainedComponent : Component; -// TODO: Add a timer to kill the entity if they don't get a new brain in time. diff --git a/Content.Shared/Body/Organ/OrganComponent.cs b/Content.Shared/Body/Organ/OrganComponent.cs index c7212cbec31..f9037641fc1 100644 --- a/Content.Shared/Body/Organ/OrganComponent.cs +++ b/Content.Shared/Body/Organ/OrganComponent.cs @@ -15,6 +15,12 @@ public sealed partial class OrganComponent : Component, ISurgeryToolComponent [DataField, AutoNetworkedField] public EntityUid? Body; + /// + /// Relevant body this organ originally belonged to. + /// + [DataField, AutoNetworkedField] + public EntityUid? OriginalBody; + /// /// Shitcodey solution to not being able to know what name corresponds to each organ's slot ID /// without referencing the prototype or hardcoding. diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs index db7a625fbb9..9dbe3936e76 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Body.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Body.cs @@ -375,6 +375,7 @@ public virtual HashSet GibPart( if (IsPartRoot(bodyEnt, partId, part: part)) return gibs; + ChangeSlotState((partId, part), true); RemovePartChildren((partId, part), bodyEnt); foreach (var organ in GetPartOrgans(partId, part)) { diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs b/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs index e006d0feeb2..0666b6b9ec1 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Organs.cs @@ -3,6 +3,7 @@ using Content.Shared.Body.Events; using Content.Shared.Body.Organ; using Content.Shared.Body.Part; +using Content.Shared.Damage; using Robust.Shared.Containers; namespace Content.Shared.Body.Systems; @@ -36,8 +37,13 @@ private void RemoveOrgan(Entity organEnt, EntityUid parentPartUi { var removedInBodyEv = new OrganRemovedFromBodyEvent(bodyUid, parentPartUid); RaiseLocalEvent(organEnt, ref removedInBodyEv); + organEnt.Comp.OriginalBody = bodyUid; } + if (TryComp(parentPartUid, out DamageableComponent? damageable) + && damageable.TotalDamage > 200) + TrySetOrganUsed(organEnt, true, organEnt.Comp); + organEnt.Comp.Body = null; Dirty(organEnt, organEnt.Comp); } @@ -216,10 +222,10 @@ public bool TryGetBodyOrganComponents( public bool TrySetOrganUsed(EntityUid organId, bool used, OrganComponent? organ = null) { if (!Resolve(organId, ref organ) - || organ.Used == true) + || organ.Used == used) return false; - organ.Used = true; + organ.Used = used; Dirty(organId, organ); return true; } diff --git a/Content.Shared/Medical/Surgery/SharedSurgerySystem.Steps.cs b/Content.Shared/Medical/Surgery/SharedSurgerySystem.Steps.cs index 0686bf53095..2027c525d46 100644 --- a/Content.Shared/Medical/Surgery/SharedSurgerySystem.Steps.cs +++ b/Content.Shared/Medical/Surgery/SharedSurgerySystem.Steps.cs @@ -420,6 +420,12 @@ private void OnAddOrganStep(Entity ent, ref Surger && _body.InsertOrgan(args.Part, tool, insertedOrgan.SlotId, partComp, insertedOrgan)) { EnsureComp(tool); + if (_body.TrySetOrganUsed(tool, true, insertedOrgan) + && insertedOrgan.OriginalBody != args.Body) + { + var ev = new SurgeryStepDamageChangeEvent(args.User, args.Body, args.Part, ent); + RaiseLocalEvent(ent, ref ev); + } break; } } diff --git a/Content.Shared/Medical/Surgery/SurgeryStepDamageChangeEvent.cs b/Content.Shared/Medical/Surgery/SurgeryStepDamageChangeEvent.cs new file mode 100644 index 00000000000..e8f0a34cde3 --- /dev/null +++ b/Content.Shared/Medical/Surgery/SurgeryStepDamageChangeEvent.cs @@ -0,0 +1,9 @@ +using Content.Shared.Damage; + +namespace Content.Shared.Medical.Surgery; + +/// +/// Raised on the target entity. +/// +[ByRefEvent] +public record struct SurgeryStepDamageChangeEvent(EntityUid User, EntityUid Body, EntityUid Part, EntityUid Step); diff --git a/Resources/Prototypes/Body/Organs/Animal/slimes.yml b/Resources/Prototypes/Body/Organs/Animal/slimes.yml index fdc247f0f22..baa6674a471 100644 --- a/Resources/Prototypes/Body/Organs/Animal/slimes.yml +++ b/Resources/Prototypes/Body/Organs/Animal/slimes.yml @@ -8,9 +8,9 @@ sprite: Mobs/Species/Slime/organs.rsi state: brain-slime - type: Stomach - - type: Metabolizer - type: Organ slotId: core + - type: Metabolizer maxReagents: 3 metabolizerTypes: [ Slime ] removeEmpty: true diff --git a/Resources/Prototypes/Body/Organs/diona.yml b/Resources/Prototypes/Body/Organs/diona.yml index d4b7ccf53bd..9bfb5e6cef8 100644 --- a/Resources/Prototypes/Body/Organs/diona.yml +++ b/Resources/Prototypes/Body/Organs/diona.yml @@ -64,8 +64,7 @@ - state: eyeball-l - state: eyeball-r - type: Eyes - - type: Organ - slotId: eyes + - type: entity id: OrganDionaStomach diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml b/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml index 184e7097ee0..52d319cef63 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/slimes.yml @@ -116,7 +116,7 @@ - type: SurgeryTarget - type: UserInterface interfaces: - enum.SurgeryUIKey.key: + enum.SurgeryUIKey.Key: type: SurgeryBui - type: entity