| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- 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;
- using Robust.Client.GameObjects;
- using Robust.Client.Graphics;
- using Robust.Client.UserInterface.Controls;
- using Robust.Client.ResourceManagement;
- using Robust.Client.UserInterface;
- using Robust.Shared.Prototypes;
- using Robust.Shared.Utility;
- using Content.Shared._Shitmed.Targeting; // Shitmed
- namespace Content.Client.MedBook.UI
- {
- [GenerateTypedNameReferences]
- public sealed partial class MedBookWindow : FancyWindow
- {
- private readonly IEntityManager _entityManager;
- private readonly SpriteSystem _spriteSystem;
- private readonly IPrototypeManager _prototypes;
- private readonly IResourceCache _cache;
- // Shitmed Change Start
- public event Action<TargetBodyPart?, EntityUid>? OnBodyPartSelected;
- private EntityUid _spriteViewEntity;
- [ValidatePrototypeId<EntityPrototype>]
- private readonly EntProtoId _bodyView = "AlertSpriteView";
- private readonly Dictionary<TargetBodyPart, TextureButton> _bodyPartControls;
- private EntityUid? _target;
- // Shitmed Change End
- public MedBookWindow()
- {
- RobustXamlLoader.Load(this);
- var dependencies = IoCManager.Instance!;
- _entityManager = dependencies.Resolve<IEntityManager>();
- _spriteSystem = _entityManager.System<SpriteSystem>();
- _prototypes = dependencies.Resolve<IPrototypeManager>();
- _cache = dependencies.Resolve<IResourceCache>();
- // Shitmed Change Start
- _bodyPartControls = new Dictionary<TargetBodyPart, TextureButton>
- {
- { TargetBodyPart.Head, HeadButton },
- { TargetBodyPart.Torso, ChestButton },
- { TargetBodyPart.Groin, GroinButton },
- { TargetBodyPart.LeftArm, LeftArmButton },
- { TargetBodyPart.LeftHand, LeftHandButton },
- { TargetBodyPart.RightArm, RightArmButton },
- { TargetBodyPart.RightHand, RightHandButton },
- { TargetBodyPart.LeftLeg, LeftLegButton },
- { TargetBodyPart.LeftFoot, LeftFootButton },
- { TargetBodyPart.RightLeg, RightLegButton },
- { TargetBodyPart.RightFoot, RightFootButton },
- };
- foreach (var bodyPartButton in _bodyPartControls)
- {
- bodyPartButton.Value.MouseFilter = MouseFilterMode.Stop;
- bodyPartButton.Value.OnPressed += _ => SetActiveBodyPart(bodyPartButton.Key, bodyPartButton.Value);
- }
- ReturnButton.OnPressed += _ => ResetBodyPart();
- // Shitmed Change End
- }
- // Shitmed Change Start
- public void SetActiveBodyPart(TargetBodyPart part, TextureButton button)
- {
- if (_target == null)
- return;
- // Bit of the ole shitcode until we have Groins in the prototypes.
- OnBodyPartSelected?.Invoke(part == TargetBodyPart.Groin ? TargetBodyPart.Torso : part, _target.Value);
- }
- public void ResetBodyPart()
- {
- if (_target == null)
- return;
- OnBodyPartSelected?.Invoke(null, _target.Value);
- }
- public void SetActiveButtons(bool isHumanoid)
- {
- foreach (var button in _bodyPartControls)
- button.Value.Visible = isHumanoid;
- }
- public void Populate(MedBookScannedUserMessage msg)
- {
- _target = _entityManager.GetEntity(msg.TargetEntity);
- EntityUid? part = msg.Part != null ? _entityManager.GetEntity(msg.Part.Value) : null;
- var isPart = part != null;
- if (_target == null
- || !_entityManager.TryGetComponent<DamageableComponent>(isPart ? part : _target, out var damageable))
- {
- NoPatientDataText.Visible = true;
- return;
- }
- SetActiveButtons(_entityManager.HasComponent<TargetingComponent>(_target.Value));
- ReturnButton.Visible = isPart;
- PartNameLabel.Visible = isPart;
- if (part != null)
- PartNameLabel.Text = _entityManager.HasComponent<MetaDataComponent>(part)
- ? Identity.Name(part.Value, _entityManager)
- : Loc.GetString("health-analyzer-window-entity-unknown-value-text");
- NoPatientDataText.Visible = false;
- // Patient Information
- SpriteView.SetEntity(SetupIcon(msg.Body) ?? _target.Value);
- SpriteView.Visible = msg.ScanMode.HasValue && msg.ScanMode.Value;
- PartView.Visible = SpriteView.Visible;
- 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
- var parsedBlood = Loc.GetString("medbook-status-normal");
- BloodLabel.FontColorOverride = Color.Green;
- if (msg.BloodLevel <= 0.6)
- {
- parsedBlood = Loc.GetString("medbook-status-critical");
- BloodLabel.FontColorOverride = Color.Red;
- }
- else if (msg.BloodLevel <= 0.8)
- {
- parsedBlood = Loc.GetString("medbook-status-low");
- BloodLabel.FontColorOverride = Color.Yellow;
- }
- BloodLabel.Text = !float.IsNaN(msg.BloodLevel)
- ? parsedBlood
- : Loc.GetString("health-analyzer-window-entity-unknown-value-text");
- StatusLabel.Text = Loc.GetString("health-analyzer-window-entity-alive-text");
- StatusLabel.FontColorOverride = Color.Green;
- if (_entityManager.TryGetComponent<MobStateComponent>(_target.Value, out var mobStateComponent))
- {
- if (mobStateComponent.CurrentState == MobState.Critical)
- {
- StatusLabel.FontColorOverride = Color.Yellow;
- StatusLabel.Text = Loc.GetString("health-analyzer-window-entity-critical-text");
- }
- else if (mobStateComponent.CurrentState == MobState.Dead)
- {
- StatusLabel.FontColorOverride = Color.Red;
- StatusLabel.Text = Loc.GetString("health-analyzer-window-entity-dead-text");
- }
- }
- // Alerts
- var showAlerts = msg.Unrevivable == true || msg.Bleeding == true;
- AlertsDivider.Visible = showAlerts;
- AlertsContainer.Visible = showAlerts;
- if (showAlerts)
- AlertsContainer.DisposeAllChildren();
- 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);
- }
- // Not all of this function got messed with, but it was spread enough to warrant being covered entirely by a Shitmed Change
- 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 parsedDamage = "None";
- var color = Color.Green;
- if (damageAmount > 0 && damageAmount <= 20)
- {
- parsedDamage = "Minimal";
- color = Color.Yellow;
- }
- else if (damageAmount <= 60)
- {
- parsedDamage = "Medium";
- color = Color.Orange;
- }
- else if (damageAmount <= 100)
- {
- parsedDamage = "High";
- color = Color.Red;
- }
- else
- {
- parsedDamage = "Extreme";
- color = Color.DarkRed;
- }
- var groupTitleText = $"{Loc.GetString(
- "health-analyzer-window-damage-group-text",
- ("damageGroup", _prototypes.Index<DamageGroupPrototype>(damageGroupId).LocalizedName),
- ("amount", parsedDamage)
- )}";
- var groupContainer = new BoxContainer
- {
- Align = BoxContainer.AlignMode.Begin,
- Orientation = BoxContainer.LayoutOrientation.Vertical,
- };
- groupContainer.AddChild(CreateDiagnosticGroupTitle(groupTitleText, damageGroupId, color));
- GroupsContainer.AddChild(groupContainer);
- }
- }
- private Texture GetTexture(string texture)
- {
- var rsiPath = new ResPath("/Textures/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, Color color)
- {
- return new Label
- {
- Text = text,
- FontColorOverride = color
- };
- }
- private BoxContainer CreateDiagnosticGroupTitle(string text, string id, Color color)
- {
- var rootContainer = new BoxContainer
- {
- Margin = new Thickness(0, 6, 0, 0),
- VerticalAlignment = VAlignment.Bottom,
- Orientation = BoxContainer.LayoutOrientation.Horizontal,
- };
- rootContainer.AddChild(new TextureRect
- {
- SetSize = new Vector2(30, 30),
- Texture = GetTexture(id.ToLower())
- });
- rootContainer.AddChild(CreateDiagnosticItemLabel(text, color));
- return rootContainer;
- }
- // Shitmed Change Start
- /// <summary>
- /// Sets up the Body Doll using Alert Entity to use in Health Analyzer.
- /// </summary>
- private EntityUid? SetupIcon(Dictionary<TargetBodyPart, TargetIntegrity>? body)
- {
- if (body is null)
- return null;
- if (!_entityManager.Deleted(_spriteViewEntity))
- _entityManager.QueueDeleteEntity(_spriteViewEntity);
- _spriteViewEntity = _entityManager.Spawn(_bodyView);
- if (!_entityManager.TryGetComponent<SpriteComponent>(_spriteViewEntity, out var sprite))
- return null;
- int layer = 0;
- foreach (var (bodyPart, integrity) in body)
- {
- // TODO: PartStatusUIController and make it use layers instead of TextureRects when EE refactors alerts.
- string enumName = Enum.GetName(typeof(TargetBodyPart), bodyPart) ?? "Unknown";
- int enumValue = (int)integrity;
- var rsi = new SpriteSpecifier.Rsi(new ResPath($"/Textures/_Shitmed/Interface/Targeting/Status/{enumName.ToLowerInvariant()}.rsi"), $"{enumName.ToLowerInvariant()}_{enumValue}");
- // Shitcode with love from Russia :)
- if (!sprite.TryGetLayer(layer, out _))
- sprite.AddLayer(_spriteSystem.Frame0(rsi));
- else
- sprite.LayerSetTexture(layer, _spriteSystem.Frame0(rsi));
- sprite.LayerSetScale(layer, new Vector2(3f, 3f));
- layer++;
- }
- return _spriteViewEntity;
- }
- // Shitmed Change End
- }
- }
|