using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Client.Chemistry.EntitySystems; using Content.Client.Guidebook.Richtext; using Content.Client.Message; using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reagent; using JetBrains.Annotations; using Robust.Client.AutoGenerated; using Robust.Client.Graphics; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; using Robust.Shared.Utility; namespace Content.Client.Guidebook.Controls; /// /// Control for embedding a reagent into a guidebook. /// [UsedImplicitly, GenerateTypedNameReferences] public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag { [Dependency] private readonly IEntitySystemManager _systemManager = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; private readonly ChemistryGuideDataSystem _chemistryGuideData; public GuideReagentEmbed() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _chemistryGuideData = _systemManager.GetEntitySystem(); MouseFilter = MouseFilterMode.Stop; } public GuideReagentEmbed(string reagent) : this() { GenerateControl(_prototype.Index(reagent)); } public GuideReagentEmbed(ReagentPrototype reagent) : this() { GenerateControl(reagent); } public bool TryParseTag(Dictionary args, [NotNullWhen(true)] out Control? control) { control = null; if (!args.TryGetValue("Reagent", out var id)) { Logger.Error("Reagent embed tag is missing reagent prototype argument"); return false; } if (!_prototype.TryIndex(id, out var reagent)) { Logger.Error($"Specified reagent prototype \"{id}\" is not a valid reagent prototype"); return false; } GenerateControl(reagent); control = this; return true; } private void GenerateControl(ReagentPrototype reagent) { NameBackground.PanelOverride = new StyleBoxFlat { BackgroundColor = reagent.SubstanceColor }; var textColor = Color.ToHsl(reagent.SubstanceColor).Z > 0.45 ? Color.Black : Color.White; ReagentName.SetMarkup(Loc.GetString("guidebook-reagent-name", ("color", textColor), ("name", reagent.LocalizedName))); #region Recipe // by default, we assume that the reaction has the same ID as the reagent. // if this isn't true, we'll loop through reactions. if (!_prototype.TryIndex(reagent.ID, out var reactionPrototype)) { reactionPrototype = _prototype.EnumeratePrototypes() .FirstOrDefault(p => p.Products.ContainsKey(reagent.ID)); } if (reactionPrototype != null) { var reactantMsg = new FormattedMessage(); var reactantsCount = reactionPrototype.Reactants.Count; var i = 0; foreach (var (product, reactant) in reactionPrototype.Reactants) { reactantMsg.AddMarkup(Loc.GetString("guidebook-reagent-recipes-reagent-display", ("reagent", _prototype.Index(product).LocalizedName), ("ratio", reactant.Amount))); i++; if (i < reactantsCount) reactantMsg.PushNewline(); } reactantMsg.Pop(); ReactantsLabel.SetMessage(reactantMsg); var productMsg = new FormattedMessage(); var productCount = reactionPrototype.Products.Count; var u = 0; foreach (var (product, ratio) in reactionPrototype.Products) { productMsg.AddMarkup(Loc.GetString("guidebook-reagent-recipes-reagent-display", ("reagent", _prototype.Index(product).LocalizedName), ("ratio", ratio))); u++; if (u < productCount) productMsg.PushNewline(); } productMsg.Pop(); ProductsLabel.SetMessage(productMsg); } else { RecipesContainer.Visible = false; } #endregion #region Effects if (_chemistryGuideData.ReagentGuideRegistry.TryGetValue(reagent.ID, out var guideEntryRegistry) && guideEntryRegistry.GuideEntries != null && guideEntryRegistry.GuideEntries.Values.Any(pair => pair.EffectDescriptions.Any())) { EffectsDescriptionContainer.Children.Clear(); foreach (var (group, effect) in guideEntryRegistry.GuideEntries) { if (!effect.EffectDescriptions.Any()) continue; var groupLabel = new RichTextLabel(); groupLabel.SetMarkup(Loc.GetString("guidebook-reagent-effects-metabolism-group-rate", ("group", group), ("rate", effect.MetabolismRate))); var descriptionLabel = new RichTextLabel { Margin = new Thickness(25, 0, 10, 0) }; var descMsg = new FormattedMessage(); var descriptionsCount = effect.EffectDescriptions.Length; var i = 0; foreach (var effectString in effect.EffectDescriptions) { descMsg.AddMarkup(effectString); i++; if (i < descriptionsCount) descMsg.PushNewline(); } descriptionLabel.SetMessage(descMsg); EffectsDescriptionContainer.AddChild(groupLabel); EffectsDescriptionContainer.AddChild(descriptionLabel); } } else { EffectsContainer.Visible = false; } #endregion FormattedMessage description = new(); description.AddText(reagent.LocalizedDescription); description.PushNewline(); description.AddText(Loc.GetString("guidebook-reagent-physical-description", ("description", reagent.LocalizedPhysicalDescription))); ReagentDescription.SetMessage(description); } }