MedBookWindow.xaml.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. using System.Linq;
  2. using System.Numerics;
  3. using Content.Client.Message;
  4. using Content.Shared.Atmos;
  5. using Content.Client.UserInterface.Controls;
  6. using Content.Shared.Alert;
  7. using Content.Shared.Damage;
  8. using Content.Shared.Damage.Prototypes;
  9. using Content.Shared.FixedPoint;
  10. using Content.Shared.Humanoid;
  11. using Content.Shared.Humanoid.Prototypes;
  12. using Content.Shared.IdentityManagement;
  13. using Content.Shared.Inventory;
  14. using Content.Shared.MedicalScanner;
  15. using Content.Shared.Mobs;
  16. using Content.Shared.Mobs.Components;
  17. using Content.Shared.Mobs.Systems;
  18. using Content.Shared.Nutrition.Components;
  19. using Robust.Client.AutoGenerated;
  20. using Robust.Client.UserInterface.XAML;
  21. using Robust.Client.GameObjects;
  22. using Robust.Client.Graphics;
  23. using Robust.Client.UserInterface.Controls;
  24. using Robust.Client.ResourceManagement;
  25. using Robust.Client.UserInterface;
  26. using Robust.Shared.Prototypes;
  27. using Robust.Shared.Utility;
  28. namespace Content.Client.MedBook.UI
  29. {
  30. [GenerateTypedNameReferences]
  31. public sealed partial class MedBookWindow : FancyWindow
  32. {
  33. private readonly IEntityManager _entityManager;
  34. private readonly SpriteSystem _spriteSystem;
  35. private readonly IPrototypeManager _prototypes;
  36. private readonly IResourceCache _cache;
  37. public MedBookWindow()
  38. {
  39. RobustXamlLoader.Load(this);
  40. var dependencies = IoCManager.Instance!;
  41. _entityManager = dependencies.Resolve<IEntityManager>();
  42. _spriteSystem = _entityManager.System<SpriteSystem>();
  43. _prototypes = dependencies.Resolve<IPrototypeManager>();
  44. _cache = dependencies.Resolve<IResourceCache>();
  45. }
  46. public void Populate(MedBookScannedUserMessage msg)
  47. {
  48. var target = _entityManager.GetEntity(msg.TargetEntity);
  49. if (target == null
  50. || !_entityManager.TryGetComponent<DamageableComponent>(target, out var damageable))
  51. {
  52. NoPatientDataText.Visible = true;
  53. return;
  54. }
  55. NoPatientDataText.Visible = false;
  56. // Patient Information
  57. SpriteView.SetEntity(target.Value);
  58. SpriteView.Visible = msg.ScanMode.HasValue && msg.ScanMode.Value;
  59. NoDataTex.Visible = !SpriteView.Visible;
  60. var name = new FormattedMessage();
  61. name.PushColor(Color.White);
  62. name.AddText(_entityManager.HasComponent<MetaDataComponent>(target.Value)
  63. ? Identity.Name(target.Value, _entityManager)
  64. : Loc.GetString("health-analyzer-window-entity-unknown-text"));
  65. NameLabel.SetMessage(name);
  66. SpeciesLabel.Text =
  67. _entityManager.TryGetComponent<HumanoidAppearanceComponent>(target.Value,
  68. out var humanoidAppearanceComponent)
  69. ? Loc.GetString(_prototypes.Index<SpeciesPrototype>(humanoidAppearanceComponent.Species).Name)
  70. : Loc.GetString("health-analyzer-window-entity-unknown-species-text");
  71. // Basic Diagnostic
  72. var parsedBlood = Loc.GetString("medbook-status-normal");
  73. BloodLabel.FontColorOverride = Color.Green;
  74. if (msg.BloodLevel <= 0.6)
  75. {
  76. parsedBlood = Loc.GetString("medbook-status-critical");
  77. BloodLabel.FontColorOverride = Color.Red;
  78. }
  79. else if (msg.BloodLevel <= 0.8)
  80. {
  81. parsedBlood = Loc.GetString("medbook-status-low");
  82. BloodLabel.FontColorOverride = Color.Yellow;
  83. }
  84. BloodLabel.Text = !float.IsNaN(msg.BloodLevel)
  85. ? parsedBlood
  86. : Loc.GetString("health-analyzer-window-entity-unknown-value-text");
  87. StatusLabel.Text = Loc.GetString("health-analyzer-window-entity-alive-text");
  88. StatusLabel.FontColorOverride = Color.Green;
  89. if (_entityManager.TryGetComponent<MobStateComponent>(target.Value, out var mobStateComponent))
  90. {
  91. if (mobStateComponent.CurrentState == MobState.Critical)
  92. {
  93. StatusLabel.FontColorOverride = Color.Yellow;
  94. StatusLabel.Text = Loc.GetString("health-analyzer-window-entity-critical-text");
  95. }
  96. else if (mobStateComponent.CurrentState == MobState.Dead)
  97. {
  98. StatusLabel.FontColorOverride = Color.Red;
  99. StatusLabel.Text = Loc.GetString("health-analyzer-window-entity-dead-text");
  100. }
  101. }
  102. // Alerts
  103. var showAlerts = msg.Unrevivable == true || msg.Bleeding == true;
  104. AlertsDivider.Visible = showAlerts;
  105. AlertsContainer.Visible = showAlerts;
  106. if (showAlerts)
  107. AlertsContainer.DisposeAllChildren();
  108. if (msg.Unrevivable == true)
  109. AlertsContainer.AddChild(new RichTextLabel
  110. {
  111. Text = Loc.GetString("health-analyzer-window-entity-unrevivable-text"),
  112. Margin = new Thickness(0, 4),
  113. MaxWidth = 300
  114. });
  115. if (msg.Bleeding == true)
  116. AlertsContainer.AddChild(new RichTextLabel
  117. {
  118. Text = Loc.GetString("health-analyzer-window-entity-bleeding-text"),
  119. Margin = new Thickness(0, 4),
  120. MaxWidth = 300
  121. });
  122. // Damage Groups
  123. var damageSortedGroups =
  124. damageable.DamagePerGroup.OrderByDescending(damage => damage.Value)
  125. .ToDictionary(x => x.Key, x => x.Value);
  126. IReadOnlyDictionary<string, FixedPoint2> damagePerType = damageable.Damage.DamageDict;
  127. DrawDiagnosticGroups(damageSortedGroups, damagePerType);
  128. }
  129. private static string GetStatus(MobState mobState)
  130. {
  131. return mobState switch
  132. {
  133. MobState.Alive => Loc.GetString("health-analyzer-window-entity-alive-text"),
  134. MobState.Critical => Loc.GetString("health-analyzer-window-entity-critical-text"),
  135. MobState.Dead => Loc.GetString("health-analyzer-window-entity-dead-text"),
  136. _ => Loc.GetString("health-analyzer-window-entity-unknown-text"),
  137. };
  138. }
  139. private void DrawDiagnosticGroups(
  140. Dictionary<string, FixedPoint2> groups,
  141. IReadOnlyDictionary<string, FixedPoint2> damageDict)
  142. {
  143. GroupsContainer.RemoveAllChildren();
  144. foreach (var (damageGroupId, damageAmount) in groups)
  145. {
  146. if (damageAmount == 0)
  147. continue;
  148. var parsedDamage = "None";
  149. var color = Color.Green;
  150. if (damageAmount > 0 && damageAmount <= 20)
  151. {
  152. parsedDamage = "Minimal";
  153. color = Color.Yellow;
  154. }
  155. else if (damageAmount <= 60)
  156. {
  157. parsedDamage = "Medium";
  158. color = Color.Orange;
  159. }
  160. else if (damageAmount <= 100)
  161. {
  162. parsedDamage = "High";
  163. color = Color.Red;
  164. }
  165. else
  166. {
  167. parsedDamage = "Extreme";
  168. color = Color.DarkRed;
  169. }
  170. var groupTitleText = $"{Loc.GetString(
  171. "health-analyzer-window-damage-group-text",
  172. ("damageGroup", _prototypes.Index<DamageGroupPrototype>(damageGroupId).LocalizedName),
  173. ("amount", parsedDamage)
  174. )}";
  175. var groupContainer = new BoxContainer
  176. {
  177. Align = BoxContainer.AlignMode.Begin,
  178. Orientation = BoxContainer.LayoutOrientation.Vertical,
  179. };
  180. groupContainer.AddChild(CreateDiagnosticGroupTitle(groupTitleText, damageGroupId, color));
  181. GroupsContainer.AddChild(groupContainer);
  182. }
  183. }
  184. private Texture GetTexture(string texture)
  185. {
  186. var rsiPath = new ResPath("/Textures/Objects/Devices/health_analyzer.rsi");
  187. var rsiSprite = new SpriteSpecifier.Rsi(rsiPath, texture);
  188. var rsi = _cache.GetResource<RSIResource>(rsiSprite.RsiPath).RSI;
  189. if (!rsi.TryGetState(rsiSprite.RsiState, out var state))
  190. {
  191. rsiSprite = new SpriteSpecifier.Rsi(rsiPath, "unknown");
  192. }
  193. return _spriteSystem.Frame0(rsiSprite);
  194. }
  195. private static Label CreateDiagnosticItemLabel(string text, Color color)
  196. {
  197. return new Label
  198. {
  199. Text = text,
  200. FontColorOverride = color
  201. };
  202. }
  203. private BoxContainer CreateDiagnosticGroupTitle(string text, string id, Color color)
  204. {
  205. var rootContainer = new BoxContainer
  206. {
  207. Margin = new Thickness(0, 6, 0, 0),
  208. VerticalAlignment = VAlignment.Bottom,
  209. Orientation = BoxContainer.LayoutOrientation.Horizontal,
  210. };
  211. rootContainer.AddChild(new TextureRect
  212. {
  213. SetSize = new Vector2(30, 30),
  214. Texture = GetTexture(id.ToLower())
  215. });
  216. rootContainer.AddChild(CreateDiagnosticItemLabel(text, color));
  217. return rootContainer;
  218. }
  219. }
  220. }