Chem guidebook (#17123)

* im good at atomizing. welcome to half-finished chem guides.

* wagh

* e

* save work

* aa

* woweee UI

* finishing the last of it

* don't actually update the engine :(

---------

Co-authored-by: moonheart08 <moonheart08@users.noreply.github.com>
This commit is contained in:
Nemanja
2023-06-04 16:45:02 -04:00
committed by GitHub
parent 1e6dbd0b67
commit b9fb66f005
72 changed files with 1411 additions and 12 deletions

View File

@@ -0,0 +1,58 @@
<BoxContainer xmlns="https://spacestation14.io"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
Orientation="Vertical"
Margin="5 5 5 5">
<PanelContainer HorizontalExpand="True">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BorderThickness="1" BorderColor="#777777"/>
</PanelContainer.PanelOverride>
<BoxContainer Orientation="Vertical">
<PanelContainer Name="NameBackground" HorizontalExpand="True" VerticalExpand="False">
<RichTextLabel Name="ReagentName" HorizontalAlignment="Center"/>
</PanelContainer>
<BoxContainer Name="RecipesContainer" HorizontalExpand="True">
<Collapsible Orientation="Vertical" HorizontalExpand="True">
<CollapsibleHeading Title="{Loc 'guidebook-reagent-recipes-header'}"/>
<CollapsibleBody>
<BoxContainer Name="RecipesDescriptionContainer"
Margin="10 0 10 0"
Orientation="Horizontal"
HorizontalAlignment="Stretch"
HorizontalExpand="True">
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalAlignment="Center">
<RichTextLabel Name="ReactantsLabel"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</BoxContainer>
<BoxContainer Orientation="Vertical" VerticalAlignment="Center">
<TextureRect TexturePath="/Textures/Interface/Misc/beakerlarge.png"/>
<Label Text="{Loc 'guidebook-reagent-recipes-mix'}"
HorizontalAlignment="Center"/>
</BoxContainer>
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalAlignment="Center">
<RichTextLabel Name="ProductsLabel"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</BoxContainer>
</BoxContainer>
</CollapsibleBody>
</Collapsible>
</BoxContainer>
<BoxContainer Name="EffectsContainer" HorizontalExpand="True">
<Collapsible Orientation="Vertical">
<CollapsibleHeading Title="{Loc 'guidebook-reagent-effects-header'}"/>
<CollapsibleBody>
<BoxContainer Name="EffectsDescriptionContainer"
Orientation="Vertical"
Margin="10 0 10 0"
HorizontalExpand="True"/>
</CollapsibleBody>
</Collapsible>
</BoxContainer>
<BoxContainer Margin="10 5 10 10" HorizontalExpand="True">
<!-- The troublemaker !-->
<RichTextLabel Name="ReagentDescription" HorizontalAlignment="Left"/>
</BoxContainer>
</BoxContainer>
</PanelContainer>
</BoxContainer>

View File

@@ -0,0 +1,176 @@
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;
/// <summary>
/// Control for embedding a reagent into a guidebook.
/// </summary>
[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<ChemistryGuideDataSystem>();
MouseFilter = MouseFilterMode.Stop;
}
public GuideReagentEmbed(string reagent) : this()
{
GenerateControl(_prototype.Index<ReagentPrototype>(reagent));
}
public GuideReagentEmbed(ReagentPrototype reagent) : this()
{
GenerateControl(reagent);
}
public bool TryParseTag(Dictionary<string, string> 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<ReagentPrototype>(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<ReactionPrototype>(reagent.ID, out var reactionPrototype))
{
reactionPrototype = _prototype.EnumeratePrototypes<ReactionPrototype>()
.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<ReagentPrototype>(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<ReagentPrototype>(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);
}
}

View File

@@ -0,0 +1,4 @@
<BoxContainer xmlns="https://spacestation14.io"
Orientation="Vertical">
<BoxContainer Name="GroupContainer" Orientation="Vertical"/>
</BoxContainer>

View File

@@ -0,0 +1,60 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Client.Guidebook.Richtext;
using Content.Shared.Chemistry.Reagent;
using JetBrains.Annotations;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
namespace Content.Client.Guidebook.Controls;
/// <summary>
/// Control for embedding a reagent into a guidebook.
/// </summary>
[UsedImplicitly, GenerateTypedNameReferences]
public sealed partial class GuideReagentGroupEmbed : BoxContainer, IDocumentTag
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
public GuideReagentGroupEmbed()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
MouseFilter = MouseFilterMode.Stop;
}
public GuideReagentGroupEmbed(string group) : this()
{
var prototypes = _prototype.EnumeratePrototypes<ReagentPrototype>()
.Where(p => p.Group.Equals(group)).OrderBy(p => p.LocalizedName);
foreach (var reagent in prototypes)
{
var embed = new GuideReagentEmbed(reagent);
GroupContainer.AddChild(embed);
}
}
public bool TryParseTag(Dictionary<string, string> args, [NotNullWhen(true)] out Control? control)
{
control = null;
if (!args.TryGetValue("Group", out var group))
{
Logger.Error("Reagent group embed tag is missing group argument");
return false;
}
var prototypes = _prototype.EnumeratePrototypes<ReagentPrototype>()
.Where(p => p.Group.Equals(group)).OrderBy(p => p.LocalizedName);
foreach (var reagent in prototypes)
{
var embed = new GuideReagentEmbed(reagent);
GroupContainer.AddChild(embed);
}
control = this;
return true;
}
}