diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml
index 401f9768629..a096caa4cfd 100644
--- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml
+++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml
@@ -1,48 +1,64 @@
+ MaxHeight="525"
+ MinWidth="300">
+
-
-
-
+ Margin="0 0 0 5"
+ Orientation="Vertical">
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs
index 0cb3ad144d7..b3b3539c09f 100644
--- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs
+++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs
@@ -1,12 +1,20 @@
using System.Linq;
using System.Numerics;
+using Content.Client.Message;
using Content.Shared.Atmos;
using Content.Client.UserInterface.Controls;
+using Content.Shared.Alert;
using Content.Shared.Damage;
using Content.Shared.Damage.Prototypes;
using Content.Shared.FixedPoint;
+using Content.Shared.Humanoid;
+using Content.Shared.Humanoid.Prototypes;
using Content.Shared.IdentityManagement;
+using Content.Shared.Inventory;
using Content.Shared.MedicalScanner;
+using Content.Shared.Mobs;
+using Content.Shared.Mobs.Components;
+using Content.Shared.Mobs.Systems;
using Content.Shared.Nutrition.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
@@ -28,9 +36,6 @@ public sealed partial class HealthAnalyzerWindow : FancyWindow
private readonly IPrototypeManager _prototypes;
private readonly IResourceCache _cache;
- private const int AnalyzerHeight = 430;
- private const int AnalyzerWidth = 300;
-
public HealthAnalyzerWindow()
{
RobustXamlLoader.Load(this);
@@ -44,8 +49,6 @@ public HealthAnalyzerWindow()
public void Populate(HealthAnalyzerScannedUserMessage msg)
{
- GroupsContainer.RemoveAllChildren();
-
var target = _entityManager.GetEntity(msg.TargetEntity);
if (target == null
@@ -57,82 +60,96 @@ public void Populate(HealthAnalyzerScannedUserMessage msg)
NoPatientDataText.Visible = false;
- string entityName = Loc.GetString("health-analyzer-window-entity-unknown-text");
- if (_entityManager.HasComponent(target.Value))
- {
- entityName = Identity.Name(target.Value, _entityManager);
- }
+ // Scan Mode
- if (msg.ScanMode.HasValue)
- {
- ScanModePanel.Visible = true;
- ScanModeText.Text = Loc.GetString(msg.ScanMode.Value ? "health-analyzer-window-scan-mode-active" : "health-analyzer-window-scan-mode-inactive");
- ScanModeText.FontColorOverride = msg.ScanMode.Value ? Color.Green : Color.Red;
- }
- else
- {
- ScanModePanel.Visible = false;
- }
+ ScanModeLabel.Text = msg.ScanMode.HasValue
+ ? msg.ScanMode.Value
+ ? Loc.GetString("health-analyzer-window-scan-mode-active")
+ : Loc.GetString("health-analyzer-window-scan-mode-inactive")
+ : Loc.GetString("health-analyzer-window-entity-unknown-text");
+
+ ScanModeLabel.FontColorOverride = msg.ScanMode.HasValue && msg.ScanMode.Value ? Color.Green : Color.Red;
+
+ // Patient Information
+
+ SpriteView.SetEntity(target.Value);
+
+ var name = new FormattedMessage();
+ name.PushColor(Color.White);
+ name.AddText(_entityManager.HasComponent(target.Value)
+ ? Identity.Name(target.Value, _entityManager)
+ : Loc.GetString("health-analyzer-window-entity-unknown-text"));
+ NameLabel.SetMessage(name);
+
+ SpeciesLabel.Text =
+ _entityManager.TryGetComponent(target.Value,
+ out var humanoidAppearanceComponent)
+ ? Loc.GetString(_prototypes.Index(humanoidAppearanceComponent.Species).Name)
+ : Loc.GetString("health-analyzer-window-entity-unknown-species-text");
+
+ // Basic Diagnostic
+
+ TemperatureLabel.Text = !float.IsNaN(msg.Temperature)
+ ? $"{msg.Temperature - Atmospherics.T0C:F1} °C ({msg.Temperature:F1} K)"
+ : Loc.GetString("health-analyzer-window-entity-unknown-value-text");
+
+ BloodLabel.Text = !float.IsNaN(msg.BloodLevel)
+ ? $"{msg.BloodLevel * 100:F1} %"
+ : Loc.GetString("health-analyzer-window-entity-unknown-value-text");
- PatientName.Text = Loc.GetString(
- "health-analyzer-window-entity-health-text",
- ("entityName", entityName)
- );
+ StatusLabel.Text =
+ _entityManager.TryGetComponent(target.Value, out var mobStateComponent)
+ ? GetStatus(mobStateComponent.CurrentState)
+ : Loc.GetString("health-analyzer-window-entity-unknown-text");
- Temperature.Text = Loc.GetString("health-analyzer-window-entity-temperature-text",
- ("temperature", float.IsNaN(msg.Temperature) ? "N/A" : $"{msg.Temperature - Atmospherics.T0C:F1} °C ({msg.Temperature:F1} K)")
- );
+ // Total Damage
- BloodLevel.Text = Loc.GetString("health-analyzer-window-entity-blood-level-text",
- ("bloodLevel", float.IsNaN(msg.BloodLevel) ? "N/A" : $"{msg.BloodLevel * 100:F1} %")
- );
+ DamageLabel.Text = damageable.TotalDamage.ToString();
+
+ // Alerts
+
+ AlertsDivider.Visible = msg.Bleeding == true;
+ AlertsContainer.Visible = msg.Bleeding == true;
if (msg.Bleeding == true)
{
- Bleeding.Text = Loc.GetString("health-analyzer-window-entity-bleeding-text");
- Bleeding.FontColorOverride = Color.Red;
- }
- else
- {
- Bleeding.Text = string.Empty; // Clear the text
+ AlertsContainer.DisposeAllChildren();
+ AlertsContainer.AddChild(new Label
+ {
+ Text = Loc.GetString("health-analyzer-window-entity-bleeding-text"),
+ FontColorOverride = Color.Red,
+ });
}
- patientDamageAmount.Text = Loc.GetString(
- "health-analyzer-window-entity-damage-total-text",
- ("amount", damageable.TotalDamage)
- );
+ // Damage Groups
var damageSortedGroups =
- damageable.DamagePerGroup.OrderBy(damage => damage.Value)
+ damageable.DamagePerGroup.OrderByDescending(damage => damage.Value)
.ToDictionary(x => x.Key, x => x.Value);
+
IReadOnlyDictionary damagePerType = damageable.Damage.DamageDict;
DrawDiagnosticGroups(damageSortedGroups, damagePerType);
+ }
- if (_entityManager.TryGetComponent(target, out HungerComponent? hunger)
- && hunger.StarvationDamage != null
- && hunger.CurrentThreshold <= HungerThreshold.Starving)
+ private static string GetStatus(MobState mobState)
+ {
+ return mobState switch
{
- var box = new Control { Margin = new Thickness(0, 0, 0, 15) };
-
- box.AddChild(CreateDiagnosticGroupTitle(
- Loc.GetString("health-analyzer-window-malnutrition"),
- "malnutrition"));
-
- GroupsContainer.AddChild(box);
- }
-
- SetHeight = AnalyzerHeight;
- SetWidth = AnalyzerWidth;
+ MobState.Alive => Loc.GetString("health-analyzer-window-entity-alive-text"),
+ MobState.Critical => Loc.GetString("health-analyzer-window-entity-critical-text"),
+ MobState.Dead => Loc.GetString("health-analyzer-window-entity-dead-text"),
+ _ => Loc.GetString("health-analyzer-window-entity-unknown-text"),
+ };
}
private void DrawDiagnosticGroups(
- Dictionary groups, IReadOnlyDictionary damageDict)
+ Dictionary groups,
+ IReadOnlyDictionary damageDict)
{
- HashSet shownTypes = new();
+ GroupsContainer.RemoveAllChildren();
- // Show the total damage and type breakdown for each damage group.
- foreach (var (damageGroupId, damageAmount) in groups.Reverse())
+ foreach (var (damageGroupId, damageAmount) in groups)
{
if (damageAmount == 0)
continue;
@@ -145,7 +162,6 @@ private void DrawDiagnosticGroups(
var groupContainer = new BoxContainer
{
- Margin = new Thickness(0, 0, 0, 15),
Align = BoxContainer.AlignMode.Begin,
Orientation = BoxContainer.LayoutOrientation.Vertical,
};
@@ -159,23 +175,16 @@ private void DrawDiagnosticGroups(
foreach (var type in group.DamageTypes)
{
- if (damageDict.TryGetValue(type, out var typeAmount) && typeAmount > 0)
- {
- // If damage types are allowed to belong to more than one damage group,
- // they may appear twice here. Mark them as duplicate.
- if (shownTypes.Contains(type))
- continue;
-
- shownTypes.Add(type);
-
- var damageString = Loc.GetString(
- "health-analyzer-window-damage-type-text",
- ("damageType", Loc.GetString("health-analyzer-window-damage-type-" + type)),
- ("amount", typeAmount)
- );
-
- groupContainer.AddChild(CreateDiagnosticItemLabel(damageString.Insert(0, "- ")));
- }
+ if (!damageDict.TryGetValue(type, out var typeAmount) || typeAmount <= 0)
+ continue;
+
+ var damageString = Loc.GetString(
+ "health-analyzer-window-damage-type-text",
+ ("damageType", Loc.GetString("health-analyzer-window-damage-type-" + type)),
+ ("amount", typeAmount)
+ );
+
+ groupContainer.AddChild(CreateDiagnosticItemLabel(damageString.Insert(0, " · ")));
}
}
}
@@ -198,7 +207,6 @@ private static Label CreateDiagnosticItemLabel(string text)
{
return new Label
{
- Margin = new Thickness(2, 2),
Text = text,
};
}
@@ -207,13 +215,13 @@ private BoxContainer CreateDiagnosticGroupTitle(string text, string id)
{
var rootContainer = new BoxContainer
{
+ Margin = new Thickness(0, 6, 0, 0),
VerticalAlignment = VAlignment.Bottom,
- Orientation = BoxContainer.LayoutOrientation.Horizontal
+ Orientation = BoxContainer.LayoutOrientation.Horizontal,
};
rootContainer.AddChild(new TextureRect
{
- Margin = new Thickness(0, 3),
SetSize = new Vector2(30, 30),
Texture = GetTexture(id.ToLower())
});
diff --git a/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl b/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl
index 648db3f4ebd..7a2f8b8c6b7 100644
--- a/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl
+++ b/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl
@@ -1,18 +1,21 @@
health-analyzer-window-no-patient-data-text = No patient data.
-health-analyzer-window-entity-unknown-text = unknown
-health-analyzer-window-entity-health-text = {$entityName}'s health:
-health-analyzer-window-entity-temperature-text = Temperature: {$temperature}
-health-analyzer-window-entity-blood-level-text = Blood Level: {$bloodLevel}
-health-analyzer-window-entity-bleeding-text = Patient is bleeding!
-health-analyzer-window-entity-damage-total-text = Total Damage: {$amount}
+health-analyzer-window-entity-unknown-text = Unknown
+health-analyzer-window-entity-unknown-species-text = Non-Humanoid
+health-analyzer-window-entity-unknown-value-text = N/A
+
+health-analyzer-window-entity-alive-text = Alive
+health-analyzer-window-entity-dead-text = Dead
+health-analyzer-window-entity-critical-text = Critical
+
+health-analyzer-window-entity-temperature-text = Temperature:
+health-analyzer-window-entity-blood-level-text = Blood Level:
+health-analyzer-window-entity-status-text = Status:
+health-analyzer-window-entity-damage-total-text = Total Damage:
+
health-analyzer-window-damage-group-text = {$damageGroup}: {$amount}
health-analyzer-window-damage-type-text = {$damageType}: {$amount}
health-analyzer-window-damage-type-duplicate-text = {$damageType}: {$amount} (duplicate)
-health-analyzer-window-scan-mode-text = Scan Mode:
-health-analyzer-window-scan-mode-active = ACTIVE
-health-analyzer-window-scan-mode-inactive = INACTIVE
-
health-analyzer-window-damage-group-Brute = Brute
health-analyzer-window-damage-type-Blunt = Blunt
health-analyzer-window-damage-type-Slash = Slash
@@ -36,3 +39,11 @@ health-analyzer-window-damage-group-Genetic = Genetic
health-analyzer-window-damage-type-Cellular = Cellular
health-analyzer-window-malnutrition = Severely malnourished
+
+health-analyzer-window-entity-bleeding-text = Patient is bleeding!
+
+health-analyzer-window-scan-mode-text = Scan Mode:
+health-analyzer-window-scan-mode-active = Active
+health-analyzer-window-scan-mode-inactive = Inactive
+
+health-analyzer-popup-scan-target = {CAPITALIZE(THE($user))} is trying to scan you!
\ No newline at end of file