Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Port] Surgery Fixes: Popup Walker #923

Merged
merged 10 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions Content.Server/Backmen/Body/Systems/HeartSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Content.Shared.Body.Components;
using Content.Shared.Body.Systems;
using Content.Shared.Body.Events;
using Content.Shared.Body.Organ;
using Content.Server.Backmen.DelayedDeath;
using Content.Server.Body.Components;
using Content.Shared.Backmen.Surgery.Body.Organs;

namespace Content.Server.Backmen.Body.Systems;

public sealed class HeartSystem : EntitySystem
{
[Dependency] private readonly SharedBodySystem _bodySystem = default!;
public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<HeartComponent, OrganAddedToBodyEvent>(HandleAddition);
SubscribeLocalEvent<HeartComponent, OrganRemovedFromBodyEvent>(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<DelayedDeathComponent>(args.OldBody);
}

private void HandleAddition(EntityUid uid, HeartComponent _, ref OrganAddedToBodyEvent args)
{
if (TerminatingOrDeleted(uid) || TerminatingOrDeleted(args.Body))
return;

if (_bodySystem.TryGetBodyOrganEntityComps<BrainComponent>(args.Body, out var _))
RemComp<DelayedDeathComponent>(args.Body);
}
// Shitmed-End
}
16 changes: 16 additions & 0 deletions Content.Server/Backmen/DelayedDeath/DelayedDeathComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Content.Server.Backmen.DelayedDeath;

[RegisterComponent]
public sealed partial class DelayedDeathComponent : Component
{
/// <summary>
/// How long it takes to kill the entity.
/// </summary>
[DataField]
public float DeathTime = 60;

/// <summary>
/// How long it has been since the delayed death timer started.
/// </summary>
public float DeathTimer;
}
32 changes: 32 additions & 0 deletions Content.Server/Backmen/DelayedDeath/DelayedDeathSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
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.Backmen.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<DelayedDeathComponent>();
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<DamageTypePrototype>("Bloodloss"), 150);
_damageable.TryChangeDamage(ent, damage, partMultiplier: 0f);
}
}
}
}
39 changes: 15 additions & 24 deletions Content.Server/Backmen/Surgery/SurgerySystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using Content.Shared.Backmen.Surgery.Effects.Step;
using Content.Shared.Backmen.Surgery.Tools;
using Content.Shared.Bed.Sleep;
using Content.Shared.Medical.Surgery;

namespace Content.Server.Backmen.Surgery;

Expand All @@ -43,8 +44,10 @@ public override void Initialize()

SubscribeLocalEvent<SurgeryToolComponent, AfterInteractEvent>(OnToolAfterInteract);
SubscribeLocalEvent<SurgeryTargetComponent, SurgeryStepDamageEvent>(OnSurgeryStepDamage);
SubscribeLocalEvent<SurgeryDamageChangeEffectComponent, SurgeryStepEvent>(OnSurgeryDamageChange);
SubscribeLocalEvent<SurgerySpecialDamageChangeEffectComponent, SurgeryStepEvent>(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<SurgerySpecialDamageChangeEffectComponent, SurgeryStepDamageChangeEvent>(OnSurgerySpecialDamageChange);
SubscribeLocalEvent<SurgeryDamageChangeEffectComponent, SurgeryStepDamageChangeEvent>(OnSurgeryDamageChange);
SubscribeLocalEvent<SurgeryStepEmoteEffectComponent, SurgeryStepEvent>(OnStepScreamComplete);
SubscribeLocalEvent<SurgeryStepSpawnEffectComponent, SurgeryStepEvent>(OnStepSpawnComplete);
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
Expand Down Expand Up @@ -127,37 +130,25 @@ private void OnToolAfterInteract(Entity<SurgeryToolComponent> ent, ref AfterInte
private void OnSurgeryStepDamage(Entity<SurgeryTargetComponent> ent, ref SurgeryStepDamageEvent args) =>
SetDamage(args.Body, args.Damage, args.PartMultiplier, args.User, args.Part);

private void OnSurgeryDamageChange(Entity<SurgeryDamageChangeEffectComponent> ent, ref SurgeryStepEvent args)
private void OnSurgerySpecialDamageChange(Entity<SurgerySpecialDamageChangeEffectComponent> 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<OrganComponent>(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<SurgeryDamageChangeEffectComponent> ent, ref SurgeryStepDamageChangeEvent args)
{
var damageChange = ent.Comp.Damage;
if (HasComp<ForcedSleepingComponent>(args.Body))
damageChange = damageChange * ent.Comp.SleepModifier;

SetDamage(args.Body, damageChange, 0.5f, args.User, args.Part);
}

private void OnSurgerySpecialDamageChange(Entity<SurgerySpecialDamageChangeEffectComponent> ent, ref SurgeryStepEvent args)
{
if (ent.Comp.IsConsumable
&& args.Tools.Where(tool => TryComp<OrganComponent>(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<SurgeryStepEmoteEffectComponent> ent, ref SurgeryStepEvent args)
{
if (HasComp<ForcedSleepingComponent>(args.Body))
Expand Down
6 changes: 3 additions & 3 deletions Content.Server/Body/Systems/BodySystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,8 @@ protected override void AddPart(
var layer = partEnt.Comp.ToHumanoidLayers();
if (layer != null)
{
var layers = HumanoidVisualLayersExtension.Sublayers(layer.Value);
_humanoidSystem.SetLayersVisibility(
bodyEnt, layers, visible: true, permanent: true, humanoid);
bodyEnt, new[] { layer.Value }, visible: true, permanent: true, humanoid);
}
}
}
Expand Down Expand Up @@ -172,7 +171,8 @@ public override HashSet<EntityUid> GibPart(
var ev = new BeingGibbedEvent(gibs);
RaiseLocalEvent(partId, ref ev);

QueueDel(partId);
if (gibs.Any())
QueueDel(partId);

return gibs;
}
Expand Down
11 changes: 9 additions & 2 deletions Content.Server/Body/Systems/BrainSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
using Content.Server.Ghost.Components;
using Content.Shared.Backmen.Surgery.Body;
using Content.Shared.Body.Components;
using Content.Shared.Body.Systems;
using Content.Shared.Body.Events;
using Content.Shared.Body.Organ;
using Content.Server.Backmen.DelayedDeath;
using Content.Shared.Backmen.Surgery.Body.Organs;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
using Content.Shared.Pointing;
Expand All @@ -13,8 +16,8 @@ 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()
{
base.Initialize();
Expand All @@ -31,17 +34,21 @@ private void HandleRemoval(EntityUid uid, BrainComponent _, ref OrganRemovedFrom

// Prevents revival, should kill the user within a given timespan too.
EnsureComp<DebrainedComponent>(args.OldBody);
EnsureComp<DelayedDeathComponent>(args.OldBody);
HandleMind(uid, args.OldBody);
}

private void HandleAddition(EntityUid uid, BrainComponent _, ref OrganAddedToBodyEvent args)
{
if (TerminatingOrDeleted(uid) || TerminatingOrDeleted(args.Body))
return;

RemComp<DebrainedComponent>(args.Body);
if (_bodySystem.TryGetBodyOrganEntityComps<HeartComponent>(args.Body, out var _))
RemComp<DelayedDeathComponent>(args.Body);
HandleMind(args.Body, uid);
}
// Shitmed-End

private void HandleMind(EntityUid newEntity, EntityUid oldEntity)
{
if (TerminatingOrDeleted(newEntity) || TerminatingOrDeleted(oldEntity))
Expand Down
4 changes: 2 additions & 2 deletions Content.Server/Body/Systems/RespiratorSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public override void Update(float frameTime)

UpdateSaturation(uid, -(float) respirator.UpdateInterval.TotalSeconds, respirator);

if (!_mobState.IsIncapacitated(uid) || HasComp<DebrainedComponent>(uid)) // Shitmed: cannot breathe in crit or when no brain.
if (!_mobState.IsIncapacitated(uid) && !HasComp<DebrainedComponent>(uid)) // Shitmed: cannot breathe in crit or when no brain.
{
switch (respirator.Status)
{
Expand Down Expand Up @@ -310,7 +310,7 @@ private void TakeSuffocationDamage(Entity<RespiratorComponent> ent)
RaiseLocalEvent(ent, new MoodEffectEvent("Suffocating")); // backmen: mood
}

_damageableSys.TryChangeDamage(ent, ent.Comp.Damage, interruptsDoAfters: false);
_damageableSys.TryChangeDamage(ent, HasComp<DebrainedComponent>(ent) ? ent.Comp.Damage * 4.5f : ent.Comp.Damage, interruptsDoAfters: false);
}

private void StopSuffocation(Entity<RespiratorComponent> ent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ namespace Content.Shared.Backmen.Surgery.Body;

[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.
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,18 @@ private void InitializePartAppearances()
private void OnPartAppearanceStartup(EntityUid uid, BodyPartAppearanceComponent component, ComponentStartup args)
{
if (!TryComp(uid, out BodyPartComponent? part)
|| part.OriginalBody == null
|| TerminatingOrDeleted(part.OriginalBody.Value)
|| !TryComp(part.OriginalBody.Value, out HumanoidAppearanceComponent? bodyAppearance)
|| part.ToHumanoidLayers() is not { } relevantLayer)
return;

if (part.OriginalBody == null
|| TerminatingOrDeleted(part.OriginalBody.Value)
|| !TryComp(part.OriginalBody.Value, out HumanoidAppearanceComponent? bodyAppearance))
{
//component.ID = part.BaseLayerId;
component.Type = relevantLayer;
return;
}

var customLayers = bodyAppearance.CustomBaseLayers;
var spriteLayers = bodyAppearance.BaseLayers;
component.Type = relevantLayer;
Expand Down Expand Up @@ -159,7 +165,7 @@ protected void UpdateAppearance(EntityUid target,
_humanoid.SetBaseLayerColor(target, component.Type, component.Color, true, bodyAppearance);

_humanoid.SetLayerVisibility(target, component.Type, true, true, bodyAppearance);

foreach (var (visualLayer, markingList) in component.Markings)
{
_humanoid.SetLayerVisibility(target, visualLayer, true, true, bodyAppearance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ namespace Content.Shared.Medical.Surgery.Conditions;
[RegisterComponent, NetworkedComponent]
public sealed partial class SurgeryPartRemovedConditionComponent : Component
{
/// <summary>
/// Requires that the parent part can attach a new part to this slot.
/// </summary>
[DataField(required: true)]
public string Connection = string.Empty;

[DataField]
public BodyPartType Part;

[DataField]
public BodyPartSymmetry? Symmetry;
}
}
24 changes: 23 additions & 1 deletion Content.Shared/Backmen/Surgery/SharedSurgerySystem.Steps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.DoAfter;
using Content.Shared.IdentityManagement;
using Content.Shared.Inventory;
using Content.Shared.Item;
using Content.Shared.Popups;
Expand All @@ -22,6 +23,7 @@
using Content.Shared.Backmen.Surgery.Steps.Parts;
using Content.Shared.Backmen.Surgery.Tools;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Medical.Surgery;

namespace Content.Shared.Backmen.Surgery;

Expand Down Expand Up @@ -420,6 +422,12 @@ private void OnAddOrganStep(Entity<SurgeryAddOrganStepComponent> ent, ref Surger
&& _body.InsertOrgan(args.Part, tool, insertedOrgan.SlotId, partComp, insertedOrgan))
{
EnsureComp<OrganReattachedComponent>(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;
}
}
Expand Down Expand Up @@ -621,7 +629,21 @@ private void OnSurgeryTargetStepChosen(Entity<SurgeryTargetComponent> ent, ref S
BreakOnHandChange = true,
};

_doAfter.TryStartDoAfter(doAfter);
if (_doAfter.TryStartDoAfter(doAfter))
{
var userName = Identity.Entity(user, EntityManager);
var targetName = Identity.Entity(ent.Owner, EntityManager);

var locName = $"surgery-popup-procedure-{args.Surgery}-step-{args.Step}";
var locResult = Loc.GetString(locName,
("user", userName), ("target", targetName), ("part", part));

if (locResult == locName)
locResult = Loc.GetString($"surgery-popup-step-{args.Step}",
("user", userName), ("target", targetName), ("part", part));

_popup.PopupEntity(locResult, user);
}
}

private (Entity<SurgeryComponent> Surgery, int Step)? GetNextStep(EntityUid body, EntityUid part, Entity<SurgeryComponent?> surgery, List<EntityUid> requirements)
Expand Down
6 changes: 6 additions & 0 deletions Content.Shared/Backmen/Surgery/SharedSurgerySystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ private void OnOrganConditionValid(Entity<SurgeryOrganConditionComponent> ent, r

private void OnPartRemovedConditionValid(Entity<SurgeryPartRemovedConditionComponent> ent, ref SurgeryValidEvent args)
{
if (!_body.CanAttachToSlot(args.Part, ent.Comp.Connection))
{
args.Cancelled = true;
return;
}

var results = _body.GetBodyChildrenOfType(args.Body, ent.Comp.Part, symmetry: ent.Comp.Symmetry);
if (results is not { } || !results.Any())
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Content.Shared.Damage;

namespace Content.Shared.Medical.Surgery;

/// <summary>
/// Raised on the target entity.
/// </summary>
[ByRefEvent]
public record struct SurgeryStepDamageChangeEvent(EntityUid User, EntityUid Body, EntityUid Part, EntityUid Step);
7 changes: 7 additions & 0 deletions Content.Shared/Body/Organ/OrganComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ public sealed partial class OrganComponent : Component, ISurgeryToolComponent
[DataField, AutoNetworkedField]
public EntityUid? Body;

/// <summary>
/// Relevant body this organ originally belonged to.
/// /// FOR WHATEVER FUCKING REASON AUTONETWORKING THIS CRASHES GIBTEST AAAAAAAAAAAAAAA
/// </summary>
[DataField]
public EntityUid? OriginalBody;

/// <summary>
/// Shitcodey solution to not being able to know what name corresponds to each organ's slot ID
/// without referencing the prototype or hardcoding.
Expand Down
Loading
Loading