diff --git a/Content.Client/Chemistry/Visualizers/SolutionContainerVisualsSystem.cs b/Content.Client/Chemistry/Visualizers/SolutionContainerVisualsSystem.cs index 6f5c14852e..6fdf38441d 100644 --- a/Content.Client/Chemistry/Visualizers/SolutionContainerVisualsSystem.cs +++ b/Content.Client/Chemistry/Visualizers/SolutionContainerVisualsSystem.cs @@ -1,4 +1,4 @@ -using Content.Shared.Chemistry; +using Content.Shared.Chemistry; using Content.Shared.Chemistry.Reagent; using Content.Shared.Rounding; using Robust.Client.GameObjects; @@ -64,17 +64,12 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem(baseOverride, out var reagentProto); - var metadata = MetaData(uid); - if (reagentProto?.MetamorphicSprite is { } sprite) { args.Sprite.LayerSetSprite(baseLayer, sprite); args.Sprite.LayerSetVisible(fillLayer, false); if (hasOverlay) args.Sprite.LayerSetVisible(overlayLayer, false); - metadata.EntityName = Loc.GetString(component.MetamorphicNameFull, - ("name", reagentProto.LocalizedName)); - metadata.EntityDescription = reagentProto.LocalizedDescription; return; } else @@ -82,8 +77,6 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem +/// A container that transforms its appearance depending on the reagent it contains. +/// It returns to its initial state once the reagent is removed. +/// e.g. An empty glass changes to a beer glass when beer is added to it. +/// +/// Should probably be joined with SolutionContainerVisualsComponent when solutions are networked. +/// +[RegisterComponent, Access(typeof(TransformableContainerSystem))] +public sealed class TransformableContainerComponent : Component +{ + /// + /// This is the initial metadata name for the container. + /// It will revert to this when emptied. + /// It defaults to the name of the parent entity unless overwritten. + /// + [DataField("initialName")] + public string? InitialName; + + /// + /// This is the initial metadata description for the container. + /// It will revert to this when emptied. + /// /// It defaults to the description of the parent entity unless overwritten. + /// + [DataField("initialDescription")] + public string? InitialDescription; + /// + /// This stores whatever primary reagent is currently in the container. + /// It is used to help determine if a transformation is needed on solution update. + /// + [DataField("currentReagent")] + public ReagentPrototype? CurrentReagent; + + /// + /// This returns whether this container in a transformed or initial state. + /// + /// + [DataField("transformed")] + public bool Transformed; +} diff --git a/Content.Server/Chemistry/EntitySystems/TransformableContainerSystem.cs b/Content.Server/Chemistry/EntitySystems/TransformableContainerSystem.cs new file mode 100644 index 0000000000..41ab11aab0 --- /dev/null +++ b/Content.Server/Chemistry/EntitySystems/TransformableContainerSystem.cs @@ -0,0 +1,84 @@ +using Content.Server.Chemistry.Components; +using Content.Shared.Chemistry.Reagent; +using Robust.Shared.GameObjects; +using Robust.Shared.Prototypes; + +namespace Content.Server.Chemistry.EntitySystems; + +public sealed class TransformableContainerSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!; + [Dependency] private readonly MetaDataSystem _metadataSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnSolutionChange); + } + + private void OnMapInit(EntityUid uid, TransformableContainerComponent component, MapInitEvent args) + { + var meta = MetaData(uid); + if (string.IsNullOrEmpty(component.InitialName)) + { + component.InitialName = meta.EntityName; + } + if (string.IsNullOrEmpty(component.InitialDescription)) + { + component.InitialDescription = meta.EntityDescription; + } + } + + private void OnSolutionChange(EntityUid owner, TransformableContainerComponent component, + SolutionChangedEvent args) + { + if (!_solutionsSystem.TryGetFitsInDispenser(owner, out var solution)) + return; + //Transform container into initial state when emptied + if (component.CurrentReagent != null && solution.Contents.Count == 0) + { + CancelTransformation(owner, component); + } + + //the biggest reagent in the solution decides the appearance + var reagentId = solution.GetPrimaryReagentId(); + + //If biggest reagent didn't changed - don't change anything at all + if (component.CurrentReagent != null && component.CurrentReagent.ID == reagentId) + { + return; + } + + //Only reagents with spritePath property can change appearance of transformable containers! + if (!string.IsNullOrWhiteSpace(reagentId) + && _prototypeManager.TryIndex(reagentId, out ReagentPrototype? proto)) + { + var metadata = MetaData(owner); + var val = Loc.GetString("transformable-container-component-glass", ("name", proto.LocalizedName)); + _metadataSystem.SetEntityName(owner, val, metadata); + _metadataSystem.SetEntityDescription(owner, proto.LocalizedDescription, metadata); + component.CurrentReagent = proto; + component.Transformed = true; + } + } + + private void CancelTransformation(EntityUid owner, TransformableContainerComponent component) + { + component.CurrentReagent = null; + component.Transformed = false; + + var metadata = MetaData(owner); + + if (!string.IsNullOrEmpty(component.InitialName)) + { + _metadataSystem.SetEntityName(owner, component.InitialName, metadata); + } + if (!string.IsNullOrEmpty(component.InitialDescription)) + { + _metadataSystem.SetEntityDescription(owner, component.InitialDescription, metadata); + } + } +} diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml index 405e21c1a5..4baaa3f3bc 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks.yml @@ -107,6 +107,7 @@ metamorphicDefaultSprite: sprite: Objects/Consumable/Drinks/glass_clear.rsi state: icon + - type: TransformableContainer - type: entity name: Coupe glass