Add 'Scan DNA' function to medical scanner (#1783)
* Add art assets for cloning * Added a 'Scan DNA' button to the medical scanner * Made the UI update unconditional for the medical scanner until checks for power changes are in place * Update Medical scanner to reflect powered status and fix #1774 * added a 'scan dna' button the the medical scanner that will add the contained bodies Uid to a list in CloningSystem, fixed an issue with the menu not populating if the scanner starts in an unpowered state * Add disabling logic to 'Scan DNA' button on medical scanner * Removed un-used libraries * changed scan dna button to Scan and Save DNA
@@ -22,6 +22,7 @@ namespace Content.Client.GameObjects.Components.MedicalScanner
|
|||||||
Title = Owner.Owner.Name,
|
Title = Owner.Owner.Name,
|
||||||
};
|
};
|
||||||
_window.OnClose += Close;
|
_window.OnClose += Close;
|
||||||
|
_window.ScanButton.OnPressed += _ => SendMessage(new UiButtonPressedMessage(UiButton.ScanDNA));
|
||||||
_window.OpenCentered();
|
_window.OpenCentered();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,18 +12,38 @@ namespace Content.Client.GameObjects.Components.MedicalScanner
|
|||||||
{
|
{
|
||||||
public class MedicalScannerWindow : SS14Window
|
public class MedicalScannerWindow : SS14Window
|
||||||
{
|
{
|
||||||
|
public readonly Button ScanButton;
|
||||||
|
private readonly Label _diagnostics;
|
||||||
protected override Vector2? CustomSize => (485, 90);
|
protected override Vector2? CustomSize => (485, 90);
|
||||||
|
|
||||||
|
public MedicalScannerWindow()
|
||||||
|
{
|
||||||
|
Contents.AddChild(new VBoxContainer
|
||||||
|
{
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
(ScanButton = new Button
|
||||||
|
{
|
||||||
|
Text = "Scan and Save DNA"
|
||||||
|
}),
|
||||||
|
(_diagnostics = new Label
|
||||||
|
{
|
||||||
|
Text = ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void Populate(MedicalScannerBoundUserInterfaceState state)
|
public void Populate(MedicalScannerBoundUserInterfaceState state)
|
||||||
{
|
{
|
||||||
Contents.RemoveAllChildren();
|
|
||||||
var text = new StringBuilder();
|
var text = new StringBuilder();
|
||||||
|
|
||||||
if (!state.Entity.HasValue ||
|
if (!state.Entity.HasValue ||
|
||||||
!state.HasDamage() ||
|
!state.HasDamage() ||
|
||||||
!IoCManager.Resolve<IEntityManager>().TryGetEntity(state.Entity.Value, out var entity))
|
!IoCManager.Resolve<IEntityManager>().TryGetEntity(state.Entity.Value, out var entity))
|
||||||
{
|
{
|
||||||
text.Append(Loc.GetString("No patient data."));
|
_diagnostics.Text = Loc.GetString("No patient data.");
|
||||||
|
ScanButton.Disabled = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -45,9 +65,10 @@ namespace Content.Client.GameObjects.Components.MedicalScanner
|
|||||||
|
|
||||||
text.Append("\n");
|
text.Append("\n");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Contents.AddChild(new Label() {Text = text.ToString()});
|
_diagnostics.Text = text.ToString();
|
||||||
|
ScanButton.Disabled = state.IsScanned;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
using Content.Server.GameObjects.Components.Power.ApcNetComponents;
|
||||||
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Shared.GameObjects.Components.Damage;
|
using Content.Shared.GameObjects.Components.Damage;
|
||||||
using Content.Shared.GameObjects.Components.Medical;
|
using Content.Shared.GameObjects.Components.Medical;
|
||||||
using Content.Shared.GameObjects.EntitySystems;
|
using Content.Shared.GameObjects.EntitySystems;
|
||||||
@@ -38,9 +39,14 @@ namespace Content.Server.GameObjects.Components.Medical
|
|||||||
_appearance = Owner.GetComponent<AppearanceComponent>();
|
_appearance = Owner.GetComponent<AppearanceComponent>();
|
||||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||||
.GetBoundUserInterface(MedicalScannerUiKey.Key);
|
.GetBoundUserInterface(MedicalScannerUiKey.Key);
|
||||||
|
_userInterface.OnReceiveMessage += OnUiReceiveMessage;
|
||||||
_bodyContainer = ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-bodyContainer", Owner);
|
_bodyContainer = ContainerManagerComponent.Ensure<ContainerSlot>($"{Name}-bodyContainer", Owner);
|
||||||
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
_powerReceiver = Owner.GetComponent<PowerReceiverComponent>();
|
||||||
|
|
||||||
|
//TODO: write this so that it checks for a change in power events and acts accordingly.
|
||||||
|
var newState = GetUserInterfaceState();
|
||||||
|
_userInterface.SetState(newState);
|
||||||
|
|
||||||
UpdateUserInterface();
|
UpdateUserInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +54,8 @@ namespace Content.Server.GameObjects.Components.Medical
|
|||||||
new MedicalScannerBoundUserInterfaceState(
|
new MedicalScannerBoundUserInterfaceState(
|
||||||
null,
|
null,
|
||||||
new Dictionary<DamageClass, int>(),
|
new Dictionary<DamageClass, int>(),
|
||||||
new Dictionary<DamageType, int>());
|
new Dictionary<DamageType, int>(),
|
||||||
|
false);
|
||||||
|
|
||||||
private MedicalScannerBoundUserInterfaceState GetUserInterfaceState()
|
private MedicalScannerBoundUserInterfaceState GetUserInterfaceState()
|
||||||
{
|
{
|
||||||
@@ -68,7 +75,7 @@ namespace Content.Server.GameObjects.Components.Medical
|
|||||||
var classes = new Dictionary<DamageClass, int>(damageable.DamageClasses);
|
var classes = new Dictionary<DamageClass, int>(damageable.DamageClasses);
|
||||||
var types = new Dictionary<DamageType, int>(damageable.DamageTypes);
|
var types = new Dictionary<DamageType, int>(damageable.DamageTypes);
|
||||||
|
|
||||||
return new MedicalScannerBoundUserInterfaceState(body.Uid, classes, types);
|
return new MedicalScannerBoundUserInterfaceState(body.Uid, classes, types, CloningSystem.HasUid(body.Uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateUserInterface()
|
private void UpdateUserInterface()
|
||||||
@@ -92,12 +99,18 @@ namespace Content.Server.GameObjects.Components.Medical
|
|||||||
default: throw new ArgumentException(nameof(damageState));
|
default: throw new ArgumentException(nameof(damageState));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MedicalScannerStatus GetStatus()
|
private MedicalScannerStatus GetStatus()
|
||||||
{
|
{
|
||||||
var body = _bodyContainer.ContainedEntity;
|
if (Powered)
|
||||||
return body == null
|
{
|
||||||
? MedicalScannerStatus.Open
|
var body = _bodyContainer.ContainedEntity;
|
||||||
: GetStatusFromDamageState(body.GetComponent<IDamageableComponent>().CurrentDamageState);
|
return body == null
|
||||||
|
? MedicalScannerStatus.Open
|
||||||
|
: GetStatusFromDamageState(body.GetComponent<IDamageableComponent>().CurrentDamageState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MedicalScannerStatus.Off;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAppearance()
|
private void UpdateAppearance()
|
||||||
@@ -178,14 +191,28 @@ namespace Content.Server.GameObjects.Components.Medical
|
|||||||
|
|
||||||
public void Update(float frameTime)
|
public void Update(float frameTime)
|
||||||
{
|
{
|
||||||
if (_bodyContainer.ContainedEntity == null)
|
|
||||||
{
|
|
||||||
// There's no need to update if there's no one inside
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateUserInterface();
|
UpdateUserInterface();
|
||||||
UpdateAppearance();
|
UpdateAppearance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnUiReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
||||||
|
{
|
||||||
|
if (!(obj.Message is UiButtonPressedMessage message))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (message.Button)
|
||||||
|
{
|
||||||
|
case UiButton.ScanDNA:
|
||||||
|
if (_bodyContainer.ContainedEntity != null)
|
||||||
|
{
|
||||||
|
CloningSystem.AddToScannedUids(_bodyContainer.ContainedEntity.Uid);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
Content.Server/GameObjects/EntitySystems/CloningSystem.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects.Systems;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.EntitySystems
|
||||||
|
{
|
||||||
|
internal sealed class CloningSystem : EntitySystem
|
||||||
|
{
|
||||||
|
public static List<EntityUid> scannedUids = new List<EntityUid>();
|
||||||
|
|
||||||
|
public static void AddToScannedUids(EntityUid uid)
|
||||||
|
{
|
||||||
|
if (!scannedUids.Contains(uid))
|
||||||
|
{
|
||||||
|
scannedUids.Add(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasUid(EntityUid uid)
|
||||||
|
{
|
||||||
|
return scannedUids.Contains(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
internal sealed class MedicalScannerSystem : EntitySystem
|
internal sealed class MedicalScannerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
foreach (var comp in ComponentManager.EntityQuery<MedicalScannerComponent>())
|
foreach (var comp in ComponentManager.EntityQuery<MedicalScannerComponent>())
|
||||||
|
|||||||
@@ -17,15 +17,18 @@ namespace Content.Shared.GameObjects.Components.Medical
|
|||||||
public readonly EntityUid? Entity;
|
public readonly EntityUid? Entity;
|
||||||
public readonly Dictionary<DamageClass, int> DamageClasses;
|
public readonly Dictionary<DamageClass, int> DamageClasses;
|
||||||
public readonly Dictionary<DamageType, int> DamageTypes;
|
public readonly Dictionary<DamageType, int> DamageTypes;
|
||||||
|
public readonly bool IsScanned;
|
||||||
|
|
||||||
public MedicalScannerBoundUserInterfaceState(
|
public MedicalScannerBoundUserInterfaceState(
|
||||||
EntityUid? entity,
|
EntityUid? entity,
|
||||||
Dictionary<DamageClass, int> damageClasses,
|
Dictionary<DamageClass, int> damageClasses,
|
||||||
Dictionary<DamageType, int> damageTypes)
|
Dictionary<DamageType, int> damageTypes,
|
||||||
|
bool isScanned)
|
||||||
{
|
{
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
DamageClasses = damageClasses;
|
DamageClasses = damageClasses;
|
||||||
DamageTypes = damageTypes;
|
DamageTypes = damageTypes;
|
||||||
|
IsScanned = isScanned;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasDamage()
|
public bool HasDamage()
|
||||||
@@ -56,5 +59,24 @@ namespace Content.Shared.GameObjects.Components.Medical
|
|||||||
Green,
|
Green,
|
||||||
Yellow,
|
Yellow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum UiButton
|
||||||
|
{
|
||||||
|
ScanDNA,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public class UiButtonPressedMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public readonly UiButton Button;
|
||||||
|
|
||||||
|
public UiButtonPressedMessage(UiButton button)
|
||||||
|
{
|
||||||
|
Button = button;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC BY-SA 3.0",
|
||||||
|
"copyright": "Taken from https://github.com/tgstation/tgstation at commit 9bebd81ae0b0a7f952b59886a765c681205de31f",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "pod_0",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scanner",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.2,
|
||||||
|
0.2
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scanner_maintenance",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scanner_occupied",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scanner_open",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.2,
|
||||||
|
0.2
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scanner_open_maintenance",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scanner_open_unpowered",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scanner_unpowered",
|
||||||
|
"directions": 1,
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
1.0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |