diff --git a/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs index fa33309f58..61da862be9 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionContainerSystem.cs @@ -2,12 +2,14 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using Content.Server.Chemistry.Components.SolutionManager; +using Content.Server.Examine; using Content.Shared.Chemistry; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reagent; using Content.Shared.Examine; using Content.Shared.FixedPoint; +using Content.Shared.Verbs; using JetBrains.Annotations; using Robust.Shared.Audio; using Robust.Shared.Prototypes; @@ -41,6 +43,7 @@ public sealed partial class SolutionContainerSystem : EntitySystem [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly ExamineSystem _examine = default!; public override void Initialize() { @@ -48,6 +51,7 @@ public sealed partial class SolutionContainerSystem : EntitySystem SubscribeLocalEvent(InitSolution); SubscribeLocalEvent(OnExamineSolution); + SubscribeLocalEvent>(OnSolutionExaminableVerb); } private void InitSolution(EntityUid uid, SolutionContainerManagerComponent component, ComponentInit args) @@ -60,6 +64,69 @@ public sealed partial class SolutionContainerSystem : EntitySystem } } + private void OnSolutionExaminableVerb(EntityUid uid, ExaminableSolutionComponent component, GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess) + return; + + var scanEvent = new SolutionScanEvent(); + RaiseLocalEvent(args.User, scanEvent); + if (!scanEvent.CanScan) + { + return; + } + + SolutionContainerManagerComponent? solutionsManager = null; + if (!Resolve(args.Target, ref solutionsManager) + || !solutionsManager.Solutions.TryGetValue(component.Solution, out var solutionHolder)) + { + return; + } + + var verb = new ExamineVerb() + { + Act = () => + { + var markup = GetSolutionExamine(solutionHolder); + _examine.SendExamineTooltip(args.User, uid, markup, false, false); + }, + Text = Loc.GetString("scannable-solution-verb-text"), + Message = Loc.GetString("scannable-solution-verb-message"), + Category = VerbCategory.Examine, + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/drink.svg.192dpi.png")), + }; + + args.Verbs.Add(verb); + } + + private FormattedMessage GetSolutionExamine(Solution solution) + { + var msg = new FormattedMessage(); + + if (solution.Contents.Count == 0) //TODO: better way to see if empty? + { + msg.AddMarkup(Loc.GetString("scannable-solution-empty-container")); + return msg; + } + + msg.AddMarkup(Loc.GetString("scannable-solution-main-text")); + + foreach (var reagent in solution) + { + if (!_prototypeManager.TryIndex(reagent.ReagentId, out var proto)) + { + continue; + } + msg.PushNewline(); + msg.AddMarkup(Loc.GetString("scannable-solution-chemical" + , ("type", proto.LocalizedName) + , ("color", proto.SubstanceColor.ToHexNoAlpha()) + , ("amount", reagent.Quantity))); + } + + return msg; + } + private void OnExamineSolution(EntityUid uid, ExaminableSolutionComponent examinableComponent, ExaminedEvent args) { diff --git a/Content.Shared/Chemistry/Components/SolutionScannerComponent.cs b/Content.Shared/Chemistry/Components/SolutionScannerComponent.cs new file mode 100644 index 0000000000..12f9ebdc6d --- /dev/null +++ b/Content.Shared/Chemistry/Components/SolutionScannerComponent.cs @@ -0,0 +1,7 @@ +namespace Content.Shared.Chemistry.Components; + +[RegisterComponent] +public sealed class SolutionScannerComponent : Component +{ +} + diff --git a/Content.Shared/Chemistry/SolutionScannerSystem.cs b/Content.Shared/Chemistry/SolutionScannerSystem.cs new file mode 100644 index 0000000000..0e6d784777 --- /dev/null +++ b/Content.Shared/Chemistry/SolutionScannerSystem.cs @@ -0,0 +1,24 @@ +using Content.Shared.Chemistry.Components; +using Content.Shared.Inventory; + +namespace Content.Shared.Chemistry; + +public sealed class SolutionScannerSystem : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent(OnSolutionScanAttempt); + SubscribeLocalEvent>((e, c, ev) => OnSolutionScanAttempt(e, c, ev.Args)); + } + + private void OnSolutionScanAttempt(EntityUid eid, SolutionScannerComponent component, SolutionScanEvent args) + { + args.CanScan = true; + } +} + +public sealed class SolutionScanEvent : EntityEventArgs, IInventoryRelayEvent +{ + public bool CanScan; + public SlotFlags TargetSlots { get; } = SlotFlags.EYES; +} diff --git a/Content.Shared/Inventory/InventorySystem.Relay.cs b/Content.Shared/Inventory/InventorySystem.Relay.cs index 3a79258971..179d234ce5 100644 --- a/Content.Shared/Inventory/InventorySystem.Relay.cs +++ b/Content.Shared/Inventory/InventorySystem.Relay.cs @@ -1,3 +1,4 @@ +using Content.Shared.Chemistry; using Content.Shared.Damage; using Content.Shared.Electrocution; using Content.Shared.Explosion; @@ -31,6 +32,7 @@ public partial class InventorySystem SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent>(OnGetStrippingVerbs); } diff --git a/Resources/Locale/en-US/chemistry/components/solution-scanner-component.ftl b/Resources/Locale/en-US/chemistry/components/solution-scanner-component.ftl new file mode 100644 index 0000000000..8dbbaf3edd --- /dev/null +++ b/Resources/Locale/en-US/chemistry/components/solution-scanner-component.ftl @@ -0,0 +1,5 @@ +scannable-solution-verb-text = Solution +scannable-solution-verb-message = Examine the chemical composition. +scannable-solution-main-text = It contains the following chemicals: +scannable-solution-empty-container = It contains no chemicals. +scannable-solution-chemical = - {$amount}u [color={$color}]{$type}[/color] diff --git a/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml b/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml index 93a3ec443d..ba7823c1fb 100644 --- a/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml +++ b/Resources/Prototypes/Entities/Clothing/Eyes/glasses.yml @@ -159,3 +159,15 @@ coefficients: Heat: 0.95 - type: GroupExamine + +- type: entity + parent: ClothingEyesBase + id: ClothingEyesGlassesChemical + name: chemical analysis goggles + description: Goggles that can scan the chemical composition of a solution. + components: + - type: Sprite + sprite: Clothing/Eyes/Glasses/science.rsi + - type: Clothing + sprite: Clothing/Eyes/Glasses/science.rsi + - type: SolutionScanner diff --git a/Resources/Prototypes/Entities/Clothing/Eyes/specific.yml b/Resources/Prototypes/Entities/Clothing/Eyes/specific.yml index a213ca21cd..c04f348287 100644 --- a/Resources/Prototypes/Entities/Clothing/Eyes/specific.yml +++ b/Resources/Prototypes/Entities/Clothing/Eyes/specific.yml @@ -18,3 +18,4 @@ interfaces: - key: enum.ChameleonUiKey.Key type: ChameleonBoundUserInterface + diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 86057f2e01..7967cd4815 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -227,6 +227,7 @@ - ClothingBackpackDuffelHolding - WelderExperimental - JawsOfLife + - ClothingEyesGlassesChemical - type: entity id: CircuitImprinter diff --git a/Resources/Prototypes/Recipes/Lathes/chemistry.yml b/Resources/Prototypes/Recipes/Lathes/chemistry.yml index e2285e9be8..3d654b96f3 100644 --- a/Resources/Prototypes/Recipes/Lathes/chemistry.yml +++ b/Resources/Prototypes/Recipes/Lathes/chemistry.yml @@ -81,3 +81,13 @@ materials: Plastic: 100 Steel: 250 + +- type: latheRecipe + id: ClothingEyesGlassesChemical + result: ClothingEyesGlassesChemical + completetime: 2 + materials: + Steel: 100 + Plastic: 100 + Glass: 100 + Silver: 100 diff --git a/Resources/Prototypes/Research/biochemical.yml b/Resources/Prototypes/Research/biochemical.yml index b0b1d1ddea..00389d073d 100644 --- a/Resources/Prototypes/Research/biochemical.yml +++ b/Resources/Prototypes/Research/biochemical.yml @@ -14,6 +14,7 @@ - Dropper - HotplateMachineCircuitboard - ChemicalPayload + - ClothingEyesGlassesChemical - type: technology id: SurgicalTools diff --git a/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/equipped-EYES.png b/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/equipped-EYES.png new file mode 100644 index 0000000000..dd921481b7 Binary files /dev/null and b/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/equipped-EYES.png differ diff --git a/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/icon.png b/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/icon.png new file mode 100644 index 0000000000..af3788654b Binary files /dev/null and b/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/icon.png differ diff --git a/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/inhand-left.png b/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/inhand-left.png new file mode 100644 index 0000000000..5088632f8d Binary files /dev/null and b/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/inhand-left.png differ diff --git a/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/inhand-right.png b/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/inhand-right.png new file mode 100644 index 0000000000..14f7b4547f Binary files /dev/null and b/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/inhand-right.png differ diff --git a/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/meta.json b/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/meta.json new file mode 100644 index 0000000000..541bdfbedc --- /dev/null +++ b/Resources/Textures/Clothing/Eyes/Glasses/science.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/5a73e8f825ff279e82949b9329783a9e3070e2da", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-EYES", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +}