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;
private readonly IPrototypeManager _prototypes;
private readonly IResourceCache _cache;
- private const int AnalyzerHeight = 430;
- private const int AnalyzerWidth = 300;
-
public HealthAnalyzerWindow()
{
RobustXamlLoader.Load(this);
public void Populate(HealthAnalyzerScannedUserMessage msg)
{
- GroupsContainer.RemoveAllChildren();
-
var target = _entityManager.GetEntity(msg.TargetEntity);
if (target == null
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;
var groupContainer = new BoxContainer
{
- Margin = new Thickness(0, 0, 0, 15),
Align = BoxContainer.AlignMode.Begin,
Orientation = BoxContainer.LayoutOrientation.Vertical,
};
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", _prototypes.Index<DamageTypePrototype>(type).LocalizedName),
- ("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", _prototypes.Index<DamageTypePrototype>(type).LocalizedName),
+ ("amount", typeAmount)
+ );
+
+ groupContainer.AddChild(CreateDiagnosticItemLabel(damageString.Insert(0, " · ")));
}
}
}
{
return new Label
{
- Margin = new Thickness(2, 2),
Text = text,
};
}
{
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())
});