feat: простая хирургия
автор Грабля
This commit is contained in:
49
Content.Client/White/CheapSurgery/CheapSurgerySystem.cs
Normal file
49
Content.Client/White/CheapSurgery/CheapSurgerySystem.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using Content.Client.White.UserInterface.Controls;
|
||||||
|
using Content.Shared.White.CheapSurgery;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Client.White.CheapSurgery;
|
||||||
|
|
||||||
|
public sealed class CheapSurgerySystem : SharedCheapSurgerySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeNetworkEvent<OnSurgeryStarted>(OnStarted);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStarted(OnSurgeryStarted ev)
|
||||||
|
{
|
||||||
|
OpenRadialMenu(ev.OrganItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenRadialMenu(List<OrganItem> items)
|
||||||
|
{
|
||||||
|
if (items.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var radialContainer = new RadialContainer();
|
||||||
|
foreach (var organ in items)
|
||||||
|
{
|
||||||
|
var radialButton = radialContainer.AddButton(organ.Name, _sprite.Frame0(organ.Icon));
|
||||||
|
radialButton.Controller.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
radialContainer.Close();
|
||||||
|
if (organ.Children.Count > 0)
|
||||||
|
OpenRadialMenu(organ.Children);
|
||||||
|
else
|
||||||
|
SelectOrgan(GetEntity(organ.Uid));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
radialContainer.OpenCentered();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectOrgan(EntityUid uid)
|
||||||
|
{
|
||||||
|
var ev = new OnOrganSelected(GetNetEntity(uid));
|
||||||
|
RaiseNetworkEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ using Content.Client.Viewport;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Client.Animations;
|
using Robust.Client.Animations;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Client.ResourceManagement;
|
using Robust.Client.ResourceManagement;
|
||||||
@@ -31,10 +32,10 @@ public sealed class RadialContainerCommandTest : LocalizedCommands
|
|||||||
for (int i = 0; i < 24; i++)
|
for (int i = 0; i < 24; i++)
|
||||||
{
|
{
|
||||||
var testButton = radial.AddButton("Action " + i, "/Textures/Interface/emotions.svg.192dpi.png");
|
var testButton = radial.AddButton("Action " + i, "/Textures/Interface/emotions.svg.192dpi.png");
|
||||||
testButton.Controller.OnPressed += (_) => { Logger.Debug("Press gay"); };
|
testButton.Controller.OnPressed += _ => { Logger.Debug("Press gay"); };
|
||||||
}
|
}
|
||||||
|
|
||||||
radial.CloseButton.Controller.OnPressed += (_) =>
|
radial.CloseButton.Controller.OnPressed += _ =>
|
||||||
{
|
{
|
||||||
Logger.Debug("Close event for your own logic");
|
Logger.Debug("Close event for your own logic");
|
||||||
};
|
};
|
||||||
@@ -46,17 +47,16 @@ public sealed class RadialContainerCommandTest : LocalizedCommands
|
|||||||
[GenerateTypedNameReferences, Virtual]
|
[GenerateTypedNameReferences, Virtual]
|
||||||
public partial class RadialContainer : Control
|
public partial class RadialContainer : Control
|
||||||
{
|
{
|
||||||
private bool _isOpened = false;
|
private bool _isOpened;
|
||||||
|
|
||||||
private Vector2 _focusSize = new Vector2(64, 64);
|
private Vector2 _focusSize = new(64, 64);
|
||||||
private Vector2 _normalSize = new Vector2(50, 50);
|
private Vector2 _normalSize = new(50, 50);
|
||||||
|
|
||||||
private float _moveAniTime = 0.3f;
|
private IResourceCache _resourceCache;
|
||||||
private float _focusAniTime = 0.25f;
|
|
||||||
|
|
||||||
private int _maxButtons = 8;
|
private const int MaxButtons = 8;
|
||||||
|
|
||||||
private string _backgroundTexture = "/Textures/Interface/Default/SlotBackground.png";
|
private const string BackgroundTexture = "/Textures/Interface/Default/SlotBackground.png";
|
||||||
|
|
||||||
public const string MoveAnimationKey = "move";
|
public const string MoveAnimationKey = "move";
|
||||||
public const string InSizeAnimationKey = "insize";
|
public const string InSizeAnimationKey = "insize";
|
||||||
@@ -67,29 +67,24 @@ public partial class RadialContainer : Control
|
|||||||
get => _focusSize.Y;
|
get => _focusSize.Y;
|
||||||
set => _focusSize = new Vector2(value, value);
|
set => _focusSize = new Vector2(value, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float NormalSize
|
public float NormalSize
|
||||||
{
|
{
|
||||||
get => _normalSize.Y;
|
get => _normalSize.Y;
|
||||||
set => _normalSize = new Vector2(value, value);
|
set => _normalSize = new Vector2(value, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float MoveAnimationTime
|
public float MoveAnimationTime { get; set; } = 0.3f;
|
||||||
{
|
|
||||||
get => _moveAniTime;
|
public float FocusAnimationTime { get; set; } = 0.25f;
|
||||||
set => _moveAniTime = value;
|
|
||||||
}
|
|
||||||
public float FocusAnimationTime
|
|
||||||
{
|
|
||||||
get => _focusAniTime;
|
|
||||||
set => _focusAniTime = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsAction = true;
|
public bool IsAction = true;
|
||||||
|
|
||||||
public RadialContainer() : base()
|
public RadialContainer()
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
_resourceCache = IoCManager.Resolve<IResourceCache>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Open(Vector2 position)
|
public void Open(Vector2 position)
|
||||||
@@ -103,9 +98,10 @@ public partial class RadialContainer : Control
|
|||||||
{
|
{
|
||||||
AddToRoot();
|
AddToRoot();
|
||||||
if (Parent != null)
|
if (Parent != null)
|
||||||
LayoutContainer.SetPosition(this, (Parent.Size/2) - (this.Size/2));
|
LayoutContainer.SetPosition(this, Parent.Size / 2 - Size / 2);
|
||||||
else
|
else
|
||||||
LayoutContainer.SetPosition(this, (UserInterfaceManager.MainViewport.Size/2) - (this.Size/2));
|
LayoutContainer.SetPosition(this, UserInterfaceManager.MainViewport.Size / 2 - Size / 2);
|
||||||
|
|
||||||
UpdateButtons();
|
UpdateButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +110,7 @@ public partial class RadialContainer : Control
|
|||||||
if (UserInterfaceManager.ActiveScreen == null)
|
if (UserInterfaceManager.ActiveScreen == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var ent = IoCManager.Resolve<IPlayerManager>().LocalPlayer?.ControlledEntity;
|
var ent = IoCManager.Resolve<IPlayerManager>().LocalSession?.AttachedEntity;
|
||||||
if (ent == null)
|
if (ent == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -122,7 +118,11 @@ public partial class RadialContainer : Control
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
AddToRoot();
|
AddToRoot();
|
||||||
LayoutContainer.SetPosition(this, (IoCManager.Resolve<IEyeManager>().MapToScreen(xform.MapPosition).Position * 1.5f));
|
var position = IoCManager.Resolve<TransformSystem>().GetMapCoordinates(xform);
|
||||||
|
|
||||||
|
LayoutContainer.SetPosition(this,
|
||||||
|
IoCManager.Resolve<IEyeManager>().MapToScreen(position).Position * 1.5f);
|
||||||
|
|
||||||
UpdateButtons();
|
UpdateButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,9 +139,21 @@ public partial class RadialContainer : Control
|
|||||||
{
|
{
|
||||||
var button = new RadialButton();
|
var button = new RadialButton();
|
||||||
button.Content = action;
|
button.Content = action;
|
||||||
button.Controller.TextureNormal = IoCManager.Resolve<IResourceCache>().GetTexture(_backgroundTexture);
|
button.Controller.TextureNormal = _resourceCache.GetTexture(BackgroundTexture);
|
||||||
if (texture != null)
|
if (texture != null)
|
||||||
button.BackgroundTexture.Texture = IoCManager.Resolve<IResourceCache>().GetTexture(texture);
|
button.BackgroundTexture.Texture = _resourceCache.GetTexture(texture);
|
||||||
|
|
||||||
|
Layout.AddChild(button);
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RadialButton AddButton(string action, Texture texture)
|
||||||
|
{
|
||||||
|
var button = new RadialButton();
|
||||||
|
button.Content = action;
|
||||||
|
button.Controller.TextureNormal = _resourceCache.GetTexture(BackgroundTexture);
|
||||||
|
button.BackgroundTexture.Texture = texture;
|
||||||
Layout.AddChild(button);
|
Layout.AddChild(button);
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
@@ -151,6 +163,7 @@ public partial class RadialContainer : Control
|
|||||||
{
|
{
|
||||||
if (_isOpened)
|
if (_isOpened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UserInterfaceManager.WindowRoot.AddChild(this);
|
UserInterfaceManager.WindowRoot.AddChild(this);
|
||||||
_isOpened = !_isOpened;
|
_isOpened = !_isOpened;
|
||||||
}
|
}
|
||||||
@@ -159,31 +172,33 @@ public partial class RadialContainer : Control
|
|||||||
{
|
{
|
||||||
Visible = true;
|
Visible = true;
|
||||||
|
|
||||||
var angleDegrees = 360/Layout.ChildCount;
|
var angleDegrees = 360 / Layout.ChildCount;
|
||||||
var stepAngle = -angleDegrees + -90;
|
var stepAngle = -angleDegrees + -90;
|
||||||
var distance = FocusSize * 1.2;
|
var distance = FocusSize * 1.2;
|
||||||
if (Layout.Children.Count() > _maxButtons)
|
if (Layout.Children.Count() > MaxButtons)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (Layout.Children.Count() - _maxButtons); i++)
|
for (int i = 0; i < (Layout.Children.Count() - MaxButtons); i++)
|
||||||
{
|
{
|
||||||
distance += (NormalSize/3);
|
distance += (NormalSize / 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var child in Layout.Children)
|
foreach (var child in Layout.Children)
|
||||||
{
|
{
|
||||||
var button = (RadialButton)child;
|
var button = (RadialButton) child;
|
||||||
button.ButtonSize = _normalSize;
|
button.ButtonSize = _normalSize;
|
||||||
stepAngle += angleDegrees;
|
stepAngle += angleDegrees;
|
||||||
var pos = GetPointFromPolar(stepAngle, distance);
|
var pos = GetPointFromPolar(stepAngle, distance);
|
||||||
PlayRadialAnimation(button, pos, MoveAnimationKey);
|
PlayRadialAnimation(button, pos, MoveAnimationKey);
|
||||||
|
|
||||||
button.Controller.OnMouseEntered += (_) =>
|
button.Controller.OnMouseEntered += _ =>
|
||||||
{
|
{
|
||||||
PlaySizeAnimation(button, _focusSize, OutSizeAnimationKey, InSizeAnimationKey);
|
PlaySizeAnimation(button, _focusSize, OutSizeAnimationKey, InSizeAnimationKey);
|
||||||
ActionLabel.Text = button.Content ?? string.Empty;
|
ActionLabel.Text = button.Content ?? string.Empty;
|
||||||
ActionLabel.Visible = IsAction;
|
ActionLabel.Visible = IsAction;
|
||||||
};
|
};
|
||||||
button.Controller.OnMouseExited += (_) =>
|
|
||||||
|
button.Controller.OnMouseExited += _ =>
|
||||||
{
|
{
|
||||||
PlaySizeAnimation(button, _normalSize, InSizeAnimationKey, OutSizeAnimationKey);
|
PlaySizeAnimation(button, _normalSize, InSizeAnimationKey, OutSizeAnimationKey);
|
||||||
ActionLabel.Visible = false;
|
ActionLabel.Visible = false;
|
||||||
@@ -191,18 +206,20 @@ public partial class RadialContainer : Control
|
|||||||
}
|
}
|
||||||
|
|
||||||
CloseButton.ButtonSize = _normalSize;
|
CloseButton.ButtonSize = _normalSize;
|
||||||
CloseButton.Controller.OnMouseEntered += (_) =>
|
CloseButton.Controller.OnMouseEntered += _ =>
|
||||||
{
|
{
|
||||||
PlaySizeAnimation(CloseButton, _focusSize, OutSizeAnimationKey, InSizeAnimationKey);
|
PlaySizeAnimation(CloseButton, _focusSize, OutSizeAnimationKey, InSizeAnimationKey);
|
||||||
ActionLabel.Text = CloseButton.Content ?? string.Empty;
|
ActionLabel.Text = CloseButton.Content ?? string.Empty;
|
||||||
ActionLabel.Visible = true;
|
ActionLabel.Visible = true;
|
||||||
};
|
};
|
||||||
CloseButton.Controller.OnMouseExited += (_) =>
|
|
||||||
|
CloseButton.Controller.OnMouseExited += _ =>
|
||||||
{
|
{
|
||||||
PlaySizeAnimation(CloseButton, _normalSize, InSizeAnimationKey, OutSizeAnimationKey);
|
PlaySizeAnimation(CloseButton, _normalSize, InSizeAnimationKey, OutSizeAnimationKey);
|
||||||
ActionLabel.Visible = false;
|
ActionLabel.Visible = false;
|
||||||
};
|
};
|
||||||
CloseButton.Controller.OnPressed += (_) =>
|
|
||||||
|
CloseButton.Controller.OnPressed += _ =>
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
};
|
};
|
||||||
@@ -212,7 +229,7 @@ public partial class RadialContainer : Control
|
|||||||
{
|
{
|
||||||
var anim = new Animation
|
var anim = new Animation
|
||||||
{
|
{
|
||||||
Length = TimeSpan.FromMilliseconds(_moveAniTime * 1000),
|
Length = TimeSpan.FromMilliseconds(MoveAnimationTime * 1000),
|
||||||
AnimationTracks =
|
AnimationTracks =
|
||||||
{
|
{
|
||||||
new AnimationTrackControlProperty
|
new AnimationTrackControlProperty
|
||||||
@@ -221,12 +238,13 @@ public partial class RadialContainer : Control
|
|||||||
InterpolationMode = AnimationInterpolationMode.Linear,
|
InterpolationMode = AnimationInterpolationMode.Linear,
|
||||||
KeyFrames =
|
KeyFrames =
|
||||||
{
|
{
|
||||||
new AnimationTrackProperty.KeyFrame(new Vector2(0,0), 0f),
|
new AnimationTrackProperty.KeyFrame(new Vector2(0, 0), 0f),
|
||||||
new AnimationTrackProperty.KeyFrame(pos, _moveAniTime)
|
new AnimationTrackProperty.KeyFrame(pos, MoveAnimationTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!button.HasRunningAnimation(playKey))
|
if (!button.HasRunningAnimation(playKey))
|
||||||
button.PlayAnimation(anim, playKey);
|
button.PlayAnimation(anim, playKey);
|
||||||
}
|
}
|
||||||
@@ -235,7 +253,7 @@ public partial class RadialContainer : Control
|
|||||||
{
|
{
|
||||||
var anim = new Animation
|
var anim = new Animation
|
||||||
{
|
{
|
||||||
Length = TimeSpan.FromMilliseconds(_focusAniTime * 1000),
|
Length = TimeSpan.FromMilliseconds(FocusAnimationTime * 1000),
|
||||||
AnimationTracks =
|
AnimationTracks =
|
||||||
{
|
{
|
||||||
new AnimationTrackControlProperty
|
new AnimationTrackControlProperty
|
||||||
@@ -245,7 +263,7 @@ public partial class RadialContainer : Control
|
|||||||
KeyFrames =
|
KeyFrames =
|
||||||
{
|
{
|
||||||
new AnimationTrackProperty.KeyFrame(button.Size, 0f),
|
new AnimationTrackProperty.KeyFrame(button.Size, 0f),
|
||||||
new AnimationTrackProperty.KeyFrame(size, _focusAniTime)
|
new AnimationTrackProperty.KeyFrame(size, FocusAnimationTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,6 +271,7 @@ public partial class RadialContainer : Control
|
|||||||
|
|
||||||
if (stopKey != null && button.HasRunningAnimation(stopKey))
|
if (stopKey != null && button.HasRunningAnimation(stopKey))
|
||||||
button.StopAnimation(stopKey);
|
button.StopAnimation(stopKey);
|
||||||
|
|
||||||
if (!button.HasRunningAnimation(playKey))
|
if (!button.HasRunningAnimation(playKey))
|
||||||
button.PlayAnimation(anim, playKey);
|
button.PlayAnimation(anim, playKey);
|
||||||
}
|
}
|
||||||
@@ -263,11 +282,12 @@ public partial class RadialContainer : Control
|
|||||||
|
|
||||||
foreach (var child in Layout.Children)
|
foreach (var child in Layout.Children)
|
||||||
{
|
{
|
||||||
var button = (RadialButton)child;
|
var button = (RadialButton) child;
|
||||||
LayoutContainer.SetPosition(child, button.Offset - (button.Size/2));
|
LayoutContainer.SetPosition(child, button.Offset - (button.Size / 2));
|
||||||
}
|
}
|
||||||
LayoutContainer.SetPosition(CloseButton, CloseButton.Offset - (CloseButton.Size/2));
|
|
||||||
LayoutContainer.SetPosition(ActionBox, new Vector2(0 - (ActionLabel.Size.X), FocusSize*1.5f));
|
LayoutContainer.SetPosition(CloseButton, CloseButton.Offset - (CloseButton.Size / 2));
|
||||||
|
LayoutContainer.SetPosition(ActionBox, new Vector2(0 - (ActionLabel.Size.X), FocusSize * 1.5f));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Vector2 GetPointFromPolar(double angleDegrees, double distance)
|
private static Vector2 GetPointFromPolar(double angleDegrees, double distance)
|
||||||
@@ -277,6 +297,6 @@ public partial class RadialContainer : Control
|
|||||||
var x = distance * Math.Cos(angleRadians);
|
var x = distance * Math.Cos(angleRadians);
|
||||||
var y = distance * Math.Sin(angleRadians);
|
var y = distance * Math.Sin(angleRadians);
|
||||||
|
|
||||||
return new Vector2((int)Math.Round(x), (int)Math.Round(y));
|
return new Vector2((int) Math.Round(x), (int) Math.Round(y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
122
Content.Server/White/CheapSurgery/CheapSurgerySystem.cs
Normal file
122
Content.Server/White/CheapSurgery/CheapSurgerySystem.cs
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
using Content.Server.Body.Systems;
|
||||||
|
using Content.Server.Construction;
|
||||||
|
using Content.Server.Construction.Components;
|
||||||
|
using Content.Server.Kitchen.Components;
|
||||||
|
using Content.Shared.Body.Components;
|
||||||
|
using Content.Shared.Body.Organ;
|
||||||
|
using Content.Shared.Body.Part;
|
||||||
|
using Content.Shared.Humanoid;
|
||||||
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Mobs.Systems;
|
||||||
|
using Content.Shared.White.CheapSurgery;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.White.CheapSurgery;
|
||||||
|
|
||||||
|
public sealed class CheapSurgerySystem : SharedCheapSurgerySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly BodySystem _body = default!;
|
||||||
|
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||||
|
[Dependency] private readonly ConstructionSystem _construction = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<BodyComponent, InteractUsingEvent>(OnUsing);
|
||||||
|
SubscribeNetworkEvent<OnOrganSelected>(OnSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelected(OnOrganSelected ev)
|
||||||
|
{
|
||||||
|
var entity = GetEntity(ev.Uid);
|
||||||
|
|
||||||
|
if (TryComp<BodyPartComponent>(entity, out var partComponent) && partComponent.Body != null)
|
||||||
|
{
|
||||||
|
StartDrop(partComponent.Body.Value, entity);
|
||||||
|
}
|
||||||
|
else if (TryComp<OrganComponent>(entity, out var organComponent) && organComponent.Body != null)
|
||||||
|
{
|
||||||
|
StartDrop(organComponent.Body.Value, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUsing(EntityUid uid, BodyComponent component, InteractUsingEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled || !TryComp<SharpComponent>(args.Used, out _) || _mobState.IsAlive(uid)
|
||||||
|
|| TryComp<ActiveSurgeryComponent>(uid, out _))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!TryComp<HumanoidAppearanceComponent>(uid, out _))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var organs = GenList(uid);
|
||||||
|
|
||||||
|
var ev = new OnSurgeryStarted(GetNetEntity(uid), organs);
|
||||||
|
RaiseNetworkEvent(ev, args.User);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OrganItem GetOrganItem(EntityUid part, List<OrganItem>? child = null)
|
||||||
|
{
|
||||||
|
var metadata = MetaData(part);
|
||||||
|
|
||||||
|
var organ = new OrganItem(metadata.EntityName, GetNetEntity(part),
|
||||||
|
new SpriteSpecifier.EntityPrototype(metadata.EntityPrototype!.ID));
|
||||||
|
|
||||||
|
if (child != null)
|
||||||
|
organ.Children = child;
|
||||||
|
|
||||||
|
return organ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<OrganItem> GenList(EntityUid uid)
|
||||||
|
{
|
||||||
|
var organs = new List<OrganItem>();
|
||||||
|
|
||||||
|
if (TryComp<BodyComponent>(uid, out var bodyComponent))
|
||||||
|
{
|
||||||
|
foreach (var (part, _) in _body.GetBodyChildren(uid, bodyComponent))
|
||||||
|
{
|
||||||
|
if (part == uid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var child = GenList(part);
|
||||||
|
if (child.Count > 0)
|
||||||
|
organs.Add(GetOrganItem(part, child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TryComp<BodyPartComponent>(uid, out var partComponent))
|
||||||
|
{
|
||||||
|
foreach (var (part, _) in _body.GetBodyPartChildren(uid, partComponent))
|
||||||
|
{
|
||||||
|
if (part == uid)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var child = GenList(part);
|
||||||
|
if (child.Count > 0)
|
||||||
|
organs.Add(GetOrganItem(part, child));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (part, _) in _body.GetPartOrgans(uid, partComponent))
|
||||||
|
{
|
||||||
|
organs.Add(GetOrganItem(part, GenList(part)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return organs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StartDrop(EntityUid uid, EntityUid organUid, EntityUid? user = null, BodyComponent? component = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref component))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
EnsureComp<ActiveSurgeryComponent>(uid).OrganUid = organUid;
|
||||||
|
|
||||||
|
var construct = EnsureComp<ConstructionComponent>(uid);
|
||||||
|
return _construction.ChangeGraph(uid, user, "BodySurgery", "head", true, construct);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
Content.Server/White/Construction/Completions/Surgery.cs
Normal file
28
Content.Server/White/Construction/Completions/Surgery.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using Content.Server.Body.Systems;
|
||||||
|
using Content.Shared.Body.Organ;
|
||||||
|
using Content.Shared.Construction;
|
||||||
|
using Content.Shared.White.CheapSurgery;
|
||||||
|
|
||||||
|
namespace Content.Server.White.Construction.Completions;
|
||||||
|
|
||||||
|
public sealed partial class Surgery : IGraphAction
|
||||||
|
{
|
||||||
|
private ISawmill _sawmill = default!;
|
||||||
|
|
||||||
|
public void PerformAction(EntityUid uid, EntityUid? userUid, IEntityManager entityManager)
|
||||||
|
{
|
||||||
|
_sawmill = Logger.GetSawmill("Surgery");
|
||||||
|
var bodySystem = entityManager.EntitySysManager.GetEntitySystem<BodySystem>();
|
||||||
|
|
||||||
|
if (!entityManager.TryGetComponent<ActiveSurgeryComponent>(uid, out var surgeryComponent))
|
||||||
|
{
|
||||||
|
_sawmill.Warning($"Entity {uid} does not have a ActiveSurgery Component");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entityManager.TryGetComponent<OrganComponent>(surgeryComponent.OrganUid, out var organComponent))
|
||||||
|
bodySystem.RemoveOrgan(surgeryComponent.OrganUid, organComponent);
|
||||||
|
|
||||||
|
entityManager.RemoveComponent<ActiveSurgeryComponent>(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Content.Shared.White.CheapSurgery;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed partial class ActiveSurgeryComponent : Component
|
||||||
|
{
|
||||||
|
[ViewVariables] public EntityUid OrganUid = EntityUid.Invalid;
|
||||||
|
}
|
||||||
44
Content.Shared/White/CheapSurgery/OnSurgeryStarted.cs
Normal file
44
Content.Shared/White/CheapSurgery/OnSurgeryStarted.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Shared.White.CheapSurgery;
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class OnSurgeryStarted : EntityEventArgs
|
||||||
|
{
|
||||||
|
public NetEntity Target;
|
||||||
|
public List<OrganItem> OrganItems;
|
||||||
|
|
||||||
|
public OnSurgeryStarted(NetEntity target, List<OrganItem> organItems)
|
||||||
|
{
|
||||||
|
Target = target;
|
||||||
|
OrganItems = organItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class OrganItem
|
||||||
|
{
|
||||||
|
public string Name;
|
||||||
|
public NetEntity Uid;
|
||||||
|
public SpriteSpecifier Icon;
|
||||||
|
public List<OrganItem> Children = new();
|
||||||
|
|
||||||
|
public OrganItem(string name, NetEntity uid, SpriteSpecifier icon)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Uid = uid;
|
||||||
|
Icon = icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class OnOrganSelected : EntityEventArgs
|
||||||
|
{
|
||||||
|
public NetEntity Uid;
|
||||||
|
|
||||||
|
public OnOrganSelected(NetEntity uid)
|
||||||
|
{
|
||||||
|
Uid = uid;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Content.Shared.White.CheapSurgery;
|
||||||
|
|
||||||
|
public abstract class SharedCheapSurgerySystem : EntitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
name: scalpel
|
name: scalpel
|
||||||
id: Scalpel
|
id: Scalpel
|
||||||
parent: BaseToolSurgery
|
parent: [BaseToolSurgery, BaseKnife]
|
||||||
description: A surgical tool used to make incisions into flesh.
|
description: A surgical tool used to make incisions into flesh.
|
||||||
components:
|
components:
|
||||||
- type: Sharp
|
- type: Sharp
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
- type: constructionGraph
|
||||||
|
id: BodySurgery
|
||||||
|
start: head
|
||||||
|
graph:
|
||||||
|
- node: head
|
||||||
|
edges:
|
||||||
|
- to: drop
|
||||||
|
steps:
|
||||||
|
- tool: Sawing
|
||||||
|
doAfter: 1
|
||||||
|
|
||||||
|
- tool: Slicing
|
||||||
|
doAfter: 1
|
||||||
|
|
||||||
|
- tool: Sawing
|
||||||
|
doAfter: 1
|
||||||
|
|
||||||
|
|
||||||
|
- node: drop
|
||||||
|
actions:
|
||||||
|
- !type:Surgery
|
||||||
Reference in New Issue
Block a user