Add support for printing reagents in lathes (#30476)
* Add support for reagents in lathes * missing locale
This commit is contained in:
@@ -81,9 +81,9 @@ namespace Content.Shared.Construction
|
||||
{
|
||||
var partRecipe = recipes[0];
|
||||
if (recipes.Count > 1)
|
||||
partRecipe = recipes.MinBy(p => p.RequiredMaterials.Values.Sum());
|
||||
partRecipe = recipes.MinBy(p => p.Materials.Values.Sum());
|
||||
|
||||
foreach (var (mat, matAmount) in partRecipe!.RequiredMaterials)
|
||||
foreach (var (mat, matAmount) in partRecipe!.Materials)
|
||||
{
|
||||
materials.TryAdd(mat, 0);
|
||||
materials[mat] += matAmount * amount * coefficient;
|
||||
@@ -101,9 +101,9 @@ namespace Content.Shared.Construction
|
||||
{
|
||||
var partRecipe = recipes[0];
|
||||
if (recipes.Count > 1)
|
||||
partRecipe = recipes.MinBy(p => p.RequiredMaterials.Values.Sum());
|
||||
partRecipe = recipes.MinBy(p => p.Materials.Values.Sum());
|
||||
|
||||
foreach (var (mat, matAmount) in partRecipe!.RequiredMaterials)
|
||||
foreach (var (mat, matAmount) in partRecipe!.Materials)
|
||||
{
|
||||
materials.TryAdd(mat, 0);
|
||||
materials[mat] += matAmount * amount * coefficient;
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace Content.Shared.Lathe
|
||||
[DataField]
|
||||
public SoundSpecifier? ProducingSound;
|
||||
|
||||
[DataField]
|
||||
public string? ReagentOutputSlotId;
|
||||
|
||||
#region Visualizer info
|
||||
[DataField]
|
||||
public string? IdleState;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Localizations;
|
||||
using Content.Shared.Materials;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using JetBrains.Annotations;
|
||||
@@ -23,10 +26,21 @@ public abstract class SharedLatheSystem : EntitySystem
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<EmagLatheRecipesComponent, GotEmaggedEvent>(OnEmagged);
|
||||
SubscribeLocalEvent<LatheComponent, ExaminedEvent>(OnExamined);
|
||||
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
|
||||
|
||||
BuildInverseRecipeDictionary();
|
||||
}
|
||||
|
||||
private void OnExamined(Entity<LatheComponent> ent, ref ExaminedEvent args)
|
||||
{
|
||||
if (!args.IsInDetailsRange)
|
||||
return;
|
||||
|
||||
if (ent.Comp.ReagentOutputSlotId != null)
|
||||
args.PushMarkup(Loc.GetString("lathe-menu-reagent-slot-examine"));
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public bool CanProduce(EntityUid uid, string recipe, int amount = 1, LatheComponent? component = null)
|
||||
{
|
||||
@@ -40,7 +54,7 @@ public abstract class SharedLatheSystem : EntitySystem
|
||||
if (!HasRecipe(uid, recipe, component))
|
||||
return false;
|
||||
|
||||
foreach (var (material, needed) in recipe.RequiredMaterials)
|
||||
foreach (var (material, needed) in recipe.Materials)
|
||||
{
|
||||
var adjustedAmount = AdjustMaterial(needed, recipe.ApplyMaterialDiscount, component.MaterialUseMultiplier);
|
||||
|
||||
@@ -72,6 +86,9 @@ public abstract class SharedLatheSystem : EntitySystem
|
||||
_inverseRecipeDictionary.Clear();
|
||||
foreach (var latheRecipe in _proto.EnumeratePrototypes<LatheRecipePrototype>())
|
||||
{
|
||||
if (latheRecipe.Result == null)
|
||||
continue;
|
||||
|
||||
_inverseRecipeDictionary.GetOrNew(latheRecipe.Result).Add(latheRecipe);
|
||||
}
|
||||
}
|
||||
@@ -83,4 +100,55 @@ public abstract class SharedLatheSystem : EntitySystem
|
||||
recipes.AddRange(r);
|
||||
return recipes.Count != 0;
|
||||
}
|
||||
|
||||
public string GetRecipeName(ProtoId<LatheRecipePrototype> proto)
|
||||
{
|
||||
return GetRecipeName(_proto.Index(proto));
|
||||
}
|
||||
|
||||
public string GetRecipeName(LatheRecipePrototype proto)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(proto.Name))
|
||||
return Loc.GetString(proto.Name);
|
||||
|
||||
if (proto.Result is { } result)
|
||||
{
|
||||
return _proto.Index(result).Name;
|
||||
}
|
||||
|
||||
if (proto.ResultReagents is { } resultReagents)
|
||||
{
|
||||
return ContentLocalizationManager.FormatList(resultReagents
|
||||
.Select(p => Loc.GetString("lathe-menu-result-reagent-display", ("reagent", _proto.Index(p.Key).LocalizedName), ("amount", p.Value)))
|
||||
.ToList());
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public string GetRecipeDescription(ProtoId<LatheRecipePrototype> proto)
|
||||
{
|
||||
return GetRecipeDescription(_proto.Index(proto));
|
||||
}
|
||||
|
||||
public string GetRecipeDescription(LatheRecipePrototype proto)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(proto.Description))
|
||||
return Loc.GetString(proto.Description);
|
||||
|
||||
if (proto.Result is { } result)
|
||||
{
|
||||
return _proto.Index(result).Description;
|
||||
}
|
||||
|
||||
if (proto.ResultReagents is { } resultReagents)
|
||||
{
|
||||
// We only use the first one for the description since these descriptions don't combine very well.
|
||||
var reagent = resultReagents.First().Key;
|
||||
return _proto.Index(reagent).LocalizedDescription;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,101 +1,58 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Lathe.Prototypes;
|
||||
using Content.Shared.Materials;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Research.Prototypes
|
||||
{
|
||||
[NetSerializable, Serializable, Prototype("latheRecipe")]
|
||||
[NetSerializable, Serializable, Prototype]
|
||||
public sealed partial class LatheRecipePrototype : IPrototype
|
||||
{
|
||||
[ViewVariables]
|
||||
[IdDataField]
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
[DataField("name")]
|
||||
private string _name = string.Empty;
|
||||
|
||||
[DataField("description")]
|
||||
private string _description = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The prototype name of the resulting entity when the recipe is printed.
|
||||
/// </summary>
|
||||
[DataField("result", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string Result = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// An entity whose sprite is displayed in the ui in place of the actual recipe result.
|
||||
/// </summary>
|
||||
[DataField("icon")]
|
||||
public SpriteSpecifier? Icon;
|
||||
|
||||
[DataField("completetime")]
|
||||
private TimeSpan _completeTime = TimeSpan.FromSeconds(5);
|
||||
|
||||
[DataField("materials", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MaterialPrototype>))]
|
||||
private Dictionary<string, int> _requiredMaterials = new();
|
||||
|
||||
//todo make these function calls because we're eating tons of resolves here.
|
||||
/// <summary>
|
||||
/// Name displayed in the lathe GUI.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_name.Trim().Length != 0)
|
||||
return _name;
|
||||
var protoMan = IoCManager.Resolve<IPrototypeManager>();
|
||||
protoMan.TryIndex(Result, out EntityPrototype? prototype);
|
||||
if (prototype?.Name != null)
|
||||
_name = prototype.Name;
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
[DataField]
|
||||
public LocId? Name;
|
||||
|
||||
/// <summary>
|
||||
/// Short description displayed in the lathe GUI.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_description.Trim().Length != 0)
|
||||
return _description;
|
||||
var protoMan = IoCManager.Resolve<IPrototypeManager>();
|
||||
protoMan.TryIndex(Result, out EntityPrototype? prototype);
|
||||
if (prototype?.Description != null)
|
||||
_description = prototype.Description;
|
||||
return _description;
|
||||
}
|
||||
}
|
||||
[DataField]
|
||||
public LocId? Description;
|
||||
|
||||
/// <summary>
|
||||
/// The prototype name of the resulting entity when the recipe is printed.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntProtoId? Result;
|
||||
|
||||
[DataField]
|
||||
public Dictionary<ProtoId<ReagentPrototype>, FixedPoint2>? ResultReagents;
|
||||
|
||||
/// <summary>
|
||||
/// An entity whose sprite is displayed in the ui in place of the actual recipe result.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public SpriteSpecifier? Icon;
|
||||
|
||||
[DataField("completetime")]
|
||||
public TimeSpan CompleteTime = TimeSpan.FromSeconds(5);
|
||||
|
||||
/// <summary>
|
||||
/// The materials required to produce this recipe.
|
||||
/// Takes a material ID as string.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public Dictionary<string, int> RequiredMaterials
|
||||
{
|
||||
get => _requiredMaterials;
|
||||
private set => _requiredMaterials = value;
|
||||
}
|
||||
[DataField]
|
||||
public Dictionary<ProtoId<MaterialPrototype>, int> Materials = new();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// How many milliseconds it'll take for the lathe to finish this recipe.
|
||||
/// Might lower depending on the lathe's upgrade level.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public TimeSpan CompleteTime => _completeTime;
|
||||
|
||||
[DataField("applyMaterialDiscount")]
|
||||
[DataField]
|
||||
public bool ApplyMaterialDiscount = true;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Research.Components;
|
||||
using Content.Shared.Research.Prototypes;
|
||||
using JetBrains.Annotations;
|
||||
@@ -12,6 +13,7 @@ public abstract class SharedResearchSystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly IPrototypeManager PrototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedLatheSystem _lathe = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -185,7 +187,7 @@ public abstract class SharedResearchSystem : EntitySystem
|
||||
var recipeProto = PrototypeManager.Index(recipe);
|
||||
description.PushNewline();
|
||||
description.AddMarkup(Loc.GetString("research-console-unlocks-list-entry",
|
||||
("name",recipeProto.Name)));
|
||||
("name", _lathe.GetRecipeName(recipeProto))));
|
||||
}
|
||||
foreach (var generic in technology.GenericUnlocks)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Lathe;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Random.Helpers;
|
||||
using Content.Shared.Research.Components;
|
||||
@@ -19,6 +20,7 @@ public sealed class TechnologyDiskSystem : EntitySystem
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedResearchSystem _research = default!;
|
||||
[Dependency] private readonly SharedLatheSystem _lathe = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -83,8 +85,7 @@ public sealed class TechnologyDiskSystem : EntitySystem
|
||||
if (ent.Comp.Recipes != null && ent.Comp.Recipes.Count > 0)
|
||||
{
|
||||
var prototype = _protoMan.Index(ent.Comp.Recipes[0]);
|
||||
var resultPrototype = _protoMan.Index<EntityPrototype>(prototype.Result);
|
||||
message = Loc.GetString("tech-disk-examine", ("result", resultPrototype.Name));
|
||||
message = Loc.GetString("tech-disk-examine", ("result", _lathe.GetRecipeName(prototype)));
|
||||
|
||||
if (ent.Comp.Recipes.Count > 1) //idk how to do this well. sue me.
|
||||
message += " " + Loc.GetString("tech-disk-examine-more");
|
||||
|
||||
Reference in New Issue
Block a user