Move solution examine subscription from DrinkComponent to ExaminableSolutionComponent (#39362)
* initial it works * clean it up * yml * datafield the LocIds * move from the other branch * no max vol on puddles and anoms * closed * Changes inspired by #39008 * small bug and more color range * puddle changes and more examinable solutions * lint * small change * requested changes * un-delete * tiny comment * 1 less loc id in this world * request and last second change --------- Co-authored-by: iaada <iaada@users.noreply.github.com>
This commit is contained in:
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Component for examining a solution with shift click or through <see cref="SolutionScanEvent"/>.
|
||||||
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed partial class ExaminableSolutionComponent : Component
|
public sealed partial class ExaminableSolutionComponent : Component
|
||||||
{
|
{
|
||||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
/// <summary>
|
||||||
|
/// The solution being examined.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
public string Solution = "default";
|
public string Solution = "default";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If false then the hidden solution is always visible.
|
/// If true, the solution must be held to be examined.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField]
|
[DataField]
|
||||||
public bool HeldOnly;
|
public bool HeldOnly;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If false, the examine text will give an approximation of the remaining solution.
|
||||||
|
/// If true, the exact unit count will be shown.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public bool ExactVolume;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If false, the solution can't be examined when this entity is closed by <see cref="OpenableComponent"/>.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public bool ExaminableWhileClosed = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Examine text for the amount of solution.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="ExaminedVolumeDisplay"/>
|
||||||
|
[DataField]
|
||||||
|
public LocId LocVolume = "examinable-solution-on-examine-volume";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Examine text for the physical description of the primary reagent.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId LocPhysicalQuality = "shared-solution-container-component-on-examine-main-text";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Examine text for reagents that are obvious like water.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public LocId LocRecognizableReagents = "examinable-solution-has-recognizable-chemicals";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to choose how to display a volume.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum ExaminedVolumeDisplay
|
||||||
|
{
|
||||||
|
Exact,
|
||||||
|
Full,
|
||||||
|
MostlyFull,
|
||||||
|
HalfFull,
|
||||||
|
HalfEmpty,
|
||||||
|
MostlyEmpty,
|
||||||
|
Empty,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Kitchen.Components;
|
using Content.Shared.Kitchen.Components;
|
||||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||||
using Content.Shared.Chemistry.Reaction;
|
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Robust.Shared.Utility;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -139,12 +137,13 @@ public abstract partial class SharedSolutionContainerSystem
|
|||||||
|
|
||||||
#endregion Solution Modifiers
|
#endregion Solution Modifiers
|
||||||
|
|
||||||
|
/// <returns>A value between 0 and 100 inclusive.</returns>
|
||||||
public float PercentFull(EntityUid uid)
|
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 0;
|
||||||
|
|
||||||
return solution.FillFraction * 100;
|
return PercentFull(solution);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Static Methods
|
#region Static Methods
|
||||||
@@ -175,5 +174,14 @@ public abstract partial class SharedSolutionContainerSystem
|
|||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <returns>A value between 0 and 100 inclusive.</returns>
|
||||||
|
public static float PercentFull(Solution sol)
|
||||||
|
{
|
||||||
|
if (sol.MaxVolume.Equals(FixedPoint2.Zero))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return sol.FillFraction * 100;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Static Methods
|
#endregion Static Methods
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ using Content.Shared.Examine;
|
|||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
using Content.Shared.Hands.Components;
|
using Content.Shared.Hands.Components;
|
||||||
using Content.Shared.Hands.EntitySystems;
|
using Content.Shared.Hands.EntitySystems;
|
||||||
|
using Content.Shared.Localizations;
|
||||||
|
using Content.Shared.Nutrition.Components;
|
||||||
|
using Content.Shared.Nutrition.EntitySystems;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
@@ -61,14 +64,15 @@ public partial record struct SolutionAccessAttemptEvent(string SolutionName)
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public abstract partial class SharedSolutionContainerSystem : EntitySystem
|
public abstract partial class SharedSolutionContainerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Robust.Shared.IoC.Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
|
[Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
|
||||||
[Robust.Shared.IoC.Dependency] protected readonly ChemicalReactionSystem ChemicalReactionSystem = default!;
|
[Dependency] protected readonly ChemicalReactionSystem ChemicalReactionSystem = default!;
|
||||||
[Robust.Shared.IoC.Dependency] protected readonly ExamineSystemShared ExamineSystem = default!;
|
[Dependency] protected readonly ExamineSystemShared ExamineSystem = default!;
|
||||||
[Robust.Shared.IoC.Dependency] protected readonly SharedAppearanceSystem AppearanceSystem = default!;
|
[Dependency] protected readonly OpenableSystem Openable = default!;
|
||||||
[Robust.Shared.IoC.Dependency] protected readonly SharedHandsSystem Hands = default!;
|
[Dependency] protected readonly SharedAppearanceSystem AppearanceSystem = default!;
|
||||||
[Robust.Shared.IoC.Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
|
[Dependency] protected readonly SharedHandsSystem Hands = default!;
|
||||||
[Robust.Shared.IoC.Dependency] protected readonly MetaDataSystem MetaDataSys = default!;
|
[Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
|
||||||
[Robust.Shared.IoC.Dependency] protected readonly INetManager NetManager = default!;
|
[Dependency] protected readonly MetaDataSystem MetaDataSys = default!;
|
||||||
|
[Dependency] protected readonly INetManager NetManager = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -791,52 +795,55 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shift click examine.
|
||||||
|
/// </summary>
|
||||||
private void OnExamineSolution(Entity<ExaminableSolutionComponent> entity, ref ExaminedEvent args)
|
private void OnExamineSolution(Entity<ExaminableSolutionComponent> 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;
|
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)))
|
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<ReagentPrototype>(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
|
// Sort the reagents by amount, descending then alphabetically
|
||||||
var sortedReagentPrototypes = reagentPrototypes
|
var sortedReagentPrototypes = solution.GetReagentPrototypes(PrototypeManager)
|
||||||
.OrderByDescending(pair => pair.Value.Value)
|
.OrderByDescending(pair => pair.Value.Value)
|
||||||
.ThenBy(pair => pair.Key.LocalizedName);
|
.ThenBy(pair => pair.Key.LocalizedName);
|
||||||
|
|
||||||
// Add descriptions of immediately recognizable reagents, like water or beer
|
// Collect recognizable reagents, like water or beer
|
||||||
var recognized = new List<ReagentPrototype>();
|
var recognized = new List<string>();
|
||||||
foreach (var keyValuePair in sortedReagentPrototypes)
|
foreach (var keyValuePair in sortedReagentPrototypes)
|
||||||
{
|
{
|
||||||
var proto = keyValuePair.Key;
|
var proto = keyValuePair.Key;
|
||||||
@@ -845,41 +852,58 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
|
|||||||
continue;
|
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)
|
if (recognized.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var msg = new StringBuilder();
|
var msg = ContentLocalizationManager.FormatList(recognized);
|
||||||
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";
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.Append(Loc.GetString(part, ("color", reagent.SubstanceColor.ToHexNoAlpha()),
|
// Finally push the full message
|
||||||
("chemical", reagent.LocalizedName)));
|
args.PushMarkup(Loc.GetString(entity.Comp.LocRecognizableReagents,
|
||||||
}
|
("recognizedString", msg)));
|
||||||
|
|
||||||
args.PushMarkup(Loc.GetString("examinable-solution-has-recognizable-chemicals",
|
|
||||||
("recognizedString", msg.ToString())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <returns>An enum for how to display the solution.</returns>
|
||||||
|
public ExaminedVolumeDisplay ExaminedVolume(Entity<ExaminableSolutionComponent> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Full reagent scan, such as with chemical analysis goggles.
|
||||||
|
/// </summary>
|
||||||
private void OnSolutionExaminableVerb(Entity<ExaminableSolutionComponent> entity, ref GetVerbsEvent<ExamineVerb> args)
|
private void OnSolutionExaminableVerb(Entity<ExaminableSolutionComponent> entity, ref GetVerbsEvent<ExamineVerb> args)
|
||||||
{
|
{
|
||||||
if (!args.CanInteract || !args.CanAccess)
|
if (!args.CanInteract || !args.CanAccess)
|
||||||
@@ -953,15 +977,18 @@ public abstract partial class SharedSolutionContainerSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if examinable solution requires you to hold the item in hand.
|
/// Check if an examinable solution is hidden by something.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool CanSeeHiddenSolution(Entity<ExaminableSolutionComponent> entity, EntityUid examiner)
|
private bool CanSeeHiddenSolution(Entity<ExaminableSolutionComponent> entity, EntityUid examiner)
|
||||||
{
|
{
|
||||||
// If not held-only then it's always visible.
|
// If not held-only then it's always visible.
|
||||||
if (!entity.Comp.HeldOnly)
|
if (entity.Comp.HeldOnly && !Hands.IsHolding(examiner, entity, out _))
|
||||||
return true;
|
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<SolutionContainerManagerComponent> entity, ref MapInitEvent args)
|
private void OnMapInit(Entity<SolutionContainerManagerComponent> entity, ref MapInitEvent args)
|
||||||
|
|||||||
@@ -24,9 +24,6 @@ public sealed partial class DrinkComponent : Component
|
|||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public float Delay = 1;
|
public float Delay = 1;
|
||||||
|
|
||||||
[DataField, AutoNetworkedField]
|
|
||||||
public bool Examinable = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If true, trying to drink when empty will not handle the event.
|
/// If true, trying to drink when empty will not handle the event.
|
||||||
/// This means other systems such as equipping on use can run.
|
/// This means other systems such as equipping on use can run.
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ public abstract partial class SharedDrinkSystem : EntitySystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<DrinkComponent, AttemptShakeEvent>(OnAttemptShake);
|
SubscribeLocalEvent<DrinkComponent, AttemptShakeEvent>(OnAttemptShake);
|
||||||
SubscribeLocalEvent<DrinkComponent, ExaminedEvent>(OnExamined);
|
|
||||||
SubscribeLocalEvent<DrinkComponent, GetVerbsEvent<AlternativeVerb>>(AddDrinkVerb);
|
SubscribeLocalEvent<DrinkComponent, GetVerbsEvent<AlternativeVerb>>(AddDrinkVerb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,38 +46,6 @@ public abstract partial class SharedDrinkSystem : EntitySystem
|
|||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void OnExamined(Entity<DrinkComponent> entity, ref ExaminedEvent args)
|
|
||||||
{
|
|
||||||
TryComp<OpenableComponent>(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<ExaminableSolutionComponent>(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<DrinkComponent> entity, ref GetVerbsEvent<AlternativeVerb> ev)
|
private void AddDrinkVerb(Entity<DrinkComponent> entity, ref GetVerbsEvent<AlternativeVerb> ev)
|
||||||
{
|
{
|
||||||
if (entity.Owner == ev.User ||
|
if (entity.Owner == ev.User ||
|
||||||
@@ -130,18 +97,6 @@ public abstract partial class SharedDrinkSystem : EntitySystem
|
|||||||
return DrinkVolume(uid, component) <= 0;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to feed the drink item to the target entity
|
/// Tries to feed the drink item to the target entity
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -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] { $chemCount ->
|
||||||
shared-solution-container-component-on-examine-main-text = It contains {INDEFINITE($desc)} [color={$color}]{$desc}[/color] {$wordedAmount}
|
[1] chemical.
|
||||||
shared-solution-container-component-on-examine-worded-amount-one-reagent = chemical.
|
*[other] mixture of chemicals.
|
||||||
shared-solution-container-component-on-examine-worded-amount-multiple-reagents = mixture of chemicals.
|
}
|
||||||
|
|
||||||
examinable-solution-has-recognizable-chemicals = You can recognize {$recognizedString} in the solution.
|
examinable-solution-has-recognizable-chemicals = You can recognize {$recognizedString} in the solution.
|
||||||
examinable-solution-recognized-first = [color={$color}]{$chemical}[/color]
|
examinable-solution-recognized = [color={$color}]{$chemical}[/color]
|
||||||
examinable-solution-recognized-next = , [color={$color}]{$chemical}[/color]
|
|
||||||
examinable-solution-recognized-last = and [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]
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,14 +1,7 @@
|
|||||||
drink-component-on-use-is-empty = {CAPITALIZE(THE($owner))} is empty!
|
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-opened = [color=yellow]Opened[/color]
|
||||||
drink-component-on-examine-is-sealed = The seal is intact.
|
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-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-not-open = Open {$owner} first!
|
||||||
drink-component-try-use-drink-is-empty = {CAPITALIZE(THE($entity))} is empty!
|
drink-component-try-use-drink-is-empty = {CAPITALIZE(THE($entity))} is empty!
|
||||||
drink-component-try-use-drink-cannot-drink = You can't drink anything!
|
drink-component-try-use-drink-cannot-drink = You can't drink anything!
|
||||||
|
|||||||
@@ -75,6 +75,7 @@
|
|||||||
solution: tank
|
solution: tank
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: tank
|
solution: tank
|
||||||
|
exactVolume: true
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ClothingBackpack
|
parent: ClothingBackpack
|
||||||
|
|||||||
@@ -205,9 +205,9 @@
|
|||||||
delay: 3
|
delay: 3
|
||||||
transferAmount: 1
|
transferAmount: 1
|
||||||
solution: puddle
|
solution: puddle
|
||||||
examinable: false
|
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: puddle
|
solution: puddle
|
||||||
|
locVolume: "examinable-solution-on-examine-volume-puddle"
|
||||||
- type: DrawableSolution
|
- type: DrawableSolution
|
||||||
solution: puddle
|
solution: puddle
|
||||||
- type: BadDrink
|
- type: BadDrink
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
maxVol: 50
|
maxVol: 50
|
||||||
- type: PressurizedSolution
|
- type: PressurizedSolution
|
||||||
solution: drink
|
solution: drink
|
||||||
|
- type: ExaminableSolution
|
||||||
|
examinableWhileClosed: false
|
||||||
- type: Shakeable
|
- type: Shakeable
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
state: icon
|
state: icon
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
solution: drink
|
solution: drink
|
||||||
- type: DrainableSolution
|
- type: DrainableSolution
|
||||||
solution: drink
|
solution: drink
|
||||||
|
- type: ExaminableSolution
|
||||||
|
solution: drink
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
interfaces:
|
interfaces:
|
||||||
enum.TransferAmountUiKey.Key:
|
enum.TransferAmountUiKey.Key:
|
||||||
@@ -75,8 +77,6 @@
|
|||||||
- type: PhysicalComposition
|
- type: PhysicalComposition
|
||||||
materialComposition:
|
materialComposition:
|
||||||
Glass: 25
|
Glass: 25
|
||||||
- type: ExaminableSolution
|
|
||||||
solution: drink
|
|
||||||
- type: FitsInDispenser
|
- type: FitsInDispenser
|
||||||
solution: drink
|
solution: drink
|
||||||
- type: Tag
|
- type: Tag
|
||||||
|
|||||||
@@ -192,6 +192,8 @@
|
|||||||
layers:
|
layers:
|
||||||
- state: icon
|
- state: icon
|
||||||
map: ["enum.OpenableVisuals.Layer"]
|
map: ["enum.OpenableVisuals.Layer"]
|
||||||
|
- type: ExaminableSolution
|
||||||
|
examinableWhileClosed: false # If you can't see fill levels, it's probably opaque
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: DrinkBottleVisualsAll
|
id: DrinkBottleVisualsAll
|
||||||
@@ -217,6 +219,7 @@
|
|||||||
fillBaseName: fill-
|
fillBaseName: fill-
|
||||||
inHandsMaxFillLevels: 3
|
inHandsMaxFillLevels: 3
|
||||||
inHandsFillBaseName: -fill-
|
inHandsFillBaseName: -fill-
|
||||||
|
- type: ExaminableSolution
|
||||||
|
|
||||||
# Large Glass Bottles
|
# Large Glass Bottles
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,9 @@
|
|||||||
solution: drink
|
solution: drink
|
||||||
- type: PressurizedSolution
|
- type: PressurizedSolution
|
||||||
solution: drink
|
solution: drink
|
||||||
|
- type: ExaminableSolution
|
||||||
|
solution: drink
|
||||||
|
examinableWhileClosed: false
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
- type: GenericVisualizer
|
- type: GenericVisualizer
|
||||||
visuals:
|
visuals:
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
solution: drink
|
solution: drink
|
||||||
- type: DrainableSolution
|
- type: DrainableSolution
|
||||||
solution: drink
|
solution: drink
|
||||||
|
- type: ExaminableSolution
|
||||||
|
solution: drink
|
||||||
- type: SolutionTransfer
|
- type: SolutionTransfer
|
||||||
canChangeTransferAmount: true
|
canChangeTransferAmount: true
|
||||||
maxTransferAmount: 10
|
maxTransferAmount: 10
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
Steel: 300
|
Steel: 300
|
||||||
- type: FitsInDispenser
|
- type: FitsInDispenser
|
||||||
solution: drink
|
solution: drink
|
||||||
|
- type: ExaminableSolution
|
||||||
|
examinableWhileClosed: false
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: DrinkFlaskVisualsOpenable
|
id: DrinkFlaskVisualsOpenable
|
||||||
|
|||||||
@@ -41,6 +41,10 @@
|
|||||||
mixOnInteract: false
|
mixOnInteract: false
|
||||||
reactionTypes:
|
reactionTypes:
|
||||||
- Shake
|
- Shake
|
||||||
|
- type: ExaminableSolution
|
||||||
|
solution: drink
|
||||||
|
heldOnly: true
|
||||||
|
examinableWhileClosed: false
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: DrinkGlassBase
|
parent: DrinkGlassBase
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
solution: food
|
solution: food
|
||||||
- type: DrainableSolution
|
- type: DrainableSolution
|
||||||
solution: food
|
solution: food
|
||||||
|
- type: ExaminableSolution
|
||||||
|
solution: food
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Consumable/Food/condiments.rsi
|
sprite: Objects/Consumable/Food/condiments.rsi
|
||||||
- type: Icon
|
- type: Icon
|
||||||
@@ -69,6 +71,8 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Packet
|
- Packet
|
||||||
|
- type: ExaminableSolution
|
||||||
|
exactVolume: true
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: BaseFoodCondimentPacket
|
parent: BaseFoodCondimentPacket
|
||||||
|
|||||||
@@ -110,6 +110,8 @@
|
|||||||
solution: Welder
|
solution: Welder
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: Welder
|
solution: Welder
|
||||||
|
heldOnly: true
|
||||||
|
exactVolume: true
|
||||||
- type: SolutionRegeneration
|
- type: SolutionRegeneration
|
||||||
solution: Welder
|
solution: Welder
|
||||||
generated:
|
generated:
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
solution: spray
|
solution: spray
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: spray
|
solution: spray
|
||||||
|
exactVolume: true
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: mega spray bottle
|
name: mega spray bottle
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
solution: hypospray
|
solution: hypospray
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: hypospray
|
solution: hypospray
|
||||||
|
exactVolume: true
|
||||||
- type: Hypospray
|
- type: Hypospray
|
||||||
onlyAffectsMobs: false
|
onlyAffectsMobs: false
|
||||||
- type: UseDelay
|
- type: UseDelay
|
||||||
@@ -63,6 +64,7 @@
|
|||||||
solution: hypospray
|
solution: hypospray
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: hypospray
|
solution: hypospray
|
||||||
|
exactVolume: true
|
||||||
- type: Hypospray
|
- type: Hypospray
|
||||||
onlyAffectsMobs: false
|
onlyAffectsMobs: false
|
||||||
- type: UseDelay
|
- type: UseDelay
|
||||||
@@ -142,6 +144,7 @@
|
|||||||
maxVol: 15
|
maxVol: 15
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: pen
|
solution: pen
|
||||||
|
exactVolume: true
|
||||||
- type: Hypospray
|
- type: Hypospray
|
||||||
solutionName: pen
|
solutionName: pen
|
||||||
transferAmount: 15
|
transferAmount: 15
|
||||||
@@ -661,6 +664,7 @@
|
|||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: hypospray
|
solution: hypospray
|
||||||
heldOnly: true # Allow examination only when held in hand.
|
heldOnly: true # Allow examination only when held in hand.
|
||||||
|
exactVolume: true
|
||||||
- type: Hypospray
|
- type: Hypospray
|
||||||
onlyAffectsMobs: false
|
onlyAffectsMobs: false
|
||||||
- type: UseDelay
|
- type: UseDelay
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
solution: beaker
|
solution: beaker
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
|
exactVolume: true
|
||||||
- type: DrawableSolution
|
- type: DrawableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
- type: InjectableSolution
|
- type: InjectableSolution
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
solution: drink
|
solution: drink
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: drink
|
solution: drink
|
||||||
|
exactVolume: true
|
||||||
- type: DrawableSolution
|
- type: DrawableSolution
|
||||||
solution: drink
|
solution: drink
|
||||||
- type: SolutionTransfer
|
- type: SolutionTransfer
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
solution: beaker
|
solution: beaker
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
|
exactVolume: true
|
||||||
- type: DrawableSolution
|
- type: DrawableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
- type: SolutionTransfer
|
- type: SolutionTransfer
|
||||||
@@ -137,6 +138,7 @@
|
|||||||
solution: beaker
|
solution: beaker
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
|
exactVolume: true
|
||||||
- type: DrawableSolution
|
- type: DrawableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
- type: SolutionTransfer
|
- type: SolutionTransfer
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
solution: beaker
|
solution: beaker
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
|
exactVolume: true
|
||||||
- type: DrawableSolution
|
- type: DrawableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
- type: InjectableSolution
|
- type: InjectableSolution
|
||||||
@@ -133,6 +134,7 @@
|
|||||||
solution: beaker
|
solution: beaker
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
|
exactVolume: true
|
||||||
- type: DrawableSolution
|
- type: DrawableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
- type: InjectableSolution
|
- type: InjectableSolution
|
||||||
@@ -189,6 +191,7 @@
|
|||||||
solution: beaker
|
solution: beaker
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
|
exactVolume: true
|
||||||
- type: DrawableSolution
|
- type: DrawableSolution
|
||||||
solution: beaker
|
solution: beaker
|
||||||
- type: InjectableSolution
|
- type: InjectableSolution
|
||||||
@@ -348,6 +351,7 @@
|
|||||||
toggleState: 1 # draw
|
toggleState: 1 # draw
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: dropper
|
solution: dropper
|
||||||
|
exactVolume: true
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
interfaces:
|
interfaces:
|
||||||
enum.TransferAmountUiKey.Key:
|
enum.TransferAmountUiKey.Key:
|
||||||
@@ -420,6 +424,7 @@
|
|||||||
injectOnly: false
|
injectOnly: false
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: injector
|
solution: injector
|
||||||
|
exactVolume: true
|
||||||
- type: Spillable
|
- type: Spillable
|
||||||
solution: injector
|
solution: injector
|
||||||
- type: TrashOnSolutionEmpty
|
- type: TrashOnSolutionEmpty
|
||||||
|
|||||||
@@ -979,6 +979,8 @@
|
|||||||
solution: anomaly
|
solution: anomaly
|
||||||
- type: ExaminableSolution
|
- type: ExaminableSolution
|
||||||
solution: anomaly
|
solution: anomaly
|
||||||
|
exactVolume: true
|
||||||
|
locVolume: "examinable-solution-on-examine-volume-no-max"
|
||||||
- type: RefillableSolution
|
- type: RefillableSolution
|
||||||
solution: anomaly
|
solution: anomaly
|
||||||
- type: InjectableSolution
|
- type: InjectableSolution
|
||||||
|
|||||||
Reference in New Issue
Block a user