Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated Health Analyzer UI From Latest Wizden Update #169

Merged
merged 2 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 42 additions & 26 deletions Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml
Original file line number Diff line number Diff line change
@@ -1,48 +1,64 @@
<controls:FancyWindow
xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
SetSize="250 100">
MaxHeight="525"
MinWidth="300">
<ScrollContainer
Margin="5 5 5 5"
ReturnMeasure="True"
VerticalExpand="True">
<BoxContainer
Name="RootContainer"
VerticalExpand="True"
Orientation="Vertical">
<Label
Name="NoPatientDataText"
Text="{Loc health-analyzer-window-no-patient-data-text}" />

<BoxContainer
Name="PatientDataContainer"
Orientation="Vertical"
Margin="0 0 5 10">
<BoxContainer Name="ScanModePanel" HorizontalExpand="True" Visible="False" Margin="0 5 0 0">
<Label
Name="ScanMode"
Align="Left"
Text="{Loc health-analyzer-window-scan-mode-text}"/>
<Label
Name="ScanModeText"
Align="Right"
HorizontalExpand="True"/>
Margin="0 0 0 5"
Orientation="Vertical">
<BoxContainer Orientation="Horizontal" Margin="0 0 0 5">
<SpriteView OverrideDirection="South" Scale="2 2" Name="SpriteView" Access="Public" SetSize="64 64" />
<BoxContainer Margin="5 0 0 0" Orientation="Vertical" VerticalAlignment="Top">
<RichTextLabel Name="NameLabel" SetWidth="150" />
<Label Name="SpeciesLabel" VerticalAlignment="Top" StyleClasses="LabelSubText" />
</BoxContainer>
<Label Margin="0 0 5 0" HorizontalExpand="True" HorizontalAlignment="Right" VerticalExpand="True"
VerticalAlignment="Top" Name="ScanModeLabel"
Text="{Loc 'health-analyzer-window-entity-unknown-text'}" />
</BoxContainer>
<Label
Name="PatientName"/>
<Label
Name="Temperature"
Margin="0 5 0 0"/>
<Label
Name="BloodLevel"
Margin="0 5 0 0"/>
<Label
Name="Bleeding"
Margin="0 5 0 0"/>
<Label
Name="patientDamageAmount"
Margin="0 15 0 0"/>

<PanelContainer StyleClasses="LowDivider" />

<GridContainer Margin="0 5 0 0" Columns="2">
<Label Text="{Loc 'health-analyzer-window-entity-status-text'}" />
<Label Name="StatusLabel" />
<Label Text="{Loc 'health-analyzer-window-entity-temperature-text'}" />
<Label Name="TemperatureLabel" />
<Label Text="{Loc 'health-analyzer-window-entity-blood-level-text'}" />
<Label Name="BloodLabel" />
<Label Text="{Loc 'health-analyzer-window-entity-damage-total-text'}" />
<Label Name="DamageLabel" />
</GridContainer>
</BoxContainer>

<PanelContainer Name="AlertsDivider" Visible="False" StyleClasses="LowDivider" />

<BoxContainer Name="AlertsContainer" Visible="False" Margin="0 5" Orientation="Horizontal"
HorizontalExpand="True" HorizontalAlignment="Center">

</BoxContainer>

<PanelContainer StyleClasses="LowDivider" />

<BoxContainer
Name="GroupsContainer"
Margin="0 5 0 5"
Orientation="Vertical">
</BoxContainer>

</BoxContainer>
</ScrollContainer>
</controls:FancyWindow>
168 changes: 88 additions & 80 deletions Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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);
Expand All @@ -44,8 +49,6 @@ public HealthAnalyzerWindow()

public void Populate(HealthAnalyzerScannedUserMessage msg)
{
GroupsContainer.RemoveAllChildren();

var target = _entityManager.GetEntity(msg.TargetEntity);

if (target == null
Expand All @@ -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<MetaDataComponent>(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<MetaDataComponent>(target.Value)
? Identity.Name(target.Value, _entityManager)
: Loc.GetString("health-analyzer-window-entity-unknown-text"));
NameLabel.SetMessage(name);

SpeciesLabel.Text =
_entityManager.TryGetComponent<HumanoidAppearanceComponent>(target.Value,
out var humanoidAppearanceComponent)
? Loc.GetString(_prototypes.Index<SpeciesPrototype>(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<MobStateComponent>(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<string, FixedPoint2> 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<string, FixedPoint2> groups, IReadOnlyDictionary<string, FixedPoint2> damageDict)
Dictionary<string, FixedPoint2> groups,
IReadOnlyDictionary<string, FixedPoint2> damageDict)
{
HashSet<string> 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;
Expand All @@ -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,
};
Expand All @@ -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, " · ")));
}
}
}
Expand All @@ -198,7 +207,6 @@ private static Label CreateDiagnosticItemLabel(string text)
{
return new Label
{
Margin = new Thickness(2, 2),
Text = text,
};
}
Expand All @@ -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())
});
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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!
Loading