Skip to content

Commit

Permalink
Shitmed: Implementing Existing Newmed Code Into SS14 (#1159)
Browse files Browse the repository at this point in the history
# Description

## The mythical surgery system. Heard whispered in hushed tones in the
corners of [REDACTED], it has been real since 2 years ago. If you listen
very carefully you might be able to hear the sound of arachne crashing
the server.

Jokes aside. Lets set some expectations, ideally this will not mess too
much with existing body code, besides trying to not die from all the
fucking test fails, all the while introducing needed systems for
handling wounds, surgery, part/organ manipulation, and displaying all of
those to the players.

The PR in its current state **is** working properly, you can pick it up
and get surgery on your server today, though of course its buggy due to
the unhandled issues it has right now. If you do pick it up, give me a
heads up and I'll see if I can help you out.

This PR is mostly intended as a public roasting ground for my shitcode,
so that other contribs/maints can pitch in to help improve it as well.

---

# TODO

- [ ] FIX MY FUCKING SHITCODE AAAAAAAAAAAAAAAAAAAAAAAAAA
- [x] Have fun :)

---
# Demo/Walkthrough
<p>

[![Surgery
Demo](https://i.ytimg.com/vi/UhxS5b3LC-A/maxresdefault.jpg)](https://www.youtube.com/watch?v=UhxS5b3LC-A
"Surgery Demo")

</p>
---

# Tasks currently being worked on:

- [x] Porting an upgraded body doll that is less shit to use.
- [x] Add a completely innocuous felinization/defelinization surgery.
(Highly sought after feature :D )
- [x] Implement pizza limb sprites and add em as a surgery (soon ™️)
- [ ] Add CyberneticsSystem
- [ ] Add a series of cybernetic limbs with special properties, and
different susceptibilities to EMPs
- [ ] Add the associated surgeries to cybernetic implants and their
associated maintenance.
- [ ] Tweak Cybernetics Traits to use CyberneticsSystem, and overwrite
the entity's limbs on spawn (I LOVE SHITCODE)
- [ ] Add Cybernetic Limbs to Research
- [x] Start adding a shitload of Shitmed comments on wherever I made
changes, since we're getting fairly close to what I could call a stable
v1
- [ ] Refactor SurgeryBUI to be slightly less shitcodey, and properly
use BUI states instead of a half-assed BUIMessage.
- [ ] Separate harpy wings into two distinct wings rather than a single
layer.
---

# Reported bugs that I haven't been able to replicate
- Apparently returning to the body kicks you back to the body instead of
the entity that the brain is attached to?
- Disconnecting and reconnecting after a brain/head transplant makes the
client crash. Seems to be related to identity.
- Transplanting a head sometimes makes it so that you cannot strip other
entities.

---


# Changelog

🆑 Mocho
- add: A week has passed. Surgery is here.

---------

Signed-off-by: gluesniffler <[email protected]>
Co-authored-by: FoxxoTrystan <[email protected]>
Co-authored-by: goet <[email protected]>
Co-authored-by: Saphire Lattice <[email protected]>
  • Loading branch information
4 people authored Nov 17, 2024
1 parent 1c20299 commit 029b763
Show file tree
Hide file tree
Showing 384 changed files with 8,214 additions and 199 deletions.
3 changes: 3 additions & 0 deletions Content.Client/Body/Components/BrainComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Content.Client.Body.Components;
[RegisterComponent]
public sealed partial class BrainComponent : Component { }
3 changes: 3 additions & 0 deletions Content.Client/Body/Components/LungComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Content.Client.Body.Components;
[RegisterComponent]
public sealed partial class LungComponent : Component { }
3 changes: 3 additions & 0 deletions Content.Client/Body/Components/StomachComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Content.Client.Body.Components;
[RegisterComponent]
public sealed partial class StomachComponent : Component { }
65 changes: 65 additions & 0 deletions Content.Client/Body/Systems/BodySystem.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,72 @@
using Content.Shared.Body.Systems;
using Content.Shared.Body.Part;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Robust.Client.GameObjects;
using Robust.Shared.Utility;
using Content.Shared.Body.Components;

namespace Content.Client.Body.Systems;

public sealed class BodySystem : SharedBodySystem
{
[Dependency] private readonly MarkingManager _markingManager = default!;

private void ApplyMarkingToPart(MarkingPrototype markingPrototype,
IReadOnlyList<Color>? colors,
bool visible,
SpriteComponent sprite)
{
for (var j = 0; j < markingPrototype.Sprites.Count; j++)
{
var markingSprite = markingPrototype.Sprites[j];

if (markingSprite is not SpriteSpecifier.Rsi rsi)
continue;

var layerId = $"{markingPrototype.ID}-{rsi.RsiState}";

if (!sprite.LayerMapTryGet(layerId, out _))
{
var layer = sprite.AddLayer(markingSprite, j + 1);
sprite.LayerMapSet(layerId, layer);
sprite.LayerSetSprite(layerId, rsi);
}

sprite.LayerSetVisible(layerId, visible);

if (!visible)
continue;

// Okay so if the marking prototype is modified but we load old marking data this may no longer be valid
// and we need to check the index is correct. So if that happens just default to white?
if (colors != null && j < colors.Count)
sprite.LayerSetColor(layerId, colors[j]);
else
sprite.LayerSetColor(layerId, Color.White);
}
}

protected override void ApplyPartMarkings(EntityUid target, BodyPartAppearanceComponent component)
{
if (!TryComp(target, out SpriteComponent? sprite))
return;

if (component.Color != null)
sprite.Color = component.Color.Value;

foreach (var (visualLayer, markingList) in component.Markings)
foreach (var marking in markingList)
{
if (!_markingManager.TryGetMarking(marking, out var markingPrototype))
continue;

ApplyMarkingToPart(markingPrototype, marking.MarkingColors, marking.Visible, sprite);
}
}

protected override void RemoveBodyMarkings(EntityUid target, BodyPartAppearanceComponent partAppearance, HumanoidAppearanceComponent bodyAppearance)
{
return;
}
}
35 changes: 34 additions & 1 deletion Content.Client/Hands/Systems/HandsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Content.Client.Examine;
using Content.Client.Strip;
using Content.Client.Verbs.UI;
using Content.Shared.Body.Part;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
Expand Down Expand Up @@ -38,7 +39,6 @@ public sealed class HandsSystem : SharedHandsSystem
public event Action<string, EntityUid>? OnPlayerItemRemoved;
public event Action<string>? OnPlayerHandBlocked;
public event Action<string>? OnPlayerHandUnblocked;

public override void Initialize()
{
base.Initialize();
Expand All @@ -49,6 +49,8 @@ public override void Initialize()
SubscribeLocalEvent<HandsComponent, ComponentShutdown>(OnHandsShutdown);
SubscribeLocalEvent<HandsComponent, ComponentHandleState>(HandleComponentState);
SubscribeLocalEvent<HandsComponent, VisualsChangedEvent>(OnVisualsChanged);
SubscribeLocalEvent<HandsComponent, BodyPartRemovedEvent>(HandleBodyPartRemoved);
SubscribeLocalEvent<HandsComponent, BodyPartDisabledEvent>(HandleBodyPartDisabled);

OnHandSetActive += OnHandActivated;
}
Expand Down Expand Up @@ -236,8 +238,38 @@ public void UIHandAltActivateItem(string handName)
RaisePredictiveEvent(new RequestHandAltInteractEvent(handName));
}

#region pulling

#endregion

#region visuals

private void HideLayers(EntityUid uid, HandsComponent component, Entity<BodyPartComponent> part, SpriteComponent? sprite = null)
{
if (part.Comp.PartType != BodyPartType.Hand || !Resolve(uid, ref sprite, logMissing: false))
return;

var location = part.Comp.Symmetry switch
{
BodyPartSymmetry.None => HandLocation.Middle,
BodyPartSymmetry.Left => HandLocation.Left,
BodyPartSymmetry.Right => HandLocation.Right,
_ => throw new ArgumentOutOfRangeException(nameof(part.Comp.Symmetry))
};

if (component.RevealedLayers.TryGetValue(location, out var revealedLayers))
{
foreach (var key in revealedLayers)
sprite.RemoveLayer(key);

revealedLayers.Clear();
}
}

private void HandleBodyPartRemoved(EntityUid uid, HandsComponent component, ref BodyPartRemovedEvent args) => HideLayers(uid, component, args.Part);

private void HandleBodyPartDisabled(EntityUid uid, HandsComponent component, ref BodyPartDisabledEvent args) => HideLayers(uid, component, args.Part);

protected override void HandleEntityInserted(EntityUid uid, HandsComponent hands, EntInsertedIntoContainerMessage args)
{
base.HandleEntityInserted(uid, hands, args);
Expand All @@ -262,6 +294,7 @@ protected override void HandleEntityRemoved(EntityUid uid, HandsComponent hands,

if (!hands.Hands.TryGetValue(args.Container.ID, out var hand))
return;

UpdateHandVisuals(uid, args.Entity, hand);
_stripSys.UpdateUi(uid);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Content.Shared.MedicalScanner;
using Content.Shared.Targeting;
using JetBrains.Annotations;
using Robust.Client.GameObjects;

Expand All @@ -22,6 +23,7 @@ protected override void Open()
Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName,
};
_window.OnClose += Close;
_window.OnBodyPartSelected += SendBodyPartMessage;
_window.OpenCentered();
}

Expand All @@ -36,14 +38,19 @@ protected override void ReceiveMessage(BoundUserInterfaceMessage message)
_window.Populate(cast);
}

private void SendBodyPartMessage(TargetBodyPart? part, EntityUid target) => SendMessage(new HealthAnalyzerPartMessage(EntMan.GetNetEntity(target), part ?? null));

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing)
return;

if (_window != null)
{
_window.OnClose -= Close;
_window.OnBodyPartSelected -= SendBodyPartMessage;
}

_window?.Dispose();
}
Expand Down
Loading

0 comments on commit 029b763

Please sign in to comment.