Обновление хирургии (#1375)
Co-authored-by: Rinary <rinary.super@gmail.com>
|
|
@ -5,6 +5,7 @@ using Content.Shared.Chemistry.Reagent;
|
|||
using Content.Shared.Clothing;
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Rounding;
|
||||
using Robust.Client.GameObjects;
|
||||
|
|
@ -166,7 +167,17 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
|
|||
var layer = new PrototypeLayerData();
|
||||
|
||||
var heldPrefix = item.HeldPrefix == null ? "inhand-" : $"{item.HeldPrefix}-inhand-";
|
||||
var key = heldPrefix + args.Location.ToString().ToLowerInvariant() + component.InHandsFillBaseName + closestFillSprite;
|
||||
|
||||
// Sunrise-start
|
||||
var locationString = args.Location switch
|
||||
{
|
||||
HandLocation.Left => "left",
|
||||
HandLocation.Right => "right",
|
||||
_ => "left" // bruh? Maybe add a middle hand for something, so this has some logic
|
||||
};
|
||||
|
||||
var key = $"{heldPrefix}{locationString}{component.InHandsFillBaseName}{closestFillSprite}";
|
||||
// Sunrise-end
|
||||
|
||||
layer.State = key;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Item.ItemToggle.Components;
|
||||
using Content.Shared.Toggleable;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Client.GameObjects;
|
||||
using Content.Shared._Sunrise.Medical.Surgery;
|
||||
using Content.Shared.Humanoid;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Content.Shared.DisplacementMap;
|
||||
using Content.Client.DisplacementMap;
|
||||
using System.Reflection;
|
||||
using Robust.Shared.Graphics.RSI;
|
||||
using Robust.Shared.Utility;
|
||||
using Content.Client.Clothing;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Client._Sunrise.Medical.Surgery;
|
||||
|
||||
public sealed class CustomLimbVisualizerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly DisplacementMapSystem _displacement = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CustomLimbVisualizerComponent, AfterAutoHandleStateEvent>(OnChanged);
|
||||
}
|
||||
|
||||
private void OnChanged(Entity<CustomLimbVisualizerComponent> ent, ref AfterAutoHandleStateEvent _) => OnChanged(ent);
|
||||
private void OnChanged(Entity<CustomLimbVisualizerComponent> ent, bool repeat = true)
|
||||
{
|
||||
if (!TryComp<SpriteComponent>(ent.Owner, out var sprite))
|
||||
return;
|
||||
|
||||
var old = ent.Comp.CachedLayers.ToHashSet();
|
||||
ent.Comp.CachedLayers.Clear();
|
||||
|
||||
foreach (var item in ent.Comp.Layers)
|
||||
{
|
||||
if (!item.Value.HasValue || !TryComp<SpriteComponent>(GetEntity(item.Value), out var layerSprite))
|
||||
{
|
||||
if (repeat) Timer.Spawn(TimeSpan.FromMilliseconds(150), () => OnChanged(ent, false));
|
||||
return;
|
||||
}
|
||||
string? state = null;
|
||||
if (TryComp<ItemComponent>(GetEntity(item.Value), out var itemComp) && itemComp.HeldPrefix is not null)
|
||||
state = $"{itemComp.HeldPrefix}-";
|
||||
|
||||
var offset = Vector2.Zero;
|
||||
switch (item.Key)
|
||||
{
|
||||
case HumanoidVisualLayers.LArm:
|
||||
case HumanoidVisualLayers.LHand:
|
||||
case HumanoidVisualLayers.LLeg:
|
||||
case HumanoidVisualLayers.LFoot:
|
||||
state += "inhand-left";
|
||||
break;
|
||||
case HumanoidVisualLayers.RArm:
|
||||
case HumanoidVisualLayers.RHand:
|
||||
case HumanoidVisualLayers.RLeg:
|
||||
case HumanoidVisualLayers.RFoot:
|
||||
state += "inhand-right";
|
||||
break;
|
||||
}
|
||||
if (state is null) continue;
|
||||
|
||||
switch (item.Key)
|
||||
{
|
||||
case HumanoidVisualLayers.LArm:
|
||||
offset = new Vector2(0, 0.1875f);
|
||||
break;
|
||||
case HumanoidVisualLayers.LHand:
|
||||
offset = new Vector2(0, 0.09375f);
|
||||
break;
|
||||
case HumanoidVisualLayers.LLeg:
|
||||
offset = new Vector2(0, -0.15625f);
|
||||
break;
|
||||
case HumanoidVisualLayers.LFoot:
|
||||
offset = new Vector2(0, -0.34375f);
|
||||
break;
|
||||
case HumanoidVisualLayers.RArm:
|
||||
offset = new Vector2(0, 0.1875f);
|
||||
break;
|
||||
case HumanoidVisualLayers.RHand:
|
||||
offset = new Vector2(0, 0.09375f);
|
||||
break;
|
||||
case HumanoidVisualLayers.RLeg:
|
||||
offset = new Vector2(0, -0.15625f);
|
||||
break;
|
||||
case HumanoidVisualLayers.RFoot:
|
||||
offset = new Vector2(0, -0.34375f);
|
||||
break;
|
||||
}
|
||||
if (layerSprite?.BaseRSI?.TryGetState(state, out var rsiState) ?? false)
|
||||
{
|
||||
var index = sprite.LayerMapReserveBlank($"custom-{item.Key}");
|
||||
|
||||
sprite.LayerSetState(index, rsiState.StateId, layerSprite.BaseRSI);
|
||||
sprite.LayerSetOffset(index, offset);
|
||||
sprite.LayerSetVisible(index, true);
|
||||
ent.Comp.CachedLayers.Add(item.Key);
|
||||
}
|
||||
|
||||
//if (ent.Comp.Displacements.TryGetValue(item.Key, out var displacementData) && !ent.Comp.CachedLayers.Contains($"{item.Key}-displacement"))
|
||||
//{
|
||||
// sprite.LayerMapSet(item.Key.ToString(), (int)item.Key);
|
||||
// _displacement.TryAddDisplacement(displacementData, sprite, (int)item.Key, item.Key.ToString(), ent.Comp.CachedLayers);
|
||||
//}
|
||||
}
|
||||
|
||||
foreach (var layer in old)
|
||||
if (!ent.Comp.CachedLayers.Contains(layer))
|
||||
{
|
||||
var index = sprite.LayerMapReserveBlank($"custom-{layer}");
|
||||
sprite.LayerSetVisible(layer, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
using Content.Client._Sunrise.Choice;
|
||||
using Content.Client.Administration.UI.CustomControls;
|
||||
using Content.Client.Administration.UI.CustomControls;
|
||||
using Content.Client.Hands.Systems;
|
||||
using Content.Client._Sunrise.Choice;
|
||||
using Content.Shared._Sunrise.Medical.Surgery;
|
||||
using Content.Shared.Body.Part;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
using static Robust.Client.UserInterface.Control;
|
||||
using Content.Shared.Timing;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client._Sunrise.Medical.Surgery;
|
||||
// Based on the RMC14 build.
|
||||
|
|
@ -19,7 +22,7 @@ public sealed class SurgeryBui : BoundUserInterface
|
|||
{
|
||||
[Dependency] private readonly IEntityManager _entities = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
|
||||
[Dependency] private readonly IGameTiming _game = default!;
|
||||
private readonly SurgerySystem _system;
|
||||
private readonly HandsSystem _hands;
|
||||
|
||||
|
|
@ -38,16 +41,17 @@ public sealed class SurgeryBui : BoundUserInterface
|
|||
_system.OnRefresh += UpdateDisabledPanel;
|
||||
_hands.OnPlayerItemAdded += OnPlayerItemAdded;
|
||||
}
|
||||
private DateTime _lastRefresh = DateTime.UtcNow;
|
||||
private (string k1, EntityUid k2) _throttling = ("", new EntityUid());
|
||||
private void OnPlayerItemAdded(string k1, EntityUid k2)
|
||||
{
|
||||
if (_throttling.k1.Equals(k1) && _throttling.k2.Equals(k2) && DateTime.UtcNow - _lastRefresh < TimeSpan.FromSeconds(1)) return;
|
||||
_throttling = (k1, k2);
|
||||
_lastRefresh = DateTime.UtcNow;
|
||||
if (!_game.IsFirstTimePredicted) return;
|
||||
RefreshUI();
|
||||
}
|
||||
protected override void Open() => UpdateState(State);
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
UpdateState(State);
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState? state)
|
||||
{
|
||||
if (state is SurgeryBuiState s)
|
||||
|
|
@ -215,24 +219,30 @@ public sealed class SurgeryBui : BoundUserInterface
|
|||
|
||||
_window.Steps.DisposeAllChildren();
|
||||
|
||||
if (surgery.Comp.Requirement is { } requirementId && _system.GetSingleton(requirementId) is { } requirement)
|
||||
if (surgery.Comp.Requirement is { } requirementIds)
|
||||
{
|
||||
var label = new ChoiceControl();
|
||||
label.Button.OnPressed += _ =>
|
||||
foreach (var requirementId in requirementIds)
|
||||
{
|
||||
_previousSurgeries.Add(surgeryId);
|
||||
if (_system.GetSingleton(requirementId) is { } requirement && _entities.TryGetComponent(_part, out BodyPartComponent? partComp) && partComp.Body is { } Body && _part is { } Part && _system.IsSurgeryValid(Body, Part, requirementId, surgeryId, out _, out _, out _))
|
||||
{
|
||||
var label = new ChoiceControl();
|
||||
label.Button.OnPressed += _ =>
|
||||
{
|
||||
_previousSurgeries.Add(surgeryId);
|
||||
|
||||
if (_entities.TryGetComponent(requirement, out SurgeryComponent? requirementComp))
|
||||
OnSurgeryPressed((requirement, requirementComp), netPart, requirementId);
|
||||
};
|
||||
if (_entities.TryGetComponent(requirement, out SurgeryComponent? requirementComp))
|
||||
OnSurgeryPressed((requirement, requirementComp), netPart, requirementId);
|
||||
};
|
||||
|
||||
var msg = new FormattedMessage();
|
||||
var surgeryName = _entities.GetComponent<MetaDataComponent>(requirement).EntityName;
|
||||
msg.AddMarkupOrThrow(Loc.GetString("surgery-window-reguires", ("surgeryname", surgeryName)));
|
||||
label.Set(msg, null);
|
||||
var msg = new FormattedMessage();
|
||||
var surgeryName = _entities.GetComponent<MetaDataComponent>(requirement).EntityName;
|
||||
msg.AddMarkupOrThrow(Loc.GetString("surgery-window-reguires", ("surgeryname", surgeryName)));
|
||||
label.Set(msg, null);
|
||||
|
||||
_window.Steps.AddChild(label);
|
||||
_window.Steps.AddChild(new HSeparator(Color.FromHex("#4972A1")) { Margin = new Thickness(0, 0, 0, 1) });
|
||||
_window.Steps.AddChild(label);
|
||||
_window.Steps.AddChild(new HSeparator(Color.FromHex("#4972A1")) { Margin = new Thickness(0, 0, 0, 1) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var stepId in surgery.Comp.Steps)
|
||||
|
|
@ -354,6 +364,12 @@ public sealed class SurgeryBui : BoundUserInterface
|
|||
case StepInvalidReason.MissingTool:
|
||||
stepName.AddMarkupOrThrow(Loc.GetString("surgery-window-reguires-tool"));
|
||||
break;
|
||||
case StepInvalidReason.DisabledTool:
|
||||
stepName.AddMarkupOrThrow(Loc.GetString("surgery-window-reguires-enable"));
|
||||
break;
|
||||
case StepInvalidReason.TooHigh:
|
||||
stepName.AddMarkupOrThrow(Loc.GetString("surgery-window-too-high"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -369,22 +385,21 @@ public sealed class SurgeryBui : BoundUserInterface
|
|||
if (_window == null)
|
||||
return;
|
||||
|
||||
if (_system.IsLyingDown(Owner))
|
||||
{
|
||||
_window.DisabledPanel.Visible = false;
|
||||
_window.DisabledPanel.MouseFilter = MouseFilterMode.Ignore;
|
||||
return;
|
||||
}
|
||||
_window.DisabledPanel.Visible = false;
|
||||
_window.DisabledPanel.MouseFilter = MouseFilterMode.Ignore;
|
||||
return;
|
||||
|
||||
_window.DisabledPanel.Visible = true;
|
||||
if (_window.DisabledLabel.GetMessage() is null)
|
||||
if (!_system.IsLyingDown(Owner))
|
||||
{
|
||||
var text = new FormattedMessage();
|
||||
text.AddMarkupOrThrow(Loc.GetString("surgery-window-reguires-laydown"));
|
||||
_window.DisabledLabel.SetMessage(text);
|
||||
_window.DisabledPanel.Visible = true;
|
||||
if (_window.DisabledLabel.GetMessage() is null)
|
||||
{
|
||||
var text = new FormattedMessage();
|
||||
text.AddMarkupOrThrow(Loc.GetString("surgery-window-reguires-laydown"));
|
||||
_window.DisabledLabel.SetMessage(text);
|
||||
}
|
||||
_window.DisabledPanel.MouseFilter = MouseFilterMode.Stop;
|
||||
}
|
||||
|
||||
_window.DisabledPanel.MouseFilter = MouseFilterMode.Stop;
|
||||
}
|
||||
|
||||
private void View(ViewType type)
|
||||
|
|
@ -437,7 +452,6 @@ public sealed class SurgeryBui : BoundUserInterface
|
|||
|
||||
if (disposing)
|
||||
_window?.Dispose();
|
||||
_system.OnRefresh -= UpdateDisabledPanel;
|
||||
_hands.OnPlayerItemAdded -= OnPlayerItemAdded;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Content.Client._Sunrise.Choice;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Content.Client._Sunrise.Choice;
|
||||
|
||||
namespace Content.Client._Sunrise.Medical.Surgery;
|
||||
// Based on the RMC14.
|
||||
|
|
|
|||
156
Content.Server/_Sunrise/Medical/LimbDamageSystem.cs
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Hands.Systems;
|
||||
using Content.Server._Sunrise.Medical.Surgery;
|
||||
using Content.Shared._Sunrise.Medical.Damage;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Components;
|
||||
using Content.Shared.NukeOps;
|
||||
using Content.Shared.Random.Helpers;
|
||||
using Content.Shared._Sunrise.Medical.Surgery;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Effects.Step;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._Sunrise.Medical;
|
||||
public sealed class LimbDamageSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _rand = default!;
|
||||
[Dependency] private readonly BodySystem _body = default!;
|
||||
[Dependency] private readonly ContainerSystem _containers = default!;
|
||||
[Dependency] private readonly HandsSystem _hands = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<BodyComponent, DamageBeforeApplyEvent>(OnDamage);
|
||||
}
|
||||
//duct tape solution
|
||||
private void OnDamage(Entity<BodyComponent> ent, ref DamageBeforeApplyEvent args)
|
||||
{
|
||||
if (HasComp<NukeOperativeComponent>(ent)) return; // Nuke Ops are immune to limb damage. Temporary solution. mb Deathsquad?
|
||||
if (!TryComp<HumanoidAppearanceComponent>(ent, out var appr) || appr.Species == "SlimePerson") return; // SlimePeople are immune to limb damage.
|
||||
|
||||
var chance = 0f;
|
||||
foreach (var damage in args.Damage.DamageDict.Where(x => x.Value > 0))
|
||||
switch (damage.Key)
|
||||
{
|
||||
case "Blunt":
|
||||
chance += 0.00005f * damage.Value.Float();
|
||||
break;
|
||||
case "Slash":
|
||||
chance += 0.0005f * damage.Value.Float();
|
||||
break;
|
||||
case "Piercing":
|
||||
chance += 0.0001f * damage.Value.Float();
|
||||
break;
|
||||
case "Heat":
|
||||
chance += 0.0002f * damage.Value.Float();
|
||||
break;
|
||||
case "Cold":
|
||||
chance += 0.0004f * damage.Value.Float();
|
||||
break;
|
||||
case "Caustic":
|
||||
chance += 0.001f * damage.Value.Float();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
chance = Math.Clamp(chance, 0, 1);
|
||||
if (_rand.Prob(chance))
|
||||
{
|
||||
if (!TryRemoveLimb(ent, out var part)) return;
|
||||
Dirty(ent);
|
||||
QueueDel(part.Value.Owner);
|
||||
args.Cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryRemoveLimb(Entity<BodyComponent> ent, [NotNullWhen(true)] out Entity<BodyPartComponent>? part)
|
||||
{
|
||||
part = null;
|
||||
var root = _body.GetRootPartOrNull(ent.Owner);
|
||||
if (root is null) return false;
|
||||
var parts = _body.GetAllBodyPart(root.Value.Entity, root.Value.BodyPart)
|
||||
.Where(p => p.Comp.PartType != BodyPartType.Head)
|
||||
.ToList();
|
||||
if (parts.Count == 0) return false;
|
||||
part = _rand.Pick(parts);
|
||||
var parentPartAndSlot = _body.GetParentPartAndSlotOrNull(part.Value.Owner);
|
||||
if (parentPartAndSlot is null) return false;
|
||||
var (_, slotId) = parentPartAndSlot.Value;
|
||||
|
||||
if (!_containers.TryGetContainingContainer((part.Value.Owner, null, null), out var container)) return false;
|
||||
if (!_containers.Remove(part.Value.Owner, container)) return false;
|
||||
if (TryComp<CustomLimbComponent>(part.Value.Owner, out var virtualLimb)
|
||||
&& virtualLimb.Item.HasValue)
|
||||
{
|
||||
RemoveItemHand(ent.Owner, virtualLimb.Item.Value, BodySystem.GetPartSlotContainerId(slotId));
|
||||
|
||||
var vizualizer = EnsureComp<CustomLimbVisualizerComponent>(ent.Owner);
|
||||
|
||||
var layer = SurgerySystem.GetLayer(slotId);
|
||||
if (layer is not null)
|
||||
{
|
||||
vizualizer.Layers.Remove(layer.Value);
|
||||
Dirty(ent.Owner, vizualizer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (part.Value.Comp.PartType)
|
||||
{
|
||||
case BodyPartType.Arm: //todo move to systems
|
||||
foreach (var limbSlotId in part.Value.Comp.Children.Keys)
|
||||
{
|
||||
if (limbSlotId is null) continue;
|
||||
var child = _containers.GetContainer(part.Value.Owner, BodySystem.GetPartSlotContainerId(limbSlotId));
|
||||
|
||||
foreach (var containedEnt in child.ContainedEntities)
|
||||
{
|
||||
if (TryComp(containedEnt, out BodyPartComponent? innerPart)
|
||||
&& innerPart.PartType == BodyPartType.Hand)
|
||||
_hands.RemoveHand(ent.Owner, BodySystem.GetPartSlotContainerId(limbSlotId));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BodyPartType.Hand:
|
||||
var parentSlot = _body.GetParentPartAndSlotOrNull(part.Value.Owner);
|
||||
if (parentSlot is not null)
|
||||
_hands.RemoveHand(ent.Owner, BodySystem.GetPartSlotContainerId(parentSlot.Value.Slot));
|
||||
break;
|
||||
case BodyPartType.Leg:
|
||||
case BodyPartType.Foot:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void RemoveItemHand(EntityUid bodyId, EntityUid itemId, string handId)
|
||||
{
|
||||
if (!TryComp<HandsComponent>(bodyId, out var hands)
|
||||
|| !_hands.TryGetHand(bodyId, handId, out var hand, hands))
|
||||
return;
|
||||
|
||||
if (!itemId.IsValid())
|
||||
{
|
||||
Log.Debug("no valid item");
|
||||
return;
|
||||
}
|
||||
RemComp<UnremoveableComponent>(itemId);
|
||||
_hands.DoDrop(itemId, hand);
|
||||
_hands.RemoveHand(bodyId, handId, hands);
|
||||
}
|
||||
}
|
||||
147
Content.Server/_Sunrise/Medical/Surgery/OrganSystem.cs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Eye.Blinding.Components;
|
||||
using Content.Shared.Eye.Blinding.Systems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Speech.Muting;
|
||||
using Content.Shared._Sunrise.Antags.Abductor;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Effects.Step;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Events;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Steps.Parts;
|
||||
using Content.Shared._Sunrise.VentCraw;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._Sunrise.Medical.Surgery;
|
||||
public sealed partial class OrganSystem : EntitySystem
|
||||
{
|
||||
|
||||
[Dependency] private readonly BlindableSystem _blindable = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
[Dependency] private readonly IComponentFactory _compFactory = default!;
|
||||
[Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearanceSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<FunctionalOrganComponent, SurgeryOrganImplantationCompleted>(OnFunctionalOrganImplanted);
|
||||
SubscribeLocalEvent<FunctionalOrganComponent, SurgeryOrganExtracted>(OnFunctionalOrganExtracted);
|
||||
|
||||
SubscribeLocalEvent<OrganEyesComponent, SurgeryOrganImplantationCompleted>(OnEyeImplanted);
|
||||
SubscribeLocalEvent<OrganEyesComponent, SurgeryOrganExtracted>(OnEyeExtracted);
|
||||
|
||||
SubscribeLocalEvent<OrganTongueComponent, SurgeryOrganImplantationCompleted>(OnTongueImplanted);
|
||||
SubscribeLocalEvent<OrganTongueComponent, SurgeryOrganExtracted>(OnTongueExtracted);
|
||||
|
||||
SubscribeLocalEvent<AbductorOrganComponent, SurgeryOrganImplantationCompleted>(OnAbductorOrganImplanted);
|
||||
SubscribeLocalEvent<AbductorOrganComponent, SurgeryOrganExtracted>(OnAbductorOrganExtracted);
|
||||
|
||||
SubscribeLocalEvent<DamageableComponent, SurgeryOrganImplantationCompleted>(OnOrganImplanted);
|
||||
SubscribeLocalEvent<DamageableComponent, SurgeryOrganExtracted>(OnOrganExtracted);
|
||||
|
||||
SubscribeLocalEvent<OrganVisualizationComponent, SurgeryOrganImplantationCompleted>(OnVisualizationImplanted);
|
||||
SubscribeLocalEvent<OrganVisualizationComponent, SurgeryOrganExtracted>(OnVisualizationExtracted);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private void OnFunctionalOrganImplanted(Entity<FunctionalOrganComponent> ent, ref SurgeryOrganImplantationCompleted args)
|
||||
{
|
||||
foreach (var comp in (ent.Comp.Components ?? []).Values)
|
||||
if (!EntityManager.HasComponent(args.Body, comp.Component.GetType()))
|
||||
EntityManager.AddComponent(args.Body, _compFactory.GetComponent(comp.Component.GetType()));
|
||||
}
|
||||
|
||||
private void OnFunctionalOrganExtracted(Entity<FunctionalOrganComponent> ent, ref SurgeryOrganExtracted args)
|
||||
{
|
||||
foreach (var comp in (ent.Comp.Components ?? []).Values)
|
||||
if (EntityManager.HasComponent(args.Body, comp.Component.GetType()))
|
||||
EntityManager.RemoveComponent(args.Body, _compFactory.GetComponent(comp.Component.GetType()));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private void OnOrganImplanted(Entity<DamageableComponent> ent, ref SurgeryOrganImplantationCompleted args)
|
||||
{
|
||||
if (!TryComp<DamageableComponent>(args.Body, out var bodyDamageable)) return;
|
||||
|
||||
var change = _damageableSystem.TryChangeDamage(args.Body, ent.Comp.Damage, true, false, bodyDamageable);
|
||||
if (change is not null)
|
||||
_damageableSystem.TryChangeDamage(ent.Owner, change.Invert(), true, false, ent.Comp);
|
||||
}
|
||||
private void OnOrganExtracted(Entity<DamageableComponent> ent, ref SurgeryOrganExtracted args)
|
||||
{
|
||||
if (!TryComp<OrganDamageComponent>(ent.Owner, out var damageRule)
|
||||
|| damageRule.Damage is null
|
||||
|| !TryComp<DamageableComponent>(args.Body, out var bodyDamageable)) return;
|
||||
|
||||
var change = _damageableSystem.TryChangeDamage(args.Body, damageRule.Damage.Invert(), true, false, bodyDamageable);
|
||||
if (change is not null)
|
||||
_damageableSystem.TryChangeDamage(ent.Owner, change.Invert(), true, false, ent.Comp);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private void OnAbductorOrganImplanted(Entity<AbductorOrganComponent> ent, ref SurgeryOrganImplantationCompleted args)
|
||||
{
|
||||
if (TryComp<AbductorVictimComponent>(args.Body, out var victim))
|
||||
victim.Organ = ent.Comp.Organ;
|
||||
if (ent.Comp.Organ == AbductorOrganType.Vent)
|
||||
AddComp<VentCrawlerComponent>(args.Body);
|
||||
}
|
||||
private void OnAbductorOrganExtracted(Entity<AbductorOrganComponent> ent, ref SurgeryOrganExtracted args)
|
||||
{
|
||||
if (TryComp<AbductorVictimComponent>(args.Body, out var victim))
|
||||
if (victim.Organ == ent.Comp.Organ)
|
||||
victim.Organ = AbductorOrganType.None;
|
||||
|
||||
if (ent.Comp.Organ == AbductorOrganType.Vent)
|
||||
RemComp<VentCrawlerComponent>(args.Body);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private void OnTongueImplanted(Entity<OrganTongueComponent> ent, ref SurgeryOrganImplantationCompleted args)
|
||||
{
|
||||
if (HasComp<AbductorComponent>(args.Body) || !ent.Comp.IsMuted) return;
|
||||
RemComp<MutedComponent>(args.Body);
|
||||
}
|
||||
|
||||
private void OnTongueExtracted(Entity<OrganTongueComponent> ent, ref SurgeryOrganExtracted args)
|
||||
{
|
||||
ent.Comp.IsMuted = HasComp<MutedComponent>(args.Body);
|
||||
AddComp<MutedComponent>(args.Body);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private void OnEyeExtracted(Entity<OrganEyesComponent> ent, ref SurgeryOrganExtracted args)
|
||||
{
|
||||
if (!TryComp<BlindableComponent>(args.Body, out var blindable)) return;
|
||||
|
||||
ent.Comp.EyeDamage = blindable.EyeDamage;
|
||||
ent.Comp.MinDamage = blindable.MinDamage;
|
||||
_blindable.UpdateIsBlind((args.Body, blindable));
|
||||
}
|
||||
private void OnEyeImplanted(Entity<OrganEyesComponent> ent, ref SurgeryOrganImplantationCompleted args)
|
||||
{
|
||||
if (!TryComp<BlindableComponent>(args.Body, out var blindable)) return;
|
||||
|
||||
_blindable.SetMinDamage((args.Body, blindable), ent.Comp.MinDamage ?? 0);
|
||||
_blindable.AdjustEyeDamage((args.Body, blindable), (ent.Comp.EyeDamage ?? 0) - blindable.MaxDamage);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private void OnVisualizationExtracted(Entity<OrganVisualizationComponent> ent, ref SurgeryOrganExtracted args)
|
||||
=> _humanoidAppearanceSystem.SetLayersVisibility(args.Body, [ent.Comp.Layer], false);
|
||||
private void OnVisualizationImplanted(Entity<OrganVisualizationComponent> ent, ref SurgeryOrganImplantationCompleted args)
|
||||
{
|
||||
_humanoidAppearanceSystem.SetLayersVisibility(args.Body, [ent.Comp.Layer], true);
|
||||
_humanoidAppearanceSystem.SetBaseLayerId(args.Body, ent.Comp.Layer, ent.Comp.Prototype);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,8 @@ using Content.Shared._Sunrise.Medical.Surgery.Steps.Parts;
|
|||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Organ;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Body.Systems;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
using Content.Shared.Eye.Blinding.Components;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Speech.Muting;
|
||||
|
|
@ -16,12 +16,21 @@ using Robust.Shared.Prototypes;
|
|||
using Content.Shared.Humanoid;
|
||||
using Content.Shared._Sunrise;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Interaction.Components;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Content.Server._Sunrise.Medical.Surgery;
|
||||
// Based on the RMC14.
|
||||
// https://github.com/RMC-14/RMC-14
|
||||
//
|
||||
//This file is already overloaded with responsibilities,
|
||||
//it’s time to break its functionality into different systems.
|
||||
//However, I don’t want to touch the official systems, so I need to come up with extensions for them.
|
||||
public sealed partial class SurgerySystem : SharedSurgerySystem
|
||||
{
|
||||
[Dependency] private readonly IComponentFactory _compFactory = default!;
|
||||
|
||||
private readonly EntProtoId _virtual = "PartVirtual";
|
||||
public void InitializeSteps()
|
||||
{
|
||||
SubscribeLocalEvent<SurgeryStepBleedEffectComponent, SurgeryStepEvent>(OnStepBleedComplete);
|
||||
|
|
@ -32,16 +41,29 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
|
|||
SubscribeLocalEvent<SurgeryStepOrganExtractComponent, SurgeryStepEvent>(OnStepOrganExtractComplete);
|
||||
SubscribeLocalEvent<SurgeryStepOrganInsertComponent, SurgeryStepEvent>(OnStepOrganInsertComplete);
|
||||
|
||||
SubscribeLocalEvent<SurgeryStepAttachLimbEffectComponent, SurgeryStepEvent>(OnStepAttachLimbComplete);
|
||||
SubscribeLocalEvent<SurgeryStepAttachLimbEffectComponent, SurgeryStepEvent>(OnStepAttachComplete);
|
||||
SubscribeLocalEvent<SurgeryStepAmputationEffectComponent, SurgeryStepEvent>(OnStepAmputationComplete);
|
||||
|
||||
SubscribeLocalEvent<CustomLimbMarkerComponent, ComponentRemove>(CustomLimbRemoved);
|
||||
|
||||
SubscribeLocalEvent<SurgeryRemoveAccentComponent, SurgeryStepEvent>(OnRemoveAccent);
|
||||
|
||||
}
|
||||
|
||||
private void OnStepAttachComplete(Entity<SurgeryStepAttachLimbEffectComponent> ent, ref SurgeryStepEvent args)
|
||||
{
|
||||
if (GetSingleton(args.SurgeryProto) is not { } surgery
|
||||
|| !TryComp<SurgeryLimbSlotConditionComponent>(surgery, out var slotComp))
|
||||
return;
|
||||
|
||||
OnStepAttachLimbComplete(ent, slotComp.Slot, ref args);
|
||||
if (slotComp.Slot != "head")
|
||||
OnStepAttachItemComplete(ent, slotComp.Slot, ref args);
|
||||
}
|
||||
|
||||
private void OnStepBleedComplete(Entity<SurgeryStepBleedEffectComponent> ent, ref SurgeryStepEvent args)
|
||||
{
|
||||
if(ent.Comp.Damage is not null && TryComp<DamageableComponent>(args.Body, out var comp))
|
||||
if (ent.Comp.Damage is not null && TryComp<DamageableComponent>(args.Body, out var comp))
|
||||
_damageableSystem.TryChangeDamage(args.Body, ent.Comp.Damage);
|
||||
//todo add wound
|
||||
}
|
||||
|
|
@ -54,8 +76,18 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
|
|||
{
|
||||
if (args.Tools.Count == 0
|
||||
|| !(args.Tools.FirstOrDefault() is var organId)
|
||||
|| !TryComp<BodyPartComponent>(args.Part, out var bodyPart)
|
||||
|| !TryComp<OrganComponent>(organId, out var organComp))
|
||||
|| !TryComp<BodyPartComponent>(args.Part, out var bodyPart))
|
||||
return;
|
||||
|
||||
var containerId = SharedBodySystem.GetOrganContainerId(ent.Comp.Slot);
|
||||
|
||||
if (ent.Comp.Slot == "cavity" && _containers.TryGetContainer(args.Part, containerId, out var container))
|
||||
{
|
||||
_containers.Insert(organId, container);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryComp<OrganComponent>(organId, out var organComp))
|
||||
return;
|
||||
|
||||
var part = args.Part;
|
||||
|
|
@ -63,59 +95,36 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
|
|||
_delayAccumulator = 0;
|
||||
_delayQueue.Enqueue(() =>
|
||||
{
|
||||
if (_body.InsertOrgan(part, organId, ent.Comp.Slot, bodyPart, organComp)
|
||||
&& TryComp<DamageableComponent>(organId, out var organDamageable)
|
||||
&& TryComp<DamageableComponent>(body, out var bodyDamageable))
|
||||
{
|
||||
if (TryComp<OrganEyesComponent>(organId, out var organEyes)
|
||||
&& TryComp<BlindableComponent>(body, out var blindable))
|
||||
{
|
||||
_blindable.SetMinDamage((body, blindable), organEyes.MinDamage ?? 0);
|
||||
_blindable.AdjustEyeDamage((body, blindable), (organEyes.EyeDamage ?? 0) - blindable.MaxDamage);
|
||||
}
|
||||
if (TryComp<OrganTongueComponent>(organId, out var organTongue)
|
||||
&& !organTongue.IsMuted)
|
||||
RemComp<MutedComponent>(body);
|
||||
if (!_body.InsertOrgan(part, organId, ent.Comp.Slot, bodyPart, organComp)) return;
|
||||
|
||||
var change = _damageableSystem.TryChangeDamage(body, organDamageable.Damage, true, false, bodyDamageable);
|
||||
if (change is not null)
|
||||
_damageableSystem.TryChangeDamage(organId, change.Invert(), true, false, organDamageable);
|
||||
}
|
||||
var ev = new SurgeryOrganImplantationCompleted(body, part, organId);
|
||||
RaiseLocalEvent(organId, ref ev);
|
||||
});
|
||||
}
|
||||
private void OnStepOrganExtractComplete(Entity<SurgeryStepOrganExtractComponent> ent, ref SurgeryStepEvent args)
|
||||
{
|
||||
if (ent.Comp.Organ?.Count != 1) return;
|
||||
var organs = _body.GetPartOrgans(args.Part, Comp<BodyPartComponent>(args.Part));
|
||||
|
||||
var type = ent.Comp.Organ.Values.First().Component.GetType();
|
||||
|
||||
if (ent.Comp.Slot != null && _containers.TryGetContainer(args.Part, SharedBodySystem.GetOrganContainerId(ent.Comp.Slot), out var container))
|
||||
{
|
||||
foreach (var containedEnt in container.ContainedEntities)
|
||||
if (HasComp(containedEnt, type))
|
||||
_containers.Remove(containedEnt, container);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var organs = _body.GetPartOrgans(args.Part, Comp<BodyPartComponent>(args.Part));
|
||||
foreach (var organ in organs)
|
||||
{
|
||||
if (HasComp(organ.Id, type))
|
||||
{
|
||||
if (_body.RemoveOrgan(organ.Id, organ.Component)
|
||||
&& TryComp<OrganDamageComponent>(organ.Id, out var damageRule)
|
||||
&& damageRule.Damage is not null
|
||||
&& TryComp<DamageableComponent>(organ.Id, out var organDamageable)
|
||||
&& TryComp<DamageableComponent>(args.Body, out var bodyDamageable))
|
||||
{
|
||||
if (TryComp<OrganEyesComponent>(organ.Id, out var organEyes)
|
||||
&& TryComp<BlindableComponent>(args.Body, out var blindable))
|
||||
{
|
||||
organEyes.EyeDamage = blindable.EyeDamage;
|
||||
organEyes.MinDamage = blindable.MinDamage;
|
||||
_blindable.UpdateIsBlind((args.Body, blindable));
|
||||
}
|
||||
if (TryComp<OrganTongueComponent>(organ.Id, out var organTongue))
|
||||
{
|
||||
organTongue.IsMuted = HasComp<MutedComponent>(args.Body);
|
||||
AddComp<MutedComponent>(args.Body);
|
||||
}
|
||||
var change = _damageableSystem.TryChangeDamage(args.Body, damageRule.Damage.Invert(), true, false, bodyDamageable);
|
||||
if (change is not null)
|
||||
_damageableSystem.TryChangeDamage(organ.Id, change.Invert(), true, false, organDamageable);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!HasComp(organ.Id, type) || !_body.RemoveOrgan(organ.Id, organ.Component)) continue;
|
||||
|
||||
var ev = new SurgeryOrganExtracted(args.Body, args.Part, organ.Id);
|
||||
RaiseLocalEvent(organ.Id, ref ev);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +142,7 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
|
|||
if (TryComp(args.Body, out TransformComponent? xform))
|
||||
SpawnAtPosition(ent.Comp.Entity, xform.Coordinates);
|
||||
}
|
||||
private void OnStepAttachLimbComplete(Entity<SurgeryStepAttachLimbEffectComponent> ent, ref SurgeryStepEvent args)
|
||||
private void OnStepAttachLimbComplete(Entity<SurgeryStepAttachLimbEffectComponent> _, string slot, ref SurgeryStepEvent args)
|
||||
{
|
||||
if (args.Tools.Count == 0
|
||||
|| !(args.Tools.FirstOrDefault() is var limbId)
|
||||
|
|
@ -144,61 +153,130 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
|
|||
var part = args.Part;
|
||||
var body = args.Body;
|
||||
|
||||
_delayAccumulator = 0;
|
||||
_delayQueue.Enqueue(() =>
|
||||
if (!_body.AttachPart(part, slot, limbId, bodyPart, limb))
|
||||
{
|
||||
var slot = "";
|
||||
foreach (var slotTemp in _body.TryGetFreePartSlots(part, bodyPart))
|
||||
{
|
||||
slot = slotTemp;
|
||||
if (_body.AttachPart(part, slot, limbId, bodyPart, limb))
|
||||
break;
|
||||
}
|
||||
args.IsCancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryComp<HumanoidAppearanceComponent>(body, out var humanoid)) //todo move to system
|
||||
if (TryComp<HumanoidAppearanceComponent>(body, out var humanoid)) //todo move to system
|
||||
{
|
||||
var limbs = _body.GetBodyPartAdjacentParts(limbId, limb).Except([part]).Concat([limbId]);
|
||||
foreach (var partLimbId in limbs)
|
||||
{
|
||||
var limbs = _body.GetBodyPartAdjacentParts(limbId, limb).Except([part]).Concat([limbId]);
|
||||
foreach (var partLimbId in limbs)
|
||||
if (TryComp<BaseLayerIdComponent>(partLimbId, out var baseLayerStorage)
|
||||
&& TryComp(partLimbId, out BodyPartComponent? partLimb))
|
||||
{
|
||||
if (TryComp<BaseLayerIdComponent>(partLimbId, out var baseLayerStorage)
|
||||
&& TryComp(partLimbId, out BodyPartComponent? partLimb))
|
||||
{
|
||||
var layer = partLimb.ToHumanoidLayers();
|
||||
if (layer is null) continue;
|
||||
_humanoidAppearanceSystem.SetBaseLayerId(body, layer.Value, baseLayerStorage.Layer, true, humanoid);
|
||||
}
|
||||
var layer = partLimb.ToHumanoidLayers();
|
||||
if (layer is null) continue;
|
||||
_humanoidAppearanceSystem.SetBaseLayerId(body, layer.Value, baseLayerStorage.Layer, true, humanoid);
|
||||
}
|
||||
}
|
||||
switch (limb.PartType)
|
||||
{
|
||||
case BodyPartType.Arm: //todo move to systems
|
||||
if (limb.Children.Keys.Count == 0)
|
||||
{
|
||||
_body.TryCreatePartSlot(limbId, limb.Symmetry == BodyPartSymmetry.Left ? "left hand" : "right hand", BodyPartType.Hand, out var slotId);
|
||||
}
|
||||
foreach (var slotId in limb.Children.Keys)
|
||||
{
|
||||
if (slotId is null) continue;
|
||||
var slotFullId = BodySystem.GetPartSlotContainerId(slotId);
|
||||
var child = _containers.GetContainer(limbId, slotFullId);
|
||||
}
|
||||
|
||||
foreach (var containedEnt in child.ContainedEntities)
|
||||
{
|
||||
if (TryComp(containedEnt, out BodyPartComponent? innerPart)
|
||||
&& innerPart.PartType == BodyPartType.Hand)
|
||||
_hands.AddHand(body, slotFullId, limb.Symmetry == BodyPartSymmetry.Left ? HandLocation.Left : HandLocation.Right);
|
||||
}
|
||||
switch (limb.PartType)
|
||||
{
|
||||
case BodyPartType.Arm: //todo move to systems
|
||||
if (limb.Children.Keys.Count == 0)
|
||||
_body.TryCreatePartSlot(limbId, limb.Symmetry == BodyPartSymmetry.Left ? "left hand" : "right hand", BodyPartType.Hand, out var slotId);
|
||||
|
||||
foreach (var slotId in limb.Children.Keys)
|
||||
{
|
||||
if (slotId is null) continue;
|
||||
var slotFullId = BodySystem.GetPartSlotContainerId(slotId);
|
||||
var child = _containers.GetContainer(limbId, slotFullId);
|
||||
|
||||
foreach (var containedEnt in child.ContainedEntities)
|
||||
{
|
||||
if (TryComp(containedEnt, out BodyPartComponent? innerPart)
|
||||
&& innerPart.PartType == BodyPartType.Hand)
|
||||
_hands.AddHand(body, slotFullId, limb.Symmetry == BodyPartSymmetry.Left ? HandLocation.Left : HandLocation.Right);
|
||||
}
|
||||
break;
|
||||
case BodyPartType.Hand:
|
||||
_hands.AddHand(body, BodySystem.GetPartSlotContainerId(slot), limb.Symmetry == BodyPartSymmetry.Left ? HandLocation.Left : HandLocation.Right);
|
||||
break;
|
||||
case BodyPartType.Leg:
|
||||
case BodyPartType.Foot:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
case BodyPartType.Hand:
|
||||
_hands.AddHand(body, BodySystem.GetPartSlotContainerId(slot), limb.Symmetry == BodyPartSymmetry.Left ? HandLocation.Left : HandLocation.Right);
|
||||
break;
|
||||
case BodyPartType.Leg:
|
||||
if (limb.Children.Keys.Count == 0)
|
||||
_body.TryCreatePartSlot(limbId, limb.Symmetry == BodyPartSymmetry.Left ? "left foot" : "right foot", BodyPartType.Foot, out var slotId);
|
||||
break;
|
||||
case BodyPartType.Foot:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStepAttachItemComplete(Entity<SurgeryStepAttachLimbEffectComponent> ent, string slot, ref SurgeryStepEvent args)
|
||||
{
|
||||
if (args.Tools.Count == 0
|
||||
|| !(args.Tools.FirstOrDefault() is var itemId)
|
||||
|| !TryComp<BodyPartComponent>(args.Part, out var bodyPart)
|
||||
|| !TryComp(itemId, out MetaDataComponent? metada)
|
||||
|| TryComp<BodyPartComponent>(itemId, out var _)
|
||||
|| Prototype(itemId) is not EntityPrototype prototype)
|
||||
return;
|
||||
|
||||
var marker = EnsureComp<CustomLimbMarkerComponent>(itemId);
|
||||
|
||||
var virtualIteam = Spawn(_virtual);
|
||||
var virtualBodyPart = EnsureComp<BodyPartComponent>(virtualIteam);
|
||||
var virtualMetadata = EnsureComp<MetaDataComponent>(virtualIteam);
|
||||
var virtualCustomLimb = EnsureComp<CustomLimbComponent>(virtualIteam);
|
||||
_metadata.SetEntityName(virtualIteam, metada.EntityName, virtualMetadata);
|
||||
|
||||
marker.VirtualPart = virtualIteam;
|
||||
virtualCustomLimb.Item = itemId;
|
||||
|
||||
virtualBodyPart.PartType = slot switch
|
||||
{
|
||||
"left arm" => BodyPartType.Arm,
|
||||
"right arm" => BodyPartType.Arm,
|
||||
"left hand" => BodyPartType.Hand,
|
||||
"right hand" => BodyPartType.Hand,
|
||||
"left leg" => BodyPartType.Leg,
|
||||
"right leg" => BodyPartType.Leg,
|
||||
"left foot" => BodyPartType.Foot,
|
||||
"right foot" => BodyPartType.Foot,
|
||||
"tail" => BodyPartType.Tail,
|
||||
_ => BodyPartType.Other,
|
||||
};
|
||||
if (!_body.AttachPart(args.Part, slot, virtualIteam, bodyPart, virtualBodyPart))
|
||||
{
|
||||
args.IsCancelled = true;
|
||||
QueueDel(virtualIteam);
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryComp<HumanoidAppearanceComponent>(args.Body, out var humanoid)) //todo move to system
|
||||
{
|
||||
var layer = GetLayer(slot);
|
||||
if (layer is null)
|
||||
return;
|
||||
|
||||
var vizualizer = EnsureComp<CustomLimbVisualizerComponent>(args.Body);
|
||||
vizualizer.Layers[layer.Value] = GetNetEntity(itemId);
|
||||
Dirty(args.Body, vizualizer);
|
||||
|
||||
}
|
||||
AddItemHand(args.Body, itemId, BodySystem.GetPartSlotContainerId(slot));
|
||||
}
|
||||
|
||||
private void AddItemHand(EntityUid bodyId, EntityUid itemId, string handId)
|
||||
{
|
||||
if (!TryComp<HandsComponent>(bodyId, out var hands))
|
||||
return;
|
||||
|
||||
if (!itemId.IsValid())
|
||||
{
|
||||
Log.Debug("no valid item");
|
||||
return;
|
||||
}
|
||||
|
||||
_hands.AddHand(bodyId, handId, HandLocation.Middle, hands);
|
||||
_hands.DoPickup(bodyId, hands.Hands[handId], itemId, hands);
|
||||
EnsureComp<UnremoveableComponent>(itemId);
|
||||
}
|
||||
|
||||
private void OnStepAmputationComplete(Entity<SurgeryStepAmputationEffectComponent> ent, ref SurgeryStepEvent args)
|
||||
{
|
||||
if (TryComp(args.Body, out TransformComponent? xform)
|
||||
|
|
@ -207,55 +285,114 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
|
|||
{
|
||||
|
||||
if (!_containers.TryGetContainingContainer((args.Part, null, null), out var container)) return;
|
||||
|
||||
var parentPartAndSlot = _body.GetParentPartAndSlotOrNull(args.Part);
|
||||
if (parentPartAndSlot is null) return;
|
||||
var (_, slotId) = parentPartAndSlot.Value;
|
||||
|
||||
if (_containers.Remove(args.Part, container, destination: xform.Coordinates))
|
||||
{
|
||||
if (TryComp<HumanoidAppearanceComponent>(args.Body, out var humanoid)) //todo move to system
|
||||
if (TryComp<CustomLimbComponent>(args.Part, out var virtualLimb)
|
||||
&& virtualLimb.Item.HasValue)
|
||||
{
|
||||
var limbs = _body.GetBodyPartAdjacentParts(args.Part, limb).Concat([args.Part]); ;
|
||||
foreach (var partLimbId in limbs)
|
||||
RemoveItemHand(args.Body, virtualLimb.Item.Value, BodySystem.GetPartSlotContainerId(slotId));
|
||||
|
||||
var vizualizer = EnsureComp<CustomLimbVisualizerComponent>(args.Body);
|
||||
|
||||
var layer = GetLayer(slotId);
|
||||
if (layer is not null)
|
||||
{
|
||||
if (TryComp<BaseLayerIdComponent>(partLimbId, out var baseLayerStorage)
|
||||
&& TryComp(partLimbId, out BodyPartComponent? partLimb))
|
||||
vizualizer.Layers.Remove(layer.Value);
|
||||
Dirty(args.Body, vizualizer);
|
||||
}
|
||||
QueueDel(args.Part);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TryComp<HumanoidAppearanceComponent>(args.Body, out var humanoid)) //todo move to system
|
||||
{
|
||||
var limbs = _body.GetBodyPartAdjacentParts(args.Part, limb).Concat([args.Part]); ;
|
||||
foreach (var partLimbId in limbs)
|
||||
{
|
||||
var layer = partLimb.ToHumanoidLayers();
|
||||
if (layer is null) continue;
|
||||
if (humanoid.CustomBaseLayers.TryGetValue(layer.Value, out var customBaseLayer))
|
||||
baseLayerStorage.Layer = customBaseLayer.Id;
|
||||
else
|
||||
if (TryComp<BaseLayerIdComponent>(partLimbId, out var baseLayerStorage)
|
||||
&& TryComp(partLimbId, out BodyPartComponent? partLimb))
|
||||
{
|
||||
var bodyType = _prototypes.Index(humanoid.BodyType);
|
||||
if (bodyType.Sprites.TryGetValue(layer.Value, out var baseLayer))
|
||||
baseLayerStorage.Layer = baseLayer;
|
||||
var layer = partLimb.ToHumanoidLayers();
|
||||
if (layer is null) continue;
|
||||
if (humanoid.CustomBaseLayers.TryGetValue(layer.Value, out var customBaseLayer))
|
||||
baseLayerStorage.Layer = customBaseLayer.Id;
|
||||
else
|
||||
{
|
||||
var bodyType = _prototypes.Index(humanoid.BodyType);
|
||||
if (bodyType.Sprites.TryGetValue(layer.Value, out var baseLayer))
|
||||
baseLayerStorage.Layer = baseLayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (limb.PartType)
|
||||
{
|
||||
case BodyPartType.Arm: //todo move to systems
|
||||
foreach (var slotId in limb.Children.Keys)
|
||||
{
|
||||
if (slotId is null) continue;
|
||||
var child = _containers.GetContainer(args.Part, BodySystem.GetPartSlotContainerId(slotId));
|
||||
|
||||
foreach (var containedEnt in child.ContainedEntities)
|
||||
switch (limb.PartType)
|
||||
{
|
||||
case BodyPartType.Arm: //todo move to systems
|
||||
foreach (var limbSlotId in limb.Children.Keys)
|
||||
{
|
||||
if (TryComp(containedEnt, out BodyPartComponent? innerPart)
|
||||
&& innerPart.PartType == BodyPartType.Hand)
|
||||
_hands.RemoveHand(args.Body, BodySystem.GetPartSlotContainerId(slotId));
|
||||
if (limbSlotId is null) continue;
|
||||
var child = _containers.GetContainer(args.Part, BodySystem.GetPartSlotContainerId(limbSlotId));
|
||||
|
||||
foreach (var containedEnt in child.ContainedEntities)
|
||||
{
|
||||
if (TryComp(containedEnt, out BodyPartComponent? innerPart)
|
||||
&& innerPart.PartType == BodyPartType.Hand)
|
||||
_hands.RemoveHand(args.Body, BodySystem.GetPartSlotContainerId(limbSlotId));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BodyPartType.Hand:
|
||||
var parentSlot = _body.GetParentPartAndSlotOrNull(args.Part);
|
||||
if (parentSlot is not null)
|
||||
_hands.RemoveHand(args.Body, BodySystem.GetPartSlotContainerId(parentSlot.Value.Slot));
|
||||
break;
|
||||
case BodyPartType.Leg:
|
||||
case BodyPartType.Foot:
|
||||
break;
|
||||
break;
|
||||
case BodyPartType.Hand:
|
||||
var parentSlot = _body.GetParentPartAndSlotOrNull(args.Part);
|
||||
if (parentSlot is not null)
|
||||
_hands.RemoveHand(args.Body, BodySystem.GetPartSlotContainerId(parentSlot.Value.Slot));
|
||||
break;
|
||||
case BodyPartType.Leg:
|
||||
case BodyPartType.Foot:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void RemoveItemHand(EntityUid bodyId, EntityUid itemId, string handId)
|
||||
{
|
||||
if (!TryComp<HandsComponent>(bodyId, out var hands)
|
||||
|| !_hands.TryGetHand(bodyId, handId, out var hand, hands))
|
||||
return;
|
||||
|
||||
if (!itemId.IsValid())
|
||||
{
|
||||
Log.Debug("no valid item");
|
||||
return;
|
||||
}
|
||||
RemComp<UnremoveableComponent>(itemId);
|
||||
_hands.DoDrop(itemId, hand);
|
||||
_hands.RemoveHand(bodyId, handId, hands);
|
||||
}
|
||||
|
||||
private void CustomLimbRemoved(Entity<CustomLimbMarkerComponent> ent, ref ComponentRemove args)
|
||||
{
|
||||
if (ent.Comp.VirtualPart is null) return;
|
||||
QueueDel(ent.Comp.VirtualPart.Value);
|
||||
}
|
||||
|
||||
public static HumanoidVisualLayers? GetLayer(string slotId) => slotId switch
|
||||
{
|
||||
"left arm" => HumanoidVisualLayers.LArm,
|
||||
"right arm" => HumanoidVisualLayers.RArm,
|
||||
"left hand" => HumanoidVisualLayers.LHand,
|
||||
"right hand" => HumanoidVisualLayers.RHand,
|
||||
"left leg" => HumanoidVisualLayers.LLeg,
|
||||
"right leg" => HumanoidVisualLayers.RLeg,
|
||||
"left foot" => HumanoidVisualLayers.LFoot,
|
||||
"right foot" => HumanoidVisualLayers.RFoot,
|
||||
"tail" => HumanoidVisualLayers.Tail,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using Content.Server.Body.Systems;
|
||||
using System.Linq;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Hands.Systems;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared._Sunrise.Medical.Surgery;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Effects.Step;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Events;
|
||||
|
|
@ -11,6 +13,7 @@ using Content.Shared.Eye.Blinding.Systems;
|
|||
using Content.Shared.HealthExaminable;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Prototypes;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
|
@ -31,6 +34,8 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
|
|||
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||
[Dependency] private readonly ContainerSystem _containers = default!;
|
||||
[Dependency] private readonly BlindableSystem _blindable = default!;
|
||||
[Dependency] private readonly TagSystem _tag = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metadata = default!;
|
||||
|
||||
private readonly List<EntProtoId> _surgeries = [];
|
||||
public override void Initialize()
|
||||
|
|
@ -61,40 +66,52 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
|
|||
return;
|
||||
|
||||
var surgeries = new Dictionary<NetEntity, List<(EntProtoId, string suffix, bool isCompleted)>>();
|
||||
foreach (var part in _body.GetBodyChildren(body))
|
||||
if (HasComp<BodyPartComponent>(body))
|
||||
{
|
||||
if (!TryComp<SurgeryProgressComponent>(part.Id, out var progress))
|
||||
AddSurgeries(body, body, surgeries);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var part in _body.GetBodyChildren(body))
|
||||
{
|
||||
progress = new SurgeryProgressComponent();
|
||||
AddComp(part.Id, progress);
|
||||
}
|
||||
|
||||
foreach (var surgery in _surgeries)
|
||||
{
|
||||
if (GetSingleton(surgery) is not { } surgeryEnt
|
||||
|| !TryComp(surgeryEnt, out SurgeryComponent? surgeryComp)
|
||||
|| (surgeryComp.Requirement is not null && !progress.CompletedSurgeries.Contains(surgeryComp.Requirement.Value)))
|
||||
continue;
|
||||
|
||||
var ev = new SurgeryValidEvent(body, part.Id);
|
||||
|
||||
var isCompleted = progress.CompletedSurgeries.Contains(surgery);
|
||||
if (!progress.StartedSurgeries.Contains(surgery)
|
||||
&& !isCompleted)
|
||||
{
|
||||
RaiseLocalEvent(surgeryEnt, ref ev);
|
||||
|
||||
if (ev.Cancelled)
|
||||
continue;
|
||||
}
|
||||
|
||||
surgeries.GetOrNew(GetNetEntity(part.Id)).Add((surgery, ev.Suffix, isCompleted));
|
||||
AddSurgeries(part.Id, body, surgeries);
|
||||
}
|
||||
}
|
||||
|
||||
_ui.SetUiState(body, SurgeryUIKey.Key, new SurgeryBuiState() { Choices = surgeries });
|
||||
}
|
||||
|
||||
private void AddSurgeries(EntityUid part, EntityUid body, Dictionary<NetEntity, List<(EntProtoId, string suffix, bool isCompleted)>> surgeries)
|
||||
{
|
||||
if (!TryComp<SurgeryProgressComponent>(part, out var progress))
|
||||
{
|
||||
progress = new SurgeryProgressComponent();
|
||||
AddComp(part, progress);
|
||||
}
|
||||
|
||||
foreach (var surgery in _surgeries)
|
||||
{
|
||||
if (GetSingleton(surgery) is not { } surgeryEnt
|
||||
|| !TryComp(surgeryEnt, out SurgeryComponent? surgeryComp)
|
||||
|| (surgeryComp.Requirement.Count() > 0 && !progress.CompletedSurgeries.Any(x => surgeryComp.Requirement.Contains(x))))
|
||||
continue;
|
||||
|
||||
var ev = new SurgeryValidEvent(body, part);
|
||||
|
||||
var isCompleted = progress.CompletedSurgeries.Contains(surgery);
|
||||
if (!progress.StartedSurgeries.Contains(surgery)
|
||||
&& !isCompleted)
|
||||
{
|
||||
RaiseLocalEvent(surgeryEnt, ref ev);
|
||||
|
||||
if (ev.Cancelled)
|
||||
continue;
|
||||
}
|
||||
|
||||
surgeries.GetOrNew(GetNetEntity(part)).Add((surgery, ev.Suffix, isCompleted));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnToolAfterInteract(Entity<SurgeryToolComponent> ent, ref AfterInteractEvent args)
|
||||
{
|
||||
var user = args.User;
|
||||
|
|
@ -106,7 +123,7 @@ public sealed partial class SurgerySystem : SharedSurgerySystem
|
|||
|
||||
if (user == args.Target)
|
||||
{
|
||||
_popup.PopupEntity("You can't perform surgery on yourself!", user, user);
|
||||
_popup.PopupEntity(Loc.GetString("cant-perform-operation-on-yourself"), user, user);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ using Content.Shared.Body.Systems;
|
|||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using Content.Shared._Sunrise.Medical.Surgery;
|
||||
|
||||
namespace Content.Shared.Body.Part;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
[Access(typeof(SharedBodySystem))]
|
||||
[Access(typeof(SharedBodySystem), typeof(SharedSurgerySystem))] // Sunrise-edit
|
||||
public sealed partial class BodyPartComponent : Component
|
||||
{
|
||||
// Need to set this on container changes as it may be several transform parents up the hierarchy.
|
||||
|
|
|
|||
|
|
@ -40,11 +40,23 @@ public sealed class BodyPrototypeSerializer : ITypeReader<BodyPrototype, Mapping
|
|||
{
|
||||
foreach (var (key, value) in organsNode)
|
||||
{
|
||||
// STARLIGHT-SURGERY start
|
||||
// if (key is not ValueDataNode)
|
||||
// {
|
||||
// nodes.Add(new ErrorNode(key, $"Key is not a value data node"));
|
||||
// continue;
|
||||
// }
|
||||
// STARLIGHT-SURGERY end
|
||||
|
||||
if (value is not ValueDataNode organ)
|
||||
{
|
||||
nodes.Add(new ErrorNode(value, $"Value is not a value data node"));
|
||||
continue;
|
||||
}
|
||||
// STARLIGHT-SURGERY start
|
||||
if (organ.Value == "null" || organ.Value == null)
|
||||
continue;
|
||||
// STARLIGHT-SURGERY end
|
||||
|
||||
if (!prototypes.TryIndex(organ.Value, out EntityPrototype? organPrototype))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -205,6 +205,12 @@ public partial class SharedBodySystem
|
|||
foreach (var (organSlotId, organProto) in organs)
|
||||
{
|
||||
var slot = CreateOrganSlot((ent, ent), organSlotId);
|
||||
|
||||
// Starlight-surgery start
|
||||
if (organProto == "null")
|
||||
return;
|
||||
// Starlight-surgery end
|
||||
|
||||
SpawnInContainerOrDrop(organProto, ent, GetOrganContainerId(organSlotId));
|
||||
|
||||
if (slot is null)
|
||||
|
|
|
|||
|
|
@ -602,6 +602,36 @@ public partial class SharedBodySystem
|
|||
}
|
||||
}
|
||||
}
|
||||
// Sunrise-Start
|
||||
public IEnumerable<Entity<BodyPartComponent>> GetAllBodyPart(
|
||||
EntityUid partId,
|
||||
BodyPartComponent? part = null)
|
||||
{
|
||||
if (!Resolve(partId, ref part, logMissing: false))
|
||||
yield break;
|
||||
|
||||
foreach (var (slotId, slot) in part.Children)
|
||||
{
|
||||
var containerSlotId = GetPartSlotContainerId(slotId);
|
||||
|
||||
if (Containers.TryGetContainer(partId, containerSlotId, out var container))
|
||||
{
|
||||
foreach (var containedEnt in container.ContainedEntities)
|
||||
{
|
||||
if (!TryComp(containedEnt, out BodyPartComponent? childPart))
|
||||
continue;
|
||||
yield return (containedEnt, childPart);
|
||||
|
||||
foreach (var subPart in GetAllBodyPart(containedEnt, childPart))
|
||||
{
|
||||
yield return subPart;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Sunrise-End
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the bodyId has any parts of this type.
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ using Robust.Shared.Prototypes;
|
|||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Random;
|
||||
using Content.Shared._Sunrise.Medical.Damage;
|
||||
|
||||
namespace Content.Shared.Damage
|
||||
{
|
||||
|
|
@ -239,6 +240,17 @@ namespace Content.Shared.Damage
|
|||
|
||||
damage = ApplyUniversalAllModifiers(damage);
|
||||
|
||||
// Sunrise-start
|
||||
var finalEv = new DamageBeforeApplyEvent
|
||||
{
|
||||
Damage = damage,
|
||||
Origin = origin
|
||||
};
|
||||
RaiseLocalEvent(uid.Value, finalEv);
|
||||
if (finalEv.Cancelled)
|
||||
return damage;
|
||||
// Sunrise-end
|
||||
|
||||
// TODO DAMAGE PERFORMANCE
|
||||
// Consider using a local private field instead of creating a new dictionary here.
|
||||
// Would need to check that nothing ever tries to cache the delta.
|
||||
|
|
|
|||
|
|
@ -550,9 +550,12 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var markingObject = new Marking(marking, colors);
|
||||
markingObject.Forced = forced;
|
||||
// Sunrise-start
|
||||
var markingObject = new Marking(marking, colors)
|
||||
{
|
||||
Forced = forced
|
||||
};
|
||||
// Sunrise-end
|
||||
humanoid.MarkingSet.AddBack(prototype.MarkingCategory, markingObject);
|
||||
|
||||
if (sync)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Inventory;
|
||||
|
||||
namespace Content.Shared._Sunrise.Medical.Damage;
|
||||
public sealed class DamageBeforeApplyEvent : EntityEventArgs
|
||||
{
|
||||
public required DamageSpecifier Damage;
|
||||
public EntityUid? Origin;
|
||||
|
||||
public bool Cancelled { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using Content.Shared.DisplacementMap;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Item;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
namespace Content.Shared._Sunrise.Medical.Surgery;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
||||
public sealed partial class CustomLimbVisualizerComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public Dictionary<HumanoidVisualLayers, NetEntity?> Layers = [];
|
||||
|
||||
[DataField]
|
||||
public HashSet<HumanoidVisualLayers> CachedLayers = [];
|
||||
|
||||
[DataField]
|
||||
public Dictionary<HumanoidVisualLayers, DisplacementData> Displacements = [];
|
||||
}
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class CustomLimbComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntityUid? Item;
|
||||
}
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class CustomLimbMarkerComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntityUid? VirtualPart;
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ public sealed partial class SurgeryComponent : Component
|
|||
public int Priority;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntProtoId? Requirement;
|
||||
public List<EntProtoId> Requirement = [];
|
||||
|
||||
[DataField(required: true), AutoNetworkedField]
|
||||
public List<EntProtoId> Steps = new();
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ public sealed partial class SurgeryProgressComponent : Component
|
|||
|
||||
[DataField, AutoNetworkedField]
|
||||
public HashSet<EntProtoId> StartedSurgeries = [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Item;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
// Based on the RMC14.
|
||||
|
|
@ -9,6 +11,20 @@ namespace Content.Shared._Sunrise.Medical.Surgery.Effects.Step;
|
|||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class SurgeryAnyLimbSlotConditionComponent : Component;
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class SurgeryOperatingTableConditionComponent : Component;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
public sealed partial class SurgeryLimbSlotConditionComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public string Slot;
|
||||
}
|
||||
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
public sealed partial class SurgeryItemSizeConditionComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public ProtoId<ItemSizePrototype> Size = "Small";
|
||||
}
|
||||
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
public sealed partial class SurgeryPartConditionComponent : Component
|
||||
{
|
||||
|
|
@ -16,14 +32,35 @@ public sealed partial class SurgeryPartConditionComponent : Component
|
|||
public List<BodyPartType> Parts = [];
|
||||
}
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
public sealed partial class SurgerySpeciesConditionComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public HashSet<ProtoId<SpeciesPrototype>> SpeciesBlacklist = [];
|
||||
|
||||
[DataField]
|
||||
public HashSet<ProtoId<SpeciesPrototype>> SpeciesWhitelist = [];
|
||||
}
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
public sealed partial class SurgeryOrganExistConditionComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public ComponentRegistry? Organ;
|
||||
|
||||
[DataField]
|
||||
public string? Container;
|
||||
}
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
public sealed partial class SurgeryHasCompConditionComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public ComponentRegistry? Component;
|
||||
}
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
public sealed partial class SurgeryOrganDontExistConditionComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public ComponentRegistry? Organ;
|
||||
}
|
||||
|
||||
[DataField]
|
||||
public string? Container;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
namespace Content.Shared._Sunrise.Medical.Surgery.Steps.Parts;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class EyeImplantComponent : Component;
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class OrganBrainComponent : Component;
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class OrganAppendixComponent : Component;
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class OrganEarsComponent : Component;
|
||||
|
|
@ -11,14 +14,14 @@ namespace Content.Shared._Sunrise.Medical.Surgery.Steps.Parts;
|
|||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class OrganStomachComponent : Component;
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class OrganLiverComponent : Component;
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class OrganKidneysComponent : Component;
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class OrganTongueComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public bool IsMuted;
|
||||
}
|
||||
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class OrganEyesComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
|
|
@ -26,10 +29,25 @@ public sealed partial class OrganEyesComponent : Component
|
|||
[DataField]
|
||||
public int? MinDamage;
|
||||
}
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class OrganVisualizationComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public HumanoidVisualLayers Layer;
|
||||
[DataField]
|
||||
public ProtoId<HumanoidSpeciesSpriteLayer> Prototype;
|
||||
}
|
||||
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
public sealed partial class FunctionalOrganComponent : Component
|
||||
{
|
||||
[DataField("comps")]
|
||||
public ComponentRegistry? Components;
|
||||
}
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class OrganDamageComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public DamageSpecifier? Damage;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,13 @@ public sealed partial class SurgeryStepOrganExtractComponent : Component
|
|||
{
|
||||
[DataField]
|
||||
public ComponentRegistry? Organ;
|
||||
|
||||
[DataField]
|
||||
public string? Slot;
|
||||
}
|
||||
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))]
|
||||
public sealed partial class SurgeryStepOrganInsertComponent : Component
|
||||
public sealed partial class SurgeryStepOrganInsertComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public string Slot;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Content.Shared._Sunrise.Medical.Surgery.Effects.Step;
|
|||
{
|
||||
[DataField]
|
||||
public DamageSpecifier? Damage;
|
||||
};
|
||||
}
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class SurgeryStepAmputationEffectComponent : Component;
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class SurgeryRemoveAccentComponent : Component;
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedSurgerySystem))] public sealed partial class SurgeryClearProgressComponent : Component;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ public sealed partial class SurgeryToolComponent : Component
|
|||
[DataField, AutoNetworkedField]
|
||||
public float Speed = 1;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public float SuccessRate = 1f;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public SoundSpecifier? StartSound;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,12 @@ public sealed partial class SurgeryDoAfterEvent : SimpleDoAfterEvent
|
|||
{
|
||||
public readonly EntProtoId Surgery;
|
||||
public readonly EntProtoId Step;
|
||||
public readonly float SuccessRate;
|
||||
|
||||
public SurgeryDoAfterEvent(EntProtoId surgery, EntProtoId step)
|
||||
public SurgeryDoAfterEvent(EntProtoId surgery, EntProtoId step, float successRate)
|
||||
{
|
||||
Surgery = surgery;
|
||||
Step = step;
|
||||
SuccessRate = successRate;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._Sunrise.Medical.Surgery.Events;
|
||||
// Based on the RMC14.
|
||||
// https://github.com/RMC-14/RMC-14
|
||||
[ByRefEvent]
|
||||
public record struct SurgeryOrganImplantationCompleted(EntityUid Body, EntityUid Part, EntityUid Organ);
|
||||
[ByRefEvent]
|
||||
public record struct SurgeryOrganExtracted(EntityUid Body, EntityUid Part, EntityUid Organ);
|
||||
|
|
@ -8,6 +8,13 @@ namespace Content.Shared._Sunrise.Medical.Surgery.Events;
|
|||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct SurgeryStepEvent(EntityUid User, EntityUid Body, EntityUid Part, List<EntityUid> Tools)
|
||||
{
|
||||
public required EntProtoId StepProto { get; init; }
|
||||
public required EntProtoId SurgeryProto { get; init; }
|
||||
public bool IsCancelled { get; set; }
|
||||
}
|
||||
[ByRefEvent]
|
||||
public record struct SurgeryStepCompleteEvent(EntityUid User, EntityUid Body, EntityUid Part, List<EntityUid> Tools)
|
||||
{
|
||||
public required EntProtoId StepProto { get; init; }
|
||||
public required EntProtoId SurgeryProto { get; init; }
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
using Content.Shared._Sunrise.Medical.Surgery.Steps;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Item.ItemToggle.Components;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Events;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Effects.Step;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Events;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Steps;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Shared._Sunrise.Medical.Surgery;
|
||||
|
|
@ -14,13 +17,15 @@ namespace Content.Shared._Sunrise.Medical.Surgery;
|
|||
// https://github.com/RMC-14/RMC-14
|
||||
public abstract partial class SharedSurgerySystem
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
protected float _delayAccumulator = 0f;
|
||||
protected readonly Queue<Action> _delayQueue = new();
|
||||
private void InitializeSteps()
|
||||
{
|
||||
SubscribeLocalEvent<SurgeryStepComponent, SurgeryStepCompleteEvent>(OnStepComplete);
|
||||
SubscribeLocalEvent<SurgeryClearProgressComponent, SurgeryStepCompleteEvent>(OnClearProgressStep);
|
||||
SubscribeLocalEvent<SurgeryStepComponent, SurgeryStepEvent>(OnStep);
|
||||
SubscribeLocalEvent<SurgeryClearProgressComponent, SurgeryStepEvent>(OnClearProgressStep);
|
||||
SubscribeLocalEvent<SurgeryTargetComponent, SurgeryDoAfterEvent>(OnTargetDoAfter);
|
||||
|
||||
SubscribeLocalEvent<SurgeryStepComponent, SurgeryCanPerformStepEvent>(OnCanPerformStep);
|
||||
|
|
@ -43,47 +48,63 @@ public abstract partial class SharedSurgerySystem
|
|||
return;
|
||||
}
|
||||
|
||||
if (!_random.Prob(args.SuccessRate))
|
||||
{
|
||||
if (_net.IsClient) return;
|
||||
_popup.PopupClient(Loc.GetString("surgery-careless-tool"), args.User, PopupType.SmallCaution);
|
||||
return;
|
||||
}
|
||||
|
||||
var ev = new SurgeryStepEvent(args.User, ent, part, GetTools(args.User))
|
||||
{
|
||||
StepProto = args.Step,
|
||||
SurgeryProto = args.Surgery,
|
||||
};
|
||||
RaiseLocalEvent(step, ref ev);
|
||||
|
||||
if (ev.IsCancelled) return;
|
||||
var evComplete = new SurgeryStepCompleteEvent(args.User, ent, part, GetTools(args.User))
|
||||
{
|
||||
StepProto = args.Step,
|
||||
SurgeryProto = args.Surgery,
|
||||
IsFinal = surgery.Comp.Steps[^1] == args.Step,
|
||||
};
|
||||
RaiseLocalEvent(step, ref ev);
|
||||
RaiseLocalEvent(step, ref evComplete);
|
||||
|
||||
if (_net.IsClient) return;
|
||||
_delayAccumulator = 0f;
|
||||
_delayQueue.Enqueue(() => RefreshUI(ent));
|
||||
}
|
||||
|
||||
private void OnClearProgressStep(Entity<SurgeryClearProgressComponent> ent, ref SurgeryStepEvent args)
|
||||
private void OnClearProgressStep(Entity<SurgeryClearProgressComponent> ent, ref SurgeryStepCompleteEvent args)
|
||||
{
|
||||
var progress = Comp<SurgeryProgressComponent>(args.Part);
|
||||
progress.CompletedSteps.Clear();
|
||||
progress.CompletedSurgeries.Clear();
|
||||
}
|
||||
|
||||
private void OnStepComplete(Entity<SurgeryStepComponent> ent, ref SurgeryStepCompleteEvent args)
|
||||
{
|
||||
if (TryComp<SurgeryClearProgressComponent>(ent, out _)) return;
|
||||
if (TryComp<SurgeryProgressComponent>(args.Part, out var progress))
|
||||
{
|
||||
progress.CompletedSteps.Add($"{args.SurgeryProto}:{args.StepProto}");
|
||||
if (!progress.StartedSurgeries.Contains(args.SurgeryProto) && !args.IsFinal)
|
||||
progress.StartedSurgeries.Add(args.SurgeryProto);
|
||||
if (progress.StartedSurgeries.Contains(args.SurgeryProto) && args.IsFinal)
|
||||
progress.StartedSurgeries.Remove(args.SurgeryProto);
|
||||
}
|
||||
else
|
||||
{
|
||||
progress = new SurgeryProgressComponent { CompletedSteps = [$"{args.SurgeryProto}:{args.StepProto}"]};
|
||||
if(!args.IsFinal)
|
||||
progress.StartedSurgeries.Add(args.SurgeryProto);
|
||||
AddComp(args.Part, progress);
|
||||
}
|
||||
if (args.IsFinal)
|
||||
progress.CompletedSurgeries.Add(args.SurgeryProto);
|
||||
}
|
||||
private void OnStep(Entity<SurgeryStepComponent> ent, ref SurgeryStepEvent args)
|
||||
{
|
||||
if (!TryComp<SurgeryClearProgressComponent>(ent, out _))
|
||||
{
|
||||
if (TryComp<SurgeryProgressComponent>(args.Part, out var progress))
|
||||
{
|
||||
progress.CompletedSteps.Add($"{args.SurgeryProto}:{args.StepProto}");
|
||||
if(!progress.StartedSurgeries.Contains(args.SurgeryProto) && !args.IsFinal)
|
||||
progress.StartedSurgeries.Add(args.SurgeryProto);
|
||||
if (progress.StartedSurgeries.Contains(args.SurgeryProto) && args.IsFinal)
|
||||
progress.StartedSurgeries.Remove(args.SurgeryProto);
|
||||
}
|
||||
else
|
||||
{
|
||||
progress = new SurgeryProgressComponent { CompletedSteps = [$"{args.SurgeryProto}:{args.StepProto}"] };
|
||||
AddComp(args.Part, progress);
|
||||
}
|
||||
if (args.IsFinal)
|
||||
progress.CompletedSurgeries.Add(args.SurgeryProto);
|
||||
}
|
||||
|
||||
foreach (var reg in (ent.Comp.Tools ?? []).Values)
|
||||
{
|
||||
var tool = args.Tools.FirstOrDefault(x => HasComp(x, reg.Component.GetType()));
|
||||
|
|
@ -130,6 +151,28 @@ public abstract partial class SharedSurgerySystem
|
|||
|
||||
RaiseLocalEvent(args.Body, ref args);
|
||||
|
||||
if (args.Invalid != StepInvalidReason.None)
|
||||
return;
|
||||
|
||||
if (_inventory.TryGetContainerSlotEnumerator(args.Body, out var enumerator, args.TargetSlots))
|
||||
{
|
||||
var items = 0f;
|
||||
var total = 0f;
|
||||
while (enumerator.MoveNext(out var con))
|
||||
{
|
||||
total++;
|
||||
if (con.ContainedEntity != null)
|
||||
items++;
|
||||
}
|
||||
|
||||
if (items > 0)
|
||||
{
|
||||
args.Invalid = StepInvalidReason.Armor;
|
||||
args.Popup = Loc.GetString("surgery-need-remove-armor");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.Invalid != StepInvalidReason.None || ent.Comp.Tools == null)
|
||||
return;
|
||||
|
||||
|
|
@ -141,10 +184,24 @@ public abstract partial class SharedSurgerySystem
|
|||
args.Invalid = StepInvalidReason.MissingTool;
|
||||
|
||||
if (reg.Component is ISurgeryToolComponent toolComp)
|
||||
args.Popup = $"You need {toolComp.ToolName} to perform this step!";
|
||||
args.Popup = Loc.GetString("surgery-need-tool");
|
||||
|
||||
return;
|
||||
}
|
||||
else if (TryComp<ItemToggleComponent>(tool, out var togglable) && !togglable.Activated)
|
||||
{
|
||||
args.Invalid = StepInvalidReason.DisabledTool;
|
||||
|
||||
if (reg.Component is ISurgeryToolComponent toolComp)
|
||||
args.Popup = Loc.GetString("surgery-need-enable");
|
||||
|
||||
return;
|
||||
}
|
||||
else if (TryComp<SurgeryItemSizeConditionComponent>(ent, out var itemSizeComp) && TryComp<ItemComponent>(tool, out var item) && _item.GetSizePrototype(item.Size) > _item.GetSizePrototype(itemSizeComp.Size))
|
||||
{
|
||||
args.Invalid = StepInvalidReason.TooHigh;
|
||||
return;
|
||||
}
|
||||
|
||||
args.ValidTools.Add(tool);
|
||||
}
|
||||
|
|
@ -162,7 +219,7 @@ public abstract partial class SharedSurgerySystem
|
|||
{
|
||||
return;
|
||||
}
|
||||
if(!PreviousStepsComplete(body, part, surgery, args.Step) || IsStepComplete(part, args.Surgery, args.Step))
|
||||
if (!PreviousStepsComplete(body, part, surgery, args.Step) || IsStepComplete(part, args.Surgery, args.Step))
|
||||
{
|
||||
var progress = Comp<SurgeryProgressComponent>(part);
|
||||
Dirty(part, progress);
|
||||
|
|
@ -173,17 +230,22 @@ public abstract partial class SharedSurgerySystem
|
|||
|
||||
var duration = stepComp.Duration;
|
||||
|
||||
float SmallestSuccessRate = 1f;
|
||||
|
||||
foreach (var tool in validTools)
|
||||
if (TryComp(tool, out SurgeryToolComponent? toolComp))
|
||||
{
|
||||
duration *= toolComp.Speed;
|
||||
if (toolComp.StartSound != null) _audio.PlayPvs(toolComp.StartSound, tool);
|
||||
|
||||
if(toolComp.SuccessRate < SmallestSuccessRate)
|
||||
SmallestSuccessRate = toolComp.SuccessRate;
|
||||
}
|
||||
|
||||
if (TryComp(body, out TransformComponent? xform))
|
||||
_rotateToFace.TryFaceCoordinates(user, _transform.GetMapCoordinates(body, xform).Position);
|
||||
|
||||
var ev = new SurgeryDoAfterEvent(args.Surgery, args.Step);
|
||||
var ev = new SurgeryDoAfterEvent(args.Surgery, args.Step, SmallestSuccessRate);
|
||||
var doAfter = new DoAfterArgs(EntityManager, user, duration, ev, body, part)
|
||||
{
|
||||
BreakOnMove = true,
|
||||
|
|
@ -204,10 +266,16 @@ public abstract partial class SharedSurgerySystem
|
|||
|
||||
requirements.Add(surgery);
|
||||
|
||||
if (surgery.Comp.Requirement is { } requirementId &&
|
||||
GetSingleton(requirementId) is { } requirement &&
|
||||
GetNextStep(body, part, requirement, requirements) is { } requiredNext)
|
||||
return requiredNext;
|
||||
if (surgery.Comp.Requirement is { } requirementsIds)
|
||||
{
|
||||
foreach (var requirementId in requirementsIds)
|
||||
{
|
||||
if (GetSingleton(requirementId) is { } requirement
|
||||
&& GetNextStep(body, part, requirement, requirements) is { } requiredNext
|
||||
&& IsSurgeryValid(body, part, requirementId, requiredNext.Surgery.Comp.Steps[requiredNext.Step], out _, out _, out _))
|
||||
return requiredNext;
|
||||
}
|
||||
}
|
||||
|
||||
if (!TryComp<SurgeryProgressComponent>(part, out var progress))
|
||||
{
|
||||
|
|
@ -224,13 +292,15 @@ public abstract partial class SharedSurgerySystem
|
|||
|
||||
public bool PreviousStepsComplete(EntityUid body, EntityUid part, Entity<SurgeryComponent> surgery, EntProtoId step)
|
||||
{
|
||||
if (surgery.Comp.Requirement is { } requirement)
|
||||
if (surgery.Comp.Requirement is { } requirements)
|
||||
{
|
||||
if (GetSingleton(requirement) is not { } requiredEnt ||
|
||||
!TryComp(requiredEnt, out SurgeryComponent? requiredComp) ||
|
||||
!PreviousStepsComplete(body, part, (requiredEnt, requiredComp), step))
|
||||
foreach (var requirement in requirements)
|
||||
{
|
||||
return false;
|
||||
if (GetSingleton(requirement) is not { } requiredEnt
|
||||
|| !TryComp(requiredEnt, out SurgeryComponent? requiredComp)
|
||||
|| !PreviousStepsComplete(body, part, (requiredEnt, requiredComp), step)
|
||||
&& IsSurgeryValid(body, part, requirement, step, out _, out _, out _))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +321,7 @@ public abstract partial class SharedSurgerySystem
|
|||
{
|
||||
var slot = part switch
|
||||
{
|
||||
BodyPartType.Head => SlotFlags.HEAD,
|
||||
BodyPartType.Head => SlotFlags.HEAD | SlotFlags.MASK | SlotFlags.EYES,
|
||||
BodyPartType.Torso => SlotFlags.OUTERCLOTHING | SlotFlags.INNERCLOTHING,
|
||||
BodyPartType.Arm => SlotFlags.OUTERCLOTHING | SlotFlags.INNERCLOTHING,
|
||||
BodyPartType.Hand => SlotFlags.GLOVES,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Humanoid;
|
||||
using System.Linq;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Steps.Parts;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Events;
|
||||
using Content.Shared._Sunrise.Medical.Surgery.Effects.Step;
|
||||
using Content.Shared.Body.Systems;
|
||||
|
||||
namespace Content.Shared._Sunrise.Medical.Surgery;
|
||||
// Based on the RMC14.
|
||||
|
|
@ -17,33 +20,86 @@ public abstract partial class SharedSurgerySystem
|
|||
.ToList();
|
||||
|
||||
SubscribeLocalEvent<SurgeryPartConditionComponent, SurgeryValidEvent>(OnPartConditionValid);
|
||||
SubscribeLocalEvent<SurgerySpeciesConditionComponent, SurgeryValidEvent>(OnSpeciesConditionValid);
|
||||
SubscribeLocalEvent<SurgeryOrganExistConditionComponent, SurgeryValidEvent>(OnOrganExistConditionValid);
|
||||
SubscribeLocalEvent<SurgeryOrganDontExistConditionComponent, SurgeryValidEvent>(OnOrganDontExistConditionValid);
|
||||
SubscribeLocalEvent<SurgeryAnyAccentConditionComponent, SurgeryValidEvent>(OnAnyAccentConditionValid);
|
||||
SubscribeLocalEvent<SurgeryAnyLimbSlotConditionComponent, SurgeryValidEvent>(OnAnyLimbSlotConditionValid);
|
||||
SubscribeLocalEvent<SurgeryLimbSlotConditionComponent, SurgeryValidEvent>(OnLimbSlotConditionValid);
|
||||
}
|
||||
|
||||
private void OnOrganDontExistConditionValid(Entity<SurgeryOrganDontExistConditionComponent> ent, ref SurgeryValidEvent args)
|
||||
{
|
||||
if (ent.Comp.Organ?.Count != 1) return;
|
||||
var type = ent.Comp.Organ.Values.First().Component.GetType();
|
||||
|
||||
var organs = _body.GetPartOrgans(args.Part, Comp<BodyPartComponent>(args.Part));
|
||||
foreach (var organ in organs)
|
||||
if (HasComp(organ.Id, type))
|
||||
if (ent.Comp.Container != null)
|
||||
{
|
||||
foreach (var slotId in Comp<BodyPartComponent>(args.Part).Organs.Keys)
|
||||
{
|
||||
args.Cancelled = true;
|
||||
return;
|
||||
if (ent.Comp.Container == slotId)
|
||||
{
|
||||
if (!_containers.TryGetContainer(args.Part, ent.Comp.Container, out var container))
|
||||
continue;
|
||||
|
||||
foreach (var containedEnt in container.ContainedEntities)
|
||||
{
|
||||
if (HasComp(containedEnt, type))
|
||||
{
|
||||
args.Cancelled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var organs = _body.GetPartOrgans(args.Part, Comp<BodyPartComponent>(args.Part));
|
||||
foreach (var organ in organs)
|
||||
if (HasComp(organ.Id, type))
|
||||
{
|
||||
args.Cancelled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void OnOrganExistConditionValid(Entity<SurgeryOrganExistConditionComponent> ent, ref SurgeryValidEvent args)
|
||||
{
|
||||
if (ent.Comp.Organ?.Count != 1) return;
|
||||
var organs = _body.GetPartOrgans(args.Part, Comp<BodyPartComponent>(args.Part));
|
||||
|
||||
var type = ent.Comp.Organ.Values.First().Component.GetType();
|
||||
foreach (var organ in organs)
|
||||
if (HasComp(organ.Id, type))
|
||||
return;
|
||||
args.Cancelled = true;
|
||||
|
||||
EntityUid mainPart = args.Part;
|
||||
|
||||
if (TryComp<BodyPartComponent>(args.Body, out var itemPart))
|
||||
mainPart = args.Body;
|
||||
|
||||
if (ent.Comp.Container != null)
|
||||
{
|
||||
foreach (var slotId in Comp<BodyPartComponent>(mainPart).Organs.Keys)
|
||||
{
|
||||
if (ent.Comp.Container == slotId)
|
||||
{
|
||||
if (!_containers.TryGetContainer(mainPart, SharedBodySystem.GetOrganContainerId(ent.Comp.Container), out var container))
|
||||
continue;
|
||||
|
||||
foreach (var containedEnt in container.ContainedEntities)
|
||||
if (HasComp(containedEnt, type))
|
||||
return;
|
||||
|
||||
args.Cancelled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var organs = _body.GetPartOrgans(mainPart, Comp<BodyPartComponent>(mainPart));
|
||||
foreach (var organ in organs)
|
||||
if (HasComp(organ.Id, type))
|
||||
return;
|
||||
args.Cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPartConditionValid(Entity<SurgeryPartConditionComponent> ent, ref SurgeryValidEvent args)
|
||||
|
|
@ -51,9 +107,35 @@ public abstract partial class SharedSurgerySystem
|
|||
if (ent.Comp.Parts.Count == 0)
|
||||
return;
|
||||
|
||||
if (TryComp<BodyPartComponent>(args.Body, out var itemPart) && itemPart.PartType is BodyPartType item && !ent.Comp.Parts.Contains(item))
|
||||
{
|
||||
Logger.Warning("don't have part at part");
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
if (CompOrNull<BodyPartComponent>(args.Part)?.PartType is BodyPartType part && !ent.Comp.Parts.Contains(part))
|
||||
args.Cancelled = true;
|
||||
}
|
||||
private void OnSpeciesConditionValid(Entity<SurgerySpeciesConditionComponent> ent, ref SurgeryValidEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent<HumanoidAppearanceComponent>(args.Body, out var humanoidAppearanceComponent))
|
||||
{
|
||||
args.Cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ent.Comp.SpeciesBlacklist.Contains(humanoidAppearanceComponent.Species))
|
||||
{
|
||||
args.Cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ent.Comp.SpeciesWhitelist.Count > 0 && !ent.Comp.SpeciesWhitelist.Contains(humanoidAppearanceComponent.Species))
|
||||
{
|
||||
args.Cancelled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
private void OnAnyAccentConditionValid(Entity<SurgeryAnyAccentConditionComponent> ent, ref SurgeryValidEvent args)
|
||||
{
|
||||
foreach (var accent in _accents)
|
||||
|
|
@ -71,4 +153,7 @@ public abstract partial class SharedSurgerySystem
|
|||
else
|
||||
args.Cancelled = true;
|
||||
}
|
||||
private void OnLimbSlotConditionValid(Entity<SurgeryLimbSlotConditionComponent> ent, ref SurgeryValidEvent args)
|
||||
=> args.Cancelled = !(_containers.TryGetContainer(args.Part, SharedBodySystem.GetPartSlotContainerId(ent.Comp.Slot), out var container)
|
||||
&& container.ContainedEntities.Count == 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ using Content.Shared.DoAfter;
|
|||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Standing;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
|
|
@ -43,6 +45,8 @@ public abstract partial class SharedSurgerySystem : EntitySystem
|
|||
[Dependency] private readonly ISerializationManager _serialization = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _containers = default!;
|
||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||
[Dependency] private readonly SharedItemSystem _item = default!;
|
||||
|
||||
private readonly Dictionary<EntProtoId, EntityUid> _surgeries = new();
|
||||
|
||||
|
|
@ -61,7 +65,7 @@ public abstract partial class SharedSurgerySystem : EntitySystem
|
|||
_surgeries.Clear();
|
||||
}
|
||||
|
||||
protected bool IsSurgeryValid(EntityUid body, EntityUid targetPart, EntProtoId surgery, EntProtoId stepId, out Entity<SurgeryComponent> surgeryEnt, out Entity<BodyPartComponent> part, out EntityUid step)
|
||||
public bool IsSurgeryValid(EntityUid body, EntityUid targetPart, EntProtoId surgery, EntProtoId stepId, out Entity<SurgeryComponent> surgeryEnt, out Entity<BodyPartComponent> part, out EntityUid step)
|
||||
{
|
||||
surgeryEnt = default;
|
||||
part = default;
|
||||
|
|
@ -125,6 +129,9 @@ public abstract partial class SharedSurgerySystem : EntitySystem
|
|||
if (_standing.IsDown(entity))
|
||||
return true;
|
||||
|
||||
if (HasComp<ItemComponent>(entity))
|
||||
return true;
|
||||
|
||||
if (TryComp(entity, out BuckleComponent? buckle) &&
|
||||
TryComp(buckle.BuckledTo, out StrapComponent? strap))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,4 +7,6 @@ public enum StepInvalidReason
|
|||
NeedsOperatingTable,
|
||||
Armor,
|
||||
MissingTool,
|
||||
DisabledTool,
|
||||
TooHigh,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
surgery-careless-tool = Из-за небрежного обращения с инструментом ваша рука дрогнула. Вам придется начать этот шаг заново!
|
||||
surgery-need-remove-armor = Чтобы выполнить этот шаг, необходимо снять броню с пациента!
|
||||
surgery-need-tool = Вам необходим {toolComp.ToolName} чтобы выполнить этот шаг!
|
||||
surgery-need-enable = Вам необходимо включить {toolComp.ToolName} чтобы выполнить шаг!
|
||||
|
|
@ -0,0 +1 @@
|
|||
cant-perform-operation-on-yourself = Вы не можете провести операцию на самом себе!
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
surgery-window-name = Хирургия
|
||||
surgery-window-partsbutton-name = Части тела
|
||||
surgery-window-surgeriesbutton-name = Операции
|
||||
surgery-window-stepsbutton-name = Этапы
|
||||
surgery-window-partsbutton-name = < Части тела
|
||||
surgery-window-surgeriesbutton-name = < Операции
|
||||
surgery-window-stepsbutton-name = < Этапы
|
||||
surgery-window-reguires = [bold]Требует: { $surgeryname }[/bold]
|
||||
surgery-window-reguires-table = [color=red](Требует операционный стол)[/color]
|
||||
surgery-window-reguires-undress = [color=red](Снимите с него броню!)[/color]
|
||||
surgery-window-reguires-tool = [color=red](Отсутствует инструмент)[/color]
|
||||
surgery-window-reguires-laydown = [color=red][font size=16]Он должен лежать![/font][/color]
|
||||
surgery-window-reguires-enable = [color=red](Предмет выключен)[/color]
|
||||
surgery-window-too-high = [color=red](Слишком высокий)[/color]
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@
|
|||
|
||||
- type: entity
|
||||
id: OrganAnimalHeart
|
||||
parent: BaseAnimalOrgan
|
||||
parent: [ BaseAnimalOrgan, BaseOrganHeart]
|
||||
name: heart
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
|
|
|
|||
|
|
@ -160,6 +160,9 @@
|
|||
- type: Item
|
||||
size: Small
|
||||
heldPrefix: eyeballs
|
||||
- type: OrganVisualization
|
||||
layer: Eyes
|
||||
prototype: MobArachnidEyes
|
||||
|
||||
- type: entity
|
||||
id: OrganArachnidTongue
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@
|
|||
Caustic: 5
|
||||
- type: Damageable
|
||||
damageContainer: Biological
|
||||
|
||||
- type: OrganVisualization
|
||||
layer: Eyes
|
||||
prototype: MobHumanoidEyes
|
||||
|
||||
- type: entity
|
||||
id: BaseOrganTongue
|
||||
abstract: true
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@
|
|||
layers:
|
||||
- state: eyeball-l
|
||||
- state: eyeball-r
|
||||
- type: OrganVisualization
|
||||
layer: Eyes
|
||||
prototype: MobDionaEyes
|
||||
|
||||
- type: entity
|
||||
id: OrganDionaStomach
|
||||
|
|
|
|||
|
|
@ -88,6 +88,9 @@
|
|||
- type: Item
|
||||
size: Small
|
||||
heldPrefix: eyeballs
|
||||
- type: OrganVisualization
|
||||
layer: Eyes
|
||||
prototype: MobHumanoidEyes
|
||||
|
||||
- type: entity
|
||||
id: OrganHumanTongue
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@
|
|||
groups:
|
||||
- id: Food
|
||||
- id: Drink
|
||||
- id: Medicine
|
||||
- id: Poison
|
||||
- id: Narcotic
|
||||
# Sunrise-start
|
||||
#- id: Medicine
|
||||
#- id: Poison
|
||||
#- id: Narcotic
|
||||
# Sunrise-end
|
||||
- id: Alcohol
|
||||
rateModifier: 0.25
|
||||
- type: SolutionContainerManager
|
||||
|
|
@ -37,7 +39,6 @@
|
|||
size: Small
|
||||
heldPrefix: brain
|
||||
|
||||
|
||||
- type: entity
|
||||
id: OrganSlimeLungs
|
||||
parent: [BaseHumanOrgan, BaseOrganLungs]
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@
|
|||
- type: Tag
|
||||
tags:
|
||||
- Trash
|
||||
# Sunrise-start
|
||||
- type: SurgeryTarget
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
enum.SurgeryUIKey.Key:
|
||||
type: SurgeryBui
|
||||
# Sunrise-end
|
||||
|
||||
- type: entity
|
||||
id: BaseTorso
|
||||
|
|
|
|||
|
|
@ -10,20 +10,31 @@
|
|||
organs:
|
||||
brain: OrganHumanBrain
|
||||
eyes: OrganArachnidEyes
|
||||
# Sunrise-start
|
||||
tongue: OrganHumanTongue
|
||||
eye_implant: null
|
||||
# Sunrise-end
|
||||
torso:
|
||||
part: TorsoArachnid
|
||||
# Sunrise-start
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
- right leg
|
||||
- left leg
|
||||
# Sunrise-end
|
||||
organs:
|
||||
heart: OrganArachnidHeart
|
||||
lungs: OrganAnimalLungs
|
||||
stomach: OrganArachnidStomach
|
||||
liver: OrganArachnidLiver
|
||||
kidneys: OrganArachnidKidneys
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
- right leg
|
||||
- left leg
|
||||
cavity: null # Sunrise-edit
|
||||
# connections:
|
||||
# - right arm
|
||||
# - left arm
|
||||
# - right leg
|
||||
# - left leg
|
||||
right arm:
|
||||
part: RightArmArachnid
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
organs:
|
||||
stomach: OrganDionaStomachNymph
|
||||
lungs: OrganDionaLungsNymph
|
||||
heart: null # Sunrise-edit
|
||||
cavity: null # Sunrise-edit
|
||||
right arm:
|
||||
part: RightArmDiona
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -10,20 +10,31 @@
|
|||
organs:
|
||||
brain: OrganHumanBrain
|
||||
eyes: OrganHumanEyes
|
||||
# Sunrise-start
|
||||
tongue: OrganHumanTongue
|
||||
eye_implant: null
|
||||
# Sunrise-end
|
||||
torso:
|
||||
part: TorsoHuman
|
||||
# Sunrise-start
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
- right leg
|
||||
- left leg
|
||||
# Sunrise-end
|
||||
organs:
|
||||
heart: OrganDwarfHeart
|
||||
lungs: OrganHumanLungs
|
||||
stomach: OrganDwarfStomach
|
||||
liver: OrganDwarfLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
cavity: null # Sunrise-edit
|
||||
# connections:
|
||||
# - right arm
|
||||
# - left arm
|
||||
# - right leg
|
||||
# - left leg
|
||||
right arm:
|
||||
part: RightArmHuman
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
stomach: OrganHumanStomach
|
||||
liver: OrganHumanLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
cavity: null # Sunrise-edit
|
||||
right arm:
|
||||
part: RightArmGingerbread
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -10,41 +10,43 @@
|
|||
organs:
|
||||
brain: OrganHumanBrain
|
||||
eyes: OrganHumanEyes
|
||||
tongue: OrganHumanTongue
|
||||
tongue: OrganHumanTongue # Sunrise-edit
|
||||
torso:
|
||||
part: TorsoHuman
|
||||
connections:
|
||||
- right_arm
|
||||
- left_arm
|
||||
- right_leg
|
||||
- left_leg
|
||||
- right arm # STARLIGHT-SURGERY EDITED, be careful to not delete this
|
||||
- left arm
|
||||
- right leg
|
||||
- left leg
|
||||
organs:
|
||||
heart: OrganHumanHeart
|
||||
lungs: OrganHumanLungs
|
||||
stomach: OrganHumanStomach
|
||||
liver: OrganHumanLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
right_arm:
|
||||
cavity: null # Sunrise-edit
|
||||
right arm:
|
||||
part: RightArmHuman
|
||||
connections:
|
||||
- right_hand
|
||||
left_arm:
|
||||
- right hand
|
||||
left arm:
|
||||
part: LeftArmHuman
|
||||
connections:
|
||||
- left_hand
|
||||
right_hand:
|
||||
- left hand
|
||||
right hand:
|
||||
part: RightHandHuman
|
||||
left_hand:
|
||||
left hand:
|
||||
part: LeftHandHuman
|
||||
right_leg:
|
||||
right leg:
|
||||
part: RightLegHuman
|
||||
connections:
|
||||
- right_foot
|
||||
left_leg:
|
||||
- right foot
|
||||
left leg:
|
||||
part: LeftLegHuman
|
||||
connections:
|
||||
- left_foot
|
||||
right_foot:
|
||||
- left foot
|
||||
right foot:
|
||||
part: RightFootHuman
|
||||
left_foot:
|
||||
left foot:
|
||||
part: LeftFootHuman
|
||||
|
||||
|
|
|
|||
|
|
@ -10,20 +10,31 @@
|
|||
organs:
|
||||
brain: OrganHumanBrain
|
||||
eyes: OrganHumanEyes
|
||||
# Sunrise-start
|
||||
tongue: OrganHumanTongue
|
||||
eye_implant: null
|
||||
# Sunrise-end
|
||||
torso:
|
||||
part: TorsoMoth
|
||||
# Sunrise-start
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
- right leg
|
||||
- left leg
|
||||
# Sunrise-end
|
||||
organs:
|
||||
heart: OrganAnimalHeart
|
||||
lungs: OrganHumanLungs
|
||||
stomach: OrganMothStomach
|
||||
liver: OrganAnimalLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
- right leg
|
||||
- left leg
|
||||
cavity: null # Sunrise-edit
|
||||
# connections:
|
||||
# - right arm
|
||||
# - left arm
|
||||
# - right leg
|
||||
# - left leg
|
||||
right arm:
|
||||
part: RightArmMoth
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
liver: OrganAnimalLiver
|
||||
heart: OrganPrimateHeart # Sunrise Edit
|
||||
kidneys: OrganAnimalKidneys
|
||||
cavity: null # Sunrise-edit
|
||||
hands:
|
||||
part: HandsAnimal
|
||||
legs:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
liver: OrganAnimalLiver
|
||||
heart: OrganAnimalHeart
|
||||
kidneys: OrganAnimalKidneys
|
||||
cavity: null # Sunrise-edit
|
||||
legs:
|
||||
part: LegsAnimal
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -10,20 +10,31 @@
|
|||
organs:
|
||||
brain: OrganHumanBrain
|
||||
eyes: OrganHumanEyes
|
||||
# Sunrise-start
|
||||
tongue: OrganHumanTongue
|
||||
eye_implant: null
|
||||
# Sunrise-end
|
||||
torso:
|
||||
part: TorsoReptilian
|
||||
# Sunrise-start
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
- right leg
|
||||
- left leg
|
||||
# Sunrise-end
|
||||
organs:
|
||||
heart: OrganAnimalHeart
|
||||
lungs: OrganHumanLungs
|
||||
stomach: OrganReptilianStomach
|
||||
liver: OrganAnimalLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
- right leg
|
||||
- left leg
|
||||
cavity: null # Sunrise-edit
|
||||
# connections:
|
||||
# - right arm
|
||||
# - left arm
|
||||
# - right leg
|
||||
# - left leg
|
||||
right arm:
|
||||
part: RightArmReptilian
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@
|
|||
- torso
|
||||
organs:
|
||||
eyes: OrganHumanEyes
|
||||
# Sunrise-start
|
||||
tongue: OrganHumanTongue
|
||||
eye_implant: null
|
||||
# Sunrise-end
|
||||
torso:
|
||||
part: TorsoSlime
|
||||
connections:
|
||||
|
|
@ -18,8 +21,10 @@
|
|||
- right leg
|
||||
- left leg
|
||||
organs:
|
||||
heart: OrganSlimeHeart # Sunrise-edit
|
||||
core: SentientSlimeCore
|
||||
lungs: OrganSlimeLungs
|
||||
cavity: null # Sunrise-edit
|
||||
right arm:
|
||||
part: RightArmSlime
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
- torso
|
||||
organs:
|
||||
brain: MobTerminatorEndoskeleton
|
||||
cavity: null # Sunrise-edit
|
||||
torso:
|
||||
part: TorsoHuman
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@
|
|||
organs:
|
||||
brain: OrganHumanBrain
|
||||
eyes: OrganHumanEyes
|
||||
# Sunrise-start
|
||||
tongue: OrganHumanTongue
|
||||
eye_implant: null
|
||||
# Sunrise-end
|
||||
torso:
|
||||
part: TorsoVox
|
||||
connections:
|
||||
|
|
@ -24,6 +27,7 @@
|
|||
stomach: OrganVoxStomach
|
||||
liver: OrganVoxLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
cavity: null # Sunrise-edit
|
||||
right arm:
|
||||
part: RightArmVox
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
id: BaseMobSlimePerson
|
||||
abstract: true
|
||||
components:
|
||||
- type: Absorbable
|
||||
- type: Hunger
|
||||
- type: Thirst
|
||||
baseDecayRate: 0.3
|
||||
|
|
@ -40,7 +39,13 @@
|
|||
type: StrippableBoundUserInterface
|
||||
enum.StoreUiKey.Key:
|
||||
type: StoreBoundUserInterface
|
||||
# to prevent bag open/honk spam
|
||||
# Sunrise-start
|
||||
enum.SurgeryUIKey.Key:
|
||||
type: SurgeryBui
|
||||
enum.VampireMutationUiKey.Key:
|
||||
type: VampireMutationBoundUserInterface
|
||||
- type: Absorbable
|
||||
# Sunrise-end
|
||||
- type: UseDelay
|
||||
delay: 0.5
|
||||
- type: HumanoidAppearance
|
||||
|
|
|
|||
|
|
@ -48,7 +48,50 @@
|
|||
- type: TTS
|
||||
- type: DamageOverlay
|
||||
- type: EmoteAnimation
|
||||
# Sunrise-End
|
||||
- type: CustomLimbVisualizer
|
||||
displacements:
|
||||
LHand:
|
||||
sizeMaps:
|
||||
32:
|
||||
sprite: _Sunrise/CustomLimb/displacement.rsi
|
||||
state: l_hand
|
||||
RHand:
|
||||
sizeMaps:
|
||||
32:
|
||||
sprite: _Sunrise/CustomLimb/displacement.rsi
|
||||
state: r_hand
|
||||
LLeg:
|
||||
sizeMaps:
|
||||
32:
|
||||
sprite: _Sunrise/CustomLimb/displacement.rsi
|
||||
state: l_leg
|
||||
RLeg:
|
||||
sizeMaps:
|
||||
32:
|
||||
sprite: _Sunrise/CustomLimb/displacement.rsi
|
||||
state: r_leg
|
||||
LFoot:
|
||||
sizeMaps:
|
||||
32:
|
||||
sprite: _Sunrise/CustomLimb/displacement.rsi
|
||||
state: l_foot
|
||||
RFoot:
|
||||
sizeMaps:
|
||||
32:
|
||||
sprite: _Sunrise/CustomLimb/displacement.rsi
|
||||
state: r_foot
|
||||
LArm:
|
||||
sizeMaps:
|
||||
32:
|
||||
sprite: _Sunrise/CustomLimb/displacement.rsi
|
||||
state: l_arm
|
||||
RArm:
|
||||
sizeMaps:
|
||||
32:
|
||||
sprite: _Sunrise/CustomLimb/displacement.rsi
|
||||
state: r_arm
|
||||
# Sunrise-end
|
||||
|
||||
|
||||
- type: entity
|
||||
save: false
|
||||
|
|
|
|||
|
|
@ -79,6 +79,15 @@
|
|||
- type: DeleteOnTrigger
|
||||
- type: StaticPrice
|
||||
price: 0
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.6
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
||||
- type: entity
|
||||
parent: ShardBase
|
||||
|
|
|
|||
|
|
@ -24,6 +24,15 @@
|
|||
Piercing: 6
|
||||
soundHit:
|
||||
path: "/Audio/Weapons/bladeslice.ogg"
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.12
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
- type: PhysicalComposition
|
||||
materialComposition:
|
||||
Steel: 200
|
||||
|
|
|
|||
|
|
@ -4,6 +4,15 @@
|
|||
id: Lighter
|
||||
description: "A simple plastic cigarette lighter."
|
||||
components:
|
||||
# Sunrise-start
|
||||
- type: SurgeryTool
|
||||
successRate: 0.1
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/cautery1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/cautery2.ogg
|
||||
- type: Cautery
|
||||
# Sunrise-end
|
||||
- type: IgnitionSource
|
||||
ignited: false
|
||||
- type: ItemToggle
|
||||
|
|
|
|||
|
|
@ -55,6 +55,15 @@
|
|||
Steel: 100
|
||||
- type: StaticPrice
|
||||
price: 30
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.35
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
||||
- type: entity
|
||||
name: screwdriver
|
||||
|
|
|
|||
|
|
@ -47,3 +47,12 @@
|
|||
maxVol: 300
|
||||
- type: UseDelay
|
||||
delay: 1
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.01
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
|
|
|||
|
|
@ -98,6 +98,15 @@
|
|||
sprite: Objects/Weapons/Melee/e_sword-inhands.rsi
|
||||
- type: StaticPrice
|
||||
price: 2500
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.6
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
||||
- type: entity
|
||||
name: energy dagger
|
||||
|
|
@ -162,6 +171,15 @@
|
|||
energy: 1.5
|
||||
color: white
|
||||
netsync: false
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.6
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
||||
- type: entity
|
||||
name: pen
|
||||
|
|
@ -232,6 +250,15 @@
|
|||
tags:
|
||||
- Write
|
||||
- NoPaint # Sunrise-edit
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.6
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
||||
- type: entity
|
||||
parent: [BaseItem, BaseSyndicateContraband]
|
||||
|
|
@ -341,6 +368,15 @@
|
|||
spread: 75
|
||||
- type: FlipOnAttack # Sunrise-Edit
|
||||
probability: 0.5 # Sunrise-Edit
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.6
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
||||
# Item will look weird in handslot. Will need to adjust handstorage visuals in a future PR
|
||||
- type: entity
|
||||
|
|
@ -413,3 +449,12 @@
|
|||
- type: EnergySword
|
||||
colorOptions:
|
||||
- "#2288ff" # can only be blue
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.6
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
|
|
|||
|
|
@ -27,6 +27,15 @@
|
|||
- Slicing
|
||||
useSound:
|
||||
path: /Audio/Items/Culinary/chop.ogg
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.9
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
||||
- type: entity
|
||||
name: kitchen knife
|
||||
|
|
@ -210,6 +219,15 @@
|
|||
sprite: Objects/Weapons/Melee/shiv.rsi
|
||||
- type: DisarmMalus
|
||||
malus: 0.225
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.7
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
||||
- type: entity
|
||||
name: reinforced shiv
|
||||
|
|
|
|||
|
|
@ -209,8 +209,17 @@
|
|||
- Back
|
||||
- SuitStorage #Bigger than the other swords, easier to strap to your suit.
|
||||
- type: DisarmMalus
|
||||
# Sunrise-start
|
||||
- type: Scalpel
|
||||
- type: SurgeryTool
|
||||
successRate: 0.6
|
||||
startSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel1.ogg
|
||||
endSound:
|
||||
path: /Audio/_Sunrise/Medical/Surgery/scalpel2.ogg
|
||||
# Sunrise-end
|
||||
|
||||
|
||||
#Other/Weird
|
||||
- type: entity
|
||||
name: throngler
|
||||
parent: [ BaseSword, BaseMajorContraband ]
|
||||
|
|
|
|||
20
Resources/Prototypes/_Sunrise/Body/Organs/slime.yml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
- type: entity
|
||||
id: OrganSlimeHeart
|
||||
parent: [BaseHumanOrgan, BaseOrganHeart]
|
||||
name: slime circulator
|
||||
description: "A little circulator what makes the fluid move through the slime body."
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/Mobs/Species/Slime/organs.rsi
|
||||
state: heart-on
|
||||
- type: Item
|
||||
size: Small
|
||||
heldPrefix: heart
|
||||
- type: Metabolizer
|
||||
maxReagents: 6
|
||||
metabolizerTypes: [ Slime ]
|
||||
removeEmpty: true
|
||||
groups:
|
||||
- id: Medicine
|
||||
- id: Poison
|
||||
- id: Narcotic
|
||||
5
Resources/Prototypes/_Sunrise/Body/Parts/virtual.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
- type: entity
|
||||
id: PartVirtual
|
||||
parent: BaseItem
|
||||
components:
|
||||
- type: BodyPart
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
liver: OrganAnimalLiver
|
||||
heart: OrganPigHeart
|
||||
kidneys: OrganAnimalKidneys
|
||||
cavity: null
|
||||
legs:
|
||||
part: LegsAnimal
|
||||
connections:
|
||||
|
|
@ -90,4 +91,4 @@
|
|||
connections:
|
||||
- feet
|
||||
feet:
|
||||
part: FeetAnimal
|
||||
part: FeetAnimal
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
liver: OrganBloodsuckerLiver
|
||||
heart: OrganBloodsuckerHeart
|
||||
kidneys: OrganAnimalKidneys
|
||||
cavity: null
|
||||
right arm:
|
||||
part: RightArmHuman
|
||||
connections:
|
||||
|
|
@ -25,4 +26,4 @@
|
|||
right hand:
|
||||
part: RightHandHuman
|
||||
left hand:
|
||||
part: LeftHandHuman
|
||||
part: LeftHandHuman
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
stomach: OrganDemonStomach
|
||||
liver: OrganAnimalLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
cavity: null
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
|
|
@ -46,4 +47,4 @@
|
|||
right foot:
|
||||
part: RightFootDemon
|
||||
left foot:
|
||||
part: LeftFootDemon
|
||||
part: LeftFootDemon
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
part: TorsoHuman
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
- left arm
|
||||
- left leg
|
||||
- right leg
|
||||
organs:
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
stomach: OrganReptilianStomach
|
||||
liver: OrganAnimalLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
cavity: null
|
||||
right arm:
|
||||
part: RightArmHuman
|
||||
connections:
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
stomach: OrganHumanoidXenoStomach
|
||||
liver: OrganHumanoidXenoLiver
|
||||
kidneys: OrganHumanoidXenoKidneys
|
||||
cavity: null
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
stomach: OrganPredatorStomach
|
||||
liver: OrganPredatorLiver
|
||||
kidneys: OrganPredatorKidneys
|
||||
cavity: null
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
stomach: OrganSwineStomach
|
||||
liver: OrganAnimalLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
cavity: null
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
stomach: OrganTajaranStomach
|
||||
liver: OrganAnimalLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
cavity: null
|
||||
connections:
|
||||
- right arm
|
||||
- left arm
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
stomach: OrganVulpkaninStomach
|
||||
liver: OrganAnimalLiver
|
||||
kidneys: OrganHumanKidneys
|
||||
cavity: null
|
||||
connections:
|
||||
- right_arm
|
||||
- left_arm
|
||||
|
|
|
|||
|
|
@ -16,3 +16,70 @@
|
|||
types:
|
||||
Slash: 24
|
||||
- type: SurgeryStepAmputationEffect
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepExposeSkull
|
||||
name: Expose Skull
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 2
|
||||
tools:
|
||||
- type: BoneSaw
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/saw.rsi
|
||||
state: saw
|
||||
- type: SurgeryStepBleedEffect
|
||||
damage:
|
||||
types:
|
||||
Slash: 5
|
||||
- type: SurgeryStepEmoteEffect
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepLigateVessels
|
||||
name: Ligate Vessels
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 3
|
||||
tools:
|
||||
- type: Hemostat
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scissors.rsi
|
||||
state: hemostat
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepSawSkull
|
||||
name: Saw Skull
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 20
|
||||
tools:
|
||||
- type: BoneSaw
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/saw.rsi
|
||||
state: saw
|
||||
- type: SurgeryStepBleedEffect
|
||||
damage:
|
||||
types:
|
||||
Slash: 15
|
||||
- type: SurgeryStepAmputationEffect
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepInciseCartilage
|
||||
name: Incise Cartilage
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
tools:
|
||||
- type: Scalpel
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scalpel.rsi
|
||||
state: scalpel
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepSawSkull
|
||||
id: SurgeryStepHeadFinalizeSeparation
|
||||
name: Finalize Separation
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryAmputation
|
||||
name: Amputation
|
||||
description: Surgical removal of a limb.
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
steps:
|
||||
- SurgeryStepInciseCartilage
|
||||
- SurgeryStepExposeNerves
|
||||
- SurgeryStepExposeBloodVessels
|
||||
- SurgeryAmputationStep
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Arm
|
||||
- Hand
|
||||
- Leg
|
||||
- Foot
|
||||
- Tail
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/saw.rsi
|
||||
state: saw
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryAmputation
|
||||
id: SurgeryAmputationHead
|
||||
name: Amputation
|
||||
description: Surgical removal of a head.
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
steps:
|
||||
- SurgeryStepDeepIncision
|
||||
- SurgeryStepExposeSkull
|
||||
- SurgeryStepExposeNerves
|
||||
- SurgeryStepExposeBloodVessels
|
||||
- SurgeryStepSawSkull
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Head
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryAmputation
|
||||
id: SurgeryAmputationSlime
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenIncisionSlime
|
||||
steps:
|
||||
- SurgeryStepDeepIncision
|
||||
- SurgeryStepInciseCartilage
|
||||
- SurgeryStepSawSkull
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryAmputationHead
|
||||
id: SurgeryAmputationHeadSlime
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenIncisionSlime
|
||||
steps:
|
||||
- SurgeryStepDeepIncision
|
||||
- SurgeryStepInciseCartilage
|
||||
- SurgeryStepHeadFinalizeSeparation
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
|
|
@ -1,32 +1,4 @@
|
|||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepExposeNerves
|
||||
name: Expose Nerves
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 4
|
||||
tools:
|
||||
- type: Scalpel
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scalpel.rsi
|
||||
state: scalpel
|
||||
- type: SurgeryStepEmoteEffect
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepExposeBloodVessels
|
||||
name: Expose Blood Vessels
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 4
|
||||
tools:
|
||||
- type: Scalpel
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scalpel.rsi
|
||||
state: scalpel
|
||||
- type: SurgeryStepEmoteEffect
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryLimbAttachmentStep
|
||||
name: attach a limb
|
||||
|
|
@ -34,7 +6,7 @@
|
|||
- type: SurgeryStep
|
||||
duration: 4
|
||||
tools:
|
||||
- type: BodyPart
|
||||
- type: MetaData
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Food/Baked/pizza.rsi
|
||||
state: meat-slice
|
||||
|
|
|
|||
223
Resources/Prototypes/_Sunrise/Surgery/attachment_surgeries.yml
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryLimbAttachmentHead
|
||||
name: Limb Attachment Head
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
steps:
|
||||
- SurgeryStepExposeNerves
|
||||
- SurgeryStepExposeBloodVessels
|
||||
- SurgeryLimbAttachmentStep
|
||||
- SurgeryStepRejoinNerves
|
||||
- SurgeryStepRejoinBloodVessels
|
||||
- SurgeryStepRestoreCartilage
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: head
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/medical.rsi
|
||||
state: medicated-suture
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentLeftArm
|
||||
name: Limb Attachment Left Arm
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: left arm
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentLeftHand
|
||||
name: Limb Attachment Left Hand
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: left hand
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentRightArm
|
||||
name: Limb Attachment Right Arm
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: right arm
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentRightHand
|
||||
name: Limb Attachment Right Hand
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: right hand
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentLeftLeg
|
||||
name: Limb Attachment Left Leg
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: left leg
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentLeftFoot
|
||||
name: Limb Attachment Left Foot
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: left foot
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentRightLeg
|
||||
name: Limb Attachment Right Leg
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: right leg
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentRightFoot
|
||||
name: Limb Attachment Right Foot
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: right foot
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentTail
|
||||
name: Limb Attachment Tail
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: tail
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentOther
|
||||
name: Limb Attachment Other
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: other
|
||||
|
||||
#SlimePerson
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentHead
|
||||
id: SurgeryLimbAttachmentSlimeHead
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenIncisionSlime
|
||||
steps:
|
||||
- SurgeryStepDeepIncision
|
||||
- SurgeryLimbAttachmentStep
|
||||
- SurgeryStepRestoreCartilage
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentSlimeHead
|
||||
id: SurgeryLimbAttachmentSlimeLeftArm
|
||||
name: Limb Attachment Left Arm
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: left arm
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentSlimeHead
|
||||
id: SurgeryLimbAttachmentSlimeLeftHand
|
||||
name: Limb Attachment Left Hand
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: left hand
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentSlimeHead
|
||||
id: SurgeryLimbAttachmentSlimeRightArm
|
||||
name: Limb Attachment Right Arm
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: right arm
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentSlimeHead
|
||||
id: SurgeryLimbAttachmentSlimeRightHand
|
||||
name: Limb Attachment Right Hand
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: right hand
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentSlimeHead
|
||||
id: SurgeryLimbAttachmentSlimeLeftLeg
|
||||
name: Limb Attachment Left Leg
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: left leg
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentSlimeHead
|
||||
id: SurgeryLimbAttachmentSlimeLeftFoot
|
||||
name: Limb Attachment Left Foot
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: left foot
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentSlimeHead
|
||||
id: SurgeryLimbAttachmentSlimeRightLeg
|
||||
name: Limb Attachment Right Leg
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: right leg
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentSlimeHead
|
||||
id: SurgeryLimbAttachmentSlimeRightFoot
|
||||
name: Limb Attachment Right Foot
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: right foot
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentSlimeHead
|
||||
id: SurgeryLimbAttachmentSlimeTail
|
||||
name: Limb Attachment Tail
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: tail
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryLimbAttachmentSlimeHead
|
||||
id: SurgeryLimbAttachmentSlimeOther
|
||||
name: Limb Attachment Other
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: SurgeryLimbSlotCondition
|
||||
slot: other
|
||||
72
Resources/Prototypes/_Sunrise/Surgery/common_steps.yml
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepExposeNerves
|
||||
name: Expose Nerves
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 4
|
||||
tools:
|
||||
- type: Scalpel
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scalpel.rsi
|
||||
state: scalpel
|
||||
- type: SurgeryStepEmoteEffect
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepExposeBloodVessels
|
||||
name: Expose Blood Vessels
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 4
|
||||
tools:
|
||||
- type: Scalpel
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scalpel.rsi
|
||||
state: scalpel
|
||||
- type: SurgeryStepEmoteEffect
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepDeepIncision
|
||||
name: Deep Incision
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 5
|
||||
tools:
|
||||
- type: Scalpel
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scalpel.rsi
|
||||
state: scalpel
|
||||
- type: SurgeryStepEmoteEffect
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepRetractSkin
|
||||
name: Retract the skin
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
tools:
|
||||
- type: Retractor
|
||||
add:
|
||||
- type: SkinRetracted
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scissors.rsi
|
||||
state: retractor
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepRetractSkin
|
||||
id: SurgeryStepRetractMembrane
|
||||
name: Retract the membrane
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepCoagulateJellyFlow
|
||||
name: Coagulate Jelly Flow
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
tools:
|
||||
- type: Hemostat
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scissors.rsi
|
||||
state: hemostat
|
||||
|
|
@ -574,7 +574,7 @@
|
|||
state: hemostat
|
||||
|
||||
# kidneys
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepPrepareImplantSiteKidneys
|
||||
|
|
@ -619,7 +619,7 @@
|
|||
state: hemostat
|
||||
|
||||
# stomach
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepPrepareImplantSiteStomach
|
||||
|
|
@ -662,7 +662,7 @@
|
|||
state: hemostat
|
||||
|
||||
# lungs
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepPrepareImplantSiteLungs
|
||||
|
|
@ -705,7 +705,7 @@
|
|||
state: hemostat
|
||||
|
||||
# heart
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepPrepareImplantSiteHeart
|
||||
|
|
@ -984,4 +984,62 @@
|
|||
state: cautery
|
||||
- type: SurgeryClearProgress
|
||||
|
||||
# Cavity
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepLocateItemCavity
|
||||
name: Locate Item
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 3
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: torso_m
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepRemoveItemCavity
|
||||
name: Remove Item
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 6
|
||||
tools:
|
||||
- type: Scalpel
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: torso_m
|
||||
- type: SurgeryStepEmoteEffect
|
||||
- type: SurgeryStepOrganExtract
|
||||
organ:
|
||||
- type: Item
|
||||
slot: cavity
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepPrepareImplantSiteCavity
|
||||
name: Prepare Implant Site
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 4
|
||||
tools:
|
||||
- type: Scalpel
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scalpel.rsi
|
||||
state: scalpel
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepInsertItemCavity
|
||||
name: Insert Item
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
duration: 3
|
||||
tools:
|
||||
- type: Item
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: torso_m
|
||||
- type: SurgeryItemSizeCondition
|
||||
- type: SurgeryStepOrganInsert
|
||||
slot: cavity
|
||||
|
|
|
|||
|
|
@ -14,6 +14,24 @@
|
|||
- SurgeryStepOpenIncisionScalpel
|
||||
- SurgeryStepClampBleeders
|
||||
- SurgeryStepRetractSkin
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryOpenIncision
|
||||
id: SurgeryOpenIncisionSlime
|
||||
components:
|
||||
- type: Surgery
|
||||
priority: -100
|
||||
steps:
|
||||
- SurgeryStepOpenIncisionScalpel
|
||||
- SurgeryStepCoagulateJellyFlow
|
||||
- SurgeryStepRetractMembrane
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
|
|
@ -21,12 +39,32 @@
|
|||
name: Close Incision
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenIncision
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
priority: 100
|
||||
steps:
|
||||
- SurgeryStepCloseBones
|
||||
- SurgeryStepMendRibcage
|
||||
- SurgeryStepCloseIncision
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryCloseIncision
|
||||
id: SurgeryCloseIncisionSlime
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenIncisionSlime
|
||||
priority: 100
|
||||
steps:
|
||||
- SurgeryStepMendRibcage
|
||||
- SurgeryStepCloseIncision
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
|
|
@ -34,25 +72,31 @@
|
|||
name: Open Ribcage
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenIncision
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
priority: -50
|
||||
steps:
|
||||
- SurgeryStepSawBones
|
||||
- SurgeryStepPriseOpenBones
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
parts:
|
||||
- Torso
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
sprite: Mobs/Species/Skeleton/parts.rsi
|
||||
state: torso_m
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryOpenAbdomen
|
||||
name: Open Abdomen
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenIncision
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
- SurgeryOpenIncisionSlime
|
||||
priority: -50
|
||||
steps:
|
||||
- SurgeryStepCutAbdominalMuscles
|
||||
|
|
@ -61,71 +105,31 @@
|
|||
parts:
|
||||
- Torso
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Skeleton/parts.rsi
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: torso_m
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryEliminateVocalCordDefects
|
||||
name: Eliminate vocal cord defects.
|
||||
name: Eliminate vocal cord defects
|
||||
description: Remove speech defects, accents.
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenIncision
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
- SurgeryOpenIncisionSlime
|
||||
steps:
|
||||
- SurgeryStepExposeVocalCords
|
||||
- SurgeryStepAdjustVocalCords
|
||||
- SurgeryStepSutureIncision
|
||||
- type: SurgeryAnyAccentCondition
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
parts:
|
||||
- Head
|
||||
- type: Sprite
|
||||
sprite: Objects/Fun/Instruments/microphone.rsi
|
||||
state: icon
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryAmputation
|
||||
name: Amputation
|
||||
description: Surgical removal of a limb.
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenIncision
|
||||
steps:
|
||||
- SurgeryStepExposeNerves
|
||||
- SurgeryStepExposeBloodVessels
|
||||
- SurgeryAmputationStep
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Arm
|
||||
- Hand
|
||||
- Leg
|
||||
- Foot
|
||||
- Tail
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/saw.rsi
|
||||
state: saw
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryLimbAttachment
|
||||
name: Limb Attachment
|
||||
description: Surgical attachment of a limb.
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenIncision
|
||||
steps:
|
||||
- SurgeryStepExposeNerves
|
||||
- SurgeryStepExposeBloodVessels
|
||||
- SurgeryLimbAttachmentStep
|
||||
- SurgeryStepRejoinNerves
|
||||
- SurgeryStepRejoinBloodVessels
|
||||
- SurgeryStepRestoreCartilage
|
||||
- type: SurgeryAnyLimbSlotCondition
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/medical.rsi
|
||||
state: medicated-suture
|
||||
#organs
|
||||
|
||||
- type: entity
|
||||
|
|
@ -134,11 +138,15 @@
|
|||
name: Extract Liver
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenAbdomen
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepLocateLiver
|
||||
- SurgeryStepClampLiverVessels
|
||||
- SurgeryStepRemoveLiver
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -148,20 +156,24 @@
|
|||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/organs.rsi
|
||||
state: liver
|
||||
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryImplantLiver
|
||||
name: Implant Liver
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenAbdomen
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepPrepareImplantSiteLiver
|
||||
- SurgeryStepInsertLiver
|
||||
- SurgeryStepConnectLiverVessels
|
||||
- SurgeryStepRestoreAbdominalWalls
|
||||
- SurgeryStepSutureMuscles
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -178,11 +190,15 @@
|
|||
name: Extract Appendix
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenAbdomen
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepLocateAppendix
|
||||
- SurgeryStepClampAppendix
|
||||
- SurgeryStepRemoveAppendix
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -199,11 +215,15 @@
|
|||
name: Extract Kidneys
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenAbdomen
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepLocateKidneys
|
||||
- SurgeryStepClampKidneysVessels
|
||||
- SurgeryStepRemoveKidneys
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -222,13 +242,17 @@
|
|||
name: Implant Kidneys
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenAbdomen
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepPrepareImplantSiteKidneys
|
||||
- SurgeryStepInsertKidneys
|
||||
- SurgeryStepConnectKidneysVessels
|
||||
- SurgeryStepRestoreAbdominalWalls
|
||||
- SurgeryStepSutureMuscles
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -247,11 +271,15 @@
|
|||
name: Extract Stomach
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenAbdomen
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepLocateStomach
|
||||
- SurgeryStepClampStomachVessels
|
||||
- SurgeryStepRemoveStomach
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -268,13 +296,17 @@
|
|||
name: Implant Stomach
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenAbdomen
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepPrepareImplantSiteStomach
|
||||
- SurgeryStepInsertStomach
|
||||
- SurgeryStepConnectStomachVessels
|
||||
- SurgeryStepRestoreAbdominalWalls
|
||||
- SurgeryStepSutureMuscles
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -291,11 +323,15 @@
|
|||
name: Extract Lungs
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenRibcage
|
||||
requirement:
|
||||
- SurgeryOpenRibcage
|
||||
steps:
|
||||
- SurgeryStepLocateLungs
|
||||
- SurgeryStepClampLungVessels
|
||||
- SurgeryStepRemoveLungs
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -314,11 +350,71 @@
|
|||
name: Implant Lungs
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenRibcage
|
||||
requirement:
|
||||
- SurgeryOpenRibcage
|
||||
steps:
|
||||
- SurgeryStepPrepareImplantSiteLungs
|
||||
- SurgeryStepInsertLungs
|
||||
- SurgeryStepConnectLungVessels
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
- type: SurgeryOrganDontExistCondition
|
||||
organ:
|
||||
- type: OrganLungs
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/organs.rsi
|
||||
layers:
|
||||
- state: lung-l
|
||||
- state: lung-r
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryExtractLungsSlime
|
||||
name: Extract Lungs
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepLocateLungs
|
||||
- SurgeryStepClampLungVessels
|
||||
- SurgeryStepRemoveLungs
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
- type: SurgeryOrganExistCondition
|
||||
organ:
|
||||
- type: OrganLungs
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/organs.rsi
|
||||
layers:
|
||||
- state: lung-l
|
||||
- state: lung-r
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryImplantLungsSlime
|
||||
name: Implant Lungs
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepPrepareImplantSiteLungs
|
||||
- SurgeryStepInsertLungs
|
||||
- SurgeryStepConnectLungVessels
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -337,11 +433,15 @@
|
|||
name: Extract Heart
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenRibcage
|
||||
requirement:
|
||||
- SurgeryOpenRibcage
|
||||
steps:
|
||||
- SurgeryStepLocateHeart
|
||||
- SurgeryStepClampHeartVessels
|
||||
- SurgeryStepRemoveHeart
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -358,11 +458,15 @@
|
|||
name: Implant Heart
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenRibcage
|
||||
requirement:
|
||||
- SurgeryOpenRibcage
|
||||
steps:
|
||||
- SurgeryStepPrepareImplantSiteHeart
|
||||
- SurgeryStepInsertHeart
|
||||
- SurgeryStepConnectHeartVessels
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
|
|
@ -373,13 +477,65 @@
|
|||
sprite: Mobs/Species/Human/organs.rsi
|
||||
state: heart-on
|
||||
#
|
||||
- type: entity
|
||||
parent: SurgeryExtractHeart
|
||||
id: SurgeryExtractHeartSlime
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepLocateHeart
|
||||
- SurgeryStepClampHeartVessels
|
||||
- SurgeryStepRemoveHeart
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
- type: SurgeryOrganExistCondition
|
||||
organ:
|
||||
- type: OrganHeart
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/Mobs/Species/Slime/organs.rsi
|
||||
state: heart-on
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryImplantHeart
|
||||
id: SurgeryImplantHeartSlime
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepPrepareImplantSiteHeart
|
||||
- SurgeryStepInsertHeart
|
||||
- SurgeryStepConnectHeartVessels
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
- type: SurgeryOrganDontExistCondition
|
||||
organ:
|
||||
- type: OrganHeart
|
||||
- type: Sprite
|
||||
sprite: _Sunrise/Mobs/Species/Slime/organs.rsi
|
||||
state: heart-on
|
||||
#
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryExtractEyes
|
||||
name: Extract Eyes
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenIncision
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
- SurgeryOpenIncisionSlime
|
||||
steps:
|
||||
- SurgeryStepLocateEyes
|
||||
- SurgeryStepClampOpticNerve
|
||||
|
|
@ -402,7 +558,9 @@
|
|||
name: Implant Eyes
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenIncision
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
- SurgeryOpenIncisionSlime
|
||||
steps:
|
||||
- SurgeryStepPrepareImplantSiteEyes
|
||||
- SurgeryStepInsertEyes
|
||||
|
|
@ -464,7 +622,8 @@
|
|||
name: Extract Brain
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenIncision
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
steps:
|
||||
- SurgeryStepPreparePatient
|
||||
- SurgeryStepShaveHead
|
||||
|
|
@ -479,6 +638,9 @@
|
|||
- SurgeryStepRetractDuraMater
|
||||
- SurgeryStepSeverCranialNerves
|
||||
- SurgeryStepExtractBrain
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Head
|
||||
|
|
@ -495,7 +657,8 @@
|
|||
name: Implant Brain
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement: SurgeryOpenIncision
|
||||
requirement:
|
||||
- SurgeryOpenIncision
|
||||
steps:
|
||||
- SurgeryStepCleanImplantSite
|
||||
- SurgeryStepPrepareScalp
|
||||
|
|
@ -515,6 +678,9 @@
|
|||
- SurgeryStepSecureBoneFlap
|
||||
- SurgeryStepReplaceScalp
|
||||
- SurgeryStepSutureScalp
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Head
|
||||
|
|
@ -524,3 +690,112 @@
|
|||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/organs.rsi
|
||||
state: brain
|
||||
|
||||
#
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryExtractCore
|
||||
name: Extract Core
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepPreparePatient
|
||||
- SurgeryStepDisinfectScalp
|
||||
- SurgeryStepMakeIncisionScalp
|
||||
- SurgeryStepRetractScalp
|
||||
- SurgeryStepExtractBrain
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
- type: SurgeryOrganExistCondition
|
||||
organ:
|
||||
- type: OrganBrain
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Slime/organs.rsi
|
||||
state: brain-slime
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryImplantCore
|
||||
name: Implant Core
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepCleanImplantSite
|
||||
- SurgeryStepPrepareScalp
|
||||
- SurgeryStepMakeIncisionScalp
|
||||
- SurgeryStepRetractScalp
|
||||
- SurgeryStepInsertBrain
|
||||
- SurgeryStepReplaceScalp
|
||||
- SurgeryStepSutureScalp
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist: []
|
||||
speciesWhitelist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
- type: SurgeryOrganDontExistCondition
|
||||
organ:
|
||||
- type: OrganBrain
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Slime/organs.rsi
|
||||
state: brain-slime
|
||||
#
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryExtractCavityItem
|
||||
name: Extract Item
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepLocateItemCavity
|
||||
- SurgeryStepRemoveItemCavity
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
- type: SurgeryOrganExistCondition
|
||||
organ:
|
||||
- type: Item
|
||||
container: cavity
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: torso_m
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryBase
|
||||
id: SurgeryImplantCavityItem
|
||||
name: Implant Item
|
||||
components:
|
||||
- type: Surgery
|
||||
requirement:
|
||||
- SurgeryOpenAbdomen
|
||||
steps:
|
||||
- SurgeryStepPrepareImplantSiteCavity
|
||||
- SurgeryStepInsertItemCavity
|
||||
- type: SurgerySpeciesCondition
|
||||
speciesBlacklist:
|
||||
- SlimePerson
|
||||
- type: SurgeryPartCondition
|
||||
parts:
|
||||
- Torso
|
||||
- type: SurgeryOrganDontExistCondition
|
||||
organ:
|
||||
- type: Item
|
||||
container: cavity
|
||||
- type: Sprite
|
||||
sprite: Mobs/Species/Human/parts.rsi
|
||||
state: torso_m
|
||||
|
|
|
|||
|
|
@ -39,20 +39,6 @@
|
|||
state: hemostat
|
||||
- type: SurgeryClampBleedEffect
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepRetractSkin
|
||||
name: Retract the skin
|
||||
components:
|
||||
- type: SurgeryStep
|
||||
tools:
|
||||
- type: Retractor
|
||||
add:
|
||||
- type: SkinRetracted
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Medical/Surgery/scissors.rsi
|
||||
state: retractor
|
||||
|
||||
- type: entity
|
||||
parent: SurgeryStepBase
|
||||
id: SurgeryStepSawBones
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 167 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 147 B |
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "starlight",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"load": {
|
||||
"srgb": false
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "l_arm",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "r_arm",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "l_foot",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "r_foot",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "l_leg",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "r_leg",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "l_hand",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "r_hand",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 240 B |
|
|
@ -112,6 +112,10 @@
|
|||
"name": "r_foot",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "eyes",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "r_hand",
|
||||
"directions": 4,
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 221 B |
|
After Width: | Height: | Size: 237 B |
|
After Width: | Height: | Size: 891 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Sprited by Nimfar11 (Github) for Space Station 14, inhands by mubururu_ (github)",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "heart-off"
|
||||
},
|
||||
{
|
||||
"name": "heart-on",
|
||||
"delays": [
|
||||
[
|
||||
0.6,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "heart-inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "heart-inhand-right",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||