diff --git a/Content.Shared/Chemistry/Components/SolutionManager/ExaminableSolutionComponent.cs b/Content.Shared/Chemistry/Components/SolutionManager/ExaminableSolutionComponent.cs
index 1abe81180c..913622e19d 100644
--- a/Content.Shared/Chemistry/Components/SolutionManager/ExaminableSolutionComponent.cs
+++ b/Content.Shared/Chemistry/Components/SolutionManager/ExaminableSolutionComponent.cs
@@ -1,14 +1,70 @@
-namespace Content.Shared.Chemistry.Components.SolutionManager;
+using Content.Shared.Nutrition.Components;
+using Robust.Shared.Serialization;
+namespace Content.Shared.Chemistry.Components.SolutionManager;
+
+///
+/// Component for examining a solution with shift click or through .
+///
[RegisterComponent]
public sealed partial class ExaminableSolutionComponent : Component
{
- [DataField, ViewVariables(VVAccess.ReadWrite)]
+ ///
+ /// The solution being examined.
+ ///
+ [DataField]
public string Solution = "default";
///
- /// If false then the hidden solution is always visible.
+ /// If true, the solution must be held to be examined.
///
[DataField]
public bool HeldOnly;
+
+ ///
+ /// If false, the examine text will give an approximation of the remaining solution.
+ /// If true, the exact unit count will be shown.
+ ///
+ [DataField]
+ public bool ExactVolume;
+
+ ///
+ /// If false, the solution can't be examined when this entity is closed by .
+ ///
+ [DataField]
+ public bool ExaminableWhileClosed = true;
+
+ ///
+ /// Examine text for the amount of solution.
+ ///
+ ///
+ [DataField]
+ public LocId LocVolume = "examinable-solution-on-examine-volume";
+
+ ///
+ /// Examine text for the physical description of the primary reagent.
+ ///
+ [DataField]
+ public LocId LocPhysicalQuality = "shared-solution-container-component-on-examine-main-text";
+
+ ///
+ /// Examine text for reagents that are obvious like water.
+ ///
+ [DataField]
+ public LocId LocRecognizableReagents = "examinable-solution-has-recognizable-chemicals";
+}
+
+///
+/// Used to choose how to display a volume.
+///
+[Serializable, NetSerializable]
+public enum ExaminedVolumeDisplay
+{
+ Exact,
+ Full,
+ MostlyFull,
+ HalfFull,
+ HalfEmpty,
+ MostlyEmpty,
+ Empty,
}
diff --git a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.Capabilities.cs b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.Capabilities.cs
index ffdb608875..cc511f8db9 100644
--- a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.Capabilities.cs
+++ b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.Capabilities.cs
@@ -1,9 +1,7 @@
using Content.Shared.Chemistry.Components;
using Content.Shared.Kitchen.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
-using Content.Shared.Chemistry.Reaction;
using Content.Shared.FixedPoint;
-using Robust.Shared.Utility;
using System.Diagnostics.CodeAnalysis;
using System.Text;
@@ -139,12 +137,13 @@ public abstract partial class SharedSolutionContainerSystem
#endregion Solution Modifiers
+ /// A value between 0 and 100 inclusive.
public float PercentFull(EntityUid uid)
{
- if (!TryGetDrainableSolution(uid, out _, out var solution) || solution.MaxVolume.Equals(FixedPoint2.Zero))
+ if (!TryGetDrainableSolution(uid, out _, out var solution))
return 0;
- return solution.FillFraction * 100;
+ return PercentFull(solution);
}
#region Static Methods
@@ -175,5 +174,14 @@ public abstract partial class SharedSolutionContainerSystem
return sb.ToString();
}
+ /// A value between 0 and 100 inclusive.
+ public static float PercentFull(Solution sol)
+ {
+ if (sol.MaxVolume.Equals(FixedPoint2.Zero))
+ return 0;
+
+ return sol.FillFraction * 100;
+ }
+
#endregion Static Methods
}
diff --git a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs
index 5cc12a9b69..54210cf195 100644
--- a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs
+++ b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs
@@ -12,6 +12,9 @@ using Content.Shared.Examine;
using Content.Shared.FixedPoint;
using Content.Shared.Hands.Components;
using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Localizations;
+using Content.Shared.Nutrition.Components;
+using Content.Shared.Nutrition.EntitySystems;
using Content.Shared.Verbs;
using JetBrains.Annotations;
using Robust.Shared.Containers;
@@ -61,14 +64,15 @@ public partial record struct SolutionAccessAttemptEvent(string SolutionName)
[UsedImplicitly]
public abstract partial class SharedSolutionContainerSystem : EntitySystem
{
- [Robust.Shared.IoC.Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
- [Robust.Shared.IoC.Dependency] protected readonly ChemicalReactionSystem ChemicalReactionSystem = default!;
- [Robust.Shared.IoC.Dependency] protected readonly ExamineSystemShared ExamineSystem = default!;
- [Robust.Shared.IoC.Dependency] protected readonly SharedAppearanceSystem AppearanceSystem = default!;
- [Robust.Shared.IoC.Dependency] protected readonly SharedHandsSystem Hands = default!;
- [Robust.Shared.IoC.Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
- [Robust.Shared.IoC.Dependency] protected readonly MetaDataSystem MetaDataSys = default!;
- [Robust.Shared.IoC.Dependency] protected readonly INetManager NetManager = default!;
+ [Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
+ [Dependency] protected readonly ChemicalReactionSystem ChemicalReactionSystem = default!;
+ [Dependency] protected readonly ExamineSystemShared ExamineSystem = default!;
+ [Dependency] protected readonly OpenableSystem Openable = default!;
+ [Dependency] protected readonly SharedAppearanceSystem AppearanceSystem = default!;
+ [Dependency] protected readonly SharedHandsSystem Hands = default!;
+ [Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
+ [Dependency] protected readonly MetaDataSystem MetaDataSys = default!;
+ [Dependency] protected readonly INetManager NetManager = default!;
public override void Initialize()
{
@@ -791,52 +795,55 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
}
}
+ ///
+ /// Shift click examine.
+ ///
private void OnExamineSolution(Entity entity, ref ExaminedEvent args)
{
- if (!TryGetSolution(entity.Owner, entity.Comp.Solution, out _, out var solution))
- {
+ if (!args.IsInDetailsRange ||
+ !CanSeeHiddenSolution(entity, args.Examiner) ||
+ !TryGetSolution(entity.Owner, entity.Comp.Solution, out _, out var solution))
return;
- }
-
- if (!CanSeeHiddenSolution(entity, args.Examiner))
- return;
-
- var primaryReagent = solution.GetPrimaryReagentId();
-
- if (string.IsNullOrEmpty(primaryReagent?.Prototype))
- {
- args.PushText(Loc.GetString("shared-solution-container-component-on-examine-empty-container"));
- return;
- }
-
- if (!PrototypeManager.TryIndex(primaryReagent.Value.Prototype, out ReagentPrototype? primary))
- {
- Log.Error($"{nameof(Solution)} could not find the prototype associated with {primaryReagent}.");
- return;
- }
-
- var colorHex = solution.GetColor(PrototypeManager)
- .ToHexNoAlpha(); //TODO: If the chem has a dark color, the examine text becomes black on a black background, which is unreadable.
- var messageString = "shared-solution-container-component-on-examine-main-text";
using (args.PushGroup(nameof(ExaminableSolutionComponent)))
{
- args.PushMarkup(Loc.GetString(messageString,
- ("color", colorHex),
- ("wordedAmount", Loc.GetString(solution.Contents.Count == 1
- ? "shared-solution-container-component-on-examine-worded-amount-one-reagent"
- : "shared-solution-container-component-on-examine-worded-amount-multiple-reagents")),
- ("desc", primary.LocalizedPhysicalDescription)));
- var reagentPrototypes = solution.GetReagentPrototypes(PrototypeManager);
+ var primaryReagent = solution.GetPrimaryReagentId();
+
+ // If there's no primary reagent, assume the solution is empty and exit early
+ if (string.IsNullOrEmpty(primaryReagent?.Prototype) ||
+ !PrototypeManager.Resolve(primaryReagent.Value.Prototype, out var primary))
+ {
+ args.PushMarkup(Loc.GetString(entity.Comp.LocVolume, ("fillLevel", ExaminedVolumeDisplay.Empty)));
+ return;
+ }
+
+ // Push amount of reagent
+
+ args.PushMarkup(Loc.GetString(entity.Comp.LocVolume,
+ ("fillLevel", ExaminedVolume(entity, solution, args.Examiner)),
+ ("current", solution.Volume),
+ ("max", solution.MaxVolume)));
+
+ // Push the physical description of the primary reagent
+
+ var colorHex = solution.GetColor(PrototypeManager)
+ .ToHexNoAlpha(); //TODO: If the chem has a dark color, the examine text becomes black on a black background, which is unreadable.
+
+ args.PushMarkup(Loc.GetString(entity.Comp.LocPhysicalQuality,
+ ("color", colorHex),
+ ("desc", primary.LocalizedPhysicalDescription),
+ ("chemCount", solution.Contents.Count) ));
+
+ // Push the recognizable reagents
// Sort the reagents by amount, descending then alphabetically
- var sortedReagentPrototypes = reagentPrototypes
+ var sortedReagentPrototypes = solution.GetReagentPrototypes(PrototypeManager)
.OrderByDescending(pair => pair.Value.Value)
.ThenBy(pair => pair.Key.LocalizedName);
- // Add descriptions of immediately recognizable reagents, like water or beer
- var recognized = new List();
+ // Collect recognizable reagents, like water or beer
+ var recognized = new List();
foreach (var keyValuePair in sortedReagentPrototypes)
{
var proto = keyValuePair.Key;
@@ -845,41 +852,58 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
continue;
}
- recognized.Add(proto);
+ recognized.Add(Loc.GetString("examinable-solution-recognized",
+ ("color", proto.SubstanceColor.ToHexNoAlpha()),
+ ("chemical", proto.LocalizedName)));
}
- // Skip if there's nothing recognizable
if (recognized.Count == 0)
return;
- var msg = new StringBuilder();
- foreach (var reagent in recognized)
- {
- string part;
- if (reagent == recognized[0])
- {
- part = "examinable-solution-recognized-first";
- }
- else if (reagent == recognized[^1])
- {
- // this loc specifically requires space to be appended, fluent doesnt support whitespace
- msg.Append(' ');
- part = "examinable-solution-recognized-last";
- }
- else
- {
- part = "examinable-solution-recognized-next";
- }
+ var msg = ContentLocalizationManager.FormatList(recognized);
- msg.Append(Loc.GetString(part, ("color", reagent.SubstanceColor.ToHexNoAlpha()),
- ("chemical", reagent.LocalizedName)));
- }
-
- args.PushMarkup(Loc.GetString("examinable-solution-has-recognizable-chemicals",
- ("recognizedString", msg.ToString())));
+ // Finally push the full message
+ args.PushMarkup(Loc.GetString(entity.Comp.LocRecognizableReagents,
+ ("recognizedString", msg)));
}
}
+ /// An enum for how to display the solution.
+ public ExaminedVolumeDisplay ExaminedVolume(Entity ent, Solution sol, EntityUid? examiner = null)
+ {
+ // Exact measurement
+ if (ent.Comp.ExactVolume)
+ return ExaminedVolumeDisplay.Exact;
+
+ // General approximation
+ return (int)PercentFull(sol) switch
+ {
+ 100 => ExaminedVolumeDisplay.Full,
+ > 66 => ExaminedVolumeDisplay.MostlyFull,
+ > 33 => HalfEmptyOrHalfFull(examiner),
+ > 0 => ExaminedVolumeDisplay.MostlyEmpty,
+ _ => ExaminedVolumeDisplay.Empty,
+ };
+ }
+
+ // Some spessmen see half full, some see half empty, but always the same one.
+ private ExaminedVolumeDisplay HalfEmptyOrHalfFull(EntityUid? examiner = null)
+ {
+ // Optimistic when un-observed
+ if (examiner == null)
+ return ExaminedVolumeDisplay.HalfFull;
+
+ var meta = MetaData(examiner.Value);
+ if (meta.EntityName.Length > 0 &&
+ string.Compare(meta.EntityName.Substring(0, 1), "m", StringComparison.InvariantCultureIgnoreCase) > 0)
+ return ExaminedVolumeDisplay.HalfFull;
+
+ return ExaminedVolumeDisplay.HalfEmpty;
+ }
+
+ ///
+ /// Full reagent scan, such as with chemical analysis goggles.
+ ///
private void OnSolutionExaminableVerb(Entity entity, ref GetVerbsEvent args)
{
if (!args.CanInteract || !args.CanAccess)
@@ -953,15 +977,18 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
}
///
- /// Check if examinable solution requires you to hold the item in hand.
+ /// Check if an examinable solution is hidden by something.
///
private bool CanSeeHiddenSolution(Entity entity, EntityUid examiner)
{
// If not held-only then it's always visible.
- if (!entity.Comp.HeldOnly)
- return true;
+ if (entity.Comp.HeldOnly && !Hands.IsHolding(examiner, entity, out _))
+ return false;
- return Hands.IsHolding(examiner, entity, out _);
+ if (!entity.Comp.ExaminableWhileClosed && Openable.IsClosed(entity.Owner, predicted: true))
+ return false;
+
+ return true;
}
private void OnMapInit(Entity entity, ref MapInitEvent args)
diff --git a/Content.Shared/Nutrition/Components/DrinkComponent.cs b/Content.Shared/Nutrition/Components/DrinkComponent.cs
index 17baaef5a3..2211d58071 100644
--- a/Content.Shared/Nutrition/Components/DrinkComponent.cs
+++ b/Content.Shared/Nutrition/Components/DrinkComponent.cs
@@ -24,9 +24,6 @@ public sealed partial class DrinkComponent : Component
[DataField, AutoNetworkedField]
public float Delay = 1;
- [DataField, AutoNetworkedField]
- public bool Examinable = true;
-
///
/// If true, trying to drink when empty will not handle the event.
/// This means other systems such as equipping on use can run.
diff --git a/Content.Shared/Nutrition/EntitySystems/SharedDrinkSystem.cs b/Content.Shared/Nutrition/EntitySystems/SharedDrinkSystem.cs
index a4b8e13b2f..66e4834d0d 100644
--- a/Content.Shared/Nutrition/EntitySystems/SharedDrinkSystem.cs
+++ b/Content.Shared/Nutrition/EntitySystems/SharedDrinkSystem.cs
@@ -37,7 +37,6 @@ public abstract partial class SharedDrinkSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent(OnAttemptShake);
- SubscribeLocalEvent(OnExamined);
SubscribeLocalEvent>(AddDrinkVerb);
}
@@ -47,38 +46,6 @@ public abstract partial class SharedDrinkSystem : EntitySystem
args.Cancelled = true;
}
- protected void OnExamined(Entity entity, ref ExaminedEvent args)
- {
- TryComp(entity, out var openable);
- if (_openable.IsClosed(entity.Owner, null, openable, true) || !args.IsInDetailsRange || !entity.Comp.Examinable)
- return;
-
- var empty = IsEmpty(entity, entity.Comp);
- if (empty)
- {
- args.PushMarkup(Loc.GetString("drink-component-on-examine-is-empty"));
- return;
- }
-
- if (HasComp(entity))
- {
- //provide exact measurement for beakers
- args.PushText(Loc.GetString("drink-component-on-examine-exact-volume", ("amount", DrinkVolume(entity, entity.Comp))));
- }
- else
- {
- //general approximation
- var remainingString = (int) _solutionContainer.PercentFull(entity) switch
- {
- 100 => "drink-component-on-examine-is-full",
- > 66 => "drink-component-on-examine-is-mostly-full",
- > 33 => HalfEmptyOrHalfFull(args),
- _ => "drink-component-on-examine-is-mostly-empty",
- };
- args.PushMarkup(Loc.GetString(remainingString));
- }
- }
-
private void AddDrinkVerb(Entity entity, ref GetVerbsEvent ev)
{
if (entity.Owner == ev.User ||
@@ -130,18 +97,6 @@ public abstract partial class SharedDrinkSystem : EntitySystem
return DrinkVolume(uid, component) <= 0;
}
- // some see half empty, and others see half full
- private string HalfEmptyOrHalfFull(ExaminedEvent args)
- {
- string remainingString = "drink-component-on-examine-is-half-full";
-
- if (TryComp(args.Examiner, out MetaDataComponent? examiner) && examiner.EntityName.Length > 0
- && string.Compare(examiner.EntityName.Substring(0, 1), "m", StringComparison.InvariantCultureIgnoreCase) > 0)
- remainingString = "drink-component-on-examine-is-half-empty";
-
- return remainingString;
- }
-
///
/// Tries to feed the drink item to the target entity
///
diff --git a/Resources/Locale/en-US/chemistry/solution/components/shared-solution-container-component.ftl b/Resources/Locale/en-US/chemistry/solution/components/shared-solution-container-component.ftl
index 6f1ba911f7..dd78281b89 100644
--- a/Resources/Locale/en-US/chemistry/solution/components/shared-solution-container-component.ftl
+++ b/Resources/Locale/en-US/chemistry/solution/components/shared-solution-container-component.ftl
@@ -1,9 +1,37 @@
-shared-solution-container-component-on-examine-empty-container = Contains no chemicals.
-shared-solution-container-component-on-examine-main-text = It contains {INDEFINITE($desc)} [color={$color}]{$desc}[/color] {$wordedAmount}
-shared-solution-container-component-on-examine-worded-amount-one-reagent = chemical.
-shared-solution-container-component-on-examine-worded-amount-multiple-reagents = mixture of chemicals.
+shared-solution-container-component-on-examine-main-text = It contains {INDEFINITE($desc)} [color={$color}]{$desc}[/color] { $chemCount ->
+ [1] chemical.
+ *[other] mixture of chemicals.
+ }
examinable-solution-has-recognizable-chemicals = You can recognize {$recognizedString} in the solution.
-examinable-solution-recognized-first = [color={$color}]{$chemical}[/color]
-examinable-solution-recognized-next = , [color={$color}]{$chemical}[/color]
-examinable-solution-recognized-last = and [color={$color}]{$chemical}[/color]
+examinable-solution-recognized = [color={$color}]{$chemical}[/color]
+
+examinable-solution-on-examine-volume = The contained solution is { $fillLevel ->
+ [exact] holding [color=white]{$current}/{$max}u[/color].
+ *[other] [bold]{ -solution-vague-fill-level(fillLevel: $fillLevel) }[/bold].
+}
+
+examinable-solution-on-examine-volume-no-max = The contained solution is { $fillLevel ->
+ [exact] holding [color=white]{$current}u[/color].
+ *[other] [bold]{ -solution-vague-fill-level(fillLevel: $fillLevel) }[/bold].
+}
+
+examinable-solution-on-examine-volume-puddle = The puddle is { $fillLevel ->
+ [exact] [color=white]{$current}u[/color].
+ [full] huge and overflowing!
+ [mostlyfull] huge and overflowing!
+ [halffull] deep and flowing.
+ [halfempty] very deep.
+ *[mostlyempty] pooling together.
+ [empty] forming multiple small pools.
+}
+
+-solution-vague-fill-level =
+ { $fillLevel ->
+ [full] [color=white]Full[/color]
+ [mostlyfull] [color=#DFDFDF]Mostly Full[/color]
+ [halffull] [color=#C8C8C8]Half Full[/color]
+ [halfempty] [color=#C8C8C8]Half Empty[/color]
+ [mostlyempty] [color=#A4A4A4]Mostly Empty[/color]
+ *[empty] [color=gray]Empty[/color]
+ }
diff --git a/Resources/Locale/en-US/nutrition/components/drink-component.ftl b/Resources/Locale/en-US/nutrition/components/drink-component.ftl
index e80787c8d5..ab458746dd 100644
--- a/Resources/Locale/en-US/nutrition/components/drink-component.ftl
+++ b/Resources/Locale/en-US/nutrition/components/drink-component.ftl
@@ -1,14 +1,7 @@
drink-component-on-use-is-empty = {CAPITALIZE(THE($owner))} is empty!
-drink-component-on-examine-is-empty = [color=gray]Empty[/color]
drink-component-on-examine-is-opened = [color=yellow]Opened[/color]
drink-component-on-examine-is-sealed = The seal is intact.
drink-component-on-examine-is-unsealed = The seal is broken.
-drink-component-on-examine-is-full = Full
-drink-component-on-examine-is-mostly-full = Mostly Full
-drink-component-on-examine-is-half-full = Halfway Full
-drink-component-on-examine-is-half-empty = Halfway Empty
-drink-component-on-examine-is-mostly-empty = Mostly Empty
-drink-component-on-examine-exact-volume = It contains {$amount}u.
drink-component-try-use-drink-not-open = Open {$owner} first!
drink-component-try-use-drink-is-empty = {CAPITALIZE(THE($entity))} is empty!
drink-component-try-use-drink-cannot-drink = You can't drink anything!
diff --git a/Resources/Prototypes/Entities/Clothing/Back/specific.yml b/Resources/Prototypes/Entities/Clothing/Back/specific.yml
index d303aa166c..005dfedba5 100644
--- a/Resources/Prototypes/Entities/Clothing/Back/specific.yml
+++ b/Resources/Prototypes/Entities/Clothing/Back/specific.yml
@@ -75,6 +75,7 @@
solution: tank
- type: ExaminableSolution
solution: tank
+ exactVolume: true
- type: entity
parent: ClothingBackpack
diff --git a/Resources/Prototypes/Entities/Effects/puddle.yml b/Resources/Prototypes/Entities/Effects/puddle.yml
index a426e7aa1c..1b84dcd7d0 100644
--- a/Resources/Prototypes/Entities/Effects/puddle.yml
+++ b/Resources/Prototypes/Entities/Effects/puddle.yml
@@ -205,9 +205,9 @@
delay: 3
transferAmount: 1
solution: puddle
- examinable: false
- type: ExaminableSolution
solution: puddle
+ locVolume: "examinable-solution-on-examine-volume-puddle"
- type: DrawableSolution
solution: puddle
- type: BadDrink
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks-cartons.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks-cartons.yml
index c33e24ad3e..834a2c3a8e 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks-cartons.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks-cartons.yml
@@ -17,6 +17,8 @@
maxVol: 50
- type: PressurizedSolution
solution: drink
+ - type: ExaminableSolution
+ examinableWhileClosed: false
- type: Shakeable
- type: Sprite
state: icon
@@ -194,7 +196,7 @@
Quantity: 100
- type: Sprite
sprite: Objects/Consumable/Drinks/oatmilk.rsi
-
+
- type: entity
parent: [DrinkCartonVisualsOpenable, DrinkCartonBaseFull]
id: DrinkJuiceLemonCarton
@@ -209,7 +211,7 @@
Quantity: 50
- type: Sprite
sprite: Objects/Consumable/Drinks/lemonjuice.rsi
-
+
- type: entity
parent: [DrinkCartonVisualsOpenable, DrinkCartonBaseFull]
id: DrinkJuicePineappleCarton
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml
index aff0aa7a05..2d8fadfa43 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml
@@ -31,6 +31,8 @@
solution: drink
- type: DrainableSolution
solution: drink
+ - type: ExaminableSolution
+ solution: drink
- type: UserInterface
interfaces:
enum.TransferAmountUiKey.Key:
@@ -75,8 +77,6 @@
- type: PhysicalComposition
materialComposition:
Glass: 25
- - type: ExaminableSolution
- solution: drink
- type: FitsInDispenser
solution: drink
- type: Tag
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml
index c2ac4c606f..d432c6d9d5 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_bottles.yml
@@ -192,6 +192,8 @@
layers:
- state: icon
map: ["enum.OpenableVisuals.Layer"]
+ - type: ExaminableSolution
+ examinableWhileClosed: false # If you can't see fill levels, it's probably opaque
- type: entity
id: DrinkBottleVisualsAll
@@ -217,6 +219,7 @@
fillBaseName: fill-
inHandsMaxFillLevels: 3
inHandsFillBaseName: -fill-
+ - type: ExaminableSolution
# Large Glass Bottles
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml
index d933cbcd1b..e6ba0d002e 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml
@@ -46,6 +46,9 @@
solution: drink
- type: PressurizedSolution
solution: drink
+ - type: ExaminableSolution
+ solution: drink
+ examinableWhileClosed: false
- type: Appearance
- type: GenericVisualizer
visuals:
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml
index 842cf13641..d5bfdefe48 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cups.yml
@@ -20,6 +20,8 @@
solution: drink
- type: DrainableSolution
solution: drink
+ - type: ExaminableSolution
+ solution: drink
- type: SolutionTransfer
canChangeTransferAmount: true
maxTransferAmount: 10
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml
index 9e1b100dbf..8f3b9381f7 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_flasks.yml
@@ -15,6 +15,8 @@
Steel: 300
- type: FitsInDispenser
solution: drink
+ - type: ExaminableSolution
+ examinableWhileClosed: false
- type: entity
id: DrinkFlaskVisualsOpenable
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_special.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_special.yml
index 02a4346ebc..e7aa6c1252 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_special.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_special.yml
@@ -41,6 +41,10 @@
mixOnInteract: false
reactionTypes:
- Shake
+ - type: ExaminableSolution
+ solution: drink
+ heldOnly: true
+ examinableWhileClosed: false
- type: entity
parent: DrinkGlassBase
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/condiments.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/condiments.yml
index c7de98b4a4..7c7df07f78 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/condiments.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/Containers/condiments.yml
@@ -9,6 +9,8 @@
solution: food
- type: DrainableSolution
solution: food
+ - type: ExaminableSolution
+ solution: food
- type: Sprite
sprite: Objects/Consumable/Food/condiments.rsi
- type: Icon
@@ -69,6 +71,8 @@
- type: Tag
tags:
- Packet
+ - type: ExaminableSolution
+ exactVolume: true
- type: entity
parent: BaseFoodCondimentPacket
diff --git a/Resources/Prototypes/Entities/Objects/Misc/arabianlamp.yml b/Resources/Prototypes/Entities/Objects/Misc/arabianlamp.yml
index 2b1c2940fe..2a289a95f8 100644
--- a/Resources/Prototypes/Entities/Objects/Misc/arabianlamp.yml
+++ b/Resources/Prototypes/Entities/Objects/Misc/arabianlamp.yml
@@ -110,6 +110,8 @@
solution: Welder
- type: ExaminableSolution
solution: Welder
+ heldOnly: true
+ exactVolume: true
- type: SolutionRegeneration
solution: Welder
generated:
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml
index b692f20dd9..9ed5972754 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/spray.yml
@@ -42,6 +42,7 @@
solution: spray
- type: ExaminableSolution
solution: spray
+ exactVolume: true
- type: entity
name: mega spray bottle
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
index bd8e78dd9a..bc0cf16e8e 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/hypospray.yml
@@ -22,6 +22,7 @@
solution: hypospray
- type: ExaminableSolution
solution: hypospray
+ exactVolume: true
- type: Hypospray
onlyAffectsMobs: false
- type: UseDelay
@@ -63,6 +64,7 @@
solution: hypospray
- type: ExaminableSolution
solution: hypospray
+ exactVolume: true
- type: Hypospray
onlyAffectsMobs: false
- type: UseDelay
@@ -142,6 +144,7 @@
maxVol: 15
- type: ExaminableSolution
solution: pen
+ exactVolume: true
- type: Hypospray
solutionName: pen
transferAmount: 15
@@ -661,6 +664,7 @@
- type: ExaminableSolution
solution: hypospray
heldOnly: true # Allow examination only when held in hand.
+ exactVolume: true
- type: Hypospray
onlyAffectsMobs: false
- type: UseDelay
diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemical-containers.yml b/Resources/Prototypes/Entities/Objects/Specific/chemical-containers.yml
index 1bbe05944f..84990b10be 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/chemical-containers.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/chemical-containers.yml
@@ -26,6 +26,7 @@
solution: beaker
- type: ExaminableSolution
solution: beaker
+ exactVolume: true
- type: DrawableSolution
solution: beaker
- type: InjectableSolution
diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml
index a892ee6395..0c0c1cf172 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry-bottles.yml
@@ -37,6 +37,7 @@
solution: drink
- type: ExaminableSolution
solution: drink
+ exactVolume: true
- type: DrawableSolution
solution: drink
- type: SolutionTransfer
diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry-vials.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry-vials.yml
index 60441bb475..bc8207b673 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/chemistry-vials.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry-vials.yml
@@ -43,6 +43,7 @@
solution: beaker
- type: ExaminableSolution
solution: beaker
+ exactVolume: true
- type: DrawableSolution
solution: beaker
- type: SolutionTransfer
@@ -137,6 +138,7 @@
solution: beaker
- type: ExaminableSolution
solution: beaker
+ exactVolume: true
- type: DrawableSolution
solution: beaker
- type: SolutionTransfer
diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml
index ebd785ab7e..3a7e44775f 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml
@@ -35,6 +35,7 @@
solution: beaker
- type: ExaminableSolution
solution: beaker
+ exactVolume: true
- type: DrawableSolution
solution: beaker
- type: InjectableSolution
@@ -133,6 +134,7 @@
solution: beaker
- type: ExaminableSolution
solution: beaker
+ exactVolume: true
- type: DrawableSolution
solution: beaker
- type: InjectableSolution
@@ -189,6 +191,7 @@
solution: beaker
- type: ExaminableSolution
solution: beaker
+ exactVolume: true
- type: DrawableSolution
solution: beaker
- type: InjectableSolution
@@ -348,6 +351,7 @@
toggleState: 1 # draw
- type: ExaminableSolution
solution: dropper
+ exactVolume: true
- type: UserInterface
interfaces:
enum.TransferAmountUiKey.Key:
@@ -420,6 +424,7 @@
injectOnly: false
- type: ExaminableSolution
solution: injector
+ exactVolume: true
- type: Spillable
solution: injector
- type: TrashOnSolutionEmpty
diff --git a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml
index 638947af75..cb25f9199b 100644
--- a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml
+++ b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/anomalies.yml
@@ -979,6 +979,8 @@
solution: anomaly
- type: ExaminableSolution
solution: anomaly
+ exactVolume: true
+ locVolume: "examinable-solution-on-examine-volume-no-max"
- type: RefillableSolution
solution: anomaly
- type: InjectableSolution