Add chemical scanning goggles (#18373)
* add chemical scanning goggles * add prototype and textures * .ftl stuff * add lathe, recipe, research stuff * missing description * emo review * remove static method + newlines --------- Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
This commit is contained in:
@@ -2,12 +2,14 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Content.Server.Chemistry.Components.SolutionManager;
|
using Content.Server.Chemistry.Components.SolutionManager;
|
||||||
|
using Content.Server.Examine;
|
||||||
using Content.Shared.Chemistry;
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Chemistry.Reaction;
|
using Content.Shared.Chemistry.Reaction;
|
||||||
using Content.Shared.Chemistry.Reagent;
|
using Content.Shared.Chemistry.Reagent;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
|
using Content.Shared.Verbs;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -41,6 +43,7 @@ public sealed partial class SolutionContainerSystem : EntitySystem
|
|||||||
|
|
||||||
[Dependency]
|
[Dependency]
|
||||||
private readonly IPrototypeManager _prototypeManager = default!;
|
private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly ExamineSystem _examine = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -48,6 +51,7 @@ public sealed partial class SolutionContainerSystem : EntitySystem
|
|||||||
|
|
||||||
SubscribeLocalEvent<SolutionContainerManagerComponent, ComponentInit>(InitSolution);
|
SubscribeLocalEvent<SolutionContainerManagerComponent, ComponentInit>(InitSolution);
|
||||||
SubscribeLocalEvent<ExaminableSolutionComponent, ExaminedEvent>(OnExamineSolution);
|
SubscribeLocalEvent<ExaminableSolutionComponent, ExaminedEvent>(OnExamineSolution);
|
||||||
|
SubscribeLocalEvent<ExaminableSolutionComponent, GetVerbsEvent<ExamineVerb>>(OnSolutionExaminableVerb);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitSolution(EntityUid uid, SolutionContainerManagerComponent component, ComponentInit args)
|
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<ExamineVerb> 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<ReagentPrototype>(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,
|
private void OnExamineSolution(EntityUid uid, ExaminableSolutionComponent examinableComponent,
|
||||||
ExaminedEvent args)
|
ExaminedEvent args)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Content.Shared.Chemistry.Components;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class SolutionScannerComponent : Component
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
24
Content.Shared/Chemistry/SolutionScannerSystem.cs
Normal file
24
Content.Shared/Chemistry/SolutionScannerSystem.cs
Normal file
@@ -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<SolutionScannerComponent, SolutionScanEvent>(OnSolutionScanAttempt);
|
||||||
|
SubscribeLocalEvent<SolutionScannerComponent, InventoryRelayedEvent<SolutionScanEvent>>((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;
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Shared.Chemistry;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Electrocution;
|
using Content.Shared.Electrocution;
|
||||||
using Content.Shared.Explosion;
|
using Content.Shared.Explosion;
|
||||||
@@ -31,6 +32,7 @@ public partial class InventorySystem
|
|||||||
SubscribeLocalEvent<InventoryComponent, CanSeeAttemptEvent>(RelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, CanSeeAttemptEvent>(RelayInventoryEvent);
|
||||||
SubscribeLocalEvent<InventoryComponent, GetEyeProtectionEvent>(RelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, GetEyeProtectionEvent>(RelayInventoryEvent);
|
||||||
SubscribeLocalEvent<InventoryComponent, GetBlurEvent>(RelayInventoryEvent);
|
SubscribeLocalEvent<InventoryComponent, GetBlurEvent>(RelayInventoryEvent);
|
||||||
|
SubscribeLocalEvent<InventoryComponent, SolutionScanEvent>(RelayInventoryEvent);
|
||||||
|
|
||||||
SubscribeLocalEvent<InventoryComponent, GetVerbsEvent<EquipmentVerb>>(OnGetStrippingVerbs);
|
SubscribeLocalEvent<InventoryComponent, GetVerbsEvent<EquipmentVerb>>(OnGetStrippingVerbs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]
|
||||||
@@ -159,3 +159,15 @@
|
|||||||
coefficients:
|
coefficients:
|
||||||
Heat: 0.95
|
Heat: 0.95
|
||||||
- type: GroupExamine
|
- 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
|
||||||
|
|||||||
@@ -18,3 +18,4 @@
|
|||||||
interfaces:
|
interfaces:
|
||||||
- key: enum.ChameleonUiKey.Key
|
- key: enum.ChameleonUiKey.Key
|
||||||
type: ChameleonBoundUserInterface
|
type: ChameleonBoundUserInterface
|
||||||
|
|
||||||
|
|||||||
@@ -227,6 +227,7 @@
|
|||||||
- ClothingBackpackDuffelHolding
|
- ClothingBackpackDuffelHolding
|
||||||
- WelderExperimental
|
- WelderExperimental
|
||||||
- JawsOfLife
|
- JawsOfLife
|
||||||
|
- ClothingEyesGlassesChemical
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: CircuitImprinter
|
id: CircuitImprinter
|
||||||
|
|||||||
@@ -81,3 +81,13 @@
|
|||||||
materials:
|
materials:
|
||||||
Plastic: 100
|
Plastic: 100
|
||||||
Steel: 250
|
Steel: 250
|
||||||
|
|
||||||
|
- type: latheRecipe
|
||||||
|
id: ClothingEyesGlassesChemical
|
||||||
|
result: ClothingEyesGlassesChemical
|
||||||
|
completetime: 2
|
||||||
|
materials:
|
||||||
|
Steel: 100
|
||||||
|
Plastic: 100
|
||||||
|
Glass: 100
|
||||||
|
Silver: 100
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
- Dropper
|
- Dropper
|
||||||
- HotplateMachineCircuitboard
|
- HotplateMachineCircuitboard
|
||||||
- ChemicalPayload
|
- ChemicalPayload
|
||||||
|
- ClothingEyesGlassesChemical
|
||||||
|
|
||||||
- type: technology
|
- type: technology
|
||||||
id: SurgicalTools
|
id: SurgicalTools
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 374 B |
BIN
Resources/Textures/Clothing/Eyes/Glasses/science.rsi/icon.png
Normal file
BIN
Resources/Textures/Clothing/Eyes/Glasses/science.rsi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 361 B |
Binary file not shown.
|
After Width: | Height: | Size: 317 B |
Binary file not shown.
|
After Width: | Height: | Size: 322 B |
@@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user