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;
|
||||
}
|
||||
}
|
||||
47
Content.Server/Chemistry/Commands/DumpReagentGuideText.cs
Normal file
47
Content.Server/Chemistry/Commands/DumpReagentGuideText.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.Commands;
|
||||
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public sealed class DumpReagentGuideText : IConsoleCommand
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _entSys = default!;
|
||||
|
||||
public string Command => "dumpreagentguidetext";
|
||||
public string Description => "Dumps the guidebook text for a reagent to the console";
|
||||
public string Help => "dumpreagentguidetext <reagent>";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
shell.WriteError("Must have only 1 argument");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_prototype.TryIndex<ReagentPrototype>(args[0], out var reagent))
|
||||
{
|
||||
shell.WriteError($"Invalid prototype: {args[0]}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (reagent.Metabolisms is null)
|
||||
{
|
||||
shell.WriteLine("Nothing to dump.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var (_, entry) in reagent.Metabolisms)
|
||||
{
|
||||
foreach (var effect in entry.Effects)
|
||||
{
|
||||
shell.WriteLine(effect.GuidebookEffectDescription(_prototype, _entSys) ?? $"[skipped effect of type {effect.GetType()}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems;
|
||||
|
||||
|
||||
public sealed class ChemistryGuideDataSystem : SharedChemistryGuideDataSystem
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
PrototypeManager.PrototypesReloaded += PrototypeManagerReload;
|
||||
|
||||
_player.PlayerStatusChanged += OnPlayerStatusChanged;
|
||||
|
||||
InitializeServerRegistry();
|
||||
}
|
||||
|
||||
private void InitializeServerRegistry()
|
||||
{
|
||||
var changeset = new ReagentGuideChangeset(new Dictionary<string, ReagentGuideEntry>(), new HashSet<string>());
|
||||
foreach (var proto in PrototypeManager.EnumeratePrototypes<ReagentPrototype>())
|
||||
{
|
||||
var entry = new ReagentGuideEntry(proto, PrototypeManager, EntityManager.EntitySysManager);
|
||||
changeset.GuideEntries.Add(proto.ID, entry);
|
||||
Registry[proto.ID] = entry;
|
||||
}
|
||||
|
||||
var ev = new ReagentGuideRegistryChangedEvent(changeset);
|
||||
RaiseNetworkEvent(ev);
|
||||
}
|
||||
|
||||
private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
|
||||
{
|
||||
if (e.NewStatus != SessionStatus.Connected)
|
||||
return;
|
||||
|
||||
var sendEv = new ReagentGuideRegistryChangedEvent(new ReagentGuideChangeset(Registry, new HashSet<string>()));
|
||||
RaiseNetworkEvent(sendEv, e.Session);
|
||||
}
|
||||
|
||||
private void PrototypeManagerReload(PrototypesReloadedEventArgs obj)
|
||||
{
|
||||
if (!obj.ByType.TryGetValue(typeof(ReagentPrototype), out var reagents))
|
||||
return;
|
||||
|
||||
var changeset = new ReagentGuideChangeset(new Dictionary<string, ReagentGuideEntry>(), new HashSet<string>());
|
||||
|
||||
foreach (var (id, proto) in reagents.Modified)
|
||||
{
|
||||
var reagentProto = (ReagentPrototype) proto;
|
||||
var entry = new ReagentGuideEntry(reagentProto, PrototypeManager, EntityManager.EntitySysManager);
|
||||
changeset.GuideEntries.Add(id, entry);
|
||||
Registry[id] = entry;
|
||||
}
|
||||
|
||||
var ev = new ReagentGuideRegistryChangedEvent(changeset);
|
||||
RaiseNetworkEvent(ev);
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,10 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
[DataField("sound", required: true)] private SoundSpecifier _sound = default!;
|
||||
|
||||
public override bool ShouldLog => true;
|
||||
|
||||
protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-missing");
|
||||
|
||||
public override LogImpact LogImpact => LogImpact.High;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
|
||||
@@ -19,6 +19,12 @@ public sealed class CreateEntityReactionEffect : ReagentEffect
|
||||
[DataField("number")]
|
||||
public uint Number = 1;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-create-entity-reaction-effect",
|
||||
("chance", Probability),
|
||||
("entname", IoCManager.Resolve<IPrototypeManager>().Index<EntityPrototype>(Entity).Name),
|
||||
("amount", Number));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
var transform = args.EntityManager.GetComponent<TransformComponent>(args.SolutionEntity);
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Explosion;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Chemistry.ReactionEffects
|
||||
@@ -24,7 +25,7 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
[DataField("maxIntensity")]
|
||||
[JsonIgnore]
|
||||
public float MaxIntensity = 5;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// How quickly intensity drops off as you move away from the epicenter
|
||||
/// </summary>
|
||||
@@ -51,6 +52,9 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
public float IntensityPerUnit = 1;
|
||||
|
||||
public override bool ShouldLog => true;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-explosion-reaction-effect", ("chance", Probability));
|
||||
public override LogImpact LogImpact => LogImpact.High;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -16,6 +16,10 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
/// </summary>
|
||||
[DataField("temperature", required: true)] private float _temperature;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-set-solution-temperature-effect",
|
||||
("chance", Probability), ("temperature", _temperature));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
var solution = args.Source;
|
||||
@@ -52,6 +56,10 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
/// </summary>
|
||||
[DataField("scaled")] private bool _scaled;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-adjust-solution-temperature-effect",
|
||||
("chance", Probability), ("deltasign", MathF.Sign(_delta)), ("mintemp", _minTemp), ("maxtemp", _maxTemp));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
var solution = args.Source;
|
||||
@@ -101,11 +109,15 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
|
||||
var heatCap = solution.GetHeatCapacity(null);
|
||||
var deltaT = _scaled
|
||||
? _delta / heatCap * (float) args.Quantity
|
||||
? _delta / heatCap * (float) args.Quantity
|
||||
: _delta / heatCap;
|
||||
|
||||
solution.Temperature = Math.Clamp(solution.Temperature + deltaT, _minTemp, _maxTemp);
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-adjust-solution-temperature-effect",
|
||||
("chance", Probability), ("deltasign", MathF.Sign(_delta)), ("mintemp", _minTemp), ("maxtemp", _maxTemp));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
{
|
||||
@@ -13,7 +14,7 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
public float Min = 0;
|
||||
|
||||
[DataField("max")]
|
||||
public float Max = float.MaxValue;
|
||||
public float Max = float.PositiveInfinity;
|
||||
public override bool Condition(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.EntityManager.TryGetComponent(args.SolutionEntity, out TemperatureComponent? temp))
|
||||
@@ -24,5 +25,12 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string GuidebookExplanation(IPrototypeManager prototype)
|
||||
{
|
||||
return Loc.GetString("reagent-effect-condition-guidebook-body-temperature",
|
||||
("max", float.IsPositiveInfinity(Max) ? (float) int.MaxValue : Max),
|
||||
("min", Min));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Tag;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffectConditions;
|
||||
@@ -21,4 +22,10 @@ public sealed class HasTag : ReagentEffectCondition
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string GuidebookExplanation(IPrototypeManager prototype)
|
||||
{
|
||||
// this should somehow be made (much) nicer.
|
||||
return Loc.GetString("reagent-effect-condition-guidebook-has-tag", ("tag", Tag), ("invert", Invert));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
{
|
||||
@@ -21,6 +22,11 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string GuidebookExplanation(IPrototypeManager prototype)
|
||||
{
|
||||
return Loc.GetString("reagent-effect-condition-guidebook-mob-state-condition", ("state", mobstate));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Shared.Body.Prototypes;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
@@ -30,5 +31,12 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
return ShouldHave;
|
||||
return !ShouldHave;
|
||||
}
|
||||
|
||||
public override string GuidebookExplanation(IPrototypeManager prototype)
|
||||
{
|
||||
return Loc.GetString("reagent-effect-condition-guidebook-organ-type",
|
||||
("name", prototype.Index<MetabolizerTypePrototype>(Type).Name),
|
||||
("shouldhave", ShouldHave));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
{
|
||||
@@ -35,5 +36,17 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
|
||||
return quant >= Min && quant <= Max;
|
||||
}
|
||||
|
||||
public override string GuidebookExplanation(IPrototypeManager prototype)
|
||||
{
|
||||
ReagentPrototype? reagentProto = null;
|
||||
if (Reagent is not null)
|
||||
prototype.TryIndex(Reagent, out reagentProto);
|
||||
|
||||
return Loc.GetString("reagent-effect-condition-guidebook-reagent-threshold",
|
||||
("reagent", reagentProto?.LocalizedName ?? "this reagent"),
|
||||
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
|
||||
("min", Min.Float()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
{
|
||||
@@ -24,5 +25,12 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string GuidebookExplanation(IPrototypeManager prototype)
|
||||
{
|
||||
return Loc.GetString("reagent-effect-condition-guidebook-solution-temperature",
|
||||
("max", float.IsPositiveInfinity(Max) ? (float) int.MaxValue : Max),
|
||||
("min", Min));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
{
|
||||
@@ -23,5 +24,12 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string GuidebookExplanation(IPrototypeManager prototype)
|
||||
{
|
||||
return Loc.GetString("reagent-effect-condition-guidebook-total-damage",
|
||||
("max", Max == FixedPoint2.MaxValue ? (float) int.MaxValue : Max.Float()),
|
||||
("min", Min.Float()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -10,4 +11,7 @@ public sealed class ActivateArtifact : ReagentEffect
|
||||
var artifact = args.EntityManager.EntitySysManager.GetEntitySystem<ArtifactSystem>();
|
||||
artifact.TryActivateArtifact(args.SolutionEntity);
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) =>
|
||||
Loc.GetString("reagent-effect-guidebook-activate-artifact", ("chance", Probability));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
@@ -24,5 +25,8 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
.TryAddReagent(args.SolutionEntity, solutionContainer, args.Reagent.ID, args.Quantity, out var accepted))
|
||||
args.Source?.RemoveReagent(args.Reagent.ID, accepted);
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) =>
|
||||
Loc.GetString("reagent-effect-guidebook-missing", ("chance", Probability));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
@@ -18,6 +19,9 @@ public sealed class AdjustAlert : ReagentEffect
|
||||
[DataField("time")]
|
||||
public float Time;
|
||||
|
||||
//JUSTIFICATION: This just changes some visuals, doesn't need to be documented.
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => null;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
var alertSys = EntitySystem.Get<AlertsSystem>();
|
||||
|
||||
@@ -60,5 +60,27 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
if (Reagent is not null && prototype.TryIndex(Reagent, out ReagentPrototype? reagentProto))
|
||||
{
|
||||
return Loc.GetString("reagent-effect-guidebook-adjust-reagent-reagent",
|
||||
("chance", Probability),
|
||||
("deltasign", MathF.Sign(Amount.Float())),
|
||||
("reagent", reagentProto.LocalizedName),
|
||||
("amount", MathF.Abs(Amount.Float())));
|
||||
}
|
||||
else if (Group is not null && prototype.TryIndex(Group, out MetabolismGroupPrototype? groupProto))
|
||||
{
|
||||
return Loc.GetString("reagent-effect-guidebook-adjust-reagent-group",
|
||||
("chance", Probability),
|
||||
("deltasign", MathF.Sign(Amount.Float())),
|
||||
("group", groupProto.ID),
|
||||
("amount", MathF.Abs(Amount.Float())));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Server.Temperature.Systems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
@@ -9,6 +10,12 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
[DataField("amount")]
|
||||
public float Amount;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-adjust-temperature",
|
||||
("chance", Probability),
|
||||
("deltasign", MathF.Sign(Amount)),
|
||||
("amount", MathF.Abs(Amount)));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.EntityManager.TryGetComponent(args.SolutionEntity, out TemperatureComponent? temp))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using JetBrains.Annotations;
|
||||
using Content.Server.Body.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReactionEffects
|
||||
{
|
||||
@@ -12,6 +13,10 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
{
|
||||
[DataField("cleanseRate")]
|
||||
public float CleanseRate = 3.0f;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-chem-clean-bloodstream", ("chance", Probability));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.Source == null || args.Reagent == null)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Eye.Blinding;
|
||||
using Content.Shared.Eye.Blinding.Systems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
@@ -17,6 +18,9 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
[DataField("amount")]
|
||||
public int Amount = -1;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-cure-eye-damage", ("chance", Probability), ("deltasign", MathF.Sign(Amount)));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.Scale != 1f) // huh?
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Server.Medical;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
@@ -17,6 +18,9 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
[DataField("hungerAmount")]
|
||||
public float HungerAmount = -40f;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-chem-vomit", ("chance", Probability));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.Scale != 1f)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -17,6 +18,17 @@ public sealed class CreateGas : ReagentEffect
|
||||
public float Multiplier = 3f;
|
||||
|
||||
public override bool ShouldLog => true;
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
var atmos = entSys.GetEntitySystem<AtmosphereSystem>();
|
||||
var gasProto = atmos.GetGas(Gas);
|
||||
|
||||
return Loc.GetString("reagent-effect-guidebook-create-gas",
|
||||
("chance", Probability),
|
||||
("moles", Multiplier),
|
||||
("gas", gasProto.Name));
|
||||
}
|
||||
|
||||
public override LogImpact LogImpact => LogImpact.High;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Drunk;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -17,6 +18,9 @@ public sealed class Drunk : ReagentEffect
|
||||
[DataField("slurSpeech")]
|
||||
public bool SlurSpeech = true;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-drunk", ("chance", Probability));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
var boozePower = BoozePower;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.Electrocution;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -14,6 +15,9 @@ public sealed class Electrocute : ReagentEffect
|
||||
/// </remarks>
|
||||
[DataField("refresh")] public bool Refresh = true;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-electrocute", ("chance", Probability), ("time", ElectrocuteTime));
|
||||
|
||||
public override bool ShouldLog => true;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Server.Chat.Systems;
|
||||
using Content.Shared.Chat.Prototypes;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
@@ -18,6 +19,10 @@ public sealed class Emote : ReagentEffect
|
||||
[DataField("showInChat")]
|
||||
public bool ShowInChat;
|
||||
|
||||
// JUSTIFICATION: Emoting is flavor, so same reason popup messages are not in here.
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> null;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (EmoteId == null)
|
||||
|
||||
@@ -2,12 +2,16 @@ using Content.Server.Atmos.Components;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class ExtinguishReaction : ReagentEffect
|
||||
{
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-extinguish-reaction", ("chance", Probability));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (!args.EntityManager.TryGetComponent(args.SolutionEntity, out FlammableComponent? flammable)) return;
|
||||
|
||||
@@ -3,6 +3,7 @@ using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
@@ -13,6 +14,10 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
public float Multiplier = 0.05f;
|
||||
|
||||
public override bool ShouldLog => true;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-flammable-reaction", ("chance", Probability));
|
||||
|
||||
public override LogImpact LogImpact => LogImpact.Medium;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Localizations;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
@@ -31,6 +34,38 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
[JsonPropertyName("ignoreResistances")]
|
||||
public bool IgnoreResistances = true;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
var damages = new List<string>();
|
||||
var heals = false;
|
||||
var deals = false;
|
||||
|
||||
// TODO: This should be smarter. Namely, not showing a damage type as being in a group unless every damage type in the group is present and equal in value.
|
||||
foreach (var (kind, amount) in Damage.GetDamagePerGroup())
|
||||
{
|
||||
var sign = MathF.Sign(amount.Float());
|
||||
|
||||
if (sign < 0)
|
||||
heals = true;
|
||||
if (sign > 0)
|
||||
deals = true;
|
||||
|
||||
damages.Add(
|
||||
Loc.GetString("health-change-display",
|
||||
("kind", kind),
|
||||
("amount", MathF.Abs(amount.Float())),
|
||||
("deltasign", sign)
|
||||
));
|
||||
}
|
||||
|
||||
var healsordeals = heals ? (deals ? "both" : "heals") : (deals ? "deals" : "none");
|
||||
|
||||
return Loc.GetString("reagent-effect-guidebook-health-change",
|
||||
("chance", Probability),
|
||||
("changes", ContentLocalizationManager.FormatList(damages)),
|
||||
("healsordeals", healsordeals));
|
||||
}
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
var scale = ScaleByQuantity ? args.Quantity : FixedPoint2.New(1);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -10,6 +11,10 @@ namespace Content.Server.Chemistry.ReagentEffects;
|
||||
public sealed class Ignite : ReagentEffect
|
||||
{
|
||||
public override bool ShouldLog => true;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-ignite", ("chance", Probability));
|
||||
|
||||
public override LogImpact LogImpact => LogImpact.Medium;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
|
||||
@@ -2,11 +2,16 @@ using Content.Server.Ghost.Roles.Components;
|
||||
using Content.Server.Mind.Components;
|
||||
using Content.Server.Speech.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Server.Ghost.Roles.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
public sealed class MakeSentient : ReagentEffect
|
||||
{
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-make-sentient", ("chance", Probability));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
var entityManager = args.EntityManager;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -12,6 +13,10 @@ public sealed class ModifyBleedAmount : ReagentEffect
|
||||
[DataField("amount")]
|
||||
public float Amount = -1.0f;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-modify-bleed-amount", ("chance", Probability),
|
||||
("deltasign", MathF.Sign(Amount)));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.EntityManager.TryGetComponent<BloodstreamComponent>(args.SolutionEntity, out var blood))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -13,6 +14,10 @@ public sealed class ModifyBloodLevel : ReagentEffect
|
||||
[DataField("amount")]
|
||||
public FixedPoint2 Amount = 1.0f;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-modify-blood-level", ("chance", Probability),
|
||||
("deltasign", MathF.Sign(Amount.Float())));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.EntityManager.TryGetComponent<BloodstreamComponent>(args.SolutionEntity, out var blood))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -9,6 +10,10 @@ public sealed class ModifyLungGas : ReagentEffect
|
||||
[DataField("ratios", required: true)]
|
||||
private Dictionary<Gas, float> _ratios = default!;
|
||||
|
||||
// JUSTIFICATION: This is internal magic that players never directly interact with.
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> null;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.EntityManager.TryGetComponent<LungComponent>(args.OrganEntity, out var lung))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
@@ -29,6 +30,14 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
[DataField("statusLifetime")]
|
||||
public float StatusLifetime = 2f;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
return Loc.GetString("reagent-effect-guidebook-movespeed-modifier",
|
||||
("chance", Probability),
|
||||
("walkspeed", WalkSpeedModifier),
|
||||
("time", StatusLifetime));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove reagent at set rate, changes the movespeed modifiers and adds a MovespeedModifierMetabolismComponent if not already there.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -9,6 +10,10 @@ public sealed class Oxygenate : ReagentEffect
|
||||
[DataField("factor")]
|
||||
public float Factor = 1f;
|
||||
|
||||
// JUSTIFICATION: This is internal magic that players never directly interact with.
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> null;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.EntityManager.TryGetComponent<RespiratorComponent>(args.SolutionEntity, out var resp))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Server.Stunnable;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -12,6 +13,11 @@ public sealed class Paralyze : ReagentEffect
|
||||
/// </remarks>
|
||||
[DataField("refresh")] public bool Refresh = true;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-paralyze",
|
||||
("chance", Probability),
|
||||
("time", ParalyzeTime));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
var paralyzeTime = ParalyzeTime;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Botany.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism
|
||||
@@ -35,5 +36,7 @@ namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism
|
||||
// Dependencies are never injected for reagents if you intend to do that for this.
|
||||
return !(Prob <= 0f) && IoCManager.Resolve<IRobustRandom>().Prob(Prob);
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-missing", ("chance", Probability));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Botany.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism
|
||||
@@ -26,5 +27,7 @@ namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism
|
||||
plantHolderComp.SkipAging++;
|
||||
plantHolderComp.ForceUpdate = true;
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-missing", ("chance", Probability));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Server.Botany.Components;
|
||||
using Content.Server.Botany.Systems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism
|
||||
@@ -34,5 +35,7 @@ namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism
|
||||
plantHolderComp.Seed.Endurance++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-missing", ("chance", Probability));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Server.Botany.Components;
|
||||
using Content.Server.Botany.Systems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism
|
||||
@@ -47,5 +48,7 @@ namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism
|
||||
plantHolderComp.Seed.Yield--;
|
||||
}
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-missing", ("chance", Probability));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
@@ -16,6 +17,10 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
[DataField("visualType")]
|
||||
public PopupType VisualType = PopupType.Small;
|
||||
|
||||
// JUSTIFICATION: This is purely cosmetic.
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> null;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
var popupSys = args.EntityManager.EntitySysManager.GetEntitySystem<SharedPopupSystem>();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Traits.Assorted;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
@@ -16,6 +17,9 @@ public sealed class ResetNarcolepsy : ReagentEffect
|
||||
[DataField("TimerReset")]
|
||||
public int TimerReset = 600;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-reset-narcolepsy", ("chance", Probability));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.Scale != 1f)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Nutrition.Components;
|
||||
using Content.Shared.Nutrition.EntitySystems;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
@@ -11,10 +12,12 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
/// </summary>
|
||||
public sealed class SatiateHunger : ReagentEffect
|
||||
{
|
||||
private const float DefaultNutritionFactor = 3.0f;
|
||||
|
||||
/// <summary>
|
||||
/// How much hunger is satiated when 1u of the reagent is metabolized
|
||||
/// </summary>
|
||||
[DataField("factor")] public float NutritionFactor { get; set; } = 3.0f;
|
||||
[DataField("factor")] public float NutritionFactor { get; set; } = DefaultNutritionFactor;
|
||||
|
||||
//Remove reagent at set rate, satiate hunger if a HungerComponent can be found
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
@@ -24,5 +27,8 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
return;
|
||||
entman.System<HungerSystem>().ModifyHunger(args.SolutionEntity, NutritionFactor * (float) args.Quantity, hunger);
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-satiate-hunger", ("chance", Probability), ("relative", NutritionFactor / DefaultNutritionFactor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Server.Nutrition.EntitySystems;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
@@ -10,10 +11,12 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
/// </summary>
|
||||
public sealed class SatiateThirst : ReagentEffect
|
||||
{
|
||||
private const float DefaultHydrationFactor = 3.0f;
|
||||
|
||||
/// How much thirst is satiated each metabolism tick. Not currently tied to
|
||||
/// rate or anything.
|
||||
[DataField("factor")]
|
||||
public float HydrationFactor { get; set; } = 3.0f;
|
||||
public float HydrationFactor { get; set; } = DefaultHydrationFactor;
|
||||
|
||||
/// Satiate thirst if a ThirstComponent can be found
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
@@ -21,5 +24,8 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
if (args.EntityManager.TryGetComponent(args.SolutionEntity, out ThirstComponent? thirst))
|
||||
EntitySystem.Get<ThirstSystem>().UpdateThirst(thirst, HydrationFactor);
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-satiate-thirst", ("chance", Probability), ("relative", HydrationFactor / DefaultHydrationFactor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.StatusEffect;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects.StatusEffects
|
||||
{
|
||||
@@ -57,6 +58,13 @@ namespace Content.Server.Chemistry.ReagentEffects.StatusEffects
|
||||
statusSys.TrySetTime(args.SolutionEntity, Key, TimeSpan.FromSeconds(time));
|
||||
}
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString(
|
||||
"reagent-effect-guidebook-status-effect",
|
||||
("chance", Probability),
|
||||
("type", Type),
|
||||
("time", Time),
|
||||
("key", $"reagent-effect-status-effect-{Key}"));
|
||||
}
|
||||
|
||||
public enum StatusEffectMetabolismType
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Jittering;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects.StatusEffects
|
||||
{
|
||||
@@ -33,5 +34,8 @@ namespace Content.Server.Chemistry.ReagentEffects.StatusEffects
|
||||
args.EntityManager.EntitySysManager.GetEntitySystem<SharedJitteringSystem>()
|
||||
.DoJitter(args.SolutionEntity, TimeSpan.FromSeconds(time), Refresh, Amplitude, Frequency);
|
||||
}
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) =>
|
||||
Loc.GetString("reagent-effect-guidebook-jittering", ("chance", Probability));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,16 @@ using Content.Server.Nutrition.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Nutrition.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class WashCreamPieReaction : ReagentEffect
|
||||
{
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-wash-cream-pie-reaction", ("chance", Probability));
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (!args.EntityManager.TryGetComponent(args.SolutionEntity, out CreamPiedComponent? creamPied)) return;
|
||||
|
||||
@@ -7,5 +7,8 @@ namespace Content.Shared.Body.Prototypes
|
||||
{
|
||||
[IdDataField]
|
||||
public string ID { get; } = default!;
|
||||
|
||||
[DataField("name", required: true)]
|
||||
public string Name { get; } = default!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Localizations;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Shared.Chemistry.Reagent
|
||||
@@ -23,6 +26,10 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
[DataField("conditions")]
|
||||
public ReagentEffectCondition[]? Conditions;
|
||||
|
||||
public virtual string ReagentEffectFormat => "guidebook-reagent-effect-description";
|
||||
|
||||
protected abstract string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys); // => Loc.GetString("reagent-effect-guidebook-missing", ("chance", Probability));
|
||||
|
||||
/// <summary>
|
||||
/// What's the chance, from 0 to 1, that this effect will occur?
|
||||
/// </summary>
|
||||
@@ -42,6 +49,23 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
public virtual bool ShouldLog { get; } = false;
|
||||
|
||||
public abstract void Effect(ReagentEffectArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// Produces a localized, bbcode'd guidebook description for this effect.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string? GuidebookEffectDescription(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
var effect = ReagentEffectGuidebookText(prototype, entSys);
|
||||
if (effect is null)
|
||||
return null;
|
||||
|
||||
return Loc.GetString(ReagentEffectFormat, ("effect", effect), ("chance", Probability),
|
||||
("conditionCount", Conditions?.Length ?? 0),
|
||||
("conditions",
|
||||
ContentLocalizationManager.FormatList(Conditions?.Select(x => x.GuidebookExplanation(prototype)).ToList() ??
|
||||
new List<string>())));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ReagentEffectExt
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Chemistry.Reagent
|
||||
{
|
||||
@@ -10,5 +11,12 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
[JsonPropertyName("id")] private protected string _id => this.GetType().Name;
|
||||
|
||||
public abstract bool Condition(ReagentEffectArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// Effect explanations are of the form "[chance to] [action] when [condition] and [condition]"
|
||||
/// </summary>
|
||||
/// <param name="prototype"></param>
|
||||
/// <returns></returns>
|
||||
public abstract string GuidebookExplanation(IPrototypeManager prototype);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Body.Prototypes;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
@@ -9,6 +10,7 @@ using Robust.Shared.Audio;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
@@ -157,6 +159,23 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public struct ReagentGuideEntry
|
||||
{
|
||||
public string ReagentPrototype;
|
||||
|
||||
public Dictionary<string, ReagentEffectsGuideEntry>? GuideEntries;
|
||||
|
||||
public ReagentGuideEntry(ReagentPrototype proto, IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
ReagentPrototype = proto.ID;
|
||||
GuideEntries = proto.Metabolisms?
|
||||
.Select(x => (x.Key, x.Value.MakeGuideEntry(prototype, entSys)))
|
||||
.ToDictionary(x => x.Key, x => x.Item2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[DataDefinition]
|
||||
public sealed class ReagentEffectsEntry
|
||||
{
|
||||
@@ -173,6 +192,30 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
[JsonPropertyName("effects")]
|
||||
[DataField("effects", required: true)]
|
||||
public ReagentEffect[] Effects = default!;
|
||||
|
||||
public ReagentEffectsGuideEntry MakeGuideEntry(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
return new ReagentEffectsGuideEntry(MetabolismRate,
|
||||
Effects
|
||||
.Select(x => x.GuidebookEffectDescription(prototype, entSys)) // hate.
|
||||
.Where(x => x is not null)
|
||||
.Select(x => x!)
|
||||
.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public struct ReagentEffectsGuideEntry
|
||||
{
|
||||
public FixedPoint2 MetabolismRate;
|
||||
|
||||
public string[] EffectDescriptions;
|
||||
|
||||
public ReagentEffectsGuideEntry(FixedPoint2 metabolismRate, string[] effectDescriptions)
|
||||
{
|
||||
MetabolismRate = metabolismRate;
|
||||
EffectDescriptions = effectDescriptions;
|
||||
}
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
|
||||
42
Content.Shared/Chemistry/SharedChemistryGuideDataSystem.cs
Normal file
42
Content.Shared/Chemistry/SharedChemistryGuideDataSystem.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Chemistry;
|
||||
|
||||
/// <summary>
|
||||
/// This handles the chemistry guidebook and caching it.
|
||||
/// </summary>
|
||||
public abstract class SharedChemistryGuideDataSystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
|
||||
|
||||
protected readonly Dictionary<string, ReagentGuideEntry> Registry = new();
|
||||
|
||||
public IReadOnlyDictionary<string, ReagentGuideEntry> ReagentGuideRegistry => Registry;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ReagentGuideRegistryChangedEvent : EntityEventArgs
|
||||
{
|
||||
public ReagentGuideChangeset Changeset;
|
||||
|
||||
public ReagentGuideRegistryChangedEvent(ReagentGuideChangeset changeset)
|
||||
{
|
||||
Changeset = changeset;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ReagentGuideChangeset
|
||||
{
|
||||
public Dictionary<string,ReagentGuideEntry> GuideEntries;
|
||||
|
||||
public HashSet<string> Removed;
|
||||
|
||||
public ReagentGuideChangeset(Dictionary<string, ReagentGuideEntry> guideEntries, HashSet<string> removed)
|
||||
{
|
||||
GuideEntries = guideEntries;
|
||||
Removed = removed;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Localizations
|
||||
{
|
||||
@@ -31,13 +34,96 @@ namespace Content.Shared.Localizations
|
||||
_loc.AddFunction(culture, "UNITS", FormatUnits);
|
||||
_loc.AddFunction(culture, "TOSTRING", args => FormatToString(culture, args));
|
||||
_loc.AddFunction(culture, "LOC", FormatLoc);
|
||||
_loc.AddFunction(culture, "NATURALFIXED", FormatNaturalFixed);
|
||||
_loc.AddFunction(culture, "NATURALPERCENT", FormatNaturalPercent);
|
||||
|
||||
|
||||
/*
|
||||
* The following language functions are specific to the english localization. When working on your own
|
||||
* localization you should NOT modify these, instead add new functions specific to your language/culture.
|
||||
* This ensures the english translations continue to work as expected when fallbacks are needed.
|
||||
*/
|
||||
var cultureEn = new CultureInfo("en-US");
|
||||
|
||||
_loc.AddFunction(cultureEn, "MAKEPLURAL", FormatMakePlural);
|
||||
_loc.AddFunction(cultureEn, "MANY", FormatMany);
|
||||
}
|
||||
|
||||
private ILocValue FormatMany(LocArgs args)
|
||||
{
|
||||
var count = ((LocValueNumber) args.Args[1]).Value;
|
||||
|
||||
if (Math.Abs(count - 1) < 0.0001f)
|
||||
{
|
||||
return (LocValueString) args.Args[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return (LocValueString) FormatMakePlural(args);
|
||||
}
|
||||
}
|
||||
|
||||
private ILocValue FormatNaturalPercent(LocArgs args)
|
||||
{
|
||||
var number = ((LocValueNumber) args.Args[0]).Value * 100;
|
||||
var maxDecimals = (int)Math.Floor(((LocValueNumber) args.Args[1]).Value);
|
||||
var formatter = (NumberFormatInfo)NumberFormatInfo.GetInstance(CultureInfo.GetCultureInfo(Culture)).Clone();
|
||||
formatter.NumberDecimalDigits = maxDecimals;
|
||||
return new LocValueString(string.Format(formatter, "{0:N}", number).TrimEnd('0').TrimEnd('.') + "%");
|
||||
}
|
||||
|
||||
private ILocValue FormatNaturalFixed(LocArgs args)
|
||||
{
|
||||
var number = ((LocValueNumber) args.Args[0]).Value;
|
||||
var maxDecimals = (int)Math.Floor(((LocValueNumber) args.Args[1]).Value);
|
||||
var formatter = (NumberFormatInfo)NumberFormatInfo.GetInstance(CultureInfo.GetCultureInfo(Culture)).Clone();
|
||||
formatter.NumberDecimalDigits = maxDecimals;
|
||||
return new LocValueString(string.Format(formatter, "{0:N}", number).TrimEnd('0').TrimEnd('.'));
|
||||
}
|
||||
|
||||
private static readonly Regex PluralEsRule = new("^.*(s|sh|ch|x|z)$");
|
||||
|
||||
private ILocValue FormatMakePlural(LocArgs args)
|
||||
{
|
||||
var text = ((LocValueString) args.Args[0]).Value;
|
||||
var split = text.Split(" ", 1);
|
||||
var firstWord = split[0];
|
||||
if (PluralEsRule.IsMatch(firstWord))
|
||||
{
|
||||
if (split.Length == 1)
|
||||
return new LocValueString($"{firstWord}es");
|
||||
else
|
||||
return new LocValueString($"{firstWord}es {split[1]}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (split.Length == 1)
|
||||
return new LocValueString($"{firstWord}s");
|
||||
else
|
||||
return new LocValueString($"{firstWord}s {split[1]}");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: allow fluent to take in lists of strings so this can be a format function like it should be.
|
||||
/// <summary>
|
||||
/// Formats a list as per english grammar rules.
|
||||
/// </summary>
|
||||
public static string FormatList(List<string> list)
|
||||
{
|
||||
return list.Count switch
|
||||
{
|
||||
<= 0 => string.Empty,
|
||||
1 => list[0],
|
||||
2 => $"{list[0]} and {list[1]}",
|
||||
> 2 => $"{string.Join(", ", list.GetRange(0, list.Count - 2))}, and {list[^1]}"
|
||||
};
|
||||
}
|
||||
|
||||
private static ILocValue FormatLoc(LocArgs args)
|
||||
{
|
||||
var id = ((LocValueString)args.Args[0]).Value;
|
||||
var id = ((LocValueString) args.Args[0]).Value;
|
||||
|
||||
return new LocValueString(Loc.GetString(id));
|
||||
return new LocValueString(Loc.GetString(id, args.Options.Select(x => (x.Key, x.Value.Value!)).ToArray()));
|
||||
}
|
||||
|
||||
private static ILocValue FormatToString(CultureInfo culture, LocArgs args)
|
||||
@@ -115,8 +201,8 @@ namespace Content.Shared.Localizations
|
||||
//
|
||||
// Note that the closing brace isn't replaced so that format specifiers can be applied.
|
||||
var res = String.Format(
|
||||
fmtstr.Replace("{UNIT", "{" + $"{fargs.Length - 1}"),
|
||||
fargs
|
||||
fmtstr.Replace("{UNIT", "{" + $"{fargs.Length - 1}"),
|
||||
fargs
|
||||
);
|
||||
|
||||
return new LocValueString(res);
|
||||
|
||||
50
Resources/Locale/en-US/guidebook/chemistry/conditions.ftl
Normal file
50
Resources/Locale/en-US/guidebook/chemistry/conditions.ftl
Normal file
@@ -0,0 +1,50 @@
|
||||
reagent-effect-condition-guidebook-total-damage =
|
||||
{ $max ->
|
||||
[2147483648] it has at least {NATURALFIXED($min, 2)} total damage
|
||||
*[other] { $min ->
|
||||
[0] it has at most {NATURALFIXED($max, 2)} total damage
|
||||
*[other] it has between {NATURALFIXED($min, 2)} and {NATURALFIXED($max, 2)} total damage
|
||||
}
|
||||
}
|
||||
|
||||
reagent-effect-condition-guidebook-reagent-threshold =
|
||||
{ $max ->
|
||||
[2147483648] there's at least {NATURALFIXED($min, 2)}u of {$reagent}
|
||||
*[other] { $min ->
|
||||
[0] there's at most {NATURALFIXED($max, 2)}u of {$reagent}
|
||||
*[other] there's between {NATURALFIXED($min, 2)}u and {NATURALFIXED($max, 2)}u of {$reagent}
|
||||
}
|
||||
}
|
||||
|
||||
reagent-effect-condition-guidebook-mob-state-condition =
|
||||
the mob is { $state }
|
||||
|
||||
reagent-effect-condition-guidebook-solution-temperature =
|
||||
the solution's temperature is { $max ->
|
||||
[2147483648] at least {NATURALFIXED($min, 2)}k
|
||||
*[other] { $min ->
|
||||
[0] at most {NATURALFIXED($max, 2)}k
|
||||
*[other] between {NATURALFIXED($min, 2)}k and {NATURALFIXED($max, 2)}k
|
||||
}
|
||||
}
|
||||
|
||||
reagent-effect-condition-guidebook-body-temperature =
|
||||
the body's temperature is { $max ->
|
||||
[2147483648] at least {NATURALFIXED($min, 2)}k
|
||||
*[other] { $min ->
|
||||
[0] at most {NATURALFIXED($max, 2)}k
|
||||
*[other] between {NATURALFIXED($min, 2)}k and {NATURALFIXED($max, 2)}k
|
||||
}
|
||||
}
|
||||
|
||||
reagent-effect-condition-guidebook-organ-type =
|
||||
the metabolizing organ { $shouldhave ->
|
||||
[true] is
|
||||
*[false] is not
|
||||
} {INDEFINITE($name)} {$name} organ
|
||||
|
||||
reagent-effect-condition-guidebook-has-tag =
|
||||
the target { $invert ->
|
||||
[true] does not have
|
||||
*[false] has
|
||||
} the tag {$tag}
|
||||
16
Resources/Locale/en-US/guidebook/chemistry/core.ftl
Normal file
16
Resources/Locale/en-US/guidebook/chemistry/core.ftl
Normal file
@@ -0,0 +1,16 @@
|
||||
guidebook-reagent-effect-description =
|
||||
{$chance ->
|
||||
[1] { $effect }
|
||||
*[other] Has a { NATURALPERCENT($chance, 2) } chance to { $effect }
|
||||
}{ $conditionCount ->
|
||||
[0] .
|
||||
*[other] {" "}when { $conditions }.
|
||||
}
|
||||
|
||||
guidebook-reagent-name = [bold][color={$color}]{CAPITALIZE($name)}[/color][/bold]
|
||||
guidebook-reagent-recipes-header = Recipe
|
||||
guidebook-reagent-recipes-reagent-display = [bold]{$reagent}[/bold] \[{$ratio}\]
|
||||
guidebook-reagent-recipes-mix = Mix
|
||||
guidebook-reagent-effects-header = Effects
|
||||
guidebook-reagent-effects-metabolism-group-rate = [bold]{$group}[/bold] [color=gray]({$rate} units per second)[/color]
|
||||
guidebook-reagent-physical-description = Seems to be {$description}.
|
||||
316
Resources/Locale/en-US/guidebook/chemistry/effects.ftl
Normal file
316
Resources/Locale/en-US/guidebook/chemistry/effects.ftl
Normal file
@@ -0,0 +1,316 @@
|
||||
-create-3rd-person =
|
||||
{ $chance ->
|
||||
[1] Creates
|
||||
*[other] create
|
||||
}
|
||||
|
||||
-cause-3rd-person =
|
||||
{ $chance ->
|
||||
[1] Causes
|
||||
*[other] cause
|
||||
}
|
||||
|
||||
-satiate-3rd-person =
|
||||
{ $chance ->
|
||||
[1] Satiates
|
||||
*[other] satiate
|
||||
}
|
||||
|
||||
reagent-effect-guidebook-create-entity-reaction-effect =
|
||||
{ $chance ->
|
||||
[1] Creates
|
||||
*[other] create
|
||||
} { $amount ->
|
||||
[1] {INDEFINITE($entname)}
|
||||
*[other] {$amount} {MAKEPLURAL($entname)}
|
||||
}
|
||||
|
||||
reagent-effect-guidebook-explosion-reaction-effect =
|
||||
{ $chance ->
|
||||
[1] Causes
|
||||
*[other] cause
|
||||
} an explosion
|
||||
|
||||
reagent-effect-guidebook-foam-area-reaction-effect =
|
||||
{ $chance ->
|
||||
[1] Creates
|
||||
*[other] create
|
||||
} large quantities of foam
|
||||
|
||||
reagent-effect-guidebook-foam-area-reaction-effect =
|
||||
{ $chance ->
|
||||
[1] Creates
|
||||
*[other] create
|
||||
} large quantities of smoke
|
||||
|
||||
reagent-effect-guidebook-satiate-thirst =
|
||||
{ $chance ->
|
||||
[1] Satiates
|
||||
*[other] satiate
|
||||
} { $relative ->
|
||||
[1] thirst averagely
|
||||
*[other] thirst at {NATURALFIXED($relative, 3)}x the average rate
|
||||
}
|
||||
|
||||
reagent-effect-guidebook-satiate-hunger =
|
||||
{ $chance ->
|
||||
[1] Satiates
|
||||
*[other] satiate
|
||||
} { $relative ->
|
||||
[1] hunger averagely
|
||||
*[other] hunger at {NATURALFIXED($relative, 3)}x the average rate
|
||||
}
|
||||
|
||||
reagent-effect-guidebook-health-change =
|
||||
{ $chance ->
|
||||
[1] { $healsordeals ->
|
||||
[heals] Heals
|
||||
[deals] Deals
|
||||
*[both] Modifies health by
|
||||
}
|
||||
*[other] { $healsordeals ->
|
||||
[heals] heal
|
||||
[deals] deal
|
||||
*[both] modify health by
|
||||
}
|
||||
} { $changes }
|
||||
|
||||
reagent-effect-guidebook-status-effect =
|
||||
{ $type ->
|
||||
[add] { $chance ->
|
||||
[1] Causes
|
||||
*[other] cause
|
||||
} {LOC($key)} for at least {NATURALFIXED($time, 3)} {MANY("second", $time)} with accumulation
|
||||
*[set] { $chance ->
|
||||
[1] Causes
|
||||
*[other] cause
|
||||
} {LOC($key)} for at least {NATURALFIXED($time, 3)} {MANY("second", $time)} without accumulation
|
||||
[remove]{ $chance ->
|
||||
[1] Removes
|
||||
*[other] remove
|
||||
} {NATURALFIXED($time, 3)} {MANY("second", $time)} of {LOC($key)}
|
||||
}
|
||||
|
||||
reagent-effect-guidebook-activate-artifact =
|
||||
{ $chance ->
|
||||
[1] Attempts
|
||||
*[other] attempt
|
||||
} to activate an artifact
|
||||
|
||||
reagent-effect-guidebook-set-solution-temperature-effect =
|
||||
{ $chance ->
|
||||
[1] Sets
|
||||
*[other] set
|
||||
} the solution temperature to exactly {NATURALFIXED($temperature, 2)}k
|
||||
|
||||
reagent-effect-guidebook-adjust-solution-temperature-effect =
|
||||
{ $chance ->
|
||||
[1] { $deltasign ->
|
||||
[1] Adds
|
||||
*[-1] Removes
|
||||
}
|
||||
*[other]
|
||||
{ $deltasign ->
|
||||
[1] add
|
||||
*[-1] remove
|
||||
}
|
||||
} heat from the solution until it reaches { $deltasign ->
|
||||
[1] at most {NATURALFIXED($maxtemp, 2)}k
|
||||
*[-1] at least {NATURALFIXED($mintemp, 2)}k
|
||||
}
|
||||
|
||||
reagent-effect-guidebook-adjust-reagent-reagent =
|
||||
{ $chance ->
|
||||
[1] { $deltasign ->
|
||||
[1] Adds
|
||||
*[-1] Removes
|
||||
}
|
||||
*[other]
|
||||
{ $deltasign ->
|
||||
[1] add
|
||||
*[-1] remove
|
||||
}
|
||||
} {NATURALFIXED($amount, 2)}u of {$reagent} { $deltasign ->
|
||||
[1] to
|
||||
*[-1] from
|
||||
} the solution
|
||||
|
||||
reagent-effect-guidebook-adjust-reagent-group =
|
||||
{ $chance ->
|
||||
[1] { $deltasign ->
|
||||
[1] Adds
|
||||
*[-1] Removes
|
||||
}
|
||||
*[other]
|
||||
{ $deltasign ->
|
||||
[1] add
|
||||
*[-1] remove
|
||||
}
|
||||
} {NATURALFIXED($amount, 2)}u of reagents in the group {$group} { $deltasign ->
|
||||
[1] to
|
||||
*[-1] from
|
||||
} the solution
|
||||
|
||||
reagent-effect-guidebook-adjust-temperature =
|
||||
{ $chance ->
|
||||
[1] { $deltasign ->
|
||||
[1] Adds
|
||||
*[-1] Removes
|
||||
}
|
||||
*[other]
|
||||
{ $deltasign ->
|
||||
[1] add
|
||||
*[-1] remove
|
||||
}
|
||||
} {POWERJOULES($amount)} of heat { $deltasign ->
|
||||
[1] to
|
||||
*[-1] from
|
||||
} the body it's in
|
||||
|
||||
reagent-effect-guidebook-chem-cause-disease =
|
||||
{ $chance ->
|
||||
[1] Causes
|
||||
*[other] cause
|
||||
} the disease { $disease }
|
||||
|
||||
reagent-effect-guidebook-chem-cause-random-disease =
|
||||
{ $chance ->
|
||||
[1] Causes
|
||||
*[other] cause
|
||||
} the diseases { $diseases }
|
||||
|
||||
reagent-effect-guidebook-jittering =
|
||||
{ $chance ->
|
||||
[1] Causes
|
||||
*[other] cause
|
||||
} jittering
|
||||
|
||||
reagent-effect-guidebook-chem-clean-bloodstream =
|
||||
{ $chance ->
|
||||
[1] Cleanses
|
||||
*[other] cleanse
|
||||
} the bloodstream of other chemicals
|
||||
|
||||
reagent-effect-guidebook-cure-disease =
|
||||
{ $chance ->
|
||||
[1] Cures
|
||||
*[other] cure
|
||||
} diseases
|
||||
|
||||
reagent-effect-guidebook-cure-eye-damage =
|
||||
{ $chance ->
|
||||
[1] { $deltasign ->
|
||||
[1] Heals
|
||||
*[-1] Deals
|
||||
}
|
||||
*[other]
|
||||
{ $deltasign ->
|
||||
[1] heal
|
||||
*[-1] deal
|
||||
}
|
||||
} eye damage
|
||||
|
||||
reagent-effect-guidebook-chem-vomit =
|
||||
{ $chance ->
|
||||
[1] Causes
|
||||
*[other] cause
|
||||
} vomiting
|
||||
|
||||
reagent-effect-guidebook-create-gas =
|
||||
{ $chance ->
|
||||
[1] Creates
|
||||
*[other] create
|
||||
} { $moles } { $moles ->
|
||||
[1] mole
|
||||
*[other] moles
|
||||
} of { $gas }
|
||||
|
||||
reagent-effect-guidebook-drunk =
|
||||
{ $chance ->
|
||||
[1] Causes
|
||||
*[other] cause
|
||||
} drunkness
|
||||
|
||||
reagent-effect-guidebook-electrocute =
|
||||
{ $chance ->
|
||||
[1] Electrocutes
|
||||
*[other] electrocute
|
||||
} the metabolizer for {NATURALFIXED($time, 3)} {MANY("second", $time)}
|
||||
|
||||
reagent-effect-guidebook-extinguish-reaction =
|
||||
{ $chance ->
|
||||
[1] Extinguishes
|
||||
*[other] extinguish
|
||||
} fire
|
||||
|
||||
reagent-effect-guidebook-flammable-reaction =
|
||||
{ $chance ->
|
||||
[1] Increases
|
||||
*[other] increase
|
||||
} flammability
|
||||
|
||||
reagent-effect-guidebook-ignite =
|
||||
{ $chance ->
|
||||
[1] Ignites
|
||||
*[other] ignite
|
||||
} the metabolizer
|
||||
|
||||
reagent-effect-guidebook-make-sentient =
|
||||
{ $chance ->
|
||||
[1] Makes
|
||||
*[other] make
|
||||
} the metabolizer sentient
|
||||
|
||||
reagent-effect-guidebook-modify-bleed-amount =
|
||||
{ $chance ->
|
||||
[1] { $deltasign ->
|
||||
[1] Induces
|
||||
*[-1] Reduces
|
||||
}
|
||||
*[other] { $deltasign ->
|
||||
[1] induce
|
||||
*[-1] reduce
|
||||
}
|
||||
} bleeding
|
||||
|
||||
reagent-effect-guidebook-modify-blood-level =
|
||||
{ $chance ->
|
||||
[1] { $deltasign ->
|
||||
[1] Increases
|
||||
*[-1] Decreases
|
||||
}
|
||||
*[other] { $deltasign ->
|
||||
[1] increases
|
||||
*[-1] decreases
|
||||
}
|
||||
} blood level
|
||||
|
||||
reagent-effect-guidebook-paralyze =
|
||||
{ $chance ->
|
||||
[1] Paralyzes
|
||||
*[other] paralyze
|
||||
} the metabolizer for at least {NATURALFIXED($time, 3)} {MANY("second", $time)}
|
||||
|
||||
reagent-effect-guidebook-movespeed-modifier =
|
||||
{ $chance ->
|
||||
[1] Modifies
|
||||
*[other] modify
|
||||
} movement speed by {NATURALFIXED($walkspeed, 3)}x for at least {NATURALFIXED($time, 3)} {MANY("second", $time)}
|
||||
|
||||
reagent-effect-guidebook-reset-narcolepsy =
|
||||
{ $chance ->
|
||||
[1] Temporarily staves
|
||||
*[other] temporarily stave
|
||||
} off narcolepsy
|
||||
|
||||
reagent-effect-guidebook-wash-cream-pie-reaction =
|
||||
{ $chance ->
|
||||
[1] Washes
|
||||
*[other] wash
|
||||
} off cream pie from one's face
|
||||
|
||||
reagent-effect-guidebook-missing =
|
||||
{ $chance ->
|
||||
[1] Causes
|
||||
*[other] cause
|
||||
} an unknown effect as nobody has written this effect yet
|
||||
@@ -0,0 +1,5 @@
|
||||
health-change-display =
|
||||
{ $deltasign ->
|
||||
[-1] [color=green]{NATURALFIXED($amount, 2)}[/color] {$kind}
|
||||
*[1] [color=red]{NATURALFIXED($amount, 2)}[/color] {$kind}
|
||||
}
|
||||
11
Resources/Locale/en-US/guidebook/chemistry/statuseffects.ftl
Normal file
11
Resources/Locale/en-US/guidebook/chemistry/statuseffects.ftl
Normal file
@@ -0,0 +1,11 @@
|
||||
reagent-effect-status-effect-Stun = stunning
|
||||
reagent-effect-status-effect-KnockedDown = knockdown
|
||||
reagent-effect-status-effect-Jitter = jittering
|
||||
reagent-effect-status-effect-TemporaryBlindness = blindess
|
||||
reagent-effect-status-effect-SeeingRainbows = hallucinations
|
||||
reagent-effect-status-effect-Muted = inability to speak
|
||||
reagent-effect-status-effect-Stutter = stuttering
|
||||
reagent-effect-status-effect-ForcedSleep = unconsciousness
|
||||
reagent-effect-status-effect-Drunk = drunkness
|
||||
reagent-effect-status-effect-PressureImmunity = pressure immunity
|
||||
reagent-effect-status-effect-Pacified = combat pacification
|
||||
@@ -14,6 +14,7 @@ guide-entry-radio = Radio
|
||||
guide-entry-jobs = Jobs
|
||||
guide-entry-salvage = Salvage
|
||||
guide-entry-survival = Survival
|
||||
guide-entry-chemicals = Chemicals
|
||||
guide-entry-ss14 = Space Station 14
|
||||
guide-entry-janitorial = Janitorial
|
||||
|
||||
|
||||
@@ -3,24 +3,32 @@
|
||||
|
||||
- type: metabolizerType
|
||||
id: Animal
|
||||
name: animal
|
||||
|
||||
- type: metabolizerType
|
||||
id: Dragon
|
||||
name: dragon
|
||||
|
||||
- type: metabolizerType
|
||||
id: Human
|
||||
name: human
|
||||
|
||||
- type: metabolizerType
|
||||
id: Slime
|
||||
name: slime
|
||||
|
||||
- type: metabolizerType
|
||||
id: Vox
|
||||
name: vox
|
||||
|
||||
- type: metabolizerType
|
||||
id: Rat
|
||||
name: rat
|
||||
|
||||
- type: metabolizerType
|
||||
id: Plant
|
||||
name: plant
|
||||
|
||||
- type: metabolizerType
|
||||
id: Dwarf
|
||||
name: dwarf
|
||||
|
||||
@@ -32,3 +32,6 @@
|
||||
- type: UpgradePowerDraw
|
||||
powerDrawMultiplier: 0.75
|
||||
scaling: Exponential
|
||||
- type: GuideHelp
|
||||
guides:
|
||||
- Chemicals
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
name: guide-entry-survival
|
||||
text: "/ServerInfo/Guidebook/Survival.xml"
|
||||
|
||||
- type: guideEntry
|
||||
id: Chemicals
|
||||
name: guide-entry-chemicals
|
||||
text: "/ServerInfo/Guidebook/Chemicals.xml"
|
||||
|
||||
- type: guideEntry
|
||||
id: Janitorial
|
||||
name: guide-entry-janitorial
|
||||
|
||||
@@ -6,3 +6,4 @@
|
||||
- Controls
|
||||
- Jobs
|
||||
- Survival
|
||||
- Chemicals
|
||||
|
||||
34
Resources/ServerInfo/Guidebook/Chemicals.xml
Normal file
34
Resources/ServerInfo/Guidebook/Chemicals.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<Document>
|
||||
# Chemicals
|
||||
|
||||
Chemicals are a powerful tool that can cause a variety of effects when consumed. Some can be found in plants, purchased from cargo, or be synthesized through combination with other chemicals.
|
||||
|
||||
Knowing different types of chemicals and their effects is important for being able to manage injury and danger.
|
||||
|
||||
## Elements
|
||||
<GuideReagentGroupEmbed Group="Elements"/>
|
||||
|
||||
## Medicine
|
||||
<GuideReagentGroupEmbed Group="Medicine"/>
|
||||
|
||||
## Narcotics
|
||||
<GuideReagentGroupEmbed Group="Narcotics"/>
|
||||
|
||||
## Pyrotechnics
|
||||
<GuideReagentGroupEmbed Group="Pyrotechnic"/>
|
||||
|
||||
## Toxins
|
||||
<GuideReagentGroupEmbed Group="Toxins"/>
|
||||
|
||||
## Foods
|
||||
<GuideReagentGroupEmbed Group="Foods"/>
|
||||
|
||||
## Botanical
|
||||
<GuideReagentGroupEmbed Group="Botanical"/>
|
||||
|
||||
## Biological
|
||||
<GuideReagentGroupEmbed Group="Biological"/>
|
||||
|
||||
## Other
|
||||
<GuideReagentGroupEmbed Group="Unknown"/>
|
||||
</Document>
|
||||
BIN
Resources/Textures/Interface/Misc/beakerlarge.png
Normal file
BIN
Resources/Textures/Interface/Misc/beakerlarge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 239 B |
Submodule RobustToolbox updated: e2830c9ad8...7a04c81fe1
Reference in New Issue
Block a user