diff --git a/Content.Client/Administration/UI/CustomControls/HSeparator.cs b/Content.Client/Administration/UI/CustomControls/HSeparator.cs index d0575a4ede0..0879235ff8f 100644 --- a/Content.Client/Administration/UI/CustomControls/HSeparator.cs +++ b/Content.Client/Administration/UI/CustomControls/HSeparator.cs @@ -1,24 +1,30 @@ using Robust.Client.Graphics; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; -using Robust.Shared.Maths; namespace Content.Client.Administration.UI.CustomControls; public sealed class HSeparator : Control { - private static readonly Color SeparatorColor = Color.FromHex("#191919"); + private static readonly Color SeparatorColor = Color.FromHex("#3D4059"); + + private readonly StyleBoxFlat _styleBox; + + public Color Color + { + get => _styleBox.BackgroundColor; + set => _styleBox.BackgroundColor = value; + } public HSeparator(Color color) { - AddChild(new PanelContainer + _styleBox = new StyleBoxFlat { - PanelOverride = new StyleBoxFlat - { - BackgroundColor = color, - ContentMarginBottomOverride = 2, ContentMarginLeftOverride = 2 - } - }); + BackgroundColor = color, + ContentMarginBottomOverride = 2, ContentMarginLeftOverride = 2 + }; + + AddChild(new PanelContainer { PanelOverride = _styleBox }); } public HSeparator() : this(SeparatorColor) { } diff --git a/Content.Client/_CM14/Medical/Surgery/CMSurgeryBui.cs b/Content.Client/_CM14/Medical/Surgery/CMSurgeryBui.cs new file mode 100644 index 00000000000..7fb3b6e7909 --- /dev/null +++ b/Content.Client/_CM14/Medical/Surgery/CMSurgeryBui.cs @@ -0,0 +1,433 @@ +using Content.Client._CM14.Xenos.UI; +using Content.Client.Administration.UI.CustomControls; +using Content.Shared._CM14.Medical.Surgery; +using Content.Shared.Body.Part; +using JetBrains.Annotations; +using Robust.Client.GameObjects; +using Robust.Client.Player; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; +using static Robust.Client.UserInterface.Control; + +namespace Content.Client._CM14.Medical.Surgery; + +[UsedImplicitly] +public sealed class CMSurgeryBui : BoundUserInterface +{ + [Dependency] private readonly IEntityManager _entities = default!; + [Dependency] private readonly IPlayerManager _player = default!; + + private readonly CMSurgerySystem _system; + + [ViewVariables] + private CMSurgeryWindow? _window; + + private EntityUid? _part; + private (EntityUid Ent, EntProtoId Proto)? _surgery; + private readonly List _previousSurgeries = new(); + + public CMSurgeryBui(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + _system = _entities.System(); + } + + protected override void Open() + { + _system.OnRefresh += () => + { + UpdateDisabledPanel(); + RefreshUI(); + }; + + if (State is CMSurgeryBuiState s) + Update(s); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + if (state is CMSurgeryBuiState s) + Update(s); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + _window?.Dispose(); + + _system.OnRefresh -= RefreshUI; + } + + private void Update(CMSurgeryBuiState state) + { + if (_window == null) + { + _window = new CMSurgeryWindow(); + _window.OnClose += Close; + _window.Title = "Surgery"; + + _window.PartsButton.OnPressed += _ => + { + _part = null; + _surgery = null; + _previousSurgeries.Clear(); + View(ViewType.Parts); + }; + + _window.SurgeriesButton.OnPressed += _ => + { + _surgery = null; + _previousSurgeries.Clear(); + + if (!_entities.TryGetNetEntity(_part, out var netPart) || + State is not CMSurgeryBuiState s || + !s.Choices.TryGetValue(netPart.Value, out var surgeries)) + { + return; + } + + OnPartPressed(netPart.Value, surgeries); + }; + + _window.StepsButton.OnPressed += _ => + { + if (!_entities.TryGetNetEntity(_part, out var netPart) || + _previousSurgeries.Count == 0) + { + return; + } + + var last = _previousSurgeries[^1]; + _previousSurgeries.RemoveAt(_previousSurgeries.Count - 1); + + if (_system.GetSingleton(last) is not { } previousId || + !_entities.TryGetComponent(previousId, out CMSurgeryComponent? previous)) + { + return; + } + + OnSurgeryPressed((previousId, previous), netPart.Value, last); + }; + } + + _window.Surgeries.DisposeAllChildren(); + _window.Steps.DisposeAllChildren(); + _window.Parts.DisposeAllChildren(); + + View(ViewType.Parts); + + var oldSurgery = _surgery; + var oldPart = _part; + _part = null; + _surgery = null; + + var parts = new List>(state.Choices.Keys.Count); + foreach (var choice in state.Choices.Keys) + { + if (_entities.TryGetEntity(choice, out var ent) && + _entities.TryGetComponent(ent, out BodyPartComponent? part)) + { + parts.Add((ent.Value, part)); + } + } + + parts.Sort((a, b) => + { + int GetScore(Entity part) + { + return part.Comp.PartType switch + { + BodyPartType.Head => 1, + BodyPartType.Torso => 2, + BodyPartType.Arm => 3, + BodyPartType.Hand => 4, + BodyPartType.Leg => 5, + BodyPartType.Foot => 6, + BodyPartType.Tail => 7, + BodyPartType.Other => 8, + _ => 0 + }; + } + + return GetScore(a) - GetScore(b); + }); + + foreach (var part in parts) + { + var netPart = _entities.GetNetEntity(part.Owner); + var surgeries = state.Choices[netPart]; + var partName = _entities.GetComponent(part).EntityName; + var partButton = new BaseButtonForSurgery(); + + partButton.Set(partName, null); + partButton.Button.OnPressed += _ => OnPartPressed(netPart, surgeries); + + _window.Parts.AddChild(partButton); + + foreach (var surgeryId in surgeries) + { + if (_system.GetSingleton(surgeryId) is not { } surgery || + !_entities.TryGetComponent(surgery, out CMSurgeryComponent? surgeryComp)) + { + continue; + } + + if (oldPart == part && oldSurgery?.Proto == surgeryId) + OnSurgeryPressed((surgery, surgeryComp), netPart, surgeryId); + } + + if (oldPart == part && oldSurgery == null) + OnPartPressed(netPart, surgeries); + } + + RefreshUI(); + UpdateDisabledPanel(); + + if (!_window.IsOpen) + _window.OpenCentered(); + } + + private void AddStep(EntProtoId stepId, NetEntity netPart, EntProtoId surgeryId) + { + if (_window == null || + _system.GetSingleton(stepId) is not { } step) + { + return; + } + + var stepName = new FormattedMessage(); + stepName.AddText(_entities.GetComponent(step).EntityName); + + var stepButton = new CMSurgeryStepButton { Step = step }; + stepButton.Button.OnPressed += _ => SendMessage(new CMSurgeryStepChosenBuiMessage(netPart, surgeryId, stepId)); + + _window.Steps.AddChild(stepButton); + } + + private void OnSurgeryPressed(Entity surgery, NetEntity netPart, EntProtoId surgeryId) + { + if (_window == null) + return; + + _part = _entities.GetEntity(netPart); + _surgery = (surgery, surgeryId); + + _window.Steps.DisposeAllChildren(); + + if (surgery.Comp.Requirement is { } requirementId && _system.GetSingleton(requirementId) is { } requirement) + { + var label = new BaseButtonForSurgery(); + label.Button.OnPressed += _ => + { + _previousSurgeries.Add(surgeryId); + + if (_entities.TryGetComponent(requirement, out CMSurgeryComponent? requirementComp)) + OnSurgeryPressed((requirement, requirementComp), netPart, requirementId); + }; + + var msg = new FormattedMessage(); + var surgeryName = _entities.GetComponent(requirement).EntityName; + msg.AddMarkup($"[bold]Requires: {surgeryName}[/bold]"); + label.Set(msg, null); + + _window.Steps.AddChild(label); + _window.Steps.AddChild(new HSeparator { Color = Color.FromHex("#4972A1"), Margin = new Thickness(0, 0, 0, 1) }); + } + + foreach (var stepId in surgery.Comp.Steps) + { + AddStep(stepId, netPart, surgeryId); + } + + View(ViewType.Steps); + RefreshUI(); + } + + private void OnPartPressed(NetEntity netPart, List surgeryIds) + { + if (_window == null) + return; + + _part = _entities.GetEntity(netPart); + + _window.Surgeries.DisposeAllChildren(); + + var surgeries = new List<(Entity Ent, EntProtoId Id, string Name)>(); + foreach (var surgeryId in surgeryIds) + { + if (_system.GetSingleton(surgeryId) is not { } surgery || + !_entities.TryGetComponent(surgery, out CMSurgeryComponent? surgeryComp)) + { + continue; + } + + var name = _entities.GetComponent(surgery).EntityName; + surgeries.Add(((surgery, surgeryComp), surgeryId, name)); + } + + surgeries.Sort((a, b ) => + { + var priority = a.Ent.Comp.Priority.CompareTo(b.Ent.Comp.Priority); + if (priority != 0) + return priority; + + return string.Compare(a.Name, b.Name, StringComparison.Ordinal); + }); + + foreach (var surgery in surgeries) + { + var surgeryButton = new BaseButtonForSurgery(); + surgeryButton.Set(surgery.Name, null); + + surgeryButton.Button.OnPressed += _ => OnSurgeryPressed(surgery.Ent, netPart, surgery.Id); + _window.Surgeries.AddChild(surgeryButton); + } + + RefreshUI(); + View(ViewType.Surgeries); + } + + private void RefreshUI() + { + if (_window == null || + !_entities.HasComponent(_surgery?.Ent) || + !_entities.TryGetComponent(_part, out BodyPartComponent? part)) + { + return; + } + + var next = _system.GetNextStep(Owner, _part.Value, _surgery.Value.Ent); + var i = 0; + foreach (var child in _window.Steps.Children) + { + if (child is not CMSurgeryStepButton stepButton) + continue; + + var status = StepStatus.Incomplete; + if (next == null) + { + status = StepStatus.Complete; + } + else if (next.Value.Surgery.Owner != _surgery.Value.Ent) + { + status = StepStatus.Incomplete; + } + else if (next.Value.Step == i) + { + status = StepStatus.Next; + } + else if (i < next.Value.Step) + { + status = StepStatus.Complete; + } + + stepButton.Button.Disabled = status != StepStatus.Next; + + var stepName = new FormattedMessage(); + stepName.AddText(_entities.GetComponent(stepButton.Step).EntityName); + + if (status == StepStatus.Complete) + { + stepButton.Button.Modulate = Color.Green; + } + else + { + stepButton.Button.Modulate = Color.White; + if (_player.LocalEntity is { } player && + !_system.CanPerformStep(player, Owner, part.PartType, stepButton.Step, false, out var popup, out var reason, out _)) + { + stepButton.ToolTip = popup; + stepButton.Button.Disabled = true; + + switch (reason) + { + case StepInvalidReason.MissingSkills: + stepName.AddMarkup(" [color=red](Missing surgery skill)[/color]"); + break; + case StepInvalidReason.NeedsOperatingTable: + stepName.AddMarkup(" [color=red](Needs operating table)[/color]"); + break; + case StepInvalidReason.Armor: + stepName.AddMarkup(" [color=red](Remove their armor!)[/color]"); + break; + case StepInvalidReason.MissingTool: + stepName.AddMarkup(" [color=red](Missing tool)[/color]"); + break; + } + } + } + + var texture = _entities.GetComponentOrNull(stepButton.Step)?.Icon?.Default; + stepButton.Set(stepName, texture); + i++; + } + + UpdateDisabledPanel(); + } + + private void UpdateDisabledPanel() + { + if (_window == null) + return; + + if (_system.IsLyingDown(Owner)) + { + _window.DisabledPanel.Visible = false; + _window.DisabledPanel.MouseFilter = MouseFilterMode.Ignore; + return; + } + + _window.DisabledPanel.Visible = true; + + var text = new FormattedMessage(); + text.AddMarkup("[color=red][font size=16]They need to be lying down![/font][/color]"); + _window.DisabledLabel.SetMessage(text); + _window.DisabledPanel.MouseFilter = MouseFilterMode.Stop; + } + + private void View(ViewType type) + { + if (_window == null) + return; + + _window.PartsButton.Parent!.Margin = new Thickness(0, 0, 0, 10); + + _window.Parts.Visible = type == ViewType.Parts; + _window.PartsButton.Disabled = type == ViewType.Parts; + + _window.Surgeries.Visible = type == ViewType.Surgeries; + _window.SurgeriesButton.Disabled = type != ViewType.Steps; + + _window.Steps.Visible = type == ViewType.Steps; + _window.StepsButton.Disabled = type != ViewType.Steps || _previousSurgeries.Count == 0; + + if (_entities.TryGetComponent(_part, out MetaDataComponent? partMeta) && + _entities.TryGetComponent(_surgery?.Ent, out MetaDataComponent? surgeryMeta)) + { + _window.Title = $"Surgery - {partMeta.EntityName}, {surgeryMeta.EntityName}"; + } + else if (partMeta != null) + { + _window.Title = $"Surgery - {partMeta.EntityName}"; + } + else + { + _window.Title = "Surgery"; + } + } + + private enum ViewType + { + Parts, + Surgeries, + Steps + } + + private enum StepStatus + { + Next, + Complete, + Incomplete + } +} diff --git a/Content.Client/_CM14/Medical/Surgery/CMSurgeryStepButton.xaml b/Content.Client/_CM14/Medical/Surgery/CMSurgeryStepButton.xaml new file mode 100644 index 00000000000..368d761f9b6 --- /dev/null +++ b/Content.Client/_CM14/Medical/Surgery/CMSurgeryStepButton.xaml @@ -0,0 +1,4 @@ + + diff --git a/Content.Client/_CM14/Medical/Surgery/CMSurgeryStepButton.xaml.cs b/Content.Client/_CM14/Medical/Surgery/CMSurgeryStepButton.xaml.cs new file mode 100644 index 00000000000..bb9411c8e67 --- /dev/null +++ b/Content.Client/_CM14/Medical/Surgery/CMSurgeryStepButton.xaml.cs @@ -0,0 +1,16 @@ +using Content.Client._CM14.Xenos.UI; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._CM14.Medical.Surgery; + +[GenerateTypedNameReferences] +public sealed partial class CMSurgeryStepButton : BaseButtonForSurgery +{ + public EntityUid Step { get; set; } + + public CMSurgeryStepButton() + { + RobustXamlLoader.Load(this); + } +} diff --git a/Content.Client/_CM14/Medical/Surgery/CMSurgerySystem.cs b/Content.Client/_CM14/Medical/Surgery/CMSurgerySystem.cs new file mode 100644 index 00000000000..16a4d356765 --- /dev/null +++ b/Content.Client/_CM14/Medical/Surgery/CMSurgerySystem.cs @@ -0,0 +1,13 @@ +using Content.Shared._RMC14.Medical.Surgery; + +namespace Content.Client._CM14.Medical.Surgery; + +public sealed class CMSurgerySystem : SharedCMSurgerySystem +{ + public event Action? OnRefresh; + + public override void Update(float frameTime) + { + OnRefresh?.Invoke(); + } +} diff --git a/Content.Client/_CM14/Medical/Surgery/CMSurgeryWindow.xaml b/Content.Client/_CM14/Medical/Surgery/CMSurgeryWindow.xaml new file mode 100644 index 00000000000..510774b51d7 --- /dev/null +++ b/Content.Client/_CM14/Medical/Surgery/CMSurgeryWindow.xaml @@ -0,0 +1,30 @@ + + + + + + diff --git a/Content.Client/_CM14/Xenos/UI/BaseButtonForSurgery.xaml.cs b/Content.Client/_CM14/Xenos/UI/BaseButtonForSurgery.xaml.cs new file mode 100644 index 00000000000..5e95cb3be8f --- /dev/null +++ b/Content.Client/_CM14/Xenos/UI/BaseButtonForSurgery.xaml.cs @@ -0,0 +1,29 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.Graphics; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Utility; + +namespace Content.Client._CM14.Xenos.UI; + +[GenerateTypedNameReferences] +[Virtual] +public partial class BaseButtonForSurgery : Control +{ + public BaseButtonForSurgery() + { + RobustXamlLoader.Load(this); + } + + public void Set(string name, Texture? texture) + { + NameLabel.SetMessage(name); + Texture.Texture = texture; + } + + public void Set(FormattedMessage msg, Texture? texture) + { + NameLabel.SetMessage(msg); + Texture.Texture = texture; + } +} diff --git a/Content.Server/_CM14/Medical/Surgery/CMSurgerySystem.cs b/Content.Server/_CM14/Medical/Surgery/CMSurgerySystem.cs new file mode 100644 index 00000000000..c13b7be19f7 --- /dev/null +++ b/Content.Server/_CM14/Medical/Surgery/CMSurgerySystem.cs @@ -0,0 +1,125 @@ +using Content.Server.Body.Systems; +using Content.Server.Chat.Systems; +using Content.Server.Popups; +using Content.Shared._CM14.Marines.Skills; +using Content.Shared._CM14.Medical.Surgery; +using Content.Shared._CM14.Medical.Surgery.Conditions; +using Content.Shared._CM14.Medical.Surgery.Effects.Step; +using Content.Shared._CM14.Medical.Surgery.Tools; +using Content.Shared._RMC14.Medical.Surgery; +using Content.Shared.Interaction; +using Content.Shared.Prototypes; +using Robust.Server.GameObjects; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; +using CMSurgeryBuiState = Content.Shared._CM14.Medical.Surgery.CMSurgeryBuiState; +using CMSurgeryUIKey = Content.Shared._CM14.Medical.Surgery.CMSurgeryUIKey; + +namespace Content.Server._CM14.Medical.Surgery; + +public sealed class CMSurgerySystem : SharedCMSurgerySystem +{ + [Dependency] private readonly BloodstreamSystem _bloodstream = default!; + [Dependency] private readonly BodySystem _body = default!; + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly IPrototypeManager _prototypes = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly UserInterfaceSystem _ui = default!; + + private readonly List _surgeries = new(); + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnToolAfterInteract); + SubscribeLocalEvent(OnStepBleedComplete); + SubscribeLocalEvent(OnStepScreamComplete); + + SubscribeLocalEvent(OnPrototypesReloaded); + + LoadPrototypes(); + } + + protected override void RefreshUI(EntityUid body) + { + if (!HasComp(body)) + return; + + var surgeries = new Dictionary>(); + foreach (var surgery in _surgeries) + { + if (GetSingleton(surgery) is not { } surgeryEnt) + continue; + + foreach (var part in _body.GetBodyChildren(body)) + { + var ev = new CMSurgeryValidEvent(body, part.Id); + RaiseLocalEvent(surgeryEnt, ref ev); + + if (ev.Cancelled) + continue; + + surgeries.GetOrNew(GetNetEntity(part.Id)).Add(surgery); + } + } + + _ui.SetUiState(body, CMSurgeryUIKey.Key, new CMSurgeryBuiState(surgeries)); + } + + private void OnToolAfterInteract(Entity ent, ref AfterInteractEvent args) + { + if (args.Handled || + args.Target == null || + !TryComp(args.User, out ActorComponent? actor) || + !HasComp(args.Target)) + { + return; + } + + if (!TryComp(args.User, out SkillsComponent? skills) || skills.Surgery < 1) + { + _popup.PopupEntity("You don't know how to perform surgery!", args.User, args.User); + return; + } + + if (args.User == args.Target) + { + _popup.PopupEntity("You can't perform surgery on yourself!", args.User, args.User); + return; + } + + args.Handled = true; + _ui.OpenUi(args.Target.Value, CMSurgeryUIKey.Key, actor.PlayerSession); + + RefreshUI(args.Target.Value); + } + + private void OnStepBleedComplete(Entity ent, ref CMSurgeryStepEvent args) + { + _bloodstream.TryModifyBleedAmount(args.Body, ent.Comp.Amount); + } + + private void OnStepScreamComplete(Entity ent, ref CMSurgeryStepEvent args) + { + _chat.TryEmoteWithChat(args.Body, ent.Comp.Emote); + } + + private void OnPrototypesReloaded(PrototypesReloadedEventArgs args) + { + if (args.WasModified()) + LoadPrototypes(); + } + + private void LoadPrototypes() + { + _surgeries.Clear(); + + foreach (var entity in _prototypes.EnumeratePrototypes()) + { + if (entity.HasComponent()) + _surgeries.Add(new EntProtoId(entity.ID)); + } + } +} diff --git a/Content.Shared/_CM14/Body/BodyPrototype.cs b/Content.Shared/_CM14/Body/BodyPrototype.cs new file mode 100644 index 00000000000..9dc71f811d3 --- /dev/null +++ b/Content.Shared/_CM14/Body/BodyPrototype.cs @@ -0,0 +1,14 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; + +// ReSharper disable once CheckNamespace +namespace Content.Shared.Body.Prototypes; + +public sealed partial class BodyPrototype : IInheritingPrototype +{ + [ParentDataField(typeof(AbstractPrototypeIdArraySerializer))] + public string[]? Parents { get; } + + [AbstractDataField] + public bool Abstract { get; } +} diff --git a/Content.Shared/_CM14/Marines/Skills/SkillsComponent.cs b/Content.Shared/_CM14/Marines/Skills/SkillsComponent.cs new file mode 100644 index 00000000000..0552cb58022 --- /dev/null +++ b/Content.Shared/_CM14/Marines/Skills/SkillsComponent.cs @@ -0,0 +1,10 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Marines.Skills; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SkillsComponent : Component +{ + [DataField, AutoNetworkedField] + public int Surgery; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/CMOperatingTableComponent.cs b/Content.Shared/_CM14/Medical/Surgery/CMOperatingTableComponent.cs new file mode 100644 index 00000000000..6f9a09026ed --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/CMOperatingTableComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMOperatingTableComponent : Component {}; diff --git a/Content.Shared/_CM14/Medical/Surgery/CMSurgeryComponent.cs b/Content.Shared/_CM14/Medical/Surgery/CMSurgeryComponent.cs new file mode 100644 index 00000000000..28a5798362e --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/CMSurgeryComponent.cs @@ -0,0 +1,19 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._CM14.Medical.Surgery; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMSurgeryComponent : Component +{ + [DataField, AutoNetworkedField, Access(typeof(SharedCMSurgerySystem), Other = AccessPermissions.ReadWriteExecute)] + public int Priority; + + [DataField, AutoNetworkedField] + public EntProtoId? Requirement; + + [DataField(required: true), AutoNetworkedField] + public List Steps = new(); +} diff --git a/Content.Shared/_CM14/Medical/Surgery/CMSurgeryDoAfterEvent.cs b/Content.Shared/_CM14/Medical/Surgery/CMSurgeryDoAfterEvent.cs new file mode 100644 index 00000000000..ddbab5f89e2 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/CMSurgeryDoAfterEvent.cs @@ -0,0 +1,18 @@ +using Content.Shared.DoAfter; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Medical.Surgery; + +[Serializable, NetSerializable] +public sealed partial class CMSurgeryDoAfterEvent : SimpleDoAfterEvent +{ + public readonly EntProtoId Surgery; + public readonly EntProtoId Step; + + public CMSurgeryDoAfterEvent(EntProtoId surgery, EntProtoId step) + { + Surgery = surgery; + Step = step; + } +} diff --git a/Content.Shared/_CM14/Medical/Surgery/CMSurgeryStepEvent.cs b/Content.Shared/_CM14/Medical/Surgery/CMSurgeryStepEvent.cs new file mode 100644 index 00000000000..b52108767e0 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/CMSurgeryStepEvent.cs @@ -0,0 +1,7 @@ +namespace Content.Shared._CM14.Medical.Surgery; + +/// +/// Raised on the step entity. +/// +[ByRefEvent] +public record struct CMSurgeryStepEvent(EntityUid User, EntityUid Body, EntityUid Part, List Tools); diff --git a/Content.Shared/_CM14/Medical/Surgery/CMSurgeryTargetComponent.cs b/Content.Shared/_CM14/Medical/Surgery/CMSurgeryTargetComponent.cs new file mode 100644 index 00000000000..867d4149714 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/CMSurgeryTargetComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMSurgeryTargetComponent : Component {}; diff --git a/Content.Shared/_CM14/Medical/Surgery/CMSurgeryUI.cs b/Content.Shared/_CM14/Medical/Surgery/CMSurgeryUI.cs new file mode 100644 index 00000000000..57514ec2ec3 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/CMSurgeryUI.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._CM14.Medical.Surgery; + +[Serializable, NetSerializable] +public enum CMSurgeryUIKey +{ + Key +} + +[Serializable, NetSerializable] +public sealed class CMSurgeryBuiState(Dictionary> choices) : BoundUserInterfaceState +{ + public readonly Dictionary> Choices = choices; +} + +[Serializable, NetSerializable] +public sealed class CMSurgeryStepChosenBuiMessage(NetEntity part, EntProtoId surgery, EntProtoId step) : BoundUserInterfaceMessage +{ + public readonly NetEntity Part = part; + public readonly EntProtoId Surgery = surgery; + public readonly EntProtoId Step = step; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryCloseIncisionConditionComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryCloseIncisionConditionComponent.cs new file mode 100644 index 00000000000..248318f819b --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryCloseIncisionConditionComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Conditions; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMSurgeryCloseIncisionConditionComponent : Component {}; diff --git a/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryOperatingTableConditionComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryOperatingTableConditionComponent.cs new file mode 100644 index 00000000000..9caf66585e4 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryOperatingTableConditionComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Conditions; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMSurgeryOperatingTableConditionComponent : Component {}; diff --git a/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryPartConditionComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryPartConditionComponent.cs new file mode 100644 index 00000000000..1887872ece7 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryPartConditionComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared.Body.Part; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Conditions; + +[RegisterComponent, NetworkedComponent] +public sealed partial class CMSurgeryPartConditionComponent : Component +{ + [DataField] + public BodyPartType Part; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryValidEvent.cs b/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryValidEvent.cs new file mode 100644 index 00000000000..0a94cab1e73 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Conditions/CMSurgeryValidEvent.cs @@ -0,0 +1,7 @@ +namespace Content.Shared._CM14.Medical.Surgery.Conditions; + +/// +/// Raised on the entity that is receiving surgery. +/// +[ByRefEvent] +public record struct CMSurgeryValidEvent(EntityUid Body, EntityUid Part, bool Cancelled = false); diff --git a/Content.Shared/_CM14/Medical/Surgery/Effects/Complete/CMSurgeryCompletedEvent.cs b/Content.Shared/_CM14/Medical/Surgery/Effects/Complete/CMSurgeryCompletedEvent.cs new file mode 100644 index 00000000000..7357eef092f --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Effects/Complete/CMSurgeryCompletedEvent.cs @@ -0,0 +1,7 @@ +namespace Content.Shared._CM14.Medical.Surgery.Effects.Complete; + +/// +/// Raised on the entity that received the surgery. +/// +[ByRefEvent] +public record struct CMSurgeryCompletedEvent; diff --git a/Content.Shared/_CM14/Medical/Surgery/Effects/Step/CMSurgeryStepBleedEffectComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Effects/Step/CMSurgeryStepBleedEffectComponent.cs new file mode 100644 index 00000000000..19c80b3464d --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Effects/Step/CMSurgeryStepBleedEffectComponent.cs @@ -0,0 +1,12 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Effects.Step; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMSurgeryStepBleedEffectComponent : Component +{ + [DataField, AutoNetworkedField] + public int Amount; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Effects/Step/CMSurgeryStepEmoteEffectComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Effects/Step/CMSurgeryStepEmoteEffectComponent.cs new file mode 100644 index 00000000000..d758b197ed2 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Effects/Step/CMSurgeryStepEmoteEffectComponent.cs @@ -0,0 +1,14 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Content.Shared.Chat.Prototypes; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._CM14.Medical.Surgery.Effects.Step; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMSurgeryStepEmoteEffectComponent : Component +{ + [DataField, AutoNetworkedField] + public ProtoId Emote = "Scream"; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/SharedCMSurgerySystem.Steps.cs b/Content.Shared/_CM14/Medical/Surgery/SharedCMSurgerySystem.Steps.cs new file mode 100644 index 00000000000..7d7a47c399f --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/SharedCMSurgerySystem.Steps.cs @@ -0,0 +1,318 @@ +using Content.Shared._CM14.Medical.Surgery; +using Content.Shared._CM14.Medical.Surgery.Conditions; +using Content.Shared._CM14.Medical.Surgery.Steps; +using Content.Shared._CM14.Medical.Surgery.Tools; +using Content.Shared._RMC14.Medical.Surgery.Steps; +using Content.Shared.Body.Part; +using Content.Shared.Buckle.Components; +using Content.Shared.DoAfter; +using Content.Shared.Inventory; +using Content.Shared.Popups; +using Robust.Shared.Prototypes; + +namespace Content.Shared._RMC14.Medical.Surgery; + +public abstract partial class SharedCMSurgerySystem +{ + private void InitializeSteps() + { + SubscribeLocalEvent(OnToolStep); + SubscribeLocalEvent(OnToolCheck); + SubscribeLocalEvent(OnToolCanPerform); + + Subs.BuiEvents(CMSurgeryUIKey.Key, subs => + { + subs.Event(OnSurgeryTargetStepChosen); + }); + } + + private void SubSurgery(EntityEventRefHandler onStep, + EntityEventRefHandler onComplete) where TComp : IComponent + { + SubscribeLocalEvent(onStep); + SubscribeLocalEvent(onComplete); + } + + private void OnToolStep(Entity ent, ref CMSurgeryStepEvent args) + { + if (ent.Comp.Tool != null) + { + foreach (var reg in ent.Comp.Tool.Values) + { + if (!AnyHaveComp(args.Tools, reg.Component, out var tool)) + return; + + if (_net.IsServer && + TryComp(tool, out CMSurgeryToolComponent? toolComp) && + toolComp.EndSound != null) + { + _audio.PlayEntity(toolComp.EndSound, args.User, tool); + } + } + } + + if (ent.Comp.Add != null) + { + foreach (var reg in ent.Comp.Add.Values) + { + var compType = reg.Component.GetType(); + if (HasComp(args.Part, compType)) + continue; + + AddComp(args.Part, _compFactory.GetComponent(compType)); + } + } + + if (ent.Comp.Remove != null) + { + foreach (var reg in ent.Comp.Remove.Values) + { + RemComp(args.Part, reg.Component.GetType()); + } + } + + if (ent.Comp.BodyRemove != null) + { + foreach (var reg in ent.Comp.BodyRemove.Values) + { + RemComp(args.Body, reg.Component.GetType()); + } + } + } + + private void OnToolCheck(Entity ent, ref CMSurgeryStepCompleteCheckEvent args) + { + if (ent.Comp.Add != null) + { + foreach (var reg in ent.Comp.Add.Values) + { + if (!HasComp(args.Part, reg.Component.GetType())) + { + args.Cancelled = true; + return; + } + } + } + + if (ent.Comp.Remove != null) + { + foreach (var reg in ent.Comp.Remove.Values) + { + if (HasComp(args.Part, reg.Component.GetType())) + { + args.Cancelled = true; + return; + } + } + } + + if (ent.Comp.BodyRemove != null) + { + foreach (var reg in ent.Comp.BodyRemove.Values) + { + if (HasComp(args.Body, reg.Component.GetType())) + { + args.Cancelled = true; + return; + } + } + } + } + + private void OnToolCanPerform(Entity ent, ref CMSurgeryCanPerformStepEvent args) + { + if (HasComp(ent)) + { + if (!TryComp(args.Body, out BuckleComponent? buckle) || + !HasComp(buckle.BuckledTo)) + { + args.Invalid = StepInvalidReason.NeedsOperatingTable; + return; + } + } + + RaiseLocalEvent(args.Body, ref args); + + if (args.Invalid != StepInvalidReason.None) + return; + + if (ent.Comp.Tool != null) + { + args.ValidTools ??= new HashSet(); + + foreach (var reg in ent.Comp.Tool.Values) + { + if (!AnyHaveComp(args.Tools, reg.Component, out var withComp)) + { + args.Invalid = StepInvalidReason.MissingTool; + + if (reg.Component is ICMSurgeryToolComponent tool) + args.Popup = $"You need {tool.ToolName} to perform this step!"; + + return; + } + + args.ValidTools.Add(withComp); + } + } + } + + private void OnSurgeryTargetStepChosen(Entity ent, ref CMSurgeryStepChosenBuiMsg args) + { + if (GetEntity(args.Entity) is not { Valid: true } body || + GetEntity(args.Part) is not { Valid: true } targetPart || + !IsSurgeryValid(body, targetPart, args.Surgery, args.Step, out var surgery, out var part, out var step)) + { + return; + } + + if (!PreviousStepsComplete(body, part, surgery, args.Step) || IsStepComplete(body, part, args.Step)) + return; + + if (!CanPerformStep(args.Actor, body, part.Comp.PartType, step, true, out _, out _, out var validTools)) + return; + + if (_net.IsServer && validTools?.Count > 0) + { + foreach (var tool in validTools) + { + if (TryComp(tool, out CMSurgeryToolComponent? toolComp) && + toolComp.EndSound != null) + { + _audio.PlayEntity(toolComp.StartSound, args.Actor, tool); + } + } + } + + if (TryComp(body, out TransformComponent? xform)) + _rotateToFace.TryFaceCoordinates(args.Actor, _transform.GetMapCoordinates(body, xform).Position); + + var ev = new CMSurgeryDoAfterEvent(args.Surgery, args.Step); + var doAfter = new DoAfterArgs(EntityManager, args.Actor, 2, ev, body, part) + { + BreakOnMove = true, + }; + _doAfter.TryStartDoAfter(doAfter); + } + + private (Entity Surgery, int Step)? GetNextStep(EntityUid body, EntityUid part, Entity surgery, List requirements) + { + if (!Resolve(surgery, ref surgery.Comp)) + return null; + + if (requirements.Contains(surgery)) + throw new ArgumentException($"Surgery {surgery} has a requirement loop: {string.Join(", ", requirements)}"); + + requirements.Add(surgery); + + if (surgery.Comp.Requirement is { } requirementId && + GetSingleton(requirementId) is { } requirement && + GetNextStep(body, part, requirement, requirements) is { } requiredNext) + { + return requiredNext; + } + + for (var i = 0; i < surgery.Comp.Steps.Count; i++) + { + var surgeryStep = surgery.Comp.Steps[i]; + if (!IsStepComplete(body, part, surgeryStep)) + return ((surgery, surgery.Comp), i); + } + + return null; + } + + public (Entity Surgery, int Step)? GetNextStep(EntityUid body, EntityUid part, EntityUid surgery) + { + return GetNextStep(body, part, surgery, new List()); + } + + public bool PreviousStepsComplete(EntityUid body, EntityUid part, Entity surgery, EntProtoId step) + { + // TODO RMC14 use index instead of the prototype id + if (surgery.Comp.Requirement is { } requirement) + { + if (GetSingleton(requirement) is not { } requiredEnt || + !TryComp(requiredEnt, out CMSurgeryComponent? requiredComp) || + !PreviousStepsComplete(body, part, (requiredEnt, requiredComp), step)) + { + return false; + } + } + + foreach (var surgeryStep in surgery.Comp.Steps) + { + if (surgeryStep == step) + break; + + if (!IsStepComplete(body, part, surgeryStep)) + return false; + } + + return true; + } + + public bool CanPerformStep(EntityUid user, EntityUid body, BodyPartType part, EntityUid step, bool doPopup, out string? popup, out StepInvalidReason reason, out HashSet? validTools) + { + var slot = part switch + { + BodyPartType.Head => SlotFlags.HEAD, + BodyPartType.Torso => SlotFlags.OUTERCLOTHING | SlotFlags.INNERCLOTHING, + BodyPartType.Arm => SlotFlags.OUTERCLOTHING | SlotFlags.INNERCLOTHING, + BodyPartType.Hand => SlotFlags.GLOVES, + BodyPartType.Leg => SlotFlags.OUTERCLOTHING | SlotFlags.LEGS, + BodyPartType.Foot => SlotFlags.FEET, + BodyPartType.Tail => SlotFlags.NONE, + BodyPartType.Other => SlotFlags.NONE, + _ => SlotFlags.NONE + }; + + var check = new CMSurgeryCanPerformStepEvent(user, body, GetTools(user), slot); + RaiseLocalEvent(step, ref check); + popup = check.Popup; + validTools = check.ValidTools; + + if (check.Invalid != StepInvalidReason.None) + { + if (doPopup && check.Popup != null) + _popup.PopupEntity(check.Popup, user, PopupType.SmallCaution); + + reason = check.Invalid; + return false; + } + + reason = default; + return true; + } + + public bool CanPerformStep(EntityUid user, EntityUid body, BodyPartType part, EntityUid step, bool doPopup) + { + return CanPerformStep(user, body, part, step, doPopup, out _, out _, out _); + } + + public bool IsStepComplete(EntityUid body, EntityUid part, EntProtoId step) + { + if (GetSingleton(step) is not { } stepEnt) + return false; + + var ev = new CMSurgeryStepCompleteCheckEvent(body, part); + RaiseLocalEvent(stepEnt, ref ev); + + return !ev.Cancelled; + } + + private bool AnyHaveComp(List tools, IComponent component, out EntityUid withComp) + { + foreach (var tool in tools) + { + if (HasComp(tool, component.GetType())) + { + withComp = tool; + return true; + } + } + + withComp = default; + return false; + } +} diff --git a/Content.Shared/_CM14/Medical/Surgery/SharedCMSurgerySystem.cs b/Content.Shared/_CM14/Medical/Surgery/SharedCMSurgerySystem.cs new file mode 100644 index 00000000000..b3864e4917b --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/SharedCMSurgerySystem.cs @@ -0,0 +1,161 @@ +using System.Linq; +using Content.Shared._CM14.Medical.Surgery; +using Content.Shared._CM14.Medical.Surgery.Conditions; +using Content.Shared._CM14.Medical.Surgery.Steps.Parts; +using Content.Shared.Body.Part; +using Content.Shared.Buckle.Components; +using Content.Shared.DoAfter; +using Content.Shared.GameTicking; +using Content.Shared.Hands.EntitySystems; +using Content.Shared.Interaction; +using Content.Shared.Popups; +using Content.Shared.Standing.Systems; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Map; +using Robust.Shared.Network; +using Robust.Shared.Prototypes; +using Robust.Shared.Timing; + +namespace Content.Shared._RMC14.Medical.Surgery; + +public abstract partial class SharedCMSurgerySystem : EntitySystem +{ + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly IComponentFactory _compFactory = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly SharedHandsSystem _hands = default!; + [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly IPrototypeManager _prototypes = default!; + [Dependency] private readonly RotateToFaceSystem _rotateToFace = default!; + [Dependency] private readonly SharedStandingStateSystem _standing = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + + private readonly Dictionary _surgeries = new(); + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRoundRestartCleanup); + + SubscribeLocalEvent(OnTargetDoAfter); + + SubscribeLocalEvent(OnCloseIncisionValid); + SubscribeLocalEvent(OnPartConditionValid); + + InitializeSteps(); + } + + private void OnRoundRestartCleanup(RoundRestartCleanupEvent ev) + { + _surgeries.Clear(); + } + + private void OnTargetDoAfter(Entity ent, ref CMSurgeryDoAfterEvent args) + { + if (args.Cancelled || + args.Handled || + args.Target is not { } target || + !IsSurgeryValid(ent, target, args.Surgery, args.Step, out var surgery, out var part, out var step) || + !PreviousStepsComplete(ent, part, surgery, args.Step) || + !CanPerformStep(args.User, ent, part.Comp.PartType, step, false)) + { + Log.Warning($"{ToPrettyString(args.User)} tried to start invalid surgery."); + return; + } + + var ev = new CMSurgeryStepEvent(args.User, ent, part, GetTools(args.User)); + RaiseLocalEvent(step, ref ev); + + RefreshUI(ent); + } + + private void OnCloseIncisionValid(Entity ent, ref CMSurgeryValidEvent args) + { + if (!HasComp(args.Part) || + !HasComp(args.Part) || + !HasComp(args.Part)) + { + args.Cancelled = true; + } + } + + private void OnPartConditionValid(Entity ent, ref CMSurgeryValidEvent args) + { + if (CompOrNull(args.Part)?.PartType != ent.Comp.Part) + args.Cancelled = true; + } + + protected bool IsSurgeryValid(EntityUid body, EntityUid targetPart, EntProtoId surgery, EntProtoId stepId, out Entity surgeryEnt, out Entity part, out EntityUid step) + { + surgeryEnt = default; + part = default; + step = default; + + if (!HasComp(body) || + !IsLyingDown(body) || + !TryComp(targetPart, out BodyPartComponent? partComp) || + GetSingleton(surgery) is not { } surgeryEntId || + !TryComp(surgeryEntId, out CMSurgeryComponent? surgeryComp) || + !surgeryComp.Steps.Contains(stepId) || + GetSingleton(stepId) is not { } stepEnt) + { + return false; + } + + var ev = new CMSurgeryValidEvent(body, targetPart); + RaiseLocalEvent(stepEnt, ref ev); + RaiseLocalEvent(surgeryEntId, ref ev); + + if (ev.Cancelled) + return false; + + surgeryEnt = (surgeryEntId, surgeryComp); + part = (targetPart, partComp); + step = stepEnt; + return true; + } + + public EntityUid? GetSingleton(EntProtoId surgeryOrStep) + { + if (!_prototypes.HasIndex(surgeryOrStep)) + return null; + + // This (for now) assumes that surgery entity data remains unchanged between client + // and server + // if it does not you get the bullet + if (!_surgeries.TryGetValue(surgeryOrStep, out var ent) || TerminatingOrDeleted(ent)) + { + ent = Spawn(surgeryOrStep, MapCoordinates.Nullspace); + _surgeries[surgeryOrStep] = ent; + } + + return ent; + } + + private List GetTools(EntityUid surgeon) + { + return _hands.EnumerateHeld(surgeon).ToList(); + } + + public bool IsLyingDown(EntityUid entity) + { + if (_standing.IsDown(entity)) + return true; + + if (TryComp(entity, out BuckleComponent? buckle) && + TryComp(buckle.BuckledTo, out StrapComponent? strap)) + { + var rotation = strap.Rotation; + if (rotation.GetCardinalDir() is Direction.West or Direction.East) + return true; + } + + return false; + } + + protected virtual void RefreshUI(EntityUid body) + { + } +} diff --git a/Content.Shared/_CM14/Medical/Surgery/StepInvalidReason.cs b/Content.Shared/_CM14/Medical/Surgery/StepInvalidReason.cs new file mode 100644 index 00000000000..9865e8ea89d --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/StepInvalidReason.cs @@ -0,0 +1,10 @@ +namespace Content.Shared._CM14.Medical.Surgery; + +public enum StepInvalidReason +{ + None, + MissingSkills, + NeedsOperatingTable, + Armor, + MissingTool, +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Steps/CMSurgeryCanPerformStepEvent.cs b/Content.Shared/_CM14/Medical/Surgery/Steps/CMSurgeryCanPerformStepEvent.cs new file mode 100644 index 00000000000..cd9b821f8a3 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Steps/CMSurgeryCanPerformStepEvent.cs @@ -0,0 +1,14 @@ +using Content.Shared.Inventory; + +namespace Content.Shared._CM14.Medical.Surgery.Steps; + +[ByRefEvent] +public record struct CMSurgeryCanPerformStepEvent( + EntityUid User, + EntityUid Body, + List Tools, + SlotFlags TargetSlots, + string? Popup = null, + StepInvalidReason Invalid = StepInvalidReason.None, + HashSet? ValidTools = null +) : IInventoryRelayEvent; diff --git a/Content.Shared/_CM14/Medical/Surgery/Steps/CMSurgeryStepCompleteCheckEvent.cs b/Content.Shared/_CM14/Medical/Surgery/Steps/CMSurgeryStepCompleteCheckEvent.cs new file mode 100644 index 00000000000..37841dc3afd --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Steps/CMSurgeryStepCompleteCheckEvent.cs @@ -0,0 +1,4 @@ +namespace Content.Shared._CM14.Medical.Surgery.Steps; + +[ByRefEvent] +public record struct CMSurgeryStepCompleteCheckEvent(EntityUid Body, EntityUid Part, bool Cancelled = false); diff --git a/Content.Shared/_CM14/Medical/Surgery/Steps/CMSurgeryStepComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Steps/CMSurgeryStepComponent.cs new file mode 100644 index 00000000000..9885b2d1789 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Steps/CMSurgeryStepComponent.cs @@ -0,0 +1,24 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._RMC14.Medical.Surgery.Steps; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMSurgeryStepComponent : Component +{ + [DataField, AutoNetworkedField] + public int Skill = 1; + + [DataField] + public ComponentRegistry? Tool; + + [DataField] + public ComponentRegistry? Add; + + [DataField] + public ComponentRegistry? Remove; + + [DataField] + public ComponentRegistry? BodyRemove; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMBleedersClampedComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMBleedersClampedComponent.cs new file mode 100644 index 00000000000..d73c196cedf --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMBleedersClampedComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Steps.Parts; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMBleedersClampedComponent : Component {}; diff --git a/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMIncisionOpenComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMIncisionOpenComponent.cs new file mode 100644 index 00000000000..96557a828af --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMIncisionOpenComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Steps.Parts; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMIncisionOpenComponent : Component {}; diff --git a/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMRibcageOpenComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMRibcageOpenComponent.cs new file mode 100644 index 00000000000..bab67357cbb --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMRibcageOpenComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Steps.Parts; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMRibcageOpenComponent : Component {}; diff --git a/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMRibcageSawedComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMRibcageSawedComponent.cs new file mode 100644 index 00000000000..52565e6a71e --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMRibcageSawedComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Steps.Parts; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMRibcageSawedComponent : Component {}; diff --git a/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMSkinRetractedComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMSkinRetractedComponent.cs new file mode 100644 index 00000000000..d9042df2919 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Steps/Parts/CMSkinRetractedComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Steps.Parts; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMSkinRetractedComponent : Component {}; diff --git a/Content.Shared/_CM14/Medical/Surgery/Tools/CMBoneGelComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Tools/CMBoneGelComponent.cs new file mode 100644 index 00000000000..c8de96534ca --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Tools/CMBoneGelComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Tools; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMBoneGelComponent : Component, ICMSurgeryToolComponent +{ + public string ToolName => "bone gel"; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Tools/CMBoneSawComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Tools/CMBoneSawComponent.cs new file mode 100644 index 00000000000..7d9076513f5 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Tools/CMBoneSawComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Tools; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMBoneSawComponent : Component, ICMSurgeryToolComponent +{ + public string ToolName => "a bone saw"; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Tools/CMCauteryComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Tools/CMCauteryComponent.cs new file mode 100644 index 00000000000..5f58831ad14 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Tools/CMCauteryComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Tools; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMCauteryComponent : Component, ICMSurgeryToolComponent +{ + public string ToolName => "a cautery"; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Tools/CMHemostatComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Tools/CMHemostatComponent.cs new file mode 100644 index 00000000000..5022462d642 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Tools/CMHemostatComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Tools; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMHemostatComponent : Component, ICMSurgeryToolComponent +{ + public string ToolName => "a hemostat"; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Tools/CMRetractorComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Tools/CMRetractorComponent.cs new file mode 100644 index 00000000000..cb24fd38098 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Tools/CMRetractorComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Tools; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMRetractorComponent : Component, ICMSurgeryToolComponent +{ + public string ToolName => "a retractor"; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Tools/CMScalpelComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Tools/CMScalpelComponent.cs new file mode 100644 index 00000000000..9e71fdc39ce --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Tools/CMScalpelComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Tools; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMScalpelComponent : Component, ICMSurgeryToolComponent +{ + public string ToolName => "a scalpel"; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Tools/CMSurgeryToolComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Tools/CMSurgeryToolComponent.cs new file mode 100644 index 00000000000..6b579175ae9 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Tools/CMSurgeryToolComponent.cs @@ -0,0 +1,16 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Tools; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMSurgeryToolComponent : Component +{ + [DataField, AutoNetworkedField] + public SoundSpecifier? StartSound; + + [DataField, AutoNetworkedField] + public SoundSpecifier? EndSound; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Tools/CMSurgicalDrillComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Tools/CMSurgicalDrillComponent.cs new file mode 100644 index 00000000000..4ad2c9ee2ad --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Tools/CMSurgicalDrillComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared._RMC14.Medical.Surgery; +using Robust.Shared.GameStates; + +namespace Content.Shared._CM14.Medical.Surgery.Tools; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedCMSurgerySystem))] +public sealed partial class CMSurgicalDrillComponent : Component, ICMSurgeryToolComponent +{ + public string ToolName => "a surgical drill"; +} diff --git a/Content.Shared/_CM14/Medical/Surgery/Tools/ICMSurgeryToolComponent.cs b/Content.Shared/_CM14/Medical/Surgery/Tools/ICMSurgeryToolComponent.cs new file mode 100644 index 00000000000..6da06324584 --- /dev/null +++ b/Content.Shared/_CM14/Medical/Surgery/Tools/ICMSurgeryToolComponent.cs @@ -0,0 +1,6 @@ +namespace Content.Shared._CM14.Medical.Surgery.Tools; + +public interface ICMSurgeryToolComponent +{ + public string ToolName { get; } +} diff --git a/Content.Shared/_RMC/Medical/Surgery/CMSurgeryUI.cs b/Content.Shared/_RMC/Medical/Surgery/CMSurgeryUI.cs new file mode 100644 index 00000000000..68bef1cbc4b --- /dev/null +++ b/Content.Shared/_RMC/Medical/Surgery/CMSurgeryUI.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared._RMC14.Medical.Surgery; + +[Serializable, NetSerializable] +public enum CMSurgeryUIKey +{ + Key +} + +[Serializable, NetSerializable] +public sealed class CMSurgeryBuiState(Dictionary> choices) : BoundUserInterfaceState +{ + public readonly Dictionary> Choices = choices; +} + +[Serializable, NetSerializable] +public sealed class CMSurgeryStepChosenBuiMsg(NetEntity part, EntProtoId surgery, EntProtoId step) : BoundUserInterfaceMessage +{ + public readonly NetEntity Part = part; + public readonly EntProtoId Surgery = surgery; + public readonly EntProtoId Step = step; +} diff --git a/Resources/Audio/_CM14/Medical/Surgery/attributions.yml b/Resources/Audio/_CM14/Medical/Surgery/attributions.yml new file mode 100644 index 00000000000..0ddaa09bceb --- /dev/null +++ b/Resources/Audio/_CM14/Medical/Surgery/attributions.yml @@ -0,0 +1,49 @@ +- files: ["cautery1.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/fae73dfa5aedb0a253de04b60085ed8a178d3bf7/sound/surgery/cautery1.ogg" + +- files: ["cautery2.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/fae73dfa5aedb0a253de04b60085ed8a178d3bf7/sound/surgery/cautery2.ogg" + +- files: ["hemostat.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/fae73dfa5aedb0a253de04b60085ed8a178d3bf7/sound/surgery/hemostat.ogg" + +- files: ["organ1.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/fae73dfa5aedb0a253de04b60085ed8a178d3bf7/sound/surgery/organ1.ogg" + +- files: ["organ2.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/fae73dfa5aedb0a253de04b60085ed8a178d3bf7/sound/surgery/organ2.ogg" + +- files: ["retractor1.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/fae73dfa5aedb0a253de04b60085ed8a178d3bf7/sound/surgery/retractor1.ogg" + +- files: ["retractor2.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/fae73dfa5aedb0a253de04b60085ed8a178d3bf7/sound/surgery/retractor2.ogg" + +- files: ["saw.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/fae73dfa5aedb0a253de04b60085ed8a178d3bf7/sound/surgery/saw.ogg" + +- files: ["scalpel1.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/fae73dfa5aedb0a253de04b60085ed8a178d3bf7/sound/surgery/scalpel1.ogg" + +- files: ["scalpel2.ogg"] + license: "CC-BY-SA-3.0" + copyright: "Taken from cmss13" + source: "https://github.com/cmss13-devs/cmss13/blob/fae73dfa5aedb0a253de04b60085ed8a178d3bf7/sound/surgery/scalpel2.ogg" diff --git a/Resources/Audio/_CM14/Medical/Surgery/cautery1.ogg b/Resources/Audio/_CM14/Medical/Surgery/cautery1.ogg new file mode 100644 index 00000000000..fbd9f2b4d86 Binary files /dev/null and b/Resources/Audio/_CM14/Medical/Surgery/cautery1.ogg differ diff --git a/Resources/Audio/_CM14/Medical/Surgery/cautery2.ogg b/Resources/Audio/_CM14/Medical/Surgery/cautery2.ogg new file mode 100644 index 00000000000..cc91e9f3ce6 Binary files /dev/null and b/Resources/Audio/_CM14/Medical/Surgery/cautery2.ogg differ diff --git a/Resources/Audio/_CM14/Medical/Surgery/hemostat1.ogg b/Resources/Audio/_CM14/Medical/Surgery/hemostat1.ogg new file mode 100644 index 00000000000..e624bafafbf Binary files /dev/null and b/Resources/Audio/_CM14/Medical/Surgery/hemostat1.ogg differ diff --git a/Resources/Audio/_CM14/Medical/Surgery/organ1.ogg b/Resources/Audio/_CM14/Medical/Surgery/organ1.ogg new file mode 100644 index 00000000000..37eaffc1a34 Binary files /dev/null and b/Resources/Audio/_CM14/Medical/Surgery/organ1.ogg differ diff --git a/Resources/Audio/_CM14/Medical/Surgery/organ2.ogg b/Resources/Audio/_CM14/Medical/Surgery/organ2.ogg new file mode 100644 index 00000000000..43b22f8354c Binary files /dev/null and b/Resources/Audio/_CM14/Medical/Surgery/organ2.ogg differ diff --git a/Resources/Audio/_CM14/Medical/Surgery/retractor1.ogg b/Resources/Audio/_CM14/Medical/Surgery/retractor1.ogg new file mode 100644 index 00000000000..70625c961cf Binary files /dev/null and b/Resources/Audio/_CM14/Medical/Surgery/retractor1.ogg differ diff --git a/Resources/Audio/_CM14/Medical/Surgery/retractor2.ogg b/Resources/Audio/_CM14/Medical/Surgery/retractor2.ogg new file mode 100644 index 00000000000..94548ec2504 Binary files /dev/null and b/Resources/Audio/_CM14/Medical/Surgery/retractor2.ogg differ diff --git a/Resources/Audio/_CM14/Medical/Surgery/saw.ogg b/Resources/Audio/_CM14/Medical/Surgery/saw.ogg new file mode 100644 index 00000000000..62623f6aa3a Binary files /dev/null and b/Resources/Audio/_CM14/Medical/Surgery/saw.ogg differ diff --git a/Resources/Audio/_CM14/Medical/Surgery/scalpel1.ogg b/Resources/Audio/_CM14/Medical/Surgery/scalpel1.ogg new file mode 100644 index 00000000000..f292d1024da Binary files /dev/null and b/Resources/Audio/_CM14/Medical/Surgery/scalpel1.ogg differ diff --git a/Resources/Audio/_CM14/Medical/Surgery/scalpel2.ogg b/Resources/Audio/_CM14/Medical/Surgery/scalpel2.ogg new file mode 100644 index 00000000000..7335f3d9cef Binary files /dev/null and b/Resources/Audio/_CM14/Medical/Surgery/scalpel2.ogg differ diff --git a/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml b/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml index 6aa766bd588..0639b248cb9 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml @@ -3,8 +3,7 @@ id: BaseFlatpack name: base flatpack description: A flatpack used for constructing something. - categories: - - hideSpawnMenu + noSpawn: true components: - type: Item size: Large diff --git a/Resources/Prototypes/Entities/Structures/Machines/flatpacker.yml b/Resources/Prototypes/Entities/Structures/Machines/flatpacker.yml index b4f05cf68a7..37fdad46ba7 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/flatpacker.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/flatpacker.yml @@ -83,8 +83,7 @@ - type: entity id: FlatpackerNoBoardEffect - categories: - - hideSpawnMenu + noSpawn: true components: - type: Sprite sprite: Structures/Machines/autolathe.rsi diff --git a/Resources/Prototypes/_CM14/Entities/Mobs/Species/base.yml b/Resources/Prototypes/_CM14/Entities/Mobs/Species/base.yml new file mode 100644 index 00000000000..5e04d1761f0 --- /dev/null +++ b/Resources/Prototypes/_CM14/Entities/Mobs/Species/base.yml @@ -0,0 +1,67 @@ +- type: entity + save: false + parent: BaseMobSpeciesOrganic + id: CMBaseMobSpeciesOrganic + abstract: true + name: Urist C.M. McHands + suffix: CM14 + components: + - type: Hunger + - type: Thirst + - type: Body + prototype: Human + requiredLegs: 2 + - type: Damageable + damageContainer: Biological + damageModifierSet: null + - type: Butcherable + butcheringType: Spike + spawned: + - id: FoodMeat + amount: 5 + - type: Bloodstream + bloodReagent: Blood + - type: Vocal + sounds: + Male: MaleHuman + Female: FemaleHuman + Unsexed: MaleHuman + - type: Flammable + fireSpread: true + canResistFire: true + damage: + types: + Heat: 3 + - type: Temperature + heatDamageThreshold: 325 + coldDamageThreshold: 260 + currentTemperature: 310.15 + specificHeat: 42 + coldDamage: + types: + Cold: 0.1 + heatDamage: + types: + Heat: 1.5 + - type: MeleeWeapon + soundHit: + collection: Punch + angle: 30 + animation: WeaponArcFist + attackRate: 1 + damage: + types: + Blunt: 5 + - type: CMSurgeryTarget + - type: UserInterface + interfaces: + - key: enum.VoiceMaskUIKey.Key + type: VoiceMaskBoundUserInterface + - key: enum.HumanoidMarkingModifierKey.Key + type: HumanoidMarkingModifierBoundUserInterface + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - key: enum.HumanoidMarkingModifierKey.Key + type: HumanoidMarkingModifierBoundUserInterface + - key: enum.CMSurgeryUIKey.Key + type: CMSurgeryBui diff --git a/Resources/Prototypes/_CM14/Entities/Objects/Medical/surgery.yml b/Resources/Prototypes/_CM14/Entities/Objects/Medical/surgery.yml new file mode 100644 index 00000000000..effb10da9ff --- /dev/null +++ b/Resources/Prototypes/_CM14/Entities/Objects/Medical/surgery.yml @@ -0,0 +1,376 @@ +# Base +- type: entity + parent: BaseToolSurgery + id: CMBaseToolSurgery + abstract: true + name: retractor + description: Retracts stuff. + components: + - type: CMSurgeryTool + + + +# Retractor +- type: entity + parent: CMBaseToolSurgery + id: CMRetractor + name: retractor + description: Retracts stuff. + components: + - type: CMSurgeryTool + startSound: + path: /Audio/_CM14/Medical/Surgery/retractor1.ogg + endSound: + path: /Audio/_CM14/Medical/Surgery/retractor2.ogg + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/retractor.rsi + state: retractor + - type: Item + sprite: _CM14/Objects/Medical/Surgery/retractor.rsi + - type: CMRetractor + +# - Predator +- type: entity + parent: CMRetractor + id: CMRetractorPredator + name: opener + components: + - type: Sprite + state: predator_retractor + + + +# Hemostat +- type: entity + parent: CMBaseToolSurgery + id: CMHemostat + name: hemostat + description: You think you have seen this before. + components: + - type: CMSurgeryTool + endSound: + path: /Audio/_CM14/Medical/Surgery/hemostat1.ogg + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/hemostat.rsi + state: hemostat + - type: Item + sprite: _CM14/Objects/Medical/Surgery/hemostat.rsi + - type: CMHemostat + +# - Predator +- type: entity + parent: CMHemostat + id: CMHemostatPredator + name: pincher + components: + - type: Sprite + state: predator_hemostat + + + +# Cautery +- type: entity + parent: CMBaseToolSurgery + id: CMCautery + name: cautery + description: This stops bleeding. + components: + - type: CMSurgeryTool + startSound: + path: /Audio/_CM14/Medical/Surgery/cautery1.ogg + endSound: + path: /Audio/_CM14/Medical/Surgery/cautery2.ogg + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/cautery.rsi + state: cautery + - type: Item + sprite: _CM14/Objects/Medical/Surgery/cautery.rsi + - type: MeleeWeapon + damage: + types: + Heat: 5 + soundHit: + path: /Audio/Effects/lightburn.ogg + - type: CMCautery + +# - Predator +- type: entity + parent: CMCautery + id: CMCauteryPredator + name: cauterizer + components: + - type: Sprite + state: predator_cautery + + + +# Surgical drill +- type: entity + parent: CMBaseToolSurgery + id: CMSurgicalDrill + name: surgical drill + description: You can drill using this item. You dig? + components: + - type: CMSurgeryTool + startSound: + path: /Audio/_CM14/Medical/Surgery/saw.ogg + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/drill.rsi + state: drill + - type: Item + sprite: _CM14/Objects/Medical/Surgery/drill.rsi + - type: MeleeWeapon + damage: + types: + Piercing: 10 + soundHit: + path: /Audio/Items/drill_hit.ogg + - type: CMSurgicalDrill + +# - Bonedrill +- type: entity + parent: CMSurgicalDrill + id: CMSurgicalDrillPredator + name: bone drill + components: + - type: Sprite + state: predator_drill + + + +# Scalpel +- type: entity + parent: CMBaseToolSurgery + id: CMScalpel + name: scalpel + description: Cut, cut, and once more cut. + components: + - type: CMSurgeryTool + startSound: + path: /Audio/_CM14/Medical/Surgery/scalpel1.ogg + endSound: + path: /Audio/_CM14/Medical/Surgery/scalpel2.ogg + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/scalpel.rsi + state: scalpel + - type: Item + sprite: _CM14/Objects/Medical/Surgery/scalpel.rsi + - type: Sharp + butcherDelayModifier: 1.5 + - type: Utensil + types: + - Knife + - type: MeleeWeapon + wideAnimationRotation: 90 + swingLeft: true + attackRate: 1.5 + damage: + types: + Slash: 8 + soundHit: + path: /Audio/Weapons/bladeslice.ogg + - type: CMScalpel + +# - Predator +- type: entity + parent: CMScalpel + id: CMScalpelPredator + name: cutter + components: + - type: Sprite + state: predator_scalpel + +# - Laser +- type: entity + parent: CMScalpel + id: CMScalpelLaser + name: prototype laser scalpel + description: A scalpel augmented with a directed laser, for controlling bleeding as the incision is made. Also functions as a cautery. This one looks like an unreliable early model. + components: + - type: Sprite + layers: + - state: scalpel_laser + map: [ "enum.ToggleVisuals.Layer" ] + - type: MeleeWeapon + damage: + types: + Slash: 0 + - type: ItemToggle + predictable: false + - type: ItemToggleHot + - type: UseDelay + - type: ItemToggleMeleeWeapon + activatedDamage: + types: + Slash: 14 + - type: Appearance + - type: GenericVisualizer + visuals: + enum.ToggleVisuals.Toggled: + enum.ToggleVisuals.Layer: + True: {state: scalpel_laser_on} + False: {state: scalpel_laser} + +# - - Improved +- type: entity + parent: CMScalpelLaser + id: CMScalpelLaserImproved + name: laser scalpel + description: A scalpel augmented with a directed laser, for controlling bleeding as the incision is made. Also functions as a cautery. This one looks trustworthy, though it could be better. + components: + - type: Sprite + layers: + - state: scalpel_laser_2 + map: [ "enum.ToggleVisuals.Layer" ] + - type: GenericVisualizer + visuals: + enum.ToggleVisuals.Toggled: + enum.ToggleVisuals.Layer: + True: {state: scalpel_laser_2_on} + False: {state: scalpel_laser_2} + +# - - Advanced +- type: entity + parent: CMScalpelLaser + id: CMScalpelLaserAdvanced + name: advanced laser scalpel + description: A scalpel augmented with a directed laser, for controlling bleeding as the incision is made. Also functions as a cautery. This one looks to be the pinnacle of precision energy cutlery! + components: + - type: Sprite + layers: + - state: scalpel_laser_3 + map: [ "enum.ToggleVisuals.Layer" ] + - type: GenericVisualizer + visuals: + enum.ToggleVisuals.Toggled: + enum.ToggleVisuals.Layer: + True: {state: scalpel_laser_3_on} + False: {state: scalpel_laser_3} + +# - Pict System +- type: entity + parent: CMScalpel + id: CMScalpelPICT + name: PICT system + description: The Precision Incision and Cauterization Tool uses a high-frequency vibrating blade, laser cautery, and suction liquid control system to precisely sever target tissues while preventing all fluid leakage. Despite its troubled development program and horrifying price tag, outside of complex experimental surgeries it isn't any better than an ordinary twenty-dollar scalpel and can't create a full-length incision bloodlessly. + components: + - type: Sprite + state: pict_system + +# - Manager +- type: entity + parent: CMScalpel + id: CMScalpelManager + name: incision management system + description: A true extension of the surgeon's body, this marvel instantly and completely prepares an incision allowing for the immediate commencement of therapeutic steps. + components: + - type: Sprite + state: scalpel_manager + + + +# Circular saw +- type: entity + parent: CMBaseToolSurgery + id: CMCircularSaw + name: circular saw + description: For heavy-duty cutting. + components: + - type: CMSurgeryTool + startSound: + path: /Audio/_CM14/Medical/Surgery/saw.ogg + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/saw.rsi + state: saw + - type: Item + sprite: _CM14/Objects/Medical/Surgery/saw.rsi + - type: MeleeWeapon + damage: + groups: + Brute: 15 + soundHit: + path: /Audio/Items/drill_hit.ogg + - type: Tool + qualities: + - Sawing + speed: 1.5 + - type: CMBoneSaw + +# - Predator +- type: entity + parent: CMCircularSaw + id: CMCircularSawPredator + name: bone saw + components: + - type: Sprite + state: predator_bonesaw + + + +# Bone setter +- type: entity + parent: CMBaseToolSurgery + id: CMBonesetter + name: bone setter + components: # TODO CM14 + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/bonesetter.rsi + state: bonesetter + - type: Item + sprite: _CM14/Objects/Medical/Surgery/bonesetter.rsi + +# - Predator +- type: entity + parent: CMBonesetter + id: CMBonesetterPredator + name: bone placer + components: + - type: Sprite + state: predator_bonesetter + + + +# Pump +# Wound clamp +- type: entity + parent: CMBaseToolSurgery + id: CMWoundClamp + name: wound clamp + description: Used for clamping wounds after treatment. + components: # TODO CM14 + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/wound_clamp.rsi + state: wound_clamp + - type: Item + sprite: _CM14/Objects/Medical/Surgery/wound_clamp.rsi + + + +# Autopsy (actually just a laser scalpel) +- type: entity + parent: CMBaseToolSurgery + id: CMAutopsy + name: Weyland Brand Automatic Autopsy System(TM) + description: Putting the FUN back in Autopsy. This little gadget performs an entire autopsy of whatever strange life form you've found in about 30 seconds. + components: # TODO CM14 + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/scalpel.rsi + state: scalpel_laser_2 + - type: Item + sprite: _CM14/Objects/Medical/Surgery/scalpel.rsi + + + +# Bone Gel +- type: entity + parent: CMBaseToolSurgery + id: CMBoneGel + name: bone gel + components: + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/bone_gel.rsi + state: bone-gel + - type: Item + sprite: _CM14/Objects/Medical/Surgery/bone_gel.rsi + state: bone-gel + - type: CMBoneGel diff --git a/Resources/Prototypes/_CM14/Entities/Structures/Furniture/Tables/operating_table.yml b/Resources/Prototypes/_CM14/Entities/Structures/Furniture/Tables/operating_table.yml new file mode 100644 index 00000000000..58a9fe5339d --- /dev/null +++ b/Resources/Prototypes/_CM14/Entities/Structures/Furniture/Tables/operating_table.yml @@ -0,0 +1,14 @@ +- type: entity + parent: CMOperatingTable + id: CMOperatingTable + name: operating table + description: Used for advanced medical procedures. + components: + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/operating_table.rsi + state: base + noRot: true + - type: Icon + sprite: _CM14/Objects/Medical/Surgery/operating_table.rsi + state: base + - type: CMOperatingTable diff --git a/Resources/Prototypes/_CM14/Entities/Surgery/cm_surgeries.yml b/Resources/Prototypes/_CM14/Entities/Surgery/cm_surgeries.yml new file mode 100644 index 00000000000..c360b34f4d4 --- /dev/null +++ b/Resources/Prototypes/_CM14/Entities/Surgery/cm_surgeries.yml @@ -0,0 +1,39 @@ +- type: entity + id: CMSurgeryBase + noSpawn: true + +- type: entity + parent: CMSurgeryBase + id: CMSurgeryOpenIncision + name: Open Incision + components: + - type: CMSurgery + steps: + - CMSurgeryStepOpenIncisionScalpel + - CMSurgeryStepClampBleeders + - CMSurgeryStepRetractSkin + +- type: entity + parent: CMSurgeryBase + id: CMSurgeryCloseIncision + name: Close Incision + components: + - type: CMSurgery + priority: 1 + steps: + - CMSurgeryStepCloseBones + - CMSurgeryStepMendRibcage + - CMSurgeryStepCloseIncision + +- type: entity + parent: CMSurgeryBase + id: CMSurgeryOpenRibcage + name: Open Ribcage + components: + - type: CMSurgery + requirement: CMSurgeryOpenIncision + steps: + - CMSurgeryStepSawBones + - CMSurgeryStepPriseOpenBones + - type: CMSurgeryPartCondition + part: Torso diff --git a/Resources/Prototypes/_CM14/Entities/Surgery/cm_surgery_steps.yml b/Resources/Prototypes/_CM14/Entities/Surgery/cm_surgery_steps.yml new file mode 100644 index 00000000000..8a0a9415901 --- /dev/null +++ b/Resources/Prototypes/_CM14/Entities/Surgery/cm_surgery_steps.yml @@ -0,0 +1,126 @@ +- type: entity + id: CMSurgeryStepBase + noSpawn: true + components: + - type: CMSurgeryStep + +- type: entity + parent: CMSurgeryStepBase + id: CMSurgeryStepOpenIncisionScalpel + name: Cut with a scalpel + components: + - type: CMSurgeryStep + tool: + - type: CMScalpel + add: + - type: CMIncisionOpen + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/scalpel.rsi + state: scalpel + - type: CMSurgeryStepBleedEffect + amount: 5 + - type: CMSurgeryStepEmoteEffect + +- type: entity + parent: CMSurgeryStepBase + id: CMSurgeryStepClampBleeders + name: Clamp the bleeders + components: + - type: CMSurgeryStep + tool: + - type: CMHemostat + add: + - type: CMBleedersClamped + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/hemostat.rsi + state: hemostat + - type: CMSurgeryStepBleedEffect + amount: -5 + +- type: entity + parent: CMSurgeryStepBase + id: CMSurgeryStepRetractSkin + name: Retract the skin + components: + - type: CMSurgeryStep + tool: + - type: CMRetractor + add: + - type: CMSkinRetracted + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/retractor.rsi + state: retractor + +- type: entity + parent: CMSurgeryStepBase + id: CMSurgeryStepSawBones + name: Saw through bones + components: + - type: CMSurgeryStep + tool: + - type: CMBoneSaw + add: + - type: CMRibcageSawed + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/saw.rsi + state: saw + - type: CMSurgeryStepEmoteEffect + +- type: entity + parent: CMSurgeryStepBase + id: CMSurgeryStepPriseOpenBones + name: Prise the bones open + components: + - type: CMSurgeryStep + tool: + - type: CMRetractor + add: + - type: CMRibcageOpen + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/retractor.rsi + state: retractor + +- type: entity + parent: CMSurgeryStepBase + id: CMSurgeryStepCloseBones + name: Close bones + components: + - type: CMSurgeryStep + tool: + - type: CMRetractor + remove: + - type: CMRibcageOpen + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/retractor.rsi + state: retractor + +- type: entity + parent: CMSurgeryStepBase + id: CMSurgeryStepMendRibcage + name: Mend ribcage + components: + - type: CMSurgeryStep + tool: + - type: CMBoneGel + remove: + - type: CMRibcageSawed + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/bone_gel.rsi + state: bone-gel + +- type: entity + parent: CMSurgeryStepBase + id: CMSurgeryStepCloseIncision + name: Close incision + components: + - type: CMSurgeryStep + tool: + - type: CMCautery + remove: + - type: CMSkinRetracted + - type: CMBleedersClamped + - type: CMIncisionOpen + - type: Sprite + sprite: _CM14/Objects/Medical/Surgery/cautery.rsi + state: cautery + - type: CMSurgeryStepEmoteEffect diff --git a/Resources/Prototypes/_CM14/EntityLists/cm_surgery_list.yml b/Resources/Prototypes/_CM14/EntityLists/cm_surgery_list.yml new file mode 100644 index 00000000000..e3de7253a63 --- /dev/null +++ b/Resources/Prototypes/_CM14/EntityLists/cm_surgery_list.yml @@ -0,0 +1,11 @@ +- type: entityList + id: CMSurgeryTools + entities: + - CMScalpel + - CMHemostat + - CMRetractor + - CMCautery + - CMSurgicalDrill + - CMCircularSaw + - CMBonesetter + - CMBoneGel diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel.png new file mode 100644 index 00000000000..f66bf6cdf9e Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_0.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_0.png new file mode 100644 index 00000000000..4399c73304b Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_0.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_25.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_25.png new file mode 100644 index 00000000000..3d47302afd5 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_25.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_50.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_50.png new file mode 100644 index 00000000000..744b46f1ef8 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_50.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_75.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_75.png new file mode 100644 index 00000000000..4fbd689bb4c Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/bone-gel_75.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/meta.json new file mode 100644 index 00000000000..61ab52970b1 --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "bone-gel" + }, + { + "name": "predator_bone-gel" + }, + { + "name": "bone-gel_75" + }, + { + "name": "bone-gel_50" + }, + { + "name": "bone-gel_25" + }, + { + "name": "bone-gel_0" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/predator_bone-gel.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/predator_bone-gel.png new file mode 100644 index 00000000000..4eb66f5843a Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/bone_gel.rsi/predator_bone-gel.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/bonesetter.rsi/bonesetter.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/bonesetter.rsi/bonesetter.png new file mode 100644 index 00000000000..b876de0d28e Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/bonesetter.rsi/bonesetter.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/bonesetter.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/bonesetter.rsi/meta.json new file mode 100644 index 00000000000..227b276eda4 --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/bonesetter.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "bonesetter" + }, + { + "name": "predator_bonesetter" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/bonesetter.rsi/predator_bonesetter.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/bonesetter.rsi/predator_bonesetter.png new file mode 100644 index 00000000000..c77903ff77a Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/bonesetter.rsi/predator_bonesetter.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/cautery.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/cautery.png new file mode 100644 index 00000000000..63b804cc858 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/cautery.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/cautery_on.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/cautery_on.png new file mode 100644 index 00000000000..01d54671433 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/cautery_on.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/meta.json new file mode 100644 index 00000000000..d9ca4359f9f --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/meta.json @@ -0,0 +1,28 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "cautery" + }, + { + "name": "cautery_on", + "delays": [ + [ + 0.3, + 0.2, + 0.3, + 0.2 + ] + ] + }, + { + "name": "predator_cautery" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/predator_cautery.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/predator_cautery.png new file mode 100644 index 00000000000..9375b9ad03a Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/cautery.rsi/predator_cautery.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/drill.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/drill.png new file mode 100644 index 00000000000..7fb323dce96 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/drill.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/drill_on.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/drill_on.png new file mode 100644 index 00000000000..9d609d0033d Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/drill_on.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/meta.json new file mode 100644 index 00000000000..33c6dab625f --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/meta.json @@ -0,0 +1,35 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "drill" + }, + { + "name": "drill_on", + "delays": [ + [ + 0.1, + 0.1 + ] + ] + }, + { + "name": "predator_drill" + }, + { + "name": "predator_drill_on", + "delays": [ + [ + 0.1, + 0.1 + ] + ] + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/predator_drill.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/predator_drill.png new file mode 100644 index 00000000000..862343f2617 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/predator_drill.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/predator_drill_on.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/predator_drill_on.png new file mode 100644 index 00000000000..3543aa606e3 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/drill.rsi/predator_drill_on.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/drapes.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/drapes.png new file mode 100644 index 00000000000..f1d7a14fcdc Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/drapes.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/fixovein.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/fixovein.png new file mode 100644 index 00000000000..60f4424b12a Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/fixovein.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/meta.json new file mode 100644 index 00000000000..0931de34a5f --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/meta.json @@ -0,0 +1,23 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "fixovein" + }, + { + "name": "predator_fixovein" + }, + { + "name": "drapes" + }, + { + "name": "stabilizer_gel" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/predator_fixovein.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/predator_fixovein.png new file mode 100644 index 00000000000..e6d0bcb9fe2 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/predator_fixovein.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/stabilizer_gel.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/stabilizer_gel.png new file mode 100644 index 00000000000..06890da4898 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing.rsi/stabilizer_gel.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gel.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gel.png new file mode 100644 index 00000000000..20fb4332f12 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gel.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gun.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gun.png new file mode 100644 index 00000000000..9ed93296577 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gun.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gun_empty.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gun_empty.png new file mode 100644 index 00000000000..a92166fe24f Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gun_empty.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gun_on.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gun_on.png new file mode 100644 index 00000000000..3baa0776c0a Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/healing_gun_on.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/meta.json new file mode 100644 index 00000000000..2470d6eba10 --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/healing_gun.rsi/meta.json @@ -0,0 +1,36 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "healing_gun" + }, + { + "name": "healing_gun_empty" + }, + { + "name": "healing_gun_on", + "delays": [ + [ + 1.9, + 1.9, + 1.9, + 1.9, + 1.9, + 1.9, + 1.9, + 1.9, + 1.9 + ] + ] + }, + { + "name": "healing_gel" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/hemostat.rsi/hemostat.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/hemostat.rsi/hemostat.png new file mode 100644 index 00000000000..b782ed49cb8 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/hemostat.rsi/hemostat.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/hemostat.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/hemostat.rsi/meta.json new file mode 100644 index 00000000000..44f3bb9e5c4 --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/hemostat.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "hemostat" + }, + { + "name": "predator_hemostat" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/hemostat.rsi/predator_hemostat.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/hemostat.rsi/predator_hemostat.png new file mode 100644 index 00000000000..5924c5a9b57 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/hemostat.rsi/predator_hemostat.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/active.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/active.png new file mode 100644 index 00000000000..b29e1045e54 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/active.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/base.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/base.png new file mode 100644 index 00000000000..095660b8d7a Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/base.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/idle.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/idle.png new file mode 100644 index 00000000000..095660b8d7a Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/idle.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/meta.json new file mode 100644 index 00000000000..e0419e6b34e --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/operating_table.rsi/meta.json @@ -0,0 +1,28 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/f2cb08d6e44acb66becfc0bfea88b25c08c5102b/icons/obj/structures/machinery/surgery.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "base" + }, + { + "name": "idle" + }, + { + "name": "active", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/pump.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/pump.rsi/meta.json new file mode 100644 index 00000000000..36a78bbb36b --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/pump.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "pump" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/pump.rsi/pump.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/pump.rsi/pump.png new file mode 100644 index 00000000000..42b6d3667e6 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/pump.rsi/pump.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/retractor.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/retractor.rsi/meta.json new file mode 100644 index 00000000000..ebf8ec88d1c --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/retractor.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "retractor" + }, + { + "name": "predator_retractor" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/retractor.rsi/predator_retractor.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/retractor.rsi/predator_retractor.png new file mode 100644 index 00000000000..9a58bba518b Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/retractor.rsi/predator_retractor.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/retractor.rsi/retractor.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/retractor.rsi/retractor.png new file mode 100644 index 00000000000..333a286a4f1 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/retractor.rsi/retractor.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/meta.json new file mode 100644 index 00000000000..9f89c354820 --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/meta.json @@ -0,0 +1,27 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "saw" + }, + { + "name": "saw_on", + "delays": [ + [ + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "predator_bonesaw" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/predator_bonesaw.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/predator_bonesaw.png new file mode 100644 index 00000000000..94593dc10e6 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/predator_bonesaw.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/saw.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/saw.png new file mode 100644 index 00000000000..ea570c4d151 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/saw.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/saw_on.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/saw_on.png new file mode 100644 index 00000000000..707dc6e0342 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/saw.rsi/saw_on.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/meta.json new file mode 100644 index 00000000000..3066034524b --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/meta.json @@ -0,0 +1,73 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "scalpel" + }, + { + "name": "pict_system" + }, + { + "name": "scalpel_laser" + }, + { + "name": "scalpel_laser_on", + "delays": [ + [ + 0.1, + 0.1 + ] + ] + }, + { + "name": "scalpel_laser_2" + }, + { + "name": "scalpel_laser_2_on", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "scalpel_laser_3" + }, + { + "name": "scalpel_laser_3_on", + "delays": [ + [ + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "scalpel_manager" + }, + { + "name": "scalpel_manager_on", + "delays": [ + [ + 0.3, + 0.2, + 0.3, + 0.2 + ] + ] + }, + { + "name": "predator_scalpel" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/pict_system.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/pict_system.png new file mode 100644 index 00000000000..ee7d9b2887a Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/pict_system.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/predator_scalpel.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/predator_scalpel.png new file mode 100644 index 00000000000..f503fc0d1d3 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/predator_scalpel.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel.png new file mode 100644 index 00000000000..91c002a8f4a Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser.png new file mode 100644 index 00000000000..9b5d19c28b6 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_2.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_2.png new file mode 100644 index 00000000000..0384e1ab36f Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_2.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_2_on.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_2_on.png new file mode 100644 index 00000000000..4fc26472124 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_2_on.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_3.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_3.png new file mode 100644 index 00000000000..b7174c2edad Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_3.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_3_on.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_3_on.png new file mode 100644 index 00000000000..1a6383c05d6 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_3_on.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_on.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_on.png new file mode 100644 index 00000000000..75041112d5c Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_laser_on.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_manager.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_manager.png new file mode 100644 index 00000000000..af593050e77 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_manager.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_manager_on.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_manager_on.png new file mode 100644 index 00000000000..d04cb0ca29d Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/scalpel.rsi/scalpel_manager_on.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/wound_clamp.rsi/meta.json b/Resources/Textures/_CM14/Objects/Medical/Surgery/wound_clamp.rsi/meta.json new file mode 100644 index 00000000000..9fde86b0add --- /dev/null +++ b/Resources/Textures/_CM14/Objects/Medical/Surgery/wound_clamp.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/7917d83bac9cddd14c0ca0b457256b2683cc047f/icons/obj/items/surgery_tools.dmi", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "wound_clamp_on" + }, + { + "name": "wound_clamp" + } + ] +} diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/wound_clamp.rsi/wound_clamp.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/wound_clamp.rsi/wound_clamp.png new file mode 100644 index 00000000000..73012fe4779 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/wound_clamp.rsi/wound_clamp.png differ diff --git a/Resources/Textures/_CM14/Objects/Medical/Surgery/wound_clamp.rsi/wound_clamp_on.png b/Resources/Textures/_CM14/Objects/Medical/Surgery/wound_clamp.rsi/wound_clamp_on.png new file mode 100644 index 00000000000..067dd39c514 Binary files /dev/null and b/Resources/Textures/_CM14/Objects/Medical/Surgery/wound_clamp.rsi/wound_clamp_on.png differ diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index 3cce3cc91cb..9380ebe308e 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -698,6 +698,7 @@ public sealed partial class $CLASS$ : Shared$CLASS$ { True True True + True True True True