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:
@@ -0,0 +1,29 @@
|
||||
using Content.Shared.Chemistry;
|
||||
|
||||
namespace Content.Client.Chemistry.EntitySystems;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public sealed class ChemistryGuideDataSystem : SharedChemistryGuideDataSystem
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeNetworkEvent<ReagentGuideRegistryChangedEvent>(OnReceiveRegistryUpdate);
|
||||
}
|
||||
|
||||
private void OnReceiveRegistryUpdate(ReagentGuideRegistryChangedEvent message)
|
||||
{
|
||||
var data = message.Changeset;
|
||||
foreach (var remove in data.Removed)
|
||||
{
|
||||
Registry.Remove(remove);
|
||||
}
|
||||
|
||||
foreach (var (key, val) in data.GuideEntries)
|
||||
{
|
||||
Registry[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Content.Client/Guidebook/Controls/GuideReagentEmbed.xaml
Normal file
58
Content.Client/Guidebook/Controls/GuideReagentEmbed.xaml
Normal 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>
|
||||
176
Content.Client/Guidebook/Controls/GuideReagentEmbed.xaml.cs
Normal file
176
Content.Client/Guidebook/Controls/GuideReagentEmbed.xaml.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<BoxContainer xmlns="https://spacestation14.io"
|
||||
Orientation="Vertical">
|
||||
<BoxContainer Name="GroupContainer" Orientation="Vertical"/>
|
||||
</BoxContainer>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user