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">
+
-
-
-
+ Margin="0 0 0 5"
+ Orientation="Vertical">
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
+ }
+ ]
+}