diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml index 401f9768629..a096caa4cfd 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml @@ -1,48 +1,64 @@  + MaxHeight="525" + MinWidth="300"> diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs index 0cb3ad144d7..b3b3539c09f 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs @@ -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; @@ -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); @@ -44,8 +49,6 @@ public HealthAnalyzerWindow() public void Populate(HealthAnalyzerScannedUserMessage msg) { - GroupsContainer.RemoveAllChildren(); - var target = _entityManager.GetEntity(msg.TargetEntity); if (target == null @@ -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(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(target.Value) + ? Identity.Name(target.Value, _entityManager) + : Loc.GetString("health-analyzer-window-entity-unknown-text")); + NameLabel.SetMessage(name); + + SpeciesLabel.Text = + _entityManager.TryGetComponent(target.Value, + out var humanoidAppearanceComponent) + ? Loc.GetString(_prototypes.Index(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(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 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 groups, IReadOnlyDictionary damageDict) + Dictionary groups, + IReadOnlyDictionary damageDict) { - HashSet 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; @@ -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, }; @@ -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, " · "))); } } } @@ -198,7 +207,6 @@ private static Label CreateDiagnosticItemLabel(string text) { return new Label { - Margin = new Thickness(2, 2), Text = text, }; } @@ -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()) }); diff --git a/Resources/Changelog/Floof.yml b/Resources/Changelog/Floof.yml index 05cadd4d82c..bec62eda342 100644 --- a/Resources/Changelog/Floof.yml +++ b/Resources/Changelog/Floof.yml @@ -805,3 +805,19 @@ Entries: vampire. id: 110 time: '2024-09-02T03:14:35.0000000+00:00' +- author: Xavier + changes: + - type: Add + message: Pulled Health Analyzer UI updates from Wizden + id: 111 + time: '2024-09-03T20:00:55.0000000+00:00' +- author: Memeji + changes: + - type: Add + message: Red Canine Dildo + - type: Tweak + message: Sex Toys can be recycled and sold. + - type: Tweak + message: Sex Toy Crate price increased to 2000. + id: 112 + time: '2024-09-03T20:08:29.0000000+00:00' diff --git a/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl b/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl index 648db3f4ebd..7a2f8b8c6b7 100644 --- a/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl +++ b/Resources/Locale/en-US/medical/components/health-analyzer-component.ftl @@ -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 @@ -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! \ No newline at end of file diff --git a/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml b/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml index c29ed46a54e..ace97052a11 100644 --- a/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml +++ b/Resources/Prototypes/Catalog/Fills/Lockers/misc.yml @@ -210,6 +210,9 @@ - id: CanineDildo prob: 0.02 orGroup: Lewd + - id: CanineDildoRed + prob: 0.02 + orGroup: Lewd - id: HorseDildo prob: 0.02 orGroup: Lewd @@ -378,6 +381,9 @@ - id: CanineDildo prob: 0.02 orGroup: Lewd + - id: CanineDildoRed + prob: 0.02 + orGroup: Lewd - id: HorseDildo prob: 0.02 orGroup: Lewd diff --git a/Resources/Prototypes/Floof/Catalog/Cargo/cargo_lewd.yml b/Resources/Prototypes/Floof/Catalog/Cargo/cargo_lewd.yml index e871e57d546..f22e4a4734c 100644 --- a/Resources/Prototypes/Floof/Catalog/Cargo/cargo_lewd.yml +++ b/Resources/Prototypes/Floof/Catalog/Cargo/cargo_lewd.yml @@ -4,6 +4,6 @@ sprite: Floof/Objects/Fun/Lewd/lewd_icons.rsi state: dildo product: CrateLewdToys - cost: 1500 + cost: 2000 category: cargoproduct-category-name-fun group: market diff --git a/Resources/Prototypes/Floof/Catalog/Fills/Crates/lewd.yml b/Resources/Prototypes/Floof/Catalog/Fills/Crates/lewd.yml index bbcf58e98d8..559626a760d 100644 --- a/Resources/Prototypes/Floof/Catalog/Fills/Crates/lewd.yml +++ b/Resources/Prototypes/Floof/Catalog/Fills/Crates/lewd.yml @@ -19,6 +19,9 @@ - id: LewdFleshlightYellow - id: AvianDildo - id: CanineDildo + orGroup: canine + - id: CanineDildoRed + orGroup: canine - id: HorseDildo - id: DragonDildo - id: NormalDildo diff --git a/Resources/Prototypes/Floof/Entities/Objects/Lewd/dildos.yml b/Resources/Prototypes/Floof/Entities/Objects/Lewd/dildos.yml index 3eca3afc7ab..453c93a8571 100644 --- a/Resources/Prototypes/Floof/Entities/Objects/Lewd/dildos.yml +++ b/Resources/Prototypes/Floof/Entities/Objects/Lewd/dildos.yml @@ -1,5 +1,16 @@ - type: entity parent: BaseItem + id: BaseDildo + abstract: true + components: + - type: PhysicalComposition + materialComposition: + Plastic: 100 + - type: StaticPrice + price: 75 + +- type: entity + parent: BaseDildo id: AvianDildo name: avian dildo description: A dildo in the shape of a bird's "caw-k". @@ -9,7 +20,7 @@ state: icon - type: entity - parent: BaseItem + parent: BaseDildo id: CanineDildo name: canine dildo description: A dildo of a green rocket. @@ -19,7 +30,17 @@ state: icon - type: entity - parent: BaseItem + parent: BaseDildo + id: CanineDildoRed + name: red canine dildo + description: You'll be seeing stars when you ride THIS red rocket. + components: + - type: Sprite + sprite: Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi + state: icon + +- type: entity + parent: BaseDildo id: HorseDildo name: horse dildo description: A large dildo of a horse... Wow it's big... @@ -29,7 +50,7 @@ state: icon - type: entity - parent: BaseItem + parent: BaseDildo id: DragonDildo name: dragon dildo description: A large red dildo of a dragon... Woof... @@ -39,7 +60,7 @@ state: icon - type: entity - parent: BaseItem + parent: BaseDildo id: NormalDildo name: dildo description: A simple pink dildo. @@ -49,7 +70,7 @@ state: icon - type: entity - parent: BaseItem + parent: BaseDildo id: TentacleDildo name: tentacle dildo description: A floppy tentacle dildo... Is it slimey? @@ -59,7 +80,7 @@ state: icon - type: entity - parent: BaseItem + parent: BaseDildo id: DoubleDildo name: double-sided dildo description: A long dildo with two ends. Bring a friend! diff --git a/Resources/Prototypes/Floof/Entities/Objects/Lewd/fleshlights.yml b/Resources/Prototypes/Floof/Entities/Objects/Lewd/fleshlights.yml index 411566dd3aa..7c4282f8663 100644 --- a/Resources/Prototypes/Floof/Entities/Objects/Lewd/fleshlights.yml +++ b/Resources/Prototypes/Floof/Entities/Objects/Lewd/fleshlights.yml @@ -3,6 +3,11 @@ id: BaseFleshlight abstract: true components: + - type: PhysicalComposition + materialComposition: + Plastic: 100 + - type: StaticPrice + price: 75 - type: Drink solution: fleshlight ignoreEmpty: true diff --git a/Resources/Prototypes/Floof/Entities/Objects/Lewd/vibes.yml b/Resources/Prototypes/Floof/Entities/Objects/Lewd/vibes.yml index 8cfafc2c074..a1d786f7c16 100644 --- a/Resources/Prototypes/Floof/Entities/Objects/Lewd/vibes.yml +++ b/Resources/Prototypes/Floof/Entities/Objects/Lewd/vibes.yml @@ -3,6 +3,12 @@ id: BaseVibe abstract: true components: + - type: PhysicalComposition + materialComposition: + Plastic: 75 + Steel: 25 + - type: StaticPrice + price: 100 - type: ItemToggle predictable: false soundActivate: diff --git a/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/icon.png b/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/icon.png new file mode 100644 index 00000000000..7b61b3ef1ec Binary files /dev/null and b/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/icon.png differ diff --git a/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/inhand-left.png b/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/inhand-left.png new file mode 100644 index 00000000000..68784d18b88 Binary files /dev/null and b/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/inhand-left.png differ diff --git a/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/inhand-right.png b/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/inhand-right.png new file mode 100644 index 00000000000..e1ed1e4672d Binary files /dev/null and b/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/inhand-right.png differ diff --git a/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/meta.json b/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/meta.json new file mode 100644 index 00000000000..10d531ab7d3 --- /dev/null +++ b/Resources/Textures/Floof/Objects/Fun/Lewd/Toys/Dildos/dildo_canine_red.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Splurtstation (https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13). Edited by Memeji", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +}