fish-station/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs
Vigers Ray 7eee898afc Merge remote-tracking branch 'space-sunrise/master'
# Conflicts:
#	Content.Client/Medical/CrewMonitoring/CrewMonitoringWindow.xaml
#	Content.Client/_Sunrise/MentorHelp/MentorHelpControl.xaml.cs
#	Content.Packaging/ServerPackaging.cs
#	Content.Server/Content.Server.csproj
#	Content.Server/Entry/EntryPoint.cs
#	Content.Server/Explosion/EntitySystems/ExplosionSystem.Processing.cs
#	Content.Server/Fax/FaxSystem.cs
#	Content.Server/Medical/CrewMonitoring/CrewMonitoringConsoleSystem.cs
#	Content.Server/_Sunrise/Biocode/Systems/BiocodeDeactivationSystem.cs
#	Content.Shared/CCVar/CCVars.Atmos.cs
#	Content.Shared/Repairable/RepairableSystem.cs
#	Content.Shared/_Sunrise/FleshCult/CauseFleshCultInfection.cs
#	Resources/Locale/en-US/_prototypes/_sunrise/entities/clothing/belt/belts.ftl
#	Resources/Locale/en-US/_prototypes/_sunrise/entities/objects/specific/medical/hypospray.ftl
#	Resources/Locale/en-US/_strings/medical/components/crew-monitoring-component.ftl
#	Resources/Locale/en-US/_strings/reagents/meta/medicine.ftl
#	Resources/Locale/ru-RU/_prototypes/_sunrise/entities/clothing/belt/belts.ftl
#	Resources/Locale/ru-RU/_prototypes/_sunrise/entities/objects/specific/mech/mechs.ftl
#	Resources/Locale/ru-RU/_prototypes/_sunrise/entities/objects/specific/medical/hypospray.ftl
#	Resources/Locale/ru-RU/_strings/_sunrise/markings/vulpkanin.ftl
#	Resources/Locale/ru-RU/_strings/_sunrise/mentor-help/mentor-help-ui.ftl
#	Resources/Locale/ru-RU/_strings/reagents/meta/medicine.ftl
#	Resources/Maps/Nonstations/nukieplanet.yml
#	Resources/Maps/_Sunrise/Nonstations/nukieplanet.yml
#	Resources/Prototypes/Catalog/Fills/Items/belt.yml
#	Resources/Prototypes/Catalog/Fills/Items/firstaidkits.yml
#	Resources/Prototypes/Damage/containers.yml
#	Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
#	Resources/Prototypes/Entities/Mobs/Player/humanoid.yml
#	Resources/Prototypes/Entities/Mobs/Species/base.yml
#	Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml
#	Resources/Prototypes/Entities/Objects/Specific/Mech/mechs.yml
#	Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
#	Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml
#	Resources/Prototypes/Entities/Objects/Specific/Robotics/mmi.yml
#	Resources/Prototypes/Entities/Objects/Tools/cable_coils.yml
#	Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
#	Resources/Prototypes/Entities/Structures/Storage/Closets/Lockers/lockers.yml
#	Resources/Prototypes/Reagents/fun.yml
#	Resources/Prototypes/Reagents/medicine.yml
#	Resources/Prototypes/Reagents/narcotics.yml
#	Resources/Prototypes/Reagents/toxins.yml
#	Resources/Prototypes/Roles/Antags/nukeops.yml
#	Resources/Prototypes/Roles/Jobs/CentComm/cburn.yml
#	Resources/Prototypes/Roles/Jobs/CentComm/deathsquad.yml
#	Resources/Prototypes/Shuttles/shuttle_incoming_event.yml
#	Resources/Prototypes/Store/currency.yml
#	Resources/Prototypes/_Starlight/Entities/Objects/Weapons/Guns/Projectiles/hitscan.yml
#	Resources/Prototypes/_Sunrise/Catalog/ert_uplink_catalog.yml
#	Resources/Prototypes/_Sunrise/Chemistry/medicine.yml
#	Resources/Prototypes/_Sunrise/Entities/Clothing/Belt/belts.yml
#	Resources/Prototypes/_Sunrise/Entities/Mobs/Player/eviltwin.yml
#	Resources/Prototypes/_Sunrise/Entities/Mobs/Player/ghost_roles.yml
#	Resources/Prototypes/_Sunrise/Entities/Objects/Specific/Mech/mechs.yml
#	Resources/Prototypes/_Sunrise/Entities/Objects/Specific/Medical/hypospray.yml
#	Resources/Prototypes/_Sunrise/Entities/Objects/Specific/NTUplink.yml
#	Resources/Prototypes/_Sunrise/Entities/Objects/Specific/Robotics/borg_brains.yml
#	Resources/Prototypes/_Sunrise/Entities/Objects/Tools/biocode.yml
#	Resources/Prototypes/_Sunrise/GameRules/events.yml
#	Resources/Prototypes/_Sunrise/Reagents/gases.yml
#	Resources/Prototypes/_Sunrise/Reagents/narcotics.yml
#	Resources/Prototypes/_Sunrise/Roles/Jobs/Blueshield/blueshield_officer.yml
#	Resources/Prototypes/_Sunrise/Roles/Jobs/Security/senior_officer.yml
#	Resources/ServerInfo/Guidebook/Medical/MedicalDoctor.xml
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/meta.json
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalert.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalertdirect.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonalertnull.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonclose.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirect.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectlarge.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectsmall.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinondirectxtrlarge.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonfar.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonmedium.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinonnull.png
#	Resources/Textures/_Sunrise/BloodCult/pinpointer.rsi/pinpointer_bloodcult.png
#	Resources/manifest.yml
2025-12-29 18:37:56 +01:00

251 lines
9.5 KiB
C#

using System.Linq;
using System.Numerics;
using Content.Shared.Atmos;
using Content.Client.UserInterface.Controls;
using Content.Shared.Damage.Components;
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.MedicalScanner;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.XAML;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Client.ResourceManagement;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Client.HealthAnalyzer.UI
{
[GenerateTypedNameReferences]
public sealed partial class HealthAnalyzerWindow : FancyWindow
{
private readonly IEntityManager _entityManager;
private readonly SpriteSystem _spriteSystem;
private readonly IPrototypeManager _prototypes;
private readonly IResourceCache _cache;
public HealthAnalyzerWindow()
{
RobustXamlLoader.Load(this);
var dependencies = IoCManager.Instance!;
_entityManager = dependencies.Resolve<IEntityManager>();
_spriteSystem = _entityManager.System<SpriteSystem>();
_prototypes = dependencies.Resolve<IPrototypeManager>();
_cache = dependencies.Resolve<IResourceCache>();
}
public void Populate(HealthAnalyzerScannedUserMessage msg)
{
var target = _entityManager.GetEntity(msg.TargetEntity);
if (target == null
|| !_entityManager.TryGetComponent<DamageableComponent>(target, out var damageable))
{
NoPatientDataText.Visible = true;
return;
}
NoPatientDataText.Visible = false;
// Scan Mode
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);
SpriteView.Visible = msg.ScanMode.HasValue && msg.ScanMode.Value;
NoDataTex.Visible = !SpriteView.Visible;
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");
HungerLabel.Text = msg.HungerLevel.HasValue && !float.IsNaN(msg.HungerLevel.Value)
? $"{msg.HungerLevel.Value:F1} %"
: Loc.GetString("health-analyzer-window-entity-unknown-value-text");
ThirstLabel.Text = msg.ThirstLevel.HasValue && !float.IsNaN(msg.ThirstLevel.Value)
? $"{msg.ThirstLevel.Value:F1} %"
: Loc.GetString("health-analyzer-window-entity-unknown-value-text");
StatusLabel.Text =
_entityManager.TryGetComponent<MobStateComponent>(target.Value, out var mobStateComponent)
? GetStatus(mobStateComponent.CurrentState)
: Loc.GetString("health-analyzer-window-entity-unknown-text");
// Total Damage
DamageLabel.Text = damageable.TotalDamage.ToString();
// Alerts
var showAlerts = msg.Unrevivable == true || msg.Bleeding == true;
AlertsDivider.Visible = showAlerts;
AlertsContainer.Visible = showAlerts;
if (showAlerts)
AlertsContainer.RemoveAllChildren();
if (msg.Unrevivable == true)
AlertsContainer.AddChild(new RichTextLabel
{
Text = Loc.GetString("health-analyzer-window-entity-unrevivable-text"),
Margin = new Thickness(0, 4),
MaxWidth = 300
});
if (msg.Bleeding == true)
AlertsContainer.AddChild(new RichTextLabel
{
Text = Loc.GetString("health-analyzer-window-entity-bleeding-text"),
Margin = new Thickness(0, 4),
MaxWidth = 300
});
// Damage Groups
var damageSortedGroups =
damageable.DamagePerGroup.OrderByDescending(damage => damage.Value)
.ToDictionary(x => x.Key, x => x.Value);
IReadOnlyDictionary<string, FixedPoint2> damagePerType = damageable.Damage.DamageDict;
DrawDiagnosticGroups(damageSortedGroups, damagePerType);
}
private static string GetStatus(MobState mobState)
{
return mobState switch
{
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)
{
GroupsContainer.RemoveAllChildren();
foreach (var (damageGroupId, damageAmount) in groups)
{
if (damageAmount == 0)
continue;
var groupTitleText = $"{Loc.GetString(
"health-analyzer-window-damage-group-text",
("damageGroup", _prototypes.Index<DamageGroupPrototype>(damageGroupId).LocalizedName),
("amount", damageAmount)
)}";
var groupContainer = new BoxContainer
{
Align = BoxContainer.AlignMode.Begin,
Orientation = BoxContainer.LayoutOrientation.Vertical,
};
groupContainer.AddChild(CreateDiagnosticGroupTitle(groupTitleText, damageGroupId));
GroupsContainer.AddChild(groupContainer);
// Show the damage for each type in that group.
var group = _prototypes.Index<DamageGroupPrototype>(damageGroupId);
foreach (var type in group.DamageTypes)
{
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, " · ")));
}
}
}
private Texture GetTexture(string texture)
{
var rsiPath = new ResPath("/Textures/_Sunrise/Objects/Devices/health_analyzer.rsi");
var rsiSprite = new SpriteSpecifier.Rsi(rsiPath, texture);
var rsi = _cache.GetResource<RSIResource>(rsiSprite.RsiPath).RSI;
if (!rsi.TryGetState(rsiSprite.RsiState, out var state))
{
rsiSprite = new SpriteSpecifier.Rsi(rsiPath, "unknown");
}
return _spriteSystem.Frame0(rsiSprite);
}
private static Label CreateDiagnosticItemLabel(string text)
{
return new Label
{
Text = text,
};
}
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,
};
string spriteName = id.ToLower();
rootContainer.AddChild(new TextureRect
{
SetSize = new Vector2(30, 30),
Texture = GetTexture(spriteName)// Fish-edit
});
rootContainer.AddChild(CreateDiagnosticItemLabel(text));
return rootContainer;
}
}
}